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>
This commit is contained in:
@ -1144,24 +1144,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);
|
||||
|
||||
@ -371,11 +371,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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user