Skip to content

Commit 83447a3

Browse files
TE-N-ShengjiuWangbroonie
authored andcommitted
ASoC: fsl_asrc_m2m: Add option to start ASRC before DMA device for M2M
There is a limitation on i.MX952 that dma request is not cleared at the end of conversion with dma slave mode. Which causes sample is dropped from the input fifo on the second time if dma is triggered before the client device and EDMA may copy wrong data from output fifo as the output fifo is not ready in the beginning. The solution is to trigger asrc before dma on i.MX952, and add delay to wait output data is generated then start the EDMA for output, otherwise the m2m function has noise issues. So add an option to start ASRC first for M2M before ASRC is enabled on i.MX952. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com> Reviewed-by: Frank Li <Frank.Li@nxp.com> Link: https://patch.msgid.link/20260206014805.3897764-3-shengjiu.wang@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 37bb773 commit 83447a3

4 files changed

Lines changed: 37 additions & 1 deletion

File tree

sound/soc/fsl/fsl_asrc.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,26 @@ static unsigned int fsl_asrc_get_output_fifo_size(struct fsl_asrc_pair *pair)
10781078
return val >> ASRFSTi_OUTPUT_FIFO_SHIFT;
10791079
}
10801080

1081+
static bool fsl_asrc_m2m_output_ready(struct fsl_asrc_pair *pair)
1082+
{
1083+
struct fsl_asrc *asrc = pair->asrc;
1084+
enum asrc_pair_index index = pair->index;
1085+
u32 val;
1086+
int ret;
1087+
1088+
/* Check output fifo status if it exceeds the watermark. */
1089+
ret = regmap_read_poll_timeout(asrc->regmap, REG_ASRFST(index), val,
1090+
(ASRFSTi_OUTPUT_FIFO_FILL(val) >= ASRC_M2M_OUTPUTFIFO_WML),
1091+
1, 1000);
1092+
1093+
if (ret) {
1094+
pair_warn("output is not ready\n");
1095+
return false;
1096+
}
1097+
1098+
return true;
1099+
}
1100+
10811101
static int fsl_asrc_m2m_prepare(struct fsl_asrc_pair *pair)
10821102
{
10831103
struct fsl_asrc_pair_priv *pair_priv = pair->private;
@@ -1275,6 +1295,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
12751295

12761296
asrc_priv->soc = of_device_get_match_data(&pdev->dev);
12771297
asrc->use_edma = asrc_priv->soc->use_edma;
1298+
asrc->start_before_dma = asrc_priv->soc->start_before_dma;
12781299
asrc->get_dma_channel = fsl_asrc_get_dma_channel;
12791300
asrc->request_pair = fsl_asrc_request_pair;
12801301
asrc->release_pair = fsl_asrc_release_pair;
@@ -1289,6 +1310,7 @@ static int fsl_asrc_probe(struct platform_device *pdev)
12891310
asrc->m2m_get_maxburst = fsl_asrc_m2m_get_maxburst;
12901311
asrc->m2m_pair_resume = fsl_asrc_m2m_pair_resume;
12911312
asrc->m2m_get_cap = fsl_asrc_m2m_get_cap;
1313+
asrc->m2m_output_ready = fsl_asrc_m2m_output_ready;
12921314

12931315
if (of_device_is_compatible(np, "fsl,imx35-asrc")) {
12941316
asrc_priv->clk_map[IN] = input_clk_map_imx35;

sound/soc/fsl/fsl_asrc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@
257257
#define ASRFSTi_OUTPUT_FIFO_WIDTH 7
258258
#define ASRFSTi_OUTPUT_FIFO_SHIFT 12
259259
#define ASRFSTi_OUTPUT_FIFO_MASK (((1 << ASRFSTi_OUTPUT_FIFO_WIDTH) - 1) << ASRFSTi_OUTPUT_FIFO_SHIFT)
260+
#define ASRFSTi_OUTPUT_FIFO_FILL(v) \
261+
(((v) & ASRFSTi_OUTPUT_FIFO_MASK) >> ASRFSTi_OUTPUT_FIFO_SHIFT)
260262
#define ASRFSTi_IAEi_SHIFT 11
261263
#define ASRFSTi_IAEi_MASK (1 << ASRFSTi_IAEi_SHIFT)
262264
#define ASRFSTi_IAEi (1 << ASRFSTi_IAEi_SHIFT)
@@ -432,10 +434,12 @@ struct dma_block {
432434
*
433435
* @use_edma: using edma as dma device or not
434436
* @channel_bits: width of ASRCNCR register for each pair
437+
* @start_before_dma: start asrc before dma
435438
*/
436439
struct fsl_asrc_soc_data {
437440
bool use_edma;
438441
unsigned int channel_bits;
442+
bool start_before_dma;
439443
};
440444

441445
/**

sound/soc/fsl/fsl_asrc_common.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct fsl_asrc_pair {
107107
* @asrc_rate: default sample rate for ASoC Back-Ends
108108
* @asrc_format: default sample format for ASoC Back-Ends
109109
* @use_edma: edma is used
110+
* @start_before_dma: start asrc before dma
110111
* @get_dma_channel: function pointer
111112
* @request_pair: function pointer
112113
* @release_pair: function pointer
@@ -116,6 +117,7 @@ struct fsl_asrc_pair {
116117
* @m2m_start: function pointer
117118
* @m2m_unprepare: function pointer
118119
* @m2m_stop: function pointer
120+
* @m2m_output_ready: function pointer, check output fifo ready or not
119121
* @m2m_calc_out_len: function pointer
120122
* @m2m_get_maxburst: function pointer
121123
* @m2m_pair_suspend: function pointer
@@ -143,6 +145,7 @@ struct fsl_asrc {
143145
int asrc_rate;
144146
snd_pcm_format_t asrc_format;
145147
bool use_edma;
148+
bool start_before_dma;
146149

147150
struct dma_chan *(*get_dma_channel)(struct fsl_asrc_pair *pair, bool dir);
148151
int (*request_pair)(int channels, struct fsl_asrc_pair *pair);
@@ -154,6 +157,7 @@ struct fsl_asrc {
154157
int (*m2m_start)(struct fsl_asrc_pair *pair);
155158
int (*m2m_unprepare)(struct fsl_asrc_pair *pair);
156159
int (*m2m_stop)(struct fsl_asrc_pair *pair);
160+
bool (*m2m_output_ready)(struct fsl_asrc_pair *pair);
157161

158162
int (*m2m_calc_out_len)(struct fsl_asrc_pair *pair, int input_buffer_length);
159163
int (*m2m_get_maxburst)(u8 dir, struct fsl_asrc_pair *pair);

sound/soc/fsl/fsl_asrc_m2m.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,15 +253,21 @@ static int asrc_m2m_device_run(struct fsl_asrc_pair *pair, struct snd_compr_task
253253
reinit_completion(&pair->complete[IN]);
254254
reinit_completion(&pair->complete[OUT]);
255255

256+
if (asrc->start_before_dma)
257+
asrc->m2m_start(pair);
258+
256259
/* Submit DMA request */
257260
dmaengine_submit(pair->desc[IN]);
258261
dma_async_issue_pending(pair->desc[IN]->chan);
259262
if (out_dma_len > 0) {
263+
if (asrc->start_before_dma && asrc->m2m_output_ready)
264+
asrc->m2m_output_ready(pair);
260265
dmaengine_submit(pair->desc[OUT]);
261266
dma_async_issue_pending(pair->desc[OUT]->chan);
262267
}
263268

264-
asrc->m2m_start(pair);
269+
if (!asrc->start_before_dma)
270+
asrc->m2m_start(pair);
265271

266272
if (!wait_for_completion_interruptible_timeout(&pair->complete[IN], 10 * HZ)) {
267273
dev_err(dev, "out DMA task timeout\n");

0 commit comments

Comments
 (0)