[Sound-open-firmware] [PATCH] comp: buffer: reset components to use non colliding R/W pointers
Liam Girdwood
liam.r.girdwood at linux.intel.com
Fri Nov 10 21:24:39 CET 2017
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 at 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;
--
2.11.0
More information about the Sound-open-firmware
mailing list