diff options
author | Shengjiu Wang <shengjiu.wang@nxp.com> | 2018-08-07 15:02:34 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | 70d66c9ab195ac6af947a1aff67ade889349dbd5 (patch) | |
tree | 769acae6847b594861c24c6e1ef332b79f2ea81f /sound/soc | |
parent | 7389590e8ac7457f2a6cebd3ab997ac30ca17375 (diff) |
MLK-19151: ASoC: fsl_asrc: fix dma timeout issue for imx8qxp
In the imx8qxp, the DMA is EDMA, which require the buffer size
should be divided by burst size with no remainder, otherwise
the remainder is not transferred by EDMA, so the input buffer
is not consumed by ASRC, then there will be dma output timeout
issue. This behavior is different with SDMA.
This patch is to change the input burst size to be 1 to avoid
the issue, and refine the last_period_size for output buffer.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
(cherry picked from commit 8e6b6939e7708c6ecd8f8a439a6f19b20cabfd07)
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/fsl/fsl_asrc.c | 4 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_asrc.h | 4 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_asrc_m2m.c | 18 |
3 files changed, 24 insertions, 2 deletions
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 3ca0d370bf2b..969c5c20605a 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1142,24 +1142,28 @@ static int fsl_asrc_probe(struct platform_device *pdev) sizeof(asrc_priv->name) - 1); asrc_priv->clk_map[IN] = input_clk_map_imx35; asrc_priv->clk_map[OUT] = output_clk_map_imx35; + asrc_priv->dma_type = DMA_SDMA; } else if (of_device_is_compatible(np, "fsl,imx53-asrc")) { asrc_priv->channel_bits = 4; strncpy(asrc_priv->name, "mxc_asrc", sizeof(asrc_priv->name) - 1); asrc_priv->clk_map[IN] = input_clk_map_imx53; asrc_priv->clk_map[OUT] = output_clk_map_imx53; + asrc_priv->dma_type = DMA_SDMA; } else if (of_device_is_compatible(np, "fsl,imx8qm-asrc0")) { asrc_priv->channel_bits = 4; strncpy(asrc_priv->name, "mxc_asrc", sizeof(asrc_priv->name) - 1); asrc_priv->clk_map[IN] = input_clk_map_imx8_0; asrc_priv->clk_map[OUT] = output_clk_map_imx8_0; + asrc_priv->dma_type = DMA_EDMA; } else if (of_device_is_compatible(np, "fsl,imx8qm-asrc1")) { asrc_priv->channel_bits = 4; strncpy(asrc_priv->name, "mxc_asrc1", sizeof(asrc_priv->name) - 1); asrc_priv->clk_map[IN] = input_clk_map_imx8_1; asrc_priv->clk_map[OUT] = output_clk_map_imx8_1; + asrc_priv->dma_type = DMA_EDMA; } ret = fsl_asrc_init(asrc_priv); diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h index 7e7f0e8a1c88..1d592f7b73d2 100644 --- a/sound/soc/fsl/fsl_asrc.h +++ b/sound/soc/fsl/fsl_asrc.h @@ -370,11 +370,15 @@ struct fsl_asrc { int asrc_rate; int asrc_width; + int dma_type; /* 0 is sdma, 1 is edma */ u32 regcache_cfg; char name[20]; }; +#define DMA_SDMA 0 +#define DMA_EDMA 1 + extern struct snd_soc_platform_driver fsl_asrc_platform; struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir); int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair); diff --git a/sound/soc/fsl/fsl_asrc_m2m.c b/sound/soc/fsl/fsl_asrc_m2m.c index 9f0314970cbb..2684518d26ee 100644 --- a/sound/soc/fsl/fsl_asrc_m2m.c +++ b/sound/soc/fsl/fsl_asrc_m2m.c @@ -174,8 +174,11 @@ static int fsl_asrc_dmaconfig(struct fsl_asrc_pair *pair, struct dma_chan *chan, slave_config.direction = DMA_MEM_TO_DEV; slave_config.dst_addr = dma_addr; slave_config.dst_addr_width = buswidth; - slave_config.dst_maxburst = - m2m->watermark[IN] * pair->channels; + if (asrc_priv->dma_type == DMA_SDMA) + slave_config.dst_maxburst = + m2m->watermark[IN] * pair->channels; + else + slave_config.dst_maxburst = 1; } else { slave_config.direction = DMA_DEV_TO_MEM; slave_config.src_addr = dma_addr; @@ -283,6 +286,9 @@ static int fsl_asrc_prepare_io_buffer(struct fsl_asrc_pair *pair, *dma_len -= last_period_size * word_size * pair->channels; *dma_len = *dma_len / (word_size * pair->channels) * (word_size * pair->channels); + if (asrc_priv->dma_type == DMA_EDMA) + *dma_len = *dma_len / (word_size * pair->channels * m2m->watermark[OUT]) + * (word_size * pair->channels * m2m->watermark[OUT]); } *sg_nodes = *dma_len / ASRC_MAX_BUFFER_SIZE + 1; @@ -625,11 +631,13 @@ static long fsl_asrc_calc_last_period_size(struct fsl_asrc_pair *pair, struct asrc_convert_buffer *pbuf) { struct fsl_asrc_m2m *m2m = pair->private; + struct fsl_asrc *asrc_priv = pair->asrc_priv; unsigned int out_length; unsigned int in_width, out_width; unsigned int channels = pair->channels; unsigned int in_samples, out_samples; unsigned int last_period_size; + unsigned int remain; switch (m2m->word_width[IN]) { case ASRC_WIDTH_24_BIT: @@ -672,6 +680,12 @@ static long fsl_asrc_calc_last_period_size(struct fsl_asrc_pair *pair, m2m->last_period_size = last_period_size + 1 + ASRC_OUTPUT_LAST_SAMPLE; + if (asrc_priv->dma_type == DMA_EDMA) { + remain = pbuf->output_buffer_length % (out_width * channels * m2m->watermark[OUT]); + if (remain) + m2m->last_period_size += remain / (out_width * channels); + } + return 0; } |