Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e45c136 authored by Arun Raghavan's avatar Arun Raghavan Committed by Greg Kroah-Hartman
Browse files

ASoC: fsl_sai: Force a software reset when starting in consumer mode



commit dc78f7e59169d3f0e6c3c95d23dc8e55e95741e2 upstream.

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: default avatarArun Raghavan <arun@asymptotic.io>
Reported-by: default avatarPieterjan Camerlynck <p.camerlynck@televic.com>
Fixes: 3e3f8bd5 ("ASoC: fsl_sai: fix no frame clk in master mode")
Cc: stable@vger.kernel.org
Reviewed-by: default avatarFabio Estevam <festevam@gmail.com>
Link: https://patch.msgid.link/20250626130858.163825-1-arun@arunraghavan.net


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3451944a
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -565,14 +565,16 @@ 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_slave_mode) {
	/* 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,
		struct snd_soc_dai *cpu_dai)