summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2018-07-16 18:29:23 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commite1bbf60895c9ca124b371e0dcd174e02c7ef7724 (patch)
tree5f36147e8df3e39105cd8646bb3abd45703035ae /sound
parent2f37b9f4806a92cdc0f9c103f6b0ce79e4317ca4 (diff)
MLK-18866: ASoC: imx-pcm-dma-v2: refine the callback function
The commit 7f3ff14b7eb1 ("dmaengine: imx-sdma: add 1ms delay to ensure SDMA channel is stopped") add 1ms delay may cause the audio underrun/overrun. But ESAI has an hardware issue in older version which work abnormal after underrun/overrun, especially there will be channel swap. To workaround this issue, the ESAI need to be reset. in imx-pcm-dma.c we include a new callback function for DMA interrupt which will check the state of cpu dai and reset it in necessary. So inport same function to imx-pcm-dma-v2. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> Reviewed-by: Viorel Suman <viorel.suman@nxp.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/fsl/imx-pcm-dma-v2.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/sound/soc/fsl/imx-pcm-dma-v2.c b/sound/soc/fsl/imx-pcm-dma-v2.c
index 814483790a97..4831141b9afd 100644
--- a/sound/soc/fsl/imx-pcm-dma-v2.c
+++ b/sound/soc/fsl/imx-pcm-dma-v2.c
@@ -45,6 +45,25 @@ static bool imx_dma_filter_fn(struct dma_chan *chan, void *param)
return true;
}
+static void imx_pcm_dma_v2_complete(void *arg)
+{
+ struct snd_pcm_substream *substream = arg;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct dmaengine_pcm_runtime_data *prtd =
+ substream->runtime->private_data;
+ struct snd_dmaengine_dai_dma_data *dma_data;
+
+ prtd->pos += snd_pcm_lib_period_bytes(substream);
+ if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
+ prtd->pos = 0;
+
+ snd_pcm_period_elapsed(substream);
+
+ dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ if (dma_data->check_xrun && dma_data->check_xrun(substream))
+ dma_data->device_reset(substream, 1);
+}
+
/* this may get called several times by oss emulation */
static int imx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
@@ -54,8 +73,12 @@ static int imx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_dmaengine_dai_dma_data *dma_data;
struct dma_slave_config config;
struct dma_chan *chan;
+ struct dmaengine_pcm_runtime_data *prtd =
+ substream->runtime->private_data;
int err = 0;
+ prtd->callback = imx_pcm_dma_v2_complete;
+
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
/* return if this is a bufferless transfer e.g.