[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, &current->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, &current->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