Skip to content

ASoC: soundwire: retain required resources for WoV - #6021

Draft
bardliao wants to merge 10 commits into
thesofproject:topic/sof-devfrom
bardliao:retain-wov-widgets
Draft

bardliao wants to merge 10 commits into
thesofproject:topic/sof-devfrom
bardliao:retain-wov-widgets

Conversation

@bardliao

@bardliao bardliao commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator

Wake-on-voice requires the DSP audio path to remain available while the
system is suspended. Although SOF can keep a D0i3-compatible PCM running,
SoundWire stream and Intel controller suspend handling may still disable
the stream or its bus, while DAPM may power down widgets on the path.
This series propagates the ignore-suspend requirement from SOF to the
SoundWire stream and connected DAPM widgets and keep the required
components alive during system suspend.
An alternative to #5968

Some streams, such as those used for wake-on-voice, must remain active
during system suspend. Add an ignore_suspend flag to
sdw_stream_runtime and export sdw_bus_ignore_suspend() so bus drivers can
check whether any stream on the bus requires it to remain active.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Honor the SoundWire bus ignore-suspend state in the Intel drivers.
Preserve the master across system suspend when a stream requires the bus
to remain active.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Do not disable a SoundWire stream on suspend when it is marked to remain
active. If the stream is already enabled on resume, no further action is
needed.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical retention-handling defects allow duplicate IPC3 STARTs, fail to retain legacy SoundWire streams, and leave wake-on-voice disabled after aborted S3 preparation.

3 open issues
What changed in this PR

This PR extends SOF’s wake-on-voice retention across SoundWire streams, Intel controllers, and DAPM paths so required audio resources remain active during system suspend.

Changes:

  • Propagates per-stream retention decisions from SOF to SoundWire and connected DAPM widgets.
  • Updates Intel suspend/resume handling to preserve retained buses and clean up revoked retention.
  • Revises PCM recovery and IPC4 pipeline reference accounting.
File Description
sound/​soc/​sof/​sof-priv.h Tracks suspend progress and retention revocation.
sound/​soc/​sof/​sof-audio.h Adds PCM retention state and lifecycle declarations.
sound/​soc/​sof/​pm.c Integrates retention preparation and completion.
sound/​soc/​sof/​pcm.c Selects retained streams and updates PCM lifecycle handling.
sound/​soc/​sof/​ipc4-topology.c Resets pipeline counters when freeing pipelines.
sound/​soc/​sof/​ipc4-pcm.c Tracks per-stream pipeline references and cleanup.
sound/​soc/​sof/​intel/​hda.c Adds SoundWire retention-query callbacks.
sound/​soc/​sof/​intel/​hda-dsp.c Clears retention state during system D3 transitions.
sound/​soc/​sof/​intel/​hda-dai.c Propagates retention and updates backend recovery.
sound/​soc/​sof/​intel/​hda-dai-ops.c Skips firmware IPC during cleanup after firmware failure.
sound/​soc/​soc-dapm.c Marks and preserves connected retained audio paths.
sound/​soc/​sdw_utils/​soc_sdw_utils.c Handles retained SoundWire streams across PCM operations.
include/​sound/​soc-dapm.h Adds widget retention flags.
include/​sound/​soc-component.h Adds a component retention-query callback.
include/​linux/​soundwire/​sdw.h Exposes stream retention state and a bus query.
include/​linux/​soundwire/​sdw_intel.h Adds the Intel retention-query interface.
drivers/​soundwire/​stream.c Detects enabled retained streams on a bus.
drivers/​soundwire/​intel.h Records whether a bus remained active.
drivers/​soundwire/​intel.c Exempts retained streams from DAI suspend marking.
drivers/​soundwire/​intel_auxdevice.c Preserves retained buses and revokes stale retention.
drivers/​soundwire/​intel_ace2x.c Exempts retained ACE2x streams from suspend marking.

Review effort: Balanced

Comment thread sound/soc/sof/intel/hda.c Outdated
struct sdw_intel_ops sdw_callback = {
.params_stream = sdw_params_stream,
.free_stream = sdw_params_free,
.ignore_suspend = sdw_ignore_suspend,
Comment thread sound/soc/sof/pcm.c Resolved
Comment thread sound/soc/sof/pm.c Outdated
Comment on lines +439 to +440
if (sdev->system_suspend_retention_revoked && !sdev->system_suspend_started)
dev_err(sdev->dev, "system suspend aborted after revoking WoV retention; close and reopen PCM\n");

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* Revoke retention from an earlier S0ix before any controller or codec
* suspends. An already-suspended PCM will not issue another trigger.
*/
if (pm_suspend_target_state != PM_SUSPEND_TO_IDLE) {
Comment on lines +653 to +654
if (stream->state == SDW_STREAM_ENABLED) {
ret = sdw_disable_stream(stream);
Comment thread sound/soc/sdw_utils/soc_sdw_rt_dmic.c Outdated
!strcmp(component->name_prefix, "rt713") ||
!strcmp(component->name_prefix, "rt713-dmic") ||
!strcmp(component->name_prefix, "rt766") ||
!strcmp(component->name_prefix, "rt1320")) {
Comment thread sound/soc/sdw_utils/soc_sdw_rt_dmic.c Resolved
Comment thread sound/soc/sof/pcm.c Resolved
Comment thread sound/soc/sof/pcm.c Outdated

list_for_each_entry(spcm, &sdev->pcm_list, list)
for_each_pcm_streams(dir)
spcm->stream[dir].suspend_ignored = false;
Comment thread sound/soc/sof/intel/hda-dai.c Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread sound/soc/sdw_utils/soc_sdw_rt_dmic.c Resolved
Comment thread sound/soc/sof/pcm.c Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Comment thread drivers/soundwire/intel.c Resolved
Comment thread sound/soc/sof/pcm.c Resolved
Comment thread sound/soc/sof/pcm.c Resolved
bardliao and others added 7 commits November 6, 2026 18:01
Keep a SoundWire stream active during system suspend when it is used by
a WoV stream. WoV streams can be identified by: They are capture streams
and. They have the d0i3_compatible flag set and They don't use Deep
Buffer.

The decision is made in the BE SUSPEND trigger. The BE DAI trigger runs
before the SoundWire link trigger, so the ignore_suspend flag of the
SoundWire stream is updated before the link trigger decides whether to
disable the stream. When a BE is shared by WoV and regular FEs, the BE
only receives SUSPEND once the last FE is suspended, and all connected
FEs are checked at that point regardless of their open or suspend order.

A WoV PCM retained in a previous S0ix suspend stays in the SUSPENDED
state and will not receive another SUSPEND trigger. If the system then
enters a deeper suspend state, stop its FE and BE pipelines and release
its DAPM retention at PM prepare time.

Assisted-by: LLM

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Multiple FE streams can share a SoundWire BE, so prepare may arrive
after another FE has enabled the shared stream. Skip
sdw_prepare_stream() when the stream is already enabled.

When hw_free is called for an enabled stream, disable it before
depreparing. Propagate disable errors rather than attempting to
deprepare an enabled stream.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
A SoundWire capture BE shared by regular and WoV FEs can remain running
across S0ix. Its HDA suspend trigger sets suspend_ignored and skips the
pipeline and link DMA teardown. Recovery must consume that flag without
starting the retained hardware again.

The first BE trigger after system resume is not necessarily RESUME. A
regular capture FE can recover through prepare followed by START. Also,
when another FE has already prepared the shared BE, DPCM translates the
first RESUME into START rather than resuming an unprepared stream.

Only handling RESUME in the retained-stream shortcut lets START fall
through to the normal HDA trigger callbacks. This unnecessarily pauses
and restarts the retained IPC4 pipeline, starts the link DMA again and
increments the BE pipeline's started_count even though its existing
running reference was preserved during suspend. It also leaves
suspend_ignored set after recovery.

Consume suspend_ignored on either START or RESUME and return without
retriggering the retained hardware. DPCM still accounts for the recovering
FE in be_start, while the HDA pipeline keeps its existing running reference
until the last BE user stops. Ordinary START triggers are unchanged when
suspend_ignored is false.

With IPC4 capture links the FE is triggered before the BE. If a regular
FE has prepared the shared BE before a retained WoV FE resumes, the WoV
FE trigger consumes its suspend_ignored flag before DPCM sends START to
the BE, and its DPCM state is only updated after the trigger completes.
Treat a WoV FE which is being triggered while its PCM is still SUSPENDED
as resuming so the retained BE is not restarted.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
A WoV PCM can remain SUSPENDED after waking from S0ix until userspace
recovers it. If the next sleep transition enters S3 or S4 first, ALSA
does not send another SUSPEND trigger, leaving the SoundWire stream
ENABLED with ignore_suspend set even though the hardware loses its
configuration during the deeper transition.

The controller suspend-target check alone does not invalidate the
stream state. An ENABLED stream makes prepare and RESUME skip port
configuration, so the stream must be disabled before powering down.

Disable retained SoundWire streams and clear ignore_suspend in Intel
link PM prepare when the target is not suspend-to-idle, before the
controller and codecs suspend. Use each stream state, retention flag
and sleep target to decide whether its Intel DAI needs reinitialization.
Keep the component suspend callbacks limited to marking DAI state and
preserve the S0ix retention path.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
A WoV PCM can remain SUSPENDED after waking from S0ix until userspace
recovers it. If the next sleep transition enters S3 or S4 first, ALSA
does not send another SUSPEND trigger. The FE and HDA BE can therefore
keep suspend_ignored although the deeper transition resets the DSP and
link DMA hardware.

A retained FE pipeline still owes the STOP it skipped at SUSPEND. Its
started_count stays non-zero, which makes the IPC4 RESET and later
RUNNING transitions skip the pipeline. Clearing the flag before teardown
would lose this information.

Pay the skipped STOP in sof_pcm_stream_free() and clear the flag there.
Include retained streams in sof_pcm_free_all_streams(), which only runs
when the DSP is not staying in D0. If the STOP fails, still free the
stream so the flag cannot outlive the firmware state.

A retained stream that is dropped while SUSPENDED never receives a STOP
trigger. PREPARE cannot tell this from a normal recovery because ALSA
moves a SUSPENDED PCM to SETUP before calling it, and the pipeline is
still running in both cases. Keep the stream in PREPARE and let START
skip it. Clear the flag on STOP, PAUSE and close.

Clear HDA stream retention flags on the system D3 path so subsequent BE
triggers cannot mistake reset hardware for a still-running stream.
Preserve the S0ix WoV retention path.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
A BE may be shared by multiple FEs. Some FEs need to remain active
during system suspend while others do not.

Keep a BE DAI endpoint active if it is connected to an active FE DAI
with ignore_suspend set. This lets drivers mark only the FE DAI instead
of retaining the shared BE for every connected FE.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Keep the DAPM capture path of a WoV stream powered during S0ix.

Find the microphone endpoint from the FE capture path instead of
assuming a card widget named DMIC, since cards may name it differently.
Mark the FE DAI widget and the endpoint when the WoV stream is suspended
for S0ix, so the lookup runs while the path is connected. If no endpoint
is found, the stream is suspended normally.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>

Copilot AI left a comment

Copy link
Copy Markdown

Comment on lines +862 to +863
hda_stream = hstream_to_sof_hda_stream(stream_to_hdac_ext_stream(s));
hda_stream->suspend_ignored = false;
Comment thread sound/soc/sof/pcm.c
Comment on lines +496 to +499
if (!sof_pcm_set_dai_ignore_suspend(rtd, substream->stream)) {
spcm->stream[substream->stream].suspend_ignored = true;
return 0;
}
Comment thread sound/soc/sof/pcm.c
Comment on lines +91 to +92
if (!ret)
widget->ignore_suspend = 1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants