Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/audio/module_adapter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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()
Expand Down
128 changes: 34 additions & 94 deletions src/audio/module_adapter/module/dolby/dax.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,13 @@
// Author: Jun Lai <jun.lai@dolby.com>
//

#include <stdio.h>

#include <rtos/atomic.h>
#include <rtos/init.h>
#include <sof/audio/data_blob.h>
#include <sof/audio/module_adapter/module/generic.h>
#include <sof/compiler_attributes.h>
#include <sof/debug/debug.h>

#include <dax_inf.h>
#include "dax.h"

LOG_MODULE_REGISTER(dolby_dax_audio_processing, CONFIG_SOF_LOG_LEVEL);
SOF_DEFINE_REG_UUID(dolby_dax_audio_processing);
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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, &params_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;
}
Expand All @@ -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, &params_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;
}
Expand All @@ -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, &params_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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -661,6 +601,8 @@ static int sof_dax_init(struct processing_module *mod)
return -ENOMEM;
}

dax_instance_manager_init();

return 0;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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,
Expand Down
78 changes: 78 additions & 0 deletions src/audio/module_adapter/module/dolby/dax.h
Original file line number Diff line number Diff line change
@@ -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 <jun.lai@dolby.com>
*/

#include <sof/audio/module_adapter/module/generic.h>
#include <dax_inf.h>

#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);
2 changes: 1 addition & 1 deletion src/audio/module_adapter/module/dolby/dax.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading
Loading