From a7015c3f72f3617704763311b1ebfd69c7fd6f36 Mon Sep 17 00:00:00 2001 From: Jun Lai Date: Tue, 13 Oct 2026 14:02:22 +0800 Subject: [PATCH 1/4] dax: remove invalid null-check Remove dead null-check in sof_dax_process(). Signed-off-by: Jun Lai --- src/audio/module_adapter/module/dolby/dax.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/audio/module_adapter/module/dolby/dax.c b/src/audio/module_adapter/module/dolby/dax.c index a9a71087b483..2ce68ea84809 100644 --- a/src/audio/module_adapter/module/dolby/dax.c +++ b/src/audio/module_adapter/module/dolby/dax.c @@ -777,21 +777,23 @@ static int sof_dax_process(struct processing_module *mod, struct sof_source **so int num_of_sources, struct sof_sink **sinks, int num_of_sinks) { struct dax_adapter_data *adapter_data = module_get_private_data(mod); - struct sof_dax *dax_ctx = &adapter_data->dax_ctx; + struct sof_dax *dax_ctx; struct sof_source *source = sources[0]; struct sof_sink *sink = sinks[0]; uint8_t *buf, *bufstart, *bufend, *dax_buf; size_t bufsz; - struct dax_buffer *dax_input_buffer = &dax_ctx->input_buffer; - struct dax_buffer *dax_output_buffer = &dax_ctx->output_buffer; + struct dax_buffer *dax_input_buffer; + struct dax_buffer *dax_output_buffer; uint32_t consumed_bytes, processed_bytes, produced_bytes; - flag_process(adapter_data, DAX_PROCESSING_MASK, DAX_FLAG_SET); - if (!adapter_data) { comp_err(mod->dev, "invalid adapter data"); return -EINVAL; } + dax_ctx = &adapter_data->dax_ctx; + dax_input_buffer = &dax_ctx->input_buffer; + dax_output_buffer = &dax_ctx->output_buffer; + flag_process(adapter_data, DAX_PROCESSING_MASK, DAX_FLAG_SET); /* source stream -> internal input buffer */ consumed_bytes = MIN(source_get_data_available(source), dax_input_buffer->free); From 915233ae8f2bad1d19748b30d4b13d631778c8f5 Mon Sep 17 00:00:00 2001 From: Jun Lai Date: Tue, 13 Oct 2026 14:02:55 +0800 Subject: [PATCH 2/4] dax: avoid DAX manager initialization race Initialize the instance manager from static data instead of using an unguarded runtime check. Remove the obsolete initializer and its call. Signed-off-by: Jun Lai --- src/audio/module_adapter/module/dolby/dax.c | 2 -- src/audio/module_adapter/module/dolby/dax.h | 5 ----- .../module/dolby/dax_instance_manager.c | 16 ++++------------ 3 files changed, 4 insertions(+), 19 deletions(-) diff --git a/src/audio/module_adapter/module/dolby/dax.c b/src/audio/module_adapter/module/dolby/dax.c index 2ce68ea84809..782ac6cad023 100644 --- a/src/audio/module_adapter/module/dolby/dax.c +++ b/src/audio/module_adapter/module/dolby/dax.c @@ -635,8 +635,6 @@ static int sof_dax_init(struct processing_module *mod) return -ENOMEM; } - dax_instance_manager_init(); - return 0; } diff --git a/src/audio/module_adapter/module/dolby/dax.h b/src/audio/module_adapter/module/dolby/dax.h index 43c900253dc6..a52156c619bb 100644 --- a/src/audio/module_adapter/module/dolby/dax.h +++ b/src/audio/module_adapter/module/dolby/dax.h @@ -48,11 +48,6 @@ void dax_buffer_release(struct processing_module *mod, struct dax_buffer *dax_bu */ 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. * diff --git a/src/audio/module_adapter/module/dolby/dax_instance_manager.c b/src/audio/module_adapter/module/dolby/dax_instance_manager.c index 36ef4f052757..8cec8e30819f 100644 --- a/src/audio/module_adapter/module/dolby/dax_instance_manager.c +++ b/src/audio/module_adapter/module/dolby/dax_instance_manager.c @@ -45,10 +45,12 @@ struct dax_instance_manager { int32_t available_inst_cnt; struct k_spinlock lock; - bool initialized; }; -static struct dax_instance_manager inst_mgr; +/* Zero-initialized global and available_inst_cnt is seeded with the maximum. */ +static struct dax_instance_manager inst_mgr = { + .available_inst_cnt = DAX_MAX_INSTANCE, +}; static void update_alloc_state_l(struct processing_module *mod) { @@ -164,16 +166,6 @@ static bool check_priority_l(struct processing_module *mod) 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 dax_register_user(struct processing_module *mod) { struct dax_adapter_data *adapter_data = module_get_private_data(mod); From b4b05d6ef0ebe2b69b0b1dbc4ad195f5fe9f372d Mon Sep 17 00:00:00 2001 From: Jun Lai Date: Tue, 13 Oct 2026 14:03:44 +0800 Subject: [PATCH 3/4] dax: isolate DAX parameter logging buffer Replace the shared static parameter-formatting buffer with per-instance storage. Pass that storage through get_params_str() to avoid concurrent calls overwriting each other across module instances. Signed-off-by: Jun Lai --- src/audio/module_adapter/module/dolby/dax.c | 17 +++++++++++------ src/audio/module_adapter/module/dolby/dax.h | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/audio/module_adapter/module/dolby/dax.c b/src/audio/module_adapter/module/dolby/dax.c index 782ac6cad023..9f038861681c 100644 --- a/src/audio/module_adapter/module/dolby/dax.c +++ b/src/audio/module_adapter/module/dolby/dax.c @@ -18,7 +18,6 @@ LOG_MODULE_REGISTER(dolby_dax_audio_processing, CONFIG_SOF_LOG_LEVEL); SOF_DEFINE_REG_UUID(dolby_dax_audio_processing); -#define MAX_PARAMS_STR_BUFFER_SIZE 1536 #define DAX_ENABLE_MASK 0x1 #define DAX_PROFILE_MASK 0x2 #define DAX_DEVICE_MASK 0x4 @@ -121,20 +120,24 @@ static int itostr(int num, char *str) return index + digit_count; } -static const char *get_params_str(const void *val, uint32_t val_sz) +static void get_params_str(const void *val, uint32_t val_sz, + char *params_str, size_t params_str_sz) { - static char params_str[MAX_PARAMS_STR_BUFFER_SIZE + 16]; const int32_t *param_val = (const int32_t *)val; const uint32_t param_sz = val_sz >> 2; uint32_t offset = 0; - for (uint32_t i = 0; i < param_sz && offset < MAX_PARAMS_STR_BUFFER_SIZE; i++) { + if (params_str_sz == 0) + return; + params_str[0] = '\0'; + + /* Assume each value is an int32_t with maximum 16 characters when converted to string */ + for (uint32_t i = 0; i < param_sz && offset + 16 < params_str_sz; i++) { offset += itostr(param_val[i], params_str + offset); params_str[offset] = ','; offset++; params_str[offset] = '\0'; } - return ¶ms_str[0]; } static int sof_to_dax_frame_fmt(enum sof_ipc_frame sof_frame_fmt) @@ -445,8 +448,10 @@ static int dax_set_param_wrapper(struct processing_module *mod, break; default: ret = dax_set_param(id, (void *)(value), size, dax_ctx); + get_params_str(value, size, adapter_data->params_str, + sizeof(adapter_data->params_str)); comp_info(dev, "dax_set_param: ret %d, id %#x, size %u, value %s", - ret, id, size >> 2, get_params_str(value, size)); + ret, id, size >> 2, adapter_data->params_str); break; } diff --git a/src/audio/module_adapter/module/dolby/dax.h b/src/audio/module_adapter/module/dolby/dax.h index a52156c619bb..eb50db9cd94e 100644 --- a/src/audio/module_adapter/module/dolby/dax.h +++ b/src/audio/module_adapter/module/dolby/dax.h @@ -13,6 +13,7 @@ #define DAX_USER_ID_INVALID 0 #define DAX_MAX_INSTANCE 2 +#define DAX_PARAMS_STR_BUFFER_SIZE 1536 enum dax_user_priority { DAX_USER_PRIORITY_DEFAULT = 0, @@ -27,6 +28,7 @@ struct dax_adapter_data { int32_t priority; struct dax_buffer cache_tuning_buf; struct k_spinlock lock; + char params_str[DAX_PARAMS_STR_BUFFER_SIZE]; }; /** From aadb750eaafadc3c7ab1fa67114996a300ff05a1 Mon Sep 17 00:00:00 2001 From: Jun Lai Date: Mon, 19 Oct 2026 18:00:26 +0800 Subject: [PATCH 4/4] dax: fix IPC3 configuration issues Recognize tuning-parameter blob configuration ID and reject unsupported configuration IDs. For IPC3, process zero-size SET_VALUE controls convert the volume format. Signed-off-by: Jun Lai --- src/audio/module_adapter/module/dolby/dax.c | 34 ++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/audio/module_adapter/module/dolby/dax.c b/src/audio/module_adapter/module/dolby/dax.c index 9f038861681c..0d53f47a758d 100644 --- a/src/audio/module_adapter/module/dolby/dax.c +++ b/src/audio/module_adapter/module/dolby/dax.c @@ -35,6 +35,8 @@ SOF_DEFINE_REG_UUID(dolby_dax_audio_processing); #define DAX_ENUM_PROFILE_CONTROL_ID 0 #define DAX_ENUM_DEVICE_CONTROL_ID 1 +#define IPC4_DAX_MODULE_CFG_PARAM_BLOB 1 + enum dax_flag_opt_mode { DAX_FLAG_READ = 0, DAX_FLAG_SET, @@ -848,12 +850,12 @@ static int sof_dax_set_configuration(struct processing_module *mod, uint32_t con int32_t dax_param_id = 0; int32_t val; - if (fragment_size == 0) - return 0; - #if CONFIG_IPC_MAJOR_4 const struct sof_ipc4_control_msg_payload *ctl = NULL; + if (fragment_size == 0) + return 0; + switch (config_id) { case 0: /* IPC4_VOLUME */ /* ipc4_peak_volume_config::target_volume */ @@ -900,15 +902,27 @@ static int sof_dax_set_configuration(struct processing_module *mod, uint32_t con return -EINVAL; } break; - default: + case IPC4_DAX_MODULE_CFG_PARAM_BLOB: + dax_param_id = DAX_PARAM_ID_TUNING_FILE; break; + default: + comp_err(dev, "unsupported config id %u", config_id); + return -EINVAL; } #else struct sof_ipc_ctrl_data *ctl = (struct sof_ipc_ctrl_data *)fragment; + /* + * IPC3 SET_VALUE (volume/switch/enum) always arrives with fragment_size 0, + * only SET_DATA (binary) carries a payload size. + */ switch (ctl->cmd) { case SOF_CTRL_CMD_VOLUME: - val = ctl->chanv[0].value; + if (ctl->num_elems < 1) + return -EINVAL; + + /* Host linear volume is Q8.16, DAX expects Q8.23 */ + val = sat_int32(Q_SHIFT_LEFT((int64_t)ctl->chanv[0].value, 16, 23)); dax_param_id = DAX_PARAM_ID_ABSOLUTE_VOLUME; break; case SOF_CTRL_CMD_SWITCH: @@ -948,12 +962,18 @@ static int sof_dax_set_configuration(struct processing_module *mod, uint32_t con return -EINVAL; } break; - default: + case SOF_CTRL_CMD_BINARY: + if (fragment_size == 0) + return 0; + dax_param_id = DAX_PARAM_ID_TUNING_FILE; break; + default: + comp_err(dev, "unsupported control cmd %d", ctl->cmd); + return -EINVAL; } #endif - if (dax_param_id == 0) { + if (dax_param_id == DAX_PARAM_ID_TUNING_FILE) { ret = comp_data_blob_set(dax_ctx->blob_handler, pos, data_offset_size, fragment, fragment_size); if (ret == 0 && (pos == MODULE_CFG_FRAGMENT_LAST ||