Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 // Copyright 2017-2021 NXP
0003 
0004 #include <linux/dma-mapping.h>
0005 #include <linux/slab.h>
0006 #include <linux/module.h>
0007 #include <linux/delay.h>
0008 #include <linux/rpmsg.h>
0009 #include <sound/core.h>
0010 #include <sound/pcm.h>
0011 #include <sound/pcm_params.h>
0012 #include <sound/dmaengine_pcm.h>
0013 #include <sound/soc.h>
0014 
0015 #include "imx-pcm.h"
0016 #include "fsl_rpmsg.h"
0017 #include "imx-pcm-rpmsg.h"
0018 
0019 static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = {
0020     .info = SNDRV_PCM_INFO_INTERLEAVED |
0021         SNDRV_PCM_INFO_BLOCK_TRANSFER |
0022         SNDRV_PCM_INFO_MMAP |
0023         SNDRV_PCM_INFO_MMAP_VALID |
0024         SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
0025         SNDRV_PCM_INFO_PAUSE |
0026         SNDRV_PCM_INFO_RESUME,
0027     .buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE,
0028     .period_bytes_min = 512,
0029     .period_bytes_max = 65536,
0030     .periods_min = 2,
0031     .periods_max = 6000,
0032     .fifo_size = 0,
0033 };
0034 
0035 static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg,
0036                       struct rpmsg_info *info)
0037 {
0038     struct rpmsg_device *rpdev = info->rpdev;
0039     int ret = 0;
0040 
0041     mutex_lock(&info->msg_lock);
0042     if (!rpdev) {
0043         dev_err(info->dev, "rpmsg channel not ready\n");
0044         mutex_unlock(&info->msg_lock);
0045         return -EINVAL;
0046     }
0047 
0048     dev_dbg(&rpdev->dev, "send cmd %d\n", msg->s_msg.header.cmd);
0049 
0050     if (!(msg->s_msg.header.type == MSG_TYPE_C))
0051         reinit_completion(&info->cmd_complete);
0052 
0053     ret = rpmsg_send(rpdev->ept, (void *)&msg->s_msg,
0054              sizeof(struct rpmsg_s_msg));
0055     if (ret) {
0056         dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
0057         mutex_unlock(&info->msg_lock);
0058         return ret;
0059     }
0060 
0061     /* No receive msg for TYPE_C command */
0062     if (msg->s_msg.header.type == MSG_TYPE_C) {
0063         mutex_unlock(&info->msg_lock);
0064         return 0;
0065     }
0066 
0067     /* wait response from rpmsg */
0068     ret = wait_for_completion_timeout(&info->cmd_complete,
0069                       msecs_to_jiffies(RPMSG_TIMEOUT));
0070     if (!ret) {
0071         dev_err(&rpdev->dev, "rpmsg_send cmd %d timeout!\n",
0072             msg->s_msg.header.cmd);
0073         mutex_unlock(&info->msg_lock);
0074         return -ETIMEDOUT;
0075     }
0076 
0077     memcpy(&msg->r_msg, &info->r_msg, sizeof(struct rpmsg_r_msg));
0078     memcpy(&info->msg[msg->r_msg.header.cmd].r_msg,
0079            &msg->r_msg, sizeof(struct rpmsg_r_msg));
0080 
0081     /*
0082      * Reset the buffer pointer to be zero, actully we have
0083      * set the buffer pointer to be zero in imx_rpmsg_terminate_all
0084      * But if there is timer task queued in queue, after it is
0085      * executed the buffer pointer will be changed, so need to
0086      * reset it again with TERMINATE command.
0087      */
0088     switch (msg->s_msg.header.cmd) {
0089     case TX_TERMINATE:
0090         info->msg[TX_POINTER].r_msg.param.buffer_offset = 0;
0091         break;
0092     case RX_TERMINATE:
0093         info->msg[RX_POINTER].r_msg.param.buffer_offset = 0;
0094         break;
0095     default:
0096         break;
0097     }
0098 
0099     dev_dbg(&rpdev->dev, "cmd:%d, resp %d\n", msg->s_msg.header.cmd,
0100         info->r_msg.param.resp);
0101 
0102     mutex_unlock(&info->msg_lock);
0103 
0104     return 0;
0105 }
0106 
0107 static int imx_rpmsg_insert_workqueue(struct snd_pcm_substream *substream,
0108                       struct rpmsg_msg *msg,
0109                       struct rpmsg_info *info)
0110 {
0111     unsigned long flags;
0112     int ret = 0;
0113 
0114     /*
0115      * Queue the work to workqueue.
0116      * If the queue is full, drop the message.
0117      */
0118     spin_lock_irqsave(&info->wq_lock, flags);
0119     if (info->work_write_index != info->work_read_index) {
0120         int index = info->work_write_index;
0121 
0122         memcpy(&info->work_list[index].msg, msg,
0123                sizeof(struct rpmsg_s_msg));
0124 
0125         queue_work(info->rpmsg_wq, &info->work_list[index].work);
0126         info->work_write_index++;
0127         info->work_write_index %= WORK_MAX_NUM;
0128     } else {
0129         info->msg_drop_count[substream->stream]++;
0130         ret = -EPIPE;
0131     }
0132     spin_unlock_irqrestore(&info->wq_lock, flags);
0133 
0134     return ret;
0135 }
0136 
0137 static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component,
0138                    struct snd_pcm_substream *substream,
0139                    struct snd_pcm_hw_params *params)
0140 {
0141     struct rpmsg_info *info = dev_get_drvdata(component->dev);
0142     struct rpmsg_msg *msg;
0143     int ret = 0;
0144 
0145     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0146         msg = &info->msg[TX_HW_PARAM];
0147         msg->s_msg.header.cmd = TX_HW_PARAM;
0148     } else {
0149         msg = &info->msg[RX_HW_PARAM];
0150         msg->s_msg.header.cmd = RX_HW_PARAM;
0151     }
0152 
0153     msg->s_msg.param.rate = params_rate(params);
0154 
0155     switch (params_format(params)) {
0156     case SNDRV_PCM_FORMAT_S16_LE:
0157         msg->s_msg.param.format   = RPMSG_S16_LE;
0158         break;
0159     case SNDRV_PCM_FORMAT_S24_LE:
0160         msg->s_msg.param.format   = RPMSG_S24_LE;
0161         break;
0162     case SNDRV_PCM_FORMAT_DSD_U16_LE:
0163         msg->s_msg.param.format   = RPMSG_DSD_U16_LE;
0164         break;
0165     case SNDRV_PCM_FORMAT_DSD_U32_LE:
0166         msg->s_msg.param.format   = RPMSG_DSD_U32_LE;
0167         break;
0168     default:
0169         msg->s_msg.param.format   = RPMSG_S32_LE;
0170         break;
0171     }
0172 
0173     switch (params_channels(params)) {
0174     case 1:
0175         msg->s_msg.param.channels = RPMSG_CH_LEFT;
0176         break;
0177     case 2:
0178         msg->s_msg.param.channels = RPMSG_CH_STEREO;
0179         break;
0180     default:
0181         ret = -EINVAL;
0182         break;
0183     }
0184 
0185     info->send_message(msg, info);
0186 
0187     return ret;
0188 }
0189 
0190 static snd_pcm_uframes_t imx_rpmsg_pcm_pointer(struct snd_soc_component *component,
0191                            struct snd_pcm_substream *substream)
0192 {
0193     struct rpmsg_info *info = dev_get_drvdata(component->dev);
0194     struct rpmsg_msg *msg;
0195     unsigned int pos = 0;
0196     int buffer_tail = 0;
0197 
0198     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0199         msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
0200     else
0201         msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
0202 
0203     buffer_tail = msg->r_msg.param.buffer_tail;
0204     pos = buffer_tail * snd_pcm_lib_period_bytes(substream);
0205 
0206     return bytes_to_frames(substream->runtime, pos);
0207 }
0208 
0209 static void imx_rpmsg_timer_callback(struct timer_list *t)
0210 {
0211     struct stream_timer  *stream_timer =
0212             from_timer(stream_timer, t, timer);
0213     struct snd_pcm_substream *substream = stream_timer->substream;
0214     struct rpmsg_info *info = stream_timer->info;
0215     struct rpmsg_msg *msg;
0216 
0217     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0218         msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
0219         msg->s_msg.header.cmd = TX_PERIOD_DONE;
0220     } else {
0221         msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
0222         msg->s_msg.header.cmd = RX_PERIOD_DONE;
0223     }
0224 
0225     imx_rpmsg_insert_workqueue(substream, msg, info);
0226 }
0227 
0228 static int imx_rpmsg_pcm_open(struct snd_soc_component *component,
0229                   struct snd_pcm_substream *substream)
0230 {
0231     struct rpmsg_info *info = dev_get_drvdata(component->dev);
0232     struct rpmsg_msg *msg;
0233     int ret = 0;
0234     int cmd;
0235 
0236     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0237         msg = &info->msg[TX_OPEN];
0238         msg->s_msg.header.cmd = TX_OPEN;
0239 
0240         /* reinitialize buffer counter*/
0241         cmd = TX_PERIOD_DONE + MSG_TYPE_A_NUM;
0242         info->msg[cmd].s_msg.param.buffer_tail = 0;
0243         info->msg[cmd].r_msg.param.buffer_tail = 0;
0244         info->msg[TX_POINTER].r_msg.param.buffer_offset = 0;
0245 
0246     } else {
0247         msg = &info->msg[RX_OPEN];
0248         msg->s_msg.header.cmd = RX_OPEN;
0249 
0250         /* reinitialize buffer counter*/
0251         cmd = RX_PERIOD_DONE + MSG_TYPE_A_NUM;
0252         info->msg[cmd].s_msg.param.buffer_tail = 0;
0253         info->msg[cmd].r_msg.param.buffer_tail = 0;
0254         info->msg[RX_POINTER].r_msg.param.buffer_offset = 0;
0255     }
0256 
0257     info->send_message(msg, info);
0258 
0259     imx_rpmsg_pcm_hardware.period_bytes_max =
0260             imx_rpmsg_pcm_hardware.buffer_bytes_max / 2;
0261 
0262     snd_soc_set_runtime_hwparams(substream, &imx_rpmsg_pcm_hardware);
0263 
0264     ret = snd_pcm_hw_constraint_integer(substream->runtime,
0265                         SNDRV_PCM_HW_PARAM_PERIODS);
0266     if (ret < 0)
0267         return ret;
0268 
0269     info->msg_drop_count[substream->stream] = 0;
0270 
0271     /* Create timer*/
0272     info->stream_timer[substream->stream].info = info;
0273     info->stream_timer[substream->stream].substream = substream;
0274     timer_setup(&info->stream_timer[substream->stream].timer,
0275             imx_rpmsg_timer_callback, 0);
0276     return ret;
0277 }
0278 
0279 static int imx_rpmsg_pcm_close(struct snd_soc_component *component,
0280                    struct snd_pcm_substream *substream)
0281 {
0282     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0283     struct rpmsg_info *info = dev_get_drvdata(component->dev);
0284     struct rpmsg_msg *msg;
0285     int ret = 0;
0286 
0287     /* Flush work in workqueue to make TX_CLOSE is the last message */
0288     flush_workqueue(info->rpmsg_wq);
0289 
0290     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0291         msg = &info->msg[TX_CLOSE];
0292         msg->s_msg.header.cmd = TX_CLOSE;
0293     } else {
0294         msg = &info->msg[RX_CLOSE];
0295         msg->s_msg.header.cmd = RX_CLOSE;
0296     }
0297 
0298     info->send_message(msg, info);
0299 
0300     del_timer(&info->stream_timer[substream->stream].timer);
0301 
0302     rtd->dai_link->ignore_suspend = 0;
0303 
0304     if (info->msg_drop_count[substream->stream])
0305         dev_warn(rtd->dev, "Msg is dropped!, number is %d\n",
0306              info->msg_drop_count[substream->stream]);
0307 
0308     return ret;
0309 }
0310 
0311 static int imx_rpmsg_pcm_prepare(struct snd_soc_component *component,
0312                  struct snd_pcm_substream *substream)
0313 {
0314     struct snd_pcm_runtime *runtime = substream->runtime;
0315     struct snd_soc_pcm_runtime *rtd = substream->private_data;
0316     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0317     struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev);
0318 
0319     /*
0320      * NON-MMAP mode, NONBLOCK, Version 2, enable lpa in dts
0321      * four conditions to determine the lpa is enabled.
0322      */
0323     if ((runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
0324          runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) &&
0325          rpmsg->enable_lpa) {
0326         /*
0327          * Ignore suspend operation in low power mode
0328          * M core will continue playback music on A core suspend.
0329          */
0330         rtd->dai_link->ignore_suspend = 1;
0331         rpmsg->force_lpa = 1;
0332     } else {
0333         rpmsg->force_lpa = 0;
0334     }
0335 
0336     return 0;
0337 }
0338 
0339 static void imx_rpmsg_pcm_dma_complete(void *arg)
0340 {
0341     struct snd_pcm_substream *substream = arg;
0342 
0343     snd_pcm_period_elapsed(substream);
0344 }
0345 
0346 static int imx_rpmsg_prepare_and_submit(struct snd_soc_component *component,
0347                     struct snd_pcm_substream *substream)
0348 {
0349     struct rpmsg_info *info = dev_get_drvdata(component->dev);
0350     struct rpmsg_msg *msg;
0351 
0352     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0353         msg = &info->msg[TX_BUFFER];
0354         msg->s_msg.header.cmd = TX_BUFFER;
0355     } else {
0356         msg = &info->msg[RX_BUFFER];
0357         msg->s_msg.header.cmd = RX_BUFFER;
0358     }
0359 
0360     /* Send buffer address and buffer size */
0361     msg->s_msg.param.buffer_addr = substream->runtime->dma_addr;
0362     msg->s_msg.param.buffer_size = snd_pcm_lib_buffer_bytes(substream);
0363     msg->s_msg.param.period_size = snd_pcm_lib_period_bytes(substream);
0364     msg->s_msg.param.buffer_tail = 0;
0365 
0366     info->num_period[substream->stream] = msg->s_msg.param.buffer_size /
0367                           msg->s_msg.param.period_size;
0368 
0369     info->callback[substream->stream] = imx_rpmsg_pcm_dma_complete;
0370     info->callback_param[substream->stream] = substream;
0371 
0372     return imx_rpmsg_insert_workqueue(substream, msg, info);
0373 }
0374 
0375 static int imx_rpmsg_async_issue_pending(struct snd_soc_component *component,
0376                      struct snd_pcm_substream *substream)
0377 {
0378     struct rpmsg_info *info = dev_get_drvdata(component->dev);
0379     struct rpmsg_msg *msg;
0380 
0381     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0382         msg = &info->msg[TX_START];
0383         msg->s_msg.header.cmd = TX_START;
0384     } else {
0385         msg = &info->msg[RX_START];
0386         msg->s_msg.header.cmd = RX_START;
0387     }
0388 
0389     return imx_rpmsg_insert_workqueue(substream, msg, info);
0390 }
0391 
0392 static int imx_rpmsg_restart(struct snd_soc_component *component,
0393                  struct snd_pcm_substream *substream)
0394 {
0395     struct rpmsg_info *info = dev_get_drvdata(component->dev);
0396     struct rpmsg_msg *msg;
0397 
0398     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0399         msg = &info->msg[TX_RESTART];
0400         msg->s_msg.header.cmd = TX_RESTART;
0401     } else {
0402         msg = &info->msg[RX_RESTART];
0403         msg->s_msg.header.cmd = RX_RESTART;
0404     }
0405 
0406     return imx_rpmsg_insert_workqueue(substream, msg, info);
0407 }
0408 
0409 static int imx_rpmsg_pause(struct snd_soc_component *component,
0410                struct snd_pcm_substream *substream)
0411 {
0412     struct rpmsg_info *info = dev_get_drvdata(component->dev);
0413     struct rpmsg_msg *msg;
0414 
0415     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0416         msg = &info->msg[TX_PAUSE];
0417         msg->s_msg.header.cmd = TX_PAUSE;
0418     } else {
0419         msg = &info->msg[RX_PAUSE];
0420         msg->s_msg.header.cmd = RX_PAUSE;
0421     }
0422 
0423     return imx_rpmsg_insert_workqueue(substream, msg, info);
0424 }
0425 
0426 static int imx_rpmsg_terminate_all(struct snd_soc_component *component,
0427                    struct snd_pcm_substream *substream)
0428 {
0429     struct rpmsg_info *info = dev_get_drvdata(component->dev);
0430     struct rpmsg_msg *msg;
0431     int cmd;
0432 
0433     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0434         msg = &info->msg[TX_TERMINATE];
0435         msg->s_msg.header.cmd = TX_TERMINATE;
0436         /* Clear buffer count*/
0437         cmd = TX_PERIOD_DONE + MSG_TYPE_A_NUM;
0438         info->msg[cmd].s_msg.param.buffer_tail = 0;
0439         info->msg[cmd].r_msg.param.buffer_tail = 0;
0440         info->msg[TX_POINTER].r_msg.param.buffer_offset = 0;
0441     } else {
0442         msg = &info->msg[RX_TERMINATE];
0443         msg->s_msg.header.cmd = RX_TERMINATE;
0444         /* Clear buffer count*/
0445         cmd = RX_PERIOD_DONE + MSG_TYPE_A_NUM;
0446         info->msg[cmd].s_msg.param.buffer_tail = 0;
0447         info->msg[cmd].r_msg.param.buffer_tail = 0;
0448         info->msg[RX_POINTER].r_msg.param.buffer_offset = 0;
0449     }
0450 
0451     del_timer(&info->stream_timer[substream->stream].timer);
0452 
0453     return imx_rpmsg_insert_workqueue(substream, msg, info);
0454 }
0455 
0456 static int imx_rpmsg_pcm_trigger(struct snd_soc_component *component,
0457                  struct snd_pcm_substream *substream, int cmd)
0458 {
0459     struct snd_pcm_runtime *runtime = substream->runtime;
0460     struct snd_soc_pcm_runtime *rtd = substream->private_data;
0461     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0462     struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev);
0463     int ret = 0;
0464 
0465     switch (cmd) {
0466     case SNDRV_PCM_TRIGGER_START:
0467         ret = imx_rpmsg_prepare_and_submit(component, substream);
0468         if (ret)
0469             return ret;
0470         ret = imx_rpmsg_async_issue_pending(component, substream);
0471         break;
0472     case SNDRV_PCM_TRIGGER_RESUME:
0473         if (rpmsg->force_lpa)
0474             break;
0475         fallthrough;
0476     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0477         ret = imx_rpmsg_restart(component, substream);
0478         break;
0479     case SNDRV_PCM_TRIGGER_SUSPEND:
0480         if (!rpmsg->force_lpa) {
0481             if (runtime->info & SNDRV_PCM_INFO_PAUSE)
0482                 ret = imx_rpmsg_pause(component, substream);
0483             else
0484                 ret = imx_rpmsg_terminate_all(component, substream);
0485         }
0486         break;
0487     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0488         ret = imx_rpmsg_pause(component, substream);
0489         break;
0490     case SNDRV_PCM_TRIGGER_STOP:
0491         ret = imx_rpmsg_terminate_all(component, substream);
0492         break;
0493     default:
0494         return -EINVAL;
0495     }
0496 
0497     if (ret)
0498         return ret;
0499 
0500     return 0;
0501 }
0502 
0503 /*
0504  * imx_rpmsg_pcm_ack
0505  *
0506  * Send the period index to M core through rpmsg, but not send
0507  * all the period index to M core, reduce some unnessesary msg
0508  * to reduce the pressure of rpmsg bandwidth.
0509  */
0510 static int imx_rpmsg_pcm_ack(struct snd_soc_component *component,
0511                  struct snd_pcm_substream *substream)
0512 {
0513     struct snd_pcm_runtime *runtime = substream->runtime;
0514     struct snd_soc_pcm_runtime *rtd = substream->private_data;
0515     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0516     struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev);
0517     struct rpmsg_info *info = dev_get_drvdata(component->dev);
0518     snd_pcm_uframes_t period_size = runtime->period_size;
0519     snd_pcm_sframes_t avail;
0520     struct timer_list *timer;
0521     struct rpmsg_msg *msg;
0522     unsigned long flags;
0523     int buffer_tail = 0;
0524     int written_num;
0525 
0526     if (!rpmsg->force_lpa)
0527         return 0;
0528 
0529     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0530         msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
0531         msg->s_msg.header.cmd = TX_PERIOD_DONE;
0532     } else {
0533         msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
0534         msg->s_msg.header.cmd = RX_PERIOD_DONE;
0535     }
0536 
0537     msg->s_msg.header.type = MSG_TYPE_C;
0538 
0539     buffer_tail = (frames_to_bytes(runtime, runtime->control->appl_ptr) %
0540                snd_pcm_lib_buffer_bytes(substream));
0541     buffer_tail = buffer_tail / snd_pcm_lib_period_bytes(substream);
0542 
0543     /* There is update for period index */
0544     if (buffer_tail != msg->s_msg.param.buffer_tail) {
0545         written_num = buffer_tail - msg->s_msg.param.buffer_tail;
0546         if (written_num < 0)
0547             written_num += runtime->periods;
0548 
0549         msg->s_msg.param.buffer_tail = buffer_tail;
0550 
0551         /* The notification message is updated to latest */
0552         spin_lock_irqsave(&info->lock[substream->stream], flags);
0553         memcpy(&info->notify[substream->stream], msg,
0554                sizeof(struct rpmsg_s_msg));
0555         info->notify_updated[substream->stream] = true;
0556         spin_unlock_irqrestore(&info->lock[substream->stream], flags);
0557 
0558         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0559             avail = snd_pcm_playback_hw_avail(runtime);
0560         else
0561             avail = snd_pcm_capture_hw_avail(runtime);
0562 
0563         timer = &info->stream_timer[substream->stream].timer;
0564         /*
0565          * If the data in the buffer is less than one period before
0566          * this fill, which means the data may not enough on M
0567          * core side, we need to send message immediately to let
0568          * M core know the pointer is updated.
0569          * if there is more than one period data in the buffer before
0570          * this fill, which means the data is enough on M core side,
0571          * we can delay one period (using timer) to send the message
0572          * for reduce the message number in workqueue, because the
0573          * pointer may be updated by ack function later, we can
0574          * send latest pointer to M core side.
0575          */
0576         if ((avail - written_num * period_size) <= period_size) {
0577             imx_rpmsg_insert_workqueue(substream, msg, info);
0578         } else if (rpmsg->force_lpa && !timer_pending(timer)) {
0579             int time_msec;
0580 
0581             time_msec = (int)(runtime->period_size * 1000 / runtime->rate);
0582             mod_timer(timer, jiffies + msecs_to_jiffies(time_msec));
0583         }
0584     }
0585 
0586     return 0;
0587 }
0588 
0589 static int imx_rpmsg_pcm_new(struct snd_soc_component *component,
0590                  struct snd_soc_pcm_runtime *rtd)
0591 {
0592     struct snd_card *card = rtd->card->snd_card;
0593     struct snd_pcm *pcm = rtd->pcm;
0594     struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
0595     struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev);
0596     int ret;
0597 
0598     ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
0599     if (ret)
0600         return ret;
0601 
0602     imx_rpmsg_pcm_hardware.buffer_bytes_max = rpmsg->buffer_size;
0603     return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
0604                         pcm->card->dev, rpmsg->buffer_size);
0605 }
0606 
0607 static const struct snd_soc_component_driver imx_rpmsg_soc_component = {
0608     .name       = IMX_PCM_DRV_NAME,
0609     .pcm_construct  = imx_rpmsg_pcm_new,
0610     .open       = imx_rpmsg_pcm_open,
0611     .close      = imx_rpmsg_pcm_close,
0612     .hw_params  = imx_rpmsg_pcm_hw_params,
0613     .trigger    = imx_rpmsg_pcm_trigger,
0614     .pointer    = imx_rpmsg_pcm_pointer,
0615     .ack        = imx_rpmsg_pcm_ack,
0616     .prepare    = imx_rpmsg_pcm_prepare,
0617 };
0618 
0619 static void imx_rpmsg_pcm_work(struct work_struct *work)
0620 {
0621     struct work_of_rpmsg *work_of_rpmsg;
0622     bool is_notification = false;
0623     struct rpmsg_info *info;
0624     struct rpmsg_msg msg;
0625     unsigned long flags;
0626 
0627     work_of_rpmsg = container_of(work, struct work_of_rpmsg, work);
0628     info = work_of_rpmsg->info;
0629 
0630     /*
0631      * Every work in the work queue, first we check if there
0632      * is update for period is filled, because there may be not
0633      * enough data in M core side, need to let M core know
0634      * data is updated immediately.
0635      */
0636     spin_lock_irqsave(&info->lock[TX], flags);
0637     if (info->notify_updated[TX]) {
0638         memcpy(&msg, &info->notify[TX], sizeof(struct rpmsg_s_msg));
0639         info->notify_updated[TX] = false;
0640         spin_unlock_irqrestore(&info->lock[TX], flags);
0641         info->send_message(&msg, info);
0642     } else {
0643         spin_unlock_irqrestore(&info->lock[TX], flags);
0644     }
0645 
0646     spin_lock_irqsave(&info->lock[RX], flags);
0647     if (info->notify_updated[RX]) {
0648         memcpy(&msg, &info->notify[RX], sizeof(struct rpmsg_s_msg));
0649         info->notify_updated[RX] = false;
0650         spin_unlock_irqrestore(&info->lock[RX], flags);
0651         info->send_message(&msg, info);
0652     } else {
0653         spin_unlock_irqrestore(&info->lock[RX], flags);
0654     }
0655 
0656     /* Skip the notification message for it has been processed above */
0657     if (work_of_rpmsg->msg.s_msg.header.type == MSG_TYPE_C &&
0658         (work_of_rpmsg->msg.s_msg.header.cmd == TX_PERIOD_DONE ||
0659          work_of_rpmsg->msg.s_msg.header.cmd == RX_PERIOD_DONE))
0660         is_notification = true;
0661 
0662     if (!is_notification)
0663         info->send_message(&work_of_rpmsg->msg, info);
0664 
0665     /* update read index */
0666     spin_lock_irqsave(&info->wq_lock, flags);
0667     info->work_read_index++;
0668     info->work_read_index %= WORK_MAX_NUM;
0669     spin_unlock_irqrestore(&info->wq_lock, flags);
0670 }
0671 
0672 static int imx_rpmsg_pcm_probe(struct platform_device *pdev)
0673 {
0674     struct snd_soc_component *component;
0675     struct rpmsg_info *info;
0676     int ret, i;
0677 
0678     info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
0679     if (!info)
0680         return -ENOMEM;
0681 
0682     platform_set_drvdata(pdev, info);
0683 
0684     info->rpdev = container_of(pdev->dev.parent, struct rpmsg_device, dev);
0685     info->dev = &pdev->dev;
0686     /* Setup work queue */
0687     info->rpmsg_wq = alloc_ordered_workqueue("rpmsg_audio",
0688                          WQ_HIGHPRI |
0689                          WQ_UNBOUND |
0690                          WQ_FREEZABLE);
0691     if (!info->rpmsg_wq) {
0692         dev_err(&pdev->dev, "workqueue create failed\n");
0693         return -ENOMEM;
0694     }
0695 
0696     /* Write index initialize 1, make it differ with the read index */
0697     info->work_write_index = 1;
0698     info->send_message = imx_rpmsg_pcm_send_message;
0699 
0700     for (i = 0; i < WORK_MAX_NUM; i++) {
0701         INIT_WORK(&info->work_list[i].work, imx_rpmsg_pcm_work);
0702         info->work_list[i].info = info;
0703     }
0704 
0705     /* Initialize msg */
0706     for (i = 0; i < MSG_MAX_NUM; i++) {
0707         info->msg[i].s_msg.header.cate  = IMX_RPMSG_AUDIO;
0708         info->msg[i].s_msg.header.major = IMX_RMPSG_MAJOR;
0709         info->msg[i].s_msg.header.minor = IMX_RMPSG_MINOR;
0710         info->msg[i].s_msg.header.type  = MSG_TYPE_A;
0711         info->msg[i].s_msg.param.audioindex = 0;
0712     }
0713 
0714     init_completion(&info->cmd_complete);
0715     mutex_init(&info->msg_lock);
0716     spin_lock_init(&info->lock[TX]);
0717     spin_lock_init(&info->lock[RX]);
0718     spin_lock_init(&info->wq_lock);
0719 
0720     ret = devm_snd_soc_register_component(&pdev->dev,
0721                           &imx_rpmsg_soc_component,
0722                           NULL, 0);
0723     if (ret)
0724         goto fail;
0725 
0726     component = snd_soc_lookup_component(&pdev->dev, IMX_PCM_DRV_NAME);
0727     if (!component) {
0728         ret = -EINVAL;
0729         goto fail;
0730     }
0731 #ifdef CONFIG_DEBUG_FS
0732     component->debugfs_prefix = "rpmsg";
0733 #endif
0734 
0735     return 0;
0736 
0737 fail:
0738     if (info->rpmsg_wq)
0739         destroy_workqueue(info->rpmsg_wq);
0740 
0741     return ret;
0742 }
0743 
0744 static int imx_rpmsg_pcm_remove(struct platform_device *pdev)
0745 {
0746     struct rpmsg_info *info = platform_get_drvdata(pdev);
0747 
0748     if (info->rpmsg_wq)
0749         destroy_workqueue(info->rpmsg_wq);
0750 
0751     return 0;
0752 }
0753 
0754 #ifdef CONFIG_PM
0755 static int imx_rpmsg_pcm_runtime_resume(struct device *dev)
0756 {
0757     struct rpmsg_info *info = dev_get_drvdata(dev);
0758 
0759     cpu_latency_qos_add_request(&info->pm_qos_req, 0);
0760 
0761     return 0;
0762 }
0763 
0764 static int imx_rpmsg_pcm_runtime_suspend(struct device *dev)
0765 {
0766     struct rpmsg_info *info = dev_get_drvdata(dev);
0767 
0768     cpu_latency_qos_remove_request(&info->pm_qos_req);
0769 
0770     return 0;
0771 }
0772 #endif
0773 
0774 #ifdef CONFIG_PM_SLEEP
0775 static int imx_rpmsg_pcm_suspend(struct device *dev)
0776 {
0777     struct rpmsg_info *info = dev_get_drvdata(dev);
0778     struct rpmsg_msg *rpmsg_tx;
0779     struct rpmsg_msg *rpmsg_rx;
0780 
0781     rpmsg_tx = &info->msg[TX_SUSPEND];
0782     rpmsg_rx = &info->msg[RX_SUSPEND];
0783 
0784     rpmsg_tx->s_msg.header.cmd = TX_SUSPEND;
0785     info->send_message(rpmsg_tx, info);
0786 
0787     rpmsg_rx->s_msg.header.cmd = RX_SUSPEND;
0788     info->send_message(rpmsg_rx, info);
0789 
0790     return 0;
0791 }
0792 
0793 static int imx_rpmsg_pcm_resume(struct device *dev)
0794 {
0795     struct rpmsg_info *info = dev_get_drvdata(dev);
0796     struct rpmsg_msg *rpmsg_tx;
0797     struct rpmsg_msg *rpmsg_rx;
0798 
0799     rpmsg_tx = &info->msg[TX_RESUME];
0800     rpmsg_rx = &info->msg[RX_RESUME];
0801 
0802     rpmsg_tx->s_msg.header.cmd = TX_RESUME;
0803     info->send_message(rpmsg_tx, info);
0804 
0805     rpmsg_rx->s_msg.header.cmd = RX_RESUME;
0806     info->send_message(rpmsg_rx, info);
0807 
0808     return 0;
0809 }
0810 #endif /* CONFIG_PM_SLEEP */
0811 
0812 static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = {
0813     SET_RUNTIME_PM_OPS(imx_rpmsg_pcm_runtime_suspend,
0814                imx_rpmsg_pcm_runtime_resume,
0815                NULL)
0816     SET_SYSTEM_SLEEP_PM_OPS(imx_rpmsg_pcm_suspend,
0817                 imx_rpmsg_pcm_resume)
0818 };
0819 
0820 static struct platform_driver imx_pcm_rpmsg_driver = {
0821     .probe  = imx_rpmsg_pcm_probe,
0822     .remove = imx_rpmsg_pcm_remove,
0823     .driver = {
0824         .name = IMX_PCM_DRV_NAME,
0825         .pm = &imx_rpmsg_pcm_pm_ops,
0826     },
0827 };
0828 module_platform_driver(imx_pcm_rpmsg_driver);
0829 
0830 MODULE_DESCRIPTION("Freescale SoC Audio RPMSG PCM interface");
0831 MODULE_AUTHOR("Shengjiu Wang <shengjiu.wang@nxp.com>");
0832 MODULE_ALIAS("platform:" IMX_PCM_DRV_NAME);
0833 MODULE_LICENSE("GPL v2");