diff --git a/src/audio/module_adapter/CMakeLists.txt b/src/audio/module_adapter/CMakeLists.txt index c728ef6d54b8..c4b4a43e99e5 100644 --- a/src/audio/module_adapter/CMakeLists.txt +++ b/src/audio/module_adapter/CMakeLists.txt @@ -41,6 +41,7 @@ endif() else() zephyr_library_sources( module/dolby/dax.c + module/dolby/dax_instance_manager.c ) if (CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK) zephyr_library_sources( @@ -150,6 +151,7 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD) if(CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING) target_include_directories(sof PRIVATE ${PROJECT_SOURCE_DIR}/third_party/include) add_local_sources(sof module/dolby/dax.c) + add_local_sources(sof module/dolby/dax_instance_manager.c) if (CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK) add_local_sources(sof module/dolby/dax_mock.c) else() diff --git a/src/audio/module_adapter/module/dolby/dax.c b/src/audio/module_adapter/module/dolby/dax.c index 0261d3767b3c..ba55dff094df 100644 --- a/src/audio/module_adapter/module/dolby/dax.c +++ b/src/audio/module_adapter/module/dolby/dax.c @@ -7,16 +7,13 @@ // Author: Jun Lai // -#include - #include #include #include #include #include -#include -#include +#include "dax.h" LOG_MODULE_REGISTER(dolby_dax_audio_processing, CONFIG_SOF_LOG_LEVEL); SOF_DEFINE_REG_UUID(dolby_dax_audio_processing); @@ -38,11 +35,6 @@ SOF_DEFINE_REG_UUID(dolby_dax_audio_processing); #define DAX_ENUM_PROFILE_CONTROL_ID 0 #define DAX_ENUM_DEVICE_CONTROL_ID 1 -struct dax_adapter_data { - struct sof_dax dax_ctx; - atomic_t proc_flags; -}; - enum dax_flag_opt_mode { DAX_FLAG_READ = 0, DAX_FLAG_SET, @@ -192,7 +184,7 @@ static int sof_to_dax_buffer_layout(enum sof_ipc_buffer_format sof_buf_fmt) } } -static void dax_buffer_release(struct processing_module *mod, struct dax_buffer *dax_buff) +void dax_buffer_release(struct processing_module *mod, struct dax_buffer *dax_buff) { if (dax_buff->addr) { mod_free(mod, dax_buff->addr); @@ -203,7 +195,7 @@ static void dax_buffer_release(struct processing_module *mod, struct dax_buffer dax_buff->free = 0; } -static int dax_buffer_alloc(struct processing_module *mod, +int dax_buffer_alloc(struct processing_module *mod, struct dax_buffer *dax_buff, uint32_t bytes) { dax_buffer_release(mod, dax_buff); @@ -241,53 +233,12 @@ static void dax_buffer_produce(struct dax_buffer *dax_buff, uint32_t bytes) dax_buff->free = dax_buff->size - dax_buff->avail; } -static void destroy_instance(struct processing_module *mod) +static bool is_enabled(struct processing_module *mod) { struct dax_adapter_data *adapter_data = module_get_private_data(mod); struct sof_dax *dax_ctx = &adapter_data->dax_ctx; - dax_free(dax_ctx); /* free internal dax instance in dax_ctx */ - dax_buffer_release(mod, &dax_ctx->persist_buffer); - dax_buffer_release(mod, &dax_ctx->scratch_buffer); -} - -static int establish_instance(struct processing_module *mod) -{ - int ret = 0; - struct comp_dev *dev = mod->dev; - struct dax_adapter_data *adapter_data = module_get_private_data(mod); - struct sof_dax *dax_ctx = &adapter_data->dax_ctx; - uint32_t persist_sz; - uint32_t scratch_sz; - - persist_sz = dax_query_persist_memory(dax_ctx); - if (dax_buffer_alloc(mod, &dax_ctx->persist_buffer, persist_sz) != 0) { - comp_err(dev, "allocate %u bytes failed for persist", persist_sz); - ret = -ENOMEM; - goto err; - } - scratch_sz = dax_query_scratch_memory(dax_ctx); - if (dax_buffer_alloc(mod, &dax_ctx->scratch_buffer, scratch_sz) != 0) { - comp_err(dev, "allocate %u bytes failed for scratch", scratch_sz); - ret = -ENOMEM; - goto err; - } - ret = dax_init(dax_ctx); - if (ret != 0) { - comp_err(dev, "dax instance initialization failed, ret %d", ret); - goto err; - } - - /* set DAX_ENABLE_MASK bit to trigger the fully update of kcontrol values */ - flag_process(adapter_data, DAX_ENABLE_MASK, DAX_FLAG_SET); - - comp_info(dev, "allocated: persist %u, scratch %u. version: %s", - persist_sz, scratch_sz, dax_get_version()); - return 0; - -err: - destroy_instance(mod); - return ret; + return dax_ctx->enable && dax_ctx->p_dax; } static int set_tuning_file(struct processing_module *mod, void *value, uint32_t size) @@ -313,18 +264,11 @@ static int set_tuning_file(struct processing_module *mod, void *value, uint32_t static int set_enable(struct processing_module *mod, int32_t enable) { - int ret = 0; + int ret; struct dax_adapter_data *adapter_data = module_get_private_data(mod); struct sof_dax *dax_ctx = &adapter_data->dax_ctx; - if (enable) { - ret = dax_set_enable(1, dax_ctx); - dax_ctx->enable = (ret == 0 ? 1 : 0); - } else { - dax_ctx->enable = 0; - dax_set_enable(0, dax_ctx); - } - + ret = dax_set_enable(enable, dax_ctx); comp_info(mod->dev, "set dax enable %d, ret %d", enable, ret); return ret; } @@ -335,10 +279,6 @@ static int set_volume(struct processing_module *mod, int32_t abs_volume) struct dax_adapter_data *adapter_data = module_get_private_data(mod); struct sof_dax *dax_ctx = &adapter_data->dax_ctx; - dax_ctx->volume = abs_volume; - if (!dax_ctx->enable) - return 0; - ret = dax_set_volume(abs_volume, dax_ctx); comp_info(mod->dev, "set volume %d, ret %d", abs_volume, ret); return ret; @@ -350,9 +290,7 @@ static int set_device(struct processing_module *mod, int32_t out_device) struct dax_adapter_data *adapter_data = module_get_private_data(mod); struct sof_dax *dax_ctx = &adapter_data->dax_ctx; - dax_ctx->out_device = out_device; ret = dax_set_device(out_device, dax_ctx); - comp_info(mod->dev, "set device %d, ret %d", out_device, ret); return ret; } @@ -363,9 +301,7 @@ static int set_crosstalk_cancellation_enable(struct processing_module *mod, int3 struct dax_adapter_data *adapter_data = module_get_private_data(mod); struct sof_dax *dax_ctx = &adapter_data->dax_ctx; - dax_ctx->ctc_enable = enable; ret = dax_set_ctc_enable(enable, dax_ctx); - comp_info(mod->dev, "set ctc enable %d, ret %d", enable, ret); return ret; } @@ -381,14 +317,9 @@ static int set_profile(struct processing_module *mod, int32_t profile_id) uint32_t params_sz = 0; void *params; - dax_ctx->profile = profile_id; - if (!dax_ctx->enable) - return 0; - params = dax_find_params(DAX_PARAM_ID_PROFILE, profile_id, ¶ms_sz, dax_ctx); if (params) ret = update_params_from_buffer(mod, params, params_sz); - comp_info(dev, "switched to profile %d, ret %d", profile_id, ret); return ret; } @@ -402,14 +333,9 @@ static int set_tuning_device(struct processing_module *mod, int32_t tuning_devic uint32_t params_sz = 0; void *params; - dax_ctx->tuning_device = tuning_device; - if (!dax_ctx->enable) - return 0; - params = dax_find_params(DAX_PARAM_ID_TUNING_DEVICE, tuning_device, ¶ms_sz, dax_ctx); if (params) ret = update_params_from_buffer(mod, params, params_sz); - comp_info(dev, "switched to tuning device %d, ret %d", tuning_device, ret); return ret; } @@ -423,14 +349,9 @@ static int set_content_processing_enable(struct processing_module *mod, int32_t uint32_t params_sz = 0; void *params; - dax_ctx->content_processing_enable = enable; - if (!dax_ctx->enable) - return 0; - params = dax_find_params(DAX_PARAM_ID_CP_ENABLE, enable, ¶ms_sz, dax_ctx); if (params) ret = update_params_from_buffer(mod, params, params_sz); - comp_info(dev, "set content processing enable %d, ret %d", enable, ret); return ret; } @@ -539,17 +460,34 @@ static int update_params_from_buffer(struct processing_module *mod, void *data, static void check_and_update_settings(struct processing_module *mod) { + int ret; struct dax_adapter_data *adapter_data = module_get_private_data(mod); struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + /* ret equals to 0 mean a new creation or destruction of dax instance */ + ret = check_and_update_instance(mod); + if (ret == 0) { + if (is_enabled(mod) /* A new creation */) { + /* set DAX_ENABLE_MASK bit to trigger the fully update of kcontrol values */ + flag_process(adapter_data, DAX_ENABLE_MASK, DAX_FLAG_SET); + } else if (!dax_ctx->p_dax /* A new destruction */) { + set_enable(mod, 0); + comp_info(mod->dev, "falling back to pass-through mode."); + } + } + if (flag_process(adapter_data, DAX_ENABLE_MASK, DAX_FLAG_READ_AND_CLEAR)) { set_enable(mod, dax_ctx->enable); - if (dax_ctx->enable) { + if (is_enabled(mod)) { flag_process(adapter_data, DAX_DEVICE_MASK, DAX_FLAG_SET); flag_process(adapter_data, DAX_VOLUME_MASK, DAX_FLAG_SET); } return; } + + if (!is_enabled(mod)) + return; + if (flag_process(adapter_data, DAX_DEVICE_MASK, DAX_FLAG_READ_AND_CLEAR)) { set_device(mod, dax_ctx->out_device); set_tuning_device(mod, dax_ctx->tuning_device); @@ -586,7 +524,7 @@ static int sof_dax_reset(struct processing_module *mod) if (flag_process(adapter_data, DAX_PROCESSING_MASK, DAX_FLAG_READ)) { flag_process(adapter_data, DAX_RESET_MASK, DAX_FLAG_SET); } else { - destroy_instance(mod); + unregister_user(mod); dax_buffer_release(mod, &dax_ctx->input_buffer); dax_buffer_release(mod, &dax_ctx->output_buffer); } @@ -644,6 +582,8 @@ static int sof_dax_init(struct processing_module *mod) } adapter_data = module_get_private_data(mod); + adapter_data->comp_id = dev->ipc_config.id; + adapter_data->priority = DAX_USER_PRIORITY_DEFAULT; dax_ctx = &adapter_data->dax_ctx; dax_ctx->enable = 0; dax_ctx->profile = 0; @@ -661,6 +601,8 @@ static int sof_dax_init(struct processing_module *mod) return -ENOMEM; } + dax_instance_manager_init(); + return 0; } @@ -757,11 +699,6 @@ static int sof_dax_prepare(struct processing_module *mod, struct sof_source **so if (ret != 0) return ret; - /* dax instance will be established on prepare(), and destroyed on reset() */ - ret = establish_instance(mod); - if (ret != 0) - return ret; - dax_ctx->sof_period_bytes = dev->frames * dax_ctx->output_media_format.num_channels * dax_ctx->output_media_format.bytes_per_sample; @@ -791,6 +728,9 @@ static int sof_dax_prepare(struct processing_module *mod, struct sof_source **so dax_buffer_produce(&dax_ctx->output_buffer, dax_ctx->output_buffer.size); comp_info(dev, "allocated: ibs %u, obs %u", ibs, obs); + register_user(mod); + check_and_update_instance(mod); + return 0; err: @@ -1013,7 +953,7 @@ static const struct sof_man_module_manifest main_manifest __section(".module") _ .name = "DAX", .uuid = SOF_REG_UUID(dolby_dax_audio_processing), .entry_point = (uint32_t)(&dolby_dax_audio_processing_interface), - .instance_max_count = 1, + .instance_max_count = DAX_MAX_INSTANCE, .type = { .load_type = SOF_MAN_MOD_TYPE_LLEXT, .domain_dp = 1, diff --git a/src/audio/module_adapter/module/dolby/dax.h b/src/audio/module_adapter/module/dolby/dax.h new file mode 100644 index 000000000000..639e4a7611bc --- /dev/null +++ b/src/audio/module_adapter/module/dolby/dax.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE + * + * Copyright(c) 2025 Dolby Laboratories. All rights reserved. + * + * Author: Jun Lai + */ + +#include +#include + +#define DAX_USER_ID_INVALID 0 +#define DAX_MAX_INSTANCE 2 + +enum dax_user_priority { + DAX_USER_PRIORITY_DEFAULT = 0, + DAX_USER_PRIORITY_P0 = 0, + DAX_USER_PRIORITY_P1 = 1, /* Highest priority */ +}; + +struct dax_adapter_data { + struct sof_dax dax_ctx; + atomic_t proc_flags; + uint32_t comp_id; + int32_t priority; +}; + +/** + * @brief Release memory used by a DAX buffer. + * + * @param[in] mod Pointer to the processing module. + * @param[in,out] dax_buff Pointer to the DAX buffer to release. + */ +void dax_buffer_release(struct processing_module *mod, struct dax_buffer *dax_buff); + +/** + * @brief Allocate memory for a DAX buffer. + * + * @param[in] mod Pointer to the processing module. + * @param[in,out] dax_buff Pointer to the DAX buffer to allocate. + * @param[in] bytes Number of bytes to allocate. + * + * @return 0 on success, negative error code on failure. + */ +int dax_buffer_alloc(struct processing_module *mod, struct dax_buffer *dax_buff, uint32_t bytes); + +/** + * @brief Initialize global DAX instance manager state. + */ +void dax_instance_manager_init(void); + +/** + * @brief Register the current module as a DAX instance user. + * + * @param[in] mod Pointer to the processing module. + * + * @return 0 on success, negative error code on failure. + */ +int register_user(struct processing_module *mod); + +/** + * @brief Unregister the current module from DAX instance user management. + * + * @param[in] mod Pointer to the processing module. + * + * @return 0 on success, negative error code on failure. + */ +int unregister_user(struct processing_module *mod); + +/** + * @brief Reconcile DAX instance allocation based on user priority. + * + * @param[in] mod Pointer to the processing module. + * + * @return 0 on success, negative error code on failure. + */ +int check_and_update_instance(struct processing_module *mod); diff --git a/src/audio/module_adapter/module/dolby/dax.toml b/src/audio/module_adapter/module/dolby/dax.toml index c53911a3b33e..e57f29c8c792 100644 --- a/src/audio/module_adapter/module/dolby/dax.toml +++ b/src/audio/module_adapter/module/dolby/dax.toml @@ -7,7 +7,7 @@ name = "DAX" uuid = "40F66C8B-5AA5-4345-8919-53EC431AAA98" affinity_mask = "0x7" - instance_count = "1" + instance_count = "2" domain_types = "1" load_type = LOAD_TYPE module_type = "9" diff --git a/src/audio/module_adapter/module/dolby/dax_instance_manager.c b/src/audio/module_adapter/module/dolby/dax_instance_manager.c new file mode 100644 index 000000000000..f9e2191126c6 --- /dev/null +++ b/src/audio/module_adapter/module/dolby/dax_instance_manager.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE +// +// Copyright(c) 2026 Dolby Laboratories. All rights reserved. +// +// Author: Jun Lai +// + +#include + +#include +#include +#include + +#include "dax.h" + +LOG_MODULE_DECLARE(dolby_dax_audio_processing, CONFIG_SOF_LOG_LEVEL); + +/* A DAX user refers to a DAX component, i.e., the processing_module + * object. When a DAX user intends to process audio data, it first needs + * to create a DAX instance. However, when multiple DAX users coexist + * in the system simultaneously, each DAX user will request its own DAX instance. + * Under limited memory resources, users that make later requests may fail to + * allocate the required memory. To address this, each DAX user is assigned a + * priority level, ensuring that higher-priority users are always granted + * instance resources first, regardless of the order in which the requests + * were made. + * + * The specific priority value will be automatically assigned in the register_user + * function based on the configuration of the DAX component. + */ +struct dax_user { + uint32_t id; /* Component ID */ + enum dax_user_priority priority; + bool allocated; /* Whether the instance memory has been allocated */ +}; + +struct dax_instance_manager { + struct dax_user users[DAX_MAX_INSTANCE]; + + /* The maximum count of DAX instances that can be allocated simultaneously, + * determined by the system memory resource + */ + int32_t available_inst_cnt; + + struct k_spinlock lock; + bool initialized; +}; + +static struct dax_instance_manager inst_mgr; + +static void update_alloc_state_l(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + struct dax_user *user = NULL; + + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (inst_mgr.users[i].id == adapter_data->comp_id) { + user = &inst_mgr.users[i]; + break; + } + } + + if (!user) + return; + + if (dax_ctx->p_dax && dax_ctx->persist_buffer.addr && dax_ctx->scratch_buffer.addr) + user->allocated = true; + else + user->allocated = false; +} + +static int destroy_instance(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + + if (!dax_ctx->p_dax) + return -EFAULT; + + /* free internal dax instance data and set dax_ctx->p_dax to NULL */ + dax_free(dax_ctx); + dax_buffer_release(mod, &dax_ctx->persist_buffer); + dax_buffer_release(mod, &dax_ctx->scratch_buffer); + comp_info(mod->dev, "freed instance"); + + return 0; +} + +static int establish_instance(struct processing_module *mod) +{ + int ret; + struct comp_dev *dev = mod->dev; + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + uint32_t persist_sz; + uint32_t scratch_sz; + + if (dax_ctx->p_dax && dax_ctx->persist_buffer.addr && dax_ctx->scratch_buffer.addr) + return -EEXIST; + + if (dax_ctx->persist_buffer.addr || dax_ctx->scratch_buffer.addr) + destroy_instance(mod); + + persist_sz = dax_query_persist_memory(dax_ctx); + if (dax_buffer_alloc(mod, &dax_ctx->persist_buffer, persist_sz) != 0) { + comp_err(dev, "allocate %u bytes failed for persist", persist_sz); + ret = -ENOMEM; + goto err; + } + scratch_sz = dax_query_scratch_memory(dax_ctx); + if (dax_buffer_alloc(mod, &dax_ctx->scratch_buffer, scratch_sz) != 0) { + comp_err(dev, "allocate %u bytes failed for scratch", scratch_sz); + ret = -ENOMEM; + goto err; + } + ret = dax_init(dax_ctx); + if (ret != 0) { + comp_err(dev, "dax instance initialization failed, ret %d", ret); + goto err; + } + + comp_info(dev, "allocated: persist %u, scratch %u. version: %s", + persist_sz, scratch_sz, dax_get_version()); + return 0; + +err: + destroy_instance(mod); + return ret; +} + +static bool check_priority_l(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct dax_user *user = NULL; + int32_t allocated_cnt = 0; + + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (inst_mgr.users[i].id == adapter_data->comp_id) { + user = &inst_mgr.users[i]; + break; + } + } + + /* If the current module (user) is not existing in user manager, + * instance memory allocation is not allowed. + */ + if (!user) + return false; + + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (inst_mgr.users[i].priority > user->priority && !inst_mgr.users[i].allocated) + return false; + if (inst_mgr.users[i].allocated) + allocated_cnt++; + } + + /* Resource is exhausted */ + if (!user->allocated && allocated_cnt >= inst_mgr.available_inst_cnt) + return false; + + return true; +} + +void dax_instance_manager_init(void) +{ + if (!inst_mgr.initialized) { + k_spinlock_init(&inst_mgr.lock); + /* Assume memory source is sufficient for maximum instances at the beginning */ + inst_mgr.available_inst_cnt = DAX_MAX_INSTANCE; + inst_mgr.initialized = true; + } +} + +int register_user(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + struct dax_user *user = NULL; + k_spinlock_key_t key; + + key = k_spin_lock(&inst_mgr.lock); + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (!user && inst_mgr.users[i].id == DAX_USER_ID_INVALID) + user = &inst_mgr.users[i]; + + if (inst_mgr.users[i].id == adapter_data->comp_id) { + k_spin_unlock(&inst_mgr.lock, key); + return -EEXIST; + } + } + + if (!user) { + k_spin_unlock(&inst_mgr.lock, key); + return -ENOSPC; + } + + user->id = adapter_data->comp_id; + if (dax_ctx->out_device == DAX_DEVICE_SPEAKER) { + /* If the current component's output device is a speaker, it is assigned + * the highest priority. + */ + user->priority = DAX_USER_PRIORITY_P1; + } else if (dax_ctx->out_device == DAX_DEVICE_HEADPHONE) { + user->priority = DAX_USER_PRIORITY_P0; + } else { + user->priority = DAX_USER_PRIORITY_DEFAULT; + } + adapter_data->priority = user->priority; + + if (dax_ctx->p_dax && dax_ctx->persist_buffer.addr && dax_ctx->scratch_buffer.addr) + user->allocated = true; + else + user->allocated = false; + + k_spin_unlock(&inst_mgr.lock, key); + + comp_info(mod->dev, "added user %#x, priority %d", + adapter_data->comp_id, adapter_data->priority); + return 0; +} + +int unregister_user(struct processing_module *mod) +{ + struct dax_adapter_data *adapter_data = module_get_private_data(mod); + struct dax_user *user = NULL; + k_spinlock_key_t key; + + key = k_spin_lock(&inst_mgr.lock); + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (inst_mgr.users[i].id == adapter_data->comp_id) { + user = &inst_mgr.users[i]; + break; + } + } + + if (!user) { + k_spin_unlock(&inst_mgr.lock, key); + return -EINVAL; + } + k_spin_unlock(&inst_mgr.lock, key); + + destroy_instance(mod); + adapter_data->priority = DAX_USER_PRIORITY_DEFAULT; + + key = k_spin_lock(&inst_mgr.lock); + user->id = DAX_USER_ID_INVALID; + user->priority = DAX_USER_PRIORITY_DEFAULT; + user->allocated = false; + k_spin_unlock(&inst_mgr.lock, key); + + comp_info(mod->dev, "removed user %#x", adapter_data->comp_id); + return 0; +} + +int check_and_update_instance(struct processing_module *mod) +{ + k_spinlock_key_t key; + bool has_priority; + int ret = 0; + + key = k_spin_lock(&inst_mgr.lock); + /* Check whether any user that has higher priority is waiting for allocating instance + * memory (allocated == false), if is, current user should release its instance memory + * to make sure the higher priority user can allocate memory successfully. + */ + has_priority = check_priority_l(mod); + k_spin_unlock(&inst_mgr.lock, key); + + if (has_priority) + ret = establish_instance(mod); + else + ret = destroy_instance(mod); + + key = k_spin_lock(&inst_mgr.lock); + update_alloc_state_l(mod); + + /* Auto detect and update the available memory count */ + if (ret == -ENOMEM) { + inst_mgr.available_inst_cnt = 0; + for (int i = 0; i < DAX_MAX_INSTANCE; i++) { + if (inst_mgr.users[i].id != DAX_USER_ID_INVALID && + !inst_mgr.users[i].allocated) { + inst_mgr.available_inst_cnt++; + } + } + } + k_spin_unlock(&inst_mgr.lock, key); + return ret; +} diff --git a/src/audio/module_adapter/module/dolby/llext/CMakeLists.txt b/src/audio/module_adapter/module/dolby/llext/CMakeLists.txt index fe8a965d8c87..377373ddc5b5 100644 --- a/src/audio/module_adapter/module/dolby/llext/CMakeLists.txt +++ b/src/audio/module_adapter/module/dolby/llext/CMakeLists.txt @@ -4,12 +4,13 @@ if(CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK) sof_llext_build("dolby_dax_audio_processing" SOURCES ../dax.c + ../dax_instance_manager.c ../dax_mock.c INCLUDES ${sof_top_dir}/third_party/include ) else() sof_llext_build("dolby_dax_audio_processing" - SOURCES ../dax.c ../llext-wrap.c + SOURCES ../dax.c ../dax_instance_manager.c ../llext-wrap.c INCLUDES ${sof_top_dir}/third_party/include LIBS_PATH ${sof_top_dir}/third_party/lib/ LIBS dax m c gcc diff --git a/third_party/include/dax_inf.h b/third_party/include/dax_inf.h index a257cfd9e24f..8e25f52fc4a7 100644 --- a/third_party/include/dax_inf.h +++ b/third_party/include/dax_inf.h @@ -14,6 +14,12 @@ #include #include +enum dax_device { + DAX_DEVICE_UNSUPPORTED = -1, + DAX_DEVICE_SPEAKER = 0, + DAX_DEVICE_HEADPHONE = 1, +}; + enum dax_frame_fmt { DAX_FMT_UNSUPPORTED = -1, DAX_FMT_SHORT_16 = 4, @@ -144,6 +150,10 @@ int dax_init(struct sof_dax *dax_ctx); /** * @brief Process audio data through the DAX module * + * If DAX is disabled or the DAX instance is invalid (dax_ctx->p_dax is NULL), + * the dax_process will by default perform only copy operations, without any + * audio processing. + * * @param[in] dax_ctx Pointer to the DAX context structure * * @return Bytes of processed. negative error code on failure