diff --git a/src/audio/module_adapter/module/modules.c b/src/audio/module_adapter/module/modules.c index 83f2cf231162..7c94174c037d 100644 --- a/src/audio/module_adapter/module/modules.c +++ b/src/audio/module_adapter/module/modules.c @@ -9,11 +9,8 @@ #include #include #include -#include -#include #include #include -#include /* Intel module adapter is an extension to SOF module adapter component that allows to integrate * modules developed under IADK (Intel Audio Development Kit) Framework. IADK modules uses uniform @@ -60,18 +57,17 @@ static int modules_init(struct processing_module *mod) { uint32_t module_entry_point; struct module_data *md = &mod->priv; - struct comp_dev *dev = mod->dev; - struct comp_driver *drv = (struct comp_driver *)dev->drv; + const struct comp_dev *dev = mod->dev; + const struct comp_driver *const drv = dev->drv; const struct ipc4_base_module_cfg *src_cfg = &md->cfg.base_cfg; byte_array_t mod_cfg; void *system_agent; - bool is_native_sof = false; mod_cfg.data = (uint8_t *)md->cfg.init_data; /* Intel modules expects DW size here */ mod_cfg.size = md->cfg.size >> 2; - struct comp_ipc_config *config = &(mod->dev->ipc_config); + const struct comp_ipc_config *config = &dev->ipc_config; /* At this point module resources are allocated and it is moved to L2 memory. */ module_entry_point = lib_manager_allocate_module(dev->drv, config, src_cfg); @@ -81,69 +77,25 @@ static int modules_init(struct processing_module *mod) } comp_info(mod->dev, "modules_init() start"); - uint32_t module_id = IPC4_MOD_ID(mod->dev->ipc_config.id); - uint32_t instance_id = IPC4_INST_ID(mod->dev->ipc_config.id); - uint32_t log_handle = (uint32_t) mod->dev->drv->tctx; - /* Connect loadable module interfaces with module adapter entity. */ - /* Check if native Zephyr lib is loaded */ + const uint32_t module_id = IPC4_MOD_ID(dev->ipc_config.id); + const uint32_t instance_id = IPC4_INST_ID(dev->ipc_config.id); + const uint32_t log_handle = (const uint32_t)drv->tctx; - const struct sof_man_module *const module_entry = - lib_manager_get_library_manifest(module_id); + system_agent = system_agent_start(module_entry_point, module_id, + instance_id, 0, log_handle, + &mod_cfg); - if (!module_entry) { - comp_err(dev, "modules_init(): Failed to load manifest"); - return -ENOMEM; + if (!system_agent) { + lib_manager_free_module(module_id); + comp_err(dev, "modules_init(), system_agent_start failed!"); + return -EFAULT; } - const struct sof_module_api_build_info *const mod_buildinfo = - (struct sof_module_api_build_info *) - (module_entry->segment[SOF_MAN_SEGMENT_TEXT].v_base_addr); - - /* Check if module is FDK */ - if (mod_buildinfo->format == IADK_MODULE_API_BUILD_INFO_FORMAT && - mod_buildinfo->api_version_number.full == IADK_MODULE_API_CURRENT_VERSION) { - system_agent = system_agent_start(module_entry_point, module_id, - instance_id, 0, log_handle, - &mod_cfg); - - module_set_private_data(mod, system_agent); - } else - /* Check if module is native */ - if (mod_buildinfo->format == SOF_MODULE_API_BUILD_INFO_FORMAT && - mod_buildinfo->api_version_number.full == SOF_MODULE_API_CURRENT_VERSION) { - /* If start agent for sof loadable */ - is_native_sof = true; - drv->adapter_ops = native_system_agent_start(module_entry_point, module_id, - instance_id, 0, log_handle, &mod_cfg); - } else - return -ENOEXEC; - + module_set_private_data(mod, system_agent); md->mpd.in_buff_size = src_cfg->ibs; md->mpd.out_buff_size = src_cfg->obs; - int ret; - - /* Call module specific init function if exists. */ - if (is_native_sof) { - const struct module_interface *mod_in = drv->adapter_ops; - - /* The order of preference */ - if (mod_in->process) - mod->proc_type = MODULE_PROCESS_TYPE_SOURCE_SINK; - else if (mod_in->process_audio_stream) - mod->proc_type = MODULE_PROCESS_TYPE_STREAM; - else if (mod_in->process_raw_data) - mod->proc_type = MODULE_PROCESS_TYPE_RAW; - else - return -EINVAL; - - ret = mod_in->init(mod); - } else { - mod->proc_type = MODULE_PROCESS_TYPE_SOURCE_SINK; - ret = iadk_wrapper_init(system_agent); - } - - return ret; + return iadk_wrapper_init(system_agent); } /** @@ -192,11 +144,13 @@ static int modules_free(struct processing_module *mod) comp_info(dev, "modules_free()"); ret = iadk_wrapper_free(module_get_private_data(mod)); + if (ret) + comp_err(dev, "modules_free(): iadk_wrapper_free failed with error: %d", ret); /* Free module resources allocated in L2 memory. */ ret = lib_manager_free_module(dev->ipc_config.id); if (ret < 0) - comp_err(dev, "modules_free(), lib_manager_free_module() failed!"); + comp_err(dev, "modules_free(), lib_manager_free_module failed with error: %d", ret); return ret; } diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index a8fec507c86a..153b0d9ee692 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -33,6 +33,7 @@ LOG_MODULE_REGISTER(module_adapter, CONFIG_SOF_LOG_LEVEL); * \brief Create a module adapter component. * \param[in] drv - component driver pointer. * \param[in] config - component ipc descriptor pointer. + * \param[in] spec - passdowned data from driver. * * \return: a pointer to newly created module adapter component on success. NULL on error. */ diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index 199977a2e1f8..903326e49c06 100644 --- a/src/include/sof/lib_manager.h +++ b/src/include/sof/lib_manager.h @@ -136,12 +136,12 @@ void lib_manager_init(void); /* * \brief Register module on driver list * - * param[in] desc - module manifest descriptor + * param[in] component_id - component id * * Creates new comp_driver_info and initialize it for module from library * Adds new module to sof_get()->comp_drivers list */ -int lib_manager_register_module(const struct sof_man_module *const mod); +int lib_manager_register_module(const uint32_t component_id); /* * \brief Allocate module diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index c5ee6f7ea37a..70eae6b21dcf 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -1002,7 +1002,7 @@ const struct comp_driver *ipc4_get_comp_drv(int module_id) #if CONFIG_LIBRARY_MANAGER if (!drv) { /* New module not registered yet. */ - lib_manager_register_module(mod); + lib_manager_register_module(module_id); drv = ipc4_get_drv(mod->uuid); } #endif diff --git a/src/library_manager/lib_manager.c b/src/library_manager/lib_manager.c index dc9fadfdc057..f5cc3237b7cc 100644 --- a/src/library_manager/lib_manager.c +++ b/src/library_manager/lib_manager.c @@ -22,6 +22,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -477,7 +481,6 @@ const struct sof_man_module *lib_manager_get_library_manifest(const uint32_t mod return NULL; desc = (const struct sof_man_fw_desc *)((const char *)ctx->desc + SOF_MAN_ELF_TEXT_OFFSET); - if (entry_index >= desc->header.num_module_entries) { tr_err(&lib_manager_tr, "Entry index %d out of bounds.", entry_index); return NULL; @@ -488,13 +491,91 @@ const struct sof_man_module *lib_manager_get_library_manifest(const uint32_t mod } #if CONFIG_INTEL_MODULES -int lib_manager_register_module(const struct sof_man_module *const mod) +/* + * \brief Load module code, allocate its instance and create a module adapter component. + * \param[in] drv - component driver pointer. + * \param[in] config - component ipc descriptor pointer. + * \param[in] spec - passdowned data from driver. + * + * \return: a pointer to newly created module adapter component on success. NULL on error. + */ +static struct comp_dev *lib_manager_module_create(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + const struct ipc_config_process *args = (struct ipc_config_process *)spec; + const uint32_t module_id = IPC4_MOD_ID(config->id); + const uint32_t instance_id = IPC4_INST_ID(config->id); + const uint32_t log_handle = (uint32_t)drv->tctx; + byte_array_t mod_cfg; + + /* At this point module resources are allocated and it is moved to L2 memory. */ + const uint32_t module_entry_point = lib_manager_allocate_module(drv, config, args->data); + if (!module_entry_point) { + tr_err(&lib_manager_tr, + "lib_manager_module_create(), lib_manager_allocate_module() failed!"); + return NULL; + } + tr_info(&lib_manager_tr, "lib_manager_module_create() start"); + + mod_cfg.data = (uint8_t *)args->data; + /* Intel modules expects DW size here */ + mod_cfg.size = args->size >> 2; + + ((struct comp_driver *)drv)->adapter_ops = native_system_agent_start(module_entry_point, + module_id, instance_id, + 0, log_handle, + &mod_cfg); + + if (!drv->adapter_ops) { + lib_manager_free_module(module_id); + tr_err(&lib_manager_tr, + "lib_manager_module_create(), native_system_agent_start failed!"); + return NULL; + } + + return module_adapter_new(drv, config, spec); +} + + +static void lib_manager_module_free(struct comp_dev *dev) +{ + struct processing_module *mod = comp_get_drvdata(dev); + const struct comp_ipc_config *const config = &(mod->dev->ipc_config); + const uint32_t module_id = config->id; + int ret; + + /* This call invalidates dev, mod and config pointers! */ + module_adapter_free(dev); + + /* Free module resources allocated in L2 memory. */ + ret = lib_manager_free_module(module_id); + if (ret < 0) + comp_err(dev, "modules_free(), lib_manager_free_module() failed!"); +} + +int lib_manager_register_module(const uint32_t component_id) { - /* allocate new comp_driver_info */ + const struct lib_manager_mod_ctx *const ctx = lib_manager_get_mod_ctx(component_id); + const uint32_t entry_index = LIB_MANAGER_GET_MODULE_INDEX(component_id); + const struct sof_module_api_build_info *build_info; struct comp_driver_info *new_drv_info; + const struct sof_man_fw_desc *desc; + const struct sof_man_module *mod; struct comp_driver *drv = NULL; int ret; + /* Get library manifest based on component_id */ + if (!ctx || !ctx->desc) + return -ENOENT; + + desc = (const struct sof_man_fw_desc *)((const char *)ctx->desc + SOF_MAN_ELF_TEXT_OFFSET); + if (entry_index >= desc->header.num_module_entries) { + tr_err(&lib_manager_tr, "Entry index %d out of bounds.", entry_index); + return -ENOENT; + } + + /* allocate new comp_driver_info */ new_drv_info = rmalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM | SOF_MEM_FLAG_COHERENT, sizeof(struct comp_driver_info)); @@ -515,13 +596,41 @@ int lib_manager_register_module(const struct sof_man_module *const mod) ret = -ENOMEM; goto cleanup; } + + mod = (const struct sof_man_module *)((const char *)desc + + SOF_MAN_MODULE_OFFSET(entry_index)); - /* Fill the new_drv_info structure with already known parameters */ - /* Check already registered components */ const struct sof_uuid *const uid = (const struct sof_uuid *)&mod->uuid[0]; declare_dynamic_module_adapter(drv, SOF_COMP_MODULE_ADAPTER, uid, &lib_manager_tr); + build_info = (const struct sof_module_api_build_info *)((const char *)ctx->desc + + mod->segment[SOF_MAN_SEGMENT_TEXT].file_offset); + + tr_info(&lib_manager_tr, + "lib_manager_register_module(): Module API version: %u.%u.%u, format: 0x%x", + build_info->api_version_number.fields.major, + build_info->api_version_number.fields.middle, + build_info->api_version_number.fields.minor, + build_info->format); + + /* Check if module is native */ + if (build_info->format == SOF_MODULE_API_BUILD_INFO_FORMAT && + build_info->api_version_number.full == SOF_MODULE_API_CURRENT_VERSION) { + /* Use lib_manager shim functions */ + drv->ops.create = &lib_manager_module_create; + drv->ops.free = &lib_manager_module_free; + } else { + /* Check if module is not FDK */ + if (build_info->format != IADK_MODULE_API_BUILD_INFO_FORMAT || + build_info->api_version_number.full != IADK_MODULE_API_CURRENT_VERSION) { + tr_err(&lib_manager_tr, + "lib_manager_register_module(): Unsupported module API version"); + return -ENOEXEC; + } + } + + /* Fill the new_drv_info structure with already known parameters */ new_drv_info->drv = drv; /* Register new driver in the list */