@@ -292,6 +292,35 @@ static struct hdac_ext_link *sdw_get_hlink(struct snd_sof_dev *sdev,
292292 return hdac_bus_eml_sdw_get_hlink (bus );
293293}
294294
295+ /*
296+ * Count how many CPU DAIs in this BE link share the same pipeline (spipe)
297+ * as the target. Used to determine the per-pipeline trigger threshold for
298+ * aggregate DAIs where some may share a pipeline and others may not.
299+ */
300+ static int hda_ipc4_count_spipe_dais (struct snd_pcm_substream * substream ,
301+ struct snd_sof_pipeline * target_spipe )
302+ {
303+ struct snd_soc_pcm_runtime * rtd = snd_soc_substream_to_rtd (substream );
304+ struct snd_soc_dai * dai ;
305+ int count = 0 ;
306+ int i ;
307+
308+ for_each_rtd_cpu_dais (rtd , i , dai ) {
309+ struct snd_soc_dapm_widget * w ;
310+ struct snd_sof_widget * sw ;
311+
312+ w = snd_soc_dai_get_widget (dai , substream -> stream );
313+ if (!w )
314+ continue ;
315+
316+ sw = w -> dobj .private ;
317+ if (sw -> spipe == target_spipe )
318+ count ++ ;
319+ }
320+
321+ return count ;
322+ }
323+
295324static int hda_ipc4_pre_trigger (struct snd_sof_dev * sdev , struct snd_soc_dai * cpu_dai ,
296325 struct snd_pcm_substream * substream , int cmd )
297326{
@@ -319,13 +348,22 @@ static int hda_ipc4_pre_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cp
319348 case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
320349 case SNDRV_PCM_TRIGGER_SUSPEND :
321350 case SNDRV_PCM_TRIGGER_STOP :
351+ /*
352+ * For aggregate DAIs with shared pipelines, the state check
353+ * deduplicates: the first DAI sends the IPC, subsequent DAIs
354+ * sharing the same pipeline see it already paused and skip.
355+ * For aggregate DAIs with different pipelines, each DAI pauses
356+ * its own pipeline independently.
357+ */
358+ if (pipeline -> state == SOF_IPC4_PIPE_PAUSED )
359+ break ;
360+
322361 ret = sof_ipc4_set_pipeline_state (sdev , pipe_widget -> instance_id ,
323362 SOF_IPC4_PIPE_PAUSED );
324363 if (ret < 0 )
325364 return ret ;
326365
327366 pipeline -> state = SOF_IPC4_PIPE_PAUSED ;
328-
329367 break ;
330368 default :
331369 dev_err (sdev -> dev , "unknown trigger command %d\n" , cmd );
@@ -372,11 +410,13 @@ static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
372410static int hda_ipc4_post_trigger (struct snd_sof_dev * sdev , struct snd_soc_dai * cpu_dai ,
373411 struct snd_pcm_substream * substream , int cmd )
374412{
413+ struct snd_soc_pcm_runtime * rtd = snd_soc_substream_to_rtd (substream );
375414 struct sof_ipc4_fw_data * ipc4_data = sdev -> private ;
376415 struct snd_sof_widget * pipe_widget ;
377416 struct sof_ipc4_pipeline * pipeline ;
378417 struct snd_sof_widget * swidget ;
379418 struct snd_soc_dapm_widget * w ;
419+ int num_cpus = rtd -> dai_link -> num_cpus ;
380420 int ret = 0 ;
381421
382422 w = snd_soc_dai_get_widget (cpu_dai , substream -> stream );
@@ -391,6 +431,26 @@ static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
391431
392432 switch (cmd ) {
393433 case SNDRV_PCM_TRIGGER_START :
434+ /*
435+ * For aggregated DAIs (num_cpus > 1), defer pipeline RUNNING
436+ * IPC until all CPU DAIs sharing this pipeline have started
437+ * their link DMAs. The per-spipe threshold handles all cases:
438+ * - shared pipeline: waits for all DAIs on the same spipe
439+ * - different pipelines: each fires independently (threshold=1)
440+ * - mixed: each group fires when its members complete
441+ */
442+ if (num_cpus > 1 ) {
443+ int spipe_dais = hda_ipc4_count_spipe_dais (substream ,
444+ swidget -> spipe );
445+
446+ swidget -> spipe -> trigger_count ++ ;
447+ swidget -> spipe -> started_count ++ ;
448+ if (swidget -> spipe -> trigger_count < spipe_dais )
449+ break ;
450+
451+ swidget -> spipe -> trigger_count = 0 ;
452+ }
453+
394454 if (pipeline -> state != SOF_IPC4_PIPE_PAUSED ) {
395455 ret = sof_ipc4_set_pipeline_state (sdev , pipe_widget -> instance_id ,
396456 SOF_IPC4_PIPE_PAUSED );
@@ -406,9 +466,21 @@ static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
406466 return ret ;
407467
408468 pipeline -> state = SOF_IPC4_PIPE_RUNNING ;
409- swidget -> spipe -> started_count ++ ;
469+ if (num_cpus <= 1 )
470+ swidget -> spipe -> started_count ++ ;
410471 break ;
411472 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
473+ if (num_cpus > 1 ) {
474+ int spipe_dais = hda_ipc4_count_spipe_dais (substream ,
475+ swidget -> spipe );
476+
477+ swidget -> spipe -> trigger_count ++ ;
478+ if (swidget -> spipe -> trigger_count < spipe_dais )
479+ break ;
480+
481+ swidget -> spipe -> trigger_count = 0 ;
482+ }
483+
412484 ret = sof_ipc4_set_pipeline_state (sdev , pipe_widget -> instance_id ,
413485 SOF_IPC4_PIPE_RUNNING );
414486 if (ret < 0 )
@@ -420,9 +492,11 @@ static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
420492 case SNDRV_PCM_TRIGGER_STOP :
421493 /*
422494 * STOP/SUSPEND trigger is invoked only once when all users of this pipeline have
423- * been stopped. So, clear the started_count so that the pipeline can be reset
495+ * been stopped. So, clear the started_count so that the pipeline can be reset.
496+ * Also reset trigger_count for aggregate DAIs in case of partial trigger rollback.
424497 */
425498 swidget -> spipe -> started_count = 0 ;
499+ swidget -> spipe -> trigger_count = 0 ;
426500 break ;
427501 case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
428502 break ;
0 commit comments