[PATCH v2 1/2] ASoC: sdw_utils: prepare the stream again when resuming

Andrey Golovko <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.sound
Message-ID <[email protected]>
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 <[email protected]>
---
New in v2, after Mark Brown and Vijendar Mukunda pointed out that a stream
restarted with SNDRV_PCM_IOCTL_RESUME never prepares its ports again.

Measured on an ASUS ProArt PX13 HN7306EAC: without this patch a tone that
is resumed with snd_pcm_resume() alone comes back inaudible with DP1
PrepareCtrl at 0x0 and PDE23 at PS3, with it the ports are prepared again
and the tone returns at its pre-suspend level.  Numbers are in the cover
letter.
 sound/soc/sdw_utils/soc_sdw_utils.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 8a07ba2a29e5..3e091e78d8c2 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -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;
 
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.