Skip to content
77 changes: 65 additions & 12 deletions src/audio/module_adapter/module/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,22 @@
*/

#include <rtos/symbol.h>

#include <sof/audio/module_adapter/module/generic.h>
#include <sof/audio/data_blob.h>
#include <sof/lib/fast-get.h>
#include <sof/schedule/dp_schedule.h>
#if CONFIG_IPC_MAJOR_4
#include <ipc4/header.h>
#include <ipc4/module.h>
#include <ipc4/pipeline.h>
#endif

/* The __ZEPHYR__ condition is to keep cmocka tests working */
#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__)
#define MEM_API_CHECK_THREAD(res) __ASSERT((res)->rsrc_mngr == k_current_get(), \
"Module memory API operation from wrong thread")
#define MEM_API_CHECK_THREAD(res) do { \
if ((res)->rsrc_mngr != k_current_get()) \
LOG_WRN("mngr %p != cur %p", (res)->rsrc_mngr, k_current_get()); \
} while (0)
#else
#define MEM_API_CHECK_THREAD(res)
#endif
Expand Down Expand Up @@ -114,7 +121,13 @@ int module_init(struct processing_module *mod)
mod->priv.resources.rsrc_mngr = k_current_get();
#endif
/* Now we can proceed with module specific initialization */
ret = interface->init(mod);
#if CONFIG_IPC_MAJOR_4
if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this safe for the proxy-dp implementation?

ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_INIT_INSTANCE, NULL);
else
#endif
ret = interface->init(mod);

if (ret) {
comp_err(dev, "error %d: module specific init failed", ret);
mod_free_all(mod);
Expand Down Expand Up @@ -433,7 +446,27 @@ int module_prepare(struct processing_module *mod,
return -EPERM;
#endif
if (ops->prepare) {
int ret = ops->prepare(mod, sources, num_of_sources, sinks, num_of_sinks);
int ret;

if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) {
#if CONFIG_IPC_MAJOR_4
union scheduler_dp_thread_ipc_param param = {
.pipeline_state = {
.trigger_cmd = COMP_TRIGGER_PREPARE,
.state = SOF_IPC4_PIPELINE_STATE_RUNNING,
.n_sources = num_of_sources,
.sources = sources,
.n_sinks = num_of_sinks,
.sinks = sinks,
},
};
ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_GLB_SET_PIPELINE_STATE, &param);
#else
ret = 0;
#endif
} else {
ret = ops->prepare(mod, sources, num_of_sources, sinks, num_of_sinks);
}

if (ret) {
comp_err(dev, "error %d: module specific prepare failed", ret);
Expand Down Expand Up @@ -552,11 +585,21 @@ int module_reset(struct processing_module *mod)
if (md->state < MODULE_IDLE)
return 0;
#endif
/* cancel task if DP task*/
if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP && mod->dev->task)
schedule_task_cancel(mod->dev->task);

if (ops->reset) {
ret = ops->reset(mod);
if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) {
#if CONFIG_IPC_MAJOR_4
union scheduler_dp_thread_ipc_param param = {
.pipeline_state.trigger_cmd = COMP_TRIGGER_STOP,
};
ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_GLB_SET_PIPELINE_STATE, &param);
#else
ret = 0;
#endif
} else {
ret = ops->reset(mod);
}

if (ret) {
if (ret != PPL_STATUS_PATH_STOP)
comp_err(mod->dev,
Expand Down Expand Up @@ -627,7 +670,7 @@ int module_free(struct processing_module *mod)
struct module_data *md = &mod->priv;
int ret = 0;

if (ops->free) {
if (ops->free && mod->dev->ipc_config.proc_domain != COMP_PROCESSING_DOMAIN_DP) {
ret = ops->free(mod);
if (ret)
comp_warn(mod->dev, "error: %d", ret);
Expand Down Expand Up @@ -772,8 +815,18 @@ int module_bind(struct processing_module *mod, struct bind_info *bind_data)
if (ret)
return ret;

if (ops->bind)
ret = ops->bind(mod, bind_data);
if (ops->bind) {
if (mod->dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) {
#if CONFIG_IPC_MAJOR_4
union scheduler_dp_thread_ipc_param param = {
.bind_data = bind_data,
};
ret = scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_BIND, &param);
#endif
} else {
ret = ops->bind(mod, bind_data);
}
}

return ret;
}
Expand Down
27 changes: 25 additions & 2 deletions src/audio/module_adapter/module_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@
#include <sof/audio/source_api.h>
#include <sof/audio/audio_buffer.h>
#include <sof/audio/pipeline.h>
#include <sof/schedule/dp_schedule.h>
#include <sof/schedule/ll_schedule_domain.h>
#include <sof/common.h>
#include <sof/platform.h>
#include <sof/ut.h>
#if CONFIG_IPC_MAJOR_4
#include <ipc4/base_fw.h>
#include <ipc4/header.h>
#include <ipc4/module.h>
#endif
#include <rtos/interrupt.h>
#include <rtos/kernel.h>
#include <rtos/symbol.h>
Expand Down Expand Up @@ -1291,8 +1297,20 @@ int module_adapter_trigger(struct comp_dev *dev, int cmd)
dev->state = COMP_STATE_ACTIVE;
return PPL_STATUS_PATH_STOP;
}
if (interface->trigger)

if (interface->trigger) {
#if CONFIG_IPC_MAJOR_4
if (dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) {
/* Process DP module's trigger */
union scheduler_dp_thread_ipc_param param = {
.pipeline_state.trigger_cmd = cmd,
};
return scheduler_dp_thread_ipc(mod, SOF_IPC4_GLB_SET_PIPELINE_STATE,
&param);
}
#endif
return interface->trigger(mod, cmd);
}

return module_adapter_set_state(mod, dev, cmd);
}
Expand Down Expand Up @@ -1354,8 +1372,13 @@ void module_adapter_free(struct comp_dev *dev)

comp_dbg(dev, "start");

if (dev->task)
if (dev->task) {
/* Run DP module's .free() method in its thread context */
#if CONFIG_IPC_MAJOR_4
scheduler_dp_thread_ipc(mod, SOF_IPC4_MOD_DELETE_INSTANCE, NULL);
#endif
schedule_task_cancel(dev->task);
}

ret = module_free(mod);
if (ret)
Expand Down
22 changes: 14 additions & 8 deletions src/include/sof/audio/component_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,23 @@ struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_init);
/** See comp_ops::free */
static inline void comp_free(struct comp_dev *dev)
{
assert(dev->drv->ops.free);
struct task *task = dev->is_shared ||
dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP ? dev->task : NULL;
const struct comp_driver *drv = dev->drv;

assert(drv->ops.free);

/*
* In DP case this will run in DP thread context, so the task can only
* be freed after this.
*/
drv->ops.free(dev);

/* free task if shared component or DP task*/
if ((dev->is_shared || dev->ipc_config.proc_domain == COMP_PROCESSING_DOMAIN_DP) &&
dev->task) {
schedule_task_free(dev->task);
sof_heap_free(dev->drv->user_heap, dev->task);
dev->task = NULL;
if (task) {
schedule_task_free(task);
sof_heap_free(drv->user_heap, task);
}

dev->drv->ops.free(dev);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/schedule/zephyr_dp_schedule_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ int scheduler_dp_thread_ipc(struct processing_module *pmod, enum sof_ipc4_module

if (cmd == SOF_IPC4_MOD_INIT_INSTANCE) {
/* Wait for the DP thread to start */
ret = k_sem_take(&dp_sync[cpu_get_id()], K_MSEC(100));
ret = k_sem_take(&dp_sync[pmod->dev->task->core], K_MSEC(100));
if (ret == -EAGAIN)
return -ETIMEDOUT;
}
Expand Down