]> git.hungrycats.org Git - linux/commitdiff
ASoC: sdw_utils: prepare the stream again when resuming
authorAndrey Golovko <andrey.golovko@gmail.com>
Thu, 13 Aug 2026 16:40:00 +0000 (19:40 +0300)
committerMark Brown <broonie@kernel.org>
Wed, 19 Aug 2026 14:22:18 +0000 (15:22 +0100)
A peripheral loses its Data Port configuration when the controller is
power-gated during system suspend, so the ports have to be prepared
again before the stream can be enabled.  That happens on its own when
userspace calls snd_pcm_prepare() after SNDRV_PCM_STATE_SUSPENDED, but
an application is also allowed to restart the stream with
SNDRV_PCM_IOCTL_RESUME on a card that advertises SNDRV_PCM_INFO_RESUME,
as the AMD ACP platforms do.  That path only reaches the trigger
callback, sdw_enable_stream() writes the channels of ports that were
never prepared, and playback silently produces nothing: the PCM keeps
running, no error is reported anywhere, and the speakers stay quiet
until the stream is torn down and set up again.

Prepare the stream on SNDRV_PCM_TRIGGER_RESUME, before enabling it.
The SoundWire core expects exactly this: sdw_prepare_stream() accepts a
disabled stream and then reapplies the bus parameters without
recomputing them, which it documents as the resume case.

Signed-off-by: Andrey Golovko <andrey.golovko@gmail.com>
Link: https://patch.msgid.link/20260813194000.10412-2-andrey.golovko@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sdw_utils/soc_sdw_utils.c

index 8a07ba2a29e5a77b20bb16feae8c1cd5a6510ed7..3e091e78d8c253720d2b8059b8779e4f11fc4c14 100644 (file)
@@ -1510,9 +1510,24 @@ int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd)
        }
 
        switch (cmd) {
+       case SNDRV_PCM_TRIGGER_RESUME:
+               /*
+                * The peripherals lose their port configuration when the
+                * controller is power-gated during system suspend, and an
+                * application that restarts the stream with
+                * SNDRV_PCM_IOCTL_RESUME - which platforms advertising
+                * SNDRV_PCM_INFO_RESUME allow - never goes through
+                * .prepare() again.  Prepare the stream here so that the
+                * ports are reprogrammed before they are enabled;
+                * sdw_prepare_stream() reapplies the parameters without
+                * recomputing them when the stream is disabled.
+                */
+               ret = sdw_prepare_stream(sdw_stream);
+               if (ret)
+                       break;
+               fallthrough;
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-       case SNDRV_PCM_TRIGGER_RESUME:
                ret = sdw_enable_stream(sdw_stream);
                break;