diff --git a/sound/soc/fsl/fsl_rpmsg_i2s.c b/sound/soc/fsl/fsl_rpmsg_i2s.c index 192802ae339be49207b9aaf8bb01bb11c4e3c24d..c6836736662b73bb1da7ed2f6e9e66bdc4a9cfbe 100644 --- a/sound/soc/fsl/fsl_rpmsg_i2s.c +++ b/sound/soc/fsl/fsl_rpmsg_i2s.c @@ -149,6 +149,9 @@ static void rpmsg_i2s_work(struct work_struct *work) i2s_info = work_of_rpmsg->i2s_info; i2s_send_message(&work_of_rpmsg->msg, i2s_info); + + i2s_info->work_read_index++; + i2s_info->work_read_index %= WORK_MAX_NUM; } static int fsl_rpmsg_i2s_probe(struct platform_device *pdev) @@ -179,6 +182,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++) { diff --git a/sound/soc/fsl/fsl_rpmsg_i2s.h b/sound/soc/fsl/fsl_rpmsg_i2s.h index 36d6c5f51360039bf58166cbd6a7d1d2e80ab12e..14922f1a7690807f458cd8bf3020ab22a1088a77 100644 --- a/sound/soc/fsl/fsl_rpmsg_i2s.h +++ b/sound/soc/fsl/fsl_rpmsg_i2s.h @@ -309,7 +309,7 @@ #define I2S_TYPE_A_NUM 0x18 -#define WORK_MAX_NUM 0x18 +#define WORK_MAX_NUM 0x30 #define I2S_TX_PERIOD_DONE 0x0 #define I2S_RX_PERIOD_DONE 0x1 @@ -397,7 +397,9 @@ struct i2s_info { struct workqueue_struct *rpmsg_wq; struct work_of_rpmsg work_list[WORK_MAX_NUM]; - int work_index; + int work_write_index; + int work_read_index; + int msg_drop_count[2]; int num_period[2]; void *callback_param[2]; int (*send_message)(struct i2s_rpmsg *msg, struct i2s_info *info); diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index c61dc98dd335386d933c1dd85cea5141b0e52b56..1cbdf4215c11e69700babcb43ab7aa5cb5fe5c20 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -127,7 +127,7 @@ static void imx_rpmsg_timer_callback(unsigned long data) struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev); struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info; struct i2s_rpmsg *rpmsg; - u8 index = i2s_info->work_index; + int index = i2s_info->work_write_index; int time_msec; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -140,11 +140,14 @@ static void imx_rpmsg_timer_callback(unsigned long data) else rpmsg->send_msg.header.cmd = I2S_RX_POINTER; - memcpy(&i2s_info->work_list[index].msg, rpmsg, + if (i2s_info->work_write_index != i2s_info->work_read_index) { + memcpy(&i2s_info->work_list[index].msg, rpmsg, sizeof(struct i2s_rpmsg_s)); - queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); - i2s_info->work_index++; - i2s_info->work_index %= WORK_MAX_NUM; + queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); + i2s_info->work_write_index++; + i2s_info->work_write_index %= WORK_MAX_NUM; + } else + i2s_info->msg_drop_count[substream->stream]++; if (rpmsg_i2s->force_lpa) { time_msec = (int)(runtime->period_size*1000/runtime->rate); @@ -208,6 +211,7 @@ static int imx_rpmsg_pcm_open(struct snd_pcm_substream *substream) if (ret < 0) return ret; + i2s_info->msg_drop_count[substream->stream] = 0; /*create thread*/ setup_timer(&i2s_info->stream_timer[substream->stream], @@ -243,6 +247,10 @@ static int imx_rpmsg_pcm_close(struct snd_pcm_substream *substream) kfree(prtd); + if (i2s_info->msg_drop_count[substream->stream]) + dev_warn(rtd->dev, "Msg is dropped!, number is %d\n", + i2s_info->msg_drop_count[substream->stream]); + return ret; } @@ -324,7 +332,7 @@ 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 *rpmsg; - u8 index = i2s_info->work_index; + int index = i2s_info->work_write_index; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) rpmsg = &i2s_info->rpmsg[I2S_TX_BUFFER]; @@ -346,18 +354,21 @@ static int imx_rpmsg_pcm_prepare_and_submit(struct snd_pcm_substream *substream) rpmsg->send_msg.param.buffer_size / rpmsg->send_msg.param.period_size; - memcpy(&i2s_info->work_list[index].msg, rpmsg, + if (i2s_info->work_write_index != i2s_info->work_read_index) { + memcpy(&i2s_info->work_list[index].msg, rpmsg, sizeof(struct i2s_rpmsg_s)); - queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); - i2s_info->work_index++; - i2s_info->work_index %= WORK_MAX_NUM; + queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); + i2s_info->work_write_index++; + i2s_info->work_write_index %= WORK_MAX_NUM; + } else + return -EPIPE; i2s_info->callback[substream->stream] = imx_rpmsg_pcm_dma_complete; i2s_info->callback_param[substream->stream] = substream; return 0; } -static void imx_rpmsg_async_issue_pending(struct snd_pcm_substream *substream) +static int imx_rpmsg_async_issue_pending(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -365,7 +376,7 @@ 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 *rpmsg; - u8 index = i2s_info->work_index; + int index = i2s_info->work_write_index; int time_msec; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -378,17 +389,22 @@ static void imx_rpmsg_async_issue_pending(struct snd_pcm_substream *substream) else rpmsg->send_msg.header.cmd = I2S_RX_START; - memcpy(&i2s_info->work_list[index].msg, rpmsg, - sizeof(struct i2s_rpmsg_s)); - queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); - i2s_info->work_index++; - i2s_info->work_index %= WORK_MAX_NUM; + if (i2s_info->work_write_index != i2s_info->work_read_index) { + memcpy(&i2s_info->work_list[index].msg, rpmsg, + sizeof(struct i2s_rpmsg_s)); + queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); + i2s_info->work_write_index++; + i2s_info->work_write_index %= WORK_MAX_NUM; + } else + return -EPIPE; if (rpmsg_i2s->force_lpa) { time_msec = (int)(runtime->period_size*1000/runtime->rate); mod_timer(&i2s_info->stream_timer[substream->stream], jiffies + msecs_to_jiffies(time_msec)); } + + return 0; } static int imx_rpmsg_restart(struct snd_pcm_substream *substream) @@ -398,7 +414,7 @@ static int imx_rpmsg_restart(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 *rpmsg; - u8 index = i2s_info->work_index; + int index = i2s_info->work_write_index; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) rpmsg = &i2s_info->rpmsg[I2S_TX_RESTART]; @@ -410,11 +426,14 @@ static int imx_rpmsg_restart(struct snd_pcm_substream *substream) else rpmsg->send_msg.header.cmd = I2S_RX_RESTART; - memcpy(&i2s_info->work_list[index].msg, rpmsg, + if (i2s_info->work_write_index != i2s_info->work_read_index) { + memcpy(&i2s_info->work_list[index].msg, rpmsg, sizeof(struct i2s_rpmsg_s)); - queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); - i2s_info->work_index++; - i2s_info->work_index %= WORK_MAX_NUM; + queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); + i2s_info->work_write_index++; + i2s_info->work_write_index %= WORK_MAX_NUM; + } else + return -EPIPE; return 0; } @@ -426,7 +445,7 @@ 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 *rpmsg; - u8 index = i2s_info->work_index; + int index = i2s_info->work_write_index; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) rpmsg = &i2s_info->rpmsg[I2S_TX_PAUSE]; @@ -438,11 +457,15 @@ static int imx_rpmsg_pause(struct snd_pcm_substream *substream) else rpmsg->send_msg.header.cmd = I2S_RX_PAUSE; - memcpy(&i2s_info->work_list[index].msg, rpmsg, - sizeof(struct i2s_rpmsg_s)); - queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); - i2s_info->work_index++; - i2s_info->work_index %= WORK_MAX_NUM; + if (i2s_info->work_write_index != i2s_info->work_read_index) { + memcpy(&i2s_info->work_list[index].msg, rpmsg, + sizeof(struct i2s_rpmsg_s)); + queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); + i2s_info->work_write_index++; + i2s_info->work_write_index %= WORK_MAX_NUM; + } else + return -EPIPE; + return 0; } @@ -453,7 +476,7 @@ 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 *rpmsg; - u8 index = i2s_info->work_index; + int index = i2s_info->work_write_index; int cmd; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -466,12 +489,6 @@ static int imx_rpmsg_terminate_all(struct snd_pcm_substream *substream) else rpmsg->send_msg.header.cmd = I2S_RX_TERMINATE; - memcpy(&i2s_info->work_list[index].msg, rpmsg, - sizeof(struct i2s_rpmsg_s)); - queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); - i2s_info->work_index++; - i2s_info->work_index %= WORK_MAX_NUM; - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { cmd = I2S_TX_PERIOD_DONE + I2S_TYPE_A_NUM; i2s_info->rpmsg[cmd].send_msg.param.buffer_tail = 0; @@ -485,6 +502,16 @@ static int imx_rpmsg_terminate_all(struct snd_pcm_substream *substream) } del_timer(&i2s_info->stream_timer[substream->stream]); + + if (i2s_info->work_write_index != i2s_info->work_read_index) { + memcpy(&i2s_info->work_list[index].msg, rpmsg, + sizeof(struct i2s_rpmsg_s)); + queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work); + i2s_info->work_write_index++; + i2s_info->work_write_index %= WORK_MAX_NUM; + } else + return -EPIPE; + return 0; } @@ -495,14 +522,14 @@ int imx_rpmsg_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_soc_dai *cpu_dai = rtd->cpu_dai; struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev); struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info; - int ret; + int ret = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: ret = imx_rpmsg_pcm_prepare_and_submit(substream); if (ret) return ret; - imx_rpmsg_async_issue_pending(substream); + ret = imx_rpmsg_async_issue_pending(substream); break; case SNDRV_PCM_TRIGGER_RESUME: if (rpmsg_i2s->force_lpa) { @@ -514,27 +541,30 @@ int imx_rpmsg_pcm_trigger(struct snd_pcm_substream *substream, int cmd) break; } case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - imx_rpmsg_restart(substream); + ret = imx_rpmsg_restart(substream); break; case SNDRV_PCM_TRIGGER_SUSPEND: if (!rpmsg_i2s->force_lpa) { if (runtime->info & SNDRV_PCM_INFO_PAUSE) - imx_rpmsg_pause(substream); + ret = imx_rpmsg_pause(substream); else - imx_rpmsg_terminate_all(substream); + ret = imx_rpmsg_terminate_all(substream); } else del_timer(&i2s_info->stream_timer[substream->stream]); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - imx_rpmsg_pause(substream); + ret = imx_rpmsg_pause(substream); break; case SNDRV_PCM_TRIGGER_STOP: - imx_rpmsg_terminate_all(substream); + ret = imx_rpmsg_terminate_all(substream); break; default: return -EINVAL; } + if (ret) + return ret; + return 0; } @@ -547,7 +577,7 @@ int imx_rpmsg_pcm_ack(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 *rpmsg; - u8 index = i2s_info->work_index; + int index = i2s_info->work_write_index; int buffer_tail = 0; if (!rpmsg_i2s->force_lpa) @@ -571,12 +601,15 @@ int imx_rpmsg_pcm_ack(struct snd_pcm_substream *substream) if (buffer_tail != rpmsg->send_msg.param.buffer_tail) { rpmsg->send_msg.param.buffer_tail = buffer_tail; - memcpy(&i2s_info->work_list[index].msg, rpmsg, + if (i2s_info->work_write_index != i2s_info->work_read_index) { + memcpy(&i2s_info->work_list[index].msg, rpmsg, sizeof(struct i2s_rpmsg_s)); - queue_work(i2s_info->rpmsg_wq, + 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->work_write_index++; + i2s_info->work_write_index %= WORK_MAX_NUM; + } else + i2s_info->msg_drop_count[substream->stream]++; } return 0;