diff options
author | Ranjani Sridharan <ranjani.sridharan@linux.intel.com> | 2023-04-20 14:41:37 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2023-04-20 14:51:59 +0300 |
commit | 6d0a21dd95c349bbe3663a4870ff7e70ddc6c9b6 (patch) | |
tree | 3c94805ed7b4a43d9ac2a4f636dec96eb602479e /sound/soc/sof/pcm.c | |
parent | 3e94369729ea8a825cf8bf304bfb1749de62ebf4 (diff) | |
download | linux-6d0a21dd95c349bbe3663a4870ff7e70ddc6c9b6.tar.xz |
ASoC: SOF: pcm: Add an option to skip platform trigger during stop
In the case of IPC4, a pipeline is only paused during STOP/PAUSE/SUSPEND
triggers and the FW keeps the host DMA running when a pipeline is
paused. The start/stop tests iterate through STOP/START triggers without
involving a hw_free. This means that the pipeline state will only toggle
between PAUSED (during the STOP trigger) and RUNNING (during the START
trigger). So this test should be treated in the same way as a
PAUSE_PUSH/PAUSE_RELEASE test and the DMA should be kept running when
toggling the pipeline states between PAUSED and RUNNING.
Since there is no way to tell if a STOP trigger will be followed by hw_free
or not, this patch proposes to always skip DMA stop during the STOP trigger
and handle it later during hw_free. Introduce a new flag in struct
sof_ipc_pcm_ops, delayed_platform_trigger, that will be used to ensure that
the host DMA will not be stopped during the STOP/PAUSE/RELEASE triggers
and set it for IPC4. The platform_trigger call to stop the DMA will be
invoked during PCM hw_free instead when the pipeline is reset.
Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Péter Ujfalusi <peter.ujfalusi@linux.intel.com>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://lore.kernel.org/r/20230420114137.27613-3-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sof/pcm.c')
-rw-r--r-- | sound/soc/sof/pcm.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 127b68caf9e1..567db32173a8 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -211,16 +211,22 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, dev_dbg(component->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); - /* free PCM in the DSP */ - if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) { - ret = pcm_ops->hw_free(component, substream); - if (ret < 0) - err = ret; + if (spcm->prepared[substream->stream]) { + /* stop DMA first if needed */ + if (pcm_ops && pcm_ops->platform_stop_during_hw_free) + snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP); + + /* free PCM in the DSP */ + if (pcm_ops && pcm_ops->hw_free) { + ret = pcm_ops->hw_free(component, substream); + if (ret < 0) + err = ret; + } spcm->prepared[substream->stream] = false; } - /* stop DMA */ + /* reset DMA */ ret = snd_sof_pcm_platform_hw_free(sdev, substream); if (ret < 0) { dev_err(component->dev, "error: platform hw free failed\n"); @@ -362,8 +368,9 @@ static int sof_pcm_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_STOP: - /* invoke platform trigger to stop DMA even if pcm_ops failed */ - snd_sof_pcm_platform_trigger(sdev, substream, cmd); + /* invoke platform trigger to stop DMA even if pcm_ops isn't set or if it failed */ + if (!pcm_ops || (pcm_ops && !pcm_ops->platform_stop_during_hw_free)) + snd_sof_pcm_platform_trigger(sdev, substream, cmd); break; default: break; |