soundwire: intel: Move suspend tracking from trigger to pm suspend

Mark all open DAI runtimes as suspended in the component .suspend
callback instead of relying on SNDRV_PCM_TRIGGER_SUSPEND, which is
not delivered during PAUSE or xrun states.

If during system suspend a dai is open it means that it is in either in
SUSPENDED, PAUSED or STOPPED  (due to xrun) state and they will need to be
re-initialized during resume (which is done in .prepare callback).

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://patch.msgid.link/20260508101755.1247039-1-yung-chuan.liao@linux.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Peter Ujfalusi 2026-05-08 18:17:55 +08:00 committed by Vinod Koul
parent 4e90368e86
commit acf676b9de
2 changed files with 33 additions and 37 deletions

View File

@ -906,19 +906,6 @@ static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct sn
}
switch (cmd) {
case SNDRV_PCM_TRIGGER_SUSPEND:
/*
* The .prepare callback is used to deal with xruns and resume operations.
* In the case of xruns, the DMAs and SHIM registers cannot be touched,
* but for resume operations the DMAs and SHIM registers need to be initialized.
* the .trigger callback is used to track the suspend case only.
*/
dai_runtime->suspended = true;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
dai_runtime->paused = true;
break;
@ -955,10 +942,12 @@ static int intel_component_dais_suspend(struct snd_soc_component *component)
struct snd_soc_dai *dai;
/*
* In the corner case where a SUSPEND happens during a PAUSE, the ALSA core
* does not throw the TRIGGER_SUSPEND. This leaves the DAIs in an unbalanced state.
* Since the component suspend is called last, we can trap this corner case
* and force the DAIs to release their resources.
* Mark all open streams as suspended.
* Open streams at this point can be in SUSPENDED, PAUSED or STOPPED
* state and during prepare the DMAs and SHIM registers need to be
* initialized for them.
* The STOPPED state is a special corner case which can happen if audio
* experiences xrun at suspend time.
*/
for_each_component_dais(component, dai) {
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
@ -966,13 +955,7 @@ static int intel_component_dais_suspend(struct snd_soc_component *component)
dai_runtime = cdns->dai_runtime_array[dai->id];
if (!dai_runtime)
continue;
if (dai_runtime->suspended)
continue;
if (dai_runtime->paused)
if (dai_runtime)
dai_runtime->suspended = true;
}

View File

@ -894,19 +894,6 @@ static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct sn
}
switch (cmd) {
case SNDRV_PCM_TRIGGER_SUSPEND:
/*
* The .prepare callback is used to deal with xruns and resume operations.
* In the case of xruns, the DMAs and SHIM registers cannot be touched,
* but for resume operations the DMAs and SHIM registers need to be initialized.
* the .trigger callback is used to track the suspend case only.
*/
dai_runtime->suspended = true;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
dai_runtime->paused = true;
break;
@ -930,8 +917,34 @@ static const struct snd_soc_dai_ops intel_pcm_dai_ops = {
.get_stream = intel_get_sdw_stream,
};
static int intel_component_dais_suspend(struct snd_soc_component *component)
{
struct snd_soc_dai *dai;
/*
* Mark all open streams as suspended.
* Open streams at this point can be in SUSPENDED, PAUSED or STOPPED
* state and during prepare the DMAs and SHIM registers need to be
* initialized for them.
* The STOPPED state is a special corner case which can happen if audio
* experiences xrun at suspend time.
*/
for_each_component_dais(component, dai) {
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_cdns_dai_runtime *dai_runtime;
dai_runtime = cdns->dai_runtime_array[dai->id];
if (dai_runtime)
dai_runtime->suspended = true;
}
return 0;
}
static const struct snd_soc_component_driver dai_component = {
.name = "soundwire",
.suspend = intel_component_dais_suspend,
};
/*