Commit 9bffb1fb7c22c96d51d4ba06e2e023dd568a5872
Committed by
Mark Brown
1 parent
29594404d7
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
ASoC: Prevent pop_wait overwrite
pop_wait is used to determine if a deferred playback close needs to be cancelled when the a PCM is open or if after the power-down delay expires it needs to run. pop_wait is associated with the CODEC DAI, so the CODEC DAI must be unique. This holds true for most CODECs, except for the dummy CODEC and its DAI. In DAI links with non-unique dummy CODECs (e.g. front-ends), pop_wait can be overwritten by another DAI link using also a dummy CODEC. Failure to cancel a deferred close can cause mute due to the DAPM STOP event sent in the deferred work. One scenario where pop_wait is overwritten and causing mute is below (where hw:0,0 and hw:0,1 are two front-ends with default pmdown_time = 5 secs): aplay /dev/urandom -D hw:0,0 -c 2 -r 48000 -f S16_LE -d 1 sleep 1 aplay /dev/urandom -D hw:0,1 -c 2 -r 48000 -f S16_LE -d 3 & aplay /dev/urandom -D hw:0,0 -c 2 -r 48000 -f S16_LE Since CODECs may not be unique, pop_wait is moved to the PCM runtime structure. Creating separate dummy CODECs for each DAI link can also solve the problem, but at this point it's only pop_wait variable in the CODEC DAI that has negative effects by not being unique. Signed-off-by: Misael Lopez Cruz <misael.lopez@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Showing 4 changed files with 8 additions and 8 deletions Side-by-side Diff
include/sound/soc-dai.h
include/sound/soc.h
sound/soc/soc-compress.c
sound/soc/soc-pcm.c
... | ... | @@ -333,11 +333,11 @@ |
333 | 333 | pr_debug("pop wq checking: %s status: %s waiting: %s\n", |
334 | 334 | codec_dai->driver->playback.stream_name, |
335 | 335 | codec_dai->playback_active ? "active" : "inactive", |
336 | - codec_dai->pop_wait ? "yes" : "no"); | |
336 | + rtd->pop_wait ? "yes" : "no"); | |
337 | 337 | |
338 | 338 | /* are we waiting on this codec DAI stream */ |
339 | - if (codec_dai->pop_wait == 1) { | |
340 | - codec_dai->pop_wait = 0; | |
339 | + if (rtd->pop_wait == 1) { | |
340 | + rtd->pop_wait = 0; | |
341 | 341 | snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, |
342 | 342 | SND_SOC_DAPM_STREAM_STOP); |
343 | 343 | } |
... | ... | @@ -407,7 +407,7 @@ |
407 | 407 | SND_SOC_DAPM_STREAM_STOP); |
408 | 408 | } else { |
409 | 409 | /* start delayed pop wq here for playback streams */ |
410 | - codec_dai->pop_wait = 1; | |
410 | + rtd->pop_wait = 1; | |
411 | 411 | schedule_delayed_work(&rtd->delayed_work, |
412 | 412 | msecs_to_jiffies(rtd->pmdown_time)); |
413 | 413 | } |
... | ... | @@ -478,8 +478,8 @@ |
478 | 478 | |
479 | 479 | /* cancel any delayed stream shutdown that is pending */ |
480 | 480 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
481 | - codec_dai->pop_wait) { | |
482 | - codec_dai->pop_wait = 0; | |
481 | + rtd->pop_wait) { | |
482 | + rtd->pop_wait = 0; | |
483 | 483 | cancel_delayed_work(&rtd->delayed_work); |
484 | 484 | } |
485 | 485 |