Skip to content

Commit 389b01a

Browse files
committed
ASoC: SOF: pcm/Intel: Pause-resume improvements for
Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>: Last minute patch for correct the pasue/resume operation with IPC4. The issues are hardto reproduce and needs extended stress testing to be hit, in which case the audio breaks due to DMA errors.
2 parents efd090c + 6d0a21d commit 389b01a

5 files changed

Lines changed: 47 additions & 18 deletions

File tree

sound/soc/sof/intel/hda-stream.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,13 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
337337
/* cmd must be for audio stream */
338338
switch (cmd) {
339339
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
340+
if (!sdev->dspless_mode_selected)
341+
break;
342+
fallthrough;
340343
case SNDRV_PCM_TRIGGER_START:
344+
if (hstream->running)
345+
break;
346+
341347
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL,
342348
1 << hstream->index,
343349
1 << hstream->index);
@@ -360,8 +366,11 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
360366
hstream->running = true;
361367

362368
break;
363-
case SNDRV_PCM_TRIGGER_SUSPEND:
364369
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
370+
if (!sdev->dspless_mode_selected)
371+
break;
372+
fallthrough;
373+
case SNDRV_PCM_TRIGGER_SUSPEND:
365374
case SNDRV_PCM_TRIGGER_STOP:
366375
snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
367376
sd_offset,

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)