@@ -292,6 +292,38 @@ 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 )
318+ continue ;
319+
320+ if (sw -> spipe == target_spipe )
321+ count ++ ;
322+ }
323+
324+ return count ;
325+ }
326+
295327static int hda_ipc4_pre_trigger (struct snd_sof_dev * sdev , struct snd_soc_dai * cpu_dai ,
296328 struct snd_pcm_substream * substream , int cmd )
297329{
@@ -319,13 +351,22 @@ static int hda_ipc4_pre_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cp
319351 case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
320352 case SNDRV_PCM_TRIGGER_SUSPEND :
321353 case SNDRV_PCM_TRIGGER_STOP :
354+ /*
355+ * For aggregate DAIs with shared pipelines, the state check
356+ * deduplicates: the first DAI sends the IPC, subsequent DAIs
357+ * sharing the same pipeline see it already paused and skip.
358+ * For aggregate DAIs with different pipelines, each DAI pauses
359+ * its own pipeline independently.
360+ */
361+ if (pipeline -> state == SOF_IPC4_PIPE_PAUSED )
362+ break ;
363+
322364 ret = sof_ipc4_set_pipeline_state (sdev , pipe_widget -> instance_id ,
323365 SOF_IPC4_PIPE_PAUSED );
324366 if (ret < 0 )
325367 return ret ;
326368
327369 pipeline -> state = SOF_IPC4_PIPE_PAUSED ;
328-
329370 break ;
330371 default :
331372 dev_err (sdev -> dev , "unknown trigger command %d\n" , cmd );
@@ -372,11 +413,13 @@ static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
372413static int hda_ipc4_post_trigger (struct snd_sof_dev * sdev , struct snd_soc_dai * cpu_dai ,
373414 struct snd_pcm_substream * substream , int cmd )
374415{
416+ struct snd_soc_pcm_runtime * rtd = snd_soc_substream_to_rtd (substream );
375417 struct sof_ipc4_fw_data * ipc4_data = sdev -> private ;
376418 struct snd_sof_widget * pipe_widget ;
377419 struct sof_ipc4_pipeline * pipeline ;
378420 struct snd_sof_widget * swidget ;
379421 struct snd_soc_dapm_widget * w ;
422+ int num_cpus = rtd -> dai_link -> num_cpus ;
380423 int ret = 0 ;
381424
382425 w = snd_soc_dai_get_widget (cpu_dai , substream -> stream );
@@ -391,6 +434,25 @@ static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
391434
392435 switch (cmd ) {
393436 case SNDRV_PCM_TRIGGER_START :
437+ /*
438+ * For aggregated DAIs (num_cpus > 1), defer pipeline RUNNING
439+ * IPC until all CPU DAIs sharing this pipeline have started
440+ * their link DMAs. The per-spipe threshold handles all cases:
441+ * - shared pipeline: waits for all DAIs on the same spipe
442+ * - different pipelines: each fires independently (threshold=1)
443+ * - mixed: each group fires when its members complete
444+ */
445+ if (num_cpus > 1 ) {
446+ int spipe_dais = hda_ipc4_count_spipe_dais (substream ,
447+ swidget -> spipe );
448+
449+ swidget -> spipe -> trigger_count ++ ;
450+ if (swidget -> spipe -> trigger_count < spipe_dais )
451+ break ;
452+
453+ swidget -> spipe -> trigger_count = 0 ;
454+ }
455+
394456 if (pipeline -> state != SOF_IPC4_PIPE_PAUSED ) {
395457 ret = sof_ipc4_set_pipeline_state (sdev , pipe_widget -> instance_id ,
396458 SOF_IPC4_PIPE_PAUSED );
@@ -409,6 +471,17 @@ static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
409471 swidget -> spipe -> started_count ++ ;
410472 break ;
411473 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
474+ if (num_cpus > 1 ) {
475+ int spipe_dais = hda_ipc4_count_spipe_dais (substream ,
476+ swidget -> spipe );
477+
478+ swidget -> spipe -> trigger_count ++ ;
479+ if (swidget -> spipe -> trigger_count < spipe_dais )
480+ break ;
481+
482+ swidget -> spipe -> trigger_count = 0 ;
483+ }
484+
412485 ret = sof_ipc4_set_pipeline_state (sdev , pipe_widget -> instance_id ,
413486 SOF_IPC4_PIPE_RUNNING );
414487 if (ret < 0 )
@@ -420,9 +493,11 @@ static int hda_ipc4_post_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *c
420493 case SNDRV_PCM_TRIGGER_STOP :
421494 /*
422495 * 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
496+ * been stopped. So, clear the started_count so that the pipeline can be reset.
497+ * Also reset trigger_count for aggregate DAIs in case of partial trigger rollback.
424498 */
425499 swidget -> spipe -> started_count = 0 ;
500+ swidget -> spipe -> trigger_count = 0 ;
426501 break ;
427502 case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
428503 break ;
0 commit comments