From: Arun Raghavan <a...@asymptotic.io> In a setup with an external clock provider, when running the receiver (arecord) and triggering an xrun with xrun_injection, we see a channel swap/offset. This happens sometimes when running only the receiver, but occurs reliably if a transmitter (aplay) is also concurrently running.
The theory is that SAI seems to lose track of frame sync during the trigger stop -> trigger start cycle that occurs during an xrun. Doing just a FIFO reset in this case does not suffice, and only a software reset seems to get it back on track. Signed-off-by: Arun Raghavan <a...@asymptotic.io> Reported-by: Pieterjan Camerlynck <p.camerly...@televic.com> --- sound/soc/fsl/fsl_sai.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index af1a168d35e3..3a5ebf32903f 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -841,6 +841,18 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + /* + * Force a software reset if we are not the clock provider, as we + * might have lost frame sync during xrun recovery. + */ + if (sai->is_consumer_mode) { + regmap_update_bits(sai->regmap, + FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR, + FSL_SAI_CSR_SR); + regmap_update_bits(sai->regmap, + FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR, + 0); + } regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_FRDE, FSL_SAI_CSR_FRDE); -- 2.49.0