]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
soundwire: intel: Move suspend tracking from trigger to pm suspend
authorPeter Ujfalusi <peter.ujfalusi@linux.intel.com>
Fri, 8 May 2026 10:17:55 +0000 (18:17 +0800)
committerVinod Koul <vkoul@kernel.org>
Thu, 14 May 2026 15:09:42 +0000 (20:39 +0530)
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>
drivers/soundwire/intel.c
drivers/soundwire/intel_ace2x.c

index dcd7440e78fa64e8936eecef098de3d1e475add2..af65214836b4d0b5fd96010b211b30346eccb35b 100644 (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;
        }
 
index 20422534baf19f7dc20d9153daaf96b60608ba2f..0a97253fe0c27825bb258d7a95825928da5056a9 100644 (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,
 };
 
 /*