diff --git a/app/overlays/mtl/dax_overlay.conf b/app/overlays/mtl/dax_overlay.conf index f73f79addf32..cdfe51d0629d 100644 --- a/app/overlays/mtl/dax_overlay.conf +++ b/app/overlays/mtl/dax_overlay.conf @@ -3,6 +3,7 @@ CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING=y CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK=n CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n CONFIG_SOF_STACK_SIZE=8192 +CONFIG_IDC_TIMEOUT_US=50000 # LLEXT CONFIG_LLEXT_HEAP_SIZE=32 diff --git a/app/overlays/ptl/dax_overlay.conf b/app/overlays/ptl/dax_overlay.conf index 9211e845cc36..4858af591923 100644 --- a/app/overlays/ptl/dax_overlay.conf +++ b/app/overlays/ptl/dax_overlay.conf @@ -3,6 +3,7 @@ CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING=y CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK=n CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL=n CONFIG_SOF_STACK_SIZE=8192 +CONFIG_IDC_TIMEOUT_US=50000 # LLEXT CONFIG_LLEXT_HEAP_SIZE=32 diff --git a/src/audio/module_adapter/module/dolby/dax.c b/src/audio/module_adapter/module/dolby/dax.c index c027f7985932..5778c6f4f21e 100644 --- a/src/audio/module_adapter/module/dolby/dax.c +++ b/src/audio/module_adapter/module/dolby/dax.c @@ -9,6 +9,7 @@ #include +#include #include #include #include @@ -27,6 +28,9 @@ SOF_DEFINE_REG_UUID(dolby_dax_audio_processing); #define DAX_CP_MASK 0x8 #define DAX_VOLUME_MASK 0x10 #define DAX_CTC_MASK 0x20 +#define DAX_PROCESSING_MASK 0x10000 +#define DAX_RESET_MASK 0x20000 +#define DAX_FREE_MASK 0x40000 #define DAX_SWITCH_ENABLE_CONTROL_ID 0 #define DAX_SWITCH_CP_CONTROL_ID 1 @@ -34,6 +38,41 @@ SOF_DEFINE_REG_UUID(dolby_dax_audio_processing); #define DAX_ENUM_PROFILE_CONTROL_ID 0 #define DAX_ENUM_DEVICE_CONTROL_ID 1 +/* dax_adapter_data can be only used within dax module adapter + * and is not visible in dax_inf.h + */ +struct dax_adapter_data { + atomic_t flags; +}; + +enum dax_flag_opt_mode { + DAX_FLAG_READ = 0, + DAX_FLAG_ADD, + DAX_FLAG_CLEAR, +}; + +static uint32_t flag_process(atomic_t *flags, + uint32_t flag, + enum dax_flag_opt_mode opt_mode) +{ + switch (opt_mode) { + case DAX_FLAG_READ: + return atomic_read(flags) & flag; + case DAX_FLAG_ADD: + if ((atomic_read(flags) & flag) == 0) + atomic_add(flags, flag); + break; + case DAX_FLAG_CLEAR: + if ((atomic_read(flags) & flag) == flag) + atomic_sub(flags, flag); + break; + default: + break; + } + + return atomic_read(flags); +} + static int itostr(int num, char *str) { int index = 0, digit_count = 0; @@ -181,6 +220,54 @@ 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) +{ + struct sof_dax *dax_ctx = module_get_private_data(mod); + + 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 sof_dax *dax_ctx = module_get_private_data(mod); + struct dax_adapter_data *adapter_data = (struct dax_adapter_data *)dax_ctx->reserved; + 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->flags, DAX_ENABLE_MASK, DAX_FLAG_ADD); + + 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 int set_tuning_file(struct processing_module *mod, void *value, uint32_t size) { int ret = 0; @@ -324,6 +411,7 @@ static int dax_set_param_wrapper(struct processing_module *mod, int ret = 0; struct comp_dev *dev = mod->dev; struct sof_dax *dax_ctx = module_get_private_data(mod); + struct dax_adapter_data *adapter_data = (struct dax_adapter_data *)dax_ctx->reserved; int32_t tmp_val; switch (id) { @@ -335,25 +423,25 @@ static int dax_set_param_wrapper(struct processing_module *mod, tmp_val = !!tmp_val; if (dax_ctx->enable != tmp_val) { dax_ctx->enable = tmp_val; - dax_ctx->update_flags |= DAX_ENABLE_MASK; + flag_process(&adapter_data->flags, DAX_ENABLE_MASK, DAX_FLAG_ADD); } break; case DAX_PARAM_ID_ABSOLUTE_VOLUME: dax_ctx->volume = *((int32_t *)value); - dax_ctx->update_flags |= DAX_VOLUME_MASK; + flag_process(&adapter_data->flags, DAX_VOLUME_MASK, DAX_FLAG_ADD); break; case DAX_PARAM_ID_OUT_DEVICE: tmp_val = *((int32_t *)value); if (dax_ctx->out_device != tmp_val) { dax_ctx->out_device = tmp_val; - dax_ctx->update_flags |= DAX_DEVICE_MASK; + flag_process(&adapter_data->flags, DAX_DEVICE_MASK, DAX_FLAG_ADD); } break; case DAX_PARAM_ID_PROFILE: tmp_val = *((int32_t *)value); if (dax_ctx->profile != tmp_val) { dax_ctx->profile = tmp_val; - dax_ctx->update_flags |= DAX_PROFILE_MASK; + flag_process(&adapter_data->flags, DAX_PROFILE_MASK, DAX_FLAG_ADD); } break; case DAX_PARAM_ID_CP_ENABLE: @@ -361,7 +449,7 @@ static int dax_set_param_wrapper(struct processing_module *mod, tmp_val = !!tmp_val; if (dax_ctx->content_processing_enable != tmp_val) { dax_ctx->content_processing_enable = tmp_val; - dax_ctx->update_flags |= DAX_CP_MASK; + flag_process(&adapter_data->flags, DAX_CP_MASK, DAX_FLAG_ADD); } break; case DAX_PARAM_ID_CTC_ENABLE: @@ -369,7 +457,7 @@ static int dax_set_param_wrapper(struct processing_module *mod, tmp_val = !!tmp_val; if (dax_ctx->ctc_enable != tmp_val) { dax_ctx->ctc_enable = tmp_val; - dax_ctx->update_flags |= DAX_CTC_MASK; + flag_process(&adapter_data->flags, DAX_CTC_MASK, DAX_FLAG_ADD); } break; case DAX_PARAM_ID_ENDPOINT: @@ -422,76 +510,115 @@ static int update_params_from_buffer(struct processing_module *mod, void *data, static void check_and_update_settings(struct processing_module *mod) { struct sof_dax *dax_ctx = module_get_private_data(mod); + struct dax_adapter_data *adapter_data = (struct dax_adapter_data *)dax_ctx->reserved; - if (dax_ctx->update_flags & DAX_ENABLE_MASK) { + if (flag_process(&adapter_data->flags, DAX_ENABLE_MASK, DAX_FLAG_READ)) { + flag_process(&adapter_data->flags, DAX_ENABLE_MASK, DAX_FLAG_CLEAR); set_enable(mod, dax_ctx->enable); if (dax_ctx->enable) { - dax_ctx->update_flags |= DAX_DEVICE_MASK; - dax_ctx->update_flags |= DAX_VOLUME_MASK; + flag_process(&adapter_data->flags, DAX_DEVICE_MASK, DAX_FLAG_ADD); + flag_process(&adapter_data->flags, DAX_VOLUME_MASK, DAX_FLAG_ADD); } - dax_ctx->update_flags &= ~DAX_ENABLE_MASK; return; } - if (dax_ctx->update_flags & DAX_DEVICE_MASK) { + if (flag_process(&adapter_data->flags, DAX_DEVICE_MASK, DAX_FLAG_READ)) { + flag_process(&adapter_data->flags, DAX_DEVICE_MASK, DAX_FLAG_CLEAR); set_device(mod, dax_ctx->out_device); set_tuning_device(mod, dax_ctx->tuning_device); - dax_ctx->update_flags |= DAX_PROFILE_MASK; - dax_ctx->update_flags &= ~DAX_DEVICE_MASK; + flag_process(&adapter_data->flags, DAX_PROFILE_MASK, DAX_FLAG_ADD); return; } - if (dax_ctx->update_flags & DAX_CTC_MASK) { + if (flag_process(&adapter_data->flags, DAX_CTC_MASK, DAX_FLAG_READ)) { + flag_process(&adapter_data->flags, DAX_CTC_MASK, DAX_FLAG_CLEAR); set_crosstalk_cancellation_enable(mod, dax_ctx->ctc_enable); - dax_ctx->update_flags |= DAX_PROFILE_MASK; - dax_ctx->update_flags &= ~DAX_CTC_MASK; + flag_process(&adapter_data->flags, DAX_PROFILE_MASK, DAX_FLAG_ADD); return; } - if (dax_ctx->update_flags & DAX_PROFILE_MASK) { + if (flag_process(&adapter_data->flags, DAX_PROFILE_MASK, DAX_FLAG_READ)) { + flag_process(&adapter_data->flags, DAX_PROFILE_MASK, DAX_FLAG_CLEAR); set_profile(mod, dax_ctx->profile); if (!dax_ctx->content_processing_enable) - dax_ctx->update_flags |= DAX_CP_MASK; - dax_ctx->update_flags &= ~DAX_PROFILE_MASK; + flag_process(&adapter_data->flags, DAX_CP_MASK, DAX_FLAG_ADD); return; } - if (dax_ctx->update_flags & DAX_CP_MASK) { + if (flag_process(&adapter_data->flags, DAX_CP_MASK, DAX_FLAG_READ)) { + flag_process(&adapter_data->flags, DAX_CP_MASK, DAX_FLAG_CLEAR); set_content_processing_enable(mod, dax_ctx->content_processing_enable); - dax_ctx->update_flags &= ~DAX_CP_MASK; return; } - if (dax_ctx->update_flags & DAX_VOLUME_MASK) { + if (flag_process(&adapter_data->flags, DAX_VOLUME_MASK, DAX_FLAG_READ)) { + flag_process(&adapter_data->flags, DAX_VOLUME_MASK, DAX_FLAG_CLEAR); set_volume(mod, dax_ctx->volume); - dax_ctx->update_flags &= ~DAX_VOLUME_MASK; } } +static int sof_dax_reset(struct processing_module *mod) +{ + struct sof_dax *dax_ctx = module_get_private_data(mod); + struct dax_adapter_data *adapter_data; + + /* dax instance will be established on prepare(), and destroyed on reset() */ + if (dax_ctx) { + adapter_data = (struct dax_adapter_data *)dax_ctx->reserved; + if (flag_process(&adapter_data->flags, DAX_PROCESSING_MASK, DAX_FLAG_READ)) { + flag_process(&adapter_data->flags, DAX_PROCESSING_MASK, DAX_FLAG_ADD); + } else { + destroy_instance(mod); + dax_buffer_release(mod, &dax_ctx->input_buffer); + dax_buffer_release(mod, &dax_ctx->output_buffer); + } + } + + return 0; +} + static int sof_dax_free(struct processing_module *mod) { struct sof_dax *dax_ctx = module_get_private_data(mod); + struct dax_adapter_data *adapter_data; if (dax_ctx) { - dax_free(dax_ctx); - dax_buffer_release(mod, &dax_ctx->persist_buffer); - dax_buffer_release(mod, &dax_ctx->scratch_buffer); - dax_buffer_release(mod, &dax_ctx->tuning_file_buffer); - dax_buffer_release(mod, &dax_ctx->input_buffer); - dax_buffer_release(mod, &dax_ctx->output_buffer); - mod_data_blob_handler_free(mod, dax_ctx->blob_handler); - dax_ctx->blob_handler = NULL; - mod_free(mod, dax_ctx); - module_set_private_data(mod, NULL); + adapter_data = (struct dax_adapter_data *)dax_ctx->reserved; + if (flag_process(&adapter_data->flags, DAX_PROCESSING_MASK, DAX_FLAG_READ)) { + flag_process(&adapter_data->flags, DAX_FREE_MASK, DAX_FLAG_ADD); + } else { + sof_dax_reset(mod); + dax_buffer_release(mod, &dax_ctx->tuning_file_buffer); + mod_data_blob_handler_free(mod, dax_ctx->blob_handler); + dax_ctx->blob_handler = NULL; + mod_free(mod, dax_ctx); + module_set_private_data(mod, NULL); + } } return 0; } +static void check_and_update_state(struct processing_module *mod) +{ + struct sof_dax *dax_ctx = module_get_private_data(mod); + struct dax_adapter_data *adapter_data; + + if (!dax_ctx) + return; + + adapter_data = (struct dax_adapter_data *)dax_ctx->reserved; + if (flag_process(&adapter_data->flags, DAX_FREE_MASK, DAX_FLAG_READ)) { + flag_process(&adapter_data->flags, DAX_FREE_MASK, DAX_FLAG_CLEAR); + sof_dax_free(mod); + } else if (flag_process(&adapter_data->flags, DAX_RESET_MASK, DAX_FLAG_READ)) { + flag_process(&adapter_data->flags, DAX_RESET_MASK, DAX_FLAG_CLEAR); + sof_dax_reset(mod); + } +} + static int sof_dax_init(struct processing_module *mod) { - int ret; struct comp_dev *dev = mod->dev; struct module_data *md = &mod->priv; struct sof_dax *dax_ctx; - uint32_t persist_sz; - uint32_t scratch_sz; + struct dax_adapter_data *adapter_data; - md->private = mod_zalloc(mod, sizeof(struct sof_dax)); + md->private = mod_zalloc(mod, sizeof(struct sof_dax) + sizeof(struct dax_adapter_data)); if (!md->private) { comp_err(dev, "failed to allocate %u bytes for initialization", sizeof(struct sof_dax)); @@ -506,38 +633,18 @@ static int sof_dax_init(struct processing_module *mod) dax_ctx->volume = 1 << 23; dax_ctx->update_flags = 0; + adapter_data = (struct dax_adapter_data *)dax_ctx->reserved; + atomic_init(&adapter_data->flags, 0); + dax_ctx->blob_handler = mod_data_blob_handler_new(mod); if (!dax_ctx->blob_handler) { comp_err(dev, "create blob handler failed"); - ret = -ENOMEM; - goto err; - } - - 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; + mod_free(mod, dax_ctx); + module_set_private_data(mod, NULL); + return -ENOMEM; } - comp_info(dev, "allocated: persist %u, scratch %u. version: %s", - persist_sz, scratch_sz, dax_get_version()); return 0; - -err: - sof_dax_free(mod); - return ret; } static int check_media_format(struct processing_module *mod) @@ -631,6 +738,11 @@ 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; @@ -672,6 +784,7 @@ 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 sof_dax *dax_ctx = module_get_private_data(mod); + struct dax_adapter_data *adapter_data; struct sof_source *source = sources[0]; struct sof_sink *sink = sinks[0]; uint8_t *buf, *bufstart, *bufend, *dax_buf; @@ -680,6 +793,13 @@ static int sof_dax_process(struct processing_module *mod, struct sof_source **so struct dax_buffer *dax_output_buffer = &dax_ctx->output_buffer; uint32_t consumed_bytes, processed_bytes, produced_bytes; + if (!dax_ctx) { + comp_err(mod->dev, "invalid dax context"); + return -EINVAL; + } + + adapter_data = (struct dax_adapter_data *)dax_ctx->reserved; + flag_process(&adapter_data->flags, DAX_PROCESSING_MASK, DAX_FLAG_ADD); /* source stream -> internal input buffer */ consumed_bytes = MIN(source_get_data_available(source), dax_input_buffer->free); source_get_data(source, consumed_bytes, (void *)&buf, (void *)&bufstart, &bufsz); @@ -711,6 +831,8 @@ static int sof_dax_process(struct processing_module *mod, struct sof_source **so dax_buffer_consume(dax_output_buffer, produced_bytes); sink_commit_buffer(sink, produced_bytes); } + flag_process(&adapter_data->flags, DAX_PROCESSING_MASK, DAX_FLAG_CLEAR); + check_and_update_state(mod); return 0; } @@ -855,6 +977,7 @@ static const struct module_interface dolby_dax_audio_processing_interface = { .prepare = sof_dax_prepare, .process = sof_dax_process, .set_configuration = sof_dax_set_configuration, + .reset = sof_dax_reset, .free = sof_dax_free, }; diff --git a/third_party/include/dax_inf.h b/third_party/include/dax_inf.h index 54464f7590b6..5fca20cec1c1 100644 --- a/third_party/include/dax_inf.h +++ b/third_party/include/dax_inf.h @@ -83,7 +83,7 @@ struct sof_dax { int32_t ctc_enable; int32_t content_processing_enable; int32_t volume; - uint32_t update_flags; + uint32_t update_flags; /* Deprecated */ /* DAX buffers */ struct dax_buffer persist_buffer; /* Used for dax instance */ @@ -91,6 +91,9 @@ struct sof_dax { struct dax_buffer input_buffer; struct dax_buffer output_buffer; struct dax_buffer tuning_file_buffer; + + /* Other data */ + uint8_t reserved[]; }; /**