Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: SOF: pcm/Intel: Handle IPC dependent sequencing

Merge series from Peter Ujfalusi <peter.ujfalusi@linux.intel.com>:

IPC3 and IPC4 firmwares handle and execute tasks at different
stages, like managing DMAs. In most cases these are aligned, but
we have few exceptions that needs to be handled differently.

This series introduces flags to handle the differing cases to make sure that
the correct sequencing is used regerless of the IPC version.

+31 -9
-1
sound/soc/sof/intel/hda-dai.c
··· 305 305 306 306 switch (cmd) { 307 307 case SNDRV_PCM_TRIGGER_SUSPEND: 308 - case SNDRV_PCM_TRIGGER_STOP: 309 308 ret = hda_link_dma_cleanup(substream, hext_stream, dai, codec_dai); 310 309 if (ret < 0) { 311 310 dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__);
+1
sound/soc/sof/ipc3-pcm.c
··· 382 382 .hw_free = sof_ipc3_pcm_hw_free, 383 383 .trigger = sof_ipc3_pcm_trigger, 384 384 .dai_link_fixup = sof_ipc3_pcm_dai_link_fixup, 385 + .reset_hw_params_during_stop = true, 385 386 };
+2 -1
sound/soc/sof/ipc4-pcm.c
··· 835 835 .dai_link_fixup = sof_ipc4_pcm_dai_link_fixup, 836 836 .pcm_setup = sof_ipc4_pcm_setup, 837 837 .pcm_free = sof_ipc4_pcm_free, 838 - .delay = sof_ipc4_pcm_delay 838 + .delay = sof_ipc4_pcm_delay, 839 + .ipc_first_on_start = true 839 840 };
+22 -7
sound/soc/sof/pcm.c
··· 301 301 ipc_first = true; 302 302 break; 303 303 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 304 + if (pcm_ops && pcm_ops->ipc_first_on_start) 305 + ipc_first = true; 304 306 break; 305 307 case SNDRV_PCM_TRIGGER_START: 306 308 if (spcm->stream[substream->stream].suspend_ignored) { ··· 314 312 spcm->stream[substream->stream].suspend_ignored = false; 315 313 return 0; 316 314 } 315 + 316 + if (pcm_ops && pcm_ops->ipc_first_on_start) 317 + ipc_first = true; 317 318 break; 318 319 case SNDRV_PCM_TRIGGER_SUSPEND: 319 320 if (sdev->system_suspend_target == SOF_SUSPEND_S0IX && ··· 333 328 fallthrough; 334 329 case SNDRV_PCM_TRIGGER_STOP: 335 330 ipc_first = true; 336 - reset_hw_params = true; 331 + if (pcm_ops && pcm_ops->reset_hw_params_during_stop) 332 + reset_hw_params = true; 337 333 break; 338 334 default: 339 335 dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd); 340 336 return -EINVAL; 341 337 } 342 338 343 - /* 344 - * DMA and IPC sequence is different for start and stop. Need to send 345 - * STOP IPC before stop DMA 346 - */ 347 339 if (!ipc_first) 348 340 snd_sof_pcm_platform_trigger(sdev, substream, cmd); 349 341 350 342 if (pcm_ops && pcm_ops->trigger) 351 343 ret = pcm_ops->trigger(component, substream, cmd); 352 344 353 - /* need to STOP DMA even if trigger IPC failed */ 354 - if (ipc_first) 345 + switch (cmd) { 346 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 347 + case SNDRV_PCM_TRIGGER_START: 348 + /* invoke platform trigger to start DMA only if pcm_ops is successful */ 349 + if (ipc_first && !ret) 350 + snd_sof_pcm_platform_trigger(sdev, substream, cmd); 351 + break; 352 + case SNDRV_PCM_TRIGGER_SUSPEND: 353 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 354 + case SNDRV_PCM_TRIGGER_STOP: 355 + /* invoke platform trigger to stop DMA even if pcm_ops failed */ 355 356 snd_sof_pcm_platform_trigger(sdev, substream, cmd); 357 + break; 358 + default: 359 + break; 360 + } 356 361 357 362 /* free PCM if reset_hw_params is set and the STOP IPC is successful */ 358 363 if (!ret && reset_hw_params)
+6
sound/soc/sof/sof-audio.h
··· 104 104 * @pcm_free: Function pointer for PCM free that can be used for freeing any 105 105 * additional memory in the SOF PCM stream structure 106 106 * @delay: Function pointer for pcm delay calculation 107 + * @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the 108 + * STOP pcm trigger 109 + * @ipc_first_on_start: Send IPC before invoking platform trigger during 110 + * START/PAUSE_RELEASE triggers 107 111 */ 108 112 struct sof_ipc_pcm_ops { 109 113 int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, ··· 121 117 void (*pcm_free)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm); 122 118 snd_pcm_sframes_t (*delay)(struct snd_soc_component *component, 123 119 struct snd_pcm_substream *substream); 120 + bool reset_hw_params_during_stop; 121 + bool ipc_first_on_start; 124 122 }; 125 123 126 124 /**