Skip to content

Commit e123036

Browse files
ranj063broonie
authored andcommitted
ASoC: soc-pcm: test if a BE can be prepared
In the BE hw_params configuration, the existing code checks if any of the existing FEs are prepared, running, paused or suspended - and skips the configuration in those cases. This allows multiple calls of hw_params which the ALSA state machine supports. This check is not handled for the prepare stage, which can lead to the same BE being prepared multiple times. This patch adds a check similar to that of the hw_params, with the main difference being that the suspended state is allowed: the ALSA state machine allows a transition from suspended to prepared with hw_params skipped. This problem was detected on Intel IPC4/SoundWire devices, where the BE dailink .prepare stage is used to configure the SoundWire stream with a bank switch. Multiple .prepare calls lead to conflicts with the .trigger operation with IPC4 configurations. This problem was not detected earlier on Intel devices, HDaudio BE dailinks detect that the link is already prepared and skip the configuration, and for IPC3 devices there is no BE trigger. Link: thesofproject/sof#7596 Signed-off-by: Ranjani Sridharan <[email protected] Signed-off-by: Bard Liao <[email protected] Signed-off-by: Pierre-Louis Bossart <[email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]
1 parent 8b27137 commit e123036

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

include/sound/soc-dpcm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe,
122122
int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
123123
struct snd_soc_pcm_runtime *be, int stream);
124124

125+
/* can this BE perform prepare */
126+
int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
127+
struct snd_soc_pcm_runtime *be, int stream);
128+
125129
/* is the current PCM operation for this FE ? */
126130
int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream);
127131

sound/soc/soc-pcm.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2405,6 +2405,9 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream)
24052405
if (!snd_soc_dpcm_be_can_update(fe, be, stream))
24062406
continue;
24072407

2408+
if (!snd_soc_dpcm_can_be_prepared(fe, be, stream))
2409+
continue;
2410+
24082411
if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
24092412
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
24102413
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) &&
@@ -3042,3 +3045,20 @@ int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe,
30423045
return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
30433046
}
30443047
EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_params);
3048+
3049+
/*
3050+
* We can only prepare a BE DAI if any of it's FE are not prepared,
3051+
* running or paused for the specified stream direction.
3052+
*/
3053+
int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe,
3054+
struct snd_soc_pcm_runtime *be, int stream)
3055+
{
3056+
const enum snd_soc_dpcm_state state[] = {
3057+
SND_SOC_DPCM_STATE_START,
3058+
SND_SOC_DPCM_STATE_PAUSED,
3059+
SND_SOC_DPCM_STATE_PREPARE,
3060+
};
3061+
3062+
return snd_soc_dpcm_check_state(fe, be, stream, state, ARRAY_SIZE(state));
3063+
}
3064+
EXPORT_SYMBOL_GPL(snd_soc_dpcm_can_be_prepared);

0 commit comments

Comments
 (0)