@@ -353,6 +353,8 @@ int pipeline_prepare(struct pipeline *p, struct comp_dev *dev)
353353 goto out ;
354354 }
355355
356+ /* pipeline preload needed only for playback streams */
357+ p -> preload = dev -> params .direction == SOF_IPC_STREAM_PLAYBACK ;
356358 p -> status = COMP_STATE_PREPARE ;
357359
358360out :
@@ -574,8 +576,7 @@ static int pipeline_comp_copy(struct comp_dev *current, void *data, int dir)
574576 struct pipeline_data * ppl_data = data ;
575577 int is_single_ppl = comp_is_single_pipeline (current , ppl_data -> start );
576578 int is_same_sched =
577- pipeline_is_same_sched_comp (current -> pipeline ,
578- ppl_data -> start -> pipeline );
579+ pipeline_is_same_sched_comp (current -> pipeline , ppl_data -> p );
579580 int err = 0 ;
580581
581582 tracev_pipe ("pipeline_comp_copy(), current->comp.id = %u, dir = %u" ,
@@ -593,7 +594,7 @@ static int pipeline_comp_copy(struct comp_dev *current, void *data, int dir)
593594 }
594595
595596 /* copy to downstream immediately */
596- if (current != ppl_data -> start && dir == PPL_DIR_DOWNSTREAM ) {
597+ if (dir == PPL_DIR_DOWNSTREAM ) {
597598 err = comp_copy (current );
598599 if (err < 0 )
599600 return err ;
@@ -610,29 +611,53 @@ static int pipeline_comp_copy(struct comp_dev *current, void *data, int dir)
610611 return err ;
611612}
612613
613- /* copy data from upstream source endpoints to downstream endpoints */
614- static int pipeline_copy (struct comp_dev * dev )
614+ /* Copy data across all pipeline components.
615+ * For capture pipelines it always starts from source component
616+ * and continues downstream. For playback pipelines there are two
617+ * possibilities: for preload it starts from sink component and
618+ * continues upstream and if not preload, then it first copies
619+ * sink component itself and then goes upstream.
620+ */
621+ static int pipeline_copy (struct pipeline * p )
615622{
616623 struct pipeline_data data ;
624+ struct comp_dev * start ;
625+ uint32_t dir ;
617626 int ret = 0 ;
618627
619- data .start = dev ;
620-
621- ret = pipeline_comp_copy (dev , & data , PPL_DIR_UPSTREAM );
622- if (ret < 0 ) {
623- trace_ipc_error ("pipeline_copy() error: ret = %d, dev->comp."
624- "id = %u, dir = %u" , ret , dev -> comp .id ,
625- PPL_DIR_UPSTREAM );
626- return ret ;
628+ if (p -> source_comp -> params .direction == SOF_IPC_STREAM_PLAYBACK ) {
629+ dir = PPL_DIR_UPSTREAM ;
630+ start = p -> sink_comp ;
631+
632+ /* if not pipeline preload then copy sink comp first */
633+ if (!p -> preload ) {
634+ ret = comp_copy (start );
635+ if (ret < 0 ) {
636+ trace_pipe_error ("pipeline_copy() error: "
637+ "ret = %d" , ret );
638+ return ret ;
639+ }
640+
641+ start = comp_get_previous (start , dir );
642+ if (!start )
643+ /* nothing else to do */
644+ return ret ;
645+ }
646+ } else {
647+ dir = PPL_DIR_DOWNSTREAM ;
648+ start = p -> source_comp ;
627649 }
628650
629- ret = pipeline_comp_copy (dev , & data , PPL_DIR_DOWNSTREAM );
630- if (ret < 0 ) {
631- trace_ipc_error ("pipeline_copy() error: ret = %d, dev->comp."
632- "id = %u, dir = %u" , ret , dev -> comp .id ,
633- PPL_DIR_DOWNSTREAM );
634- return ret ;
635- }
651+ data .start = start ;
652+ data .p = p ;
653+
654+ ret = pipeline_comp_copy (start , & data , dir );
655+ if (ret < 0 )
656+ trace_pipe_error ("pipeline_copy() error: ret = %d, start"
657+ "->comp.id = %u, dir = %u" , ret ,
658+ start -> comp .id , dir );
659+
660+ p -> preload = false;
636661
637662 return ret ;
638663}
@@ -809,7 +834,7 @@ static void pipeline_task(void *arg)
809834 goto sched ;/* skip copy if still in xrun */
810835 }
811836
812- err = pipeline_copy (p -> sched_comp );
837+ err = pipeline_copy (p );
813838 if (err < 0 ) {
814839 /* try to recover */
815840 err = pipeline_xrun_recover (p );
0 commit comments