[Sound-open-firmware] [PATCH 1/4] SRC: IPC updates and fixes v2

Seppo Ingalsuo seppo.ingalsuo at linux.intel.com
Wed Jun 28 12:32:02 CEST 2017


SRC updates sink and downstream pipeline PCM rate, period_count and
period_bytes in src_params() according to received out_rate via IPC.
Also the use of incorrect alloc_size is replaced by ipc_buffer.size.

Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo at linux.intel.com>
---
 src/audio/src.c                 | 90 ++++++++++++++++++++++++-----------------
 src/include/reef/audio/buffer.h |  8 ++--
 src/include/uapi/ipc.h          |  1 +
 3 files changed, 57 insertions(+), 42 deletions(-)

diff --git a/src/audio/src.c b/src/audio/src.c
index c338220..f1f4b86 100644
--- a/src/audio/src.c
+++ b/src/audio/src.c
@@ -56,9 +56,13 @@
 /* src component private data */
 struct comp_data {
 	struct polyphase_src src[PLATFORM_MAX_CHANNELS];
+	/* Next two elements must be kept in this order since
+	 * the end of pcm_params is a flexible array.
+	 */
+	struct sof_ipc_pcm_params pcm_params;
+	enum sof_ipc_chmap channel_map[PLATFORM_MAX_CHANNELS];
 	int32_t *delay_lines;
 	int scratch_length;
-	//int32_t z[STAGE_BUF_SIZE];
 	void (*src_func)(struct comp_dev *dev,
 		struct comp_buffer *source,
 		struct comp_buffer *sink,
@@ -155,7 +159,7 @@ static void src_2s_s32_default(struct comp_dev *dev,
 
 	s1.times = n_times1;
 	s1.x_end_addr = source->end_addr;
-	s1.x_size = source->alloc_size;
+	s1.x_size = source->ipc_buffer.size;
 	s1.x_inc = nch;
 	s1.y_end_addr = &cd->delay_lines[cd->scratch_length];
 	s1.y_size = STAGE_BUF_SIZE * sizeof(int32_t);
@@ -166,7 +170,7 @@ static void src_2s_s32_default(struct comp_dev *dev,
 	s2.x_size = STAGE_BUF_SIZE * sizeof(int32_t);
 	s2.x_inc = 1;
 	s2.y_end_addr = sink->end_addr;
-	s2.y_size = sink->alloc_size;
+	s2.y_size = sink->ipc_buffer.size;
 	s2.y_inc = nch;
 
 	s1.x_rptr = src + nch - 1;
@@ -227,10 +231,10 @@ static void src_1s_s32_default(struct comp_dev *dev,
 
 	s1.times = n_times;
 	s1.x_end_addr = source->end_addr;
-	s1.x_size = source->alloc_size;
+	s1.x_size = source->ipc_buffer.size;
 	s1.x_inc = nch;
 	s1.y_end_addr = sink->end_addr;
-	s1.y_size = sink->alloc_size;
+	s1.y_size = sink->ipc_buffer.size;
 	s1.y_inc = nch;
 	s1.x_rptr = src + nch - 1;
 	s1.y_wptr = dest + nch - 1;
@@ -263,7 +267,7 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp)
 {
 	struct comp_dev *dev;
 	struct sof_ipc_comp_src *src;
-	struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *)comp;
+	struct sof_ipc_comp_src *ipc_src = (struct sof_ipc_comp_src *) comp;
 	struct comp_data *cd;
 	int i;
 
@@ -274,7 +278,7 @@ static struct comp_dev *src_new(struct sof_ipc_comp *comp)
 	if (dev == NULL)
 		return NULL;
 
-	src = (struct sof_ipc_comp_src *)&dev->comp;
+	src = (struct sof_ipc_comp_src *) &dev->comp;
 	memcpy(src, ipc_src, sizeof(struct sof_ipc_comp_src));
 
 	cd = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, sizeof(*cd));
@@ -317,6 +321,7 @@ static int src_params(struct comp_dev *dev, struct stream_params *params)
 	int32_t *buffer_start;
 	int n = 0;
 	struct comp_data *cd = comp_get_drvdata(dev);
+	struct sof_ipc_comp_src *src = (struct sof_ipc_comp_src *) &dev->comp;
 
 	trace_src("SPa");
 
@@ -325,23 +330,43 @@ static int src_params(struct comp_dev *dev, struct stream_params *params)
 		|| (params->pcm->frame_fmt != SOF_IPC_FRAME_S32_LE))
 		return -EINVAL;
 
-	/* No data transformation */
-	comp_set_sink_params(dev, params);
-
-	/* Allocate needed memory for delay lines */
 	source = list_first_item(&dev->bsource_list, struct comp_buffer,
 		sink_list);
 	sink = list_first_item(&dev->bsink_list, struct comp_buffer,
 		source_list);
-	src_buffer_lengths(&need, source->params.pcm->rate,
-		sink->params.pcm->rate, source->params.pcm->channels);
+
+	/* Copy PCM stream parameters and the channel map array */
+	memcpy(&cd->pcm_params, &(*params->pcm),
+		sizeof(struct sof_ipc_pcm_params));
+	for (i = 0; i < params->pcm->channels; i++)
+		cd->pcm_params.channel_map[i] = params->pcm->channel_map[i];
+
+	/* Point sink stream parameters to copy */
+	sink->params.pcm = &cd->pcm_params;
+
+	/* Stored IPC from src_new() contains the output rate for sink,
+	 * set the new rate for sink.
+	 */
+	sink->params.pcm->rate = src->out_rate;
+
+	/* Adjust sink buffer parameters to match fs_out/fs_in */
+	sink->params.pcm->period_count = sink->params.pcm->period_count
+		* sink->params.pcm->rate / source->params.pcm->rate;
+	sink->params.pcm->period_bytes = sink->params.pcm->period_bytes
+		* sink->params.pcm->rate / source->params.pcm->rate;
+
+	/* Allocate needed memory for delay lines */
+	if (src_buffer_lengths(&need, source->params.pcm->rate,
+		sink->params.pcm->rate, source->params.pcm->channels) < 0)
+		return -EINVAL;
+
 	delay_lines_size = sizeof(int32_t) * need.total;
 	if (cd->delay_lines != NULL)
 		rfree(cd->delay_lines);
 
 	cd->delay_lines = rmalloc(RZONE_RUNTIME, RFLAGS_NONE, delay_lines_size);
 	if (cd->delay_lines == NULL)
-		return -EINVAL;
+		return -ENOMEM;
 
 	/* Clear all delay lines here */
 	memset(cd->delay_lines, 0, delay_lines_size);
@@ -369,19 +394,20 @@ static int src_params(struct comp_dev *dev, struct stream_params *params)
 		 */
 		trace_src("SFa");
 		cd->src_func = fallback_s32;
-		return(-EINVAL);
-		break;
+		rfree(cd->delay_lines);
+		return -EINVAL;
 	}
 
 	/* Check that src blk_in and blk_out are less than params.period_frames.
 	 * Return an error if the period is too short.
 	 */
-	if (src_polyphase_get_blk_in(&cd->src[0]) > source->params.pcm->period_count)
-		return(-EINVAL);
-
-	if (src_polyphase_get_blk_out(&cd->src[0]) > sink->params.pcm->period_count)
-		return(-EINVAL);
+	if (src_polyphase_get_blk_in(&cd->src[0])
+		> source->params.pcm->period_count)
+		return -EINVAL;
 
+	if (src_polyphase_get_blk_out(&cd->src[0])
+		> sink->params.pcm->period_count)
+		return -EINVAL;
 
 	return 0;
 }
@@ -453,7 +479,8 @@ static int src_copy(struct comp_dev *dev)
 	struct comp_buffer *sink;
 	uint32_t frames_source;
 	uint32_t frames_sink;
-	int need_source, need_sink, min_frames;
+	int need_source, need_sink;
+	// int min_frames;
 
 	trace_comp("SRC");
 
@@ -464,25 +491,12 @@ static int src_copy(struct comp_dev *dev)
 		source_list);
 
 	/* Check that source has enough frames available and sink enough
-	 * frames free.
+	 * frames free. Increase tried period_count if not sufficient to run. 
 	 */
 	frames_source = source->params.pcm->period_count;
 	frames_sink = sink->params.pcm->period_count;
-	min_frames = src_polyphase_get_blk_in(&cd->src[0]);
-	if (frames_source > min_frames)
-		need_source = frames_source * source->params.pcm->frame_size;
-	else {
-		frames_source = min_frames;
-		need_source = min_frames * source->params.pcm->frame_size;
-	}
-
-	min_frames = src_polyphase_get_blk_out(&cd->src[0]);
-	if (frames_sink > min_frames)
-		need_sink = frames_sink * sink->params.pcm->frame_size;
-	else {
-		frames_sink = min_frames;
-		need_sink = min_frames * sink->params.pcm->frame_size;
-	}
+	need_source = source->params.pcm->period_bytes;
+	need_sink = sink->params.pcm->period_bytes;
 
 	/* Run as many times as buffers allow */
 	while ((source->avail >= need_source) && (sink->free >= need_sink)) {
diff --git a/src/include/reef/audio/buffer.h b/src/include/reef/audio/buffer.h
index 5f2dbb7..0817a40 100644
--- a/src/include/reef/audio/buffer.h
+++ b/src/include/reef/audio/buffer.h
@@ -119,20 +119,20 @@ static inline void comp_update_sink_free_avail(struct comp_buffer *snk, int n)
 static inline void comp_wrap_source_r_ptr_circular(struct comp_buffer *src)
 {
         if (src->r_ptr >= src->end_addr)
-                src->r_ptr -= src->alloc_size;
+                src->r_ptr -= src->ipc_buffer.size;
 
         if (src->r_ptr < src->addr)
-                src->r_ptr += src->alloc_size;
+                src->r_ptr += src->ipc_buffer.size;
 }
 
 
 static inline void comp_wrap_sink_w_ptr_circular(struct comp_buffer *snk)
 {
         if (snk->w_ptr >= snk->end_addr)
-                snk->w_ptr -= snk->alloc_size;
+                snk->w_ptr -= snk->ipc_buffer.size;
 
         if (snk->w_ptr < snk->addr)
-                snk->w_ptr += snk->alloc_size;
+                snk->w_ptr += snk->ipc_buffer.size;
 }
 
 #endif
diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h
index 3d78db3..d89039e 100644
--- a/src/include/uapi/ipc.h
+++ b/src/include/uapi/ipc.h
@@ -488,6 +488,7 @@ struct sof_ipc_comp_src {
 	struct sof_ipc_pcm_comp pcm;
 	uint32_t in_mask;	/* SOF_RATE_ supported input rates */
 	uint32_t out_mask;	/* SOF_RATE_ supported output rates */
+	int32_t out_rate;
 } __attribute__((packed));
 
 /* generic MUX component */
-- 
2.11.0



More information about the Sound-open-firmware mailing list