No data will exist in DMA capture buffers when starting capture pipelines. This causes the downstream pipe to underrun and run XRUN recovery. Add a copy() return value of -ENODATA to indicate that no data has yet entered an active pipeline and stop pipeline processing at this point before rescheduling.
i.e. break from pipeline walk and reschedule.
This removes XRUN recovery work from the capture startup trace.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/audio/pipeline.c | 24 +++++++++++++++++++++++- src/include/reef/audio/component.h | 8 ++++++-- 2 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index 4fe7896..40a0ebf 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -750,6 +750,12 @@ static int pipeline_copy_from_upstream(struct comp_dev *start, /* continue upstream */ err = pipeline_copy_from_upstream(start, buffer->source); if (err < 0) { + + /* ENODATA is special case where data has not entered pipe yet */ + if (err == -ENODATA) + goto out; + + /* must be an error */ trace_pipe_error("ePU"); trace_value(current->comp.id); return err; @@ -760,6 +766,7 @@ copy: /* we are at the upstream end point component so copy the buffers */ err = comp_copy(current);
+out: /* return back downstream */ tracev_pipe("CD+"); return err; @@ -809,6 +816,12 @@ static int pipeline_copy_to_downstream(struct comp_dev *start, /* continue downstream */ err = pipeline_copy_to_downstream(start, buffer->sink); if (err < 0) { + + /* ENODATA is special case where data has not entered pipe yet */ + if (err == -ENODATA) + goto out; + + /* it must be an error */ trace_pipe_error("ePD"); trace_value(current->comp.id); return err; @@ -1082,6 +1095,11 @@ static void pipeline_task(void *arg) /* copy data from upstream source endpoints to downstream endpoints */ err = pipeline_copy_from_upstream(dev, dev); if (err < 0) { + + /* special case, we reschedule until data enters pipe */ + if (err == -ENODATA) + goto sched; + err = pipeline_xrun_recover(p); if (err < 0) return; /* failed - host will stop this pipeline */ @@ -1090,10 +1108,14 @@ static void pipeline_task(void *arg)
err = pipeline_copy_to_downstream(dev, dev); if (err < 0) { + + /* special case, we reschedule until data enters pipe */ + if (err == -ENODATA) + goto sched; + err = pipeline_xrun_recover(p); if (err < 0) return; /* failed - host will stop this pipeline */ - goto sched; }
sched: diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h index f25ad3d..59682d4 100644 --- a/src/include/reef/audio/component.h +++ b/src/include/reef/audio/component.h @@ -118,8 +118,12 @@ struct pipeline; /* * Audio component operations - all mandatory. * - * All component operations must return 0 for success, negative values for - * errors and 1 to stop the pipeline walk operation. + * All component operations except copy() must return 0 for success, + * negative values for errors and 1 to stop the pipeline walk operation. + * + * copy() returns 0 for success, positive values for frames produced, + * negative values for errors (except -EDATA meaning no data has entered + * the pipeline and that it must be rescheduled). */ struct comp_ops { /* component creation and destruction */