* [BUG] ASoC: Intel: sof_es8336: speaker amp GPIO stays off after stream stop/restart (no sound until "Speaker Switch" is toggled) @ 2026-10-04 17:12 David Márquez 2026-10-05 11:22 ` Pierre-Louis Bossart 0 siblings, 1 reply; 6+ messages in thread From: David Márquez @ 2026-10-04 17:12 UTC (permalink / raw) To: linux-sound Cc: sound-open-firmware, broonie, kai.vehmanen, pierre-louis.bossart Hello, Resending this report in plain text: my first attempt was rejected by vger because it contained an HTML part. Sorry for any duplicate. I am a user of an Adreamer Leobook 13 laptop (Intel Gemini Lake, ES8336 codec on SSP2, board name PN1308P) running Linux Mint 22 with the Ubuntu kernel 6.8.0-139-generic (based on v6.8), SOF firmware sof-glk.ri 2.2.0, topology sof-glk-es8336-ssp2.tplg, PipeWire 1.0.5, WirePlumber 0.4.17. Problem ------- The speaker randomly goes silent, typically when a browser stops and restarts playback (for example YouTube ad transitions). While it is silent the PCM is RUNNING and hw_ptr advances at 48 kHz, PipeWire reports no errors, the ALSA mixer is unchanged and nothing is logged in dmesg. Toggling "Speaker Switch" off and on restores the sound without closing the PCM. Before I worked around it, this happened 15 times in about 10 hours of use on one day. Evidence -------- I captured the full DAPM debugfs tree, the ES8336 regmap registers and /sys/kernel/debug/gpio in the broken and in the working state. Everything is identical (including "Speaker Power: On" and "Speaker: On") except the speaker enable GPIO: broken: gpio-541 (speakers-enable) out lo ACTIVE LOW working: gpio-541 (speakers-enable) out hi ACTIVE LOW Setting pmdown_time to 0 on the codec and BE links did not prevent it. Analysis -------- In sound/soc/intel/boards/sof_es8336.c, sof_8336_trigger() drives the speaker GPIO to the "off" level on PAUSE_PUSH, SUSPEND and STOP without updating priv->speaker_en, while START, PAUSE_RELEASE and RESUME do nothing. The GPIO is only restored by sof_es8316_speaker_power_event() when DAPM actually powers the "Speaker Power" supply down and up again. If the stream is stopped and started again without that full power cycle, nothing re-enables the amplifier: the GPIO stays off while DAPM still considers the speaker on. I have not determined which exact path triggers it on my machine (pause/resume, xrun recovery, or a restart within pmdown_time). Proposed change (sketch, not a formal patch) -------------------------------------------- Re-enable the amplifier on resume when the driver believes it is on: case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: + if (substream->stream == 0 && priv->speaker_en == false) + schedule_delayed_work(&priv->pcm_pop_work, + msecs_to_jiffies(70)); break; Result ------ I tested this change (with an extra dev_info message to count the occurrences) on 6.8.0-139, built out-of-tree as a replacement for the module. In about 42 hours of YouTube and Netflix use it caught and fixed the condition 6 times, with no audible dropouts and no interventions from a userspace watchdog that I kept running as a safety net. Before loading the patched module, the same watchdog had to intervene 15 times in about 10 hours on one day. From reading a recent mainline tree, sof_8336_trigger() looks unchanged there, but I have not tested mainline. I am happy to test other proposals, to provide the full debugfs dumps, or to turn this into a formal patch if the approach looks acceptable. Thank you, David Marquez Fernandez ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [BUG] ASoC: Intel: sof_es8336: speaker amp GPIO stays off after stream stop/restart (no sound until "Speaker Switch" is toggled) 2026-10-04 17:12 [BUG] ASoC: Intel: sof_es8336: speaker amp GPIO stays off after stream stop/restart (no sound until "Speaker Switch" is toggled) David Márquez @ 2026-10-05 11:22 ` Pierre-Louis Bossart 2026-10-05 12:17 ` Mark Brown 0 siblings, 1 reply; 6+ messages in thread From: Pierre-Louis Bossart @ 2026-10-05 11:22 UTC (permalink / raw) To: David Márquez, linux-sound Cc: sound-open-firmware, broonie, kai.vehmanen > Problem > ------- > The speaker randomly goes silent, typically when a browser stops and > restarts playback (for example YouTube ad transitions). While it is > silent the PCM is RUNNING and hw_ptr advances at 48 kHz, PipeWire reports > no errors, the ALSA mixer is unchanged and nothing is logged in dmesg. > Toggling "Speaker Switch" off and on restores the sound without closing > the PCM. Before I worked around it, this happened 15 times in about 10 > hours of use on one day. my money is on the asymmetric code structure which mixes DAPM and stream triggers, see below. > Evidence > -------- > I captured the full DAPM debugfs tree, the ES8336 regmap registers and > /sys/kernel/debug/gpio in the broken and in the working state. Everything > is identical (including "Speaker Power: On" and "Speaker: On") except the > speaker enable GPIO: > > broken: gpio-541 (speakers-enable) out lo ACTIVE LOW > working: gpio-541 (speakers-enable) out hi ACTIVE LOW > > Setting pmdown_time to 0 on the codec and BE links did not prevent it. > > Analysis > -------- > In sound/soc/intel/boards/sof_es8336.c, sof_8336_trigger() drives the > speaker GPIO to the "off" level on PAUSE_PUSH, SUSPEND and STOP without > updating priv->speaker_en, while START, PAUSE_RELEASE and RESUME do > nothing. The GPIO is only restored by sof_es8316_speaker_power_event() > when DAPM actually powers the "Speaker Power" supply down and up again. > If the stream is stopped and started again without that full power > cycle, nothing re-enables the amplifier: the GPIO stays off while DAPM > still considers the speaker on. I have not determined which exact path > triggers it on my machine (pause/resume, xrun recovery, or a restart > within pmdown_time). Does this happen if the time between stop and restart is greater than 3s, or only when the delta is really short? In the latter case, IIRC there's a DAPM feature where the power down happens with a delay, to avoid unnecessary power transitions. so if the new stream starts immediately, then the power-up transition will never happen. > Proposed change (sketch, not a formal patch) > -------------------------------------------- > Re-enable the amplifier on resume when the driver believes it is on: > > case SNDRV_PCM_TRIGGER_START: > case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: > case SNDRV_PCM_TRIGGER_RESUME: > + if (substream->stream == 0 && priv->speaker_en == false) > + schedule_delayed_work(&priv->pcm_pop_work, > + msecs_to_jiffies(70)); > break; alternatively you could deal with power management only in sof_es8316_speaker_power_event(), and completely remove the transitions on trigger start/stop/pause. In general it's a bad idea to add delays to the trigger, it's supposed to be real fast. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [BUG] ASoC: Intel: sof_es8336: speaker amp GPIO stays off after stream stop/restart (no sound until "Speaker Switch" is toggled) 2026-10-05 11:22 ` Pierre-Louis Bossart @ 2026-10-05 12:17 ` Mark Brown 2026-10-05 21:30 ` David Márquez 0 siblings, 1 reply; 6+ messages in thread From: Mark Brown @ 2026-10-05 12:17 UTC (permalink / raw) To: Pierre-Louis Bossart Cc: David Márquez, linux-sound, sound-open-firmware, kai.vehmanen [-- Attachment #1: Type: text/plain, Size: 454 bytes --] On Mon, Oct 05, 2026 at 01:22:10PM +0200, Pierre-Louis Bossart wrote: > Does this happen if the time between stop and restart is greater than > 3s, or only when the delta is really short? In the latter case, IIRC > there's a DAPM feature where the power down happens with a delay, to > avoid unnecessary power transitions. so if the new stream starts > immediately, then the power-up transition will never happen. Yeah, the default timer is 5 seconds. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 228 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [BUG] ASoC: Intel: sof_es8336: speaker amp GPIO stays off after stream stop/restart (no sound until "Speaker Switch" is toggled) 2026-10-05 12:17 ` Mark Brown @ 2026-10-05 21:30 ` David Márquez 2026-10-06 21:27 ` David Márquez 0 siblings, 1 reply; 6+ messages in thread From: David Márquez @ 2026-10-05 21:30 UTC (permalink / raw) To: Mark Brown Cc: Pierre-Louis Bossart, linux-sound, sound-open-firmware, kai.vehmanen Hi Pierre-Louis, Mark, Thanks for the quick feedback. > Does this happen if the time between stop and restart is greater than > 3s, or only when the delta is really short? I don't have systematic timing data yet, so I can't say for sure. What I have so far: - It still happened once with pmdown_time set to 0 on the codec and BE links (I caught the speakers-enable GPIO low after a dropout in that configuration). With pmdown_time at 0, DAPM powers down immediately on close, so a missing power-up after a quick restart should not be possible there. That makes me think the short-gap case is not the only path. - My suspicion is a STOP/PAUSE_PUSH on a PCM that stays open (for example xrun recovery, or drop+prepare on the same open stream). DAPM only powers down on hw_free/close (after pmdown_time), so no power cycle would happen regardless of the gap, while the trigger has already switched the GPIO off. I have not verified this yet. I am now collecting a trace with kprobes on sof_8336_trigger() and sof_es8316_speaker_power_event(), plus the gpio_value and DAPM widget power events, and I will correlate it with the moments where my workaround finds the GPIO low on resume. I will report the sequence and the time gaps. > alternatively you could deal with power management only in > sof_es8316_speaker_power_event(), and completely remove the transitions > on trigger start/stop/pause. Agreed, that looks cleaner than adding work to the trigger path. I will test that variant on my machine (and listen for pops at stop and pause, which I assume is why the trigger code exists) and report back. https://github.com/thesofproject/linux/issues/5967 Thanks, David Marquez El lun, 5 oct 2026 a las 13:17, Mark Brown (<broonie@kernel.org>) escribió: > > On Mon, Oct 05, 2026 at 01:22:10PM +0200, Pierre-Louis Bossart wrote: > > > Does this happen if the time between stop and restart is greater than > > 3s, or only when the delta is really short? In the latter case, IIRC > > there's a DAPM feature where the power down happens with a delay, to > > avoid unnecessary power transitions. so if the new stream starts > > immediately, then the power-up transition will never happen. > > Yeah, the default timer is 5 seconds. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [BUG] ASoC: Intel: sof_es8336: speaker amp GPIO stays off after stream stop/restart (no sound until "Speaker Switch" is toggled) 2026-10-05 21:30 ` David Márquez @ 2026-10-06 21:27 ` David Márquez 2026-10-07 5:37 ` David Márquez 0 siblings, 1 reply; 6+ messages in thread From: David Márquez @ 2026-10-06 21:27 UTC (permalink / raw) To: Mark Brown Cc: Pierre-Louis Bossart, linux-sound, sound-open-firmware, kai.vehmanen Hi Pierre-Louis, Mark, I now have data for your question. I traced sof_8336_trigger() (kprobe, with the cmd argument), sof_es8316_speaker_power_event() (event argument), gpio_value and the DAPM widget power events with timestamps over about 24 hours of normal use, and correlated them with 11 occurrences of the dropout (my out-of-tree workaround logs a message when it finds the speakers-enable GPIO low at stream start). Short answer: it does not depend on the time between stop and restart. 1) All 11 occurrences are a STOP (cmd=0) immediately followed by a START (cmd=1) 2.5 to 5.3 ms later, both issued from PipeWire's real-time data thread (pw-data-loop), on a PCM that stays open. There is no DAPM power event in between (no ev=4 and no ev=2 in any of the 11). The trigger drives the GPIO low on the STOP, "Speaker Power" is never power-cycled, and at the START the GPIO still reads back low (I read it in all 11 cases). My workaround then re-enables it about 75 ms later. The playback time before the failing STOP varies from 2 seconds to about 24 minutes. It looks like xrun/resync recovery from the data thread, but I have not confirmed the cause on the PipeWire side. 2) Normal stop/restart cycles never failed. The same trace has 46 other STOPs, all issued from the main pipewire thread when the PCM is closed after being idle. Each one is followed 14-21 ms later by sof_es8316_speaker_power_event(ev=4) (DAPM powers "Speaker Power" down), and each restart is preceded by ev=2. 45 of them were followed by a restart, from 1.5 s up to several hours later (8 restarts in under 3 s, 2 between 3 and 5 s), and none failed. So in my case the delayed power-down timer is not what matters: DAPM turns the speaker supply off right after the STOP, and I only see the 5 s delayed DAPM run later, from a kworker. 3) About your suggestion: today the trigger switches the amp off at STOP, about 15 ms before DAPM starts powering the codec down, while the GPIO write from the power event goes through the 70 ms delayed work (I measure it 71-79 ms after ev=4, when the widgets are already off). So simply dropping the trigger handling would leave the amp enabled for about 70 ms on an already powered-down path, which I would expect to pop. I will test a variant that (1) removes the GPIO handling from the trigger and (2) switches the amp off synchronously in the PRE_PMD event, before the widgets power down, keeping the delayed work only for the power-up. I will report whether the dropouts disappear and whether I hear any pops. Raw trace excerpts are available if useful. Thanks, David Marquez El lun, 5 oct 2026 a las 22:30, David Márquez (<davidmarquezfernandez@gmail.com>) escribió: > > Hi Pierre-Louis, Mark, > > Thanks for the quick feedback. > > > Does this happen if the time between stop and restart is greater than > > 3s, or only when the delta is really short? > > I don't have systematic timing data yet, so I can't say for sure. What I > have so far: > > - It still happened once with pmdown_time set to 0 on the codec and BE > links (I caught the speakers-enable GPIO low after a dropout in that > configuration). With pmdown_time at 0, DAPM powers down immediately on > close, so a missing power-up after a quick restart should not be > possible there. That makes me think the short-gap case is not the only > path. > - My suspicion is a STOP/PAUSE_PUSH on a PCM that stays open (for example > xrun recovery, or drop+prepare on the same open stream). DAPM only > powers down on hw_free/close (after pmdown_time), so no power cycle > would happen regardless of the gap, while the trigger has already > switched the GPIO off. I have not verified this yet. > > I am now collecting a trace with kprobes on sof_8336_trigger() and > sof_es8316_speaker_power_event(), plus the gpio_value and DAPM widget > power events, and I will correlate it with the moments where my > workaround finds the GPIO low on resume. I will report the sequence and > the time gaps. > > > alternatively you could deal with power management only in > > sof_es8316_speaker_power_event(), and completely remove the transitions > > on trigger start/stop/pause. > > Agreed, that looks cleaner than adding work to the trigger path. I will > test that variant on my machine (and listen for pops at stop and pause, > which I assume is why the trigger code exists) and report back. > > https://github.com/thesofproject/linux/issues/5967 > > Thanks, > David Marquez > > > El lun, 5 oct 2026 a las 13:17, Mark Brown (<broonie@kernel.org>) escribió: > > > > On Mon, Oct 05, 2026 at 01:22:10PM +0200, Pierre-Louis Bossart wrote: > > > > > Does this happen if the time between stop and restart is greater than > > > 3s, or only when the delta is really short? In the latter case, IIRC > > > there's a DAPM feature where the power down happens with a delay, to > > > avoid unnecessary power transitions. so if the new stream starts > > > immediately, then the power-up transition will never happen. > > > > Yeah, the default timer is 5 seconds. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [BUG] ASoC: Intel: sof_es8336: speaker amp GPIO stays off after stream stop/restart (no sound until "Speaker Switch" is toggled) 2026-10-06 21:27 ` David Márquez @ 2026-10-07 5:37 ` David Márquez 0 siblings, 0 replies; 6+ messages in thread From: David Márquez @ 2026-10-07 5:37 UTC (permalink / raw) To: Mark Brown Cc: Pierre-Louis Bossart, linux-sound, sound-open-firmware, kai.vehmanen Hi Pierre-Louis, Mark, A follow-up on the variant I mentioned: I tested it on my machine. Variant tested: sof_8336_trigger() no longer touches the speaker GPIO, and sof_es8316_speaker_power_event() switches the amp off synchronously in the PRE_PMD case (cancel the pending work, set the GPIO to the "off" level, return), keeping the 70 ms delayed work only for the power-up. Result: I hear a pop from the speakers each time the stream is closed after being idle, about 5 s after the last sound (when PipeWire suspends the sink and DAPM powers the codec down). I do not hear it with the original trigger-based switch-off, nor with my START-side workaround. My guess, which I have not verified, is that "Speaker Power" is a supply and DAPM powers supplies down after the output widgets, so the amp is still enabled while the output stage goes down. The trigger STOP path switches it off about 15 ms before DAPM starts, which looks like the reason it exists. So the early switch-off in the trigger seems necessary, and what is missing is the matching switch-on when the stream restarts without a DAPM power cycle. I stopped the test of this variant early because of the pops, so I cannot say whether it also removes the dropouts (by construction it should, since the GPIO would only follow DAPM). The smallest change I have validated is the START-side one from my first mail: on START/PAUSE_RELEASE/RESUME, if speaker_en says the amp should be on and the GPIO is low, re-enable it. It does not add a delay to the trigger itself: it only schedules the existing pcm_pop_work (the same 70 ms used for power-up). With it, 11 occurrences in about 24 hours were corrected with no audible dropout and no pop, and the normal close and reopen paths are untouched. Would you prefer that approach, or do you see a cleaner way to keep the early switch-off for pop suppression while keeping the GPIO state consistent with DAPM? I can turn it into a proper patch and test it on my hardware. Thanks, David Marquez El mar, 6 oct 2026 a las 22:27, David Márquez (<davidmarquezfernandez@gmail.com>) escribió: > > Hi Pierre-Louis, Mark, > > I now have data for your question. I traced sof_8336_trigger() (kprobe, > with the cmd argument), sof_es8316_speaker_power_event() (event > argument), gpio_value and the DAPM widget power events with timestamps > over about 24 hours of normal use, and correlated them with 11 > occurrences of the dropout (my out-of-tree workaround logs a message > when it finds the speakers-enable GPIO low at stream start). > > Short answer: it does not depend on the time between stop and restart. > > 1) All 11 occurrences are a STOP (cmd=0) immediately followed by a START > (cmd=1) 2.5 to 5.3 ms later, both issued from PipeWire's real-time data > thread (pw-data-loop), on a PCM that stays open. There is no DAPM power > event in between (no ev=4 and no ev=2 in any of the 11). The trigger > drives the GPIO low on the STOP, "Speaker Power" is never power-cycled, > and at the START the GPIO still reads back low (I read it in all 11 > cases). My workaround then re-enables it about 75 ms later. The > playback time before the failing STOP varies from 2 seconds to about 24 > minutes. It looks like xrun/resync recovery from the data thread, but I > have not confirmed the cause on the PipeWire side. > > 2) Normal stop/restart cycles never failed. The same trace has 46 other > STOPs, all issued from the main pipewire thread when the PCM is closed > after being idle. Each one is followed 14-21 ms later by > sof_es8316_speaker_power_event(ev=4) (DAPM powers "Speaker Power" down), > and each restart is preceded by ev=2. 45 of them were followed by a > restart, from 1.5 s up to several hours later (8 restarts in under 3 s, > 2 between 3 and 5 s), and none failed. So in my case the delayed > power-down timer is not what matters: DAPM turns the speaker supply > off right after the STOP, and I only see the 5 s delayed DAPM run later, > from a kworker. > > 3) About your suggestion: today the trigger switches the amp off at > STOP, about 15 ms before DAPM starts powering the codec down, while the > GPIO write from the power event goes through the 70 ms delayed work (I > measure it 71-79 ms after ev=4, when the widgets are already off). So > simply dropping the trigger handling would leave the amp enabled for > about 70 ms on an already powered-down path, which I would expect to > pop. I will test a variant that (1) removes the GPIO handling from the > trigger and (2) switches the amp off synchronously in the PRE_PMD > event, before the widgets power down, keeping the delayed work only for > the power-up. I will report whether the dropouts disappear and whether > I hear any pops. > > Raw trace excerpts are available if useful. > > Thanks, > David Marquez > > > El lun, 5 oct 2026 a las 22:30, David Márquez > (<davidmarquezfernandez@gmail.com>) escribió: > > > > Hi Pierre-Louis, Mark, > > > > Thanks for the quick feedback. > > > > > Does this happen if the time between stop and restart is greater than > > > 3s, or only when the delta is really short? > > > > I don't have systematic timing data yet, so I can't say for sure. What I > > have so far: > > > > - It still happened once with pmdown_time set to 0 on the codec and BE > > links (I caught the speakers-enable GPIO low after a dropout in that > > configuration). With pmdown_time at 0, DAPM powers down immediately on > > close, so a missing power-up after a quick restart should not be > > possible there. That makes me think the short-gap case is not the only > > path. > > - My suspicion is a STOP/PAUSE_PUSH on a PCM that stays open (for example > > xrun recovery, or drop+prepare on the same open stream). DAPM only > > powers down on hw_free/close (after pmdown_time), so no power cycle > > would happen regardless of the gap, while the trigger has already > > switched the GPIO off. I have not verified this yet. > > > > I am now collecting a trace with kprobes on sof_8336_trigger() and > > sof_es8316_speaker_power_event(), plus the gpio_value and DAPM widget > > power events, and I will correlate it with the moments where my > > workaround finds the GPIO low on resume. I will report the sequence and > > the time gaps. > > > > > alternatively you could deal with power management only in > > > sof_es8316_speaker_power_event(), and completely remove the transitions > > > on trigger start/stop/pause. > > > > Agreed, that looks cleaner than adding work to the trigger path. I will > > test that variant on my machine (and listen for pops at stop and pause, > > which I assume is why the trigger code exists) and report back. > > > > https://github.com/thesofproject/linux/issues/5967 > > > > Thanks, > > David Marquez > > > > > > El lun, 5 oct 2026 a las 13:17, Mark Brown (<broonie@kernel.org>) escribió: > > > > > > On Mon, Oct 05, 2026 at 01:22:10PM +0200, Pierre-Louis Bossart wrote: > > > > > > > Does this happen if the time between stop and restart is greater than > > > > 3s, or only when the delta is really short? In the latter case, IIRC > > > > there's a DAPM feature where the power down happens with a delay, to > > > > avoid unnecessary power transitions. so if the new stream starts > > > > immediately, then the power-up transition will never happen. > > > > > > Yeah, the default timer is 5 seconds. ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-07 5:37 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-04 17:12 [BUG] ASoC: Intel: sof_es8336: speaker amp GPIO stays off after stream stop/restart (no sound until "Speaker Switch" is toggled) David Márquez 2026-10-05 11:22 ` Pierre-Louis Bossart 2026-10-05 12:17 ` Mark Brown 2026-10-05 21:30 ` David Márquez 2026-10-06 21:27 ` David Márquez 2026-10-07 5:37 ` David Márquez
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.