Skip to content

Commit 6d0a21d

Browse files
ranj063broonie
authored andcommitted
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>
1 parent 3e94369 commit 6d0a21d

4 files changed

Lines changed: 37 additions & 17 deletions

File tree

sound/soc/sof/ipc4-pcm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,5 +836,6 @@ const struct sof_ipc_pcm_ops ipc4_pcm_ops = {
836836
.pcm_setup = sof_ipc4_pcm_setup,
837837
.pcm_free = sof_ipc4_pcm_free,
838838
.delay = sof_ipc4_pcm_delay,
839-
.ipc_first_on_start = true
839+
.ipc_first_on_start = true,
840+
.platform_stop_during_hw_free = true,
840841
};

sound/soc/sof/pcm.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,22 @@ static int sof_pcm_hw_free(struct snd_soc_component *component,
211211
dev_dbg(component->dev, "pcm: free stream %d dir %d\n",
212212
spcm->pcm.pcm_id, substream->stream);
213213

214-
/* free PCM in the DSP */
215-
if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) {
216-
ret = pcm_ops->hw_free(component, substream);
217-
if (ret < 0)
218-
err = ret;
214+
if (spcm->prepared[substream->stream]) {
215+
/* stop DMA first if needed */
216+
if (pcm_ops && pcm_ops->platform_stop_during_hw_free)
217+
snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP);
218+
219+
/* free PCM in the DSP */
220+
if (pcm_ops && pcm_ops->hw_free) {
221+
ret = pcm_ops->hw_free(component, substream);
222+
if (ret < 0)
223+
err = ret;
224+
}
219225

220226
spcm->prepared[substream->stream] = false;
221227
}
222228

223-
/* stop DMA */
229+
/* reset DMA */
224230
ret = snd_sof_pcm_platform_hw_free(sdev, substream);
225231
if (ret < 0) {
226232
dev_err(component->dev, "error: platform hw free failed\n");
@@ -362,8 +368,9 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
362368
case SNDRV_PCM_TRIGGER_SUSPEND:
363369
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
364370
case SNDRV_PCM_TRIGGER_STOP:
365-
/* invoke platform trigger to stop DMA even if pcm_ops failed */
366-
snd_sof_pcm_platform_trigger(sdev, substream, cmd);
371+
/* invoke platform trigger to stop DMA even if pcm_ops isn't set or if it failed */
372+
if (!pcm_ops || (pcm_ops && !pcm_ops->platform_stop_during_hw_free))
373+
snd_sof_pcm_platform_trigger(sdev, substream, cmd);
367374
break;
368375
default:
369376
break;

sound/soc/sof/sof-audio.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -805,16 +805,22 @@ int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *subs
805805
const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
806806
int ret;
807807

808-
/* Send PCM_FREE IPC to reset pipeline */
809-
if (pcm_ops && pcm_ops->hw_free && spcm->prepared[substream->stream]) {
810-
ret = pcm_ops->hw_free(sdev->component, substream);
811-
if (ret < 0)
812-
return ret;
813-
}
808+
if (spcm->prepared[substream->stream]) {
809+
/* stop DMA first if needed */
810+
if (pcm_ops && pcm_ops->platform_stop_during_hw_free)
811+
snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP);
812+
813+
/* Send PCM_FREE IPC to reset pipeline */
814+
if (pcm_ops && pcm_ops->hw_free) {
815+
ret = pcm_ops->hw_free(sdev->component, substream);
816+
if (ret < 0)
817+
return ret;
818+
}
814819

815-
spcm->prepared[substream->stream] = false;
820+
spcm->prepared[substream->stream] = false;
821+
}
816822

817-
/* stop the DMA */
823+
/* reset the DMA */
818824
ret = snd_sof_pcm_platform_hw_free(sdev, substream);
819825
if (ret < 0)
820826
return ret;

sound/soc/sof/sof-audio.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ struct snd_sof_dai_config_data {
108108
* STOP pcm trigger
109109
* @ipc_first_on_start: Send IPC before invoking platform trigger during
110110
* START/PAUSE_RELEASE triggers
111+
* @platform_stop_during_hw_free: Invoke the platform trigger during hw_free. This is needed for
112+
* IPC4 where a pipeline is only paused during stop/pause/suspend
113+
* triggers. The FW keeps the host DMA running in this case and
114+
* therefore the host must do the same and should stop the DMA during
115+
* hw_free.
111116
*/
112117
struct sof_ipc_pcm_ops {
113118
int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream,
@@ -123,6 +128,7 @@ struct sof_ipc_pcm_ops {
123128
struct snd_pcm_substream *substream);
124129
bool reset_hw_params_during_stop;
125130
bool ipc_first_on_start;
131+
bool platform_stop_during_hw_free;
126132
};
127133

128134
/**

0 commit comments

Comments
 (0)