]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ASoC: soc-pcm: Fix hw_params() and DAPM widget sequence
authorSheetal <sheetal@nvidia.com>
Fri, 4 Apr 2025 10:59:53 +0000 (10:59 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 9 May 2025 07:43:56 +0000 (09:43 +0200)
[ 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: 0c25db3f7621 ("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>
sound/soc/soc-pcm.c

index 60248a6820aacca07970e01a80b2b9f41b0a5a29..30e93f9aad762487410e72e8bd70efbe78c36e46 100644 (file)
@@ -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;