diff --git a/src/audio/module_adapter/module_adapter_ipc4.c b/src/audio/module_adapter/module_adapter_ipc4.c index a50b78ff7714..f41ed7f6556c 100644 --- a/src/audio/module_adapter/module_adapter_ipc4.c +++ b/src/audio/module_adapter/module_adapter_ipc4.c @@ -25,6 +25,76 @@ LOG_MODULE_DECLARE(module_adapter, CONFIG_SOF_LOG_LEVEL); +static const struct ipc4_base_module_extended_cfg * +module_ext_init_decode(struct comp_dev *dev, struct module_config *dst, + const unsigned char *data, size_t *size) +{ + const struct ipc4_module_init_ext_init *ext_init = + (const struct ipc4_module_init_ext_init *)data; + bool last_object = !ext_init->data_obj_array; + const struct ipc4_module_init_ext_object *obj; + + if (*size < sizeof(ext_init)) { + comp_err(dev, "Size too small for ext init %u < %u", + *size, sizeof(ext_init)); + return NULL; + } + /* TODO: Handle ext_init->gna_used and ext_init->rtos_domain here */ + /* Get the first obj struct right after ext_init struct */ + obj = (const struct ipc4_module_init_ext_object *)(ext_init + 1); + while (!last_object) { + const struct ipc4_module_init_ext_object *next_obj; + + /* Check if there is space for the object header */ + if ((unsigned char *)(obj + 1) - data > *size) { + comp_err(dev, "ext init obj overflow, %u > %u", + (unsigned char *)(obj + 1) - data, *size); + return NULL; + } + /* Calculate would be next object position and check if current object fits */ + next_obj = (const struct ipc4_module_init_ext_object *) + (((uint32_t *) (obj + 1)) + obj->object_words); + if ((unsigned char *)next_obj - data > *size) { + comp_err(dev, "ext init object array overflow, %u > %u", + (unsigned char *)obj - data, *size); + return NULL; + } + switch (obj->object_id) { + case IPC4_MOD_INIT_DATA_ID_DP_DATA: + { + /* Get dp_data struct that follows the obj struct */ + const struct ipc4_module_init_ext_obj_dp_data *dp_data = + (const struct ipc4_module_init_ext_obj_dp_data *)(obj + 1); + + if (obj->object_words * sizeof(uint32_t) < sizeof(*dp_data)) { + comp_err(dev, "dp_data object too small %u < %u", + obj->object_words * sizeof(uint32_t), sizeof(*dp_data)); + return NULL; + } + dst->domain_id = dp_data->domain_id; + dst->stack_bytes = dp_data->stack_bytes; + dst->heap_bytes = dp_data->heap_bytes; + comp_info(dev, "init_ext_obj_dp_data domain %u stack %u heap %u", + dp_data->domain_id, dp_data->stack_bytes, dp_data->heap_bytes); + break; + } + default: + comp_info(dev, "Unknown ext init object id %u of %u words", + obj->object_id, obj->object_words); + } + /* Read the last object flag from obj header */ + last_object = obj->last_object; + /* Move to next object */ + obj = next_obj; + } + + /* Remove decoded ext_init payload from the size */ + *size -= (unsigned char *) obj - data; + + /* return remaining payload */ + return (const struct ipc4_base_module_extended_cfg *)obj; +} + /* * \module adapter data initialize. * \param[in] dev - device. @@ -39,11 +109,18 @@ int module_adapter_init_data(struct comp_dev *dev, const struct comp_ipc_config *config, const void *spec) { + const struct ipc4_base_module_extended_cfg *cfg; const struct ipc_config_process *args = spec; - const struct ipc4_base_module_extended_cfg *cfg = (void *)args->data; size_t cfgsz = args->size; assert(dev->drv->type == SOF_COMP_MODULE_ADAPTER); + if (config->ipc_extended_init) + cfg = module_ext_init_decode(dev, dst, args->data, &cfgsz); + else + cfg = (const struct ipc4_base_module_extended_cfg *)args->data; + + if (cfg == NULL) + return -EINVAL; if (cfgsz < sizeof(cfg->base_cfg)) return -EINVAL; diff --git a/src/include/ipc4/module.h b/src/include/ipc4/module.h index f38621ead52c..a73ede0b0bd5 100644 --- a/src/include/ipc4/module.h +++ b/src/include/ipc4/module.h @@ -73,6 +73,28 @@ struct ipc4_vendor_error { uint32_t err_code; }; +/* IDs for all global object types in struct ipc4_module_init_ext_object */ +enum ipc4_mod_init_data_glb_id { + IPC4_MOD_INIT_DATA_ID_INVALID = 0, + IPC4_MOD_INIT_DATA_ID_DP_DATA = 1, + IPC4_MOD_INIT_DATA_ID_MAX = IPC4_MOD_INIT_DATA_ID_DP_DATA, +}; + +/* data object for vendor bespoke data with ABI growth and backwards compat */ +struct ipc4_module_init_ext_object { + uint32_t last_object : 1; /* object is last in array if 1 else object follows. */ + uint32_t object_id : 15; /* unique ID for this object or globally */ + uint32_t object_words : 16; /* size in dwords (excluding this structure) */ +} __attribute__((packed, aligned(4))); +/* the object data will be placed in memory here and will have size "object_words" */ + +/* Ext init array data object for Data Processing module memory requirements */ +struct ipc4_module_init_ext_obj_dp_data { + uint32_t domain_id; /* userspace domain ID */ + uint32_t stack_bytes; /* required stack size in bytes, 0 means default size */ + uint32_t heap_bytes; /* required heap size in bytes, 0 means default size */ +} __attribute__((packed, aligned(4))); + /* * Host Driver sends this message to create a new module instance. */ @@ -83,7 +105,8 @@ struct ipc4_module_init_ext_init { /**< Indicates that GNA is used by a module and additional information */ /* (gna_config) is passed after ExtendedData. */ uint32_t gna_used : 1; - uint32_t rsvd_0 : 30; + uint32_t data_obj_array : 1; /* struct ipc4_module_init_ext_object data */ + uint32_t rsvd_0 : 29; uint32_t rsvd_1[2]; } __attribute__((packed, aligned(4))); diff --git a/src/include/module/module/base.h b/src/include/module/module/base.h index f4da3252f4e3..ce5ca363ba73 100644 --- a/src/include/module/module/base.h +++ b/src/include/module/module/base.h @@ -34,6 +34,9 @@ struct module_config { uint8_t nb_output_pins; struct ipc4_input_pin_format *input_pins; struct ipc4_output_pin_format *output_pins; + uint32_t domain_id; /* userspace domain ID */ + uint32_t stack_bytes; /* stack size in bytes, 0 means default value */ + uint32_t heap_bytes; /* max heap size in bytes, 0 means default value */ #endif }; diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 337730ccae7d..f8fb0bbdf928 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -617,6 +617,7 @@ struct comp_ipc_config { uint32_t frame_fmt; /**< SOF_IPC_FRAME_ */ uint32_t xrun_action; /**< action we should take on XRUN */ #if CONFIG_IPC_MAJOR_4 + bool ipc_extended_init; /**< true if extended init is included in ipc payload */ uint32_t ipc_config_size; /**< size of a config received by ipc */ #endif }; diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 4ff7d3a378d1..2211c5009f97 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -137,6 +137,7 @@ __cold struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_i ipc_config.pipeline_id = module_init->extension.r.ppl_instance_id; ipc_config.core = module_init->extension.r.core_id; ipc_config.ipc_config_size = module_init->extension.r.param_block_size * sizeof(uint32_t); + ipc_config.ipc_extended_init = module_init->extension.r.extended_init; dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE, MAILBOX_HOSTBOX_SIZE); diff --git a/tools/topology/topology2/cavs-nocodec.conf b/tools/topology/topology2/cavs-nocodec.conf index 3970778de1f3..398b0f86abb9 100644 --- a/tools/topology/topology2/cavs-nocodec.conf +++ b/tools/topology/topology2/cavs-nocodec.conf @@ -693,7 +693,14 @@ IncludeByKey.PASSTHROUGH { } Object.Widget.src.1 { scheduler_domain "$SRC_DOMAIN" - core_id $DP_SRC_CORE_ID + IncludeByKey.SRC_DOMAIN { + "DP" { + core_id $DP_SRC_CORE_ID + domain_id 123 + stack_bytes_requirement 4096 + heap_bytes_requirement 8192 + } + } } Object.Widget.pipeline.1 { core $SSP2_PCM_CORE_ID @@ -1370,7 +1377,14 @@ IncludeByKey.PASSTHROUGH { index 11 rate_in 48000 scheduler_domain "$SRC_DOMAIN" - core_id $DP_SRC_CORE_ID + IncludeByKey.SRC_DOMAIN { + "DP" { + core_id $DP_SRC_CORE_ID + domain_id 123 + stack_bytes_requirement 4096 + heap_bytes_requirement 8192 + } + } } diff --git a/tools/topology/topology2/include/common/tokens.conf b/tools/topology/topology2/include/common/tokens.conf index 4f00ad79a73f..d1b986ab01d4 100644 --- a/tools/topology/topology2/include/common/tokens.conf +++ b/tools/topology/topology2/include/common/tokens.conf @@ -26,6 +26,9 @@ Object.Base.VendorToken { num_output_audio_formats 416 no_wname_in_kcontrol_name 417 scheduler_domain 418 + domain_id 419 + stack_bytes_requirement 420 + heap_bytes_requirement 421 } "2" { diff --git a/tools/topology/topology2/include/components/widget-common.conf b/tools/topology/topology2/include/components/widget-common.conf index a0e816a0f22e..851e78ae1721 100644 --- a/tools/topology/topology2/include/components/widget-common.conf +++ b/tools/topology/topology2/include/components/widget-common.conf @@ -136,3 +136,22 @@ DefineAttribute."scheduler_domain" { ] } } + +## Userspace domain id +DefineAttribute."domain_id" { + # Token set reference name and type + token_ref "comp.word" +} + +## Stack size requirement in bytes for this component. Zero indicates default stack size. +DefineAttribute."stack_bytes_requirement" { + # Token set reference name and type + token_ref "comp.word" +} + +## Heap size requirement in bytes for this component. Zero indicates default heap size. +DefineAttribute."heap_bytes_requirement" { + # Token set reference name and type + token_ref "comp.word" +} +