summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@freescale.com>2017-02-23 15:54:20 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:52:52 +0800
commitc040763b306ba030c4213e9a927038e9e217b885 (patch)
tree79175a31fc6258b17f4d2924b7d77fadc39e0020 /sound
parent45aa9064e240a0174754aed88a0f9c6dd83fe1a4 (diff)
MLK-14254: ASoC: imx_pcm_rpmsg: fix cmd dropped by work queue
The test case is to playback a bitstream, then repeat ctrl+z and fg, several times later, the playback is failed to continue. The reason is if the work is pending in work queue, send second time of this work, the second work is dropped by work queue. so use one work for one cmd is not fit for audio case. use a work loop for audio cmd to fix this issue. Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/fsl/fsl_rpmsg_i2s.h1
-rw-r--r--sound/soc/fsl/imx-pcm-rpmsg.c65
2 files changed, 36 insertions, 30 deletions
diff --git a/sound/soc/fsl/fsl_rpmsg_i2s.h b/sound/soc/fsl/fsl_rpmsg_i2s.h
index 7439f8a81923..0fcc80de953f 100644
--- a/sound/soc/fsl/fsl_rpmsg_i2s.h
+++ b/sound/soc/fsl/fsl_rpmsg_i2s.h
@@ -290,6 +290,7 @@ struct i2s_info {
struct workqueue_struct *rpmsg_wq;
struct work_of_rpmsg work_list[WORK_MAX_NUM];
+ int work_index;
int num_period[2];
void *callback_param[2];
int (*send_message)(struct i2s_rpmsg_s *msg, struct i2s_info *info);
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
index ace3bd77c8c2..2ece2cfaa728 100644
--- a/sound/soc/fsl/imx-pcm-rpmsg.c
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -189,14 +189,13 @@ static int imx_rpmsg_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
- u8 cmd;
+ u8 index = i2s_info->work_index;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- cmd = I2S_TX_BUFFER;
+ rpmsg->header.cmd = I2S_TX_BUFFER;
else
- cmd = I2S_RX_BUFFER;
+ rpmsg->header.cmd = I2S_RX_BUFFER;
- rpmsg->header.cmd = cmd;
rpmsg->param.buffer_addr = substream->runtime->dma_addr;
rpmsg->param.buffer_size = snd_pcm_lib_buffer_bytes(substream);
rpmsg->param.period_size = snd_pcm_lib_period_bytes(substream);
@@ -205,9 +204,11 @@ static int imx_rpmsg_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
i2s_info->num_period[substream->stream] =
rpmsg->param.buffer_size/rpmsg->param.period_size;
- memcpy(&i2s_info->work_list[cmd].msg, rpmsg,
+ memcpy(&i2s_info->work_list[index].msg, rpmsg,
sizeof(struct i2s_rpmsg_s));
- queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[cmd].work);
+ queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
+ i2s_info->work_index++;
+ i2s_info->work_index %= WORK_MAX_NUM;
i2s_info->callback[substream->stream] = imx_rpmsg_pcm_dma_complete;
i2s_info->callback_param[substream->stream] = substream;
@@ -221,17 +222,18 @@ static void imx_rpmsg_async_issue_pending(struct snd_pcm_substream *substream)
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
- u8 cmd;
+ u8 index = i2s_info->work_index;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- cmd = I2S_TX_START;
+ rpmsg->header.cmd = I2S_TX_START;
else
- cmd = I2S_RX_START;
+ rpmsg->header.cmd = I2S_RX_START;
- rpmsg->header.cmd = cmd;
- memcpy(&i2s_info->work_list[cmd].msg, rpmsg,
+ memcpy(&i2s_info->work_list[index].msg, rpmsg,
sizeof(struct i2s_rpmsg_s));
- queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[cmd].work);
+ queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
+ i2s_info->work_index++;
+ i2s_info->work_index %= WORK_MAX_NUM;
}
static int imx_rpmsg_resume(struct snd_pcm_substream *substream)
@@ -241,17 +243,18 @@ static int imx_rpmsg_resume(struct snd_pcm_substream *substream)
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
- u8 cmd;
+ u8 index = i2s_info->work_index;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- cmd = I2S_TX_RESTART;
+ rpmsg->header.cmd = I2S_TX_RESTART;
else
- cmd = I2S_RX_RESTART;
+ rpmsg->header.cmd = I2S_RX_RESTART;
- rpmsg->header.cmd = cmd;
- memcpy(&i2s_info->work_list[cmd].msg, rpmsg,
+ memcpy(&i2s_info->work_list[index].msg, rpmsg,
sizeof(struct i2s_rpmsg_s));
- queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[cmd].work);
+ queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
+ i2s_info->work_index++;
+ i2s_info->work_index %= WORK_MAX_NUM;
return 0;
}
@@ -263,17 +266,18 @@ static int imx_rpmsg_pause(struct snd_pcm_substream *substream)
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
- u8 cmd;
+ u8 index = i2s_info->work_index;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- cmd = I2S_TX_PAUSE;
+ rpmsg->header.cmd = I2S_TX_PAUSE;
else
- cmd = I2S_RX_PAUSE;
+ rpmsg->header.cmd = I2S_RX_PAUSE;
- rpmsg->header.cmd = cmd;
- memcpy(&i2s_info->work_list[cmd].msg, rpmsg,
+ memcpy(&i2s_info->work_list[index].msg, rpmsg,
sizeof(struct i2s_rpmsg_s));
- queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[cmd].work);
+ queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
+ i2s_info->work_index++;
+ i2s_info->work_index %= WORK_MAX_NUM;
return 0;
}
@@ -285,17 +289,18 @@ static int imx_rpmsg_terminate_all(struct snd_pcm_substream *substream)
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
struct i2s_rpmsg_s *rpmsg = &i2s_info->send_msg[substream->stream];
- u8 cmd;
+ u8 index = i2s_info->work_index;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- cmd = I2S_TX_TERMINATE;
+ rpmsg->header.cmd = I2S_TX_TERMINATE;
else
- cmd = I2S_RX_TERMINATE;
+ rpmsg->header.cmd = I2S_RX_TERMINATE;
- rpmsg->header.cmd = cmd;
- memcpy(&i2s_info->work_list[cmd].msg, rpmsg,
+ memcpy(&i2s_info->work_list[index].msg, rpmsg,
sizeof(struct i2s_rpmsg_s));
- queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[cmd].work);
+ queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
+ i2s_info->work_index++;
+ i2s_info->work_index %= WORK_MAX_NUM;
return 0;
}