summaryrefslogtreecommitdiff
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2018-08-07 15:02:34 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:48:33 +0800
commit9d607a7189bad77c8357a0646a353e5ee74d9d4c (patch)
treee24bdc403091198c954692a8e3dc495ac866bde9 /sound/soc/fsl
parent6e7c69f03b0d932d247dc88746b3c6d794f3d640 (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>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_asrc.c4
-rw-r--r--sound/soc/fsl/fsl_asrc.h4
-rw-r--r--sound/soc/fsl/fsl_asrc_m2m.c18
3 files changed, 24 insertions, 2 deletions
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 6cf16f46b339..ede17dddae6a 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1070,24 +1070,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 d65481c92107..45562aae89f0 100644
--- a/sound/soc/fsl/fsl_asrc.h
+++ b/sound/soc/fsl/fsl_asrc.h
@@ -367,11 +367,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
+
#define DRV_NAME "fsl-asrc-dai"
extern struct snd_soc_component_driver fsl_asrc_component;
struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir);
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;
}