diff --git a/src/audio/module_adapter/module/dolby/dax.c b/src/audio/module_adapter/module/dolby/dax.c index a9a71087b483..0d53f47a758d 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 @@ -36,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, @@ -121,20 +122,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 +450,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; } @@ -635,8 +642,6 @@ static int sof_dax_init(struct processing_module *mod) return -ENOMEM; } - dax_instance_manager_init(); - return 0; } @@ -777,21 +782,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); @@ -843,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 */ @@ -895,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: @@ -943,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 || diff --git a/src/audio/module_adapter/module/dolby/dax.h b/src/audio/module_adapter/module/dolby/dax.h index 43c900253dc6..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]; }; /** @@ -48,11 +50,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);