Skip to content

Commit 2b0800b

Browse files
committed
dax: add an instance manager
When multiple DAX components are running simultaneously, instance resources may be insufficient. In this case, DAX instance manager ensures that higher-priority DAX components are always granted instance resources. For DAX components that cannot obtain instance resources in a timely manner, `dax_process` will operate in pass-through mode. Signed-off-by: Jun Lai <jun.lai@dolby.com>
1 parent 4d062a0 commit 2b0800b

File tree

7 files changed

+419
-96
lines changed

7 files changed

+419
-96
lines changed

src/audio/module_adapter/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ endif()
4141
else()
4242
zephyr_library_sources(
4343
module/dolby/dax.c
44+
module/dolby/dax_instance_manager.c
4445
)
4546
if (CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK)
4647
zephyr_library_sources(
@@ -150,6 +151,7 @@ if(NOT CONFIG_COMP_MODULE_SHARED_LIBRARY_BUILD)
150151
if(CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING)
151152
target_include_directories(sof PRIVATE ${PROJECT_SOURCE_DIR}/third_party/include)
152153
add_local_sources(sof module/dolby/dax.c)
154+
add_local_sources(sof module/dolby/dax_instance_manager.c)
153155
if (CONFIG_COMP_DOLBY_DAX_AUDIO_PROCESSING_MOCK)
154156
add_local_sources(sof module/dolby/dax_mock.c)
155157
else()

src/audio/module_adapter/module/dolby/dax.c

Lines changed: 34 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@
77
// Author: Jun Lai <jun.lai@dolby.com>
88
//
99

10-
#include <stdio.h>
11-
1210
#include <rtos/atomic.h>
1311
#include <rtos/init.h>
1412
#include <sof/audio/data_blob.h>
1513
#include <sof/audio/module_adapter/module/generic.h>
1614
#include <sof/compiler_attributes.h>
17-
#include <sof/debug/debug.h>
1815

19-
#include <dax_inf.h>
16+
#include "dax.h"
2017

2118
LOG_MODULE_REGISTER(dolby_dax_audio_processing, CONFIG_SOF_LOG_LEVEL);
2219
SOF_DEFINE_REG_UUID(dolby_dax_audio_processing);
@@ -38,11 +35,6 @@ SOF_DEFINE_REG_UUID(dolby_dax_audio_processing);
3835
#define DAX_ENUM_PROFILE_CONTROL_ID 0
3936
#define DAX_ENUM_DEVICE_CONTROL_ID 1
4037

41-
struct dax_adapter_data {
42-
struct sof_dax dax_ctx;
43-
atomic_t proc_flags;
44-
};
45-
4638
enum dax_flag_opt_mode {
4739
DAX_FLAG_READ = 0,
4840
DAX_FLAG_SET,
@@ -192,7 +184,7 @@ static int sof_to_dax_buffer_layout(enum sof_ipc_buffer_format sof_buf_fmt)
192184
}
193185
}
194186

195-
static void dax_buffer_release(struct processing_module *mod, struct dax_buffer *dax_buff)
187+
void dax_buffer_release(struct processing_module *mod, struct dax_buffer *dax_buff)
196188
{
197189
if (dax_buff->addr) {
198190
mod_free(mod, dax_buff->addr);
@@ -203,7 +195,7 @@ static void dax_buffer_release(struct processing_module *mod, struct dax_buffer
203195
dax_buff->free = 0;
204196
}
205197

206-
static int dax_buffer_alloc(struct processing_module *mod,
198+
int dax_buffer_alloc(struct processing_module *mod,
207199
struct dax_buffer *dax_buff, uint32_t bytes)
208200
{
209201
dax_buffer_release(mod, dax_buff);
@@ -241,53 +233,12 @@ static void dax_buffer_produce(struct dax_buffer *dax_buff, uint32_t bytes)
241233
dax_buff->free = dax_buff->size - dax_buff->avail;
242234
}
243235

244-
static void destroy_instance(struct processing_module *mod)
236+
static bool is_enabled(struct processing_module *mod)
245237
{
246238
struct dax_adapter_data *adapter_data = module_get_private_data(mod);
247239
struct sof_dax *dax_ctx = &adapter_data->dax_ctx;
248240

249-
dax_free(dax_ctx); /* free internal dax instance in dax_ctx */
250-
dax_buffer_release(mod, &dax_ctx->persist_buffer);
251-
dax_buffer_release(mod, &dax_ctx->scratch_buffer);
252-
}
253-
254-
static int establish_instance(struct processing_module *mod)
255-
{
256-
int ret = 0;
257-
struct comp_dev *dev = mod->dev;
258-
struct dax_adapter_data *adapter_data = module_get_private_data(mod);
259-
struct sof_dax *dax_ctx = &adapter_data->dax_ctx;
260-
uint32_t persist_sz;
261-
uint32_t scratch_sz;
262-
263-
persist_sz = dax_query_persist_memory(dax_ctx);
264-
if (dax_buffer_alloc(mod, &dax_ctx->persist_buffer, persist_sz) != 0) {
265-
comp_err(dev, "allocate %u bytes failed for persist", persist_sz);
266-
ret = -ENOMEM;
267-
goto err;
268-
}
269-
scratch_sz = dax_query_scratch_memory(dax_ctx);
270-
if (dax_buffer_alloc(mod, &dax_ctx->scratch_buffer, scratch_sz) != 0) {
271-
comp_err(dev, "allocate %u bytes failed for scratch", scratch_sz);
272-
ret = -ENOMEM;
273-
goto err;
274-
}
275-
ret = dax_init(dax_ctx);
276-
if (ret != 0) {
277-
comp_err(dev, "dax instance initialization failed, ret %d", ret);
278-
goto err;
279-
}
280-
281-
/* set DAX_ENABLE_MASK bit to trigger the fully update of kcontrol values */
282-
flag_process(adapter_data, DAX_ENABLE_MASK, DAX_FLAG_SET);
283-
284-
comp_info(dev, "allocated: persist %u, scratch %u. version: %s",
285-
persist_sz, scratch_sz, dax_get_version());
286-
return 0;
287-
288-
err:
289-
destroy_instance(mod);
290-
return ret;
241+
return dax_ctx->enable && dax_ctx->p_dax;
291242
}
292243

293244
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
313264

314265
static int set_enable(struct processing_module *mod, int32_t enable)
315266
{
316-
int ret = 0;
267+
int ret;
317268
struct dax_adapter_data *adapter_data = module_get_private_data(mod);
318269
struct sof_dax *dax_ctx = &adapter_data->dax_ctx;
319270

320-
if (enable) {
321-
ret = dax_set_enable(1, dax_ctx);
322-
dax_ctx->enable = (ret == 0 ? 1 : 0);
323-
} else {
324-
dax_ctx->enable = 0;
325-
dax_set_enable(0, dax_ctx);
326-
}
327-
271+
ret = dax_set_enable(enable, dax_ctx);
328272
comp_info(mod->dev, "set dax enable %d, ret %d", enable, ret);
329273
return ret;
330274
}
@@ -335,10 +279,6 @@ static int set_volume(struct processing_module *mod, int32_t abs_volume)
335279
struct dax_adapter_data *adapter_data = module_get_private_data(mod);
336280
struct sof_dax *dax_ctx = &adapter_data->dax_ctx;
337281

338-
dax_ctx->volume = abs_volume;
339-
if (!dax_ctx->enable)
340-
return 0;
341-
342282
ret = dax_set_volume(abs_volume, dax_ctx);
343283
comp_info(mod->dev, "set volume %d, ret %d", abs_volume, ret);
344284
return ret;
@@ -350,9 +290,7 @@ static int set_device(struct processing_module *mod, int32_t out_device)
350290
struct dax_adapter_data *adapter_data = module_get_private_data(mod);
351291
struct sof_dax *dax_ctx = &adapter_data->dax_ctx;
352292

353-
dax_ctx->out_device = out_device;
354293
ret = dax_set_device(out_device, dax_ctx);
355-
356294
comp_info(mod->dev, "set device %d, ret %d", out_device, ret);
357295
return ret;
358296
}
@@ -363,9 +301,7 @@ static int set_crosstalk_cancellation_enable(struct processing_module *mod, int3
363301
struct dax_adapter_data *adapter_data = module_get_private_data(mod);
364302
struct sof_dax *dax_ctx = &adapter_data->dax_ctx;
365303

366-
dax_ctx->ctc_enable = enable;
367304
ret = dax_set_ctc_enable(enable, dax_ctx);
368-
369305
comp_info(mod->dev, "set ctc enable %d, ret %d", enable, ret);
370306
return ret;
371307
}
@@ -381,14 +317,9 @@ static int set_profile(struct processing_module *mod, int32_t profile_id)
381317
uint32_t params_sz = 0;
382318
void *params;
383319

384-
dax_ctx->profile = profile_id;
385-
if (!dax_ctx->enable)
386-
return 0;
387-
388320
params = dax_find_params(DAX_PARAM_ID_PROFILE, profile_id, &params_sz, dax_ctx);
389321
if (params)
390322
ret = update_params_from_buffer(mod, params, params_sz);
391-
392323
comp_info(dev, "switched to profile %d, ret %d", profile_id, ret);
393324
return ret;
394325
}
@@ -402,14 +333,9 @@ static int set_tuning_device(struct processing_module *mod, int32_t tuning_devic
402333
uint32_t params_sz = 0;
403334
void *params;
404335

405-
dax_ctx->tuning_device = tuning_device;
406-
if (!dax_ctx->enable)
407-
return 0;
408-
409336
params = dax_find_params(DAX_PARAM_ID_TUNING_DEVICE, tuning_device, &params_sz, dax_ctx);
410337
if (params)
411338
ret = update_params_from_buffer(mod, params, params_sz);
412-
413339
comp_info(dev, "switched to tuning device %d, ret %d", tuning_device, ret);
414340
return ret;
415341
}
@@ -423,14 +349,9 @@ static int set_content_processing_enable(struct processing_module *mod, int32_t
423349
uint32_t params_sz = 0;
424350
void *params;
425351

426-
dax_ctx->content_processing_enable = enable;
427-
if (!dax_ctx->enable)
428-
return 0;
429-
430352
params = dax_find_params(DAX_PARAM_ID_CP_ENABLE, enable, &params_sz, dax_ctx);
431353
if (params)
432354
ret = update_params_from_buffer(mod, params, params_sz);
433-
434355
comp_info(dev, "set content processing enable %d, ret %d", enable, ret);
435356
return ret;
436357
}
@@ -539,17 +460,34 @@ static int update_params_from_buffer(struct processing_module *mod, void *data,
539460

540461
static void check_and_update_settings(struct processing_module *mod)
541462
{
463+
int ret;
542464
struct dax_adapter_data *adapter_data = module_get_private_data(mod);
543465
struct sof_dax *dax_ctx = &adapter_data->dax_ctx;
544466

467+
/* ret equals to 0 mean a new creation or destruction of dax instance */
468+
ret = check_and_update_instance(mod);
469+
if (ret == 0) {
470+
if (is_enabled(mod) /* A new creation */) {
471+
/* set DAX_ENABLE_MASK bit to trigger the fully update of kcontrol values */
472+
flag_process(adapter_data, DAX_ENABLE_MASK, DAX_FLAG_SET);
473+
} else if (!dax_ctx->p_dax /* A new destruction */) {
474+
set_enable(mod, 0);
475+
comp_info(mod->dev, "falling back to pass-through mode.");
476+
}
477+
}
478+
545479
if (flag_process(adapter_data, DAX_ENABLE_MASK, DAX_FLAG_READ_AND_CLEAR)) {
546480
set_enable(mod, dax_ctx->enable);
547-
if (dax_ctx->enable) {
481+
if (is_enabled(mod)) {
548482
flag_process(adapter_data, DAX_DEVICE_MASK, DAX_FLAG_SET);
549483
flag_process(adapter_data, DAX_VOLUME_MASK, DAX_FLAG_SET);
550484
}
551485
return;
552486
}
487+
488+
if (!is_enabled(mod))
489+
return;
490+
553491
if (flag_process(adapter_data, DAX_DEVICE_MASK, DAX_FLAG_READ_AND_CLEAR)) {
554492
set_device(mod, dax_ctx->out_device);
555493
set_tuning_device(mod, dax_ctx->tuning_device);
@@ -586,7 +524,7 @@ static int sof_dax_reset(struct processing_module *mod)
586524
if (flag_process(adapter_data, DAX_PROCESSING_MASK, DAX_FLAG_READ)) {
587525
flag_process(adapter_data, DAX_RESET_MASK, DAX_FLAG_SET);
588526
} else {
589-
destroy_instance(mod);
527+
unregister_user(mod);
590528
dax_buffer_release(mod, &dax_ctx->input_buffer);
591529
dax_buffer_release(mod, &dax_ctx->output_buffer);
592530
}
@@ -644,6 +582,8 @@ static int sof_dax_init(struct processing_module *mod)
644582
}
645583

646584
adapter_data = module_get_private_data(mod);
585+
adapter_data->comp_id = dev->ipc_config.id;
586+
adapter_data->priority = DAX_USER_PRIORITY_DEFAULT;
647587
dax_ctx = &adapter_data->dax_ctx;
648588
dax_ctx->enable = 0;
649589
dax_ctx->profile = 0;
@@ -661,6 +601,8 @@ static int sof_dax_init(struct processing_module *mod)
661601
return -ENOMEM;
662602
}
663603

604+
dax_instance_manager_init();
605+
664606
return 0;
665607
}
666608

@@ -757,11 +699,6 @@ static int sof_dax_prepare(struct processing_module *mod, struct sof_source **so
757699
if (ret != 0)
758700
return ret;
759701

760-
/* dax instance will be established on prepare(), and destroyed on reset() */
761-
ret = establish_instance(mod);
762-
if (ret != 0)
763-
return ret;
764-
765702
dax_ctx->sof_period_bytes = dev->frames *
766703
dax_ctx->output_media_format.num_channels *
767704
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
791728
dax_buffer_produce(&dax_ctx->output_buffer, dax_ctx->output_buffer.size);
792729
comp_info(dev, "allocated: ibs %u, obs %u", ibs, obs);
793730

731+
register_user(mod);
732+
check_and_update_instance(mod);
733+
794734
return 0;
795735

796736
err:
@@ -1013,7 +953,7 @@ static const struct sof_man_module_manifest main_manifest __section(".module") _
1013953
.name = "DAX",
1014954
.uuid = SOF_REG_UUID(dolby_dax_audio_processing),
1015955
.entry_point = (uint32_t)(&dolby_dax_audio_processing_interface),
1016-
.instance_max_count = 1,
956+
.instance_max_count = DAX_MAX_INSTANCE,
1017957
.type = {
1018958
.load_type = SOF_MAN_MOD_TYPE_LLEXT,
1019959
.domain_dp = 1,
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/* SPDX-License-Identifier: BSD-3-Clause
2+
*
3+
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE
4+
*
5+
* Copyright(c) 2025 Dolby Laboratories. All rights reserved.
6+
*
7+
* Author: Jun Lai <jun.lai@dolby.com>
8+
*/
9+
10+
#include <sof/audio/module_adapter/module/generic.h>
11+
#include <dax_inf.h>
12+
13+
#define DAX_USER_ID_INVALID 0
14+
#define DAX_MAX_INSTANCE 2
15+
16+
enum dax_user_priority {
17+
DAX_USER_PRIORITY_DEFAULT = 0,
18+
DAX_USER_PRIORITY_P0 = 0,
19+
DAX_USER_PRIORITY_P1 = 1, /* Highest priority */
20+
};
21+
22+
struct dax_adapter_data {
23+
struct sof_dax dax_ctx;
24+
atomic_t proc_flags;
25+
uint32_t comp_id;
26+
int32_t priority;
27+
};
28+
29+
/**
30+
* @brief Release memory used by a DAX buffer.
31+
*
32+
* @param[in] mod Pointer to the processing module.
33+
* @param[in,out] dax_buff Pointer to the DAX buffer to release.
34+
*/
35+
void dax_buffer_release(struct processing_module *mod, struct dax_buffer *dax_buff);
36+
37+
/**
38+
* @brief Allocate memory for a DAX buffer.
39+
*
40+
* @param[in] mod Pointer to the processing module.
41+
* @param[in,out] dax_buff Pointer to the DAX buffer to allocate.
42+
* @param[in] bytes Number of bytes to allocate.
43+
*
44+
* @return 0 on success, negative error code on failure.
45+
*/
46+
int dax_buffer_alloc(struct processing_module *mod, struct dax_buffer *dax_buff, uint32_t bytes);
47+
48+
/**
49+
* @brief Initialize global DAX instance manager state.
50+
*/
51+
void dax_instance_manager_init(void);
52+
53+
/**
54+
* @brief Register the current module as a DAX instance user.
55+
*
56+
* @param[in] mod Pointer to the processing module.
57+
*
58+
* @return 0 on success, negative error code on failure.
59+
*/
60+
int register_user(struct processing_module *mod);
61+
62+
/**
63+
* @brief Unregister the current module from DAX instance user management.
64+
*
65+
* @param[in] mod Pointer to the processing module.
66+
*
67+
* @return 0 on success, negative error code on failure.
68+
*/
69+
int unregister_user(struct processing_module *mod);
70+
71+
/**
72+
* @brief Reconcile DAX instance allocation based on user priority.
73+
*
74+
* @param[in] mod Pointer to the processing module.
75+
*
76+
* @return 0 on success, negative error code on failure.
77+
*/
78+
int check_and_update_instance(struct processing_module *mod);

src/audio/module_adapter/module/dolby/dax.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
name = "DAX"
88
uuid = "40F66C8B-5AA5-4345-8919-53EC431AAA98"
99
affinity_mask = "0x7"
10-
instance_count = "1"
10+
instance_count = "2"
1111
domain_types = "1"
1212
load_type = LOAD_TYPE
1313
module_type = "9"

0 commit comments

Comments
 (0)