diff --git a/src/audio/asrc/asrc.c b/src/audio/asrc/asrc.c index 9f88d6d4b1b6..6f25e15129c5 100644 --- a/src/audio/asrc/asrc.c +++ b/src/audio/asrc/asrc.c @@ -539,9 +539,13 @@ static int asrc_params(struct comp_dev *dev, comp_info(dev, "asrc_params()"); +#if CONFIG_IPC_MAJOR_4 + ipc4_base_module_cfg_to_stream_params(&cd->ipc_config.base, pcm_params); +#endif + err = asrc_verify_params(dev, pcm_params); if (err < 0) { - comp_err(dev, "src_params(): pcm params verification failed."); + comp_err(dev, "asrc_params(): pcm params verification failed."); return -EINVAL; } @@ -553,6 +557,12 @@ static int asrc_params(struct comp_dev *dev, source_c = buffer_acquire(sourceb); sink_c = buffer_acquire(sinkb); +#if CONFIG_IPC_MAJOR_4 + /* update the source/sink buffer formats. Sink rate will be modified below */ + ipc4_update_buffer_format(source_c, &cd->ipc_config.base.audio_fmt); + ipc4_update_buffer_format(sink_c, &cd->ipc_config.base.audio_fmt); +#endif + /* Don't change sink rate if value from IPC is 0 (auto detect) */ if (asrc_get_sink_rate(&cd->ipc_config)) audio_stream_set_rate(&sink_c->stream, asrc_get_sink_rate(&cd->ipc_config)); diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index cd997595352c..d5abcb8422b2 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -44,8 +45,6 @@ #include #endif -static const struct comp_driver comp_copier; - LOG_MODULE_REGISTER(copier, CONFIG_SOF_LOG_LEVEL); /* this id aligns windows driver requirement to support windows driver */ @@ -85,9 +84,6 @@ static int copier_init(struct processing_module *mod) for (i = 0; i < IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; i++) cd->out_fmt[i] = cd->config.out_fmt; - list_init(&dev->bsource_list); - list_init(&dev->bsink_list); - ipc_pipe = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, config->pipeline_id); if (!ipc_pipe) { comp_err(dev, "pipeline %d is not existed", config->pipeline_id); @@ -144,6 +140,9 @@ static int copier_init(struct processing_module *mod) }; dev->direction_set = true; + } else { + /* set max sink count for module copier */ + mod->max_sinks = IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; } dev->direction = cd->direction; @@ -154,43 +153,7 @@ static int copier_init(struct processing_module *mod) return ret; } -static struct comp_dev *copier_new(const struct comp_driver *drv, - const struct comp_ipc_config *config, - const void *spec) -{ - struct comp_dev *dev; - struct processing_module *mod; - struct module_data *md; - int ret; - - comp_cl_dbg(&comp_copier, "copier_new()"); - - mod = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*mod)); - if (!mod) - return NULL; - - dev = comp_alloc(drv, sizeof(*dev)); - if (!dev) - goto error_dev; - - dev->ipc_config = *config; - - comp_set_drvdata(dev, mod); - md = &mod->priv; - mod->dev = dev; - md->cfg.init_data = spec; - - ret = copier_init(mod); - if (!ret) - return dev; - - rfree(dev); -error_dev: - rfree(mod); - return NULL; -} - -static void copier_mod_free(struct processing_module *mod) +static int copier_free(struct processing_module *mod) { struct copier_data *cd = module_get_private_data(mod); struct comp_dev *dev = mod->dev; @@ -211,27 +174,25 @@ static void copier_mod_free(struct processing_module *mod) } rfree(cd); -} -static void copier_free(struct comp_dev *dev) -{ - struct processing_module *mod = comp_get_drvdata(dev); - - copier_mod_free(mod); - - rfree(mod); - rfree(dev); + return 0; } -static int copier_mod_prepare(struct processing_module *mod, - struct sof_source __sparse_cache **sources, int num_of_sources, - struct sof_sink __sparse_cache **sinks, int num_of_sinks) +static int copier_params(struct processing_module *mod); + +static int copier_prepare(struct processing_module *mod, + struct sof_source __sparse_cache **sources, int num_of_sources, + struct sof_sink __sparse_cache **sinks, int num_of_sinks) { struct copier_data *cd = module_get_private_data(mod); struct comp_dev *dev = mod->dev; int ret; - comp_dbg(dev, "copier_prepare()"); + ret = copier_params(mod); + if (ret < 0) + return ret; + + comp_info(dev, "copier_prepare()"); switch (dev->ipc_config.type) { case SOF_COMP_HOST: @@ -267,28 +228,7 @@ static int copier_mod_prepare(struct processing_module *mod, return 0; } -static int copier_prepare(struct comp_dev *dev) -{ - struct processing_module *mod = comp_get_drvdata(dev); - int ret; - - /* cannot configure DAI while active */ - if (dev->state == COMP_STATE_ACTIVE) { - comp_info(dev, "copier_config_prepare(): Component is in active state."); - return 0; - } - - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); - if (ret < 0) - return ret; - - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; - - return copier_mod_prepare(mod, NULL, 0, NULL, 0); -} - -static int copier_mod_reset(struct processing_module *mod) +static int copier_reset(struct processing_module *mod) { struct copier_data *cd = module_get_private_data(mod); struct ipc4_pipeline_registers pipe_reg; @@ -322,18 +262,6 @@ static int copier_mod_reset(struct processing_module *mod) return 0; } -static int copier_reset(struct comp_dev *dev) -{ - struct processing_module *mod = comp_get_drvdata(dev); - int ret; - - ret = copier_mod_reset(mod); - - comp_set_state(dev, COMP_TRIGGER_RESET); - - return ret; -} - static int copier_comp_trigger(struct comp_dev *dev, int cmd) { struct processing_module *mod = comp_get_drvdata(dev); @@ -536,21 +464,59 @@ static int copier_copy_to_sinks(struct copier_data *cd, struct comp_dev *dev, return ret; } -static int copier_module_copy(struct copier_data *cd, struct comp_dev *dev) +static int copier_module_copy(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 copier_data *cd = module_get_private_data(mod); struct comp_buffer __sparse_cache *src_c; struct comp_copy_limits processed_data; - struct comp_buffer *src; - int ret; + int i; - src = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); - src_c = buffer_acquire(src); + if (!num_input_buffers || !num_output_buffers) + return 0; - ret = copier_copy_to_sinks(cd, dev, src_c, &processed_data); + src_c = attr_container_of(input_buffers[0].data, struct comp_buffer __sparse_cache, + stream, __sparse_cache); - buffer_release(src_c); + processed_data.source_bytes = 0; - return ret; + /* convert format and copy to each active sink */ + for (i = 0; i < num_output_buffers; i++) { + struct comp_buffer __sparse_cache *sink_c; + struct comp_dev *sink_dev; + + sink_c = attr_container_of(output_buffers[i].data, + struct comp_buffer __sparse_cache, + stream, __sparse_cache); + sink_dev = sink_c->sink; + processed_data.sink_bytes = 0; + if (sink_dev->state == COMP_STATE_ACTIVE) { + uint32_t samples; + int sink_queue_id; + + sink_queue_id = IPC4_SINK_QUEUE_ID(sink_c->id); + if (sink_queue_id >= IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT) + return -EINVAL; + + /* update corresponding sink format in case it isn't updated */ + ipc4_update_buffer_format(sink_c, &cd->out_fmt[sink_queue_id]); + + comp_get_copy_limits(src_c, sink_c, &processed_data); + + samples = processed_data.frames * + audio_stream_get_channels(output_buffers[i].data); + cd->converter[sink_queue_id](input_buffers[0].data, 0, + output_buffers[i].data, 0, samples); + + output_buffers[i].size = processed_data.sink_bytes; + cd->output_total_data_processed += processed_data.sink_bytes; + } + } + + input_buffers[0].consumed = processed_data.source_bytes; + + return 0; } static int copier_multi_endpoint_dai_copy(struct copier_data *cd, struct comp_dev *dev) @@ -612,12 +578,14 @@ static int copier_multi_endpoint_dai_copy(struct copier_data *cd, struct comp_de * from single stream (for output gateways) so such gateways work kind of like a single * gateway, i.e., produce/consume single stream. */ -static int copier_copy(struct comp_dev *dev) +static int copier_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 processing_module *mod = comp_get_drvdata(dev); struct copier_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; - comp_dbg(dev, "copier_copy()"); + comp_dbg(dev, "copier_process()"); switch (dev->ipc_config.type) { case SOF_COMP_HOST: @@ -636,10 +604,11 @@ static int copier_copy(struct comp_dev *dev) } /* module copier case */ - return copier_module_copy(cd, dev); + return copier_module_copy(mod, input_buffers, num_input_buffers, output_buffers, + num_output_buffers); } -static int copier_mod_params(struct processing_module *mod) +static int copier_params(struct processing_module *mod) { struct sof_ipc_stream_params *params = mod->stream_params; struct copier_data *cd = module_get_private_data(mod); @@ -673,17 +642,6 @@ static int copier_mod_params(struct processing_module *mod) return ret; } -/* configure the DMA params */ -static int copier_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) -{ - struct processing_module *mod = comp_get_drvdata(dev); - - /* will remove once fully convert to module interface in last patch */ - mod->stream_params = params; - - return copier_mod_params(mod); -} - static int copier_set_sink_fmt(struct comp_dev *dev, const void *data, int max_data_size) { @@ -731,7 +689,7 @@ static int copier_set_sink_fmt(struct comp_dev *dev, const void *data, sink_id = IPC4_SINK_QUEUE_ID(sink_c->id); if (sink_id == sink_fmt->sink_id) { - update_buffer_format(sink_c, &sink_fmt->sink_fmt); + ipc4_update_buffer_format(sink_c, &sink_fmt->sink_fmt); buffer_release(sink_c); break; } @@ -799,20 +757,6 @@ static int copier_set_configuration(struct processing_module *mod, } } -static int copier_set_large_config(struct comp_dev *dev, uint32_t param_id, - bool first_block, - bool last_block, - uint32_t data_offset, - const char *data) -{ - struct processing_module *mod = comp_get_drvdata(dev); - - comp_dbg(dev, "copier_set_large_config()"); - - return copier_set_configuration(mod, param_id, MODULE_CFG_FRAGMENT_SINGLE, - data_offset, data, data_offset, NULL, 0); -} - static inline void convert_u64_to_u32s(uint64_t val, uint32_t *val_l, uint32_t *val_h) { *val_l = (uint32_t)(val & 0xffffffff); @@ -905,17 +849,6 @@ static int copier_get_configuration(struct processing_module *mod, return -EINVAL; } -static int copier_get_large_config(struct comp_dev *dev, uint32_t param_id, - bool first_block, - bool last_block, - uint32_t *data_offset, - char *data) -{ - struct processing_module *mod = comp_get_drvdata(dev); - - return copier_get_configuration(mod, param_id, data_offset, data, 0); -} - static uint64_t copier_get_processed_data(struct comp_dev *dev, uint32_t stream_no, bool input) { struct processing_module *mod = comp_get_drvdata(dev); @@ -961,22 +894,6 @@ static uint64_t copier_get_processed_data(struct comp_dev *dev, uint32_t stream_ return ret; } -static int copier_get_attribute(struct comp_dev *dev, uint32_t type, void *value) -{ - struct processing_module *mod = comp_get_drvdata(dev); - struct copier_data *cd = module_get_private_data(mod); - - switch (type) { - case COMP_ATTR_BASE_CONFIG: - *(struct ipc4_base_module_cfg *)value = cd->config.base; - break; - default: - return -EINVAL; - } - - return 0; -} - static int copier_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) { struct processing_module *mod = comp_get_drvdata(dev); @@ -1060,59 +977,42 @@ static int copier_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_para return dai_common_get_hw_params(dd, dev, params, dir); } -static int copier_mod_unbind(struct processing_module *mod, void *data) +static int copier_unbind(struct processing_module *mod, void *data) { struct copier_data *cd = module_get_private_data(mod); struct comp_dev *dev = mod->dev; - struct dai_data *dd = cd->dd[0]; - if (dev->ipc_config.type == SOF_COMP_DAI) + if (dev->ipc_config.type == SOF_COMP_DAI) { + struct dai_data *dd = cd->dd[0]; + return dai_zephyr_unbind(dd, dev, data); + } return 0; } -static int copier_unbind(struct comp_dev *dev, void *data) -{ - struct processing_module *mod = comp_get_drvdata(dev); - - return copier_mod_unbind(mod, data); -} - -static const struct comp_driver comp_copier = { - .uid = SOF_RT_UUID(copier_comp_uuid), - .tctx = &copier_comp_tr, - .ops = { - .create = copier_new, - .free = copier_free, - .trigger = copier_comp_trigger, - .copy = copier_copy, - .set_large_config = copier_set_large_config, - .get_large_config = copier_get_large_config, - .params = copier_params, - .prepare = copier_prepare, - .reset = copier_reset, - .get_total_data_processed = copier_get_processed_data, - .get_attribute = copier_get_attribute, - .position = copier_position, - .dai_ts_config = copier_dai_ts_config_op, - .dai_ts_start = copier_dai_ts_start_op, - .dai_ts_stop = copier_dai_ts_stop_op, - .dai_ts_get = copier_dai_ts_get_op, - .dai_get_hw_params = copier_get_hw_params, - .unbind = copier_unbind, - }, +static struct module_endpoint_ops copier_endpoint_ops = { + .get_total_data_processed = copier_get_processed_data, + .position = copier_position, + .dai_ts_config = copier_dai_ts_config_op, + .dai_ts_start = copier_dai_ts_start_op, + .dai_ts_stop = copier_dai_ts_stop_op, + .dai_ts_get = copier_dai_ts_get_op, + .dai_get_hw_params = copier_get_hw_params, + .trigger = copier_comp_trigger }; -static SHARED_DATA struct comp_driver_info comp_copier_info = { - .drv = &comp_copier, +static struct module_interface copier_interface = { + .init = copier_init, + .prepare = copier_prepare, + .process_audio_stream = copier_process, + .reset = copier_reset, + .free = copier_free, + .set_configuration = copier_set_configuration, + .get_configuration = copier_get_configuration, + .unbind = copier_unbind, + .endpoint_ops = &copier_endpoint_ops, }; -UT_STATIC void sys_comp_copier_init(void) -{ - comp_register(platform_shared_get(&comp_copier_info, - sizeof(comp_copier_info))); -} - -DECLARE_MODULE(sys_comp_copier_init); -SOF_MODULE_INIT(copier, sys_comp_copier_init); +DECLARE_MODULE_ADAPTER(copier_interface, copier_comp_uuid, copier_comp_tr); +SOF_MODULE_INIT(copier, sys_comp_module_copier_interface_init); diff --git a/src/audio/copier/copier_dai.c b/src/audio/copier/copier_dai.c index 208f3c81a50b..dec0a7d46ad2 100644 --- a/src/audio/copier/copier_dai.c +++ b/src/audio/copier/copier_dai.c @@ -142,6 +142,7 @@ int copier_dai_create(struct comp_dev *parent_dev, struct copier_data *cd, const struct ipc4_copier_module_cfg *copier, struct pipeline *pipeline) { + struct processing_module *mod = comp_get_drvdata(parent_dev); int dai_index[IPC4_ALH_MAX_NUMBER_OF_GTW]; union ipc4_connector_node_id node_id; enum ipc4_gateway_type type; @@ -271,11 +272,15 @@ int copier_dai_create(struct comp_dev *parent_dev, struct copier_data *cd, return ret; } - if (cd->direction == SOF_IPC_STREAM_PLAYBACK) + if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { pipeline->sink_comp = parent_dev; - else + } else { pipeline->source_comp = parent_dev; + /* set max sink count for capture */ + mod->max_sinks = IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; + } + return 0; } diff --git a/src/audio/copier/copier_generic.c b/src/audio/copier/copier_generic.c index b9c80b05bebd..9ffbc8102f1e 100644 --- a/src/audio/copier/copier_generic.c +++ b/src/audio/copier/copier_generic.c @@ -4,6 +4,7 @@ // // Author: Andrula Song +#include #include #include @@ -57,29 +58,6 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, } #endif -void update_buffer_format(struct comp_buffer __sparse_cache *buf_c, - const struct ipc4_audio_format *fmt) -{ - enum sof_ipc_frame valid_fmt, frame_fmt; - int i; - - audio_stream_set_channels(&buf_c->stream, fmt->channels_count); - audio_stream_set_rate(&buf_c->stream, fmt->sampling_frequency); - audio_stream_fmt_conversion(fmt->depth, - fmt->valid_bit_depth, - &frame_fmt, &valid_fmt, - fmt->s_type); - - audio_stream_set_frm_fmt(&buf_c->stream, frame_fmt); - audio_stream_set_valid_fmt(&buf_c->stream, valid_fmt); - audio_stream_set_buffer_fmt(&buf_c->stream, fmt->interleaving_style); - - for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) - buf_c->chmap[i] = (fmt->ch_map >> i * 4) & 0xf; - - buf_c->hw_params_configured = true; -} - void copier_update_params(struct copier_data *cd, struct comp_dev *dev, struct sof_ipc_stream_params *params) { @@ -111,7 +89,7 @@ void copier_update_params(struct copier_data *cd, struct comp_dev *dev, j = IPC4_SINK_QUEUE_ID(sink_c->id); - update_buffer_format(sink_c, &cd->out_fmt[j]); + ipc4_update_buffer_format(sink_c, &cd->out_fmt[j]); buffer_release(sink_c); } @@ -127,7 +105,7 @@ void copier_update_params(struct copier_data *cd, struct comp_dev *dev, source_c = buffer_acquire(source); in_fmt = &cd->config.base.audio_fmt; - update_buffer_format(source_c, in_fmt); + ipc4_update_buffer_format(source_c, in_fmt); buffer_release(source_c); } diff --git a/src/audio/copier/copier_host.c b/src/audio/copier/copier_host.c index 78dbad237494..3e9f40139e26 100644 --- a/src/audio/copier/copier_host.c +++ b/src/audio/copier/copier_host.c @@ -48,6 +48,7 @@ int copier_host_create(struct comp_dev *parent_dev, struct copier_data *cd, const struct ipc4_copier_module_cfg *copier_cfg, int dir, struct pipeline *pipeline) { + struct processing_module *mod = comp_get_drvdata(parent_dev); struct ipc_config_host ipc_host; struct host_data *hd; int ret; @@ -100,6 +101,9 @@ int copier_host_create(struct comp_dev *parent_dev, struct copier_data *cd, ret = init_pipeline_reg(parent_dev); if (ret) goto e_conv; + + /* set max sink count for playback */ + mod->max_sinks = IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT; } else { config->frame_fmt = out_frame_fmt; pipeline->sink_comp = parent_dev; diff --git a/src/audio/mixin_mixout/mixin_mixout.c b/src/audio/mixin_mixout/mixin_mixout.c index 351977dbf140..bbed6fe56b2e 100644 --- a/src/audio/mixin_mixout/mixin_mixout.c +++ b/src/audio/mixin_mixout/mixin_mixout.c @@ -611,9 +611,6 @@ static int mixout_reset(struct processing_module *mod) return 0; } -static void base_module_cfg_to_stream_params(const struct ipc4_base_module_cfg *base_cfg, - struct sof_ipc_stream_params *params); - /* params are derived from base config for ipc4 path */ static int mixin_params(struct processing_module *mod) { @@ -625,7 +622,7 @@ static int mixin_params(struct processing_module *mod) comp_dbg(dev, "mixin_params()"); - base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); /* Buffers between mixins and mixouts are not used (mixin writes data directly to mixout * sink). But, anyway, let's setup these buffers properly just in case. @@ -732,30 +729,6 @@ static int mixin_prepare(struct processing_module *mod, return 0; } -static void base_module_cfg_to_stream_params(const struct ipc4_base_module_cfg *base_cfg, - struct sof_ipc_stream_params *params) -{ - enum sof_ipc_frame frame_fmt, valid_fmt; - int i; - - memset(params, 0, sizeof(struct sof_ipc_stream_params)); - params->channels = base_cfg->audio_fmt.channels_count; - params->rate = base_cfg->audio_fmt.sampling_frequency; - params->sample_container_bytes = base_cfg->audio_fmt.depth / 8; - params->sample_valid_bytes = base_cfg->audio_fmt.valid_bit_depth / 8; - params->buffer_fmt = base_cfg->audio_fmt.interleaving_style; - params->buffer.size = base_cfg->obs * 2; - - audio_stream_fmt_conversion(base_cfg->audio_fmt.depth, - base_cfg->audio_fmt.valid_bit_depth, - &frame_fmt, &valid_fmt, - base_cfg->audio_fmt.s_type); - params->frame_fmt = valid_fmt; - - for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) - params->chmap[i] = (base_cfg->audio_fmt.ch_map >> i * 4) & 0xf; -} - static int mixout_params(struct processing_module *mod) { struct sof_ipc_stream_params *params = mod->stream_params; @@ -768,7 +741,7 @@ static int mixout_params(struct processing_module *mod) comp_dbg(dev, "mixout_params()"); - base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); ret = comp_verify_params(dev, 0, params); if (ret < 0) { diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index ef29ec7c4c85..760652982245 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -83,11 +83,12 @@ int module_init(struct processing_module *mod, struct module_interface *interfac comp_dbg(dev, "module_init() start"); +#if CONFIG_IPC_MAJOR_3 if (mod->priv.state == MODULE_INITIALIZED) return 0; if (mod->priv.state > MODULE_INITIALIZED) return -EPERM; - +#endif if (!interface) { comp_err(dev, "module_init(): could not find module interface for comp id %d", dev_comp_id(dev)); @@ -118,7 +119,9 @@ int module_init(struct processing_module *mod, struct module_interface *interfac } comp_dbg(dev, "module_init() done"); +#if CONFIG_IPC_MAJOR_3 md->state = MODULE_INITIALIZED; +#endif return ret; } @@ -202,11 +205,12 @@ int module_prepare(struct processing_module *mod, comp_dbg(dev, "module_prepare() start"); +#if CONFIG_IPC_MAJOR_3 if (mod->priv.state == MODULE_IDLE) return 0; if (mod->priv.state < MODULE_INITIALIZED) return -EPERM; - +#endif ret = md->ops->prepare(mod, sources, num_of_sources, sinks, num_of_sinks); if (ret) { comp_err(dev, "module_prepare() error %d: module specific prepare failed, comp_id %d", @@ -224,7 +228,9 @@ int module_prepare(struct processing_module *mod, md->cfg.avail = false; md->cfg.data = NULL; +#if CONFIG_IPC_MAJOR_3 md->state = MODULE_IDLE; +#endif comp_dbg(dev, "module_prepare() done"); return ret; @@ -242,6 +248,7 @@ int module_process_legacy(struct processing_module *mod, comp_dbg(dev, "module_process_legacy() start"); +#if CONFIG_IPC_MAJOR_3 if (md->state != MODULE_IDLE) { comp_err(dev, "module_process(): wrong state of comp_id %x, state %d", dev_comp_id(dev), md->state); @@ -250,7 +257,7 @@ int module_process_legacy(struct processing_module *mod, /* set state to processing */ md->state = MODULE_PROCESSING; - +#endif if (md->ops->process_audio_stream) ret = md->ops->process_audio_stream(mod, input_buffers, num_input_buffers, output_buffers, num_output_buffers); @@ -268,8 +275,10 @@ int module_process_legacy(struct processing_module *mod, comp_dbg(dev, "module_process_legacy() done"); +#if CONFIG_IPC_MAJOR_3 /* reset state to idle */ md->state = MODULE_IDLE; +#endif return 0; } @@ -285,6 +294,7 @@ int module_process_sink_src(struct processing_module *mod, comp_dbg(dev, "module_process sink src() start"); +#if CONFIG_IPC_MAJOR_3 if (md->state != MODULE_IDLE) { comp_err(dev, "module_process(): wrong state of comp_id %x, state %d", dev_comp_id(dev), md->state); @@ -293,7 +303,7 @@ int module_process_sink_src(struct processing_module *mod, /* set state to processing */ md->state = MODULE_PROCESSING; - +#endif assert(md->ops->process); ret = md->ops->process(mod, sources, num_of_sources, sinks, num_of_sinks); @@ -305,8 +315,10 @@ int module_process_sink_src(struct processing_module *mod, comp_dbg(dev, "module_process sink src() done"); +#if CONFIG_IPC_MAJOR_3 /* reset state to idle */ md->state = MODULE_IDLE; +#endif return ret; } @@ -315,9 +327,11 @@ int module_reset(struct processing_module *mod) int ret; struct module_data *md = &mod->priv; +#if CONFIG_IPC_MAJOR_3 /* if the module was never prepared, no need to reset */ if (md->state < MODULE_IDLE) return 0; +#endif ret = md->ops->reset(mod); if (ret) { @@ -333,12 +347,13 @@ int module_reset(struct processing_module *mod) rfree(md->cfg.data); md->cfg.data = NULL; +#if CONFIG_IPC_MAJOR_3 /* * reset the state to allow the module's prepare callback to be invoked again for the * subsequent triggers */ md->state = MODULE_INITIALIZED; - +#endif return 0; } @@ -376,8 +391,9 @@ int module_free(struct processing_module *mod) rfree(md->runtime_params); md->runtime_params = NULL; } +#if CONFIG_IPC_MAJOR_3 md->state = MODULE_DISABLED; - +#endif return ret; } @@ -486,3 +502,21 @@ int module_set_configuration(struct processing_module *mod, return ret; } + +int module_bind(struct processing_module *mod, void *data) +{ + struct module_data *md = &mod->priv; + + if (md->ops->bind) + return md->ops->bind(mod, data); + return 0; +} + +int module_unbind(struct processing_module *mod, void *data) +{ + struct module_data *md = &mod->priv; + + if (md->ops->unbind) + return md->ops->unbind(mod, data); + return 0; +} diff --git a/src/audio/module_adapter/module/volume/volume.c b/src/audio/module_adapter/module/volume/volume.c index 509ab7de0c26..fd5501e39fd5 100644 --- a/src/audio/module_adapter/module/volume/volume.c +++ b/src/audio/module_adapter/module/volume/volume.c @@ -1056,7 +1056,6 @@ static int volume_set_config(struct processing_module *mod, uint32_t config_id, const uint8_t *fragment, size_t fragment_size, uint8_t *response, size_t response_size) { - struct module_data *md = &mod->priv; struct comp_dev *dev = mod->dev; int ret; @@ -1070,8 +1069,7 @@ static int volume_set_config(struct processing_module *mod, uint32_t config_id, return ret; /* return if more fragments are expected or if the module is not prepared */ - if ((pos != MODULE_CFG_FRAGMENT_LAST && pos != MODULE_CFG_FRAGMENT_SINGLE) || - md->state < MODULE_INITIALIZED) + if (pos != MODULE_CFG_FRAGMENT_LAST && pos != MODULE_CFG_FRAGMENT_SINGLE) return 0; switch (config_id) { @@ -1120,39 +1118,28 @@ static int volume_get_config(struct processing_module *mod, static int volume_params(struct processing_module *mod) { struct sof_ipc_stream_params *params = mod->stream_params; - struct sof_ipc_stream_params vol_params; - enum sof_ipc_frame frame_fmt, valid_fmt; + struct comp_buffer __sparse_cache *sink_c, *source_c; + struct comp_buffer *sinkb, *sourceb; struct comp_dev *dev = mod->dev; - struct comp_buffer *sinkb; - struct comp_buffer __sparse_cache *sink_c; - int i, ret; comp_dbg(dev, "volume_params()"); - vol_params = *params; - vol_params.channels = mod->priv.cfg.base_cfg.audio_fmt.channels_count; - vol_params.rate = mod->priv.cfg.base_cfg.audio_fmt.sampling_frequency; - vol_params.buffer_fmt = mod->priv.cfg.base_cfg.audio_fmt.interleaving_style; - - audio_stream_fmt_conversion(mod->priv.cfg.base_cfg.audio_fmt.depth, - mod->priv.cfg.base_cfg.audio_fmt.valid_bit_depth, - &frame_fmt, &valid_fmt, - mod->priv.cfg.base_cfg.audio_fmt.s_type); - - vol_params.frame_fmt = valid_fmt; - - for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) - vol_params.chmap[i] = (mod->priv.cfg.base_cfg.audio_fmt.ch_map >> i * 4) & 0xf; + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); - component_set_nearest_period_frames(dev, vol_params.rate); + component_set_nearest_period_frames(dev, params->rate); /* volume component will only ever have 1 sink buffer */ sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); sink_c = buffer_acquire(sinkb); - ret = buffer_set_params(sink_c, &vol_params, true); + ipc4_update_buffer_format(sink_c, &mod->priv.cfg.base_cfg.audio_fmt); buffer_release(sink_c); - return ret; + sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); + source_c = buffer_acquire(sourceb); + ipc4_update_buffer_format(source_c, &mod->priv.cfg.base_cfg.audio_fmt); + buffer_release(source_c); + + return 0; } #endif /* CONFIG_IPC_MAJOR_4 */ diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 4b2e475e4c5e..d40175c675db 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -256,17 +256,6 @@ int module_adapter_prepare(struct comp_dev *dev) return ret; } - /* Get period_bytes first on prepare(). At this point it is guaranteed that the stream - * parameter from sink buffer is settled, and still prior to all references to period_bytes. - */ - sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); - sink_c = buffer_acquire(sink); - - mod->period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames); - comp_dbg(dev, "module_adapter_prepare(): got period_bytes = %u", mod->period_bytes); - - buffer_release(sink_c); - /* * check if the component is already active. This could happen in the case of mixer when * one of the sources is already active @@ -284,8 +273,23 @@ int module_adapter_prepare(struct comp_dev *dev) return PPL_STATUS_PATH_STOP; } + /* nothing more to do for HOST/DAI type modules */ + if (dev->ipc_config.type == SOF_COMP_HOST || dev->ipc_config.type == SOF_COMP_DAI) + return 0; + mod->deep_buff_bytes = 0; + /* Get period_bytes first on prepare(). At this point it is guaranteed that the stream + * parameter from sink buffer is settled, and still prior to all references to period_bytes. + */ + sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); + sink_c = buffer_acquire(sink); + + mod->period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames); + comp_dbg(dev, "module_adapter_prepare(): got period_bytes = %u", mod->period_bytes); + + buffer_release(sink_c); + /* * compute number of input buffers and make the source_info shared if the module is on a * different core than any of it's sources @@ -544,6 +548,10 @@ int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *pa return ret; } +#if CONFIG_IPC_MAJOR_4 + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, params); + ipc4_base_module_cfg_to_stream_params(&mod->priv.cfg.base_cfg, mod->stream_params); +#endif return 0; } @@ -867,6 +875,10 @@ static int module_adapter_audio_stream_type_copy(struct comp_dev *dev) uint32_t num_input_buffers, num_output_buffers; int ret, i = 0; + /* handle special case of HOST/DAI type components */ + if (dev->ipc_config.type == SOF_COMP_HOST || dev->ipc_config.type == SOF_COMP_DAI) + return module_process_legacy(mod, NULL, 0, NULL, 0); + if (mod->stream_copy_single_to_single) return module_adapter_audio_stream_copy_1to1(dev); @@ -1330,6 +1342,13 @@ int module_adapter_trigger(struct comp_dev *dev, int cmd) comp_dbg(dev, "module_adapter_trigger(): cmd %d", cmd); + /* handle host/DAI gateway modules separately */ + if (dev->ipc_config.type == SOF_COMP_HOST || dev->ipc_config.type == SOF_COMP_DAI) { + struct module_data *md = &mod->priv; + + return md->ops->endpoint_ops->trigger(dev, cmd); + } + /* * If the module doesn't support pause, keep it active along with the rest of the * downstream modules @@ -1438,6 +1457,125 @@ void module_adapter_free(struct comp_dev *dev) rfree(dev); } +/* + * \brief Get DAI hw params + * \param[in] dev - component device pointer + * \param[in] params - pointer to stream params + * \param[in] dir - stream direction + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params, + int dir) +{ + struct processing_module *mod = comp_get_drvdata(dev); + struct module_data *md = &mod->priv; + + if (md->ops->endpoint_ops && md->ops->endpoint_ops->dai_get_hw_params) + return md->ops->endpoint_ops->dai_get_hw_params(dev, params, dir); + + return -EOPNOTSUPP; +} + +/* + * \brief Get stream position + * \param[in] dev - component device pointer + * \param[in] posn - pointer to stream position + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) +{ + struct processing_module *mod = comp_get_drvdata(dev); + struct module_data *md = &mod->priv; + + if (md->ops->endpoint_ops && md->ops->endpoint_ops->position) + return md->ops->endpoint_ops->position(dev, posn); + + return -EOPNOTSUPP; +} + +/* + * \brief DAI timestamp configure + * \param[in] dev - component device pointer + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_ts_config_op(struct comp_dev *dev) +{ + struct processing_module *mod = comp_get_drvdata(dev); + struct module_data *md = &mod->priv; + + if (md->ops->endpoint_ops && md->ops->endpoint_ops->dai_ts_config) + return md->ops->endpoint_ops->dai_ts_config(dev); + + return -EOPNOTSUPP; +} + +/* + * \brief DAI timestamp start + * \param[in] dev - component device pointer + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_ts_start_op(struct comp_dev *dev) +{ + struct processing_module *mod = comp_get_drvdata(dev); + struct module_data *md = &mod->priv; + + if (md->ops->endpoint_ops && md->ops->endpoint_ops->dai_ts_start) + return md->ops->endpoint_ops->dai_ts_start(dev); + + return -EOPNOTSUPP; +} + +/* + * \brief DAI timestamp stop + * \param[in] dev - component device pointer + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_ts_stop_op(struct comp_dev *dev) +{ + struct processing_module *mod = comp_get_drvdata(dev); + struct module_data *md = &mod->priv; + + if (md->ops->endpoint_ops && md->ops->endpoint_ops->dai_ts_stop) + return md->ops->endpoint_ops->dai_ts_stop(dev); + + return -EOPNOTSUPP; +} + +/* + * \brief Get DAI timestamp + * \param[in] dev - component device pointer + * \param[in] tsd - Timestamp data pointer + * + * \return integer representing either: + * 0 - success + * value < 0 - failure. + */ +int module_adapter_ts_get_op(struct comp_dev *dev, struct timestamp_data *tsd) +{ + struct processing_module *mod = comp_get_drvdata(dev); + struct module_data *md = &mod->priv; + + if (md->ops->endpoint_ops && md->ops->endpoint_ops->dai_ts_get) + return md->ops->endpoint_ops->dai_ts_get(dev, tsd); + + return -EOPNOTSUPP; +} + #if CONFIG_IPC_MAJOR_4 int module_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, bool last_block, uint32_t data_offset_size, const char *data) @@ -1552,6 +1690,11 @@ int module_adapter_bind(struct comp_dev *dev, void *data) struct comp_dev *source_dev; int source_index; int src_id; + int ret; + + ret = module_bind(mod, data); + if (ret < 0) + return ret; bu = (struct ipc4_module_bind_unbind *)data; src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id); @@ -1603,6 +1746,11 @@ int module_adapter_unbind(struct comp_dev *dev, void *data) struct comp_dev *source_dev; int source_index; int src_id; + int ret; + + ret = module_unbind(mod, data); + if (ret < 0) + return ret; bu = (struct ipc4_module_bind_unbind *)data; src_id = IPC4_COMP_ID(bu->primary.r.module_id, bu->primary.r.instance_id); @@ -1635,6 +1783,10 @@ uint64_t module_adapter_get_total_data_processed(struct comp_dev *dev, uint32_t stream_no, bool input) { struct processing_module *mod = comp_get_drvdata(dev); + struct module_data *md = &mod->priv; + + if (md->ops->endpoint_ops && md->ops->endpoint_ops->get_total_data_processed) + return md->ops->endpoint_ops->get_total_data_processed(dev, stream_no, input); if (input) return mod->total_data_produced; diff --git a/src/include/ipc4/base-config.h b/src/include/ipc4/base-config.h index 104da996e8a0..26eeb07bf355 100644 --- a/src/include/ipc4/base-config.h +++ b/src/include/ipc4/base-config.h @@ -25,6 +25,7 @@ #define __SOF_IPC4_BASE_CONFIG_H__ #include +#include enum ipc4_sampling_frequency { IPC4_FS_8000HZ = 8000, @@ -237,4 +238,11 @@ union ipc4_cfg_param_id_data { } f; } __attribute__((packed, aligned(4))); +struct sof_ipc_stream_params; +void ipc4_base_module_cfg_to_stream_params(const struct ipc4_base_module_cfg *base_cfg, + struct sof_ipc_stream_params *params); +struct comp_buffer; +void ipc4_update_buffer_format(struct comp_buffer __sparse_cache *buf_c, + const struct ipc4_audio_format *fmt); + #endif diff --git a/src/include/ipc4/copier.h b/src/include/ipc4/copier.h index 4f1f3da49c87..d6965f1c3c22 100644 --- a/src/include/ipc4/copier.h +++ b/src/include/ipc4/copier.h @@ -283,9 +283,6 @@ int create_endpoint_buffer(struct comp_dev *parent_dev, enum sof_ipc_stream_direction get_gateway_direction(enum ipc4_connector_node_id_type node_id_type); -void update_buffer_format(struct comp_buffer __sparse_cache *buf_c, - const struct ipc4_audio_format *fmt); - void copier_update_params(struct copier_data *cd, struct comp_dev *dev, struct sof_ipc_stream_params *params); #endif diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index e6d89738e1e6..4e0a5ae6988d 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -60,6 +60,12 @@ static const struct comp_driver comp_##adapter##_module = { \ .bind = module_adapter_bind,\ .unbind = module_adapter_unbind,\ .get_total_data_processed = module_adapter_get_total_data_processed,\ + .dai_get_hw_params = module_adapter_get_hw_params,\ + .position = module_adapter_position,\ + .dai_ts_config = module_adapter_ts_config_op,\ + .dai_ts_start = module_adapter_ts_start_op,\ + .dai_ts_stop = module_adapter_ts_stop_op,\ + .dai_ts_get = module_adapter_ts_get_op,\ }, \ }; \ \ @@ -249,6 +255,8 @@ int module_set_configuration(struct processing_module *mod, enum module_cfg_fragment_position pos, size_t data_offset_size, const uint8_t *fragment, size_t fragment_size, uint8_t *response, size_t response_size); +int module_bind(struct processing_module *mod, void *data); +int module_unbind(struct processing_module *mod, void *data); struct comp_dev *module_adapter_new(const struct comp_driver *drv, const struct comp_ipc_config *config, @@ -269,6 +277,13 @@ int module_adapter_bind(struct comp_dev *dev, void *data); int module_adapter_unbind(struct comp_dev *dev, void *data); uint64_t module_adapter_get_total_data_processed(struct comp_dev *dev, uint32_t stream_no, bool input); +int module_adapter_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params, + int dir); +int module_adapter_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn); +int module_adapter_ts_config_op(struct comp_dev *dev); +int module_adapter_ts_start_op(struct comp_dev *dev); +int module_adapter_ts_stop_op(struct comp_dev *dev); +int module_adapter_ts_get_op(struct comp_dev *dev, struct timestamp_data *tsd); static inline void module_update_buffer_position(struct input_stream_buffer *input_buffers, struct output_stream_buffer *output_buffers, diff --git a/src/include/sof/audio/module_adapter/module/module_interface.h b/src/include/sof/audio/module_adapter/module/module_interface.h index dec02f3cfa5a..0d020238a2ae 100644 --- a/src/include/sof/audio/module_adapter/module/module_interface.h +++ b/src/include/sof/audio/module_adapter/module/module_interface.h @@ -67,6 +67,79 @@ struct output_stream_buffer { uint32_t size; /* size of data in the buffer */ }; +/** + * \struct module_endpoint_ops + * \brief Ops relevant only for the endpoint devices such as the host copier or DAI copier. + * Other modules should not implement these. + */ +struct module_endpoint_ops { + /** + * Returns total data processed in number bytes. + * @param dev Component device + * @param stream_no Index of input/output stream + * @param input Selects between input (true) or output (false) stream direction + * @return total data processed if succeeded, 0 otherwise. + */ + uint64_t (*get_total_data_processed)(struct comp_dev *dev, uint32_t stream_no, bool input); + /** + * Retrieves component rendering position. + * @param dev Component device. + * @param posn Receives reported position. + */ + int (*position)(struct comp_dev *dev, struct sof_ipc_stream_posn *posn); + /** + * Configures timestamping in attached DAI. + * @param dev Component device. + * + * Mandatory for components that allocate DAI. + */ + int (*dai_ts_config)(struct comp_dev *dev); + + /** + * Starts timestamping. + * @param dev Component device. + * + * Mandatory for components that allocate DAI. + */ + int (*dai_ts_start)(struct comp_dev *dev); + + /** + * Stops timestamping. + * @param dev Component device. + * + * Mandatory for components that allocate DAI. + */ + int (*dai_ts_stop)(struct comp_dev *dev); + + /** + * Gets timestamp. + * @param dev Component device. + * @param tsd Receives timestamp data. + * + * Mandatory for components that allocate DAI. + */ + int (*dai_ts_get)(struct comp_dev *dev, struct timestamp_data *tsd); + + /** + * Fetches hardware stream parameters. + * @param dev Component device. + * @param params Receives copy of stream parameters retrieved from + * DAI hw settings. + * @param dir Stream direction (see enum sof_ipc_stream_direction). + * + * Mandatory for components that allocate DAI. + */ + int (*dai_get_hw_params)(struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dir); + + /** + * Triggers device state. + * @param dev Component device. + * @param cmd Trigger command. + */ + int (*trigger)(struct comp_dev *dev, int cmd); +}; + struct processing_module; /** * \struct module_interface @@ -189,6 +262,16 @@ struct module_interface { * free in .free(). This should free all memory allocated during module initialization. */ int (*free)(struct processing_module *mod); + /** + * Module specific bind procedure, called when modules are bound with each other + */ + int (*bind)(struct processing_module *mod, void *data); + /** + * Module specific unbind procedure, called when modules are disconnected from one another + */ + int (*unbind)(struct processing_module *mod, void *data); + + const struct module_endpoint_ops *endpoint_ops; }; /* Convert first_block/last_block indicator to fragment position */ diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 00f1bf4f8866..3d889a294235 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -803,3 +803,49 @@ int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint3 return IPC4_SUCCESS; } +void ipc4_base_module_cfg_to_stream_params(const struct ipc4_base_module_cfg *base_cfg, + struct sof_ipc_stream_params *params) +{ + enum sof_ipc_frame frame_fmt, valid_fmt; + int i; + + memset(params, 0, sizeof(struct sof_ipc_stream_params)); + params->channels = base_cfg->audio_fmt.channels_count; + params->rate = base_cfg->audio_fmt.sampling_frequency; + params->sample_container_bytes = base_cfg->audio_fmt.depth / 8; + params->sample_valid_bytes = base_cfg->audio_fmt.valid_bit_depth / 8; + params->buffer_fmt = base_cfg->audio_fmt.interleaving_style; + params->buffer.size = base_cfg->obs * 2; + + audio_stream_fmt_conversion(base_cfg->audio_fmt.depth, + base_cfg->audio_fmt.valid_bit_depth, + &frame_fmt, &valid_fmt, + base_cfg->audio_fmt.s_type); + params->frame_fmt = valid_fmt; + + for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) + params->chmap[i] = (base_cfg->audio_fmt.ch_map >> i * 4) & 0xf; +} + +void ipc4_update_buffer_format(struct comp_buffer __sparse_cache *buf_c, + const struct ipc4_audio_format *fmt) +{ + enum sof_ipc_frame valid_fmt, frame_fmt; + int i; + + audio_stream_set_channels(&buf_c->stream, fmt->channels_count); + audio_stream_set_rate(&buf_c->stream, fmt->sampling_frequency); + audio_stream_fmt_conversion(fmt->depth, + fmt->valid_bit_depth, + &frame_fmt, &valid_fmt, + fmt->s_type); + + audio_stream_set_frm_fmt(&buf_c->stream, frame_fmt); + audio_stream_set_valid_fmt(&buf_c->stream, valid_fmt); + audio_stream_set_buffer_fmt(&buf_c->stream, fmt->interleaving_style); + + for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) + buf_c->chmap[i] = (fmt->ch_map >> i * 4) & 0xf; + + buf_c->hw_params_configured = true; +}