This patch resets components at stream start to use non colliding areas in their source/sink buffers. It walks the non active pipelines from PCM to DAI and sets the correct r_ptr and w_ptr so that a source component never writes to the same period that the sink is reading.
The pointer spacing is fixed atm so that the reader follows the writer with a gap of 1 period, but this can be later set in topology.
Signed-off-by: Liam Girdwood liam.r.girdwood@linux.intel.com --- src/audio/dai.c | 6 --- src/audio/eq_fir.c | 2 - src/audio/eq_iir.c | 2 - src/audio/host.c | 2 - src/audio/mixer.c | 2 - src/audio/pipeline.c | 89 +++++++++++++++++++++++++++++++++++++++++ src/audio/src.c | 2 - src/audio/volume.c | 2 - src/include/reef/audio/buffer.h | 5 ++- 9 files changed, 92 insertions(+), 20 deletions(-)
diff --git a/src/audio/dai.c b/src/audio/dai.c index 4d3f0b7..f68cb44 100644 --- a/src/audio/dai.c +++ b/src/audio/dai.c @@ -268,9 +268,6 @@ static int dai_playback_params(struct comp_dev *dev) } }
- /* set write pointer to start of buffer */ - buffer_reset_pos(dma_buffer); - return 0;
err_unwind: @@ -336,9 +333,6 @@ static int dai_capture_params(struct comp_dev *dev) } }
- /* set read pointer to start of buffer */ - buffer_reset_pos(dma_buffer); - return 0;
err_unwind: diff --git a/src/audio/eq_fir.c b/src/audio/eq_fir.c index 8babed3..8a3762f 100644 --- a/src/audio/eq_fir.c +++ b/src/audio/eq_fir.c @@ -317,8 +317,6 @@ static int eq_fir_params(struct comp_dev *dev) return err; }
- buffer_reset_pos(sink); - /* EQ supports only S32_LE PCM format */ if (config->frame_fmt != SOF_IPC_FRAME_S32_LE) return -EINVAL; diff --git a/src/audio/eq_iir.c b/src/audio/eq_iir.c index 1c2389c..8cc4819 100644 --- a/src/audio/eq_iir.c +++ b/src/audio/eq_iir.c @@ -318,8 +318,6 @@ static int eq_iir_params(struct comp_dev *dev) return err; }
- buffer_reset_pos(sink); - /* EQ supports only S32_LE PCM format */ if (config->frame_fmt != SOF_IPC_FRAME_S32_LE) return -EINVAL; diff --git a/src/audio/host.c b/src/audio/host.c index aa608e7..74d3dd2 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -439,8 +439,6 @@ static int host_params(struct comp_dev *dev) if (err < 0) return err;
- buffer_reset_pos(hd->dma_buffer); - /* set up DMA configuration */ config->src_width = sizeof(uint32_t); config->dest_width = sizeof(uint32_t); diff --git a/src/audio/mixer.c b/src/audio/mixer.c index 4d50bf1..4fcaad3 100644 --- a/src/audio/mixer.c +++ b/src/audio/mixer.c @@ -149,8 +149,6 @@ static int mixer_params(struct comp_dev *dev) return ret; }
- buffer_reset_pos(sink); - return 0; }
diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index 2b6f59e..5e54f2a 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -478,6 +478,88 @@ static int component_op_upstream(struct op_data *op_data, return err; }
+static int component_prepare_buffers_upstream(struct comp_dev *start, + struct comp_dev *current, struct comp_buffer *buffer) +{ + struct list_item *clist; + int err = 0; + + /* component copy/process to downstream */ + if (current != start && buffer != NULL) { + + /* make sure current does not read from source write pos */ + /* by setting w_ptr to buffer begining and setting + * r_ptr = buffer size - period_size */ + buffer_reset_pos(buffer, current->frame_bytes); + + /* stop going downstream if we reach an end point in this pipeline */ + if (current->is_endpoint) + return 0; + } + + /* travel uptream to sink end point(s) */ + list_for_item(clist, ¤t->bsource_list) { + + buffer = container_of(clist, struct comp_buffer, sink_list); + + /* dont go upstream if this component is not connected or active */ + if (!buffer->connected || buffer->source->state == COMP_STATE_ACTIVE) + continue; + + /* continue downstream */ + err = component_prepare_buffers_upstream(start, buffer->source, + buffer); + if (err < 0) { + trace_pipe_error("eBD"); + break; + } + } + + /* return back downstream */ + return err; +} + +static int component_prepare_buffers_downstream(struct comp_dev *start, + struct comp_dev *current, struct comp_buffer *buffer) +{ + struct list_item *clist; + int err = 0; + + /* component copy/process to downstream */ + if (current != start && buffer != NULL) { + + /* make sure current does not read from source write pos */ + /* by setting w_ptr to buffer begining and setting + * r_ptr = buffer size - period_size */ + buffer_reset_pos(buffer, current->frame_bytes); + + /* stop going downstream if we reach an end point in this pipeline */ + if (current->is_endpoint) + return 0; + } + + /* travel downstream to sink end point(s) */ + list_for_item(clist, ¤t->bsink_list) { + + buffer = container_of(clist, struct comp_buffer, source_list); + + /* dont go downstream if this component is not connected or active */ + if (!buffer->connected || buffer->sink->state == COMP_STATE_ACTIVE) + continue; + + /* continue downstream */ + err = component_prepare_buffers_downstream(start, buffer->sink, + buffer); + if (err < 0) { + trace_pipe_error("eBD"); + break; + } + } + + /* return back upstream */ + return err; +} + /* prepare the pipeline for usage - preload host buffers here */ int pipeline_prepare(struct pipeline *p, struct comp_dev *dev) { @@ -498,8 +580,15 @@ int pipeline_prepare(struct pipeline *p, struct comp_dev *dev) if (ret < 0) goto out;
+ /* set up reader and writer positions */ + component_prepare_buffers_downstream(dev, dev, NULL); } else { ret = component_op_upstream(&op_data, dev, dev, NULL); + if (ret < 0) + goto out; + + /* set up reader and writer positions */ + component_prepare_buffers_upstream(dev, dev, NULL); }
out: diff --git a/src/audio/src.c b/src/audio/src.c index d71a27a..d6be7e7 100644 --- a/src/audio/src.c +++ b/src/audio/src.c @@ -450,8 +450,6 @@ static int src_params(struct comp_dev *dev) return err; }
- buffer_reset_pos(sink); - /* Check that source buffer has sufficient size */ source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); diff --git a/src/audio/volume.c b/src/audio/volume.c index 415a853..f7ca040 100644 --- a/src/audio/volume.c +++ b/src/audio/volume.c @@ -646,8 +646,6 @@ static int volume_prepare(struct comp_dev *dev) goto err; }
- buffer_reset_pos(sinkb); - /* validate */ if (cd->sink_period_bytes == 0) { trace_volume_error("vp1"); diff --git a/src/include/reef/audio/buffer.h b/src/include/reef/audio/buffer.h index d1d0869..8e9bfe9 100644 --- a/src/include/reef/audio/buffer.h +++ b/src/include/reef/audio/buffer.h @@ -164,9 +164,10 @@ static inline uint32_t comp_buffer_get_copy_bytes(struct comp_dev *dev, return copy_bytes; }
-static inline void buffer_reset_pos(struct comp_buffer *buffer) +static inline void buffer_reset_pos(struct comp_buffer *buffer, + uint32_t sink_period_bytes) { - buffer->r_ptr = buffer->addr; + buffer->r_ptr = buffer->addr + buffer->size - sink_period_bytes; buffer->w_ptr = buffer->addr; buffer->free = buffer->size; buffer->avail = 0;