@@ -59,21 +59,40 @@ pipeline_should_report_enodata_on_trigger(struct comp_dev *rsrc,
5959 return false;
6060}
6161
62+ /* Runs in IPC or in pipeline task context */
6263static int pipeline_comp_trigger (struct comp_dev * current ,
6364 struct comp_buffer * calling_buf ,
6465 struct pipeline_walk_context * ctx , int dir )
6566{
6667 struct pipeline_data * ppl_data = ctx -> comp_data ;
6768 bool is_single_ppl = comp_is_single_pipeline (current , ppl_data -> start );
68- bool is_same_sched =
69- pipeline_is_same_sched_comp (current -> pipeline ,
70- ppl_data -> start -> pipeline );
69+ bool is_same_sched , async ;
7170 int err ;
7271
7372 pipe_dbg (current -> pipeline ,
7473 "pipeline_comp_trigger(), current->comp.id = %u, dir = %u" ,
7574 dev_comp_id (current ), dir );
7675
76+ switch (ppl_data -> cmd ) {
77+ case COMP_TRIGGER_PAUSE :
78+ case COMP_TRIGGER_STOP :
79+ /*
80+ * PAUSE and STOP are triggered in IPC context, not from the
81+ * pipeline task
82+ */
83+ async = true;
84+ break ;
85+ case COMP_TRIGGER_RELEASE :
86+ case COMP_TRIGGER_START :
87+ async = !pipeline_is_timer_driven (current -> pipeline );
88+ break ;
89+ default :
90+ return - EINVAL ;
91+ }
92+
93+ is_same_sched = pipeline_is_same_sched_comp (current -> pipeline ,
94+ ppl_data -> start -> pipeline );
95+
7796 /* trigger should propagate to the connected pipelines,
7897 * which need to be scheduled together
7998 */
@@ -92,7 +111,12 @@ static int pipeline_comp_trigger(struct comp_dev *current,
92111 if (err < 0 || err == PPL_STATUS_PATH_STOP )
93112 return err ;
94113
95- pipeline_comp_trigger_sched_comp (current -> pipeline , current , ctx );
114+ /*
115+ * Add scheduling components to the list. This is only needed for the
116+ * stopping flow.
117+ */
118+ if (async )
119+ pipeline_comp_trigger_sched_comp (current -> pipeline , current , ctx );
96120
97121 return pipeline_for_each_comp (current , ctx , dir );
98122}
@@ -172,18 +196,95 @@ int pipeline_copy(struct pipeline *p)
172196 return ret ;
173197}
174198
175- /* trigger pipeline */
199+ /* only collect scheduling components */
200+ static int pipeline_comp_list (struct comp_dev * current ,
201+ struct comp_buffer * calling_buf ,
202+ struct pipeline_walk_context * ctx , int dir )
203+ {
204+ struct pipeline_data * ppl_data = ctx -> comp_data ;
205+ bool is_single_ppl = comp_is_single_pipeline (current , ppl_data -> start );
206+ bool is_same_sched = pipeline_is_same_sched_comp (current -> pipeline ,
207+ ppl_data -> start -> pipeline );
208+
209+ if (!is_single_ppl && !is_same_sched ) {
210+ pipe_dbg (current -> pipeline ,
211+ "pipeline_comp_list(), current is from another pipeline" );
212+ return 0 ;
213+ }
214+
215+ /* Add scheduling components to the list */
216+ pipeline_comp_trigger_sched_comp (current -> pipeline , current , ctx );
217+
218+ return pipeline_for_each_comp (current , ctx , dir );
219+ }
220+
221+ /* build a list of connected pipelines' scheduling components and trigger them */
222+ static int pipeline_trigger_list (struct pipeline * p , struct comp_dev * host , int cmd )
223+ {
224+ struct pipeline_data data = {
225+ .start = host ,
226+ .cmd = cmd ,
227+ };
228+ struct pipeline_walk_context walk_ctx = {
229+ .comp_func = pipeline_comp_list ,
230+ .comp_data = & data ,
231+ .skip_incomplete = true,
232+ };
233+ int ret ;
234+
235+ list_init (& walk_ctx .pipelines );
236+
237+ ret = walk_ctx .comp_func (host , NULL , & walk_ctx , host -> direction );
238+ if (ret < 0 )
239+ pipe_err (p , "pipeline_trigger_list(): ret = %d, host->comp.id = %u, cmd = %d" ,
240+ ret , dev_comp_id (host ), cmd );
241+ else
242+ pipeline_schedule_triggered (& walk_ctx , cmd );
243+
244+ return ret ;
245+ }
246+
247+ /* trigger pipeline in IPC context */
176248int pipeline_trigger (struct pipeline * p , struct comp_dev * host , int cmd )
177249{
178- struct pipeline_data data ;
250+ int ret ;
251+
252+ pipe_info (p , "pipe trigger cmd %d" , cmd );
253+
254+ switch (cmd ) {
255+ case COMP_TRIGGER_PAUSE :
256+ case COMP_TRIGGER_STOP :
257+ /* Execute immediately */
258+ ret = pipeline_trigger_run (p , host , cmd );
259+ return ret == PPL_STATUS_PATH_STOP ? 0 : ret ;
260+ case COMP_TRIGGER_RELEASE :
261+ case COMP_TRIGGER_START :
262+ /* Add all connected pipelines to the list and schedule them all */
263+ ret = pipeline_trigger_list (p , host , cmd );
264+ if (ret < 0 )
265+ return ret ;
266+ /* IPC response will be sent from the task */
267+ return 1 ;
268+ }
269+
270+ return 0 ;
271+ }
272+
273+ /* actually execute pipeline trigger, including components: either in IPC or in task context */
274+ int pipeline_trigger_run (struct pipeline * p , struct comp_dev * host , int cmd )
275+ {
276+ struct pipeline_data data = {
277+ .start = host ,
278+ .cmd = cmd ,
279+ };
179280 struct pipeline_walk_context walk_ctx = {
180281 .comp_func = pipeline_comp_trigger ,
181282 .comp_data = & data ,
182283 .skip_incomplete = true,
183284 };
184285 int ret ;
185286
186- pipe_info (p , "pipe trigger cmd %d" , cmd );
287+ pipe_dbg (p , "execute trigger cmd %d on pipe %u " , cmd , p -> pipeline_id );
187288
188289 list_init (& walk_ctx .pipelines );
189290
@@ -193,20 +294,23 @@ int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd)
193294 if (ret < 0 ) {
194295 pipe_err (p , "xrun handle: ret = %d" , ret );
195296 return ret ;
196- } else if (ret == PPL_STATUS_PATH_STOP )
297+ }
298+
299+ if (ret == PPL_STATUS_PATH_STOP )
197300 /* no further action needed*/
198- return 0 ;
301+ return pipeline_is_timer_driven ( p ) ;
199302 }
200303
201- data .start = host ;
202- data .cmd = cmd ;
203-
204304 ret = walk_ctx .comp_func (host , NULL , & walk_ctx , host -> direction );
205- if (ret < 0 ) {
206- pipe_err (p , "pipeline_trigger (): ret = %d, host->comp.id = %u, cmd = %d" ,
305+ if (ret < 0 )
306+ pipe_err (p , "pipeline_trigger_run (): ret = %d, host->comp.id = %u, cmd = %d" ,
207307 ret , dev_comp_id (host ), cmd );
208- }
209308
309+ /*
310+ * When called from the pipeline task, pipeline_comp_trigger() will not
311+ * add pipelines to the list, so pipeline_schedule_triggered() will have
312+ * no effect.
313+ */
210314 pipeline_schedule_triggered (& walk_ctx , cmd );
211315
212316 return ret ;
0 commit comments