From 26e4c3d80f3ce07dbe5732009b4e6a46ec370966 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 7 Mar 2019 11:01:06 +0800 Subject: ASoC: fsl_rpmsg: Merge changes from imx_4.19.y 77be7d36a525 ("MLK-22400-1: ASoC: fsl_rpmsg_i2s: Add rpmsg i2s for imx8mn") 31d5dfa44c20 ("MLK-22340-5: ASoC: imx-pcm-rpmsg: enable ignore_suspend for LPA") c5c41138d5c8 ("MLK-22340-4: ASoC: fsl_rpmsg_i2s: add lock to protect the resource") adb4b596d2ba ("MLK-22340-3: ASoC: imx-pcm-rpmsg: refine the timer") a5e80bf012c3 ("MLK-22340-2: ASoC: imx-pcm-rpmsg: drop the cmd I2S_TX_POINTER") 404367d9316b ("MLK-21980: ASoC: imx-pcm-rpmsg: add debugfs_prefix for platform") 971faf095246 ("MLK-21450: ASoC: fsl_rpmsg: fix timer issue for updating to 4.19") edbbcdc07bf1 ("MLK-21461: ASoC: fsl_rpmsg_i2s: clear buffer pointer in i2s_send_message") f5f2f38018d8 ("MLK-21447: ASoC: fsl_rpmsg_i2s: underrun in m4 for msg delayed") d9410ace757f ("MLK-21307: ASoC: fsl_rpmsg_i2s: optimize the message sent to m4") 98633a4cd35b ("MLK-21440-1: ASoC: fsl_rpmsg_i2s: init spin lock") 7bf6d3131863 ("MLK-21107-1: ASoC: Fix timer wake up system after suspend") eb422681ffa4 ("MLK-20661: ASoC: imx-pcm-rpmsg: remove the nonblock constraint") e36957e97ca9 ("MLK-21002-1: ASoC: imx-pcm-rpmsg: fix data consumed faster with pause") bc828e61693f ("MLK-19565-1: ASoC: fsl_rpmsg_i2s: support rpmsg on imx8qm") e56bedf71ae4 ("MLK-21107-2: ASoC: Drop msg if msg queue is full") Signed-off-by: Shengjiu Wang (cherry picked from commit 31def064871336af7780d01a6ed8c5ed075b7e48) --- sound/soc/fsl/fsl_rpmsg_i2s.c | 68 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) (limited to 'sound/soc/fsl/fsl_rpmsg_i2s.c') diff --git a/sound/soc/fsl/fsl_rpmsg_i2s.c b/sound/soc/fsl/fsl_rpmsg_i2s.c index c94212dfb48f..4ba151186681 100644 --- a/sound/soc/fsl/fsl_rpmsg_i2s.c +++ b/sound/soc/fsl/fsl_rpmsg_i2s.c @@ -70,6 +70,25 @@ static int i2s_send_message(struct i2s_rpmsg *msg, sizeof(struct i2s_rpmsg_r)); memcpy(&info->rpmsg[msg->recv_msg.header.cmd].recv_msg, &msg->recv_msg, sizeof(struct i2s_rpmsg_r)); + + /* + * Reset the buffer pointer to be zero, actully we have + * set the buffer pointer to be zero in imx_rpmsg_terminate_all + * But if there is timer task queued in queue, after it is + * executed the buffer pointer will be changed, so need to + * reset it again with TERMINATE command. + */ + + switch (msg->send_msg.header.cmd) { + case I2S_TX_TERMINATE: + info->rpmsg[I2S_TX_POINTER].recv_msg.param.buffer_offset = 0; + break; + case I2S_RX_TERMINATE: + info->rpmsg[I2S_RX_POINTER].recv_msg.param.buffer_offset = 0; + break; + default: + break; + } } dev_dbg(&info->rpdev->dev, "cmd:%d, resp %d\n", @@ -136,6 +155,7 @@ static const struct of_device_id fsl_rpmsg_i2s_ids[] = { { .compatible = "fsl,imx8mq-rpmsg-i2s"}, { .compatible = "fsl,imx8qxp-rpmsg-i2s"}, { .compatible = "fsl,imx8qm-rpmsg-i2s"}, + { .compatible = "fsl,imx8mn-rpmsg-i2s"}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_rpmsg_i2s_ids); @@ -144,11 +164,40 @@ static void rpmsg_i2s_work(struct work_struct *work) { struct work_of_rpmsg *work_of_rpmsg; struct i2s_info *i2s_info; + bool is_period_done = false; + unsigned long flags; + struct i2s_rpmsg msg; work_of_rpmsg = container_of(work, struct work_of_rpmsg, work); i2s_info = work_of_rpmsg->i2s_info; - i2s_send_message(&work_of_rpmsg->msg, i2s_info); + spin_lock_irqsave(&i2s_info->lock[0], flags); + if (i2s_info->period_done_msg_enabled[0]) { + memcpy(&msg, &i2s_info->period_done_msg[0], sizeof(struct i2s_rpmsg_s)); + i2s_info->period_done_msg_enabled[0] = false; + spin_unlock_irqrestore(&i2s_info->lock[0], flags); + + i2s_send_message(&msg, i2s_info); + } else + spin_unlock_irqrestore(&i2s_info->lock[0], flags); + + if (i2s_info->period_done_msg_enabled[1]) { + i2s_send_message(&i2s_info->period_done_msg[1], i2s_info); + i2s_info->period_done_msg_enabled[1] = false; + } + + if (work_of_rpmsg->msg.send_msg.header.type == I2S_TYPE_C && + (work_of_rpmsg->msg.send_msg.header.cmd == I2S_TX_PERIOD_DONE || + work_of_rpmsg->msg.send_msg.header.cmd == I2S_RX_PERIOD_DONE)) + is_period_done = true; + + if (!is_period_done) + i2s_send_message(&work_of_rpmsg->msg, i2s_info); + + spin_lock_irqsave(&i2s_info->wq_lock, flags); + i2s_info->work_read_index++; + i2s_info->work_read_index %= WORK_MAX_NUM; + spin_unlock_irqrestore(&i2s_info->wq_lock, flags); } static int fsl_rpmsg_i2s_probe(struct platform_device *pdev) @@ -179,6 +228,7 @@ static int fsl_rpmsg_i2s_probe(struct platform_device *pdev) return -ENOMEM; } + i2s_info->work_write_index = 1; i2s_info->send_message = i2s_send_message; for (i = 0; i < WORK_MAX_NUM; i++) { @@ -198,6 +248,7 @@ static int fsl_rpmsg_i2s_probe(struct platform_device *pdev) mutex_init(&i2s_info->i2c_lock); spin_lock_init(&i2s_info->lock[0]); spin_lock_init(&i2s_info->lock[1]); + spin_lock_init(&i2s_info->wq_lock); if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx7ulp-rpmsg-i2s")) { @@ -246,6 +297,21 @@ static int fsl_rpmsg_i2s_probe(struct platform_device *pdev) fsl_rpmsg_i2s_dai.capture.formats = rpmsg_i2s->formats; } + if (of_device_is_compatible(pdev->dev.of_node, + "fsl,imx8mn-rpmsg-i2s")) { + rpmsg_i2s->codec_dummy = 1; + rpmsg_i2s->version = 2; + rpmsg_i2s->rates = SNDRV_PCM_RATE_KNOT; + rpmsg_i2s->formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE; + + fsl_rpmsg_i2s_dai.playback.rates = rpmsg_i2s->rates; + fsl_rpmsg_i2s_dai.playback.formats = rpmsg_i2s->formats; + fsl_rpmsg_i2s_dai.capture.rates = rpmsg_i2s->rates; + fsl_rpmsg_i2s_dai.capture.formats = rpmsg_i2s->formats; + } + if (of_property_read_bool(pdev->dev.of_node, "fsl,enable-lpa")) rpmsg_i2s->enable_lpa = 1; -- cgit v1.2.3