ASoC: fsl_sai: Force a software reset when starting in consumer mode
authorArun Raghavan <arun@asymptotic.io>
Thu, 26 Jun 2025 13:08:25 +0000 (09:08 -0400)
committerMark Brown <broonie@kernel.org>
Sun, 29 Jun 2025 21:10:26 +0000 (22:10 +0100)
On an imx8mm platform 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.

It seems that the SAI loses 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.

This looks like the same h/w bug that is already handled for the
producer case, so we now do the reset unconditionally on config disable.

Signed-off-by: Arun Raghavan <arun@asymptotic.io>
Reported-by: Pieterjan Camerlynck <p.camerlynck@televic.com>
Fixes: 3e3f8bd56955 ("ASoC: fsl_sai: fix no frame clk in master mode")
Cc: stable@vger.kernel.org
Reviewed-by: Fabio Estevam <festevam@gmail.com>
Link: https://patch.msgid.link/20250626130858.163825-1-arun@arunraghavan.net
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/fsl/fsl_sai.c

index af1a168d35e379e24ce46715ba53b4a4dac65988..50af6b725670d99697bb15ea60f236e299e0e495 100644 (file)
@@ -803,13 +803,15 @@ static void fsl_sai_config_disable(struct fsl_sai *sai, int dir)
         * anymore. Add software reset to fix this issue.
         * This is a hardware bug, and will be fix in the
         * next sai version.
+        *
+        * In consumer mode, this can happen even after a
+        * single open/close, especially if both tx and rx
+        * are running concurrently.
         */
-       if (!sai->is_consumer_mode[tx]) {
-               /* Software Reset */
-               regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR);
-               /* Clear SR bit to finish the reset */
-               regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), 0);
-       }
+       /* Software Reset */
+       regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), FSL_SAI_CSR_SR);
+       /* Clear SR bit to finish the reset */
+       regmap_write(sai->regmap, FSL_SAI_xCSR(tx, ofs), 0);
 }
 
 static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,