mirror of https://gitee.com/openkylin/linux.git
ASoC: soc-pcm: disconnect BEs if the FE is not ready
FE is connected to two BEs, BE1 is active, BE2 is deactive. When closing BE1, FE/BE1 is in HW_FREE state, then BE2 is startup by mixer runtime update. For FE is in HW_FREE state, dpcm_run_update_startup() will skip BE2's startup because FE's state is HW_FREE, BE2 stays in FE's be_clients list. During FE's closed, the dpcm_fe_dai_close() will close all related BEs, BE2 will be closed. This will lead to BE2's dpcm[stream].users mismatch. We need disconnet all pending BEs in the corner case. Signed-off-by: zhucancan <zhucancan@vivo.com> Link: https://lore.kernel.org/r/AAoArwDfDnoefyxzy2wyiaqm.1.1608885766936.Hmail.zhucancan@vivo.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
aac568269b
commit
2c1382840c
|
@ -2440,8 +2440,11 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
|
|||
|
||||
/* Only start the BE if the FE is ready */
|
||||
if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE ||
|
||||
fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
|
||||
return -EINVAL;
|
||||
fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) {
|
||||
dev_err(fe->dev, "ASoC: FE %s is not ready %d\n",
|
||||
fe->dai_link->name, fe->dpcm[stream].state);
|
||||
goto disconnect;
|
||||
}
|
||||
|
||||
/* startup must always be called for new BEs */
|
||||
ret = dpcm_be_dai_startup(fe, stream);
|
||||
|
@ -2502,12 +2505,18 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream)
|
|||
close:
|
||||
dpcm_be_dai_shutdown(fe, stream);
|
||||
disconnect:
|
||||
/* disconnect any closed BEs */
|
||||
/* disconnect any pending BEs */
|
||||
spin_lock_irqsave(&fe->card->dpcm_lock, flags);
|
||||
for_each_dpcm_be(fe, stream, dpcm) {
|
||||
struct snd_soc_pcm_runtime *be = dpcm->be;
|
||||
if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE)
|
||||
dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
|
||||
|
||||
/* is this op for this BE ? */
|
||||
if (!snd_soc_dpcm_be_can_update(fe, be, stream))
|
||||
continue;
|
||||
|
||||
if (be->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE ||
|
||||
be->dpcm[stream].state == SND_SOC_DPCM_STATE_NEW)
|
||||
dpcm->state = SND_SOC_DPCM_LINK_STATE_FREE;
|
||||
}
|
||||
spin_unlock_irqrestore(&fe->card->dpcm_lock, flags);
|
||||
|
||||
|
|
Loading…
Reference in New Issue