[Sound-open-firmware] [PATCH] pipeline: Add XRUN state and handler within pipeline.
Liam Girdwood
liam.r.girdwood at linux.intel.com
Thu Nov 16 23:01:28 CET 2017
Add an XRUN handler to notify components that an XRUN has occurred and
to take any remedial action. The pipeline itself will handle an XRUN by
re-preparing the components and then send start again from the pipeline
source component.
Signed-off-by: Liam Girdwood <liam.r.girdwood at linux.intel.com>
---
src/audio/component.c | 1 +
src/audio/pipeline.c | 70 ++++++++++++++++++++++++++++++++++++--
src/include/reef/audio/component.h | 1 +
src/include/reef/audio/pipeline.h | 3 +-
4 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/src/audio/component.c b/src/audio/component.c
index 5815fad..54a7da8 100644
--- a/src/audio/component.c
+++ b/src/audio/component.c
@@ -141,6 +141,7 @@ int comp_set_state(struct comp_dev *dev, int cmd)
}
break;
case COMP_CMD_STOP:
+ case COMP_CMD_XRUN:
if (dev->state == COMP_STATE_ACTIVE) {
dev->state = COMP_STATE_PREPARE;
} else {
diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c
index bec7519..ccd6094 100644
--- a/src/audio/pipeline.c
+++ b/src/audio/pipeline.c
@@ -76,6 +76,9 @@ static void connect_upstream(struct pipeline *p, struct comp_dev *start,
/* we are an endpoint if we have 0 source components */
if (list_is_empty(¤t->bsource_list)) {
current->is_endpoint = 1;
+
+ /* pipeline source comp is current */
+ p->source_comp = current;
return;
}
@@ -86,8 +89,13 @@ static void connect_upstream(struct pipeline *p, struct comp_dev *start,
buffer = container_of(clist, struct comp_buffer, sink_list);
/* don't go upstream if this source is from another pipeline */
- if (buffer->source->comp.pipeline_id != p->ipc_pipe.pipeline_id)
+ if (buffer->source->comp.pipeline_id != p->ipc_pipe.pipeline_id) {
+
+ /* pipeline source comp is current unless we go upstream */
+ p->source_comp = current;
+
continue;
+ }
connect_upstream(p, start, buffer->source);
}
@@ -210,6 +218,7 @@ static void pipeline_cmd_update(struct pipeline *p, struct comp_dev *comp,
break;
case COMP_CMD_SUSPEND:
case COMP_CMD_RESUME:
+ case COMP_CMD_XRUN:
default:
break;
}
@@ -1001,6 +1010,38 @@ void pipeline_xrun(struct pipeline *p, struct comp_dev *dev,
}
}
+/* recover the pipeline from a XRUN condition */
+static int pipeline_xrun_recover(struct pipeline *p)
+{
+ int ret;
+
+ trace_pipe_error("pxr");
+
+ /* notify all pipeline comps we are in XRUN */
+ ret = pipeline_cmd(p, p->source_comp, COMP_CMD_XRUN, NULL);
+ if (ret < 0) {
+ trace_pipe_error("px0");
+ return ret;
+ }
+ p->xrun_bytes = 0;
+
+ /* prepare the pipeline */
+ pipeline_prepare(p, p->source_comp);
+ if (ret < 0) {
+ trace_pipe_error("px1");
+ return ret;
+ }
+
+ /* restart pipeline comps */
+ pipeline_cmd(p, p->source_comp, COMP_CMD_START, NULL);
+ if (ret < 0) {
+ trace_pipe_error("px2");
+ return ret;
+ }
+
+ return 0;
+}
+
/* notify pipeline that this component requires buffers emptied/filled */
void pipeline_schedule_copy(struct pipeline *p, uint64_t start)
{
@@ -1025,13 +1066,36 @@ static void pipeline_task(void *arg)
{
struct pipeline *p = arg;
struct comp_dev *dev = p->sched_comp;
+ int err;
tracev_pipe("PWs");
+ /* are we in xrun ? */
+ if (p->xrun_bytes) {
+ err = pipeline_xrun_recover(p);
+ if (err < 0)
+ return; /* failed - host will stop this pipeline */
+ goto sched;
+ }
+
/* copy data from upstream source endpoints to downstream endpoints */
- pipeline_copy_from_upstream(dev, dev);
- pipeline_copy_to_downstream(dev, dev);
+ err = pipeline_copy_from_upstream(dev, dev);
+ if (err < 0) {
+ err = pipeline_xrun_recover(p);
+ if (err < 0)
+ return; /* failed - host will stop this pipeline */
+ goto sched;
+ }
+
+ err = pipeline_copy_to_downstream(dev, dev);
+ if (err < 0) {
+ err = pipeline_xrun_recover(p);
+ if (err < 0)
+ return; /* failed - host will stop this pipeline */
+ goto sched;
+ }
+sched:
tracev_pipe("PWe");
/* now reschedule the task */
diff --git a/src/include/reef/audio/component.h b/src/include/reef/audio/component.h
index afd5461..5d15fdb 100644
--- a/src/include/reef/audio/component.h
+++ b/src/include/reef/audio/component.h
@@ -80,6 +80,7 @@
#define COMP_CMD_RESUME 6 /* resume component */
#define COMP_CMD_RESET 6 /* reset component */
#define COMP_CMD_PREPARE 7 /* prepare component */
+#define COMP_CMD_XRUN 8 /* XRUN component */
/*
* standard component control commands
diff --git a/src/include/reef/audio/pipeline.h b/src/include/reef/audio/pipeline.h
index c5ba49f..08a3f30 100644
--- a/src/include/reef/audio/pipeline.h
+++ b/src/include/reef/audio/pipeline.h
@@ -67,7 +67,8 @@ struct pipeline {
/* scheduling */
struct task pipe_task; /* pipeline processing task */
- struct comp_dev *sched_comp;
+ struct comp_dev *sched_comp; /* component that drives scheduling in this pipe */
+ struct comp_dev *source_comp; /* source component for this pipe */
};
/* static pipeline */
--
2.11.0
More information about the Sound-open-firmware
mailing list