From 4cec95198b5c7eac22aedfb11732fd076ffe4359 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 26 Jan 2024 16:34:20 +0200 Subject: [PATCH] ASoC: SOF: ipc4: change trigger order for chain DMA The host DMA (controlled by BE ops) must be stopped before sending PAUSE/STOP IPC (sent from FE ops) to chain DMA. Unless this is done, the DMA stop flow is not following programming sequence and DMA engine may get stuck in busy state. Link: https://github.com/thesofproject/sof/issues/8792 Signed-off-by: Kai Vehmanen --- sound/soc/sof/ipc4-pcm.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 0f332c8cdbe6af..d09fc8518f417b 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -614,9 +614,28 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; struct sof_ipc4_pipeline *pipeline = pipe_widget->private; - /* Chain DMA does not use copiers, so no fixup needed */ - if (pipeline->use_chain_dma) + if (pipeline->use_chain_dma) { + struct snd_soc_dpcm *dpcm; + int dir2; + + /* + * BE (host DMA stream) must be stopped first + * as the chain DMA IPCs sent by FE trigger, will + * require host DMA to be stopped. + */ + + rtd->dai_link->trigger[dir] = SND_SOC_DPCM_TRIGGER_PRE; + + for_each_dpcm_fe(rtd, dir2, dpcm) { + struct snd_soc_pcm_runtime *fe = dpcm->fe; + + fe->dai_link->trigger[dir2] = + SND_SOC_DPCM_TRIGGER_PRE; + } + + /* Chain DMA does not use copiers, so no fixup needed */ return 0; + } if (dir == SNDRV_PCM_STREAM_PLAYBACK) { if (sof_ipc4_copier_is_single_format(sdev,