From 5c6fa89abec03cd5a0a15121945a0b8461d7d1a5 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 11 Jun 2024 09:53:50 +0300 Subject: [PATCH] ASoC: SOF: ipc4: Use the suspending stream flag to handle paused streams correctly During system suspend while we have paused streams we need to make sure that the pipelines are properly reset. Since the stream is in paused state, the pipelines are also in paused state, which is correct for the RESET transition. Reset the started/paused counters to indicate that the pipeline will need to be initialized after resume and PAUSE_RELEASE. Signed-off-by: Peter Ujfalusi --- sound/soc/sof/ipc4-pcm.c | 27 +++++++++++++++++++++++---- sound/soc/sof/ipc4-topology.c | 2 ++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 4df2be3d39eba0..c17054d507970f 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -131,6 +131,7 @@ static void sof_ipc4_add_pipeline_by_priority(struct ipc4_pipeline_set_state_dat static void sof_ipc4_add_pipeline_to_trigger_list(struct snd_sof_dev *sdev, int state, + bool suspending, struct snd_sof_pipeline *spipe, struct ipc4_pipeline_set_state_data *trigger_list, s8 *pipe_priority) @@ -152,6 +153,18 @@ sof_ipc4_add_pipeline_to_trigger_list(struct snd_sof_dev *sdev, int state, false); break; case SOF_IPC4_PIPE_RESET: + if (suspending) { + if (pipeline->state != SOF_IPC4_PIPE_PAUSED) + dev_warn(sdev->dev, + "%s: %s is not in PAUSED state" + "(state: %d, started/paused count: %d/%d)\n", + __func__, pipe_widget->widget->name, + pipeline->state, spipe->started_count, spipe->paused_count); + + spipe->started_count = 0; + spipe->paused_count = 0; + } + /* RESET if the pipeline is neither running nor paused */ if (!spipe->started_count && !spipe->paused_count) sof_ipc4_add_pipeline_by_priority(trigger_list, pipe_widget, pipe_priority, @@ -436,18 +449,24 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component, * indeterministic. But the sink->source trigger order sink->source would still be * guaranteed for each fork independently. */ - if (state == SOF_IPC4_PIPE_RUNNING || state == SOF_IPC4_PIPE_RESET) + if (state == SOF_IPC4_PIPE_RUNNING || state == SOF_IPC4_PIPE_RESET) { + bool suspending = spcm->stream[substream->stream].suspending; + for (i = pipeline_list->count - 1; i >= 0; i--) { spipe = pipeline_list->pipelines[i]; - sof_ipc4_add_pipeline_to_trigger_list(sdev, state, spipe, trigger_list, + sof_ipc4_add_pipeline_to_trigger_list(sdev, state, + suspending, spipe, + trigger_list, pipe_priority); } - else + } else { for (i = 0; i < pipeline_list->count; i++) { spipe = pipeline_list->pipelines[i]; - sof_ipc4_add_pipeline_to_trigger_list(sdev, state, spipe, trigger_list, + sof_ipc4_add_pipeline_to_trigger_list(sdev, state, false, + spipe, trigger_list, pipe_priority); } + } /* return if all pipelines are in the requested state already */ if (!trigger_list->count) { diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index d123edfa3bae59..ac8dcb891490b4 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -3278,7 +3278,9 @@ static int sof_ipc4_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif continue; if (spcm->stream[dir].list) { + spcm->stream[dir].suspending = true; ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true); + spcm->stream[dir].suspending = false; if (ret < 0) return ret; }