ASoC: soc-pcm: Fix hw_params() and DAPM widget sequence
[ Upstream commit 9aff2e8df240e84a36f2607f98a0a9924a24e65d ]
Issue:
When multiple audio streams share a common BE DAI, the BE DAI
widget can be powered up before its hardware parameters are configured.
This incorrect sequence leads to intermittent pcm_write errors.
For example, the below Tegra use-case throws an error:
aplay(2 streams) -> AMX(mux) -> ADX(demux) -> arecord(2 streams),
here, 'AMX TX' and 'ADX RX' are common BE DAIs.
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 in the list if its state is either SND_SOC_DPCM_STATE_OPEN
or SND_SOC_DPCM_STATE_HW_PARAMS as well.
It ensures the widget is powered ON after BE DAI hw_params() callback.
Fixes: 0c25db3f76
("ASoC: soc-pcm: Don't reconnect an already active BE")
Signed-off-by: Sheetal <sheetal@nvidia.com>
Link: https://patch.msgid.link/20250404105953.2784819-1-sheetal@nvidia.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
a6dbcf69d4
commit
8890eeae5c
@@ -1534,10 +1534,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 is powered ON after hw_params() BE DAI callback.
|
||||
*/
|
||||
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;
|
||||
|
||||
|
Reference in New Issue
Block a user