From d3be95d58c5e1c6f3fd88508294358efc0f18725 Mon Sep 17 00:00:00 2001 From: Sheetal Date: Sat, 1 Feb 2025 02:38:51 +0000 Subject: [PATCH] NVIDIA: SAUCE: ASoC: soc-pcm: Fix hw_params() and DAPM widget sequence Issue: Tegra audio usecase throws pcm_write error intermittently incase common BE DAI is used, for example below usecase throws the error: aplay(2 streams) -> AMX(mux) -> ADX(demux) -> arecord(2 streams), here, 'AMX TX' and 'ADX RX' are common BE DAIs. The problem occurs when streams sharing a common BE DAI are started simultaneously. This intermittently results in the common BE DAI widget being enabled before its hw_params are configured. For above usecase when failure happens below sequence is observed: aplay(1) FE open() - BE DAI callbacks added to the list - BE DAI state = SND_SOC_DPCM_STATE_OPEN aplay(2) FE open() - BE DAI callbacks are not added to the list as the state is already SND_SOC_DPCM_STATE_OPEN during aplay(1) FE open(). aplay(2) FE hw_params() - BE DAI hw_params() callback ignored aplay(2) FE prepare() - Widget is powered ON without BE DAI hw_params() call aplay(1) FE hw_params() - BE DAI hw_params() is now called Fix: - Add BE DAIs if its state is either SND_SOC_DPCM_STATE_OPEN or SND_SOC_DPCM_STATE_HW_PARAMS as well. - Additionally, while calling hw_params() for BE DAI, the SND_SOC_DPCM_STATE_HW_PARAMS state check is not correct, as the state will change once the BE DAI hw_params() callback is completed. It avoids multiple times same BE DAI hw_params() call. The BE DAI callbacks are only called once due to the state check in the PCM BE DAI calls and will not break the existing flow, but it ensures the sequence will not break for the shared BE DAIs. http://nvbugs/4596841 Signed-off-by: Sheetal Reviewed-by: Sameer Pujar Reviewed-by: Mohan kumar Reviewed-by: Kartik Rajput Tested-by: Kartik Rajput Signed-off-by: Vishwaroop A Acked-by: Noah Wager Acked-by: Jacob Martin Signed-off-by: Noah Wager --- sound/soc/soc-pcm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 14f12cd48a75..3f08f25d1297 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1550,10 +1550,13 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, /* * Filter for systems with 'component_chaining' enabled. * This helps to avoid unnecessary re-configuration of an - * already active BE on such systems. + * already active BE on such systems and ensures the BE DAI + * widget power ON after all BE DAI callbacks. */ if (fe->card->component_chaining && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_NEW) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_CLOSE)) continue; @@ -2075,7 +2078,6 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) continue; if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE)) continue;