From 8206aa82c04a92fc3e856360849696a26968bcce Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Fri, 2 Oct 2026 17:31:53 +0200 Subject: [PATCH 1/2] module: audio: add sink/source buffer resize API Add sink_set_size() and source_set_size() backed by a new optional set_size op in struct sink_ops / source_ops, allowing a module to grow the buffer behind a sink or source after allocation. Signed-off-by: Adrian Warecki --- src/audio/buffers/comp_buffer.c | 16 ++++++++++++++++ src/include/module/audio/sink_api.h | 15 +++++++++++++++ src/include/module/audio/source_api.h | 15 +++++++++++++++ src/module/audio/sink_api.c | 8 ++++++++ src/module/audio/source_api.c | 8 ++++++++ 5 files changed, 62 insertions(+) diff --git a/src/audio/buffers/comp_buffer.c b/src/audio/buffers/comp_buffer.c index f86328e244b3..6305e75022fe 100644 --- a/src/audio/buffers/comp_buffer.c +++ b/src/audio/buffers/comp_buffer.c @@ -115,6 +115,20 @@ static int comp_buffer_source_get_state(struct sof_source *source) return comp_get_state(comp_buffer_get_source_component(buffer)); } +static int comp_buffer_sink_set_size(struct sof_sink *sink, size_t size) +{ + struct comp_buffer *buffer = comp_buffer_get_from_sink(sink); + + return buffer_set_size(buffer, size, buffer->stream.byte_align_req); +} + +static int comp_buffer_source_set_size(struct sof_source *source, size_t size) +{ + struct comp_buffer *buffer = comp_buffer_get_from_source(source); + + return buffer_set_size(buffer, size, buffer->stream.byte_align_req); +} + static int comp_buffer_set_ipc_params(struct sof_audio_buffer *audio_buffer, struct sof_ipc_stream_params *params, bool force_update) @@ -195,6 +209,7 @@ APP_TASK_DATA static const struct source_ops comp_buffer_source_ops = { .on_audio_format_set = audio_buffer_source_on_audio_format_set, .set_alignment_constants = audio_buffer_source_set_alignment_constants, .get_state = comp_buffer_source_get_state, + .set_size = comp_buffer_source_set_size, }; APP_TASK_DATA static const struct sink_ops comp_buffer_sink_ops = { @@ -206,6 +221,7 @@ APP_TASK_DATA static const struct sink_ops comp_buffer_sink_ops = { .set_alignment_constants = audio_buffer_sink_set_alignment_constants, .get_lft = audio_buffer_sink_get_lft, .get_state = comp_buffer_sink_get_state, + .set_size = comp_buffer_sink_set_size, }; static const struct audio_buffer_ops audio_buffer_ops = { diff --git a/src/include/module/audio/sink_api.h b/src/include/module/audio/sink_api.h index 3101c960c803..cf33aa65cb59 100644 --- a/src/include/module/audio/sink_api.h +++ b/src/include/module/audio/sink_api.h @@ -116,6 +116,12 @@ struct sink_ops { const uint32_t byte_align, const uint32_t frame_align_req); + /** + * OPTIONAL + * see comment for sink_set_size + */ + int (*set_size)(struct sof_sink *sink, size_t size); + /** * OPTIONAL * events called when a module is starting / finishing using of the API @@ -303,6 +309,15 @@ int sink_set_alignment_constants(struct sof_sink *sink, const uint32_t byte_align, const uint32_t frame_align_req); +/** + * Resize the buffer backing the sink. + * + * @param sink a handler to sink + * @param size requested buffer size in bytes + * @return 0 on success, -ENOSYS if the sink implementation does not support resizing + */ +int sink_set_size(struct sof_sink *sink, size_t size); + int sink_set_valid_fmt(struct sof_sink *sink, enum sof_ipc_frame valid_sample_fmt); int sink_set_rate(struct sof_sink *sink, unsigned int rate); int sink_set_channels(struct sof_sink *sink, unsigned int channels); diff --git a/src/include/module/audio/source_api.h b/src/include/module/audio/source_api.h index 33497ba136fc..80a778e7e90a 100644 --- a/src/include/module/audio/source_api.h +++ b/src/include/module/audio/source_api.h @@ -112,6 +112,12 @@ struct source_ops { const uint32_t byte_align, const uint32_t frame_align_req); + /** + * OPTIONAL + * see comment for source_set_size + */ + int (*set_size)(struct sof_source *source, size_t size); + /** * OPTIONAL * events called when a module is starting / finishing using of the API @@ -265,6 +271,15 @@ int source_get_data_s32(struct sof_source *source, size_t req_size, int32_t cons */ int source_release_data(struct sof_source *source, size_t free_size); +/** + * Resize the buffer backing the source. + * + * @param source a handler to source + * @param size requested buffer size in bytes + * @return 0 on success, -ENOSYS if the source implementation does not support resizing + */ +int source_set_size(struct sof_source *source, size_t size); + /** set of functions for retrieve audio parameters */ static inline enum sof_ipc_frame source_get_valid_fmt(struct sof_source *source) { diff --git a/src/module/audio/sink_api.c b/src/module/audio/sink_api.c index 969b37f5a987..6f8f2a18a94d 100644 --- a/src/module/audio/sink_api.c +++ b/src/module/audio/sink_api.c @@ -178,3 +178,11 @@ int sink_set_alignment_constants(struct sof_sink *sink, const uint32_t byte_alig return 0; } EXPORT_SYMBOL(sink_set_alignment_constants); + +int sink_set_size(struct sof_sink *sink, size_t size) +{ + if (sink->ops->set_size) + return sink->ops->set_size(sink, size); + return -ENOSYS; +} +EXPORT_SYMBOL(sink_set_size); diff --git a/src/module/audio/source_api.c b/src/module/audio/source_api.c index 6ee2c54ed8d3..e0f98ed9f4f2 100644 --- a/src/module/audio/source_api.c +++ b/src/module/audio/source_api.c @@ -106,3 +106,11 @@ size_t source_get_data_frames_available(struct sof_source *source) return 0; } EXPORT_SYMBOL(source_get_data_frames_available); + +int source_set_size(struct sof_source *source, size_t size) +{ + if (source->ops->set_size) + return source->ops->set_size(source, size); + return -ENOSYS; +} +EXPORT_SYMBOL(source_set_size); From 6421b53df3bb04a0a144918e295f76b0b1c2c8d2 Mon Sep 17 00:00:00 2001 From: Adrian Warecki Date: Fri, 2 Oct 2026 17:31:30 +0200 Subject: [PATCH 2/2] module: cadence: rework module to use sink/source api Rework the cadence ipc3 module variant to only use the sink/source api to prepare sof for the full transition to pipeline 2.0. Signed-off-by: Adrian Warecki --- .../module_adapter/module/cadence_ipc3.c | 143 ++++++++++-------- 1 file changed, 80 insertions(+), 63 deletions(-) diff --git a/src/audio/module_adapter/module/cadence_ipc3.c b/src/audio/module_adapter/module/cadence_ipc3.c index 1afb08fc942a..60e93ac43025 100644 --- a/src/audio/module_adapter/module/cadence_ipc3.c +++ b/src/audio/module_adapter/module/cadence_ipc3.c @@ -49,7 +49,7 @@ static int cadence_codec_init(struct processing_module *mod) struct module_config *setup_cfg; int ret; - comp_dbg(dev, "cadence_codec_init() start"); + comp_dbg(dev, "start"); cd = mod_zalloc(mod, sizeof(struct cadence_codec_data)); if (!cd) { @@ -83,7 +83,7 @@ static int cadence_codec_init(struct processing_module *mod) setup_cfg->avail = true; } - comp_dbg(dev, "cadence_codec_init() done"); + comp_dbg(dev, "done"); return 0; @@ -103,7 +103,7 @@ int cadence_codec_apply_config(struct processing_module *mod) struct module_data *codec = &mod->priv; struct cadence_codec_data *cd = codec->private; - comp_dbg(dev, "cadence_codec_apply_config() start"); + comp_dbg(dev, "start"); cfg = &codec->cfg; @@ -115,25 +115,13 @@ int cadence_codec_apply_config(struct processing_module *mod) size = cfg->size; if (!cfg->avail || !size) { - comp_err(dev, "cadence_codec_apply_config() error: no config available"); + comp_err(dev, "no config available"); return -EIO; } return cadence_codec_apply_params(mod, size, data); } -static int cadence_codec_deep_buff_allowed(struct processing_module *mod) -{ - struct cadence_codec_data *cd = module_get_private_data(mod); - - switch (cd->api_id) { - case CADENCE_CODEC_MP3_ENC_ID: - return 0; - default: - return 1; - } -} - static int cadence_codec_prepare(struct processing_module *mod, struct sof_source **sources, int num_of_sources, struct sof_sink **sinks, int num_of_sinks) @@ -143,7 +131,7 @@ static int cadence_codec_prepare(struct processing_module *mod, struct module_data *codec = &mod->priv; struct cadence_codec_data *cd = codec->private; - comp_dbg(dev, "cadence_codec_prepare() start"); + comp_dbg(dev, "start"); ret = cadence_init_codec_object(mod); if (ret) @@ -151,7 +139,7 @@ static int cadence_codec_prepare(struct processing_module *mod, ret = cadence_codec_apply_config(mod); if (ret) { - comp_err(dev, "cadence_codec_prepare() error %x: failed to apply config", + comp_err(dev, "error %x: failed to apply config", ret); return ret; } @@ -159,14 +147,14 @@ static int cadence_codec_prepare(struct processing_module *mod, /* Allocate memory for the codec */ API_CALL(cd, XA_API_CMD_GET_MEMTABS_SIZE, 0, &mem_tabs_size, ret); if (ret != LIB_NO_ERROR) { - comp_err(dev, "cadence_codec_prepare() error %x: failed to get memtabs size", + comp_err(dev, "error %x: failed to get memtabs size", ret); return ret; } cd->mem_tabs = mod_alloc(mod, mem_tabs_size); if (!cd->mem_tabs) { - comp_err(dev, "cadence_codec_prepare() error: failed to allocate space for memtabs"); + comp_err(dev, "failed to allocate space for memtabs"); return -ENOMEM; } @@ -174,17 +162,25 @@ static int cadence_codec_prepare(struct processing_module *mod, API_CALL(cd, XA_API_CMD_SET_MEMTABS_PTR, 0, cd->mem_tabs, ret); if (ret != LIB_NO_ERROR) { - comp_err(dev, "cadence_codec_prepare() error %x: failed to set memtabs", + comp_err(dev, "error %x: failed to set memtabs", ret); goto free; } ret = cadence_codec_init_memory_tables(mod); if (ret != LIB_NO_ERROR) { - comp_err(dev, "cadence_codec_prepare() error %x: failed to init memory tables", + comp_err(dev, "error %x: failed to init memory tables", ret); goto free; } + + /* grow the sink so a whole decoded frame fits */ + ret = sink_set_size(sinks[0], 2 * codec->mpd.out_buff_size); + if (ret < 0) { + comp_err(dev, "error %d: failed to resize sink", ret); + goto free; + } + /* Check init done status. Note, it may happen that init_done flag will return * false value, this is normal since some codec variants needs input in order to * fully finish initialization. That's why at codec_adapter_copy() we call @@ -200,85 +196,106 @@ static int cadence_codec_prepare(struct processing_module *mod, API_CALL(cd, XA_API_CMD_INIT, XA_CMD_TYPE_INIT_DONE_QUERY, &codec->mpd.init_done, ret); if (ret != LIB_NO_ERROR) { - comp_err(dev, "cadence_codec_init_process() error %x: failed to get lib init status", + comp_err(dev, "error %x: failed to get lib init status", ret); return ret; } #endif - comp_dbg(dev, "cadence_codec_prepare() done"); + comp_dbg(dev, "done"); return 0; free: mod_free(mod, cd->mem_tabs); return ret; } -static int -cadence_codec_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) +static int cadence_codec_process(struct processing_module *mod, + struct sof_source **sources, int num_of_sources, + struct sof_sink **sinks, int num_of_sinks) { - struct comp_buffer *local_buff; struct comp_dev *dev = mod->dev; struct module_data *codec = &mod->priv; - int free_bytes, output_bytes = cadence_codec_get_samples(mod) * - mod->stream_params->sample_container_bytes * - mod->stream_params->channels; - uint32_t remaining = input_buffers[0].size; + const size_t in_size = source_get_data_available(sources[0]); + const size_t output_bytes = cadence_codec_get_samples(mod) * + mod->stream_params->sample_container_bytes * + mod->stream_params->channels; + const size_t out_space = sink_get_free_size(sinks[0]); + const void *source_buffer_start, *src_ptr; + void *sink_buffer_start, *sink_ptr; + size_t buffer_size; int ret; - if (!cadence_codec_deep_buff_allowed(mod)) - mod->deep_buff_bytes = 0; - /* Proceed only if we have enough data to fill the module buffer completely */ - if (input_buffers[0].size < codec->mpd.in_buff_size) { + if (in_size < codec->mpd.in_buff_size) { comp_dbg(dev, "not enough data to process"); return -ENODATA; } if (!codec->mpd.init_done) { - memcpy_s(codec->mpd.in_buff, codec->mpd.in_buff_size, input_buffers[0].data, - codec->mpd.in_buff_size); - codec->mpd.avail = codec->mpd.in_buff_size; + /* Acquire data from the source buffer */ + ret = source_get_data(sources[0], codec->mpd.in_buff_size, &src_ptr, + &source_buffer_start, &buffer_size); + if (ret) { + comp_err(dev, "cannot get data from source buffer"); + return ret; + } + + cadence_copy_data_from_buffer(codec->mpd.in_buff, src_ptr, codec->mpd.in_buff_size, + buffer_size, source_buffer_start); + codec->mpd.avail = codec->mpd.in_buff_size; ret = cadence_codec_init_process(mod); - if (ret) + if (ret) { + source_release_data(sources[0], 0); return ret; + } + + source_release_data(sources[0], codec->mpd.consumed); - remaining -= codec->mpd.consumed; - input_buffers[0].consumed = codec->mpd.consumed; + /* Proceed only if we have enough data to fill the module buffer completely */ + if (in_size - codec->mpd.consumed < codec->mpd.in_buff_size) + return -ENODATA; } /* do not proceed with processing if not enough free space left in the local buffer */ - local_buff = list_first_item(&mod->raw_data_buffers_list, struct comp_buffer, buffers_list); - free_bytes = audio_stream_get_free(&local_buff->stream); - if (free_bytes < output_bytes) + if (out_space < output_bytes) return -ENOSPC; - /* Proceed only if we have enough data to fill the module buffer completely */ - if (remaining < codec->mpd.in_buff_size) - return -ENODATA; + /* Acquire data from the source buffer */ + ret = source_get_data(sources[0], codec->mpd.in_buff_size, &src_ptr, &source_buffer_start, + &buffer_size); + if (ret) { + comp_err(dev, "cannot get data from source buffer"); + return ret; + } - memcpy_s(codec->mpd.in_buff, codec->mpd.in_buff_size, - (uint8_t *)input_buffers[0].data + input_buffers[0].consumed, - codec->mpd.in_buff_size); + cadence_copy_data_from_buffer(codec->mpd.in_buff, src_ptr, codec->mpd.in_buff_size, + buffer_size, source_buffer_start); codec->mpd.avail = codec->mpd.in_buff_size; - comp_dbg(dev, "cadence_codec_process() start"); + comp_dbg(dev, "start"); ret = cadence_codec_process_data(mod, NULL); - if (ret) + if (ret) { + source_release_data(sources[0], 0); + return ret; + } + + ret = sink_get_buffer(sinks[0], codec->mpd.produced, &sink_ptr, &sink_buffer_start, + &buffer_size); + if (ret) { + comp_err(dev, "cannot get sink buffer"); + source_release_data(sources[0], 0); return ret; + } - /* update consumed with the number of samples consumed during init */ - input_buffers[0].consumed += codec->mpd.consumed; - codec->mpd.consumed = input_buffers[0].consumed; + /* Copy the produced samples into the output buffer */ + cadence_copy_data_to_buffer(sink_ptr, codec->mpd.produced, buffer_size, + sink_buffer_start, codec->mpd.out_buff); - /* copy the produced samples into the output buffer */ - memcpy_s(output_buffers[0].data, codec->mpd.produced, codec->mpd.out_buff, - codec->mpd.produced); - output_buffers[0].size = codec->mpd.produced; + source_release_data(sources[0], codec->mpd.consumed); + sink_commit_buffer(sinks[0], codec->mpd.produced); - comp_dbg(dev, "cadence_codec_process() done"); + comp_dbg(dev, "done"); return 0; } @@ -308,7 +325,7 @@ static int cadence_codec_reset(struct processing_module *mod) static const struct module_interface cadence_codec_interface = { .init = cadence_codec_init, .prepare = cadence_codec_prepare, - .process_raw_data = cadence_codec_process, + .process = cadence_codec_process, .set_configuration = cadence_codec_set_configuration, .reset = cadence_codec_reset, .free = cadence_codec_free