From dab51ffc796610b8b6be539d6dcee9f69856208f Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Tue, 6 Dec 2022 21:41:13 +0800 Subject: [PATCH 1/6] src: remove unnecessary if conditional judgment No need to add if condition judgment and rfree(NULL) is allowed. Signed-off-by: Gongjun Song --- src/audio/src/src.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/audio/src/src.c b/src/audio/src/src.c index cdbf3373fdbd..9a48a0f29637 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -618,8 +618,7 @@ static void src_free(struct comp_dev *dev) comp_info(dev, "src_free()"); /* Free dynamically reserved buffers for SRC algorithm */ - if (cd->delay_lines) - rfree(cd->delay_lines); + rfree(cd->delay_lines); rfree(cd); rfree(dev); @@ -730,8 +729,7 @@ static int src_params(struct comp_dev *dev, } /* free any existing delay lines. TODO reuse if same size */ - if (cd->delay_lines) - rfree(cd->delay_lines); + rfree(cd->delay_lines); cd->delay_lines = rballoc(0, SOF_MEM_CAPS_RAM, delay_lines_size); if (!cd->delay_lines) { From a6ecbd39b30ea6396b292cf4f4470775e648087d Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Mon, 28 Nov 2022 16:09:54 +0800 Subject: [PATCH 2/6] src: remove some unnecessary brackets Remove some unnecessary brackets in src_verify_params function. Signed-off-by: Gongjun Song --- src/audio/src/src.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/audio/src/src.c b/src/audio/src/src.c index 9a48a0f29637..70a334a964af 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -644,7 +644,7 @@ static int src_verify_params(struct comp_dev *dev, return ret; } } else { - if (cd->ipc_config.sink_rate && (params->rate != cd->ipc_config.sink_rate)) { + if (cd->ipc_config.sink_rate && params->rate != cd->ipc_config.sink_rate) { comp_err(dev, "src_verify_params(): runtime stream pcm rate %u does not match rate %u fetched from ipc.", params->rate, cd->ipc_config.sink_rate); return -EINVAL; @@ -654,9 +654,8 @@ static int src_verify_params(struct comp_dev *dev, /* update downstream (playback) or upstream (capture) buffer parameters */ ret = comp_verify_params(dev, BUFF_PARAMS_RATE, params); - if (ret < 0) { + if (ret < 0) comp_err(dev, "src_verify_params(): comp_verify_params() failed."); - } return ret; } From 13c51092c1fb00e6290ea3e705580876028b74c4 Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Fri, 25 Nov 2022 14:33:39 +0800 Subject: [PATCH 3/6] src: fix sink rate setting error of SRC ipc4 The commit that caused this bug is 1ec9fc1fbfd3616cd. Added the sink_c parameter, but did not set sink_c in src.c. This commit will set sink_c to solve the issue of wrong sink rate. Signed-off-by: Gongjun Song --- src/audio/src/src.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/src/src.c b/src/audio/src/src.c index 70a334a964af..53412b968152 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -518,6 +518,7 @@ static void src_set_params(struct comp_dev *dev, struct sof_ipc_stream_params *p { struct comp_data *cd = comp_get_drvdata(dev); struct comp_buffer *sinkb; + struct comp_buffer __sparse_cache *sink_c; memset(params, 0, sizeof(*params)); params->channels = cd->ipc_config.base.audio_fmt.channels_count; @@ -529,7 +530,9 @@ static void src_set_params(struct comp_dev *dev, struct sof_ipc_stream_params *p params->buffer.size = cd->ipc_config.base.ibs; sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); - sinkb->stream.rate = cd->ipc_config.sink_rate; + sink_c = buffer_acquire(sinkb); + sink_c->stream.rate = cd->ipc_config.sink_rate; + buffer_release(sink_c); } static void src_set_sink_params(struct comp_dev *dev, struct comp_buffer __sparse_cache *sinkb) From c81b332ef1478ff3541f569e6e4293a0e4bac451 Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Mon, 28 Nov 2022 14:52:29 +0800 Subject: [PATCH 4/6] src: move some functions positions to fit the module adapter Due to add module adapter feature, some functions need to be moved to new locations to fit it. Signed-off-by: Gongjun Song --- src/audio/src/src.c | 248 ++++++++++++++++++++++---------------------- 1 file changed, 124 insertions(+), 124 deletions(-) diff --git a/src/audio/src/src.c b/src/audio/src/src.c index 53412b968152..f07ff177a01a 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -576,6 +576,130 @@ static void src_set_sink_params(struct comp_dev *dev, struct comp_buffer __spars #error "No or invalid IPC MAJOR version selected." #endif /* CONFIG_IPC_MAJOR_4 */ +static int src_verify_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct comp_data *cd = comp_get_drvdata(dev); + int ret; + + comp_dbg(dev, "src_verify_params()"); + + /* check whether params->rate (received from driver) are equal + * to src->source_rate (PLAYBACK) or src->sink_rate (CAPTURE) set during + * creating src component in src_new(). + * src->source/sink_rate = 0 means that source/sink rate can vary. + */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + ret = src_stream_pcm_source_rate_check(cd->ipc_config, params); + if (ret < 0) { + comp_err(dev, "src_verify_params(): runtime stream pcm rate does not match rate fetched from ipc."); + return ret; + } + } else { + if (cd->ipc_config.sink_rate && params->rate != cd->ipc_config.sink_rate) { + comp_err(dev, "src_verify_params(): runtime stream pcm rate %u does not match rate %u fetched from ipc.", + params->rate, cd->ipc_config.sink_rate); + return -EINVAL; + } + } + + /* update downstream (playback) or upstream (capture) buffer parameters + */ + ret = comp_verify_params(dev, BUFF_PARAMS_RATE, params); + if (ret < 0) + comp_err(dev, "src_verify_params(): comp_verify_params() failed."); + + return ret; +} + +static int src_get_copy_limits(struct comp_data *cd, + const struct comp_buffer __sparse_cache *source, + const struct comp_buffer __sparse_cache *sink) +{ + struct src_param *sp; + struct src_stage *s1; + struct src_stage *s2; + int frames_src; + int frames_snk; + + /* Get SRC parameters */ + sp = &cd->param; + s1 = cd->src.stage1; + s2 = cd->src.stage2; + + /* Calculate how many blocks can be processed with + * available source and free sink frames amount. + */ + if (s2->filter_length > 1) { + /* Two polyphase filters case */ + frames_snk = audio_stream_get_free_frames(&sink->stream); + frames_snk = MIN(frames_snk, cd->sink_frames + s2->blk_out); + sp->stage2_times = frames_snk / s2->blk_out; + frames_src = audio_stream_get_avail_frames(&source->stream); + frames_src = MIN(frames_src, cd->source_frames + s1->blk_in); + sp->stage1_times = frames_src / s1->blk_in; + sp->blk_in = sp->stage1_times * s1->blk_in; + sp->blk_out = sp->stage2_times * s2->blk_out; + } else { + /* Single polyphase filter case */ + frames_snk = audio_stream_get_free_frames(&sink->stream); + frames_snk = MIN(frames_snk, cd->sink_frames + s1->blk_out); + sp->stage1_times = frames_snk / s1->blk_out; + frames_src = audio_stream_get_avail_frames(&source->stream); + sp->stage1_times = MIN(sp->stage1_times, + frames_src / s1->blk_in); + sp->blk_in = sp->stage1_times * s1->blk_in; + sp->blk_out = sp->stage1_times * s1->blk_out; + } + + if (sp->blk_in == 0 && sp->blk_out == 0) + return -EIO; + + return 0; +} + +static int src_check_buffer_sizes(struct comp_data *cd, + struct audio_stream __sparse_cache *source_stream, + struct audio_stream __sparse_cache *sink_stream) +{ + struct src_stage *s1 = cd->src.stage1; + struct src_stage *s2 = cd->src.stage2; + int stage1_times; + int stage2_times; + int blk_in; + int blk_out; + int n; + + if (s2->filter_length > 1) { + /* Two polyphase filters case */ + stage2_times = ceil_divide(cd->sink_frames, s2->blk_out); + stage1_times = ceil_divide(cd->source_frames, s1->blk_in); + blk_in = stage1_times * s1->blk_in; + blk_out = stage2_times * s2->blk_out; + } else { + /* Single polyphase filter case */ + stage1_times = ceil_divide(cd->sink_frames, s1->blk_out); + n = ceil_divide(cd->source_frames, s1->blk_in); + stage1_times = MAX(stage1_times, n); + blk_in = stage1_times * s1->blk_in; + blk_out = stage1_times * s1->blk_out; + } + + n = audio_stream_frame_bytes(source_stream) * (blk_in + cd->source_frames); + if (source_stream->size < n) { + comp_cl_warn(&comp_src, "Source size %d is less than required %d", + source_stream->size, n); + } + + n = audio_stream_frame_bytes(sink_stream) * (blk_out + cd->sink_frames); + if (sink_stream->size < n) { + comp_cl_warn(&comp_src, "Sink size %d is less than required %d", + sink_stream->size, n); + } + + return 0; +} + static struct comp_dev *src_new(const struct comp_driver *drv, const struct comp_ipc_config *config, const void *spec) @@ -627,42 +751,6 @@ static void src_free(struct comp_dev *dev) rfree(dev); } -static int src_verify_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int ret; - - comp_dbg(dev, "src_verify_params()"); - - /* check whether params->rate (received from driver) are equal - * to src->source_rate (PLAYBACK) or src->sink_rate (CAPTURE) set during - * creating src component in src_new(). - * src->source/sink_rate = 0 means that source/sink rate can vary. - */ - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { - ret = src_stream_pcm_source_rate_check(cd->ipc_config, params); - if (ret < 0) { - comp_err(dev, "src_verify_params(): runtime stream pcm rate does not match rate fetched from ipc."); - return ret; - } - } else { - if (cd->ipc_config.sink_rate && params->rate != cd->ipc_config.sink_rate) { - comp_err(dev, "src_verify_params(): runtime stream pcm rate %u does not match rate %u fetched from ipc.", - params->rate, cd->ipc_config.sink_rate); - return -EINVAL; - } - } - - /* update downstream (playback) or upstream (capture) buffer parameters - */ - ret = comp_verify_params(dev, BUFF_PARAMS_RATE, params); - if (ret < 0) - comp_err(dev, "src_verify_params(): comp_verify_params() failed."); - - return ret; -} - /* set component audio stream parameters */ static int src_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) @@ -816,52 +904,6 @@ static int src_trigger(struct comp_dev *dev, int cmd) return comp_set_state(dev, cmd); } -static int src_get_copy_limits(struct comp_data *cd, - const struct comp_buffer __sparse_cache *source, - const struct comp_buffer __sparse_cache *sink) -{ - struct src_param *sp; - struct src_stage *s1; - struct src_stage *s2; - int frames_src; - int frames_snk; - - /* Get SRC parameters */ - sp = &cd->param; - s1 = cd->src.stage1; - s2 = cd->src.stage2; - - /* Calculate how many blocks can be processed with - * available source and free sink frames amount. - */ - if (s2->filter_length > 1) { - /* Two polyphase filters case */ - frames_snk = audio_stream_get_free_frames(&sink->stream); - frames_snk = MIN(frames_snk, cd->sink_frames + s2->blk_out); - sp->stage2_times = frames_snk / s2->blk_out; - frames_src = audio_stream_get_avail_frames(&source->stream); - frames_src = MIN(frames_src, cd->source_frames + s1->blk_in); - sp->stage1_times = frames_src / s1->blk_in; - sp->blk_in = sp->stage1_times * s1->blk_in; - sp->blk_out = sp->stage2_times * s2->blk_out; - } else { - /* Single polyphase filter case */ - frames_snk = audio_stream_get_free_frames(&sink->stream); - frames_snk = MIN(frames_snk, cd->sink_frames + s1->blk_out); - sp->stage1_times = frames_snk / s1->blk_out; - frames_src = audio_stream_get_avail_frames(&source->stream); - sp->stage1_times = MIN(sp->stage1_times, - frames_src / s1->blk_in); - sp->blk_in = sp->stage1_times * s1->blk_in; - sp->blk_out = sp->stage1_times * s1->blk_out; - } - - if (sp->blk_in == 0 && sp->blk_out == 0) - return -EIO; - - return 0; -} - static void src_process(struct comp_dev *dev, struct comp_buffer __sparse_cache *source, struct comp_buffer __sparse_cache *sink) { @@ -918,48 +960,6 @@ static int src_copy(struct comp_dev *dev) return 0; } -static int src_check_buffer_sizes(struct comp_data *cd, - struct audio_stream __sparse_cache *source_stream, - struct audio_stream __sparse_cache *sink_stream) -{ - struct src_stage *s1 = cd->src.stage1; - struct src_stage *s2 = cd->src.stage2; - int stage1_times; - int stage2_times; - int blk_in; - int blk_out; - int n; - - if (s2->filter_length > 1) { - /* Two polyphase filters case */ - stage2_times = ceil_divide(cd->sink_frames, s2->blk_out); - stage1_times = ceil_divide(cd->source_frames, s1->blk_in); - blk_in = stage1_times * s1->blk_in; - blk_out = stage2_times * s2->blk_out; - } else { - /* Single polyphase filter case */ - stage1_times = ceil_divide(cd->sink_frames, s1->blk_out); - n = ceil_divide(cd->source_frames, s1->blk_in); - stage1_times = MAX(stage1_times, n); - blk_in = stage1_times * s1->blk_in; - blk_out = stage1_times * s1->blk_out; - } - - n = audio_stream_frame_bytes(source_stream) * (blk_in + cd->source_frames); - if (source_stream->size < n) { - comp_cl_warn(&comp_src, "Source size %d is less than required %d", - source_stream->size, n); - } - - n = audio_stream_frame_bytes(sink_stream) * (blk_out + cd->sink_frames); - if (sink_stream->size < n) { - comp_cl_warn(&comp_src, "Sink size %d is less than required %d", - sink_stream->size, n); - } - - return 0; -} - static int src_prepare(struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); From 13254fc1dd5c0bca3a95d51a78f7824abba11f7d Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Mon, 28 Nov 2022 15:11:24 +0800 Subject: [PATCH 5/6] src: change some functions to fit the module adapter Due to add module adapter feature, some functions needs to be changed to fit it. Signed-off-by: Gongjun Song --- src/audio/src/src.c | 308 +++++++++++++++++--------------- src/include/sof/audio/src/src.h | 3 - 2 files changed, 163 insertions(+), 148 deletions(-) diff --git a/src/audio/src/src.c b/src/audio/src/src.c index f07ff177a01a..dfed8c43ffa7 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -97,6 +97,7 @@ struct comp_data { int sink_frames; int sample_container_bytes; void (*src_func)(struct comp_dev *dev, + struct comp_data *cd, const struct audio_stream __sparse_cache *source, struct audio_stream __sparse_cache *sink, int *consumed, @@ -130,17 +131,25 @@ static int src_find_fs(int fs_list[], int list_length, int fs) } /* Calculates buffers to allocate for a SRC mode */ -int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch, - int source_frames) +static int src_buffer_lengths(struct comp_dev *dev, struct comp_data *cd, + int nch) { struct src_stage *stage1; struct src_stage *stage2; + struct src_param *a; + int fs_in, fs_out; + int source_frames; int r1; + a = &cd->param; + fs_in = cd->source_rate; + fs_out = cd->sink_rate; + source_frames = cd->source_frames; + if (nch > PLATFORM_MAX_CHANNELS) { /* TODO: should be device, not class */ - comp_cl_err(&comp_src, "src_buffer_lengths(): nch = %u > PLATFORM_MAX_CHANNELS", - nch); + comp_err(dev, "src_buffer_lengths(): nch = %u > PLATFORM_MAX_CHANNELS", + nch); return -EINVAL; } @@ -150,8 +159,8 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch, /* Check that both in and out rates are supported */ if (a->idx_in < 0 || a->idx_out < 0) { - comp_cl_err(&comp_src, "src_buffer_lengths(): rates not supported, fs_in: %u, fs_out: %u", - fs_in, fs_out); + comp_err(dev, "src_buffer_lengths(): rates not supported, fs_in: %u, fs_out: %u", + fs_in, fs_out); return -EINVAL; } @@ -160,8 +169,8 @@ int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch, /* Check from stage1 parameter for a deleted in/out rate combination.*/ if (stage1->filter_length < 1) { - comp_cl_err(&comp_src, "src_buffer_lengths(): Non-supported combination sfs_in = %d, fs_out = %d", - fs_in, fs_out); + comp_err(dev, "src_buffer_lengths(): Non-supported combination sfs_in = %d, fs_out = %d", + fs_in, fs_out); return -EINVAL; } @@ -325,7 +334,7 @@ int src_polyphase_init(struct polyphase_src *src, struct src_param *p, } /* Fallback function */ -static void src_fallback(struct comp_dev *dev, +static void src_fallback(struct comp_dev *dev, struct comp_data *cd, const struct audio_stream __sparse_cache *source, struct audio_stream __sparse_cache *sink, int *n_read, int *n_written) { @@ -334,7 +343,8 @@ static void src_fallback(struct comp_dev *dev, } /* Normal 2 stage SRC */ -static void src_2s(struct comp_dev *dev, const struct audio_stream __sparse_cache *source, +static void src_2s(struct comp_dev *dev, struct comp_data *cd, + const struct audio_stream __sparse_cache *source, struct audio_stream __sparse_cache *sink, int *n_read, int *n_written) { struct src_stage_prm s1; @@ -343,7 +353,6 @@ static void src_2s(struct comp_dev *dev, const struct audio_stream __sparse_cach int s1_blk_out; int s2_blk_in; int s2_blk_out; - struct comp_data *cd = comp_get_drvdata(dev); void *sbuf_addr = cd->delay_lines; void *sbuf_end_addr = &cd->delay_lines[cd->param.sbuf_length]; size_t sbuf_size = cd->param.sbuf_length * sizeof(int32_t); @@ -426,11 +435,11 @@ static void src_2s(struct comp_dev *dev, const struct audio_stream __sparse_cach } /* 1 stage SRC for simple conversions */ -static void src_1s(struct comp_dev *dev, const struct audio_stream __sparse_cache *source, +static void src_1s(struct comp_dev *dev, struct comp_data *cd, + const struct audio_stream __sparse_cache *source, struct audio_stream __sparse_cache *sink, int *n_read, int *n_written) { struct src_stage_prm s1; - struct comp_data *cd = comp_get_drvdata(dev); s1.times = cd->param.stage1_times; s1.x_rptr = source->r_ptr; @@ -451,12 +460,11 @@ static void src_1s(struct comp_dev *dev, const struct audio_stream __sparse_cach } /* A fast copy function for same in and out rate */ -static void src_copy_sxx(struct comp_dev *dev, +static void src_copy_sxx(struct comp_dev *dev, struct comp_data *cd, const struct audio_stream __sparse_cache *source, struct audio_stream __sparse_cache *sink, int *n_read, int *n_written) { - struct comp_data *cd = comp_get_drvdata(dev); int frames = cd->param.blk_in; switch (sink->frame_fmt) { @@ -576,10 +584,9 @@ static void src_set_sink_params(struct comp_dev *dev, struct comp_buffer __spars #error "No or invalid IPC MAJOR version selected." #endif /* CONFIG_IPC_MAJOR_4 */ -static int src_verify_params(struct comp_dev *dev, +static int src_verify_params(struct comp_dev *dev, struct comp_data *cd, struct sof_ipc_stream_params *params) { - struct comp_data *cd = comp_get_drvdata(dev); int ret; comp_dbg(dev, "src_verify_params()"); @@ -658,7 +665,7 @@ static int src_get_copy_limits(struct comp_data *cd, return 0; } -static int src_check_buffer_sizes(struct comp_data *cd, +static int src_check_buffer_sizes(struct comp_dev *dev, struct comp_data *cd, struct audio_stream __sparse_cache *source_stream, struct audio_stream __sparse_cache *sink_stream) { @@ -687,75 +694,22 @@ static int src_check_buffer_sizes(struct comp_data *cd, n = audio_stream_frame_bytes(source_stream) * (blk_in + cd->source_frames); if (source_stream->size < n) { - comp_cl_warn(&comp_src, "Source size %d is less than required %d", - source_stream->size, n); + comp_warn(dev, "Source size %d is less than required %d", + source_stream->size, n); } n = audio_stream_frame_bytes(sink_stream) * (blk_out + cd->sink_frames); if (sink_stream->size < n) { - comp_cl_warn(&comp_src, "Sink size %d is less than required %d", - sink_stream->size, n); + comp_warn(dev, "Sink size %d is less than required %d", + sink_stream->size, n); } return 0; } -static struct comp_dev *src_new(const struct comp_driver *drv, - const struct comp_ipc_config *config, - const void *spec) -{ - struct comp_dev *dev; - struct comp_data *cd; - - comp_cl_info(&comp_src, "src_new()"); - - /* validate init data - either SRC sink or source rate must be set */ - if (src_rate_check(spec) < 0) { - comp_cl_err(&comp_src, "src_new(): SRC sink and source rate are not set"); - return NULL; - } - - dev = comp_alloc(drv, sizeof(*dev)); - if (!dev) - return NULL; - dev->ipc_config = *config; - - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, cd); - memcpy_s(&cd->ipc_config, sizeof(cd->ipc_config), spec, sizeof(cd->ipc_config)); - - cd->delay_lines = NULL; - cd->src_func = src_fallback; - cd->polyphase_func = NULL; - src_polyphase_reset(&cd->src); - - dev->state = COMP_STATE_READY; - return dev; -} - -static void src_free(struct comp_dev *dev) +static int src_params_general(struct comp_dev *dev, struct comp_data *cd, + struct sof_ipc_stream_params *params) { - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "src_free()"); - - /* Free dynamically reserved buffers for SRC algorithm */ - rfree(cd->delay_lines); - - rfree(cd); - rfree(dev); -} - -/* set component audio stream parameters */ -static int src_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct comp_data *cd = comp_get_drvdata(dev); struct comp_buffer *sourceb, *sinkb; struct comp_buffer __sparse_cache *source_c, *sink_c; size_t delay_lines_size; @@ -766,7 +720,7 @@ static int src_params(struct comp_dev *dev, comp_info(dev, "src_params()"); src_set_params(dev, params); - err = src_verify_params(dev, params); + err = src_verify_params(dev, cd, params); if (err < 0) { comp_err(dev, "src_params(): pcm params verification failed."); return -EINVAL; @@ -803,8 +757,7 @@ static int src_params(struct comp_dev *dev, cd->source_rate, cd->sink_rate, source_c->stream.frame_fmt); comp_info(dev, "src_params(), sourceb->channels = %u, sinkb->channels = %u, dev->frames = %u", source_c->stream.channels, sink_c->stream.channels, dev->frames); - err = src_buffer_lengths(&cd->param, cd->source_rate, cd->sink_rate, - source_c->stream.channels, cd->source_frames); + err = src_buffer_lengths(dev, cd, source_c->stream.channels); if (err < 0) { comp_err(dev, "src_params(): src_buffer_lengths() failed"); goto out; @@ -868,6 +821,134 @@ static int src_params(struct comp_dev *dev, return err; } +static int src_prepare_general(struct comp_dev *dev, struct comp_data *cd) +{ + struct comp_buffer *sourceb, *sinkb; + struct comp_buffer __sparse_cache *source_c, *sink_c; + enum sof_ipc_frame source_format; + enum sof_ipc_frame sink_format; + int ret; + + /* SRC component will only ever have 1 source and 1 sink buffer */ + sourceb = list_first_item(&dev->bsource_list, + struct comp_buffer, sink_list); + sinkb = list_first_item(&dev->bsink_list, + struct comp_buffer, source_list); + + source_c = buffer_acquire(sourceb); + sink_c = buffer_acquire(sinkb); + + /* get source/sink data format */ + source_format = source_c->stream.frame_fmt; + sink_format = sink_c->stream.frame_fmt; + + ret = src_check_buffer_sizes(dev, cd, &source_c->stream, &sink_c->stream); + if (ret < 0) + goto out; + + /* SRC supports S16_LE, S24_4LE and S32_LE formats */ + if (source_format != sink_format) { + comp_err(dev, "src_prepare(): Source fmt %d and sink fmt %d are different.", + source_format, sink_format); + ret = -EINVAL; + goto out; + } + + switch (source_format) { +#if CONFIG_FORMAT_S16LE + case SOF_IPC_FRAME_S16_LE: + cd->data_shift = 0; + cd->polyphase_func = src_polyphase_stage_cir_s16; + break; +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + case SOF_IPC_FRAME_S24_4LE: + cd->data_shift = 8; + cd->polyphase_func = src_polyphase_stage_cir; + break; +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + case SOF_IPC_FRAME_S32_LE: + cd->data_shift = 0; + cd->polyphase_func = src_polyphase_stage_cir; + break; +#endif /* CONFIG_FORMAT_S32LE */ + default: + comp_err(dev, "src_prepare(): invalid format %d", source_format); + ret = -EINVAL; + goto out; + } + +out: + if (ret < 0) + comp_set_state(dev, COMP_TRIGGER_RESET); + + buffer_release(sink_c); + buffer_release(source_c); + + return ret; +} + +static struct comp_dev *src_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + struct comp_dev *dev; + struct comp_data *cd; + + comp_cl_info(&comp_src, "src_new()"); + + /* validate init data - either SRC sink or source rate must be set */ + if (src_rate_check(spec) < 0) { + comp_cl_err(&comp_src, "src_new(): SRC sink and source rate are not set"); + return NULL; + } + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); + if (!cd) { + rfree(dev); + return NULL; + } + + comp_set_drvdata(dev, cd); + memcpy_s(&cd->ipc_config, sizeof(cd->ipc_config), spec, sizeof(cd->ipc_config)); + + cd->delay_lines = NULL; + cd->src_func = src_fallback; + cd->polyphase_func = NULL; + src_polyphase_reset(&cd->src); + + dev->state = COMP_STATE_READY; + return dev; +} + +static void src_free(struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + comp_info(dev, "src_free()"); + + /* Free dynamically reserved buffers for SRC algorithm */ + rfree(cd->delay_lines); + + rfree(cd); + rfree(dev); +} + +/* set component audio stream parameters */ +static int src_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) +{ + struct comp_data *cd = comp_get_drvdata(dev); + + return src_params_general(dev, cd, params); +} + static int src_ctrl_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) { comp_err(dev, "src_ctrl_cmd()"); @@ -913,7 +994,7 @@ static void src_process(struct comp_dev *dev, struct comp_buffer __sparse_cache /* consumed bytes are not known at this point */ buffer_stream_invalidate(source, source->stream.size); - cd->src_func(dev, &source->stream, &sink->stream, &consumed, &produced); + cd->src_func(dev, cd, &source->stream, &sink->stream, &consumed, &produced); buffer_stream_writeback(sink, produced * audio_stream_frame_bytes(&sink->stream)); comp_dbg(dev, "src_copy(), consumed = %u, produced = %u", @@ -963,10 +1044,6 @@ static int src_copy(struct comp_dev *dev) static int src_prepare(struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *sourceb, *sinkb; - struct comp_buffer __sparse_cache *source_c, *sink_c; - enum sof_ipc_frame source_format; - enum sof_ipc_frame sink_format; int ret; comp_info(dev, "src_prepare()"); @@ -978,66 +1055,7 @@ static int src_prepare(struct comp_dev *dev) if (ret == COMP_STATUS_STATE_ALREADY_SET) return PPL_STATUS_PATH_STOP; - /* SRC component will only ever have 1 source and 1 sink buffer */ - sourceb = list_first_item(&dev->bsource_list, - struct comp_buffer, sink_list); - sinkb = list_first_item(&dev->bsink_list, - struct comp_buffer, source_list); - - source_c = buffer_acquire(sourceb); - sink_c = buffer_acquire(sinkb); - - /* get source data format */ - source_format = source_c->stream.frame_fmt; - - /* get sink data format */ - sink_format = sink_c->stream.frame_fmt; - - ret = src_check_buffer_sizes(cd, &source_c->stream, &sink_c->stream); - if (ret < 0) - goto out; - - /* SRC supports S16_LE, S24_4LE and S32_LE formats */ - if (source_format != sink_format) { - comp_err(dev, "src_prepare(): Source fmt %d and sink fmt %d are different.", - source_format, sink_format); - ret = -EINVAL; - goto out; - } - - switch (source_format) { -#if CONFIG_FORMAT_S16LE - case SOF_IPC_FRAME_S16_LE: - cd->data_shift = 0; - cd->polyphase_func = src_polyphase_stage_cir_s16; - break; -#endif /* CONFIG_FORMAT_S16LE */ -#if CONFIG_FORMAT_S24LE - case SOF_IPC_FRAME_S24_4LE: - cd->data_shift = 8; - cd->polyphase_func = src_polyphase_stage_cir; - break; -#endif /* CONFIG_FORMAT_S24LE */ -#if CONFIG_FORMAT_S32LE - case SOF_IPC_FRAME_S32_LE: - cd->data_shift = 0; - cd->polyphase_func = src_polyphase_stage_cir; - break; -#endif /* CONFIG_FORMAT_S32LE */ - default: - comp_err(dev, "src_prepare(): invalid format %d", source_format); - ret = -EINVAL; - goto out; - } - -out: - if (ret < 0) - comp_set_state(dev, COMP_TRIGGER_RESET); - - buffer_release(sink_c); - buffer_release(source_c); - - return ret; + return src_prepare_general(dev, cd); } static int src_reset(struct comp_dev *dev) diff --git a/src/include/sof/audio/src/src.h b/src/include/sof/audio/src/src.h index 03d1a345d1d5..6fa936fc74eb 100644 --- a/src/include/sof/audio/src/src.h +++ b/src/include/sof/audio/src/src.h @@ -115,9 +115,6 @@ void src_polyphase_stage_cir(struct src_stage_prm *s); void src_polyphase_stage_cir_s16(struct src_stage_prm *s); #endif /* CONFIG_FORMAT_S16LE */ -int src_buffer_lengths(struct src_param *a, int fs_in, int fs_out, int nch, - int source_frames); - int32_t src_input_rates(void); int32_t src_output_rates(void); From 3ed352fc45fd5771248a528c0a338d211064f24d Mon Sep 17 00:00:00 2001 From: Gongjun Song Date: Mon, 28 Nov 2022 15:22:02 +0800 Subject: [PATCH 6/6] src: convert the SRC component to use the module interface Adopt module interface for src component. IPC3 has compatibility issues, it continues to use comp_driver. Convert to module adapter only for IPC4. Signed-off-by: Gongjun Song --- src/audio/src/src.c | 215 ++++++++++++++++++++++++++++++++++++++------ zephyr/wrapper.c | 9 +- 2 files changed, 195 insertions(+), 29 deletions(-) diff --git a/src/audio/src/src.c b/src/audio/src/src.c index dfed8c43ffa7..2b56dec6df39 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -54,15 +55,21 @@ #define MAX_FIR_DELAY_SIZE_XNCH (PLATFORM_MAX_CHANNELS * MAX_FIR_DELAY_SIZE) #define MAX_OUT_DELAY_SIZE_XNCH (PLATFORM_MAX_CHANNELS * MAX_OUT_DELAY_SIZE) -static const struct comp_driver comp_src; - LOG_MODULE_REGISTER(src, CONFIG_SOF_LOG_LEVEL); #if CONFIG_IPC_MAJOR_4 +/* src component private data */ +struct ipc4_config_src { + struct ipc4_base_module_cfg base; + uint32_t sink_rate; +}; + /* e61bb28d-149a-4c1f-b709-46823ef5f5a3 */ DECLARE_SOF_RT_UUID("src", src_uuid, 0xe61bb28d, 0x149a, 0x4c1f, 0xb7, 0x09, 0x46, 0x82, 0x3e, 0xf5, 0xf5, 0xae); #elif CONFIG_IPC_MAJOR_3 +static const struct comp_driver comp_src; + /* c1c5326d-8390-46b4-aa47-95c3beca6550 */ DECLARE_SOF_RT_UUID("src", src_uuid, 0xc1c5326d, 0x8390, 0x46b4, 0xaa, 0x47, 0x95, 0xc3, 0xbe, 0xca, 0x65, 0x50); @@ -72,12 +79,6 @@ DECLARE_SOF_RT_UUID("src", src_uuid, 0xc1c5326d, 0x8390, 0x46b4, DECLARE_TR_CTX(src_tr, SOF_UUID(src_uuid), LOG_LEVEL_INFO); -/* src component private data */ -struct ipc4_config_src { - struct ipc4_base_module_cfg base; - uint32_t sink_rate; -}; - struct comp_data { #if CONFIG_IPC_MAJOR_4 struct ipc4_config_src ipc_config; @@ -483,21 +484,6 @@ static void src_copy_sxx(struct comp_dev *dev, struct comp_data *cd, } #if CONFIG_IPC_MAJOR_4 -static int src_get_attribute(struct comp_dev *dev, uint32_t type, void *value) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - switch (type) { - case COMP_ATTR_BASE_CONFIG: - *(struct ipc4_base_module_cfg *)value = cd->ipc_config.base; - break; - default: - return -EINVAL; - } - - return 0; -} - static int src_rate_check(const void *spec) { const struct ipc4_config_src *ipc_src = spec; @@ -524,7 +510,8 @@ static int src_stream_pcm_source_rate_check(struct ipc4_config_src cfg, */ static void src_set_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { - struct comp_data *cd = comp_get_drvdata(dev); + struct processing_module *mod = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); struct comp_buffer *sinkb; struct comp_buffer __sparse_cache *sink_c; @@ -545,7 +532,8 @@ static void src_set_params(struct comp_dev *dev, struct sof_ipc_stream_params *p static void src_set_sink_params(struct comp_dev *dev, struct comp_buffer __sparse_cache *sinkb) { - struct comp_data *cd = comp_get_drvdata(dev); + struct processing_module *mod = comp_get_drvdata(dev); + struct comp_data *cd = module_get_private_data(mod); /* convert IPC4 config to format used by the module */ audio_stream_fmt_conversion(cd->ipc_config.base.audio_fmt.depth, @@ -557,6 +545,27 @@ static void src_set_sink_params(struct comp_dev *dev, struct comp_buffer __spars sinkb->buffer_fmt = cd->ipc_config.base.audio_fmt.interleaving_style; } +static inline void src_update_buffer_position(struct input_stream_buffer *input_buffers, + struct output_stream_buffer *output_buffers, + int *n_read, int *n_written) +{ + struct audio_stream __sparse_cache *source = input_buffers->data; + struct audio_stream __sparse_cache *sink = output_buffers->data; + + input_buffers->consumed += audio_stream_frame_bytes(source) * (*n_read); + output_buffers->size += audio_stream_frame_bytes(sink) * (*n_written); +} + +static void src_set_alignment(struct audio_stream __sparse_cache *source, + struct audio_stream __sparse_cache *sink) +{ + const uint32_t byte_align = 1; + const uint32_t frame_align_req = 1; + + audio_stream_init_alignment_constants(byte_align, frame_align_req, source); + audio_stream_init_alignment_constants(byte_align, frame_align_req, sink); +} + #elif CONFIG_IPC_MAJOR_3 static int src_rate_check(const void *spec) { @@ -838,6 +847,11 @@ static int src_prepare_general(struct comp_dev *dev, struct comp_data *cd) source_c = buffer_acquire(sourceb); sink_c = buffer_acquire(sinkb); +#if CONFIG_IPC_MAJOR_4 + /* set align requirements */ + src_set_alignment(&source_c->stream, &sink_c->stream); +#endif + /* get source/sink data format */ source_format = source_c->stream.frame_fmt; sink_format = sink_c->stream.frame_fmt; @@ -889,6 +903,151 @@ static int src_prepare_general(struct comp_dev *dev, struct comp_data *cd) return ret; } +#if CONFIG_IPC_MAJOR_4 +static int src_init(struct processing_module *mod) +{ + struct module_data *md = &mod->priv; + struct module_config *cfg = &md->cfg; + struct comp_dev *dev = mod->dev; + struct comp_data *cd = NULL; + + comp_dbg(dev, "src_init()"); + + /* validate init data - either SRC sink or source rate must be set */ + if (src_rate_check(cfg->init_data) < 0) { + comp_err(dev, "src_init(): SRC sink and source rate are not set"); + return -EINVAL; + } + + cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); + if (!cd) { + rfree(dev); + return -ENOMEM; + } + + memcpy_s(&cd->ipc_config, sizeof(cd->ipc_config), cfg->init_data, sizeof(cd->ipc_config)); + + cd->delay_lines = NULL; + cd->src_func = src_fallback; + cd->polyphase_func = NULL; + src_polyphase_reset(&cd->src); + + md->private = cd; + + mod->simple_copy = true; + + return 0; +} + +static int src_prepare(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_dev *dev = mod->dev; + int ret; + + comp_info(dev, "src_prepare()"); + + ret = src_params_general(dev, cd, params); + if (ret < 0) + return ret; + + return src_prepare_general(dev, cd); +} + +static int src_process(struct processing_module *mod, + struct input_stream_buffer *input_buffers, int num_input_buffers, + struct output_stream_buffer *output_buffers, int num_output_buffers) +{ + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *source, *sink; + struct comp_buffer __sparse_cache *source_c, *sink_c; + int consumed = 0; + int produced = 0; + int ret; + + comp_dbg(dev, "src_process()"); + + /* src component needs 1 source and 1 sink buffer */ + source = list_first_item(&dev->bsource_list, struct comp_buffer, + sink_list); + sink = list_first_item(&dev->bsink_list, struct comp_buffer, + source_list); + + source_c = buffer_acquire(source); + sink_c = buffer_acquire(sink); + + ret = src_get_copy_limits(cd, source_c, sink_c); + if (ret) { + comp_dbg(dev, "No data to process."); + goto out; + } + + cd->src_func(dev, cd, &source_c->stream, &sink_c->stream, &consumed, &produced); + src_update_buffer_position(input_buffers, output_buffers, &consumed, &produced); + + comp_dbg(dev, "src_process(), consumed = %u, produced = %u", consumed, produced); + +out: + buffer_release(sink_c); + buffer_release(source_c); + + return 0; +} + +static int src_set_config(struct processing_module *mod, uint32_t config_id, + enum module_cfg_fragment_position pos, uint32_t data_offset_size, + const uint8_t *fragment, size_t fragment_size, uint8_t *response, + size_t response_size) +{ + return -EINVAL; +} + +static int src_get_config(struct processing_module *mod, uint32_t config_id, + uint32_t *data_offset_size, uint8_t *fragment, size_t fragment_size) +{ + return -EINVAL; +} + +static int src_reset(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "src_reset()"); + + cd->src_func = src_fallback; + src_polyphase_reset(&cd->src); + + return 0; +} + +static int src_free(struct processing_module *mod) +{ + struct comp_data *cd = module_get_private_data(mod); + + comp_info(mod->dev, "src_free()"); + + /* Free dynamically reserved buffers for SRC algorithm */ + rfree(cd->delay_lines); + + rfree(cd); + return 0; +} + +static struct module_interface src_interface = { + .init = src_init, + .prepare = src_prepare, + .process = src_process, + .set_configuration = src_set_config, + .get_configuration = src_get_config, + .reset = src_reset, + .free = src_free, +}; + +DECLARE_MODULE_ADAPTER(src_interface, src_uuid, src_tr); + +#elif CONFIG_IPC_MAJOR_3 static struct comp_dev *src_new(const struct comp_driver *drv, const struct comp_ipc_config *config, const void *spec) @@ -1084,9 +1243,6 @@ static const struct comp_driver comp_src = { .copy = src_copy, .prepare = src_prepare, .reset = src_reset, -#if CONFIG_IPC_MAJOR_4 - .get_attribute = src_get_attribute, -#endif }, }; @@ -1101,3 +1257,6 @@ UT_STATIC void sys_comp_src_init(void) } DECLARE_MODULE(sys_comp_src_init); +#else +#error "No or invalid IPC MAJOR version selected." +#endif diff --git a/zephyr/wrapper.c b/zephyr/wrapper.c index e715a120abd2..a0b4b380b210 100644 --- a/zephyr/wrapper.c +++ b/zephyr/wrapper.c @@ -191,8 +191,10 @@ void sys_comp_dai_init(void); void sys_comp_src_init(void); void sys_comp_mux_init(void); #if CONFIG_IPC_MAJOR_3 +void sys_comp_src_init(void); void sys_comp_selector_init(void); #else +void sys_comp_module_src_interface_init(void); void sys_comp_module_selector_interface_init(void); #endif void sys_comp_switch_init(void); @@ -286,8 +288,13 @@ int task_main_start(struct sof *sof) if (IS_ENABLED(CONFIG_COMP_DAI)) sys_comp_dai_init(); - if (IS_ENABLED(CONFIG_COMP_SRC)) + if (IS_ENABLED(CONFIG_COMP_SRC)) { +#if CONFIG_IPC_MAJOR_3 sys_comp_src_init(); +#else + sys_comp_module_src_interface_init(); +#endif + } if (IS_ENABLED(CONFIG_COMP_SEL)) #if CONFIG_IPC_MAJOR_3