diff --git a/doc/groups.dox b/doc/groups.dox
index 4f30724492f7..0a19d0abdbf8 100644
--- a/doc/groups.dox
+++ b/doc/groups.dox
@@ -21,23 +21,43 @@
*/
/**
- * @defgroup module_api Loadable Module & LLEXT Interface
- * @brief Dynamic module loading, processing component lifecycle, and buffer streaming endpoints.
+ * @defgroup module_api Audio Processing Components & Module Interface
+ * @brief Unified interface contracts, lifecycle callbacks, and streaming endpoints for built-in audio components and dynamic LLEXT processing modules (Volume, Mixer, EQ, DRC, SRC, etc.).
*/
/**
- * @defgroup audio_pipeline_api Pipeline & Buffer Infrastructure
- * @brief Audio pipeline execution graphs, stream buffer management, scheduling, and processing threads.
+ * @defgroup audio_pipeline_api Pipeline Graph & Lifecycle Infrastructure
+ * @brief Directed Acyclic Graph (DAG) pipeline creation, scheduling binding, traversal, and lifecycle management.
*/
/**
- * @defgroup audio_components_api Audio Processing Components
- * @brief Built-in and dynamic audio processing modules (Volume, Mixer, EQ, DRC, SRC, ASRC, etc.).
+ * @defgroup component_infra_api Audio Component Infrastructure & Driver Model
+ * @brief Component driver interface, operations vtable, hardware abstraction, IPC binding, and state machines.
+ */
+
+/**
+ * @defgroup audio_buffer_api Audio Buffer & Stream Infrastructure
+ * @brief Interconnect buffers, circular stream buffers, abstract audio buffers, and lockless ring buffers.
+ */
+
+/**
+ * @defgroup audio_format_api Audio Formats & Channel Routing
+ * @brief Channel map parsing, stream conversion, and audio sample saturation routines.
+ */
+
+/**
+ * @defgroup scheduling_api Scheduling Infrastructure
+ * @brief Real-time task schedulers (Low-Latency Timer/DMA, Data Processing preemptible threads, Thread With Budget), scheduling domains, and task state machines.
+ */
+
+/**
+ * @defgroup memory_api Memory Management Infrastructure
+ * @brief System heaps, Virtual Memory Heap (VMH), virtual regions, cold DRAM staging, and audio buffer allocators.
*/
/**
* @defgroup rtos_api RTOS Abstraction Layer
- * @brief RTOS primitives, synchronization (spinlocks, mutexes), memory allocation, clocks, and cache management.
+ * @brief RTOS primitives, synchronization (spinlocks, mutexes), task scheduling, clocks, timers, and cache management.
*/
/**
diff --git a/doc/mainpage.dox b/doc/mainpage.dox
index 2b0c574c0411..e3cec54263aa 100644
--- a/doc/mainpage.dox
+++ b/doc/mainpage.dox
@@ -70,54 +70,113 @@
* Legacy IPC3 protocol structures, stream control envelopes, DAI/buffer tokens, and mixer controls.
*
*
+
*
- * | Loadable Modules & LLEXT |
- * @ref module_api |
+ * Pipeline Graph & Lifecycle |
+ * @ref audio_pipeline_api |
*
- * - @ref src/include/module/module/interface.h "module/interface.h"
- * - @ref src/include/module/module/api_ver.h "module/api_ver.h"
- * - @ref src/include/module/module/base.h "module/base.h"
+ * - @ref src/include/sof/audio/pipeline.h "sof/audio/pipeline.h"
* |
*
- * Dynamic ELF module loading infrastructure via Zephyr LLEXT: dynamic symbol linking, module
- * interface adapters, processing state machine, parameter configuration, and multi-core routing.
+ * Audio pipeline Directed Acyclic Graph (DAG) construction, scheduling task binding (LL/DP),
+ * pipeline hierarchy traversal, and graph-wide state transitions.
* |
*
*
- * | Audio Pipeline & Buffers |
- * @ref audio_pipeline_api |
+ * Component Infrastructure |
+ * @ref component_infra_api |
*
- * - @ref src/include/sof/audio/pipeline.h "sof/audio/pipeline.h"
* - @ref src/include/sof/audio/component.h "sof/audio/component.h"
+ * - @ref src/include/sof/audio/component_ext.h "sof/audio/component_ext.h"
+ * |
+ *
+ * Unified audio component driver model (comp_ops), trigger state machines, IPC module bindings,
+ * copy limits, and remote multi-core IDC communication.
+ * |
+ *
+ *
+ * | Audio Buffers & Streams |
+ * @ref audio_buffer_api |
+ *
* - @ref src/include/sof/audio/buffer.h "sof/audio/buffer.h"
* - @ref src/include/sof/audio/audio_buffer.h "sof/audio/audio_buffer.h"
- * - @ref src/include/sof/schedule/schedule.h "sof/schedule/schedule.h"
+ * - @ref src/include/sof/audio/ring_buffer.h "sof/audio/ring_buffer.h"
+ * - @ref src/include/module/audio/audio_stream.h "module/audio/audio_stream.h"
+ * - @ref src/include/sof/audio/audio_stream.h "sof/audio/audio_stream.h"
* |
*
- * Audio pipeline Directed Acyclic Graph (DAG) construction, task scheduling domains (LL-Timer,
- * LL-DMA, DP threads), lockless ring buffers, audio format negotiation, and multi-channel interleaved/planar routing.
+ * Interconnect buffers (comp_buffer), abstract audio buffers (sof_audio_buffer), circular
+ * stream endpoints, lockless ring buffers, and buffer transaction callbacks.
* |
*
*
- * | Audio Processing Components |
- * @ref audio_components_api |
+ * Audio Formats & Routing |
+ * @ref audio_format_api |
*
- * - @ref src/include/sof/audio/component.h "sof/audio/component.h"
- * - @ref src/include/sof/audio/component_ext.h "sof/audio/component_ext.h"
- * - @ref src/include/sof/audio/smart_amp/smart_amp.h "smart_amp/smart_amp.h"
- * - Modules: Volume, Mixer, EQ FIR/IIR, DRC, SRC, ASRC, Crossover, DC Block, Copier
+ * - @ref src/include/sof/audio/channel_map.h "sof/audio/channel_map.h"
+ * - @ref src/include/sof/audio/format_generic.h "sof/audio/format_generic.h"
+ * |
+ *
+ * Channel mapping extraction, multi-channel spatial routing, and sample format saturation arithmetic.
+ * |
+ *
+ *
+ * | Scheduling Infrastructure |
+ * @ref scheduling_api |
+ *
+ * - @ref src/include/sof/schedule/schedule.h "sof/schedule/schedule.h"
+ * - @ref src/include/sof/schedule/ll_schedule.h "sof/schedule/ll_schedule.h"
+ * - @ref src/include/sof/schedule/ll_schedule_domain.h "sof/schedule/ll_schedule_domain.h"
+ * - @ref src/include/sof/schedule/dp_schedule.h "sof/schedule/dp_schedule.h"
+ * - @ref src/include/sof/schedule/twb_schedule.h "sof/schedule/twb_schedule.h"
+ * - @ref zephyr/include/rtos/task.h "rtos/task.h"
+ * |
+ *
+ * Multi-tiered real-time scheduling infrastructure: Low-Latency (LL) timer and DMA domains,
+ * Data Processing (DP) preemptible worker threads with dynamic deadline evaluation,
+ * Thread With Budget (TWB) cycle accounting, and core task state machines.
+ * |
+ *
+ *
+ * | Audio Processing Components & Modules |
+ * @ref module_api |
+ *
+ * - @ref src/include/module/module/interface.h "module/interface.h"
+ * - @ref src/include/module/module/api_ver.h "module/api_ver.h"
+ * - @ref src/include/module/module/base.h "module/base.h"
+ * - @ref src/include/module/audio/sink_api.h "module/audio/sink_api.h"
+ * - @ref src/include/module/audio/source_api.h "module/audio/source_api.h"
+ * - @ref src/include/module/audio/format.h "module/audio/format.h"
+ * - @ref src/include/module/module/system_service.h "module/system_service.h"
+ * - Built-in Modules: Volume, Mixer, EQ FIR/IIR, DRC, Multiband DRC, SRC, ASRC, Crossover, Smart Amp
* |
*
- * Standard and optimized DSP audio processing modules: smooth volume ramp, mixing, FIR/IIR
- * parametric equalization, dynamic range compression, polyphase sample rate conversion,
- * asynchronous sample rate conversion, and DAI copier sinks/sources.
+ * Standard and dynamic DSP audio processing modules and component contracts: lifecycle callbacks
+ * (init, prepare, process, config), source/sink streaming endpoints, LLEXT dynamic loading,
+ * and module adapter glue.
+ * |
+ *
+ *
+ * | Memory Management Infrastructure |
+ * @ref memory_api |
+ *
+ * - @ref zephyr/include/rtos/alloc.h "rtos/alloc.h"
+ * - @ref src/include/sof/lib/vregion.h "sof/lib/vregion.h"
+ * - @ref zephyr/include/sof/lib/regions_mm.h "sof/lib/regions_mm.h"
+ * - @ref zephyr/include/sof/lib/vpage.h "sof/lib/vpage.h"
+ * - @ref src/include/sof/lib/fast-get.h "sof/lib/fast-get.h"
+ * - @ref zephyr/include/sof/lib/memory.h "sof/lib/memory.h"
+ * |
+ *
+ * Multi-tier DSP memory subsystem: system heaps (sys_heap), Virtual Memory Heap (VMH),
+ * pre-allocated virtual regions (vregion lifetime vs interim), cold DRAM dynamic staging (fast_get),
+ * shared user/kernel buffers, and data cache coherency.
* |
*
*
* | RTOS Abstraction Layer (RAL) |
* @ref rtos_api |
*
- * - @ref zephyr/include/rtos/alloc.h "rtos/alloc.h"
* - @ref zephyr/include/rtos/spinlock.h "rtos/spinlock.h"
* - @ref zephyr/include/rtos/mutex.h "rtos/mutex.h"
* - @ref zephyr/include/rtos/wait.h "rtos/wait.h"
@@ -126,8 +185,9 @@
* - @ref zephyr/include/rtos/interrupt.h "rtos/interrupt.h"
* |
*
- * Operating system abstraction bridging Zephyr RTOS and XTOS: heap management (sys, lpsram, hpsram),
- * spinlocks, mutexes, condition variables, hardware timers, and multi-core Inter-Domain Communication (IDC).
+ * Operating system abstraction bridging Zephyr RTOS and hardware primitives:
+ * spinlocks, mutexes, condition variables, hardware timers, cache writeback/invalidation,
+ * and multi-core Inter-Domain Communication (IDC).
* |
*
*
diff --git a/doc/sof.doxygen.in b/doc/sof.doxygen.in
index b9a2867b4f73..bf9a507f2199 100644
--- a/doc/sof.doxygen.in
+++ b/doc/sof.doxygen.in
@@ -52,6 +52,18 @@ PREDEFINED = "__attribute__(x)= " \
"CONFIG_IPC_MAJOR_4=1" \
"CONFIG_IPC_MAJOR_3=1" \
"CONFIG_COMP_VOLUME=1" \
+ "CONFIG_SOF_VREGIONS=1" \
+ "CONFIG_INCOHERENT=1" \
+ "__ZEPHYR__=1" \
+ "CONFIG_LLEXT=1" \
+ "CONFIG_LLEXT_TYPE_ELF_RELOCATABLE=1" \
+ "CONFIG_SOF_USERSPACE_INTERFACE_ALLOC=1" \
+ "CONFIG_SOF_FULL_ZEPHYR_APPLICATION=1" \
+ "CONFIG_SOF_USERSPACE_USE_SHARED_HEAP=1" \
+ "__DOXYGEN__=1" \
+ "__coherent=" \
+ "__syscall=" \
+ "__must_check=" \
"__packed=" \
"__aligned(x)=" \
"__sparse_cache=" \
diff --git a/posix/include/rtos/task.h b/posix/include/rtos/task.h
index f73384b3cd58..8007d9eb850e 100644
--- a/posix/include/rtos/task.h
+++ b/posix/include/rtos/task.h
@@ -5,6 +5,12 @@
* Author: Liam Girdwood
*/
+/**
+ * @file posix/include/rtos/task.h
+ * @brief POSIX simulation task descriptor, task operations, and task execution state machine.
+ * @ingroup scheduling_api rtos_api
+ */
+
#ifndef __POSIX_RTOS_TASK_H__
#define __POSIX_RTOS_TASK_H__
@@ -20,63 +26,74 @@ struct comp_dev;
struct sof;
struct schedule_data;
-/** \brief Predefined LL task priorities. */
-#define SOF_TASK_PRI_HIGH 0 /* priority level 0 - high */
-#define SOF_TASK_PRI_MED 4 /* priority level 4 - medium */
-#define SOF_TASK_PRI_LOW 9 /* priority level 9 - low */
+/** @brief Predefined Low-Latency task priority levels. */
+#define SOF_TASK_PRI_HIGH 0 /**< Priority level 0 - high (hard real-time). */
+#define SOF_TASK_PRI_MED 4 /**< Priority level 4 - medium. */
+#define SOF_TASK_PRI_LOW 9 /**< Priority level 9 - low (background/idle). */
-/** \brief Predefined EDF task deadlines. */
-#define SOF_TASK_DEADLINE_IDLE UINT64_MAX
-#define SOF_TASK_DEADLINE_ALMOST_IDLE (SOF_TASK_DEADLINE_IDLE - 1)
-#define SOF_TASK_DEADLINE_NOW 0
+/** @brief Predefined EDF task deadlines. */
+#define SOF_TASK_DEADLINE_IDLE UINT64_MAX /**< Idle deadline; run only when nothing else is ready. */
+#define SOF_TASK_DEADLINE_ALMOST_IDLE (SOF_TASK_DEADLINE_IDLE - 1) /**< Almost idle deadline. */
+#define SOF_TASK_DEADLINE_NOW 0 /**< Immediate deadline; run as soon as possible. */
-/** \brief Task counter initial value. */
+/** @brief Task counter initial value. */
#define SOF_TASK_SKIP_COUNT 0xFFFFu
-/** \brief Task states. */
+/**
+ * @brief Lifecycle and execution states of an SOF task.
+ */
enum task_state {
- SOF_TASK_STATE_INIT = 0,
- SOF_TASK_STATE_QUEUED,
- SOF_TASK_STATE_PENDING,
- SOF_TASK_STATE_RUNNING,
- SOF_TASK_STATE_PREEMPTED,
- SOF_TASK_STATE_COMPLETED,
- SOF_TASK_STATE_FREE,
- SOF_TASK_STATE_CANCEL,
- SOF_TASK_STATE_RESCHEDULE,
+ SOF_TASK_STATE_INIT = 0, /**< Task allocated and initialized, not yet scheduled. */
+ SOF_TASK_STATE_QUEUED, /**< Task queued in scheduler run list. */
+ SOF_TASK_STATE_PENDING, /**< Task waiting for preconditions or resource availability. */
+ SOF_TASK_STATE_RUNNING, /**< Task actively executing in thread or timer/DMA handler. */
+ SOF_TASK_STATE_PREEMPTED, /**< Task preempted by higher priority thread or ISR. */
+ SOF_TASK_STATE_COMPLETED, /**< Task execution finished; removed from active scheduling. */
+ SOF_TASK_STATE_FREE, /**< Task resources released. */
+ SOF_TASK_STATE_CANCEL, /**< Task cancelled, pending removal from scheduler. */
+ SOF_TASK_STATE_RESCHEDULE, /**< Return code from run callback requesting rescheduling in next period. */
};
-/** \brief Task operations. */
+/**
+ * @brief Operations and callbacks associated with a scheduling task.
+ */
struct task_ops {
- enum task_state (*run)(void *data); /**< task's main operation */
- void (*complete)(void *data); /**< executed on completion */
- uint64_t (*get_deadline)(void *data); /**< returns current deadline */
+ enum task_state (*run)(void *data); /**< Task's main execution callback function. */
+ void (*complete)(void *data); /**< Optional callback executed on task completion. */
+ uint64_t (*get_deadline)(void *data); /**< Optional callback returning current task deadline timestamp. */
};
-/** \brief Task used by schedulers. */
+/**
+ * @brief Core task structure managed by SOF schedulers in POSIX simulation.
+ */
struct task {
- uint64_t start; /**< start time in [ms] since now (LL only) */
- const struct sof_uuid_entry *uid; /**< Uuid */
- uint16_t type; /**< type of the task (LL or EDF) */
- int16_t priority; /**< priority of the task (used by LL); lower runs first */
- uint16_t core; /**< execution core */
- uint16_t flags; /**< custom flags */
- struct schedule_data *sch; /**< scheduler bound to task */
- enum task_state state; /**< current state */
- void *data; /**< custom data passed to all ops */
- struct list_item list; /**< used by schedulers to hold tasks */
- void *priv_data; /**< task private data */
- struct task_ops ops; /**< task operations */
+ uint64_t start; /**< Scheduler/domain-specific start state (e.g. absolute tick timestamp in LL). */
+ const struct sof_uuid_entry *uid; /**< UUID identifying the task or associated component. */
+ uint16_t type; /**< Scheduler type identifier (SOF_SCHEDULE_*). */
+ int16_t priority; /**< Priority of the task (lower values run first). */
+ uint16_t core; /**< Execution core ID affinity. */
+ uint16_t flags; /**< Custom task flags. */
+ struct schedule_data *sch; /**< Pointer to scheduler instance bound to this task. */
+ enum task_state state; /**< Current task lifecycle state. */
+ void *data; /**< Custom context pointer passed to task operations. */
+ struct list_item list; /**< List node linking task into scheduler run queue. */
+ void *priv_data; /**< Scheduler-specific private task context. */
+ struct task_ops ops; /**< Task operations callbacks table. */
#if defined(CONFIG_SCHEDULE_LOG_CYCLE_STATISTICS)
- uint32_t cycles_sum;
- uint32_t cycles_max;
- uint32_t cycles_cnt;
+ uint32_t cycles_sum; /**< Cumulative execution cycles. */
+ uint32_t cycles_max; /**< Maximum cycle count recorded in a single run. */
+ uint32_t cycles_cnt; /**< Number of completed execution runs. */
#endif
#if CONFIG_PERFORMANCE_COUNTERS
- struct perf_cnt_data pcd;
+ struct perf_cnt_data pcd; /**< Performance counter telemetry data. */
#endif
};
+/**
+ * @brief Check whether a task is active (queued, running, pending, or rescheduling).
+ * @param[in] task Task to check.
+ * @return true if task is in an active execution state, false otherwise.
+ */
static inline bool task_is_active(struct task *task)
{
switch (task->state) {
@@ -91,6 +108,11 @@ static inline bool task_is_active(struct task *task)
}
}
+/**
+ * @brief Execute a task's run callback.
+ * @param[in,out] task Task to execute.
+ * @return Resulting task state returned by the run callback.
+ */
static inline enum task_state task_run(struct task *task)
{
assert(task->ops.run);
@@ -98,12 +120,21 @@ static inline enum task_state task_run(struct task *task)
return task->ops.run(task->data);
}
+/**
+ * @brief Execute a task's complete callback, if registered.
+ * @param[in,out] task Task whose completion callback should be invoked.
+ */
static inline void task_complete(struct task *task)
{
if (task->ops.complete)
task->ops.complete(task->data);
}
+/**
+ * @brief Retrieve a task's deadline timestamp.
+ * @param[in] task Task to query.
+ * @return Current deadline timestamp.
+ */
static inline uint64_t task_get_deadline(struct task *task)
{
assert(task->ops.get_deadline);
@@ -111,15 +142,41 @@ static inline uint64_t task_get_deadline(struct task *task)
return task->ops.get_deadline(task->data);
}
+/**
+ * @brief Primary core main processing loop callback in POSIX simulation.
+ * @param[in,out] data Context pointer passed to task handler.
+ * @return Resulting task state.
+ */
enum task_state task_main_primary_core(void *data);
+/**
+ * @brief Secondary core main processing loop callback in POSIX simulation.
+ * @param[in,out] data Context pointer passed to task handler.
+ * @return Resulting task state.
+ */
enum task_state task_main_secondary_core(void *data);
+/**
+ * @brief Initialize the main task execution infrastructure in POSIX simulation.
+ */
void task_main_init(void);
+/**
+ * @brief Free resources allocated for the main task infrastructure in POSIX simulation.
+ */
void task_main_free(void);
+/**
+ * @brief Start the main SOF background task loop in POSIX simulation.
+ * @param[in,out] sof Global SOF context pointer.
+ * @return 0 on success, negative error code on failure.
+ */
int task_main_start(struct sof *sof);
+
+/**
+ * @brief Signal completion of system startup in POSIX simulation.
+ * @return 0 on success, negative error code on failure.
+ */
int start_complete(void);
#endif /* __POSIX_RTOS_TASK_H__ */
diff --git a/src/include/module/audio/audio_stream.h b/src/include/module/audio/audio_stream.h
index 97cf38657019..f387ba90e458 100644
--- a/src/include/module/audio/audio_stream.h
+++ b/src/include/module/audio/audio_stream.h
@@ -6,6 +6,12 @@
* Adrian Warecki
*/
+/**
+ * @file module/audio/audio_stream.h
+ * @brief Circular audio buffer calculation and wrap utilities for processing modules.
+ * @ingroup module_api
+ */
+
#ifndef __MODULE_AUDIO_AUDIO_STREAM_H__
#define __MODULE_AUDIO_AUDIO_STREAM_H__
@@ -14,6 +20,9 @@
#include
#include "../ipc/stream.h"
+/** \addtogroup module_api
+ * @{
+ */
/**
* @enum sof_audio_buffer_state
@@ -269,4 +278,6 @@ static inline const void *source_cir_buf_rewind_wrap(const void *ptr, const void
return ptr;
}
+/** @}*/
+
#endif /* __MODULE_AUDIO_AUDIO_STREAM_H__ */
diff --git a/src/include/sof/audio/audio_buffer.h b/src/include/sof/audio/audio_buffer.h
index 14ee20c23bf1..f16a50ccd43d 100644
--- a/src/include/sof/audio/audio_buffer.h
+++ b/src/include/sof/audio/audio_buffer.h
@@ -6,7 +6,7 @@
/**
* @file sof/audio/audio_buffer.h
* @brief Audio buffer operations, descriptors, and unified audio buffer interfaces.
- * @ingroup audio_pipeline_api
+ * @ingroup audio_buffer_api
*/
#ifndef __SOF_AUDIO_BUFFER__
@@ -18,48 +18,66 @@
#include
#include
-#define BUFFER_TYPE_LEGACY_BUFFER 1
-#define BUFFER_TYPE_RING_BUFFER 2
+/** \addtogroup audio_buffer_api
+ * @{
+ */
+
+/** \name Buffer type identifiers
+ * @{
+ */
+#define BUFFER_TYPE_LEGACY_BUFFER 1 /**< Legacy comp_buffer type (pipeline 1.0) */
+#define BUFFER_TYPE_RING_BUFFER 2 /**< Lockless async circular ring buffer type (cross-core) */
+/** @}*/
/* forward def */
struct sof_audio_buffer;
+/**
+ * \brief Audio buffer virtual operations table.
+ */
struct audio_buffer_ops {
/**
- * @brief this method must free all structures allocated by buffer implementation
- * and the buffer itself
- * OBLIGATORY
+ * \brief Free all structures allocated by buffer implementation and the buffer itself.
+ *
+ * MANDATORY: audio_buffer_free() invokes this callback unconditionally.
+ *
+ * \param[in,out] buffer Buffer to free.
*/
void (*free)(struct sof_audio_buffer *buffer);
/**
- * @brief clean all buffer data, set buffer positions to initial, leaving config as is
- * the procedure is to be called only when buffer is not in use
- * OPTIONAL
+ * \brief Clean all buffer data and reset positions to initial state, keeping configuration.
+ *
+ * OPTIONAL: procedure is to be called only when buffer is not in use.
+ *
+ * \param[in,out] buffer Buffer to reset.
*/
void (*reset)(struct sof_audio_buffer *buffer);
/**
- * OPTIONAL: Notification to the sink implementation about changes in audio format
- *
- * Once any of *audio_stream_params elements changes, the implementation of
- * sink may need to perform some extra operations.
- * This callback will be called immediately after any change
- *
- * @retval 0 if success, negative if new parameters are not supported
+ * \brief Notification callback invoked on audio format modification.
+ * \param[in,out] buffer Buffer whose format changed.
+ * \retval 0 On success.
+ * \retval negative If new parameters are not supported.
*/
int (*on_audio_format_set)(struct sof_audio_buffer *buffer);
/**
- * OPTIONAL
- * see sink_set_params comments
+ * \brief Configure IPC stream parameters on buffer.
+ * \param[in,out] buffer Buffer to configure.
+ * \param[in] params Stream parameters to apply.
+ * \param[in] force_update If true, overwrite parameters unconditionally.
+ * \return 0 on success, negative error code on failure.
*/
int (*audio_set_ipc_params)(struct sof_audio_buffer *buffer,
struct sof_ipc_stream_params *params, bool force_update);
/**
- * OPTIONAL
- * see comment for sink_set_alignment_constants
+ * \brief Configure alignment constraints on buffer.
+ * \param[in,out] buffer Buffer to configure.
+ * \param[in] byte_align Byte alignment requirement in bytes.
+ * \param[in] frame_align_req Frame alignment requirement in frames.
+ * \return 0 on success, negative error code on failure.
*/
int (*set_alignment_constants)(struct sof_audio_buffer *buffer,
const uint32_t byte_align,
@@ -67,106 +85,71 @@ struct audio_buffer_ops {
};
struct mod_alloc_ctx;
-/* base class for all buffers, all buffers must inherit from it */
+
+/**
+ * \brief Base class for all audio buffers. All audio buffers must inherit from it.
+ */
struct sof_audio_buffer {
CORE_CHECK_STRUCT_FIELD;
- /* type of the buffer BUFFER_TYPE_* */
- uint32_t buffer_type;
+ uint32_t buffer_type; /**< Type of the buffer (BUFFER_TYPE_*) */
- bool is_shared; /* buffer structure is shared between 2 cores */
+ bool is_shared; /**< Buffer structure is shared between 2 cores */
#if CONFIG_PIPELINE_2_0
/**
- * sink API of an additional buffer
- * of any type at data input
- *
- * to be removed when hybrid buffers are no longer needed
+ * Sink API of an additional buffer of any type at data input.
+ * To be removed when hybrid buffers are no longer needed.
*/
struct sof_audio_buffer *secondary_buffer_sink;
/**
- * source API of an additional buffer
- * at data output
+ * Source API of an additional buffer at data output.
*/
struct sof_audio_buffer *secondary_buffer_source;
#endif /* CONFIG_PIPELINE_2_0 */
- /* effective runtime stream params
- * before pipelin2.0 is ready, stream params may be kept in audio_stream structure
- * also for hybrid buffering audio params need to be shared between primary and secondary
- * buffers
- *
- * So currently only a pointer to effective stream params is here.
- * Note that the same pointer MUST be set in source and sink api (kept there for
- * performance reasons)
+ /**
+ * Pointer to effective runtime stream parameters.
*/
struct sof_audio_stream_params *audio_stream_params;
-
/* private: */
- struct sof_source _source_api; /**< src api handler */
- struct sof_sink _sink_api; /**< sink api handler */
+ struct sof_source _source_api; /**< Source API interface handler */
+ struct sof_sink _sink_api; /**< Sink API interface handler */
/* virtual methods */
- const struct audio_buffer_ops *ops;
+ const struct audio_buffer_ops *ops; /**< Virtual methods table */
- /*
- * legacy params, needed for pipeline binding/iterating, not for data buffering
- * should not be in struct sof_audio_buffer at all, kept for pipeline2.0 transition
- */
- bool walking; /**< indicates if the buffer is being walked */
+ bool walking; /**< Indicates if the buffer is being walked in pipeline graph */
- struct mod_alloc_ctx *alloc;
+ struct mod_alloc_ctx *alloc; /**< Allocation context */
};
#if CONFIG_PIPELINE_2_0
-/*
- * attach a secondary buffer (any type) before buffer (when at_input == true) or behind a buffer
- *
- * before buffer (at_input == true):
- * 2.0 mod ==> (sink_API) secondary buffer ==>
- * ==> comp_buffer (audio_stream or source API) ==> 1.0 mod
- *
- * after buffer (at_input == false):
- * 1.0 mod ==> (audio_stream or sink API) ==> comp_buffer ==>
- * ==> secondary buffer(source API) == 2.0 mod
- *
- * If a secondary buffer is attached, it replaces source or sink interface of audio_stream
- * allowing the module connected to it using all properties of secondary buffer (like
- * lockless cross-core connection in case of ring_buffer etc.) keeping legacy interface
- * to other modules
- *
- * buffer_sync_secondary_buffer must be called every 1 ms to move data to/from
- * secondary buffer to comp_buffer
- *
- * @param buffer pointer to a buffer
- * @param at_input true indicates that a secondary buffer is located at data input, replacing
- * sink API of audio_stream
- * false indicates that a secondary buffer is located at data output, replacing
- * source API of audio_stream
- * @param secondary_buffer pointer to a buffer to be attached
- *
- * to be removed when hybrid buffers are no longer needed
+/**
+ * \brief Attach a secondary buffer at data input or data output of primary buffer.
+ * \param[in,out] buffer Pointer to primary audio buffer.
+ * \param[in] at_input True if secondary buffer is placed at input, false if at output.
+ * \param[in,out] secondary_buffer Pointer to secondary buffer to attach.
+ * \return 0 on success, or negative error code on failure.
*/
int audio_buffer_attach_secondary_buffer(struct sof_audio_buffer *buffer, bool at_input,
struct sof_audio_buffer *secondary_buffer);
-/*
- * move data from/to secondary buffer, must be called periodically as described above
- *
- * @param buffer pointer to a buffer
- * @param limit data copy limit. Indicates maximum amount of data that will be moved from/to
- * secondary buffer in an operation
- *
- * to be removed when hybrid buffers are no longer needed
+/**
+ * \brief Synchronize data between primary and secondary hybrid buffers.
+ * \param[in,out] buffer Pointer to audio buffer.
+ * \param[in] limit Maximum number of bytes to move.
+ * \return 0 on success, or negative error code on failure.
*/
int audio_buffer_sync_secondary_buffer(struct sof_audio_buffer *buffer, size_t limit);
/**
- * @brief return a handler to sink API of audio_buffer.
- * the handler may be used by helper functions defined in sink_api.h
+ * \brief Return pointer to sink interface of audio buffer.
+ * \param[in] buffer Pointer to audio buffer.
+ * \return Pointer to sink interface.
*/
static inline
struct sof_sink *audio_buffer_get_sink(struct sof_audio_buffer *buffer)
@@ -178,8 +161,9 @@ struct sof_sink *audio_buffer_get_sink(struct sof_audio_buffer *buffer)
}
/**
- * @brief return a handler to source API of audio_buffer
- * the handler may be used by helper functions defined in source_api.h
+ * \brief Return pointer to source interface of audio buffer.
+ * \param[in] buffer Pointer to audio buffer.
+ * \return Pointer to source interface.
*/
static inline
struct sof_source *audio_buffer_get_source(struct sof_audio_buffer *buffer)
@@ -193,8 +177,9 @@ struct sof_source *audio_buffer_get_source(struct sof_audio_buffer *buffer)
#else /* CONFIG_PIPELINE_2_0 */
/**
- * @brief return a handler to sink API of audio_buffer.
- * the handler may be used by helper functions defined in sink_api.h
+ * \brief Return pointer to sink interface of audio buffer.
+ * \param[in] buffer Pointer to audio buffer.
+ * \return Pointer to sink interface.
*/
static inline
struct sof_sink *audio_buffer_get_sink(struct sof_audio_buffer *buffer)
@@ -204,8 +189,9 @@ struct sof_sink *audio_buffer_get_sink(struct sof_audio_buffer *buffer)
}
/**
- * @brief return a handler to source API of audio_buffer
- * the handler may be used by helper functions defined in source_api.h
+ * \brief Return pointer to source interface of audio buffer.
+ * \param[in] buffer Pointer to audio buffer.
+ * \return Pointer to source interface.
*/
static inline
struct sof_source *audio_buffer_get_source(struct sof_audio_buffer *buffer)
@@ -216,48 +202,92 @@ struct sof_source *audio_buffer_get_source(struct sof_audio_buffer *buffer)
#endif /* CONFIG_PIPELINE_2_0 */
+/**
+ * \brief Check if audio buffer is shared across cores.
+ * \param[in] buffer Pointer to audio buffer.
+ * \return True if shared, false otherwise.
+ */
static inline bool audio_buffer_is_shared(struct sof_audio_buffer *buffer)
{
return buffer->is_shared;
}
+/**
+ * \brief Check if buffer hardware parameters are configured.
+ * \param[in] buffer Pointer to audio buffer.
+ * \return True if configured, false otherwise.
+ */
static inline bool audio_buffer_hw_params_configured(struct sof_audio_buffer *buffer)
{
return buffer->audio_stream_params->state != AUDIOBUF_STATE_INITIAL;
}
+/**
+ * \brief Mark buffer hardware parameters as configured (state set to READY).
+ * \param[in,out] buffer Pointer to audio buffer.
+ */
static inline void audio_buffer_set_hw_params_configured(struct sof_audio_buffer *buffer)
{
buffer->audio_stream_params->state = AUDIOBUF_STATE_READY;
}
+/**
+ * \brief Reset buffer parameters state to initial.
+ * \param[in,out] buffer Pointer to audio buffer.
+ */
static inline void audio_buffer_reset_params(struct sof_audio_buffer *buffer)
{
buffer->audio_stream_params->state = AUDIOBUF_STATE_INITIAL;
}
+/**
+ * \brief Retrieve current buffer state.
+ * \param[in] buffer Pointer to audio buffer.
+ * \return Current buffer state (enum sof_audio_buffer_state).
+ */
static inline enum sof_audio_buffer_state audio_buffer_get_state(
const struct sof_audio_buffer *buffer)
{
return buffer->audio_stream_params->state;
}
+/**
+ * \brief Set buffer state.
+ * \param[in,out] buffer Pointer to audio buffer.
+ * \param[in] state New state to assign.
+ */
static inline void audio_buffer_set_state(struct sof_audio_buffer *buffer,
enum sof_audio_buffer_state state)
{
buffer->audio_stream_params->state = state;
}
+/**
+ * \brief Mark buffer state as end-of-stream (EOS).
+ * \param[in,out] buffer Pointer to audio buffer.
+ */
static inline void audio_buffer_set_eos(struct sof_audio_buffer *buffer)
{
buffer->audio_stream_params->state = AUDIOBUF_STATE_END_OF_STREAM;
}
+/**
+ * \brief Retrieve channel map value for a given channel index.
+ * \param[in] buffer Pointer to audio buffer.
+ * \param[in] index Channel index.
+ * \return Channel map value.
+ */
static inline uint16_t audio_buffer_get_chmap(struct sof_audio_buffer *buffer, size_t index)
{
return buffer->audio_stream_params->chmap[index];
}
+/**
+ * \brief Set channel map value for a given channel index.
+ * \param[in,out] buffer Pointer to audio buffer.
+ * \param[in] index Channel index.
+ * \param[in] value Channel map value to set.
+ */
static inline void audio_buffer_set_chmap(struct sof_audio_buffer *buffer, size_t index,
uint16_t value)
{
@@ -265,7 +295,9 @@ static inline void audio_buffer_set_chmap(struct sof_audio_buffer *buffer, size_
}
/**
- * @brief return a handler to stream params structure
+ * \brief Retrieve pointer to runtime stream parameters.
+ * \param[in] buffer Pointer to audio buffer.
+ * \return Pointer to runtime stream parameters.
*/
static inline
struct sof_audio_stream_params *audio_buffer_get_stream_params(struct sof_audio_buffer *buffer)
@@ -274,9 +306,13 @@ struct sof_audio_stream_params *audio_buffer_get_stream_params(struct sof_audio_
}
/**
- * @brief return a pointer to struct sof_audio_buffer from sink pointer
- * NOTE! ensure that sink is really provided by sof_audio_buffer
- * otherwise a random value will be returned
+ * \brief Retrieve enclosing sof_audio_buffer from sink interface pointer.
+ *
+ * NOTE: Ensure that sink is really embedded within a sof_audio_buffer;
+ * otherwise an invalid derived pointer will be returned.
+ *
+ * \param[in] sink Pointer to sink interface.
+ * \return Pointer to enclosing struct sof_audio_buffer.
*/
static inline struct sof_audio_buffer *sof_audio_buffer_from_sink(struct sof_sink *sink)
{
@@ -284,9 +320,13 @@ static inline struct sof_audio_buffer *sof_audio_buffer_from_sink(struct sof_sin
}
/**
- * @brief return a pointer to struct sof_audio_buffer from source pointer
- * NOTE! ensure that source is really provided by sof_audio_buffer
- * otherwise a random value will be returned
+ * \brief Retrieve enclosing sof_audio_buffer from source interface pointer.
+ *
+ * NOTE: Ensure that source is really embedded within a sof_audio_buffer;
+ * otherwise an invalid derived pointer will be returned.
+ *
+ * \param[in] source Pointer to source interface.
+ * \return Pointer to enclosing struct sof_audio_buffer.
*/
static inline struct sof_audio_buffer *sof_audio_buffer_from_source(struct sof_source *source)
{
@@ -294,23 +334,14 @@ static inline struct sof_audio_buffer *sof_audio_buffer_from_source(struct sof_s
}
/**
- * @brief initialize audio buffer structures
- *
- * @param buffer pointer to the audio_buffer
- * @param buffer_type a type of the buffer, BUFFER_TYPE_*
- * @param is_shared indicates if the buffer will be shared between cores
- * @param source_ops pointer to virtual methods table for source API
- * @param sink_ops pointer to virtual methods table for sink API
- * @param audio_buffer_ops pointer to required buffer virtual methods implementation
- * @param audio_stream_params pointer to audio stream (currently kept in buffer implementation)
- *
- * in sink_ops and source_ops API if there's no implemented of following methods:
- * on_audio_format_set
- * audio_set_ipc_params
- * set_alignment_constants
- *
- * default implementation will be used instead, redirecting those calls to proper
- * audio_buffer_ops operations
+ * \brief Initialize audio buffer structure and virtual operation tables.
+ * \param[in,out] buffer Pointer to audio buffer.
+ * \param[in] buffer_type Buffer type identifier (BUFFER_TYPE_*).
+ * \param[in] is_shared True if buffer is shared between cores.
+ * \param[in] source_ops Pointer to source operations table.
+ * \param[in] sink_ops Pointer to sink operations table.
+ * \param[in] audio_buffer_ops Pointer to audio buffer operations table.
+ * \param[in,out] audio_stream_params Pointer to audio stream parameters.
*/
void audio_buffer_init(struct sof_audio_buffer *buffer, uint32_t buffer_type, bool is_shared,
const struct source_ops *source_ops, const struct sink_ops *sink_ops,
@@ -318,13 +349,14 @@ void audio_buffer_init(struct sof_audio_buffer *buffer, uint32_t buffer_type, bo
struct sof_audio_stream_params *audio_stream_params);
/**
- * @brief free buffer and all allocated resources
+ * \brief Free audio buffer and all allocated resources.
+ * \param[in,out] buffer Pointer to audio buffer to free.
*/
void audio_buffer_free(struct sof_audio_buffer *buffer);
/**
- * @brief clean all buffer data, set buffer positions to initial, leaving config as is
- * the procedure is to be called only when buffer is not in use
+ * \brief Reset all buffer data and positions leaving configuration intact.
+ * \param[in,out] buffer Pointer to audio buffer.
*/
static inline
void audio_buffer_reset(struct sof_audio_buffer *buffer)
@@ -342,18 +374,70 @@ void audio_buffer_reset(struct sof_audio_buffer *buffer)
}
/* Audio-buffer wrappers for the source-sink API */
+
+/**
+ * \brief Set IPC stream parameters via source interface wrapper.
+ * \param[in,out] source Pointer to source interface.
+ * \param[in] params Stream parameters to apply.
+ * \param[in] force_update If true, overwrite parameters unconditionally.
+ * \return 0 on success, or negative error code on failure.
+ */
int audio_buffer_source_set_ipc_params(struct sof_source *source,
struct sof_ipc_stream_params *params, bool force_update);
+
+/**
+ * \brief Audio format set callback via source interface wrapper.
+ * \param[in,out] source Pointer to source interface.
+ * \return 0 on success, or negative error code on failure.
+ */
int audio_buffer_source_on_audio_format_set(struct sof_source *source);
+
+/**
+ * \brief Set alignment constraints via source interface wrapper.
+ * \param[in,out] source Pointer to source interface.
+ * \param[in] byte_align Byte alignment requirement in bytes.
+ * \param[in] frame_align_req Frame alignment requirement in frames.
+ * \return 0 on success, or negative error code on failure.
+ */
int audio_buffer_source_set_alignment_constants(struct sof_source *source,
const uint32_t byte_align,
const uint32_t frame_align_req);
+
+/**
+ * \brief Set IPC stream parameters via sink interface wrapper.
+ * \param[in,out] sink Pointer to sink interface.
+ * \param[in] params Stream parameters to apply.
+ * \param[in] force_update If true, overwrite parameters unconditionally.
+ * \return 0 on success, or negative error code on failure.
+ */
int audio_buffer_sink_set_ipc_params(struct sof_sink *sink, struct sof_ipc_stream_params *params,
bool force_update);
+
+/**
+ * \brief Audio format set callback via sink interface wrapper.
+ * \param[in,out] sink Pointer to sink interface.
+ * \return 0 on success, or negative error code on failure.
+ */
int audio_buffer_sink_on_audio_format_set(struct sof_sink *sink);
+
+/**
+ * \brief Set alignment constraints via sink interface wrapper.
+ * \param[in,out] sink Pointer to sink interface.
+ * \param[in] byte_align Byte alignment requirement in bytes.
+ * \param[in] frame_align_req Frame alignment requirement in frames.
+ * \return 0 on success, or negative error code on failure.
+ */
int audio_buffer_sink_set_alignment_constants(struct sof_sink *sink,
const uint32_t byte_align,
const uint32_t frame_align_req);
+
+/**
+ * \brief Get linear free time (LFT) duration in microseconds from sink interface wrapper.
+ * \param[in] sink Pointer to sink interface.
+ * \return Buffered duration in microseconds (us_in_buffer) calculated from source available data and sample rate.
+ */
uint32_t audio_buffer_sink_get_lft(struct sof_sink *sink);
+/** @}*/
+
#endif /* __SOF_AUDIO_BUFFER__ */
diff --git a/src/include/sof/audio/audio_stream.h b/src/include/sof/audio/audio_stream.h
index 93d42d095dc1..45adb1e4a38a 100644
--- a/src/include/sof/audio/audio_stream.h
+++ b/src/include/sof/audio/audio_stream.h
@@ -30,7 +30,7 @@
#include
#include
-/** \addtogroup audio_pipeline_api
+/** \addtogroup audio_buffer_api
* @{
*/
diff --git a/src/include/sof/audio/buffer.h b/src/include/sof/audio/buffer.h
index 6744bbf1b5ef..9f9f7df672b5 100644
--- a/src/include/sof/audio/buffer.h
+++ b/src/include/sof/audio/buffer.h
@@ -8,7 +8,7 @@
/**
* @file sof/audio/buffer.h
* @brief Component interconnect buffer allocation and stream handling.
- * @ingroup audio_pipeline_api
+ * @ingroup audio_buffer_api
*/
#ifndef __SOF_AUDIO_BUFFER_H__
@@ -37,6 +37,10 @@
#include
#include
+/** \addtogroup audio_buffer_api
+ * @{
+ */
+
struct comp_dev;
struct buffer_cb_transact;
@@ -110,53 +114,63 @@ extern struct tr_ctx buffer_tr;
/** @}*/
-/* buffer callback types */
-#define BUFF_CB_TYPE_PRODUCE BIT(0)
-#define BUFF_CB_TYPE_CONSUME BIT(1)
+/** \name Buffer callback types
+ * @{
+ */
+#define BUFF_CB_TYPE_PRODUCE BIT(0) /**< Callback triggered on buffer produce */
+#define BUFF_CB_TYPE_CONSUME BIT(1) /**< Callback triggered on buffer consume */
+/** @}*/
-#define BUFFER_UPDATE_IF_UNSET 0
-#define BUFFER_UPDATE_FORCE 1
+/** \name Buffer parameter update modes
+ * @{
+ */
+#define BUFFER_UPDATE_IF_UNSET 0 /**< Update buffer parameters only if currently unset */
+#define BUFFER_UPDATE_FORCE 1 /**< Force update buffer parameters regardless of current state */
+/** @}*/
-/* buffer parameters */
-#define BUFF_PARAMS_FRAME_FMT BIT(0)
-#define BUFF_PARAMS_BUFFER_FMT BIT(1)
-#define BUFF_PARAMS_RATE BIT(2)
-#define BUFF_PARAMS_CHANNELS BIT(3)
+/** \name Buffer parameter bitmasks
+ * @{
+ */
+#define BUFF_PARAMS_FRAME_FMT BIT(0) /**< Buffer parameter bitmask: frame format */
+#define BUFF_PARAMS_BUFFER_FMT BIT(1) /**< Buffer parameter bitmask: buffer format */
+#define BUFF_PARAMS_RATE BIT(2) /**< Buffer parameter bitmask: sample rate */
+#define BUFF_PARAMS_CHANNELS BIT(3) /**< Buffer parameter bitmask: channels count */
+/** @}*/
-/* buffer usage */
-#define BUFFER_USAGE_SHARED true /* buffer used by multiple DSP core and/or HW blocks */
-#define BUFFER_USAGE_NOT_SHARED false /* buffer only used by one HW block */
+/** \name Buffer memory sharing usage
+ * @{
+ */
+#define BUFFER_USAGE_SHARED true /**< Buffer used by multiple DSP cores and/or HW blocks */
+#define BUFFER_USAGE_NOT_SHARED false /**< Buffer only used by one HW block */
+/** @}*/
-/*
- * audio component buffer - connects 2 audio components together in pipeline.
- *
- * this is a legacy component connector for pipeline 1.0
- *
+/**
+ * \brief Audio component interconnect buffer connecting two pipeline components.
*/
struct comp_buffer {
/* data buffer */
- struct sof_audio_buffer audio_buffer;
+ struct sof_audio_buffer audio_buffer; /**< Unified audio buffer base class */
- struct audio_stream stream;
+ struct audio_stream stream; /**< Legacy audio stream representation */
/* configuration */
- uint32_t flags;
- uint32_t core;
+ uint32_t flags; /**< Buffer flags */
+ uint32_t core; /**< DSP core ID managing this buffer */
#if !CONFIG_ZEPHYR_LOG
- struct tr_ctx tctx; /* trace settings */
+ struct tr_ctx tctx; /**< Trace context */
#endif
/* connected components */
- struct comp_dev *source; /* source component */
- struct comp_dev *sink; /* sink component */
+ struct comp_dev *source; /**< Source component feeding this buffer */
+ struct comp_dev *sink; /**< Sink component consuming from this buffer */
/* lists */
- struct list_item source_list; /* list in comp buffers */
- struct list_item sink_list; /* list in comp buffers */
+ struct list_item source_list; /**< List node in source component's buffer list */
+ struct list_item sink_list; /**< List node in sink component's buffer list */
/* list of buffers, to be used i.e. in raw data processing mode*/
- struct list_item buffers_list;
+ struct list_item buffers_list; /**< List of buffers used in raw data processing */
#if CONFIG_PROBE
/** probe produce callback, called on buffer produce */
@@ -168,56 +182,93 @@ struct comp_buffer {
#endif
};
-/*
- * get a component providing data to the buffer
+/**
+ * \brief Get component providing data to the buffer.
+ * \param[in] buffer Interconnect buffer.
+ * \return Pointer to source component device, or NULL if none.
*/
static inline struct comp_dev *comp_buffer_get_source_component(const struct comp_buffer *buffer)
{
return buffer->source;
}
-/*
- * get a component consuming data from the buffer
+/**
+ * \brief Get component consuming data from the buffer.
+ * \param[in] buffer Interconnect buffer.
+ * \return Pointer to sink component device, or NULL if none.
*/
static inline struct comp_dev *comp_buffer_get_sink_component(const struct comp_buffer *buffer)
{
return buffer->sink;
}
+/**
+ * \brief Set component providing data to the buffer.
+ * \param[in,out] buffer Interconnect buffer.
+ * \param[in] comp Source component device.
+ */
static inline
void comp_buffer_set_source_component(struct comp_buffer *buffer, struct comp_dev *comp)
{
buffer->source = comp;
}
+/**
+ * \brief Set component consuming data from the buffer.
+ * \param[in,out] buffer Interconnect buffer.
+ * \param[in] comp Sink component device.
+ */
static inline
void comp_buffer_set_sink_component(struct comp_buffer *buffer, struct comp_dev *comp)
{
buffer->sink = comp;
}
+/**
+ * \brief Reset buffer source list node.
+ * \param[in,out] buffer Interconnect buffer.
+ */
static inline void comp_buffer_reset_source_list(struct comp_buffer *buffer)
{
list_init(&buffer->source_list);
}
+/**
+ * \brief Reset buffer sink list node.
+ * \param[in,out] buffer Interconnect buffer.
+ */
static inline void comp_buffer_reset_sink_list(struct comp_buffer *buffer)
{
list_init(&buffer->sink_list);
}
-/* Used as parameter for probe produce callback */
+/**
+ * \brief Transaction descriptor passed to buffer probe callbacks.
+ */
struct buffer_cb_transact {
- struct comp_buffer *buffer;
- uint32_t transaction_amount;
- void *transaction_begin_address;
+ struct comp_buffer *buffer; /**< Buffer being transacted */
+ uint32_t transaction_amount; /**< Number of bytes transacted */
+ void *transaction_begin_address; /**< Starting address of transaction */
};
+/**
+ * \brief Retrieve enclosing comp_buffer from a list node depending on traversal direction.
+ * \param[in] ptr List item pointer.
+ * \param[in] dir Pipeline traversal direction (PPL_DIR_DOWNSTREAM or PPL_DIR_UPSTREAM).
+ * \return Pointer to enclosing struct comp_buffer.
+ */
#define buffer_from_list(ptr, dir) \
((dir) == PPL_DIR_DOWNSTREAM ? \
container_of(ptr, struct comp_buffer, source_list) : \
container_of(ptr, struct comp_buffer, sink_list))
+/**
+ * \brief Set transaction callback on a component buffer.
+ * \param[in,out] buffer Target component buffer.
+ * \param[in] func Callback function pointer.
+ * \param[in] data Callback user data.
+ * \param[in] type Callback trigger type (BUFF_CB_TYPE_*).
+ */
#define buffer_set_cb(buffer, func, data, type) \
do { \
buffer->cb = func; \
@@ -227,20 +278,69 @@ struct buffer_cb_transact {
struct mod_alloc_ctx;
-/* pipeline buffer creation and destruction */
+/**
+ * \brief Allocate a pipeline component audio buffer with explicit size and alignment.
+ * \param[in,out] alloc Allocation context (heap and optional vregion).
+ * \param[in] size Required buffer capacity in bytes.
+ * \param[in] flags Memory allocation flags (SOF_MEM_FLAG_...).
+ * \param[in] align Memory alignment requirement in bytes.
+ * \param[in] is_shared True if the buffer memory is shared across processing domains.
+ * \return Pointer to allocated comp_buffer, or NULL on failure.
+ */
struct comp_buffer *buffer_alloc(struct mod_alloc_ctx *alloc, size_t size, uint32_t flags,
uint32_t align, bool is_shared);
+
+/**
+ * \brief Allocate a pipeline component buffer with an elastic size range.
+ * \param[in,out] alloc Allocation context.
+ * \param[in] preferred_size Desired optimal buffer capacity in bytes.
+ * \param[in] minimum_size Minimum acceptable buffer capacity in bytes.
+ * \param[in] flags Memory allocation flags (SOF_MEM_FLAG_...).
+ * \param[in] align Memory alignment requirement in bytes.
+ * \param[in] is_shared True if the buffer memory is shared across processing domains.
+ * \return Pointer to allocated comp_buffer, or NULL on failure.
+ */
struct comp_buffer *buffer_alloc_range(struct mod_alloc_ctx *alloc, size_t preferred_size,
size_t minimum_size,
uint32_t flags, uint32_t align, bool is_shared);
+
+/**
+ * \brief Instantiate a pipeline component buffer from an IPC configuration descriptor.
+ * \param[in,out] alloc Allocation context.
+ * \param[in] desc IPC buffer descriptor containing size, flags, and configuration.
+ * \param[in] is_shared True if the buffer memory is shared across processing domains.
+ * \return Pointer to newly instantiated comp_buffer, or NULL on failure.
+ */
struct comp_buffer *buffer_new(struct mod_alloc_ctx *alloc, const struct sof_ipc_buffer *desc,
bool is_shared);
+/**
+ * \brief Resize an existing pipeline component buffer.
+ * \param[in,out] buffer Pointer to comp_buffer to resize.
+ * \param[in] size New buffer capacity in bytes.
+ * \param[in] alignment Required memory alignment in bytes.
+ * \return 0 on success, or negative error code on failure.
+ */
int buffer_set_size(struct comp_buffer *buffer, uint32_t size, uint32_t alignment);
+
+/**
+ * \brief Resize a pipeline component buffer within a preferred-to-minimum range.
+ * \param[in,out] buffer Pointer to comp_buffer to resize.
+ * \param[in] preferred_size Desired optimal buffer capacity in bytes.
+ * \param[in] minimum_size Minimum acceptable buffer capacity in bytes.
+ * \param[in] alignment Required memory alignment in bytes.
+ * \return 0 on success, or negative error code on failure.
+ */
int buffer_set_size_range(struct comp_buffer *buffer, size_t preferred_size, size_t minimum_size,
uint32_t alignment);
/* legacy wrappers, to be removed. Don't use them if possible */
+
+/**
+ * \brief Retrieve enclosing comp_buffer from an audio source interface pointer.
+ * \param[in] source Pointer to audio source interface.
+ * \return Pointer to enclosing struct comp_buffer.
+ */
static inline struct comp_buffer *comp_buffer_get_from_source(struct sof_source *source)
{
struct sof_audio_buffer *audio_buffer = sof_audio_buffer_from_source(source);
@@ -248,6 +348,11 @@ static inline struct comp_buffer *comp_buffer_get_from_source(struct sof_source
return container_of(audio_buffer, struct comp_buffer, audio_buffer);
}
+/**
+ * \brief Retrieve enclosing comp_buffer from an audio sink interface pointer.
+ * \param[in] sink Pointer to audio sink interface.
+ * \return Pointer to enclosing struct comp_buffer.
+ */
static inline struct comp_buffer *comp_buffer_get_from_sink(struct sof_sink *sink)
{
struct sof_audio_buffer *audio_buffer = sof_audio_buffer_from_sink(sink);
@@ -255,6 +360,10 @@ static inline struct comp_buffer *comp_buffer_get_from_sink(struct sof_sink *sin
return container_of(audio_buffer, struct comp_buffer, audio_buffer);
}
+/**
+ * \brief Free an interconnect component buffer and its underlying memory.
+ * \param[in,out] buffer Component buffer to free.
+ */
static inline void buffer_free(struct comp_buffer *buffer)
{
audio_buffer_free(&buffer->audio_buffer);
@@ -262,20 +371,51 @@ static inline void buffer_free(struct comp_buffer *buffer)
/* end of legacy wrappers */
+/**
+ * \brief Zero-fill the entire payload of an interconnect buffer.
+ * \param[in,out] buffer Component buffer to zero.
+ */
void buffer_zero(struct comp_buffer *buffer);
-/* called by a component after producing data into this buffer */
+/**
+ * \brief Notify buffer that audio data has been produced by a component.
+ * \param[in,out] buffer Component buffer written to.
+ * \param[in] bytes Number of bytes produced.
+ */
void comp_update_buffer_produce(struct comp_buffer *buffer, uint32_t bytes);
-/* called by a component after consuming data from this buffer */
+/**
+ * \brief Notify buffer that audio data has been consumed by a component.
+ * \param[in,out] buffer Component buffer read from.
+ * \param[in] bytes Number of bytes consumed.
+ */
void comp_update_buffer_consume(struct comp_buffer *buffer, uint32_t bytes);
+/**
+ * \brief Set audio stream parameters on a component buffer.
+ * \param[in,out] buffer Component buffer to configure.
+ * \param[in] params Stream parameters to apply.
+ * \param[in] force_update If true, overwrite existing parameters unconditionally.
+ * \return 0 on success, or negative error code on failure.
+ */
int buffer_set_params(struct comp_buffer *buffer,
struct sof_ipc_stream_params *params, bool force_update);
+/**
+ * \brief Test if buffer stream parameters match requested parameters.
+ * \param[in] buffer Component buffer to check.
+ * \param[in] params Stream parameters to compare.
+ * \param[in] flag Bitmask specifying which parameters to check (BUFF_PARAMS_*).
+ * \return True if matching, false otherwise.
+ */
bool buffer_params_match(struct comp_buffer *buffer,
struct sof_ipc_stream_params *params, uint32_t flag);
+/**
+ * \brief Invalidate cache for a shared buffer stream if incoherent.
+ * \param[in,out] buffer Component buffer.
+ * \param[in] bytes Number of bytes to invalidate.
+ */
static inline void buffer_stream_invalidate(struct comp_buffer *buffer, uint32_t bytes)
{
#if CONFIG_INCOHERENT
@@ -284,6 +424,11 @@ static inline void buffer_stream_invalidate(struct comp_buffer *buffer, uint32_t
#endif
}
+/**
+ * \brief Write back cache for a shared buffer stream if incoherent.
+ * \param[in] buffer Component buffer.
+ * \param[in] bytes Number of bytes to write back.
+ */
static inline void buffer_stream_writeback(struct comp_buffer *buffer, uint32_t bytes)
{
#if CONFIG_INCOHERENT
@@ -292,26 +437,40 @@ static inline void buffer_stream_writeback(struct comp_buffer *buffer, uint32_t
#endif
}
-
-/*
- * Attach a new buffer at the beginning of the list. Note, that "head" must
- * really be the head of the list, not a list head within another buffer. We
- * don't synchronise its cache, so it must not be embedded in an object, using
- * the coherent API. The caller takes care to protect list heads.
+/**
+ * \brief Attach a new buffer at the beginning of a component buffer list.
*
- * Returns -EINVAL if the buffer is already linked in this direction
- * (re-attaching would create a self-loop and corrupt the list).
+ * Locking: Must be called with interrupts disabled (or userspace LL system mutex held).
+ * The caller takes care to protect list heads. "head" must really be the head of the
+ * list, not a list node within another buffer, as its cache is not synchronized and
+ * must not be embedded in an object using the coherent API.
+ *
+ * \param[in,out] buffer Component buffer to attach.
+ * \param[in,out] head List head to prepend buffer to.
+ * \param[in] dir Traversal direction (PPL_DIR_DOWNSTREAM or PPL_DIR_UPSTREAM).
+ * \return 0 on success, or -EALREADY if the buffer is already linked in this direction.
*/
int buffer_attach(struct comp_buffer *buffer, struct list_item *head, int dir);
-/*
- * Detach a buffer from anywhere in the list. "head" is again the head of the
- * list, we need it to verify, whether this buffer was the first or the last on
- * the list. Again it is assumed that the head's cache doesn't need to be
- * synchronized. The caller takes care to protect list heads.
+/**
+ * \brief Detach a buffer from anywhere in a component buffer list.
+ *
+ * Locking: Must be called with interrupts disabled (or userspace LL system mutex held).
+ * "head" is the head of the list, assumed not to require cache synchronization.
+ * The caller takes care to protect list heads.
+ *
+ * \param[in,out] buffer Component buffer to detach.
+ * \param[in,out] head List head buffer is attached to.
+ * \param[in] dir Traversal direction (PPL_DIR_DOWNSTREAM or PPL_DIR_UPSTREAM).
*/
void buffer_detach(struct comp_buffer *buffer, struct list_item *head, int dir);
+/**
+ * \brief Get component connected to buffer in specified traversal direction.
+ * \param[in] buffer Component buffer.
+ * \param[in] dir Traversal direction (PPL_DIR_DOWNSTREAM or PPL_DIR_UPSTREAM).
+ * \return Pointer to connected component device.
+ */
static inline struct comp_dev *buffer_get_comp(struct comp_buffer *buffer, int dir)
{
struct comp_dev *comp = (dir == PPL_DIR_DOWNSTREAM) ?
@@ -320,16 +479,27 @@ static inline struct comp_dev *buffer_get_comp(struct comp_buffer *buffer, int d
return comp;
}
+/**
+ * \brief Retrieve pipeline ID associated with a component buffer.
+ * \param[in] buffer Component buffer.
+ * \return Pipeline ID.
+ */
static inline uint32_t buffer_pipeline_id(const struct comp_buffer *buffer)
{
return buffer->stream.runtime_stream_params.pipeline_id;
}
-/* Run-time buffer re-configuration calls this too, so it must use cached access */
+/**
+ * \brief Initialize circular stream buffer descriptor for a component buffer.
+ * \param[in,out] buffer Component buffer to initialize stream for.
+ * \param[in] size Capacity of the circular stream in bytes.
+ */
static inline void buffer_init_stream(struct comp_buffer *buffer, size_t size)
{
/* addr should be set in alloc function */
audio_stream_init(&buffer->stream, buffer->stream.addr, size);
}
+/** @}*/
+
#endif /* __SOF_AUDIO_BUFFER_H__ */
diff --git a/src/include/sof/audio/channel_map.h b/src/include/sof/audio/channel_map.h
index a0ec75baca48..64850f7332f1 100644
--- a/src/include/sof/audio/channel_map.h
+++ b/src/include/sof/audio/channel_map.h
@@ -8,7 +8,7 @@
/**
* @file sof/audio/channel_map.h
* @brief Audio stream channel map lookup and sizing helpers.
- * @ingroup audio_pipeline_api
+ * @ingroup audio_format_api
*/
#ifndef __SOF_AUDIO_CHANNEL_MAP_H__
@@ -18,10 +18,14 @@
#include
#include
+/** \addtogroup audio_format_api
+ * @{
+ */
+
/**
- * @brief Returns the size of an IPC channel map structure in bytes.
- * @param chmap Pointer to the channel map structure.
- * @return Total size in bytes including dynamic channel coefficients.
+ * \brief Returns the size of an IPC channel map structure in bytes.
+ * \param[in] chmap Pointer to the channel map structure.
+ * \return Total size in bytes including dynamic channel coefficients.
*/
static inline uint32_t chmap_get_size(struct sof_ipc_channel_map *chmap)
{
@@ -30,12 +34,14 @@ static inline uint32_t chmap_get_size(struct sof_ipc_channel_map *chmap)
}
/**
- * @brief Returns a channel map for a given channel index in a stream map.
- * @param smap Pointer to the stream map structure.
- * @param index Channel index.
- * @return Pointer to matching channel map structure, or NULL if not found.
+ * \brief Returns a channel map for a given channel index in a stream map.
+ * \param[in] smap Pointer to the stream map structure.
+ * \param[in] index Channel index.
+ * \return Pointer to matching channel map structure, or NULL if not found.
*/
struct sof_ipc_channel_map *chmap_get(struct sof_ipc_stream_map *smap,
int index);
+/** @}*/
+
#endif /* __SOF_AUDIO_CHANNEL_MAP_H__ */
diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h
index c290001107d2..f8d91c8d8212 100644
--- a/src/include/sof/audio/component.h
+++ b/src/include/sof/audio/component.h
@@ -38,7 +38,7 @@ struct dai_hw_params;
struct timestamp_data;
struct dai_ts_data;
-/** \addtogroup audio_pipeline_api
+/** \addtogroup component_infra_api
* @{
*/
@@ -276,41 +276,30 @@ struct comp_ipc_config;
union ipc_config_specific;
struct ipc4_module_bind_unbind;
+/** \brief Component module binding endpoint type. */
enum bind_type {
- COMP_BIND_TYPE_SOURCE,
- COMP_BIND_TYPE_SINK
+ COMP_BIND_TYPE_SOURCE, /**< Bind to a data source */
+ COMP_BIND_TYPE_SINK /**< Bind to a data sink */
};
+/**
+ * \brief Component module binding metadata and endpoint references.
+ */
struct bind_info {
- /* pointer to IPC4 bind/unbind data */
- const struct ipc4_module_bind_unbind *ipc4_data;
-
- /* type of binding
- * bind call will be called twice for every component, first when binding a data source,
- * than when binding data sink.
- *
- * bind_type is indicating type of binding
- */
- enum bind_type bind_type;
+ const struct ipc4_module_bind_unbind *ipc4_data; /**< Pointer to IPC4 bind/unbind data */
+ enum bind_type bind_type; /**< Type of binding (source or sink) */
/* pointers to sink or source API of the data provider/consumer
* that is being bound to the module
- *
- * if bind_type == COMP_BIND_TYPE_SOURCE, the pointer points to source being bound/unbound
- * if bind_type == COMP_BIND_TYPE_SINK, the pointer points to sink being bound/unbound
- *
- * NOTE! As in pipeline2.0 there may be a binding between modules,
- * without a buffer in between, it cannot be a pointer to any buffer type, module should
- * use sink/source API
*/
union {
- struct sof_source *source;
- struct sof_sink *sink;
+ struct sof_source *source; /**< Source interface pointer when bind_type == COMP_BIND_TYPE_SOURCE */
+ struct sof_sink *sink; /**< Sink interface pointer when bind_type == COMP_BIND_TYPE_SINK */
};
};
/**
- * Audio component operations.
+ * \brief Audio component operations table.
*
* All component operations must return 0 for success, negative values for
* errors and 1 to stop the pipeline walk operation unless specified otherwise
@@ -318,189 +307,149 @@ struct bind_info {
*/
struct comp_ops {
/**
- * Creates a new component device.
- * @param drv Parent component driver.
- * @param ipc_config Component parameters.
- * @param spec Pointer to initialization data
- * @return Pointer to the new component device.
- *
- * Any component-specific private data is allocated separately and
- * pointer is connected to the comp_dev::private by using
- * comp_set_drvdata() and later retrieved by comp_get_drvdata().
- *
- * All parameters should be initialized to their default values.
- * Usually can be __cold.
+ * \brief Creates a new component device.
+ * \param[in] drv Parent component driver.
+ * \param[in] ipc_config Component parameters.
+ * \param[in] spec Pointer to initialization data.
+ * \return Pointer to the new component device, or NULL on failure.
*/
struct comp_dev *(*create)(const struct comp_driver *drv,
const struct comp_ipc_config *ipc_config,
const void *spec);
/**
- * Called to delete the specified component device.
- * @param dev Component device to be deleted.
- *
- * All data structures previously allocated on the run-time heap
- * must be freed by the implementation of free().
- * Usually can be __cold.
+ * \brief Called to delete the specified component device.
+ * \param[in,out] dev Component device to be deleted.
*/
void (*free)(struct comp_dev *dev);
/**
- * Sets component audio stream parameters.
- * @param dev Component device.
- * @param params Audio (PCM) stream parameters to be set.
- *
- * Infrastructure calls comp_verify_params() if this handler is not
- * defined, therefore it should be left NULL if no extra steps are
- * required.
- * Usually shouldn't be __cold.
+ * \brief Sets component audio stream parameters.
+ * \param[in,out] dev Component device.
+ * \param[in,out] params Audio (PCM) stream parameters to be set.
+ * \return 0 on success, negative error code on failure.
*/
int (*params)(struct comp_dev *dev,
struct sof_ipc_stream_params *params);
/**
- * Fetches hardware stream parameters.
- * @param dev Component device.
- * @param params Receives copy of stream parameters retrieved from
- * DAI hw settings.
- * @param dir Stream direction (see enum sof_ipc_stream_direction).
- *
- * Mandatory for components that allocate DAI.
- * Usually can be __cold.
+ * \brief Fetches hardware stream parameters.
+ * \param[in] dev Component device.
+ * \param[out] params Receives copy of stream parameters retrieved from DAI HW settings.
+ * \param[in] dir Stream direction (enum sof_ipc_stream_direction).
+ * \return 0 on success, negative error code on failure.
*/
int (*dai_get_hw_params)(struct comp_dev *dev,
struct sof_ipc_stream_params *params, int dir);
/**
- * Configures attached DAI.
- * @param dev Component device.
- * @param dai_config DAI configuration.
- *
- * Mandatory for components that allocate DAI.
- * Usually can be __cold.
+ * \brief Configures attached DAI.
+ * \param[in,out] dd DAI data context.
+ * \param[in,out] dev Component device.
+ * \param[in] dai_config DAI configuration.
+ * \param[in] dai_spec_config DAI specific configuration data.
+ * \return 0 on success, negative error code on failure.
*/
int (*dai_config)(struct dai_data *dd, struct comp_dev *dev,
struct ipc_config_dai *dai_config, const void *dai_spec_config);
#if CONFIG_IPC_MAJOR_3 || CONFIG_LIBRARY
/**
- * Used to pass standard and bespoke commands (with optional data).
- * @param dev Component device.
- * @param cmd Command.
- * @param data Command data.
- * @param max_data_size Max size of returned data acceptable by the
- * caller in case of 'get' commands.
+ * \brief Used to pass standard and bespoke commands (with optional data).
+ * \param[in,out] dev Component device.
+ * \param[in] cmd Command.
+ * \param[in,out] data Command data.
+ * \param[in] max_data_size Max size of returned data acceptable by caller for 'get' commands.
+ * \return 0 on success, negative error code on failure.
*/
int (*cmd)(struct comp_dev *dev, int cmd, void *data,
int max_data_size);
#endif
/**
- * Trigger, atomic - used to start/stop/pause stream operations.
- * @param dev Component device.
- * @param cmd Command, one of COMP_TRIGGER_...
- *
- * Usually shouldn't be __cold.
+ * \brief Trigger, atomic - used to start/stop/pause stream operations.
+ * \param[in,out] dev Component device.
+ * \param[in] cmd Command, one of COMP_TRIGGER_...
+ * \return 0 on success, negative error code on failure.
*/
int (*trigger)(struct comp_dev *dev, int cmd);
/**
- * Prepares component after params are set.
- * @param dev Component device.
- *
- * Prepare should be used to get the component ready for starting
- * processing after it's hw_params are known or after an XRUN.
- * Usually shouldn't be __cold.
+ * \brief Prepares component after params are set.
+ * \param[in,out] dev Component device.
+ * \return 0 on success, negative error code on failure.
*/
int (*prepare)(struct comp_dev *dev);
/**
- * Resets component.
- * @param dev Component device.
- *
- * Resets the component state and any hw_params to default component
- * state. Should also free any resources acquired during hw_params.
- * Usually shouldn't be __cold.
+ * \brief Resets component.
+ * \param[in,out] dev Component device.
+ * \return 0 on success, negative error code on failure.
*/
int (*reset)(struct comp_dev *dev);
/**
- * Copy and process stream data from source to sink buffers.
- * @param dev Component device.
- * @return Number of copied frames.
- *
- * Usually shouldn't be __cold.
+ * \brief Copy and process stream data from source to sink buffers.
+ * \param[in,out] dev Component device.
+ * \return Number of copied frames, or negative error code on failure.
*/
int (*copy)(struct comp_dev *dev);
/**
- * Retrieves component rendering position.
- * @param dev Component device.
- * @param posn Receives reported position.
- *
- * Usually shouldn't be __cold.
+ * \brief Retrieves component rendering position.
+ * \param[in] dev Component device.
+ * \param[out] posn Receives reported position.
+ * \return 0 on success, negative error code on failure.
*/
int (*position)(struct comp_dev *dev,
struct sof_ipc_stream_posn *posn);
/**
- * Gets attribute in component.
- * @param dev Component device.
- * @param type Attribute type.
- * @param value Attribute value.
- * @return 0 if succeeded, error code otherwise.
- *
- * Usually can be __cold.
+ * \brief Gets attribute in component.
+ * \param[in] dev Component device.
+ * \param[in] type Attribute type.
+ * \param[out] value Attribute value buffer.
+ * \return 0 if succeeded, error code otherwise.
*/
int (*get_attribute)(struct comp_dev *dev, uint32_t type,
void *value);
/**
- * Sets attribute in component.
- * @param dev Component device.
- * @param type Attribute type.
- * @param value Attribute value.
- * @return 0 if succeeded, error code otherwise.
- *
- * Usually can be __cold.
+ * \brief Sets attribute in component.
+ * \param[in,out] dev Component device.
+ * \param[in] type Attribute type.
+ * \param[in] value Attribute value.
+ * \return 0 if succeeded, error code otherwise.
*/
int (*set_attribute)(struct comp_dev *dev, uint32_t type,
void *value);
/**
- * Configures timestamping in attached DAI.
- * @param dev Component device.
- *
- * Mandatory for components that allocate DAI.
- * Usually can be __cold.
+ * \brief Configures timestamping in attached DAI.
+ * \param[in,out] dev Component device.
+ * \return 0 on success, negative error code on failure.
*/
int (*dai_ts_config)(struct comp_dev *dev);
/**
- * Starts timestamping.
- * @param dev Component device.
- *
- * Mandatory for components that allocate DAI.
- * Usually can be __cold.
+ * \brief Starts timestamping.
+ * \param[in,out] dev Component device.
+ * \return 0 on success, negative error code on failure.
*/
int (*dai_ts_start)(struct comp_dev *dev);
/**
- * Stops timestamping.
- * @param dev Component device.
- *
- * Mandatory for components that allocate DAI.
- * Usually can be __cold.
+ * \brief Stops timestamping.
+ * \param[in,out] dev Component device.
+ * \return 0 on success, negative error code on failure.
*/
int (*dai_ts_stop)(struct comp_dev *dev);
/**
- * Gets timestamp.
- * @param dev Component device.
- * @param tsd Receives timestamp data.
- *
- * Mandatory for components that allocate DAI.
- * Usually shouldn't be __cold.
+ * \brief Gets timestamp.
+ * \param[in] dev Component device.
+ * \param[out] tsd Receives timestamp data.
+ * \return 0 on success, negative error code on failure.
*/
#if CONFIG_ZEPHYR_NATIVE_DRIVERS
int (*dai_ts_get)(struct comp_dev *dev, struct dai_ts_data *tsd);
@@ -510,36 +459,30 @@ struct comp_ops {
#endif
/**
- * Bind, atomic - used to notify component of bind event.
- * @param dev Component device.
- * @param data Bind info
- *
- * Usually can be __cold.
+ * \brief Bind, atomic - used to notify component of bind event.
+ * \param[in,out] dev Component device.
+ * \param[in] bind_data Bind info.
+ * \return 0 on success, negative error code on failure.
*/
int (*bind)(struct comp_dev *dev, const struct bind_info *bind_data);
/**
- * Unbind, atomic - used to notify component of unbind event.
- * @param dev Component device.
- * @param data unBind info
- *
- * Usually can be __cold.
+ * \brief Unbind, atomic - used to notify component of unbind event.
+ * \param[in,out] dev Component device.
+ * \param[in] unbind_data Unbind info.
+ * \return 0 on success, negative error code on failure.
*/
int (*unbind)(struct comp_dev *dev, const struct bind_info *unbind_data);
/**
- * Gets config in component.
- * @param dev Component device
- * @param param_id param id for each component
- * @param first_block first block of large block.
- * @param last_block last block of large block.
- * @param data_offset block offset filled by callee.
- * @param data block data.
- * @return 0 if succeeded, error code otherwise.
- *
- * Callee fills up *data with config data and save the config
- * size in *data_offset for host to reconstruct the config
- * Usually can be __cold.
+ * \brief Gets large config in component.
+ * \param[in,out] dev Component device.
+ * \param[in] param_id Parameter ID for each component.
+ * \param[in] first_block First block of large block.
+ * \param[in] last_block Last block of large block.
+ * \param[in,out] data_offset Block offset filled by callee.
+ * \param[out] data Block data buffer.
+ * \return 0 if succeeded, error code otherwise.
*/
int (*get_large_config)(struct comp_dev *dev, uint32_t param_id,
bool first_block,
@@ -548,19 +491,14 @@ struct comp_ops {
char *data);
/**
- * Set config in component.
- * @param dev Component device
- * @param param_id param id for each component
- * @param first_block first block of large block.
- * @param last_block last block of large block.
- * @param data_offset block offset in large block.
- * @param data block data.
- * @return 0 if succeeded, error code otherwise.
- *
- * Host divides large block into small blocks and sends them
- * to fw. The data_offset indicates the offset in the large
- * block data.
- * Usually can be __cold.
+ * \brief Set large config in component.
+ * \param[in,out] dev Component device.
+ * \param[in] param_id Parameter ID for each component.
+ * \param[in] first_block First block of large block.
+ * \param[in] last_block Last block of large block.
+ * \param[in] data_offset Block offset in large block.
+ * \param[in] data Block data payload.
+ * \return 0 if succeeded, error code otherwise.
*/
int (*set_large_config)(struct comp_dev *dev, uint32_t param_id,
bool first_block,
@@ -569,13 +507,11 @@ struct comp_ops {
const char *data);
/**
- * Returns total data processed in number bytes.
- * @param dev Component device
- * @param stream_no Index of input/output stream
- * @param input Selects between input (true) or output (false) stream direction
- * @return total data processed if succeeded, 0 otherwise.
- *
- * Usually shouldn't be __cold.
+ * \brief Returns total data processed in number of bytes.
+ * \param[in] dev Component device.
+ * \param[in] stream_no Index of input/output stream.
+ * \param[in] input Selects between input (true) or output (false) stream direction.
+ * \return Total data processed if succeeded, 0 otherwise.
*/
uint64_t (*get_total_data_processed)(struct comp_dev *dev, uint32_t stream_no, bool input);
};
@@ -612,113 +548,95 @@ struct comp_driver_info {
struct list_item list; /**< list of component drivers */
};
-#define COMP_PROCESSING_DOMAIN_LL 0
-#define COMP_PROCESSING_DOMAIN_DP 1
+/** \name Component processing domains
+ * @{
+ */
+#define COMP_PROCESSING_DOMAIN_LL 0 /**< Low latency processing domain */
+#define COMP_PROCESSING_DOMAIN_DP 1 /**< Data processing / worker thread domain */
+/** @}*/
/**
- * Audio component base configuration from IPC at creation.
+ * \brief Audio component base configuration from IPC at creation.
*/
struct comp_ipc_config {
- uint32_t core; /**< core we run on */
- uint32_t id; /**< component id */
- uint32_t pipeline_id; /**< component pipeline id */
- uint32_t proc_domain; /**< processing domain - LL or DP */
- enum sof_comp_type type; /**< component type */
- uint32_t periods_sink; /**< 0 means variable */
- uint32_t periods_source; /**< 0 means variable */
- uint32_t frame_fmt; /**< SOF_IPC_FRAME_ */
- uint32_t xrun_action; /**< action we should take on XRUN */
+ uint32_t core; /**< Core we run on */
+ uint32_t id; /**< Component ID */
+ uint32_t pipeline_id; /**< Component pipeline ID */
+ uint32_t proc_domain; /**< Processing domain (COMP_PROCESSING_DOMAIN_*) */
+ enum sof_comp_type type; /**< Component type (SOF_COMP_*) */
+ uint32_t periods_sink; /**< Sink periods (0 means variable) */
+ uint32_t periods_source; /**< Source periods (0 means variable) */
+ uint32_t frame_fmt; /**< Frame format (SOF_IPC_FRAME_*) */
+ uint32_t xrun_action; /**< Action to take on XRUN */
#if CONFIG_IPC_MAJOR_4
- bool ipc_extended_init; /**< true if extended init is included in ipc payload */
- uint32_t ipc_config_size; /**< size of a config received by ipc */
+ bool ipc_extended_init; /**< True if extended init is included in IPC payload */
+ uint32_t ipc_config_size; /**< Size of config received by IPC */
#endif
};
+/**
+ * \brief Component performance measurement tracking data.
+ */
struct comp_perf_data {
- /* maximum measured cpc on run-time.
- *
- * if current measured cpc exceeds peak_of_measured_cpc_ then
- * ResoruceEvent(BUDGET_VIOLATION) notification must be send.
- * Otherwise there is no new information for host to care about
- */
- size_t peak_of_measured_cpc;
- /* Pointer to performance data structure. */
- struct perf_data_item_comp *perf_data_item;
+ size_t peak_of_measured_cpc; /**< Maximum measured CPC at runtime */
+ struct perf_data_item_comp *perf_data_item; /**< Pointer to performance data item */
};
/**
- * Audio component base device "class"
- * - used by other component types.
+ * \brief Audio component base device "class" used by all other component types.
*/
struct comp_dev {
-
/* runtime */
- uint16_t state; /**< COMP_STATE_ */
- uint32_t frames; /**< number of frames we copy to sink */
- bool expect_eos; /**< end of stream expected */
- struct pipeline *pipeline; /**< pipeline we belong to */
-
- struct task *task; /**< component's processing task used
- * 1) for components running on different core
- * than the rest of the pipeline
- * 2) for all DP tasks
- */
- uint32_t size; /**< component's allocated size */
- uint32_t period; /**< component's processing period
- * for LL modules is set to LL pipeline's period
- * for DP module its meaning is "the time the module MUST
- * provide data that allows the following module to perform
- * without glitches"
- */
- uint32_t priority; /**< component's processing priority */
- bool is_shared; /**< indicates whether component is shared
- * across cores
- */
+ uint16_t state; /**< Component state (COMP_STATE_*) */
+ uint32_t frames; /**< Number of frames copied to sink */
+ bool expect_eos; /**< End of stream expected flag */
+ struct pipeline *pipeline; /**< Parent pipeline reference */
+
+ struct task *task; /**< Component processing task (cross-core or DP) */
+ uint32_t size; /**< Component allocated size in bytes */
+ uint32_t period; /**< Component processing period in microseconds */
+ uint32_t priority; /**< Component processing priority */
+ bool is_shared; /**< True if component is shared across cores */
struct comp_ipc_config ipc_config; /**< Component IPC configuration */
#if !CONFIG_ZEPHYR_LOG
- struct tr_ctx tctx; /**< trace settings */
+ struct tr_ctx tctx; /**< Trace settings */
#endif
/* common runtime configuration for downstream/upstream */
- uint32_t direction; /**< enum sof_ipc_stream_direction */
- bool direction_set; /**< flag indicating that the direction has been set */
+ uint32_t direction; /**< Stream direction (enum sof_ipc_stream_direction) */
+ bool direction_set; /**< Flag indicating that direction has been set */
- const struct comp_driver *drv; /**< driver */
+ const struct comp_driver *drv; /**< Component driver */
- struct processing_module *mod; /**< self->mod->dev == self, NULL if component is not using
- * module adapter
- */
+ struct processing_module *mod; /**< Module adapter reference */
/* lists */
- struct list_item bsource_list; /**< list of source buffers */
- struct list_item bsink_list; /**< list of sink buffers */
+ struct list_item bsource_list; /**< List of source buffers */
+ struct list_item bsink_list; /**< List of sink buffers */
/* performance data*/
- struct comp_perf_data perf_data;
- /* Input Buffer Size for pin 0, add array for other pins if needed */
- size_t ibs;
- /* Output Buffers Size for pin 0, add array for other pins if needed */
- size_t obs;
- /* max dsp cycles per chunk */
- size_t cpc;
- /* size of 1ms for input format in bytes */
- size_t ll_chunk_size : 16;
+ struct comp_perf_data perf_data; /**< Performance data */
+ size_t ibs; /**< Input Buffer Size for pin 0 */
+ size_t obs; /**< Output Buffer Size for pin 0 */
+ size_t cpc; /**< Max DSP cycles per chunk */
+ size_t ll_chunk_size : 16; /**< Size of 1ms input format chunk in bytes */
/* private data - core does not touch this */
- void *priv_data; /**< private data */
+ void *priv_data; /**< Driver private data */
#if CONFIG_PERFORMANCE_COUNTERS_COMPONENT
- struct perf_cnt_data pcd;
+ struct perf_cnt_data pcd; /**< Performance counter data */
#endif
#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL
- int32_t kcps_inc[CONFIG_CORE_COUNT];
+ int32_t kcps_inc[CONFIG_CORE_COUNT]; /**< KCPS clock demand per core */
#endif
};
/**
- * Get a pointer to the first comp_buffer object providing data to the component
- * The function will return NULL if there's no data provider
+ * \brief Get a pointer to the first comp_buffer object providing data to the component.
+ * \param[in] component Target component device.
+ * \return Pointer to first producer comp_buffer, or NULL if none.
*/
static inline struct comp_buffer *comp_dev_get_first_data_producer(struct comp_dev *component)
{
@@ -727,9 +645,10 @@ static inline struct comp_buffer *comp_dev_get_first_data_producer(struct comp_d
}
/**
- * Get a pointer to the next comp_buffer object providing data to the component
- * The function will return NULL if there're no more data providers
- * _save version also checks if producer != NULL
+ * \brief Get a pointer to the next comp_buffer object providing data to the component.
+ * \param[in] component Target component device.
+ * \param[in] producer Current producer buffer.
+ * \return Pointer to next producer comp_buffer, or NULL if none.
*/
static inline struct comp_buffer *comp_dev_get_next_data_producer(struct comp_dev *component,
struct comp_buffer *producer)
@@ -738,6 +657,12 @@ static inline struct comp_buffer *comp_dev_get_next_data_producer(struct comp_de
list_item(producer->sink_list.next, struct comp_buffer, sink_list);
}
+/**
+ * \brief Safely get a pointer to the next comp_buffer object providing data to the component.
+ * \param[in] component Target component device.
+ * \param[in] producer Current producer buffer, or NULL.
+ * \return Pointer to next producer comp_buffer, or NULL if none.
+ */
static inline struct comp_buffer *comp_dev_get_next_data_producer_safe(struct comp_dev *component,
struct comp_buffer *producer)
{
@@ -745,8 +670,9 @@ static inline struct comp_buffer *comp_dev_get_next_data_producer_safe(struct co
}
/**
- * Get a pointer to the first comp_buffer object receiving data from the component
- * The function will return NULL if there's no data consumers
+ * \brief Get a pointer to the first comp_buffer object receiving data from the component.
+ * \param[in] component Target component device.
+ * \return Pointer to first consumer comp_buffer, or NULL if none.
*/
static inline struct comp_buffer *comp_dev_get_first_data_consumer(struct comp_dev *component)
{
@@ -755,9 +681,10 @@ static inline struct comp_buffer *comp_dev_get_first_data_consumer(struct comp_d
}
/**
- * Get a pointer to the next comp_buffer object receiving data from the component
- * The function will return NULL if there're no more data consumers
- * _safe version also checks if consumer is != NULL
+ * \brief Get a pointer to the next comp_buffer object receiving data from the component.
+ * \param[in] component Target component device.
+ * \param[in] consumer Current consumer buffer.
+ * \return Pointer to next consumer comp_buffer, or NULL if none.
*/
static inline struct comp_buffer *comp_dev_get_next_data_consumer(struct comp_dev *component,
struct comp_buffer *consumer)
@@ -766,25 +693,33 @@ static inline struct comp_buffer *comp_dev_get_next_data_consumer(struct comp_de
list_item(consumer->source_list.next, struct comp_buffer, source_list);
}
+/**
+ * \brief Safely get a pointer to the next comp_buffer object receiving data from the component.
+ * \param[in] component Target component device.
+ * \param[in] consumer Current consumer buffer, or NULL.
+ * \return Pointer to next consumer comp_buffer, or NULL if none.
+ */
static inline struct comp_buffer *comp_dev_get_next_data_consumer_safe(struct comp_dev *component,
struct comp_buffer *consumer)
{
return consumer ? comp_dev_get_next_data_consumer(component, consumer) : NULL;
}
-/*
- * a macro for easy iteration through component's list of producers
+/**
+ * \brief Macro to iterate through component's list of producer buffers.
+ * \param[in] _dev Target component device.
+ * \param[out] _producer Buffer pointer iterator variable.
*/
#define comp_dev_for_each_producer(_dev, _producer) \
for (_producer = comp_dev_get_first_data_producer(_dev); \
_producer != NULL; \
_producer = comp_dev_get_next_data_producer(_dev, _producer))
-/*
- * a macro for easy iteration through component's list of producers
- * allowing deletion of a buffer during iteration
- *
- * additional "safe storage" pointer to struct comp_buffer must be provided
+/**
+ * \brief Safe macro to iterate through component's producer buffers allowing buffer deletion.
+ * \param[in] _dev Target component device.
+ * \param[out] _producer Buffer pointer iterator variable.
+ * \param[out] _next_producer Storage pointer for next buffer.
*/
#define comp_dev_for_each_producer_safe(_dev, _producer, _next_producer) \
for (_producer = comp_dev_get_first_data_producer(_dev), \
@@ -793,19 +728,21 @@ static inline struct comp_buffer *comp_dev_get_next_data_consumer_safe(struct co
_producer = _next_producer, \
_next_producer = comp_dev_get_next_data_producer_safe(_dev, _producer))
-/*
- * a macro for easy iteration through component's list of consumers
+/**
+ * \brief Macro to iterate through component's list of consumer buffers.
+ * \param[in] _dev Target component device.
+ * \param[out] _consumer Buffer pointer iterator variable.
*/
#define comp_dev_for_each_consumer(_dev, _consumer) \
for (_consumer = comp_dev_get_first_data_consumer(_dev); \
_consumer != NULL; \
_consumer = comp_dev_get_next_data_consumer(_dev, _consumer)) \
-/*
- * a macro for easy iteration through component's list of consumers
- * allowing deletion of a buffer during iteration
- *
- * additional "safe storage" pointer to struct comp_buffer must be provided
+/**
+ * \brief Safe macro to iterate through component's consumer buffers allowing buffer deletion.
+ * \param[in] _dev Target component device.
+ * \param[out] _consumer Buffer pointer iterator variable.
+ * \param[out] _next_consumer Storage pointer for next buffer.
*/
#define comp_dev_for_each_consumer_safe(_dev, _consumer, _next_consumer) \
for (_consumer = comp_dev_get_first_data_consumer(_dev), \
@@ -814,29 +751,23 @@ static inline struct comp_buffer *comp_dev_get_next_data_consumer_safe(struct co
_consumer = _next_consumer, \
_next_consumer = comp_dev_get_next_data_consumer_safe(_dev, _consumer))
-/** @}*/
-
/* Common helper function used internally by the component implementations
* begin here.
*/
-/** \addtogroup audio_pipeline_api
- * @{
- */
-
/** \brief Struct for use with comp_get_copy_limits() function. */
struct comp_copy_limits {
- int frames;
- int source_bytes;
- int sink_bytes;
- int source_frame_bytes;
- int sink_frame_bytes;
+ int frames; /**< Number of frames that can be copied */
+ int source_bytes; /**< Available bytes in source */
+ int sink_bytes; /**< Free bytes in sink */
+ int source_frame_bytes; /**< Frame size in bytes in source */
+ int sink_frame_bytes; /**< Frame size in bytes in sink */
};
/**
- * Retrieves Component id from device.
- * @param dev Device.
- * @return Component id.
+ * \brief Retrieves Component ID from device.
+ * \param[in] dev Component device.
+ * \return Component ID.
*/
static inline uint32_t dev_comp_id(const struct comp_dev *dev)
{
@@ -844,9 +775,9 @@ static inline uint32_t dev_comp_id(const struct comp_dev *dev)
}
/**
- * Retrieves Component pipeline id from device.
- * @param dev Device.
- * @return Component pipeline id.
+ * \brief Retrieves Component pipeline ID from device.
+ * \param[in] dev Component device.
+ * \return Component pipeline ID.
*/
static inline uint32_t dev_comp_pipe_id(const struct comp_dev *dev)
{
@@ -854,9 +785,9 @@ static inline uint32_t dev_comp_pipe_id(const struct comp_dev *dev)
}
/**
- * Retrieves component type from device.
- * @param dev Device.
- * @return Component type.
+ * \brief Retrieves component type from device.
+ * \param[in] dev Component device.
+ * \return Component type (enum sof_comp_type).
*/
static inline enum sof_comp_type dev_comp_type(const struct comp_dev *dev)
{
@@ -864,10 +795,10 @@ static inline enum sof_comp_type dev_comp_type(const struct comp_dev *dev)
}
/**
- * Initialize common part of a component device
- * @param drv Parent component driver.
- * @param dev Device.
- * @param bytes Size of the component device in bytes.
+ * \brief Initialize common part of a component device.
+ * \param[in] drv Parent component driver.
+ * \param[in,out] dev Component device.
+ * \param[in] bytes Size of the component device in bytes.
*/
static inline void comp_init(const struct comp_driver *drv,
struct comp_dev *dev, size_t bytes)
@@ -884,10 +815,10 @@ static inline void comp_init(const struct comp_driver *drv,
}
/**
- * Allocates memory for the component device and initializes common part.
- * @param drv Parent component driver.
- * @param bytes Size of the component device in bytes.
- * @return Pointer to the component device.
+ * \brief Allocates memory for the component device and initializes common part.
+ * \param[in] drv Parent component driver.
+ * \param[in] bytes Size of the component device in bytes.
+ * \return Pointer to the allocated component device, or NULL on failure.
*/
static inline struct comp_dev *comp_alloc(const struct comp_driver *drv, size_t bytes)
{
@@ -909,12 +840,11 @@ static inline struct comp_dev *comp_alloc(const struct comp_driver *drv, size_t
}
/**
- * Frees memory allocated for component device.
+ * \brief Frees memory allocated for component device.
*
- * This is a counterpart to comp_alloc() and not to be confused with
- * comp_free().
+ * This is a counterpart to comp_alloc() and not to be confused with comp_free().
*
- * @param dev Pointer to the component device.
+ * \param[in,out] dev Pointer to the component device to free.
*/
static inline void comp_free_device(struct comp_dev *dev)
{
@@ -922,8 +852,9 @@ static inline void comp_free_device(struct comp_dev *dev)
}
/**
- * \brief Module adapter associated with a component
- * @param dev Component device
+ * \brief Module adapter associated with a component.
+ * \param[in] dev Component device.
+ * \return Pointer to associated processing module, or NULL if none.
*/
static inline struct processing_module *comp_mod(const struct comp_dev *dev)
{
@@ -932,16 +863,16 @@ static inline struct processing_module *comp_mod(const struct comp_dev *dev)
/**
* \brief Assigns private data to component device.
- * @param c Component device.
- * @param data Private data.
+ * \param[in,out] c Component device.
+ * \param[in] data Private data pointer.
*/
#define comp_set_drvdata(c, data) \
(c->priv_data = data)
/**
* \brief Retrieves driver private data from component device.
- * @param c Component device.
- * @return Private data.
+ * \param[in] c Component device.
+ * \return Private data pointer.
*/
#define comp_get_drvdata(c) \
(c->priv_data)
@@ -1010,34 +941,33 @@ void sys_comp_module_volume_interface_init(void);
*/
/**
- * Registers the component driver on the list of available components.
- * @param drv Component driver to be registered.
- * @return 0 if succeeded, error code otherwise.
+ * \brief Registers the component driver on the list of available components.
+ * \param[in,out] drv Component driver to be registered.
+ * \return 0 if succeeded, error code otherwise.
*/
int comp_register(struct comp_driver_info *drv);
/**
- * Unregisters the component driver from the list of available components.
- * @param drv Component driver to be unregistered.
+ * \brief Unregisters the component driver from the list of available components.
+ * \param[in,out] drv Component driver to be unregistered.
*/
void comp_unregister(struct comp_driver_info *drv);
/**
- * Set adapter ops for a dynamically created driver.
- *
- * @param drv Component driver to update.
- * @param ops Module interface operations.
- * @return 0 or a negative error code
+ * \brief Set adapter ops for a dynamically created driver.
+ * \param[in,out] drv Component driver to update.
+ * \param[in] ops Module interface operations.
+ * \return 0 or a negative error code.
*/
int comp_set_adapter_ops(const struct comp_driver *drv, const struct module_interface *ops);
/** @}*/
/**
- * Component state set.
- * @param dev Component device.
- * @param cmd Command, one of COMP_TRIGGER_....
- * @return 0 if succeeded, error code otherwise.
+ * \brief Component state transition handling.
+ * \param[in,out] dev Component device.
+ * \param[in] cmd Command, one of COMP_TRIGGER_...
+ * \return 0 if succeeded, error code otherwise.
*
* This function should be called by a component implementation at the beginning
* of its state transition to verify whether the trigger is valid in the
@@ -1054,7 +984,11 @@ int comp_set_adapter_ops(const struct comp_driver *drv, const struct module_inte
*/
int comp_set_state(struct comp_dev *dev, int cmd);
-/* \brief Set component period frames */
+/**
+ * \brief Set component period frames based on sample rate and period.
+ * \param[in,out] current Target component device.
+ * \param[in] rate Sample rate in Hz.
+ */
static inline void component_set_nearest_period_frames(struct comp_dev *current,
uint32_t rate)
{
@@ -1093,10 +1027,10 @@ static inline void component_set_nearest_period_frames(struct comp_dev *current,
*/
/**
- * Called by the component device when underrun is detected.
- * @param dev Component device.
- * @param source Source buffer.
- * @param copy_bytes Requested size of data to be available.
+ * \brief Called by the component device when underrun is detected.
+ * \param[in,out] dev Component device.
+ * \param[in] source Source buffer.
+ * \param[in] copy_bytes Requested size of data in bytes.
*/
static inline void comp_underrun(struct comp_dev *dev,
struct comp_buffer *source,
@@ -1116,10 +1050,10 @@ static inline void comp_underrun(struct comp_dev *dev,
}
/**
- * Called by component device when overrun is detected.
- * @param dev Component device.
- * @param sink Sink buffer.
- * @param copy_bytes Requested size of free space to be available.
+ * \brief Called by component device when overrun is detected.
+ * \param[in,out] dev Component device.
+ * \param[in] sink Sink buffer.
+ * \param[in] copy_bytes Requested size of free space in bytes.
*/
static inline void comp_overrun(struct comp_dev *dev, struct comp_buffer *sink,
uint32_t copy_bytes)
@@ -1138,38 +1072,34 @@ static inline void comp_overrun(struct comp_dev *dev, struct comp_buffer *sink,
/** @}*/
/**
- * Computes source to sink copy operation boundaries including maximum number
- * of frames that can be transferred (data available in source vs. free space
- * available in sink).
+ * \brief Computes source to sink copy operation boundaries including maximum number
+ * of frames that can be transferred.
*
- * @param[in] source Source buffer.
- * @param[in] sink Sink buffer.
- * @param[out] cl Current copy limits.
+ * \param[in] source Source buffer.
+ * \param[in] sink Sink buffer.
+ * \param[out] cl Current copy limits.
*/
void comp_get_copy_limits(struct comp_buffer *source,
struct comp_buffer *sink,
struct comp_copy_limits *cl);
/**
- * Computes source to sink copy operation boundaries including maximum number
- * of frames aligned with requirement that can be transferred (data available in
- * source vs. free space available in sink).
+ * \brief Computes source to sink copy operation boundaries including maximum number
+ * of frames aligned with requirement that can be transferred.
*
- * @param[in] source Buffer of source.
- * @param[in] sink Buffer of sink.
- * @param[out] cl Current copy limits.
+ * \param[in] source Buffer of source.
+ * \param[in] sink Buffer of sink.
+ * \param[out] cl Current copy limits.
*/
void comp_get_copy_limits_frame_aligned(const struct comp_buffer *source,
const struct comp_buffer *sink,
struct comp_copy_limits *cl);
/**
- * Get component state.
- *
- * @param dev Component from which user wants to read status.
- *
- * @retval COMP_STATE_NOT_EXIST if there's no connected component
- * @return state of the component
+ * \brief Get component state.
+ * \param[in] dev Component from which user wants to read status.
+ * \retval COMP_STATE_NOT_EXIST If there's no connected component.
+ * \return State of the component (COMP_STATE_*).
*/
static inline int comp_get_state(const struct comp_dev *dev)
{
@@ -1179,12 +1109,10 @@ static inline int comp_get_state(const struct comp_dev *dev)
}
/**
- * @brief helper, provide state of a component connected to a buffer as a data provider
- *
- * @param buffer a buffer to be checked
- *
- * @retval COMP_STATE_NOT_EXIST if there's no connected component
- * @return state of the component
+ * \brief Provide state of a component connected to a buffer as a data provider.
+ * \param[in] buffer Interconnect buffer to be checked.
+ * \retval COMP_STATE_NOT_EXIST If there's no connected component.
+ * \return State of the component.
*/
static inline int comp_buffer_get_source_state(const struct comp_buffer *buffer)
{
@@ -1192,12 +1120,10 @@ static inline int comp_buffer_get_source_state(const struct comp_buffer *buffer)
}
/**
- * @brief helper, provide state of a component connected to a buffer as a data consumer
- *
- * @param buffer a buffer to be checked
- *
- * @retval COMP_STATE_NOT_EXIST if there's no connected component
- * @return state of the component
+ * \brief Provide state of a component connected to a buffer as a data consumer.
+ * \param[in] buffer Interconnect buffer to be checked.
+ * \retval COMP_STATE_NOT_EXIST If there's no connected component.
+ * \return State of the component.
*/
static inline int comp_buffer_get_sink_state(const struct comp_buffer *buffer)
{
@@ -1205,46 +1131,45 @@ static inline int comp_buffer_get_sink_state(const struct comp_buffer *buffer)
}
/**
- * Warning: duplicate declaration in topology.h
+ * \brief Verify and set component audio parameters.
*
- * Called by component in params() function in order to set and update some of
- * downstream (playback) or upstream (capture) buffer parameters with pcm
- * parameters. There is a possibility to specify which of parameters won't be
- * overwritten (e.g. SRC component should not overwrite rate parameter, because
- * it is able to change it).
+ * Called by component in params() function in order to set and update some of
+ * downstream (playback) or upstream (capture) buffer parameters with PCM
+ * parameters.
*
- * @param dev Component device
- * @param flag Specifies which parameter should not be updated
- * @param params pcm params
+ * \param[in,out] dev Component device.
+ * \param[in] flag Specifies which parameter should not be updated.
+ * \param[in,out] params PCM stream parameters.
+ * \return 0 on success, negative error code on failure.
*/
int comp_verify_params(struct comp_dev *dev, uint32_t flag,
struct sof_ipc_stream_params *params);
-/** @}*/
-
/**
- * Update ibs, obs, cpc, ll chunk size for component.
- *
- * @param dev Component to update.
+ * \brief Update IBS, OBS, CPC, LL chunk size for component.
+ * \param[in,out] dev Component to update.
*/
void comp_update_ibs_obs_cpc(struct comp_dev *dev);
/**
- * If component has assigned slot in performance measurement window,
- * initialize its fields.
- * @param dev Component to init.
+ * \brief Initialize performance data fields if component has assigned slot in measurement window.
+ * \param[in,out] dev Component to init.
*/
void comp_init_performance_data(struct comp_dev *dev);
/**
- * Update performance data entry for component. Also checks for budget violation.
- *
- * @param dev Component to update.
- * @param cycles_used Execution time.
- * @return true if budget violation occurred
+ * \brief Update performance data entry for component and check for budget violation.
+ * \param[in,out] dev Component to update.
+ * \param[in] cycles_used Execution time.
+ * \return True if budget violation occurred, false otherwise.
*/
bool comp_update_performance_data(struct comp_dev *dev, uint32_t cycles_used);
+/**
+ * \brief Get memory region flag for component buffer allocations.
+ * \param[in] drv Component driver pointer.
+ * \return Memory flag (SOF_MEM_FLAG_*).
+ */
static inline int user_get_buffer_memory_region(const struct comp_driver *drv)
{
#if CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP
@@ -1253,4 +1178,7 @@ static inline int user_get_buffer_memory_region(const struct comp_driver *drv)
return SOF_MEM_FLAG_USER;
#endif
}
+
+/** @}*/
+
#endif /* __SOF_AUDIO_COMPONENT_H__ */
diff --git a/src/include/sof/audio/component_ext.h b/src/include/sof/audio/component_ext.h
index 4bb88cce72e2..74562203864e 100644
--- a/src/include/sof/audio/component_ext.h
+++ b/src/include/sof/audio/component_ext.h
@@ -19,7 +19,7 @@
#include
#include
-/** \addtogroup audio_pipeline_api
+/** \addtogroup component_infra_api
* @{
*/
@@ -28,19 +28,35 @@ struct comp_driver_list {
struct list_item list; /**< list of component drivers */
};
-/** \brief Retrieves the component device buffer list. */
+/** \brief Retrieves the component device buffer list based on direction.
+ * \param[in] comp Component device pointer.
+ * \param[in] dir Direction (PPL_DIR_DOWNSTREAM or PPL_DIR_UPSTREAM).
+ * \return Pointer to sink list or source list.
+ */
#define comp_buffer_list(comp, dir) \
((dir) == PPL_DIR_DOWNSTREAM ? &(comp)->bsink_list : \
&(comp)->bsource_list)
-/** See comp_ops::new */
#if CONFIG_IPC_MAJOR_3
+/**
+ * \brief Instantiate a new component device from IPC3 descriptor.
+ * \param[in] comp IPC3 component descriptor.
+ * \return Pointer to new component device, or NULL on failure.
+ */
struct comp_dev *comp_new(struct sof_ipc_comp *comp);
#elif CONFIG_IPC_MAJOR_4
+/**
+ * \brief Instantiate a new component device from IPC4 module initialization descriptor.
+ * \param[in] module_init IPC4 module initialization data.
+ * \return Pointer to new component device, or NULL on failure.
+ */
struct comp_dev *comp_new_ipc4(const struct ipc4_module_init_instance *module_init);
#endif
-/** See comp_ops::free */
+/**
+ * \brief Free component device via driver ops.
+ * \param[in,out] dev Component device to free.
+ */
static inline void comp_free(struct comp_dev *dev)
{
const struct comp_driver *drv = dev->drv;
@@ -55,10 +71,10 @@ static inline void comp_free(struct comp_dev *dev)
}
/**
- * Parameter init for component on other core.
- * @param dev Component device.
- * @param params Parameters to be set.
- * @return 0 if succeeded, error code otherwise.
+ * \brief Parameter initialization for component on remote core.
+ * \param[in,out] dev Component device.
+ * \param[in] params Stream parameters to be set.
+ * \return 0 if succeeded, error code otherwise.
*/
static inline int comp_params_remote(struct comp_dev *dev,
struct sof_ipc_stream_params *params)
@@ -69,7 +85,12 @@ static inline int comp_params_remote(struct comp_dev *dev,
return idc_send_msg(&msg, IDC_BLOCKING);
}
-/** See comp_ops::params */
+/**
+ * \brief Configure audio stream parameters for component device.
+ * \param[in,out] dev Component device.
+ * \param[in,out] params Audio (PCM) stream parameters to configure.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_params(struct comp_dev *dev,
struct sof_ipc_stream_params *params)
{
@@ -97,7 +118,13 @@ static inline int comp_params(struct comp_dev *dev,
return ret;
}
-/** See comp_ops::dai_get_hw_params */
+/**
+ * \brief Retrieve DAI hardware parameters from component device.
+ * \param[in] dev Component device.
+ * \param[out] params Stream parameters to populate.
+ * \param[in] dir Stream direction (enum sof_ipc_stream_direction).
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_dai_get_hw_params(struct comp_dev *dev,
struct sof_ipc_stream_params *params,
int dir)
@@ -109,7 +136,14 @@ static inline int comp_dai_get_hw_params(struct comp_dev *dev,
}
#if CONFIG_IPC_MAJOR_3
-/** See comp_ops::cmd */
+/**
+ * \brief Dispatch IPC3 command to component device.
+ * \param[in,out] dev Component device.
+ * \param[in] cmd Command code.
+ * \param[in,out] data Command data buffer.
+ * \param[in] max_data_size Maximum acceptable size of returned data.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_cmd(struct comp_dev *dev, int cmd, void *data,
int max_data_size)
{
@@ -133,7 +167,10 @@ static inline int comp_cmd(struct comp_dev *dev, int cmd, void *data,
#endif
/**
- * Runs comp_ops::trigger on the core the target component is assigned to.
+ * \brief Run trigger command on remote core for target component.
+ * \param[in,out] dev Component device.
+ * \param[in] cmd Trigger command (COMP_TRIGGER_*).
+ * \return 0 on success, negative error code on failure.
*/
static inline int comp_trigger_remote(struct comp_dev *dev, int cmd)
{
@@ -144,6 +181,12 @@ static inline int comp_trigger_remote(struct comp_dev *dev, int cmd)
return idc_send_msg(&msg, IDC_BLOCKING);
}
+/**
+ * \brief Run trigger command locally on current core for target component.
+ * \param[in,out] dev Component device.
+ * \param[in] cmd Trigger command (COMP_TRIGGER_*).
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_trigger_local(struct comp_dev *dev, int cmd)
{
int ret;
@@ -170,7 +213,12 @@ static inline int comp_trigger_local(struct comp_dev *dev, int cmd)
return ret;
}
-/** See comp_ops::trigger */
+/**
+ * \brief Dispatch trigger command to component (local or remote).
+ * \param[in,out] dev Component device.
+ * \param[in] cmd Trigger command (COMP_TRIGGER_*).
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_trigger(struct comp_dev *dev, int cmd)
{
int ret;
@@ -184,7 +232,11 @@ static inline int comp_trigger(struct comp_dev *dev, int cmd)
return ret;
}
-/** Runs comp_ops::prepare on the target component's core */
+/**
+ * \brief Run prepare command on remote core for target component.
+ * \param[in,out] dev Component device.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_prepare_remote(struct comp_dev *dev)
{
struct idc_msg msg = { IDC_MSG_PREPARE,
@@ -193,7 +245,11 @@ static inline int comp_prepare_remote(struct comp_dev *dev)
return idc_send_msg(&msg, IDC_BLOCKING);
}
-/** See comp_ops::prepare */
+/**
+ * \brief Prepare component device for streaming (local or remote).
+ * \param[in,out] dev Component device.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_prepare(struct comp_dev *dev)
{
if (dev->drv->ops.prepare)
@@ -203,14 +259,29 @@ static inline int comp_prepare(struct comp_dev *dev)
return 0;
}
+/**
+ * \brief Process and copy audio data through component.
+ * \param[in,out] dev Component device.
+ * \return Number of copied frames, or negative error code on failure.
+ */
int comp_copy(struct comp_dev *dev);
#if CONFIG_IPC_MAJOR_4
+/**
+ * \brief Remote payload for component get_attribute IPC4 message.
+ */
struct get_attribute_remote_payload {
- uint32_t type;
- void *value;
+ uint32_t type; /**< Attribute type (COMP_ATTR_*) */
+ void *value; /**< Pointer to attribute value storage */
};
+/**
+ * \brief Retrieve component attribute from a remote core (IPC4).
+ * \param[in,out] dev Component device.
+ * \param[in] type Attribute type (COMP_ATTR_*).
+ * \param[out] value Pointer to buffer where attribute value is copied.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_ipc4_get_attribute_remote(struct comp_dev *dev, uint32_t type,
void *value)
{
@@ -243,7 +314,13 @@ static inline int comp_ipc4_get_attribute_remote(struct comp_dev *dev, uint32_t
}
#endif /* CONFIG_IPC_MAJOR_4 */
-/** See comp_ops::get_attribute */
+/**
+ * \brief Get component attribute.
+ * \param[in,out] dev Component device.
+ * \param[in] type Attribute type (COMP_ATTR_*).
+ * \param[out] value Pointer to buffer where attribute value is returned.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_get_attribute(struct comp_dev *dev, uint32_t type,
void *value)
{
@@ -262,7 +339,13 @@ static inline int comp_get_attribute(struct comp_dev *dev, uint32_t type,
#endif
}
-/** See comp_ops::set_attribute */
+/**
+ * \brief Set component attribute.
+ * \param[in,out] dev Component device.
+ * \param[in] type Attribute type (COMP_ATTR_*).
+ * \param[in] value Pointer to attribute value to set.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_set_attribute(struct comp_dev *dev, uint32_t type,
void *value)
{
@@ -272,7 +355,11 @@ static inline int comp_set_attribute(struct comp_dev *dev, uint32_t type,
return 0;
}
-/** Runs comp_ops::reset on the target component's core */
+/**
+ * \brief Run reset command on remote core for target component.
+ * \param[in,out] dev Component device.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_reset_remote(struct comp_dev *dev)
{
struct idc_msg msg = { IDC_MSG_RESET,
@@ -282,9 +369,9 @@ static inline int comp_reset_remote(struct comp_dev *dev)
}
/**
- * Component reset and free runtime resources.
- * @param dev Component device.
- * @return 0 if succeeded, error code otherwise.
+ * \brief Reset component and free runtime resources (local or remote).
+ * \param[in,out] dev Component device.
+ * \return 0 on success, negative error code on failure.
*/
static inline int comp_reset(struct comp_dev *dev)
{
@@ -296,7 +383,13 @@ static inline int comp_reset(struct comp_dev *dev)
}
#if CONFIG_IPC_MAJOR_3
-/** See comp_ops::dai_config */
+/**
+ * \brief Configure DAI component.
+ * \param[in,out] dev Component device.
+ * \param[in] config IPC DAI configuration.
+ * \param[in] spec_config Spec-specific configuration data.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_dai_config(struct comp_dev *dev, struct ipc_config_dai *config,
const void *spec_config)
{
@@ -308,6 +401,14 @@ static inline int comp_dai_config(struct comp_dev *dev, struct ipc_config_dai *c
return 0;
}
#elif CONFIG_IPC_MAJOR_4
+/**
+ * \brief Configure DAI component (IPC4).
+ * \param[in,out] dd DAI driver data.
+ * \param[in,out] dev Component device.
+ * \param[in] config IPC DAI configuration.
+ * \param[in] spec_config Spec-specific configuration data.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_dai_config(struct dai_data *dd, struct comp_dev *dev,
struct ipc_config_dai *config, const void *spec_config)
{
@@ -316,7 +417,13 @@ static inline int comp_dai_config(struct dai_data *dd, struct comp_dev *dev,
#else
#error Unknown IPC major version
#endif
-/** See comp_ops::position */
+
+/**
+ * \brief Retrieve stream position from component.
+ * \param[in,out] dev Component device.
+ * \param[out] posn Stream position structure to populate.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_position(struct comp_dev *dev,
struct sof_ipc_stream_posn *posn)
{
@@ -327,16 +434,19 @@ static inline int comp_position(struct comp_dev *dev,
}
/**
- * Allocates and initializes audio component list.
+ * \brief Allocates and initializes audio component list.
+ *
* To be called once at boot time.
+ *
+ * \param[in,out] sof SOF global system context.
*/
void sys_comp_init(struct sof *sof);
/**
- * Checks if two component devices belong to the same parent pipeline.
- * @param current Component device.
- * @param previous Another component device.
- * @return 1 if children of the same pipeline, 0 otherwise.
+ * \brief Checks if two component devices belong to the same parent pipeline.
+ * \param[in] current Component device.
+ * \param[in] previous Another component device.
+ * \return 1 if children of the same pipeline, 0 otherwise.
*/
static inline int comp_is_single_pipeline(struct comp_dev *current,
struct comp_dev *previous)
@@ -345,9 +455,9 @@ static inline int comp_is_single_pipeline(struct comp_dev *current,
}
/**
- * Checks if component device is active.
- * @param current Component device.
- * @return 1 if active, 0 otherwise.
+ * \brief Checks if component device is active.
+ * \param[in] current Component device.
+ * \return 1 if active, 0 otherwise.
*/
static inline int comp_is_active(struct comp_dev *current)
{
@@ -355,9 +465,9 @@ static inline int comp_is_active(struct comp_dev *current)
}
/**
- * Returns component state based on requested command.
- * @param cmd Request command.
- * @return Component state.
+ * \brief Returns component state based on requested command.
+ * \param[in] cmd Request command (COMP_TRIGGER_*).
+ * \return Component state (COMP_STATE_*).
*/
static inline int comp_get_requested_state(int cmd)
{
@@ -390,8 +500,8 @@ static inline int comp_get_requested_state(int cmd)
/**
* \brief Returns endpoint type of given component.
- * @param dev Component device
- * @return Endpoint type, one of comp_endpoint_type.
+ * \param[in] dev Component device.
+ * \return Endpoint type, one of comp_endpoint_type (COMP_ENDPOINT_*).
*/
static inline int comp_get_endpoint_type(struct comp_dev *dev)
{
@@ -406,9 +516,9 @@ static inline int comp_get_endpoint_type(struct comp_dev *dev)
}
/**
- * Called to check whether component schedules its pipeline.
- * @param dev Component device.
- * @return True if this is scheduling component, false otherwise.
+ * \brief Called to check whether component schedules its pipeline.
+ * \param[in] dev Component device.
+ * \return True if this is scheduling component, false otherwise.
*/
static inline bool comp_is_scheduling_source(struct comp_dev *dev)
{
@@ -416,8 +526,8 @@ static inline bool comp_is_scheduling_source(struct comp_dev *dev)
}
/**
- * Called to mark component as shared between cores
- * @param dev Component device.
+ * \brief Called to mark component as shared between cores.
+ * \param[in,out] dev Component device.
*/
static inline void comp_make_shared(struct comp_dev *dev)
{
@@ -425,8 +535,8 @@ static inline void comp_make_shared(struct comp_dev *dev)
}
/**
- * Get the global component driver list.
- * @return Pointer to the component driver list.
+ * \brief Get the global component driver list.
+ * \return Pointer to the component driver list.
*/
#ifdef CONFIG_SOF_USERSPACE_LL
struct comp_driver_list *comp_drivers_get(void);
@@ -438,6 +548,12 @@ static inline struct comp_driver_list *comp_drivers_get(void)
#endif
#if CONFIG_IPC_MAJOR_4
+/**
+ * \brief Send bind message to component on remote core (IPC4).
+ * \param[in,out] dev Component device.
+ * \param[in] bind_data Binding information.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_ipc4_bind_remote(struct comp_dev *dev, const struct bind_info *bind_data)
{
struct idc_msg msg = { IDC_MSG_BIND,
@@ -448,6 +564,12 @@ static inline int comp_ipc4_bind_remote(struct comp_dev *dev, const struct bind_
}
#endif
+/**
+ * \brief Bind component to downstream/upstream component or buffer.
+ * \param[in,out] dev Component device.
+ * \param[in] bind_data Binding information.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_bind(struct comp_dev *dev, const struct bind_info *bind_data)
{
#if CONFIG_IPC_MAJOR_4
@@ -467,6 +589,12 @@ static inline int comp_bind(struct comp_dev *dev, const struct bind_info *bind_d
}
#if CONFIG_IPC_MAJOR_4
+/**
+ * \brief Send unbind message to component on remote core (IPC4).
+ * \param[in,out] dev Component device.
+ * \param[in] unbind_data Unbinding information.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_ipc4_unbind_remote(struct comp_dev *dev, const struct bind_info *unbind_data)
{
struct idc_msg msg = { IDC_MSG_UNBIND,
@@ -477,6 +605,12 @@ static inline int comp_ipc4_unbind_remote(struct comp_dev *dev, const struct bin
}
#endif
+/**
+ * \brief Unbind component from downstream/upstream component or buffer.
+ * \param[in,out] dev Component device.
+ * \param[in] unbind_data Unbinding information.
+ * \return 0 on success, negative error code on failure.
+ */
static inline int comp_unbind(struct comp_dev *dev, const struct bind_info *unbind_data)
{
#if CONFIG_IPC_MAJOR_4
@@ -496,6 +630,13 @@ static inline int comp_unbind(struct comp_dev *dev, const struct bind_info *unbi
#endif
}
+/**
+ * \brief Retrieve total data processed by component.
+ * \param[in] dev Component device.
+ * \param[in] stream_no Stream index.
+ * \param[in] input True for input data, false for output data.
+ * \return Total processed data in bytes.
+ */
static inline uint64_t comp_get_total_data_processed(struct comp_dev *dev, uint32_t stream_no,
bool input)
{
@@ -507,7 +648,12 @@ static inline uint64_t comp_get_total_data_processed(struct comp_dev *dev, uint3
return ret;
}
-/** Returns true if the component's pipeline matches the specified direction */
+/**
+ * \brief Returns true if the component's pipeline matches the specified direction.
+ * \param[in] comp Component device.
+ * \param[in] dir Stream direction (SOF_IPC_STREAM_PLAYBACK or SOF_IPC_STREAM_CAPTURE).
+ * \return True if matching direction, false otherwise.
+ */
static inline bool comp_same_dir(struct comp_dev *comp, enum sof_ipc_stream_direction dir)
{
int end_type = comp_get_endpoint_type(comp->pipeline->sink_comp);
diff --git a/src/include/sof/audio/format_generic.h b/src/include/sof/audio/format_generic.h
index f5f2179ecee0..3902fc244ed0 100644
--- a/src/include/sof/audio/format_generic.h
+++ b/src/include/sof/audio/format_generic.h
@@ -6,7 +6,7 @@
/**
* @file sof/audio/format_generic.h
* @brief Generic audio sample saturation helpers.
- * @ingroup audio_pipeline_api
+ * @ingroup audio_format_api
*/
#ifndef __SOF_AUDIO_FORMAT_GENERIC_H__
@@ -14,10 +14,14 @@
#include
+/** \addtogroup audio_format_api
+ * @{
+ */
+
/**
- * @brief Saturate a 64-bit integer to signed 32-bit integer range.
- * @param x Input 64-bit integer.
- * @return Saturated 32-bit integer clamped between INT32_MIN and INT32_MAX.
+ * \brief Saturate a 64-bit integer to signed 32-bit integer range.
+ * \param[in] x Input 64-bit integer.
+ * \return Saturated 32-bit integer clamped between INT32_MIN and INT32_MAX.
*/
static inline int32_t sat_int32(int64_t x)
{
@@ -30,9 +34,9 @@ static inline int32_t sat_int32(int64_t x)
}
/**
- * @brief Saturate a 32-bit integer to signed 24-bit integer range.
- * @param x Input 32-bit integer.
- * @return Saturated 24-bit integer clamped between INT24_MINVALUE and INT24_MAXVALUE.
+ * \brief Saturate a 32-bit integer to signed 24-bit integer range.
+ * \param[in] x Input 32-bit integer.
+ * \return Saturated 24-bit integer clamped between INT24_MINVALUE and INT24_MAXVALUE.
*/
static inline int32_t sat_int24(int32_t x)
{
@@ -45,9 +49,9 @@ static inline int32_t sat_int24(int32_t x)
}
/**
- * @brief Saturate a 32-bit integer to signed 16-bit integer range.
- * @param x Input 32-bit integer.
- * @return Saturated 16-bit integer clamped between INT16_MIN and INT16_MAX.
+ * \brief Saturate a 32-bit integer to signed 16-bit integer range.
+ * \param[in] x Input 32-bit integer.
+ * \return Saturated 16-bit integer clamped between INT16_MIN and INT16_MAX.
*/
static inline int16_t sat_int16(int32_t x)
{
@@ -60,9 +64,9 @@ static inline int16_t sat_int16(int32_t x)
}
/**
- * @brief Saturate a 32-bit integer to signed 8-bit integer range.
- * @param x Input 32-bit integer.
- * @return Saturated 8-bit integer clamped between INT8_MIN and INT8_MAX.
+ * \brief Saturate a 32-bit integer to signed 8-bit integer range.
+ * \param[in] x Input 32-bit integer.
+ * \return Saturated 8-bit integer clamped between INT8_MIN and INT8_MAX.
*/
static inline int8_t sat_int8(int32_t x)
{
@@ -74,4 +78,6 @@ static inline int8_t sat_int8(int32_t x)
return (int8_t)x;
}
+/** @}*/
+
#endif /* __SOF_AUDIO_FORMAT_GENERIC_H__ */
diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h
index b708ef46093c..1e0d82d23380 100644
--- a/src/include/sof/audio/module_adapter/module/generic.h
+++ b/src/include/sof/audio/module_adapter/module/generic.h
@@ -191,18 +191,66 @@ struct module_processing_data {
/*****************************************************************************/
int module_load_config(struct comp_dev *dev, const void *cfg, size_t size);
int module_init(struct processing_module *mod);
+/**
+ * @brief Allocate aligned stream buffer memory for a processing module.
+ *
+ * Allocates buffer memory via the module's allocation context using
+ * #SOF_MEM_FLAG_USER and #SOF_MEM_FLAG_LARGE_BUFFER. Tracked in module
+ * resources and automatically freed on module teardown.
+ *
+ * @param mod Pointer to processing module.
+ * @param size Buffer size in bytes.
+ * @param alignment Required alignment in bytes.
+ * @return Pointer to allocated buffer, or NULL on failure.
+ */
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
__syscall void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment);
#else
void *z_impl_mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment);
#define mod_balloc_align z_impl_mod_balloc_align
#endif
+
+/**
+ * @brief Initialize module resource management locks and containers.
+ * @param mod Pointer to processing module.
+ */
void mod_resource_init(struct processing_module *mod);
+
+/**
+ * @brief Query module memory heap boundary and size.
+ * @param mod Pointer to processing module.
+ * @param size Pointer to receive heap size in bytes.
+ * @param start Pointer to receive heap start address.
+ */
void mod_heap_info(struct processing_module *mod, size_t *size, uintptr_t *start);
+
+/**
+ * @brief Allocate memory for a module with explicit flags and alignment.
+ *
+ * Allocates memory from the module's allocation context (mod_alloc_ctx).
+ * Automatically registered in module resources and released on module removal.
+ *
+ * @param mod Pointer to processing module.
+ * @param flags Memory allocation flags (SOF_MEM_FLAG_...).
+ * @param size Size in bytes to allocate.
+ * @param alignment Required alignment in bytes.
+ * @return Pointer to allocated memory, or NULL on failure.
+ */
#if defined(__ZEPHYR__) && defined(CONFIG_SOF_FULL_ZEPHYR_APPLICATION)
__syscall void *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size,
size_t alignment);
+/**
+ * @brief Free a memory block previously allocated for a module.
+ * @param mod Pointer to processing module.
+ * @param ptr Pointer to memory to free.
+ * @return 0 on success, negative error code on failure.
+ */
__syscall int mod_free(struct processing_module *mod, const void *ptr);
+
+/**
+ * @brief Free all heap resources currently tracked for a module.
+ * @param mod Pointer to processing module.
+ */
__syscall void mod_free_all(struct processing_module *mod);
#else
void *z_impl_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size,
@@ -215,11 +263,11 @@ void z_impl_mod_free_all(struct processing_module *mod);
#endif
/**
- * Allocates aligned memory block for module.
- * @param mod Pointer to the module this memory block is allocated for.
- * @param size Size in bytes.
- * @param alignment Alignment in bytes.
- * @return Pointer to the allocated memory or NULL if failed.
+ * @brief Allocate aligned memory block for module with user privileges.
+ * @param mod Pointer to processing module.
+ * @param size Size in bytes.
+ * @param alignment Alignment in bytes.
+ * @return Pointer to allocated memory, or NULL on failure.
*
* The allocated memory is automatically freed when the module is unloaded.
*/
@@ -228,16 +276,34 @@ static inline void *mod_alloc_align(struct processing_module *mod, size_t size,
return mod_alloc_ext(mod, SOF_MEM_FLAG_USER, size, alignment);
}
+/**
+ * @brief Allocate stream buffer memory for module with natural alignment.
+ * @param mod Pointer to processing module.
+ * @param size Size in bytes.
+ * @return Pointer to allocated buffer, or NULL on failure.
+ */
static inline void *mod_balloc(struct processing_module *mod, size_t size)
{
return mod_balloc_align(mod, size, 0);
}
+/**
+ * @brief Allocate memory block for module with default natural alignment.
+ * @param mod Pointer to processing module.
+ * @param size Size in bytes.
+ * @return Pointer to allocated memory, or NULL on failure.
+ */
static inline void *mod_alloc(struct processing_module *mod, size_t size)
{
return mod_alloc_align(mod, size, 0);
}
+/**
+ * @brief Allocate zero-initialized memory block for module.
+ * @param mod Pointer to processing module.
+ * @param size Size in bytes.
+ * @return Pointer to zero-initialized allocated memory, or NULL on failure.
+ */
static inline void *mod_zalloc(struct processing_module *mod, size_t size)
{
void *ret = mod_alloc(mod, size);
diff --git a/src/include/sof/audio/pipeline.h b/src/include/sof/audio/pipeline.h
index 5fa2f860021f..a621aee488ab 100644
--- a/src/include/sof/audio/pipeline.h
+++ b/src/include/sof/audio/pipeline.h
@@ -27,6 +27,10 @@
#include
#include
+/** \addtogroup audio_pipeline_api
+ * @{
+ */
+
struct comp_buffer;
struct comp_dev;
struct ipc;
@@ -34,124 +38,138 @@ struct ipc_msg;
struct k_heap;
struct mod_alloc_ctx;
-/*
- * Pipeline status to stop execution of current path, but to keep the
- * pipeline alive, when processing COMP_TRIGGER_STOP or COMP_TRIGGER_PAUSE
+/**
+ * \brief Pipeline status to stop execution of current path, but to keep the
+ * pipeline alive, when processing COMP_TRIGGER_STOP or COMP_TRIGGER_PAUSE.
*/
#define PPL_STATUS_PATH_STOP 1
-/*
- * Pipeline status to stop execution of current path, and to terminate the
- * pipeline, when processing COMP_TRIGGER_STOP or COMP_TRIGGER_PAUSE
+
+/**
+ * \brief Pipeline status to stop execution of current path, and to terminate the
+ * pipeline, when processing COMP_TRIGGER_STOP or COMP_TRIGGER_PAUSE.
*/
#define PPL_STATUS_PATH_TERMINATE 2
-/* Pipeline scheduled in another thread other than ipc thread */
+/** \brief Pipeline scheduled in another thread other than IPC thread. */
#define PPL_STATUS_SCHEDULED 2
-/* pipeline connection directions */
-#define PPL_CONN_DIR_COMP_TO_BUFFER 0
-#define PPL_CONN_DIR_BUFFER_TO_COMP 1
+/** \name Pipeline connection directions
+ * @{
+ */
+#define PPL_CONN_DIR_COMP_TO_BUFFER 0 /**< Connection from component to buffer */
+#define PPL_CONN_DIR_BUFFER_TO_COMP 1 /**< Connection from buffer to component */
+/** @}*/
-/* pipeline processing directions */
-#define PPL_DIR_DOWNSTREAM 0
-#define PPL_DIR_UPSTREAM 1
+/** \name Pipeline processing directions
+ * @{
+ */
+#define PPL_DIR_DOWNSTREAM 0 /**< Downstream playback/processing direction */
+#define PPL_DIR_UPSTREAM 1 /**< Upstream capture/processing direction */
+/** @}*/
-/*
- * Audio pipeline.
+/**
+ * \brief Audio pipeline structure representing a stream graph and execution context.
*/
struct pipeline {
- struct mod_alloc_ctx *alloc; /**< alloc context used for allocating this pipeline */
- uint32_t comp_id; /**< component id for pipeline */
- uint32_t pipeline_id; /**< pipeline id */
- uint32_t sched_id; /**< Scheduling component id */
- uint32_t core; /**< core we run on */
- uint32_t period; /**< execution period in us*/
- uint32_t priority; /**< priority level 0 (low) to 10 (max) */
- uint32_t period_mips; /**< worst case instruction count per period */
- uint32_t frames_per_sched;/**< output frames of pipeline, 0 is variable */
- uint32_t xrun_limit_usecs; /**< report xruns greater than limit */
- uint32_t time_domain; /**< scheduling time domain */
- uint32_t attributes; /**< pipeline attributes from IPC extension msg/ */
+ struct mod_alloc_ctx *alloc; /**< Alloc context used for allocating this pipeline */
+ uint32_t comp_id; /**< Component ID for pipeline */
+ uint32_t pipeline_id; /**< Pipeline ID */
+ uint32_t sched_id; /**< Scheduling component ID */
+ uint32_t core; /**< Core we run on */
+ uint32_t period; /**< Execution period in microseconds */
+ uint32_t priority; /**< Priority level 0 (low) to 10 (max) */
+ uint32_t period_mips; /**< Worst case instruction count per period */
+ uint32_t frames_per_sched;/**< Output frames of pipeline, 0 is variable */
+ uint32_t xrun_limit_usecs; /**< Report xruns greater than limit */
+ uint32_t time_domain; /**< Scheduling time domain */
+ uint32_t attributes; /**< Pipeline attributes from IPC extension message */
/* runtime status */
- int32_t xrun_bytes; /* last xrun length */
- uint32_t status; /* pipeline status */
- struct tr_ctx tctx; /* trace settings */
+ int32_t xrun_bytes; /**< Last xrun length in bytes */
+ uint32_t status; /**< Pipeline status flags */
+ struct tr_ctx tctx; /**< Trace settings */
/* scheduling */
#ifdef CONFIG_IPC_MAJOR_4
- struct task *trigger_task; /* IPC4 pipeline trigger task */
+ struct task *trigger_task; /**< IPC4 pipeline trigger task */
#endif
- struct task *pipe_task; /* IPC3 pipeline processing task or IPC4 pipeline copy task */
- struct pipeline *sched_next; /* pipeline scheduled after this */
- struct pipeline *sched_prev; /* pipeline scheduled before this */
+ struct task *pipe_task; /**< IPC3 pipeline processing task or IPC4 pipeline copy task */
+ struct pipeline *sched_next; /**< Pipeline scheduled after this */
+ struct pipeline *sched_prev; /**< Pipeline scheduled before this */
/* component that drives scheduling in this pipe */
- struct comp_dev *sched_comp;
+ struct comp_dev *sched_comp; /**< Component that drives scheduling in this pipe */
/* source component for this pipe */
- struct comp_dev *source_comp;
+ struct comp_dev *source_comp; /**< Source component for this pipe */
/* sink component for this pipe */
- struct comp_dev *sink_comp;
+ struct comp_dev *sink_comp; /**< Sink component for this pipe */
- struct list_item list; /**< list in walk context */
+ struct list_item list; /**< List item in walk context */
/* position update */
- uint32_t posn_offset; /* position update array offset*/
- struct ipc_msg *msg;
+ uint32_t posn_offset; /**< Position update array offset */
+ struct ipc_msg *msg; /**< IPC message pointer for position updates */
struct {
- int cmd;
- struct comp_dev *host;
- unsigned int delay; /* period count */
- bool aborted; /* STOP or PAUSE failed, stay active */
- bool pending; /* trigger scheduled but not executed yet */
- } trigger;
+ int cmd; /**< Trigger command */
+ struct comp_dev *host; /**< Associated host component device */
+ unsigned int delay; /**< Period count delay */
+ bool aborted; /**< STOP or PAUSE failed, stay active */
+ bool pending; /**< Trigger scheduled but not executed yet */
+ } trigger; /**< Pipeline trigger control structure */
};
+/**
+ * \brief Pipeline traversal walk context for graph exploration and operations.
+ */
struct pipeline_walk_context {
+ /** Callback function invoked for each component in walk */
int (*comp_func)(struct comp_dev *cd, struct comp_buffer *buffer,
struct pipeline_walk_context *ctx, int dir);
- void *comp_data;
+ void *comp_data; /**< Component callback user data */
+ /** Callback function invoked for each buffer in walk */
void (*buff_func)(struct comp_buffer *buffer, void *data);
- void *buff_data;
- struct comp_buffer *incoming;
- /**< pipelines to be scheduled after trigger walk */
- struct list_item pipelines;
+ void *buff_data; /**< Buffer callback user data */
+ struct comp_buffer *incoming; /**< Incoming buffer context */
+ struct list_item pipelines; /**< Pipelines to be scheduled after trigger walk */
/*
* If this flag is set, pipeline_for_each_comp() will skip all
* incompletely initialised components, i.e. those, whose .pipeline ==
* NULL. Such components should not be skipped during initialisation
* and clean up, but they should be skipped during streaming.
*/
- bool skip_incomplete;
+ bool skip_incomplete; /**< Skip incompletely initialized components */
};
-/* generic pipeline data used by pipeline_comp_* functions */
+/**
+ * \brief Generic pipeline data used by pipeline_comp_* functions.
+ */
struct pipeline_data {
- struct comp_dev *start;
- struct sof_ipc_pcm_params *params;
- struct sof_ipc_stream_posn *posn;
- struct pipeline *p;
- int cmd;
- uint32_t delay_ms; /* between PRE_{START,RELEASE} and {START,RELEASE} */
+ struct comp_dev *start; /**< Starting component device */
+ struct sof_ipc_pcm_params *params; /**< Stream PCM parameters */
+ struct sof_ipc_stream_posn *posn; /**< Stream position structure */
+ struct pipeline *p; /**< Target pipeline */
+ int cmd; /**< Command code */
+ uint32_t delay_ms; /**< Delay in milliseconds between pre and main trigger phases */
#if CONFIG_KCPS_DYNAMIC_CLOCK_CONTROL
- int32_t kcps[CONFIG_CORE_COUNT]; /**< the max count of KCPS */
+ int32_t kcps[CONFIG_CORE_COUNT]; /**< The max count of KCPS per core */
#endif
};
/** \brief Task type registered by pipelines. */
struct pipeline_task {
- struct task task; /**< parent structure */
- bool registrable; /**< should task be registered on irq */
- struct comp_dev *sched_comp; /**< pipeline scheduling component */
+ struct task task; /**< Parent task structure */
+ bool registrable; /**< Should task be registered on IRQ */
+ struct comp_dev *sched_comp; /**< Pipeline scheduling component */
};
struct ipc4_pipeline_ext_obj_mem_data;
-/** \brief For storing IPC payload data. */
+/** \brief For storing IPC payload data during pipeline creation. */
struct create_pipeline_params {
- const struct ipc4_pipeline_ext_obj_mem_data *mem_data;
+ const struct ipc4_pipeline_ext_obj_mem_data *mem_data; /**< IPC4 pipeline external memory descriptor */
};
+/** \brief Retrieves the enclosing pipeline_task structure from a task pointer. */
#define pipeline_task_get(t) container_of(t, struct pipeline_task, task)
/*
@@ -163,113 +181,113 @@ struct create_pipeline_params {
/**
* \brief Creates a new pipeline.
- * \param[in] heap Heap to allocate the pipeline on, or NULL for default.
+ * \param[in,out] heap Heap to allocate the pipeline on, or NULL for default.
* \param[in] pipeline_id Pipeline ID number.
* \param[in] priority Pipeline scheduling priority.
* \param[in] comp_id Pipeline component ID number.
- * \param[in] pparams Pipeline parameters from IPC payload, maybe NULL.
- * \return New pipeline pointer or NULL.
+ * \param[in] pparams Pipeline parameters from IPC payload, may be NULL.
+ * \return Pointer to new pipeline on success, or NULL on failure.
*/
struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_t priority,
uint32_t comp_id, struct create_pipeline_params *pparams);
/**
- * \brief Free's a pipeline.
- * \param[in] p pipeline.
- * \return 0 on success.
+ * \brief Frees a pipeline and its associated resources.
+ * \param[in,out] p Pipeline to free.
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_free(struct pipeline *p);
/**
* \brief Connect components in a pipeline.
- * \param[in] comp connecting component.
- * \param[in] buffer connecting buffer.
- * \param[in] dir Connection direction.
- * \return 0 on success.
+ * \param[in,out] comp Connecting component device.
+ * \param[in,out] buffer Connecting buffer.
+ * \param[in] dir Connection direction (PPL_CONN_DIR_*).
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_connect(struct comp_dev *comp, struct comp_buffer *buffer,
int dir);
/**
- * \brief Creates a new pipeline.
- * \param[in] comp connecting component.
- * \param[in] buffer connecting buffer.
- * \param[in] dir Connection direction.
+ * \brief Disconnect components and buffers in a pipeline.
+ * \param[in,out] comp Connecting component device.
+ * \param[in,out] buffer Connecting buffer.
+ * \param[in] dir Connection direction (PPL_CONN_DIR_*).
*/
void pipeline_disconnect(struct comp_dev *comp, struct comp_buffer *buffer,
int dir);
/**
- * \brief Completes a pipeline.
- * \param[in] p pipeline.
- * \param[in] source Pipeline component device.
- * \param[in] sink Pipeline component device.
- * \return 0 on success.
+ * \brief Completes a pipeline setup by verifying connectivity between source and sink.
+ * \param[in,out] p Pipeline to complete.
+ * \param[in,out] source Pipeline source component device.
+ * \param[in,out] sink Pipeline sink component device.
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_complete(struct pipeline *p, struct comp_dev *source,
struct comp_dev *sink);
/**
* \brief Initializes pipeline position structure.
- * \param[in,out] sof Pointer to sof structure.
+ * \param[in,out] sof Pointer to global SOF system context.
*/
void pipeline_posn_init(struct sof *sof);
#ifdef CONFIG_SOF_USERSPACE_LL
/**
* \brief Grants user-space thread access to pipeline position mutex.
- * \param[in] thread Thread to grant access to.
+ * \param[in,out] thread Thread to grant access to.
*/
void pipeline_posn_grant_access(struct k_thread *thread);
#endif
/**
- * \brief Resets the pipeline and free runtime resources.
- * \param[in] p pipeline.
- * \param[in] host_cd Host DMA component device.
- * \return 0 on success.
+ * \brief Resets the pipeline and frees runtime resources.
+ * \param[in,out] p Pipeline to reset.
+ * \param[in,out] host_cd Host DMA component device.
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_reset(struct pipeline *p, struct comp_dev *host_cd);
/**
* \brief Sets End Of Stream state for all devices in the pipeline.
- * \param[in] p pipeline.
- * \param[in] eos End Of Stream state.
+ * \param[in,out] p Target pipeline.
+ * \param[in] eos End Of Stream flag state.
*/
void pipeline_set_eos(struct pipeline *p, bool eos);
/**
* \brief Walks the pipeline graph for each component.
- * \param[in] current Current pipeline component.
- * \param[in] ctx Pipeline graph walk context.
- * \param[in] dir Walk direction.
- * \return 0 on success.
+ * \param[in,out] current Current pipeline component to start traversal from.
+ * \param[in,out] ctx Pipeline graph walk context.
+ * \param[in] dir Walk direction (PPL_DIR_*).
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_for_each_comp(struct comp_dev *current,
struct pipeline_walk_context *ctx, int dir);
/**
- * \brief Walks pipeline graph to find dai component.
- * \param[in] pipeline_id is the start pipeline id.
- * \param[in] dir is the direction of the traversal.
- * \return dai component.
+ * \brief Walks pipeline graph to find DAI component.
+ * \param[in] pipeline_id Start pipeline ID.
+ * \param[in] dir Direction of traversal (PPL_DIR_*).
+ * \return Pointer to DAI component device, or NULL if not found.
*/
struct comp_dev *pipeline_get_dai_comp(uint32_t pipeline_id, int dir);
#if CONFIG_IPC_MAJOR_4
/**
- * \brief Walks pipeline graph to find dai component and latency.
- * \param[in] pipeline_id is the start pipeline id.
- * \param[out] latency to dai.
- * \return dai component.
+ * \brief Walks pipeline graph to find DAI component and latency.
+ * \param[in] pipeline_id Start pipeline ID.
+ * \param[out] latency Receives latency to DAI as a count of buffered processing blocks (input_data/ibs - output_data/obs).
+ * \return Pointer to DAI component device, or NULL if not found.
*/
struct comp_dev *pipeline_get_dai_comp_latency(uint32_t pipeline_id, uint32_t *latency);
#endif
/**
- * Retrieves pipeline id from pipeline.
- * @param p pipeline.
- * @return pipeline id.
+ * \brief Retrieves pipeline ID from pipeline structure.
+ * \param[in] p Target pipeline.
+ * \return Pipeline ID.
*/
static inline uint32_t pipeline_id(struct pipeline *p)
{
@@ -283,20 +301,20 @@ static inline uint32_t pipeline_id(struct pipeline *p)
*/
/**
- * \brief Creates a new pipeline.
- * \param[in] p pipeline.
- * \param[in] cd Pipeline component device.
- * \param[in] params Pipeline parameters.
- * \return 0 on success.
+ * \brief Sets pipeline runtime audio stream parameters.
+ * \param[in,out] p Pipeline to configure.
+ * \param[in,out] cd Pipeline component device.
+ * \param[in] params Stream PCM parameters.
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_params(struct pipeline *p, struct comp_dev *cd,
struct sof_ipc_pcm_params *params);
/**
- * \brief Prepares pipeline for processing.
- * \param[in] p pipeline.
+ * \brief Prepares pipeline for audio processing.
+ * \param[in,out] p Pipeline to prepare.
* \param[in,out] cd Pipeline component device.
- * \return 0 on success.
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_prepare(struct pipeline *p, struct comp_dev *cd);
@@ -307,35 +325,35 @@ int pipeline_prepare(struct pipeline *p, struct comp_dev *cd);
*/
/**
- * \brief Trigger pipeline - IPC context
- * \param[in] p pipeline.
- * \param[in] host Host DMA component.
- * \param[in] cmd Pipeline trigger command.
- * \return 0 on success.
+ * \brief Trigger pipeline in IPC context.
+ * \param[in,out] p Target pipeline.
+ * \param[in,out] host Host DMA component device.
+ * \param[in] cmd Pipeline trigger command (COMP_TRIGGER_*).
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_trigger(struct pipeline *p, struct comp_dev *host, int cmd);
/**
- * \brief Trigger pipeline - either IPC or pipeline task context
- * \param[in] p pipeline.
- * \param[in] host Host DMA component.
- * \param[in] cmd Pipeline trigger command.
- * \return 0 on success.
+ * \brief Trigger pipeline in either IPC or pipeline task context.
+ * \param[in,out] p Target pipeline.
+ * \param[in,out] host Host DMA component device.
+ * \param[in] cmd Pipeline trigger command (COMP_TRIGGER_*).
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_trigger_run(struct pipeline *p, struct comp_dev *host, int cmd);
/**
- * \brief Copy data along a pipeline.
- * \param[in] p pipeline.
- * \return 0 on success.
+ * \brief Copy and process stream data along a pipeline.
+ * \param[in,out] p Target pipeline.
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_copy(struct pipeline *p);
/**
- * \brief Get time pipeline timestamps from host to dai.
- * \param[in] p pipeline.
- * \param[in] host_dev Host DMA component.
- * \param[in,out] posn Pipeline stream position.
+ * \brief Get pipeline timestamps from host to DAI.
+ * \param[in] p Target pipeline.
+ * \param[in] host_dev Host DMA component device.
+ * \param[in,out] posn Pipeline stream position structure to populate.
*/
void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host_dev,
struct sof_ipc_stream_posn *posn);
@@ -347,10 +365,10 @@ void pipeline_get_timestamp(struct pipeline *p, struct comp_dev *host_dev,
*/
/**
- * \brief Checks if two pipelines have the same scheduling component.
- * \param[in] current This pipeline.
- * \param[in] previous Other pipeline.
- * \return true if both pipelines are scheduled together.
+ * \brief Checks if two pipelines share the same scheduling component.
+ * \param[in] current First pipeline.
+ * \param[in] previous Second pipeline.
+ * \return True if both pipelines are scheduled together, false otherwise.
*/
static inline bool pipeline_is_same_sched_comp(struct pipeline *current,
struct pipeline *previous)
@@ -359,9 +377,9 @@ static inline bool pipeline_is_same_sched_comp(struct pipeline *current,
}
/**
- * \brief Is pipeline is scheduled with timer.
- * \param[in] p pipeline.
- * \return true if pipeline uses timer based scheduling.
+ * \brief Checks if pipeline is scheduled with timer.
+ * \param[in] p Target pipeline.
+ * \return True if pipeline uses timer-based scheduling, false otherwise.
*/
static inline bool pipeline_is_timer_driven(struct pipeline *p)
{
@@ -369,9 +387,9 @@ static inline bool pipeline_is_timer_driven(struct pipeline *p)
}
/**
- * \brief Is pipeline is scheduled on this core.
- * \param[in] p pipeline.
- * \return true if pipeline core ID == current core ID.
+ * \brief Checks if pipeline is scheduled on the current core.
+ * \param[in] p Target pipeline.
+ * \return True if pipeline core ID matches current core ID, false otherwise.
*/
static inline bool pipeline_is_this_cpu(struct pipeline *p)
{
@@ -379,57 +397,57 @@ static inline bool pipeline_is_this_cpu(struct pipeline *p)
}
/**
- * \brief Init an LL task for a pipeline.
- * \param[in] p pipeline.
- * \return 0 on success.
+ * \brief Initializes a low-latency (LL) task for a pipeline.
+ * \param[in,out] p Target pipeline.
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_comp_ll_task_init(struct pipeline *p);
/**
- * \brief Free the LL tasks owned by a pipeline.
- * \param[in] p pipeline.
+ * \brief Frees the low-latency (LL) tasks owned by a pipeline.
+ * \param[in,out] p Target pipeline.
*/
void pipeline_comp_ll_task_free(struct pipeline *p);
/**
- * \brief Init a DP task for a component
- * \param[in] comp a component the task is created for
- * \return 0 on success.
+ * \brief Initializes a data processing (DP) task for a component.
+ * \param[in,out] comp Component device for which the task is created.
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_comp_dp_task_init(struct comp_dev *comp);
/**
- * \brief Schedule a pipeline copy to run after a delay
- * \param[in] p pipeline.
+ * \brief Schedules a pipeline copy operation to run after a delay.
+ * \param[in,out] p Target pipeline.
* \param[in] start Pipeline start time in microseconds.
*/
void pipeline_schedule_copy(struct pipeline *p, uint64_t start);
/**
- * \brief Trigger pipeline's scheduling component.
- * \param[in] p pipeline.
+ * \brief Triggers pipeline's scheduling component.
+ * \param[in,out] p Target pipeline.
* \param[in,out] comp Pipeline component device.
- * \param[in] ctx Pipeline graph walk context.
+ * \param[in,out] ctx Pipeline graph walk context.
*/
void pipeline_comp_trigger_sched_comp(struct pipeline *p,
struct comp_dev *comp,
struct pipeline_walk_context *ctx);
/**
- * \brief Schedule all triggered pipelines.
- * \param[in] ctx Pipeline graph walk context.
- * \param[in] cmd Trigger command.
+ * \brief Schedules all triggered pipelines collected during traversal.
+ * \param[in,out] ctx Pipeline graph walk context.
+ * \param[in] cmd Trigger command (COMP_TRIGGER_*).
*/
void pipeline_schedule_triggered(struct pipeline_walk_context *ctx,
int cmd);
/**
- * \brief Configure pipeline scheduling.
- * \param[in] p pipeline.
+ * \brief Configures pipeline scheduling parameters.
+ * \param[in,out] p Target pipeline.
* \param[in] sched_id Scheduling component ID.
- * \param[in] core DSP core pipeline runs on.
- * \param[in] period Pipeline scheduling period in us.
- * \param[in] period_mips Pipeline worst case MCPS per period.
+ * \param[in] core DSP core the pipeline runs on.
+ * \param[in] period Pipeline scheduling period in microseconds.
+ * \param[in] period_mips Pipeline worst-case MCPS per period.
* \param[in] frames_per_sched Pipeline frames processed per schedule.
* \param[in] time_domain Pipeline scheduling time domain.
*/
@@ -445,40 +463,43 @@ void pipeline_schedule_config(struct pipeline *p, uint32_t sched_id,
*/
/**
- * \brief Recover the pipeline from a XRUN condition.
- * \param[in] p pipeline.
- * \return 0 on success.
+ * \brief Recovers the pipeline from an XRUN condition.
+ * \param[in,out] p Target pipeline.
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_xrun_recover(struct pipeline *p);
/**
- * \brief Perform xrun recovery.
- * \param[in] p pipeline.
- * \param[in] cmd Trigger command.
- * \return 0 on success.
+ * \brief Performs XRUN recovery trigger handling.
+ * \param[in,out] p Target pipeline.
+ * \param[in] cmd Trigger command (COMP_TRIGGER_*).
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_xrun_handle_trigger(struct pipeline *p, int cmd);
/**
- * \brief notify host that we have XRUN.
- * \param[in] p pipeline.
- * \param[in] dev Pipeline component device.
- * \param[in] bytes Number of bytes we have over or under run.
+ * \brief Notifies host and pipeline that an XRUN condition occurred.
+ * \param[in,out] p Target pipeline.
+ * \param[in,out] dev Pipeline component device where XRUN occurred.
+ * \param[in] bytes Number of overrun or underrun bytes.
*/
void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, int32_t bytes);
/**
- * \brief Set tolerance for pipeline xrun handling.
- * \param[in] p pipeline.
- * \param[in] xrun_limit_usecs Limit in micro secs that pipeline will tolerate.
+ * \brief Sets tolerance limit for pipeline XRUN handling.
+ * \param[in,out] p Target pipeline.
+ * \param[in] xrun_limit_usecs Limit in microseconds that pipeline will tolerate before reporting.
+ * \return 0 on success, or negative error code on failure.
*/
int pipeline_xrun_set_limit(struct pipeline *p, uint32_t xrun_limit_usecs);
/**
- * \brief Sends an ipc notification that an error occurred in the module's processing function.
- * \param[in] component The component in which the error occurred.
- * \param[in] error_code Error code.
+ * \brief Sends an IPC notification that an error occurred in a module's processing function.
+ * \param[in] component Component device in which the error occurred.
+ * \param[in] error_code Error code to report.
*/
void pipeline_comp_copy_error_notify(const struct comp_dev *component, int error_code);
+/** @}*/
+
#endif /* __SOF_AUDIO_PIPELINE_H__ */
diff --git a/src/include/sof/audio/ring_buffer.h b/src/include/sof/audio/ring_buffer.h
index 1ef712a56743..61b1b1e4d83c 100644
--- a/src/include/sof/audio/ring_buffer.h
+++ b/src/include/sof/audio/ring_buffer.h
@@ -4,6 +4,12 @@
*
*/
+/**
+ * @file sof/audio/ring_buffer.h
+ * @brief Lockless async circular ring buffer for cross-core audio processing.
+ * @ingroup audio_buffer_api
+ */
+
#ifndef __SOF_RING_BUFFER_H__
#define __SOF_RING_BUFFER_H__
@@ -16,6 +22,10 @@
#include
#include
+/** \addtogroup audio_buffer_api
+ * @{
+ */
+
/**
* ring_buffer is a lockless async circular buffer
* providing safe consumer/producer cached operations cross cores that may be write/read
@@ -101,31 +111,33 @@ struct comp_dev;
struct ring_buffer;
struct sof_audio_stream_params;
-/* the ring_buffer structure */
+/**
+ * \brief Lockless asynchronous circular ring buffer structure.
+ */
struct ring_buffer {
/* public: read only */
- struct sof_audio_buffer audio_buffer;
+ struct sof_audio_buffer audio_buffer; /**< Embedded audio buffer base structure */
- size_t data_buffer_size;
+ size_t data_buffer_size; /**< Total allocated data buffer capacity in bytes */
- uint8_t __sparse_cache *_data_buffer;
- size_t _write_offset; /* private: to be modified by data producer using API */
- size_t _read_offset; /* private: to be modified by data consumer using API */
+ uint8_t __sparse_cache *_data_buffer; /**< Pointer to circular data buffer memory */
+ size_t _write_offset; /**< Producer write offset in bytes */
+ size_t _read_offset; /**< Consumer read offset in bytes */
};
/**
- *
- * @param dev pointer to the DP module device structure
- * @param min_available minimum data available in queue required by the module using
- * ring_buffer's source api
- * @param min_free_space minimum buffer space in queue required by the module using
- * ring_buffer's sink api
- * @param is_shared indicates if the buffer will be shared between cores
- * @param id a stream ID, accessible later by sink_get_id/source_get_id
- *
+ * \brief Create and allocate a lockless async circular ring buffer.
+ * \param[in,out] dev Pointer to component device creating this buffer.
+ * \param[in] min_available Minimum data available required by source API consumer.
+ * \param[in] min_free_space Minimum buffer space required by sink API producer.
+ * \param[in] is_shared True if buffer memory is shared across processing cores.
+ * \param[in] id Stream identifier accessible via sink/source interface.
+ * \return Pointer to newly allocated ring_buffer, or NULL on failure.
*/
struct ring_buffer *ring_buffer_create(struct comp_dev *dev, size_t min_available,
size_t min_free_space, bool is_shared,
uint32_t id);
+/** @}*/
+
#endif /* __SOF_RING_BUFFER_H__ */
diff --git a/src/include/sof/audio/sink_api.h b/src/include/sof/audio/sink_api.h
index 11ffc6e08c3d..0059353c123e 100644
--- a/src/include/sof/audio/sink_api.h
+++ b/src/include/sof/audio/sink_api.h
@@ -4,41 +4,62 @@
*
*/
+/**
+ * \file sof/audio/sink_api.h
+ * \brief Audio sink API helpers and stream configuration.
+ * \ingroup module_api
+ */
+
#ifndef __SOF_SINK_API_H__
#define __SOF_SINK_API_H__
#include
+/** \addtogroup module_api
+ * @{
+ */
+
/**
- * Init of the API, must be called before any operation
+ * \brief Initialize sink API structure before any operation.
+ *
+ * NOTE: audio_stream_params must be accessible by the caller core, and the
+ * implementation must ensure coherent access to the parameters (e.g. for a
+ * cross-core shared queue, it must be located in non-cached memory).
*
- * @param sink pointer to the structure
- * @param ops pointer to API operations
- * @param audio_stream_params pointer to structure with audio parameters
- * note that the audio_stream_params must be accessible by the caller core
- * the implementation must ensure coherent access to the parameteres
- * in case of i.e. cross core shared queue, it must be located in non-cached memory
+ * \param[in,out] sink Pointer to sink structure.
+ * \param[in] ops Pointer to API operations vtable.
+ * \param[in] audio_stream_params Pointer to structure with audio parameters.
*/
void sink_init(struct sof_sink *sink, const struct sink_ops *ops,
struct sof_audio_stream_params *audio_stream_params);
/**
- * Get total number of bytes processed by the sink (meaning - committed by sink_commit_buffer())
- *
- * @param sink a handler to sink
- * @return total number of processed data
+ * \brief Get total number of bytes processed by the sink (committed by sink_commit_buffer()).
+ * \param[in] sink Pointer to sink structure.
+ * \return Total number of processed bytes.
*/
size_t sink_get_num_of_processed_bytes(struct sof_sink *sink);
/**
- * sets counter of total number of bytes processed to zero
+ * \brief Reset counter of total processed bytes to zero.
+ * \param[in,out] sink Pointer to sink structure.
*/
void sink_reset_num_of_processed_bytes(struct sof_sink *sink);
-/** set of functions for retrieve audio parameters */
+/**
+ * \brief Check if buffer overrun is permitted on sink stream.
+ * \param[in] sink Pointer to sink structure.
+ * \return True if overrun is permitted by audio stream params, false otherwise.
+ */
bool sink_get_overrun(struct sof_sink *sink);
-/** set of functions for setting audio parameters */
+/**
+ * \brief Set minimum free space required in sink buffer.
+ * \param[in,out] sink Pointer to sink structure.
+ * \param[in] min_free_space Minimum free space in bytes.
+ */
void sink_set_min_free_space(struct sof_sink *sink, size_t min_free_space);
+/** @}*/
+
#endif /* __SOF_SINK_API_H__ */
diff --git a/src/include/sof/audio/source_api.h b/src/include/sof/audio/source_api.h
index 2f84e1948ebe..3721cdfaec4f 100644
--- a/src/include/sof/audio/source_api.h
+++ b/src/include/sof/audio/source_api.h
@@ -4,76 +4,151 @@
*
*/
+/**
+ * \file sof/audio/source_api.h
+ * \brief Audio source API helpers and stream configuration.
+ * \ingroup module_api
+ */
+
#ifndef __SOF_SOURCE_API_H__
#define __SOF_SOURCE_API_H__
#include
+/** \addtogroup module_api
+ * @{
+ */
+
/**
- * Init of the API, must be called before any operation
+ * \brief Initialize source API structure before any operation.
*
- * @param source pointer to the structure
- * @param ops pointer to API operations
- * @param audio_stream_params pointer to structure with audio parameters
- * note that the audio_stream_params must be accessible by the caller core
- * the implementation must ensure coherent access to the parameteres
- * in case of i.e. cross core shared queue, it must be located in non-cached memory
+ * NOTE: audio_stream_params must be accessible by the caller core, and the
+ * implementation must ensure coherent access to the parameters (e.g. for a
+ * cross-core shared queue, it must be located in non-cached memory).
+ *
+ * \param[in,out] source Pointer to source structure.
+ * \param[in] ops Pointer to API operations vtable.
+ * \param[in] audio_stream_params Pointer to structure with audio parameters.
*/
void source_init(struct sof_source *source, const struct source_ops *ops,
struct sof_audio_stream_params *audio_stream_params);
/**
- * Get total number of bytes processed by the source (meaning - freed by source_release_data())
+ * \brief Get total number of bytes processed by the source (freed by source_release_data()).
+ * \param[in] source Pointer to source structure.
+ * \return Total number of processed bytes.
*/
size_t source_get_num_of_processed_bytes(struct sof_source *source);
/**
- * sets counter of total number of bytes processed to zero
+ * \brief Reset counter of total processed bytes to zero.
+ * \param[in,out] source Pointer to source structure.
*/
void source_reset_num_of_processed_bytes(struct sof_source *source);
-/** set of functions for retrieve audio parameters */
+/**
+ * \brief Check if buffer underrun is permitted on source stream.
+ * \param[in] source Pointer to source structure.
+ * \return True if underrun is permitted by audio stream params, false otherwise.
+ */
bool source_get_underrun(struct sof_source *source);
+
+/**
+ * \brief Get unique stream identifier for source.
+ * \param[in] source Pointer to source structure.
+ * \return Stream identifier.
+ */
uint32_t source_get_id(struct sof_source *source);
-/** set of functions for setting audio parameters */
+/**
+ * \brief Set audio frame format for source.
+ * \param[in,out] source Pointer to source structure.
+ * \param[in] frm_fmt Audio frame format.
+ * \return 0 on success, negative error code on failure.
+ */
int source_set_frm_fmt(struct sof_source *source, enum sof_ipc_frame frm_fmt);
+
+/**
+ * \brief Set valid sample format for source.
+ * \param[in,out] source Pointer to source structure.
+ * \param[in] valid_sample_fmt Valid sample format.
+ * \return 0 on success, negative error code on failure.
+ */
int source_set_valid_fmt(struct sof_source *source,
enum sof_ipc_frame valid_sample_fmt);
+
+/**
+ * \brief Set sample rate for source.
+ * \param[in,out] source Pointer to source structure.
+ * \param[in] rate Sample rate in Hz.
+ * \return 0 on success, negative error code on failure.
+ */
int source_set_rate(struct sof_source *source, unsigned int rate);
+
+/**
+ * \brief Set channel count for source.
+ * \param[in,out] source Pointer to source structure.
+ * \param[in] channels Number of audio channels.
+ * \return 0 on success, negative error code on failure.
+ */
int source_set_channels(struct sof_source *source, unsigned int channels);
+
+/**
+ * \brief Configure whether underrun is permitted on source.
+ * \param[in,out] source Pointer to source structure.
+ * \param[in] underrun_permitted True if underrun is permitted, false otherwise.
+ * \return 0 on success, negative error code on failure.
+ */
int source_set_underrun(struct sof_source *source, bool underrun_permitted);
+
+/**
+ * \brief Set buffer format for source.
+ * \param[in,out] source Pointer to source structure.
+ * \param[in] buffer_fmt Buffer format identifier.
+ * \return 0 on success, negative error code on failure.
+ */
int source_set_buffer_fmt(struct sof_source *source, uint32_t buffer_fmt);
+
+/**
+ * \brief Set minimum available data requirement in bytes.
+ * \param[in,out] source Pointer to source structure.
+ * \param[in] min_available Minimum available bytes.
+ */
void source_set_min_available(struct sof_source *source, size_t min_available);
/**
- * initial set of audio parameters, provided in sof_ipc_stream_params
- *
- * @param source a handler to source
- * @param params the set of parameters
- * @param force_update tells the implementation that the params should override actual settings
- * @return 0 if success
+ * \brief Configure initial set of audio parameters.
+ * \param[in,out] source Pointer to source structure.
+ * \param[in] params Audio stream parameters.
+ * \param[in] force_update True to force parameters override.
+ * \return 0 on success, negative error code on failure.
*/
int source_set_params(struct sof_source *source,
struct sof_ipc_stream_params *params, bool force_update);
/**
- * Set frame_align_shift and frame_align of stream according to byte_align and
- * frame_align_req alignment requirement. Once the channel number,frame size
- * are determined, the frame_align and frame_align_shift are determined too.
- * these two feature will be used in audio_stream_get_avail_frames_aligned
- * to calculate the available frames. it should be called in component prepare
- * or param functions only once before stream copy. if someone forgets to call
- * this first, there would be unexampled error such as nothing is copied at all.
+ * \brief Set byte and frame alignment constants for source stream.
*
- * @param source a handler to source
- * @param byte_align Processing byte alignment requirement.
- * @param frame_align_req Processing frames alignment requirement.
+ * Sets frame_align_shift and frame_align of stream according to byte_align and
+ * frame_align_req requirements. Once the channel number and frame size are
+ * determined, the frame_align and frame_align_shift are determined too.
+ * These features are used by audio_stream_get_avail_frames_aligned() to
+ * calculate available frames.
*
- * @return 0 if success
+ * @note This must be called in component prepare or param functions only once
+ * after channel count and frame size are known and before stream copying begins.
+ * If omitted or called late, aligned availability can evaluate to zero and
+ * no data will be copied.
+ *
+ * \param[in,out] source Pointer to source structure.
+ * \param[in] byte_align Processing byte alignment requirement.
+ * \param[in] frame_align_req Processing frames alignment requirement.
+ * \return 0 on success, negative error code on failure.
*/
int source_set_alignment_constants(struct sof_source *source,
const uint32_t byte_align,
const uint32_t frame_align_req);
+/** @}*/
+
#endif /* __SOF_SOURCE_API_H__ */
diff --git a/src/include/sof/coherent.h b/src/include/sof/coherent.h
index 172e45b4ed92..8b4e49142f3c 100644
--- a/src/include/sof/coherent.h
+++ b/src/include/sof/coherent.h
@@ -5,6 +5,12 @@
* Author: Liam Girdwood
*/
+/**
+ * @file sof/coherent.h
+ * @brief Cache-coherent multi-core shared memory access abstractions.
+ * @ingroup memory_api
+ */
+
#ifndef __SOF_COHERENT_H__
#define __SOF_COHERENT_H__
@@ -17,6 +23,11 @@
#include
#include
+/** \addtogroup memory_api
+ * @{
+ */
+
+/** @brief Cache line alignment specifier for coherent shared memory objects. */
#define __coherent __aligned(PLATFORM_DCACHE_ALIGN)
/*
@@ -52,21 +63,27 @@
* This structure must not be accessed outside of these APIs.
* The shared flag is only set at coherent init and thereafter it's RO.
*/
+
+/**
+ * @brief Header embedded at start of multi-core shared memory objects for cache coherence.
+ *
+ * Ensures cache line alignment and synchronizes cached/uncached state transitions across DSP cores.
+ * Must only be manipulated via coherent_* APIs.
+ */
struct coherent {
union {
struct {
- struct k_spinlock lock; /* locking mechanism */
- k_spinlock_key_t key; /* lock flags */
+ struct k_spinlock lock; /**< Spinlock synchronizing multi-core access. */
+ k_spinlock_key_t key; /**< Spinlock key storing interrupt flags. */
};
#ifdef __ZEPHYR__
- struct k_mutex mutex;
+ struct k_mutex mutex; /**< Mutex synchronizing thread-level access when sleeping is allowed. */
#endif
};
- uint8_t sleep_allowed; /* the object will never be acquired or released
- * in atomic context */
- uint8_t shared; /* shared on other non coherent cores */
- uint16_t core; /* owner core if not shared */
- struct list_item list; /* coherent list iteration */
+ uint8_t sleep_allowed; /**< Non-zero if context allows sleeping/blocking mutex operations. */
+ uint8_t shared; /**< Non-zero if object is shared across non-coherent cores. */
+ uint16_t core; /**< Owner core ID when object is not shared. */
+ struct list_item list; /**< Node for coherent tracking list iteration. */
} __coherent;
#if CONFIG_INCOHERENT
@@ -120,7 +137,17 @@ STATIC_ASSERT(sizeof(struct coherent) <= DCACHE_LINE_SIZE, DCACHE_LINE_SIZE_too
#endif
#if CONFIG_INCOHERENT
-/* When coherent_acquire() is called, we are sure not to have cache for this memory */
+/**
+ * @brief Acquire exclusive access to a cache-coherent shared object in atomic/spinlock context.
+ *
+ * For incoherent hardware platforms, validates uncache alias, acquires the spinlock,
+ * and invalidates the local data cache over the object range so local accesses observe
+ * fresh multi-core updates.
+ *
+ * @param[in,out] c Pointer to uncached coherent object header.
+ * @param[in] size Size of the coherent object including header in bytes.
+ * @return Pointer to the cached memory view of the coherent object.
+ */
__must_check static inline struct coherent __sparse_cache *coherent_acquire(struct coherent *c,
const size_t size)
{
@@ -155,6 +182,15 @@ __must_check static inline struct coherent __sparse_cache *coherent_acquire(stru
return cc;
}
+/**
+ * @brief Release exclusive access to a cache-coherent shared object in atomic/spinlock context.
+ *
+ * Writes back dirty cache lines across the object range to physical memory,
+ * invalidates local cache lines, and releases the multi-core spinlock.
+ *
+ * @param[in,out] c Pointer to cached memory view of the coherent object.
+ * @param[in] size Size of the coherent object including header in bytes.
+ */
static inline void coherent_release(struct coherent __sparse_cache *c,
const size_t size)
{
@@ -175,6 +211,16 @@ static inline void coherent_release(struct coherent __sparse_cache *c,
}
}
+/**
+ * @brief Internal helper to allocate and initialize a coherent shared object.
+ *
+ * Allocates cache-aligned uncached memory with SOF_MEM_FLAG_COHERENT and initializes
+ * the coherent spinlock, tracking list, and owner core ID.
+ *
+ * @param[in] offset Byte offset of the struct coherent member within the allocated object.
+ * @param[in] size Total size in bytes of the container object.
+ * @return Pointer to the newly allocated coherent object, or NULL on failure.
+ */
static inline void *__coherent_init(size_t offset, const size_t size)
{
/*
@@ -203,10 +249,26 @@ static inline void *__coherent_init(size_t offset, const size_t size)
return object;
}
+/**
+ * @brief Allocate and initialize a coherent shared object with spinlock protection.
+ *
+ * Wrapper around __coherent_init() computing the member offset and container type size.
+ *
+ * @param[in] type Type of the container structure.
+ * @param[in] member Member name of the embedded struct coherent.
+ */
#define coherent_init(type, member) __coherent_init(offsetof(type, member), \
sizeof(type))
-/* set the object to shared mode with coherency managed by SW */
+/**
+ * @brief Internal helper to mark an allocated coherent object as actively shared.
+ *
+ * Transitions the coherent object state to shared mode under spinlock protection
+ * and invalidates local cache.
+ *
+ * @param[in,out] c Pointer to uncached coherent object header.
+ * @param[in] size Total size in bytes of the coherent object.
+ */
static inline void __coherent_shared(struct coherent *c, const size_t size)
{
/* assert if someone passes a cache/local address in here. */
@@ -219,11 +281,29 @@ static inline void __coherent_shared(struct coherent *c, const size_t size)
k_spin_unlock(&c->lock, c->key);
}
+/**
+ * @brief Mark an allocated coherent object as actively shared across multiple DSP cores.
+ *
+ * Wrapper around __coherent_shared() computing the member address and container size.
+ *
+ * @param[in,out] object Pointer to the container structure.
+ * @param[in] member Member name of the embedded struct coherent.
+ */
#define coherent_shared(object, member) __coherent_shared(&(object)->member, \
sizeof(*object))
#ifdef __ZEPHYR__
+/**
+ * @brief Acquire exclusive access to a cache-coherent shared object in thread/mutex context.
+ *
+ * Locks the embedded mutex (blocking if necessary) and invalidates the local data
+ * cache region so thread-level accesses observe updates from other cores.
+ *
+ * @param[in,out] c Pointer to uncached coherent object header.
+ * @param[in] size Size of the coherent object including header in bytes.
+ * @return Pointer to the cached memory view of the coherent object.
+ */
__must_check static inline struct coherent __sparse_cache *coherent_acquire_thread(
struct coherent *c, const size_t size)
{
@@ -248,6 +328,15 @@ __must_check static inline struct coherent __sparse_cache *coherent_acquire_thre
return cc;
}
+/**
+ * @brief Release exclusive access to a cache-coherent shared object in thread/mutex context.
+ *
+ * Writes back dirty cache lines to physical memory, invalidates local cache,
+ * and unlocks the embedded mutex.
+ *
+ * @param[in,out] c Pointer to cached memory view of the coherent object.
+ * @param[in] size Size of the coherent object including header in bytes.
+ */
static inline void coherent_release_thread(struct coherent __sparse_cache *c,
const size_t size)
{
@@ -269,6 +358,16 @@ static inline void coherent_release_thread(struct coherent __sparse_cache *c,
}
}
+/**
+ * @brief Internal helper to allocate and initialize a thread-capable coherent shared object.
+ *
+ * Allocates cache-aligned uncached memory with SOF_MEM_FLAG_COHERENT and initializes
+ * the embedded mutex and list header with sleeping allowed.
+ *
+ * @param[in] offset Byte offset of the struct coherent member within the allocated object.
+ * @param[in] size Total size in bytes of the container object.
+ * @return Pointer to the newly allocated coherent object, or NULL on failure.
+ */
static inline void *__coherent_init_thread(size_t offset, const size_t size)
{
/* As above - prevent cache line sharing */
@@ -293,9 +392,26 @@ static inline void *__coherent_init_thread(size_t offset, const size_t size)
return object;
}
+/**
+ * @brief Allocate and initialize a coherent shared object with mutex protection for thread context.
+ *
+ * Wrapper around __coherent_init_thread() computing the member offset and container type size.
+ *
+ * @param[in] type Type of the container structure.
+ * @param[in] member Member name of the embedded struct coherent.
+ */
#define coherent_init_thread(type, member) __coherent_init_thread(offsetof(type, member), \
sizeof(type))
+/**
+ * @brief Internal helper to mark a thread-capable coherent object as actively shared.
+ *
+ * Transitions the coherent object state to shared mode under mutex protection
+ * and invalidates local cache.
+ *
+ * @param[in,out] c Pointer to uncached coherent object header.
+ * @param[in] size Total size in bytes of the coherent object.
+ */
static inline void __coherent_shared_thread(struct coherent *c, const size_t size)
{
/* assert if someone passes a cache/local address in here. */
@@ -309,11 +425,27 @@ static inline void __coherent_shared_thread(struct coherent *c, const size_t siz
k_mutex_unlock(&c->mutex);
}
+/**
+ * @brief Mark a thread-capable coherent object as shared across multiple DSP cores.
+ *
+ * Wrapper around __coherent_shared_thread() computing the member address and container size.
+ *
+ * @param[in,out] object Pointer to the container structure.
+ * @param[in] member Member name of the embedded struct coherent.
+ */
#define coherent_shared_thread(object, member) __coherent_shared_thread(&(object)->member, \
sizeof(*object))
#endif /* __ZEPHYR__ */
+/**
+ * @brief Invalidate cache and free a coherent shared memory object.
+ *
+ * Flushes dirty cache lines back to physical memory and frees the memory block via rfree().
+ *
+ * @param[in,out] object Pointer to the container structure.
+ * @param[in] member Member name of the embedded struct coherent.
+ */
#define coherent_free(object, member) \
do { \
/* assert if someone passes a cache address in here. */ \
@@ -324,7 +456,7 @@ static inline void __coherent_shared_thread(struct coherent *c, const size_t siz
rfree(object); \
} while (0)
-#else /* CONFIG_INCOHERENT */
+#else
/*
* Coherent devices only require locking to manage shared access.
@@ -442,7 +574,24 @@ static inline void __coherent_shared_thread(struct coherent *c, const size_t siz
#define coherent_shared_thread coherent_shared
#endif
+/**
+ * @brief Free a thread-capable coherent shared memory object.
+ *
+ * Flushes dirty cache lines back to physical memory and frees the memory block via rfree().
+ *
+ * @param[in,out] object Pointer to the container structure.
+ * @param[in] member Member name of the embedded struct coherent.
+ */
#define coherent_free_thread coherent_free
+/**
+ * @brief Query whether a coherent object is configured for multi-core shared mode.
+ * @param[in] object Pointer to the container structure.
+ * @param[in] member Member name of the embedded struct coherent.
+ * @return Non-zero if shared mode is enabled, 0 otherwise.
+ */
#define is_coherent_shared(object, member) ((object)->member.shared)
+
+/** @}*/
+
#endif
diff --git a/src/include/sof/ipc/schedule.h b/src/include/sof/ipc/schedule.h
index 3f3e12059701..5fe616b57974 100644
--- a/src/include/sof/ipc/schedule.h
+++ b/src/include/sof/ipc/schedule.h
@@ -6,6 +6,12 @@
* Keyon Jie
*/
+/**
+ * @file sof/ipc/schedule.h
+ * @brief Host IPC message dispatch and scheduling task interface.
+ * @ingroup scheduling_api ipc4_api
+ */
+
#ifndef __SOF_IPC_SCHEDULE_H__
#define __SOF_IPC_SCHEDULE_H__
@@ -14,14 +20,19 @@
#include
#include
-/** \brief Scheduling period for IPC task in microseconds. */
+/** \addtogroup scheduling_api
+ * @{
+ */
+
+/** @brief Scheduling period for host IPC worker task in microseconds. */
#define IPC_PERIOD_USEC 100
struct ipc;
/**
- * \brief Get IPC command processing deadline.
- * @param data Task structure.
+ * @brief Retrieve IPC command processing deadline.
+ * @param[in] data Task structure context pointer.
+ * @return Task deadline timestamp (@ref SOF_TASK_DEADLINE_NOW).
*/
static inline uint64_t ipc_task_deadline(void *data)
{
@@ -35,9 +46,11 @@ static inline uint64_t ipc_task_deadline(void *data)
}
/**
- * \brief Schedule processing of the next IPC command from host.
- * @param ipc The global IPC context.
+ * @brief Schedule processing of the next pending IPC command received from host.
+ * @param[in,out] ipc Global IPC subsystem context pointer.
*/
void ipc_schedule_process(struct ipc *ipc);
+/** @}*/
+
#endif
diff --git a/src/include/sof/lib/fast-get.h b/src/include/sof/lib/fast-get.h
index 05f098a752cc..dfea81410470 100644
--- a/src/include/sof/lib/fast-get.h
+++ b/src/include/sof/lib/fast-get.h
@@ -5,11 +5,21 @@
* Author: Jyri Sarha
*/
+/**
+ * @file sof/lib/fast-get.h
+ * @brief Dynamic SRAM staging and cache mechanisms for cold DRAM-resident modules.
+ * @ingroup memory_api
+ */
+
#ifndef __SOF_LIB_FAST_GET_H__
#define __SOF_LIB_FAST_GET_H__
#include
+/** \addtogroup memory_api
+ * @{
+ */
+
struct k_mem_domain;
struct mod_alloc_ctx;
@@ -25,7 +35,23 @@ struct mod_alloc_ctx;
#if (CONFIG_COLD_STORE_EXECUTE_DRAM && \
(CONFIG_LLEXT_TYPE_ELF_RELOCATABLE || !defined(LL_EXTENSION_BUILD))) || \
!CONFIG_SOF_FULL_ZEPHYR_APPLICATION
+/**
+ * @brief Stage DRAM-resident code or data into fast SRAM for execution.
+ * @param[in,out] alloc Pointer to allocation context.
+ * @param[in] dram_ptr Pointer to source data resident in DRAM.
+ * @param[in] size Size in bytes to stage.
+ * @return Pointer to staged SRAM memory, or NULL on allocation failure.
+ */
const void *fast_get(struct mod_alloc_ctx *alloc, const void * const dram_ptr, size_t size);
+
+/**
+ * @brief Release fast SRAM memory previously allocated by fast_get().
+ * @param[in,out] alloc Pointer to allocation context.
+ * @param[in,out] mdom Pointer to memory domain. Can be NULL for kernel threads or small allocations
+ * (<= FAST_GET_MAX_COPY_SIZE); required for large userspace staging buffers to
+ * remove the partition and prevent memory domain partition leaks.
+ * @param[in,out] sram_ptr Pointer to staged SRAM memory to release.
+ */
void fast_put(struct mod_alloc_ctx *alloc, struct k_mem_domain *mdom, const void *sram_ptr);
#else
static inline const void *fast_get(struct mod_alloc_ctx *alloc, const void * const dram_ptr,
@@ -37,4 +63,6 @@ static inline void fast_put(struct mod_alloc_ctx *alloc, struct k_mem_domain *md
const void *sram_ptr) {}
#endif
+/** @}*/
+
#endif /* __SOF_LIB_FAST_GET_H__ */
diff --git a/src/include/sof/lib/vregion.h b/src/include/sof/lib/vregion.h
index 559c47ed3431..fb5ae60e8c67 100644
--- a/src/include/sof/lib/vregion.h
+++ b/src/include/sof/lib/vregion.h
@@ -1,7 +1,12 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright(c) 2025 Intel Corporation.
-/* Pre Allocated Contiguous Virtual Region */
+/**
+ * @file sof/lib/vregion.h
+ * @brief Pre-allocated contiguous virtual memory region allocator (lifetime vs interim).
+ * @ingroup memory_api
+ */
+
#ifndef __SOF_LIB_VREGION_H__
#define __SOF_LIB_VREGION_H__
@@ -13,20 +18,28 @@
extern "C" {
#endif
+/** \addtogroup memory_api
+ * @{
+ */
+
+/**
+ * @brief Virtual region descriptor managing lifetime and interim heap partitions.
+ */
struct vregion;
/**
- * @brief Memory types for virtual region allocations.
- * Used to specify the type of memory allocation within a virtual region.
+ * @brief Memory allocation modes within a virtual memory region.
*
- * @note
- * - interim: allocation that can be freed i.e. get/set large config, kcontrols.
- * - lifetime: allocation that cannot be freed i.e. init data, pipeline data.
+ * Distinguishes lifetime allocations (bound to pipeline topology, cannot be freed until teardown)
+ * from interim allocations (dynamically created and released during runtime operations).
*/
enum vregion_mem_type {
- VREGION_MEM_TYPE_INTERIM, /* interim allocation that can be freed */
- VREGION_MEM_TYPE_LIFETIME, /* lifetime allocation */
- VREGION_MEM_TYPE_INVALID, /* Interim heap initialization failed */
+ /** @brief Interim allocation that can be freed dynamically (e.g. large config set/get, controls). */
+ VREGION_MEM_TYPE_INTERIM,
+ /** @brief Lifetime allocation that persists until region destruction (e.g. topology, module instances). */
+ VREGION_MEM_TYPE_LIFETIME,
+ /** @brief Invalid memory type indicating initialization error or exhaustion. */
+ VREGION_MEM_TYPE_INVALID,
};
#if CONFIG_SOF_VREGIONS
@@ -37,15 +50,20 @@ enum vregion_mem_type {
* Create a new virtual region instance with specified memory size.
* Allocations start in LIFETIME mode.
*
- * @param[in] memsize Total size of the virtual region memory.
- * @return struct vregion* Pointer to the new virtual region instance, or NULL on failure.
+ * @param[in] memsize Total size of the virtual region memory in bytes.
+ * @return Pointer to the new virtual region instance, or NULL on failure.
*/
struct vregion *vregion_create(size_t memsize);
/**
- * @brief Create and map a new virtual region instance.
+ * @brief Create and map a new virtual region instance accessible by user-space domains.
*
- * Like above, but usable by userspace and can add domain access.
+ * Allocates contiguous virtual memory and configures memory protection domain permissions.
+ *
+ * @param[out] vreg_start Output pointer receiving the virtual start address of the region.
+ * @param[in,out] vreg_size Input pointer specifying the requested size in bytes (must be non-zero);
+ * updated on return with the actual mapped size in bytes.
+ * @return Pointer to the allocated virtual region instance, or NULL on failure.
*/
__syscall struct vregion *vregion_create_map(uintptr_t *vreg_start, size_t *vreg_size);
@@ -96,16 +114,20 @@ __syscall struct vregion *vregion_put(struct vregion *vr);
__syscall void *vregion_alloc_align(struct vregion *vr, size_t size, size_t alignment);
/**
- * @brief like vregion_alloc_align() but allocates coherent memory
+ * @brief Allocate aligned coherent (uncached) memory from the specified virtual region.
+ * @param[in,out] vr Pointer to the virtual region instance.
+ * @param[in] size Size of memory to allocate in bytes.
+ * @param[in] alignment Alignment of memory to allocate in bytes.
+ * @return Pointer to the allocated coherent memory, or NULL on failure.
*/
__syscall void *vregion_alloc_coherent_align(struct vregion *vr, size_t size, size_t alignment);
/**
* @brief Allocate memory from the specified virtual region.
*
- * @param[in] vr Pointer to the virtual region instance.
+ * @param[in,out] vr Pointer to the virtual region instance.
* @param[in] size Size of memory to allocate in bytes.
- * @return void* Pointer to the allocated memory, or NULL on failure.
+ * @return Pointer to the allocated memory, or NULL on failure.
*/
static inline void *vregion_alloc(struct vregion *vr, size_t size)
{
@@ -113,7 +135,10 @@ static inline void *vregion_alloc(struct vregion *vr, size_t size)
}
/**
- * @brief like vregion_alloc() but allocates coherent memory
+ * @brief Allocate naturally aligned coherent (uncached) memory from the specified virtual region.
+ * @param[in,out] vr Pointer to the virtual region instance.
+ * @param[in] size Size of memory to allocate in bytes.
+ * @return Pointer to the allocated coherent memory, or NULL on failure.
*/
static inline void *vregion_alloc_coherent(struct vregion *vr, size_t size)
{
@@ -125,8 +150,8 @@ static inline void *vregion_alloc_coherent(struct vregion *vr, size_t size)
*
* Free memory previously allocated from the specified virtual region.
*
- * @param[in] vr Pointer to the virtual region instance.
- * @param[in] ptr Pointer to the memory to free.
+ * @param[in,out] vr Pointer to the virtual region instance.
+ * @param[in,out] ptr Pointer to the memory to free.
*/
__syscall void vregion_free(struct vregion *vr, void *ptr);
@@ -138,19 +163,24 @@ __syscall void vregion_free(struct vregion *vr, void *ptr);
void vregion_info(struct vregion *vr);
/**
- * @brief Get virtual region memory start and size.
+ * @brief Retrieve virtual region memory base address and size.
*
* @param[in] vr Pointer to the virtual region instance.
- * @param[in] size Pointer to size
- * @param[in] start Pointer to start
+ * @param[out] size Output pointer receiving total region size in bytes.
+ * @param[out] start Output pointer receiving starting virtual address.
*/
void vregion_mem_info(struct vregion *vr, size_t *size, uintptr_t *start);
+/**
+ * @brief Validate that a virtual region handle is genuine and isolated from user space.
+ * @param[in] vr Pointer to virtual region instance to verify.
+ * @return True if handle is valid and secure, false otherwise.
+ */
bool vregion_verify(struct vregion *vr);
#include
-#else /* CONFIG_SOF_VREGIONS */
+#else
struct vregion {
unsigned int use_count;
@@ -201,6 +231,8 @@ static inline bool vregion_verify(struct vregion *vr) {return false;}
#endif /* CONFIG_SOF_VREGIONS */
+/** @}*/
+
#ifdef __cplusplus
}
#endif
diff --git a/src/include/sof/schedule/dp_schedule.h b/src/include/sof/schedule/dp_schedule.h
index 1d6a3066e07f..1dac74b600ef 100644
--- a/src/include/sof/schedule/dp_schedule.h
+++ b/src/include/sof/schedule/dp_schedule.h
@@ -8,7 +8,22 @@
/**
* @file sof/schedule/dp_schedule.h
* @brief Data Processing (DP) preemptible worker thread scheduler.
- * @ingroup audio_pipeline_api
+ * @ingroup scheduling_api
+ *
+ * The Data Processing (DP) scheduler manages compute-intensive audio processing
+ * tasks by assigning a dedicated preemptible Zephyr thread to each SOF task.
+ *
+ * ### Key Architectural Properties
+ * - **Preemptible Execution**: Each DP task executes in its own Zephyr thread at a priority
+ * lower than the hard real-time Low-Latency (LL) scheduler thread.
+ * - **LL-Synchronized Evaluation**: At the end of each Low-Latency tick, `scheduler_dp_ll_tick()`
+ * evaluates all queued DP tasks. If a task's sources contain enough audio data and its sinks
+ * have sufficient buffer space, its deadline is calculated and applied to the Zephyr thread
+ * via `k_thread_absolute_deadline_set()`.
+ * - **Task States & Return Values**:
+ * - @ref SOF_TASK_STATE_RESCHEDULE : Task completed a data chunk and requests rescheduling next period.
+ * - @ref SOF_TASK_STATE_COMPLETED : Task completed processing and self-terminates until triggered again.
+ * - @ref SOF_TASK_STATE_CANCEL : Task was cancelled and will be removed from the active queue.
*/
#ifndef __SOF_SCHEDULE_DP_SCHEDULE_H__
@@ -23,61 +38,35 @@
#include
#include
+/** \addtogroup scheduling_api
+ * @{
+ */
+
struct processing_module;
struct module_ext_init_data;
/**
+ * @brief Initialize the Data Processing (DP) scheduler on the calling core.
*
- * DP scheduler is a scheduler that creates a separate preemptible Zephyr thread for each SOF task
- *
- * The task execution may be delayed and task may be re-scheduled periodically
- * NOTE: delayed start and rescheduling takes place in sync with LL scheduler, meaning the
- * DP scheduler is triggered on each core after all LL task have been completed
- *
- * Task run() may return:
- * SOF_TASK_STATE_RESCHEDULE - the task will be rescheduled as specified in scheduler period
- * note that task won't ever be rescheduled if LL is not running
- * SOF_TASK_STATE_COMPLETED - the task will be removed from scheduling,
- * calling schedule_task will add the task to processing again
- * task_complete() will be called
- * SOF_TASK_STATE_CANCEL - the task will be removed from scheduling,
- * calling schedule_task will add the task to processing again
- * task_complete() won't be called
- * other statuses - assert will go off
+ * Allocates per-core DP scheduler state and initializes its driving LL tick source task.
*
- * NOTE: task - means a SOF task
- * thread - means a Zephyr preemptible thread
- *
- * TODO - EDF:
- * Threads run on the same priority, lower than thread running LL tasks. Zephyr EDF mechanism
- * is used for decision which thread/task is to be scheduled next. The DP scheduler calculates
- * the task deadline and set it in Zephyr thread properties, the final scheduling decision is made
- * by Zephyr.
- *
- * Each time tick the scheduler iterates through the list of all active tasks and calculates
- * a deadline based on
- * - knowledge how the modules are bound
- * - declared time required by a task to complete processing
- * - the deadline of the last module
- *
- */
-
-/**
- * \brief Init the Data Processing scheduler
+ * @return 0 on success, negative error code (-ENOMEM) on failure.
*/
int scheduler_dp_init(void);
/**
- * \brief initialize a DP task and add it to scheduling
- * It must be called on core the task is declared to run on
+ * @brief Initialize a Data Processing task and attach a dedicated Zephyr worker thread.
+ *
+ * Must be invoked on the same core that the task is configured to execute on.
*
- * \param[out] task pointer, pointer to allocated task structure will be return
- * \param[in] uid pointer to UUID of the task
- * \param[in] ops pointer to task functions
- * \param[in] mod pointer to the module to be run
- * \param[in] core CPU the thread should run on
- * \param[in] stack_size size of stack for a zephyr task
- * \param[in] options task options used for creation
+ * @param[out] task Pointer to store the allocated @ref task structure.
+ * @param[in] uid UUID identifying the task/module.
+ * @param[in] ops Task operations callbacks (@ref task_ops).
+ * @param[in] mod Processing module descriptor bound to this task.
+ * @param[in] core DSP core affinity for the task thread.
+ * @param[in] stack_size Stack byte size for the Zephyr worker thread.
+ * @param[in] options Task configuration flags.
+ * @return 0 on success, negative error code on failure.
*/
int scheduler_dp_task_init(struct task **task,
const struct sof_uuid_entry *uid,
@@ -88,25 +77,36 @@ int scheduler_dp_task_init(struct task **task,
uint32_t options);
#if defined(__ZEPHYR__) && CONFIG_SOF_FULL_ZEPHYR_APPLICATION
+/**
+ * @brief Free kernel-side internal resources associated with a DP task.
+ * @param[in,out] task Task being freed.
+ */
__syscall void scheduler_dp_internal_free(struct task *task);
+
/**
* @brief Tick notification from the Low-Latency (LL) timer domain to the DP scheduler.
*
- * Checks if queued DP tasks require execution or synchronization following an LL period.
+ * Invoked on each core after all LL tasks complete. Evaluates readiness for all
+ * queued DP tasks, updates their absolute deadlines, and signals worker threads.
*/
__syscall void scheduler_dp_ll_tick(void);
#include
#endif
/**
- * \brief Extract information about scheduler's tasks
+ * @brief Extract telemetry information about Data Processing scheduler tasks.
*
- * \param scheduler_props Structure to be filled
- * \param data_off_size Pointer to the current size of the scheduler_props, to be updated
+ * Populates @ref scheduler_props with `COMP_PROCESSING_DOMAIN_DP` and active DP tasks.
+ *
+ * @param[out] scheduler_props Structure to be filled with DP scheduler properties.
+ * @param[in,out] data_off_size Pointer to the current size of scheduler_props buffer.
*/
void scheduler_get_task_info_dp(struct scheduler_props *scheduler_props,
uint32_t *data_off_size);
+/**
+ * @brief Events signaled to Data Processing (DP) worker threads.
+ */
enum {
DP_TASK_EVENT_PROCESS = BIT(0), /* Need to process data */
DP_TASK_EVENT_CANCEL = BIT(1), /* Thread cancellation */
@@ -157,10 +157,14 @@ union scheduler_dp_thread_ipc_param {
};
/**
- * @brief Dispatch an IPC command to a Data Processing (DP) worker thread.
- * @param pmod Pointer to the processing module descriptor.
- * @param cmd IPC command identifier to execute.
- * @param param Parameters payload for the IPC command.
+ * @brief Dispatch an IPC command synchronously to a Data Processing (DP) worker thread.
+ *
+ * Posts DP_TASK_EVENT_IPC to the thread's event queue and blocks waiting on completion
+ * (via dp_sync with a 100 ms timeout) before returning.
+ *
+ * @param[in,out] pmod Pointer to the processing module descriptor.
+ * @param[in] cmd IPC command identifier to execute.
+ * @param[in,out] param Parameters payload for the IPC command.
* @return 0 on success, negative error code on failure.
*/
#if CONFIG_ZEPHYR_DP_SCHEDULER
@@ -174,5 +178,7 @@ static inline int scheduler_dp_thread_ipc(struct processing_module *pmod,
return 0;
}
#endif
+
+/** @}*/
#endif /* __SOF_SCHEDULE_DP_SCHEDULE_H__ */
diff --git a/src/include/sof/schedule/edf_schedule.h b/src/include/sof/schedule/edf_schedule.h
index 1cc14f54d8d8..64bcbbaa2ed6 100644
--- a/src/include/sof/schedule/edf_schedule.h
+++ b/src/include/sof/schedule/edf_schedule.h
@@ -7,8 +7,13 @@
/**
* @file sof/schedule/edf_schedule.h
- * @brief Earliest Deadline First (EDF) scheduler interface.
- * @ingroup audio_pipeline_api
+ * @brief Legacy Earliest Deadline First (EDF) workqueue scheduler interface.
+ * @ingroup scheduling_api
+ * @deprecated Deprecated for modern audio pipeline processing. In Zephyr-based builds,
+ * EDF is implemented as a delayed workqueue (edf_workq) retained for
+ * host IPC processing and legacy KPB draining tasks until migration.
+ * Audio pipeline components should use @ref SOF_SCHEDULE_DP with native
+ * Zephyr thread deadlines or @ref SOF_SCHEDULE_LL_TIMER / @ref SOF_SCHEDULE_LL_DMA.
*/
#ifndef __SOF_SCHEDULE_EDF_SCHEDULE_H__
@@ -19,33 +24,57 @@
#include
#include
+/** \addtogroup scheduling_api
+ * @{
+ */
+
+/**
+ * @brief Set private data pointer of an EDF task.
+ * @param[in,out] task Pointer to the target @ref task structure.
+ * @param[in] data Pointer to private context data.
+ * @deprecated See @ref sof/schedule/edf_schedule.h.
+ */
#define edf_sch_set_pdata(task, data) \
(task->priv_data = data)
+/**
+ * @brief Retrieve private data pointer of an EDF task.
+ * @param[in] task Pointer to the target @ref task structure.
+ * @return Pointer to private context data.
+ * @deprecated See @ref sof/schedule/edf_schedule.h.
+ */
#define edf_sch_get_pdata(task) task->priv_data
+/**
+ * @brief Legacy EDF task private data container.
+ * @deprecated Deprecated along with @ref SOF_SCHEDULE_EDF.
+ */
struct edf_task_pdata {
- void *ctx;
+ void *ctx; /**< Task context pointer. */
};
/**
- * @brief Initialize the Earliest Deadline First (EDF) scheduler.
+ * @brief Initialize the Earliest Deadline First (EDF) workqueue scheduler.
+ * @deprecated Deprecated for audio pipelines; retained for host IPC and legacy KPB draining.
* @return 0 on success, negative error code on failure.
*/
int scheduler_init_edf(void);
/**
- * @brief Initialize a task for Earliest Deadline First execution.
- * @param task Pointer to task structure.
- * @param uid UUID identifying the task.
- * @param ops Task operations callbacks.
- * @param data Context pointer.
- * @param core Target DSP core ID.
- * @param flags Scheduling flags.
+ * @brief Initialize a task for Earliest Deadline First (EDF) workqueue execution.
+ * @deprecated Deprecated for audio pipelines; use @ref scheduler_dp_task_init() instead.
+ * @param[out] task Pointer to task structure to initialize.
+ * @param[in] uid UUID identifying the task.
+ * @param[in] ops Task operations callbacks (@ref task_ops).
+ * @param[in] data Context pointer passed to task callbacks.
+ * @param[in] core Target DSP core ID.
+ * @param[in] flags Scheduling flags.
* @return 0 on success, negative error code on failure.
*/
int schedule_task_init_edf(struct task *task, const struct sof_uuid_entry *uid,
const struct task_ops *ops,
void *data, uint16_t core, uint32_t flags);
+/** @}*/
+
#endif /* __SOF_SCHEDULE_EDF_SCHEDULE_H__ */
diff --git a/src/include/sof/schedule/ll_schedule.h b/src/include/sof/schedule/ll_schedule.h
index 5252b46267c8..41e8f9f42558 100644
--- a/src/include/sof/schedule/ll_schedule.h
+++ b/src/include/sof/schedule/ll_schedule.h
@@ -7,8 +7,8 @@
/**
* @file sof/schedule/ll_schedule.h
- * @brief Low-Latency (LL) timer-driven scheduler interface.
- * @ingroup audio_pipeline_api
+ * @brief Low-Latency (LL) timer and DMA-driven deterministic task scheduler interface.
+ * @ingroup scheduling_api
*
* Delayed or scheduled work. Work runs in the same context as its timer
* or DMA interrupt source. It executes deterministically and must not sleep or wait.
@@ -23,40 +23,57 @@
#include
#include
+/** \addtogroup scheduling_api
+ * @{
+ */
+
struct ll_schedule_domain;
/* ll tracing */
extern struct tr_ctx ll_tr;
+/**
+ * @brief Set the private data pointer of a Low-Latency task.
+ * @param[in,out] task Pointer to the target @ref task structure.
+ * @param[in] data Pointer to private context data (e.g. @ref ll_task_pdata).
+ */
#define ll_sch_set_pdata(task, data) \
do { (task)->priv_data = (data); } while (0)
+/**
+ * @brief Retrieve the private data pointer of a Low-Latency task.
+ * @param[in] task Pointer to the target @ref task structure.
+ * @return Pointer to private context data.
+ */
#define ll_sch_get_pdata(task) ((task)->priv_data)
+/**
+ * @brief Low-Latency task private scheduling parameters.
+ */
struct ll_task_pdata {
- uint64_t period;
- uint16_t ratio; /**< ratio of periods compared to the registrable task */
- uint16_t skip_cnt; /**< how many times the task was skipped for execution */
+ uint64_t period; /**< Execution period in microseconds. */
+ uint16_t ratio; /**< Ratio of periods compared to the base registrable task. */
+ uint16_t skip_cnt; /**< Counter tracking how many periods the task was skipped for rate alignment. */
};
+#if !defined(__ZEPHYR__)
/**
* @brief Initialize a Low-Latency scheduler for the specified domain.
- * @param domain Pointer to the Low-Latency schedule domain (timer or DMA).
+ * @param[in,out] domain Pointer to the Low-Latency schedule domain (timer or DMA).
* @return 0 on success, negative error code on failure.
*/
-#if !defined(__ZEPHYR__)
int scheduler_init_ll(struct ll_schedule_domain *domain);
/**
* @brief Initialize a Low-Latency real-time task.
- * @param task Pointer to task structure to initialize.
- * @param uid UUID identifying the task/component.
- * @param type Task type identifier.
- * @param priority Task scheduling priority.
- * @param run Callback function executing the task work.
- * @param data Private context pointer passed to run callback.
- * @param core Core affinity for the task.
- * @param flags Scheduling flags (e.g. dynamic/static).
+ * @param[out] task Pointer to task structure to initialize.
+ * @param[in] uid UUID identifying the task/component.
+ * @param[in] type Task type identifier (SOF_SCHEDULE_LL_TIMER or SOF_SCHEDULE_LL_DMA).
+ * @param[in] priority Task scheduling priority (lower values indicate higher priority).
+ * @param[in] run Callback function executing the task work.
+ * @param[in] data Private context pointer passed to run callback.
+ * @param[in] core Core affinity for the task.
+ * @param[in] flags Scheduling flags (e.g. dynamic/static).
* @return 0 on success, negative error code on failure.
*/
int schedule_task_init_ll(struct task *task,
@@ -66,21 +83,21 @@ int schedule_task_init_ll(struct task *task,
#else
/**
* @brief Initialize the Zephyr Low-Latency scheduler domain.
- * @param domain Pointer to the Low-Latency schedule domain.
+ * @param[in,out] domain Pointer to the Low-Latency schedule domain.
* @return 0 on success, negative error code on failure.
*/
int zephyr_ll_scheduler_init(struct ll_schedule_domain *domain);
/**
* @brief Initialize a Zephyr Low-Latency task.
- * @param task Pointer to task structure.
- * @param uid UUID identifying the task.
- * @param type Task type identifier.
- * @param priority Task priority.
- * @param run Work callback function.
- * @param data Context pointer.
- * @param core Target DSP core ID.
- * @param flags Scheduling flags.
+ * @param[out] task Pointer to task structure.
+ * @param[in] uid UUID identifying the task.
+ * @param[in] type Task type identifier (SOF_SCHEDULE_LL_TIMER or SOF_SCHEDULE_LL_DMA).
+ * @param[in] priority Task priority (lower values indicate higher priority).
+ * @param[in] run Work callback function.
+ * @param[in] data Context pointer.
+ * @param[in] core Target DSP core ID.
+ * @param[in] flags Scheduling flags.
* @return 0 on success, negative error code on failure.
*/
int zephyr_ll_task_init(struct task *task,
@@ -94,12 +111,16 @@ int zephyr_ll_task_init(struct task *task,
#endif
/**
- * \brief Extract information about scheduler's tasks
+ * @brief Extract telemetry information about Low-Latency scheduler tasks.
+ *
+ * Populates @ref scheduler_props with `COMP_PROCESSING_DOMAIN_LL` and active LL tasks.
*
- * \param scheduler_props Structure to be filled
- * \param data_off_size Pointer to the current size of the scheduler_props, to be updated
+ * @param[out] scheduler_props Structure to be filled with LL scheduler properties.
+ * @param[in,out] data_off_size Pointer to the current size of scheduler_props buffer.
*/
void scheduler_get_task_info_ll(struct scheduler_props *scheduler_props,
uint32_t *data_off_size);
+/** @}*/
+
#endif /* __SOF_SCHEDULE_LL_SCHEDULE_H__ */
diff --git a/src/include/sof/schedule/ll_schedule_domain.h b/src/include/sof/schedule/ll_schedule_domain.h
index cfd0043995db..6858929d97b3 100644
--- a/src/include/sof/schedule/ll_schedule_domain.h
+++ b/src/include/sof/schedule/ll_schedule_domain.h
@@ -5,6 +5,12 @@
* Author: Tomasz Lauda
*/
+/**
+ * @file sof/schedule/ll_schedule_domain.h
+ * @brief Low-Latency (LL) scheduling domain architecture, timer/DMA drivers, and core domain operations.
+ * @ingroup scheduling_api
+ */
+
#ifndef __SOF_SCHEDULE_LL_SCHEDULE_DOMAIN_H__
#define __SOF_SCHEDULE_LL_SCHEDULE_DOMAIN_H__
@@ -22,115 +28,262 @@
#include
#include
+/** \addtogroup scheduling_api
+ * @{
+ */
+
#if defined(CONFIG_AMD)
-#define LL_TIMER_PERIOD_US 500ULL /* 500us period for AMD ACP platforms */
+/** @brief Low-Latency timer scheduling period in microseconds (500us for AMD ACP platforms). */
+#define LL_TIMER_PERIOD_US 500ULL
#else
-#define LL_TIMER_PERIOD_US 1000ULL /* default period in microseconds */
+/** @brief Default Low-Latency timer scheduling period in microseconds (1000us / 1ms). */
+#define LL_TIMER_PERIOD_US 1000ULL
#endif
-/* Default ll watchdog timeout in microseconds.
- * It was decided to have a timeout of two periods to give a safe margin of time between the start
- * of the watchdog and its first feeding.
+/**
+ * @brief Default Low-Latency watchdog timeout in microseconds.
+ *
+ * Configured as two periods to provide a safe margin between watchdog start
+ * and initial task feeding.
*/
#define LL_WATCHDOG_TIMEOUT_US (2 * LL_TIMER_PERIOD_US)
-
struct dma;
struct ll_schedule_domain;
struct task;
struct timer;
struct comp_dev;
+/**
+ * @brief Low-Latency schedule domain operations table.
+ *
+ * Implements driver-level primitives for timer and DMA scheduling domains.
+ */
struct ll_schedule_domain_ops {
+ /**
+ * @brief Register a real-time task with the domain.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in,out] task Task being registered.
+ * @param[in] handler Domain tick handler callback.
+ * @param[in,out] arg Context argument passed to tick handler.
+ * @return 0 on success, negative error code on failure.
+ */
int (*domain_register)(struct ll_schedule_domain *domain,
struct task *task,
void (*handler)(void *arg), void *arg);
+
+ /**
+ * @brief Unregister a task from the domain.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in,out] task Task being unregistered.
+ * @param[in] num_tasks Current total task count.
+ * @return 0 on success, negative error code on failure.
+ */
int (*domain_unregister)(struct ll_schedule_domain *domain,
struct task *task, uint32_t num_tasks);
+
#if CONFIG_SOF_USERSPACE_LL
- /*
- * Initialize the scheduling thread and perform all privileged setup
- * (thread creation, timer init, access grants). Called once from
- * kernel context before any user-space domain_register() calls.
+ /**
+ * @brief Initialize the scheduling thread and privileged resources.
+ *
+ * Must be called from kernel context before any user-space tasks register.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in,out] task Task requiring privileged setup.
+ * @return 0 on success, negative error code on failure.
*/
int (*domain_thread_init)(struct ll_schedule_domain *domain,
struct task *task);
- /* Free resources acquired by domain_thread_init(). Called from
- * kernel context when the scheduling context is being torn down.
+
+ /**
+ * @brief Free resources acquired by domain_thread_init().
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in] num_tasks Current total task count.
*/
void (*domain_thread_free)(struct ll_schedule_domain *domain,
uint32_t num_tasks);
#endif
+
+ /**
+ * @brief Enable domain interrupts/triggers on the specified core.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in] core Core index to enable.
+ */
void (*domain_enable)(struct ll_schedule_domain *domain, int core);
+
+ /**
+ * @brief Disable domain interrupts/triggers on the specified core.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in] core Core index to disable.
+ */
void (*domain_disable)(struct ll_schedule_domain *domain, int core);
+
#if CONFIG_CROSS_CORE_STREAM
- /*
- * Unlike domain_disable(), these are intended to temporary block LL from
- * starting its next cycle. Triggering (e.g., by means of timer interrupt)
- * is still enabled and registered but execution of next cycle is blocked.
- * Once unblocked, if triggering were previously registered in a blocked
- * state -- next cycle execution could start immediately.
+ /**
+ * @brief Temporarily block domain execution across cores without disabling interrupt triggers.
+ * @param[in,out] domain Target scheduling domain.
*/
void (*domain_block)(struct ll_schedule_domain *domain);
+
+ /**
+ * @brief Unblock domain execution across cores.
+ * @param[in,out] domain Target scheduling domain.
+ */
void (*domain_unblock)(struct ll_schedule_domain *domain);
#endif
+
+ /**
+ * @brief Set the next tick timestamp for the domain.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in] start Next execution start timestamp in clock ticks.
+ */
void (*domain_set)(struct ll_schedule_domain *domain, uint64_t start);
+
+ /**
+ * @brief Clear scheduled domain interrupt / tick timer.
+ * @param[in,out] domain Target scheduling domain.
+ */
void (*domain_clear)(struct ll_schedule_domain *domain);
+
+ /**
+ * @brief Query whether a task in the domain has pending execution work.
+ * @param[in] domain Target scheduling domain.
+ * @param[in] task Task to check.
+ * @param[out] comp Pointer to associated component device, if any.
+ * @return true if work is pending, false otherwise.
+ */
bool (*domain_is_pending)(struct ll_schedule_domain *domain,
struct task *task, struct comp_dev **comp);
+
+ /**
+ * @brief Notification hook invoked when a task within the domain is cancelled.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in,out] task Task being cancelled.
+ */
void (*domain_task_cancel)(struct ll_schedule_domain *domain, struct task *task);
};
+/**
+ * @brief Low-Latency scheduling domain instance descriptor.
+ */
struct ll_schedule_domain {
- uint64_t next_tick; /**< ticks just set for next run */
- uint64_t new_target_tick; /**< for the next set, used during the reschedule stage */
+ uint64_t next_tick; /**< Ticks just set for next run. */
+ uint64_t new_target_tick; /**< For the next set, used during the reschedule stage. */
#ifdef CONFIG_SOF_USERSPACE_LL
- struct k_mutex *lock; /**< standard lock */
+ struct k_mutex *lock; /**< Domain mutex for user-space access. */
#else
- struct k_spinlock lock; /**< standard lock */
+ struct k_spinlock lock; /**< Standard spinlock. */
#endif
- atomic_t total_num_tasks; /**< total number of registered tasks */
- atomic_t enabled_cores; /**< number of enabled cores */
- uint32_t ticks_per_ms; /**< number of clock ticks per ms */
- int type; /**< domain type */
- int clk; /**< source clock */
- bool synchronous; /**< are tasks should be synchronous */
- bool full_sync; /**< tasks should be full synchronous, no time dependent */
- void *priv_data; /**< pointer to private data */
- bool enabled[CONFIG_CORE_COUNT]; /**< enabled cores */
- const struct ll_schedule_domain_ops *ops; /**< domain ops */
+ atomic_t total_num_tasks; /**< Total number of registered tasks across all cores. */
+ atomic_t enabled_cores; /**< Number of currently enabled cores. */
+ uint32_t ticks_per_ms; /**< Number of clock ticks per millisecond. */
+ int type; /**< Domain type (SOF_SCHEDULE_LL_TIMER or SOF_SCHEDULE_LL_DMA). */
+ int clk; /**< Source clock identifier. */
+ bool synchronous; /**< True if tasks in this domain execute synchronously. */
+ bool full_sync; /**< True if tasks are fully synchronous with no time dependency. */
+ void *priv_data; /**< Pointer to private domain driver data. */
+ bool enabled[CONFIG_CORE_COUNT]; /**< Per-core enablement flags. */
+ const struct ll_schedule_domain_ops *ops; /**< Domain operations table. */
};
+/**
+ * @brief Set the private data pointer of a Low-Latency scheduling domain.
+ * @param[in,out] domain Target domain.
+ * @param[in] data Private context pointer.
+ */
#define ll_sch_domain_set_pdata(domain, data) ((domain)->priv_data = (data))
+/**
+ * @brief Retrieve the private data pointer of a Low-Latency scheduling domain.
+ * @param[in] domain Target domain.
+ * @return Pointer to domain-specific context data.
+ */
#define ll_sch_domain_get_pdata(domain) ((domain)->priv_data)
+/**
+ * @brief Get the primary platform timer scheduling domain.
+ * @return Pointer to global timer scheduling domain.
+ */
static inline struct ll_schedule_domain *timer_domain_get(void)
{
return sof_get()->platform_timer_domain;
}
+/**
+ * @brief Get the primary platform DMA scheduling domain.
+ * @return Pointer to global DMA scheduling domain.
+ */
static inline struct ll_schedule_domain *dma_domain_get(void)
{
return sof_get()->platform_dma_domain;
}
#ifdef CONFIG_SOF_USERSPACE_LL
+/**
+ * @brief Allocate a task structure in the user-space LL heap.
+ * @return Pointer to allocated task, or NULL on failure.
+ */
struct task *zephyr_ll_task_alloc(void);
+
+/**
+ * @brief Get the user-space heap for Low-Latency scheduling structures.
+ * @return Pointer to the k_heap instance.
+ */
struct k_heap *zephyr_ll_user_heap(void);
+
+/**
+ * @brief Verify that a pointer belongs to the user-space LL heap.
+ * @param[in] heap Heap handle to check.
+ * @return true if valid, false otherwise.
+ */
bool zephyr_ll_user_heap_verify(struct k_heap *heap);
+
+/**
+ * @brief Initialize user-space memory partitions and access permissions for LL scheduling.
+ */
void zephyr_ll_user_resources_init(void);
+
+/**
+ * @brief Grant thread access to per-core Low-Latency mutexes.
+ * @param[in,out] thread Target thread.
+ * @param[in] core Target core ID.
+ */
void user_ll_grant_access(struct k_thread *thread, int core);
+
+/**
+ * @brief Acquire per-core user Low-Latency scheduling lock.
+ * @param[in] core Target core ID.
+ */
void user_ll_lock_sched(int core);
+
+/**
+ * @brief Release per-core user Low-Latency scheduling lock.
+ * @param[in] core Target core ID.
+ */
void user_ll_unlock_sched(int core);
+
#ifdef CONFIG_ASSERT
-/* Assert that the calling context already holds the LL lock for 'core'. */
+/**
+ * @brief Assert that the calling context holds the user Low-Latency lock for a core.
+ * @param[in] core Target core ID.
+ */
void user_ll_assert_locked(int core);
#else
static inline void user_ll_assert_locked(int core) { ARG_UNUSED(core); }
#endif
#endif /* CONFIG_SOF_USERSPACE_LL */
+/**
+ * @brief Initialize a Low-Latency scheduling domain descriptor.
+ *
+ * Allocates a @ref ll_schedule_domain on the user or kernel heap, initializes
+ * synchronization locks, resets task and core counters, and computes tick conversion constants.
+ *
+ * @param[in] type Domain type (@ref SOF_SCHEDULE_LL_TIMER or @ref SOF_SCHEDULE_LL_DMA).
+ * @param[in] clk Source clock identifier.
+ * @param[in] synchronous True if domain tasks must run synchronously.
+ * @param[in] ops Domain operations table pointer.
+ * @return Pointer to initialized domain, or NULL on allocation failure.
+ */
static inline struct ll_schedule_domain *domain_init
(int type, int clk, bool synchronous,
const struct ll_schedule_domain_ops *ops)
@@ -178,7 +331,11 @@ static inline struct ll_schedule_domain *domain_init
return domain;
}
-/* configure the next interrupt for domain */
+/**
+ * @brief Configure the next interrupt or tick timestamp for the domain.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in] start Next execution start timestamp in clock ticks.
+ */
static inline void domain_set(struct ll_schedule_domain *domain, uint64_t start)
{
if (domain->ops->domain_set)
@@ -187,7 +344,10 @@ static inline void domain_set(struct ll_schedule_domain *domain, uint64_t start)
domain->next_tick = start;
}
-/* clear the interrupt for domain */
+/**
+ * @brief Clear/disarm the interrupt tick for the domain.
+ * @param[in,out] domain Target scheduling domain.
+ */
static inline void domain_clear(struct ll_schedule_domain *domain)
{
if (domain->ops->domain_clear)
@@ -197,7 +357,11 @@ static inline void domain_clear(struct ll_schedule_domain *domain)
domain->next_tick = UINT64_MAX;
}
-/* let the domain know that a task has been cancelled */
+/**
+ * @brief Notify the domain that a task has been cancelled.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in,out] task Cancelled task pointer.
+ */
static inline void domain_task_cancel(struct ll_schedule_domain *domain,
struct task *task)
{
@@ -206,9 +370,14 @@ static inline void domain_task_cancel(struct ll_schedule_domain *domain,
}
#if CONFIG_SOF_USERSPACE_LL
-/*
- * Initialize the scheduling thread and do all privileged setup.
+/**
+ * @brief Initialize domain scheduling thread and perform privileged resource allocation.
+ *
* Must be called from kernel context before user-space tasks register.
+ *
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in,out] task Task requiring privileged setup.
+ * @return 0 on success, negative error code on failure.
*/
static inline int domain_thread_init(struct ll_schedule_domain *domain,
struct task *task)
@@ -218,9 +387,13 @@ static inline int domain_thread_init(struct ll_schedule_domain *domain,
return domain->ops->domain_thread_init(domain, task);
}
-/*
- * Free resources acquired by domain_thread_init().
+/**
+ * @brief Free resources acquired by domain_thread_init().
+ *
* Must be called from kernel context.
+ *
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in] num_tasks Current task count.
*/
static inline void domain_thread_free(struct ll_schedule_domain *domain,
uint32_t num_tasks)
@@ -230,6 +403,14 @@ static inline void domain_thread_free(struct ll_schedule_domain *domain,
}
#endif
+/**
+ * @brief Register a real-time task with the scheduling domain.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in,out] task Task to register.
+ * @param[in] handler Work handler callback function.
+ * @param[in,out] arg Private context argument passed to handler.
+ * @return 0 on success, negative error code on failure.
+ */
static inline int domain_register(struct ll_schedule_domain *domain,
struct task *task,
void (*handler)(void *arg), void *arg)
@@ -247,6 +428,12 @@ static inline int domain_register(struct ll_schedule_domain *domain,
return ret;
}
+/**
+ * @brief Unregister a real-time task from the scheduling domain.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in,out] task Task to unregister.
+ * @param[in] num_tasks Current total registered task count.
+ */
static inline void domain_unregister(struct ll_schedule_domain *domain,
struct task *task, uint32_t num_tasks)
{
@@ -268,6 +455,11 @@ static inline void domain_unregister(struct ll_schedule_domain *domain,
atomic_add(&domain->total_num_tasks, 1);
}
+/**
+ * @brief Enable Low-Latency scheduling domain execution on the specified core.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in] core Target core ID.
+ */
static inline void domain_enable(struct ll_schedule_domain *domain, int core)
{
if (!domain->enabled[core] && domain->ops->domain_enable) {
@@ -277,6 +469,11 @@ static inline void domain_enable(struct ll_schedule_domain *domain, int core)
}
}
+/**
+ * @brief Disable Low-Latency scheduling domain execution on the specified core.
+ * @param[in,out] domain Target scheduling domain.
+ * @param[in] core Target core ID.
+ */
static inline void domain_disable(struct ll_schedule_domain *domain, int core)
{
if (domain->enabled[core] && domain->ops->domain_disable) {
@@ -287,12 +484,20 @@ static inline void domain_disable(struct ll_schedule_domain *domain, int core)
}
#if CONFIG_CROSS_CORE_STREAM
+/**
+ * @brief Temporarily block domain tick processing across cores without disabling interrupt triggers.
+ * @param[in,out] domain Target scheduling domain.
+ */
static inline void domain_block(struct ll_schedule_domain *domain)
{
if (domain->ops->domain_block)
domain->ops->domain_block(domain);
}
+/**
+ * @brief Resume domain tick processing across cores.
+ * @param[in,out] domain Target scheduling domain.
+ */
static inline void domain_unblock(struct ll_schedule_domain *domain)
{
if (domain->ops->domain_unblock)
@@ -300,6 +505,13 @@ static inline void domain_unblock(struct ll_schedule_domain *domain)
}
#endif
+/**
+ * @brief Query whether a task in the domain has pending execution work.
+ * @param[in] domain Target scheduling domain.
+ * @param[in] task Task to inspect.
+ * @param[out] comp Pointer to associated component device pointer, if any.
+ * @return true if work is pending, false otherwise.
+ */
static inline bool domain_is_pending(struct ll_schedule_domain *domain,
struct task *task, struct comp_dev **comp)
{
@@ -314,26 +526,85 @@ static inline bool domain_is_pending(struct ll_schedule_domain *domain,
#ifndef __ZEPHYR__
+/**
+ * @brief Initialize timer-driven Low-Latency scheduling domain for non-Zephyr platforms.
+ * @param[in,out] timer Hardware timer device pointer.
+ * @param[in] clk Source clock identifier.
+ * @return Pointer to initialized scheduling domain.
+ */
struct ll_schedule_domain *timer_domain_init(struct timer *timer, int clk);
#else
#if CONFIG_DMA_DOMAIN
#define dma_multi_chan_domain_init(dma_array, num_dma, clk, aggregated_irq)\
zephyr_dma_domain_init(dma_array, num_dma, clk)
+/**
+ * @brief Initialize DMA interrupt-driven Low-Latency scheduling domain on Zephyr.
+ * @param[in] dma_array Array of DMA controllers tied to the domain.
+ * @param[in] num_dma Number of DMA controllers in the array.
+ * @param[in] clk Clock source identifier.
+ * @return Pointer to initialized scheduling domain, or NULL on error.
+ */
struct ll_schedule_domain *zephyr_dma_domain_init(struct dma *dma_array,
uint32_t num_dma,
int clk);
#endif /* CONFIG_DMA_DOMAIN */
+
+/**
+ * @brief Retrieve the global Low-Latency timer scheduling domain descriptor on Zephyr.
+ * @return Pointer to active domain descriptor.
+ */
struct ll_schedule_domain *zephyr_ll_domain(void);
+
+/**
+ * @brief Initialize the primary timer-driven Low-Latency scheduling domain on Zephyr.
+ * @param[in] clk Clock source identifier.
+ * @return Pointer to initialized scheduling domain, or NULL on failure.
+ */
struct ll_schedule_domain *zephyr_domain_init(int clk);
+
#define timer_domain_init(timer, clk) zephyr_domain_init(clk)
+
#ifdef CONFIG_SOF_USERSPACE_LL
+/**
+ * @brief Retrieve the Zephyr domain thread TID for the domain on the current core.
+ * @param[in] domain Target scheduling domain.
+ * @return Pointer to k_thread instance.
+ */
struct k_thread *zephyr_domain_thread_tid(struct ll_schedule_domain *domain);
+
+/**
+ * @brief Retrieve the Zephyr domain thread TID for the domain on a specific core.
+ * @param[in] core Target core ID.
+ * @return Pointer to k_thread instance.
+ */
struct k_thread *zephyr_domain_thread_tid_for_core(int core);
+
+/**
+ * @brief Retrieve the user-space LL memory domain.
+ * @return Pointer to k_mem_domain.
+ */
struct k_mem_domain *zephyr_ll_mem_domain(void);
+
+/**
+ * @brief Retrieve the Zephyr LL thread handle for the calling core.
+ * @return Pointer to k_thread instance.
+ */
struct k_thread *zephyr_ll_domain_thread(void);
#endif /* CONFIG_SOF_USERSPACE_LL */
+
#ifdef CONFIG_SOF_FULL_ZEPHYR_APPLICATION
+/**
+ * @brief Allocate a completion semaphore for a Low-Latency task.
+ * @param[in,out] task Target task.
+ * @return 0 on success, negative error code on failure.
+ */
__syscall int zephyr_ll_task_sem_alloc(struct task *task);
+
+/**
+ * @brief Free a completion semaphore for a Low-Latency task.
+ * @param[in,out] task Target task.
+ * @return 0 on success, negative error code on failure.
+ */
__syscall int zephyr_ll_task_sem_free(struct task *task);
#include
#else
@@ -344,12 +615,29 @@ int z_impl_zephyr_ll_task_sem_free(struct task *task);
#endif /* CONFIG_SOF_FULL_ZEPHYR_APPLICATION */
#endif /* __ZEPHYR__ */
+/**
+ * @brief Initialize multi-channel DMA scheduling domain.
+ * @param[in] dma_array Array of DMA controllers.
+ * @param[in] num_dma Number of DMA controllers.
+ * @param[in] clk Clock source identifier.
+ * @param[in] aggregated_irq True if IRQs from channels are aggregated into a single line.
+ * @return Pointer to initialized scheduling domain.
+ */
struct ll_schedule_domain *dma_multi_chan_domain_init(struct dma *dma_array,
uint32_t num_dma, int clk,
bool aggregated_irq);
+/**
+ * @brief Initialize single-channel DMA scheduling domain.
+ * @param[in] dma_array Array of DMA controllers.
+ * @param[in] num_dma Number of DMA controllers.
+ * @param[in] clk Clock source identifier.
+ * @return Pointer to initialized scheduling domain.
+ */
struct ll_schedule_domain *dma_single_chan_domain_init(struct dma *dma_array,
uint32_t num_dma,
int clk);
+/** @}*/
+
#endif /* __SOF_SCHEDULE_LL_SCHEDULE_DOMAIN_H__ */
diff --git a/src/include/sof/schedule/schedule.h b/src/include/sof/schedule/schedule.h
index 56dbbdc83a94..f5f646cfbc50 100644
--- a/src/include/sof/schedule/schedule.h
+++ b/src/include/sof/schedule/schedule.h
@@ -5,7 +5,12 @@
* Author: Bartosz Kokoszko
*/
-/* Generic schedule api header */
+/**
+ * @file sof/schedule/schedule.h
+ * @brief Generic scheduler interface, scheduler operations, and task management.
+ * @ingroup scheduling_api
+ */
+
#ifndef __SOF_SCHEDULE_SCHEDULE_H__
#define __SOF_SCHEDULE_SCHEDULE_H__
@@ -19,51 +24,74 @@
#include
#include
-/** \addtogroup audio_pipeline_api
+/** \addtogroup scheduling_api
* @{
*/
-/** \brief Type of scheduler, comes from topology. */
enum {
- SOF_SCHEDULE_EDF = 0, /**< EDF, schedules based on task's deadline */
- SOF_SCHEDULE_LL_TIMER, /**< Low latency timer, schedules immediately
- * on selected timer's tick
- */
- SOF_SCHEDULE_LL_DMA, /**< Low latency DMA, schedules immediately
- * on scheduling component's DMA interrupt
- */
- SOF_SCHEDULE_DP, /**< DataProcessing scheduler
- * Scheduler based on Zephyr peemptive threads
- * TODO: DP will become the Zephyr EDF scheduler type
- * and will be unified with SOF_SCHEDULE_EDF for Zephyr builds
- * current implementation of Zephyr based EDF is depreciated now
- */
- SOF_SCHEDULE_TWB, /**< Tasks With Budget scheduler based on Zephyr peemptive threads
- * for each SOF task that has pre-allocated MCPS budget
- * renewed with every system tick.
- */
- SOF_SCHEDULE_COUNT /**< indicates number of scheduler types */
+ /**
+ * @brief Earliest Deadline First (EDF) scheduler.
+ * @deprecated Deprecated for modern audio pipeline processing. In Zephyr-based builds,
+ * EDF is implemented as a delayed workqueue (edf_workq) retained for
+ * host IPC processing and legacy KPB draining tasks until migration.
+ * Audio pipeline components should use @ref SOF_SCHEDULE_DP for preemptible
+ * deadline-driven tasks or @ref SOF_SCHEDULE_LL_TIMER / @ref SOF_SCHEDULE_LL_DMA
+ * for hard real-time tasks.
+ */
+ SOF_SCHEDULE_EDF = 0,
+ /**
+ * @brief Low Latency timer domain scheduler.
+ *
+ * Executes tasks immediately upon expiration of the primary hardware timer tick.
+ */
+ SOF_SCHEDULE_LL_TIMER,
+ /**
+ * @brief Low Latency DMA interrupt domain scheduler.
+ *
+ * Executes tasks immediately upon scheduling component's DMA transfer completion interrupt.
+ */
+ SOF_SCHEDULE_LL_DMA,
+ /**
+ * @brief Data Processing (DP) worker thread scheduler.
+ *
+ * Preemptible Zephyr worker thread per SOF task. Evaluates task readiness
+ * after each Low-Latency (LL) tick, setting absolute deadlines in Zephyr EDF.
+ */
+ SOF_SCHEDULE_DP,
+ /**
+ * @brief Tasks With Budget (TWB) scheduler.
+ *
+ * Preemptible Zephyr thread per SOF task with a pre-allocated cycle budget
+ * renewed every system tick. Drops thread priority on budget exhaustion to
+ * prevent system starvation.
+ */
+ SOF_SCHEDULE_TWB,
+ /**
+ * @brief Indicates total number of scheduler types.
+ */
+ SOF_SCHEDULE_COUNT
};
-/** \brief Scheduler free available flags */
-#define SOF_SCHEDULER_FREE_IRQ_ONLY BIT(0) /**< Free function disables only
- * interrupts
- */
+/** @brief Scheduler free available flags. */
+#define SOF_SCHEDULER_FREE_IRQ_ONLY BIT(0) /**< Free function disables interrupts only, keeping data structures intact. */
+
/**
- * Scheduler operations.
+ * @brief Scheduler operations interface table.
*
- * Almost all schedule operations must return 0 for success and negative values
- * for errors. Only the scheduler_free operation is allowed to not return any
- * status.
+ * Schedulers implement this interface to plug into the unified SOF scheduling abstraction.
+ * Almost all schedule operations must return 0 for success and negative values for errors.
+ * Only the optional scheduler_free operation returns void.
*/
struct scheduler_ops {
/**
- * Schedules task with given scheduling parameters.
- * @param data Private data of selected scheduler.
- * @param task Task to be scheduled.
- * @param start Start time of given task (in microseconds).
- * @param period Scheduling period of given task (in microseconds).
- * @return 0 if succeeded, error code otherwise.
+ * @brief Schedule a task with the given timing parameters.
+ * @param[in,out] data Private state of the selected scheduler.
+ * @param[in,out] task Task descriptor to be scheduled.
+ * @param[in] start Start timing parameter (scheduler-specific, e.g. start delay or absolute tick for LL).
+ * @param[in] period Repetition period in microseconds for periodic schedulers (such as LL, where 0 denotes
+ * one-shot). Schedulers such as DP and TWB ignore this parameter as rescheduling is
+ * governed by the task's returned execution state.
+ * @return 0 on success, negative error code on failure.
*
* This operation is mandatory.
*/
@@ -71,13 +99,13 @@ struct scheduler_ops {
uint64_t period);
/**
- * Schedules task with given scheduling parameters.
- * @param data Private data of selected scheduler.
- * @param task Task to be scheduled.
- * @param start Start time of given task (in microseconds).
- * @param period Scheduling period of given task (in microseconds).
- * @param before Task to be scheduled before
- * @return 0 if succeeded, error code otherwise.
+ * @brief Schedule a task to execute before a specified reference task.
+ * @param[in,out] data Private state of the selected scheduler.
+ * @param[in,out] task Task descriptor to be scheduled.
+ * @param[in] start Start timing parameter (scheduler-specific).
+ * @param[in] period Repetition period in microseconds (scheduler-specific).
+ * @param[in] before Reference task before which this task must be enqueued.
+ * @return 0 on success, negative error code on failure.
*
* This operation is optional.
*/
@@ -85,13 +113,13 @@ struct scheduler_ops {
uint64_t period, struct task *before);
/**
- * Schedules task with given scheduling parameters.
- * @param data Private data of selected scheduler.
- * @param task Task to be scheduled.
- * @param start Start time of given task (in microseconds).
- * @param period Scheduling period of given task (in microseconds).
- * @param after Task to be scheduled after
- * @return 0 if succeeded, error code otherwise.
+ * @brief Schedule a task to execute after a specified reference task.
+ * @param[in,out] data Private state of the selected scheduler.
+ * @param[in,out] task Task descriptor to be scheduled.
+ * @param[in] start Start timing parameter (scheduler-specific).
+ * @param[in] period Repetition period in microseconds (scheduler-specific).
+ * @param[in] after Reference task after which this task must be enqueued.
+ * @return 0 on success, negative error code on failure.
*
* This operation is optional.
*/
@@ -99,42 +127,41 @@ struct scheduler_ops {
uint64_t period, struct task *after);
/**
- * Sets task into running state along with executing additional
- * scheduler specific operations.
- * @param data Private data of selected scheduler.
- * @param task Task to be set into running state.
- * @return 0 if succeeded, error code otherwise.
+ * @brief Transition a task to running state and perform scheduler-specific execution hooks.
+ * @param[in,out] data Private state of the selected scheduler.
+ * @param[in,out] task Task transitioning to running state.
+ * @return 0 on success, negative error code on failure.
*
* This operation is optional.
*/
int (*schedule_task_running)(void *data, struct task *task);
/**
- * Reschedules already scheduled task with new start time.
- * @param data Private data of selected scheduler.
- * @param task Task to be rescheduled.
- * @param start New start time of given task (in microseconds).
- * @return 0 if succeeded, error code otherwise.
+ * @brief Reschedule an already scheduled task with an updated start delay.
+ * @param[in,out] data Private state of the selected scheduler.
+ * @param[in,out] task Task descriptor to reschedule.
+ * @param[in] start New start delay in microseconds.
+ * @return 0 on success, negative error code on failure.
*
* This operation is optional.
*/
int (*reschedule_task)(void *data, struct task *task, uint64_t start);
/**
- * Cancels previously scheduled task.
- * @param data Private data of selected scheduler.
- * @param task Task to be canceled.
- * @return 0 if succeeded, error code otherwise.
+ * @brief Cancel a previously scheduled task.
+ * @param[in,out] data Private state of the selected scheduler.
+ * @param[in,out] task Task descriptor to cancel.
+ * @return 0 on success, negative error code on failure.
*
* This operation is mandatory.
*/
int (*schedule_task_cancel)(void *data, struct task *task);
/**
- * Frees task's resources.
- * @param data Private data of selected scheduler.
- * @param task Task to be freed.
- * @return 0 if succeeded, error code otherwise.
+ * @brief Free scheduler resources associated with a task.
+ * @param[in,out] data Private state of the selected scheduler.
+ * @param[in,out] task Task descriptor whose resources are to be freed.
+ * @return 0 on success, negative error code on failure.
*
* This operation is mandatory.
*/
@@ -142,63 +169,76 @@ struct scheduler_ops {
#if CONFIG_SOF_BOOT_TEST_STANDALONE || CONFIG_LIBRARY
/**
- * Frees scheduler's resources.
- * @param data Private data of selected scheduler.
- * @param flags Function specific flags.
- * @return 0 if succeeded, error code otherwise.
+ * @brief Free the scheduler instance and release its underlying resources.
+ * @param[in,out] data Private state of the selected scheduler.
+ * @param[in] flags Scheduler-specific free flags (e.g. @ref SOF_SCHEDULER_FREE_IRQ_ONLY).
*
- * This operation is optional.
+ * This operation is optional (used only in standalone testing and library testbench).
*/
void (*scheduler_free)(void *data, uint32_t flags);
#endif
/**
- * Initializes context
- * @param data Private data of selected scheduler.
- * @param task task that needs to be scheduled
- * @return thread that will be used to run the scheduled task
+ * @brief Initialize execution thread context for a scheduled task.
+ * @param[in,out] data Private state of the selected scheduler.
+ * @param[in,out] task Task requiring dedicated execution context.
+ * @return Pointer to allocated Zephyr thread object, or NULL on error or unsupported.
*
* This operation is optional.
*/
struct k_thread *(*scheduler_init_context)(void *data, struct task *task);
};
-/** \brief Holds information about scheduler. */
+/**
+ * @brief Descriptor container representing a registered scheduler instance.
+ */
struct schedule_data {
- struct list_item list; /**< list of schedulers */
- int type; /**< SOF_SCHEDULE_ type */
- const struct scheduler_ops *ops; /**< scheduler operations */
- void *data; /**< pointer to private data */
+ struct list_item list; /**< List node linking this scheduler into the per-core schedulers list. */
+ int type; /**< Scheduler type identifier (SOF_SCHEDULE_*). */
+ const struct scheduler_ops *ops; /**< Pointer to scheduler operations table. */
+ void *data; /**< Pointer to scheduler-specific private context data. */
};
-/** \brief Holds list of all registered schedulers. */
+/**
+ * @brief Container holding the linked list of all registered schedulers on a core.
+ */
struct schedulers {
- struct list_item list; /**< list of schedulers */
+ struct list_item list; /**< Head of the linked list of registered schedulers. */
};
/**
- * Retrieves registered schedulers.
- * @return List of registered schedulers.
+ * @brief Retrieve the array of registered kernel-space schedulers for the current core.
+ *
+ * Must only be called from privileged/kernel context (!k_is_user_context()).
+ *
+ * @return Pointer to the per-core schedulers list head pointer.
*/
struct schedulers **arch_schedulers_get(void);
/**
- * @brief Retrieves registered schedulers for user-space threads on the current core.
- * @return Pointer to array of registered scheduler pointers.
+ * @brief Retrieve registered schedulers for user-space threads on the current core.
+ *
+ * Invokes cpu_get_id(), so this function must only be called from kernel context.
+ * User-space callers should use @ref arch_user_schedulers_get_for_core instead.
+ *
+ * @return Pointer to the per-core user schedulers list head pointer, or NULL if user LL is disabled.
*/
struct schedulers **arch_user_schedulers_get(void);
/**
- * @brief Retrieves registered schedulers for user-space threads on a specific core.
- * @param core Target DSP core ID.
- * @return Pointer to array of registered scheduler pointers for the specified core.
+ * @brief Retrieve registered schedulers for user-space threads on a specific core.
+ *
+ * Safe to invoke from user-space contexts because the target core ID is explicitly provided.
+ *
+ * @param[in] core Target DSP core ID.
+ * @return Pointer to the user schedulers list head pointer for the specified core, or NULL if disabled.
*/
struct schedulers **arch_user_schedulers_get_for_core(int core);
/**
- * @brief Lookup scheduler private context data by scheduler type.
- * @param schedulers Schedulers list container.
- * @param type Scheduler type identifier (SOF_SCHEDULE_LL, SOF_SCHEDULE_EDF, etc.).
+ * @brief Lookup scheduler private context data by scheduler type from a schedulers container.
+ * @param[in] schedulers Schedulers list container.
+ * @param[in] type Scheduler type identifier (SOF_SCHEDULE_*).
* @return Pointer to scheduler-specific private data, or NULL if not found.
*/
static inline void *scheduler_list_get_data(struct schedulers *schedulers, uint16_t type)
@@ -219,9 +259,9 @@ static inline void *scheduler_list_get_data(struct schedulers *schedulers, uint1
}
/**
- * Retrieves scheduler's data.
- * @param type SOF_SCHEDULE_ type.
- * @return Pointer to scheduler's data.
+ * @brief Retrieve private data of a registered kernel scheduler on the current core.
+ * @param[in] type Scheduler type (SOF_SCHEDULE_*).
+ * @return Pointer to scheduler private data, or NULL if not found.
*/
static inline void *scheduler_get_data(uint16_t type)
{
@@ -229,16 +269,20 @@ static inline void *scheduler_get_data(uint16_t type)
}
/**
- * Retrieves userspace scheduler's data.
- * @param type SOF_SCHEDULE_ type.
- * @return Pointer to scheduler's data.
+ * @brief Retrieve private data of a registered user-space scheduler on the current core.
+ * @param[in] type Scheduler type (SOF_SCHEDULE_*).
+ * @return Pointer to scheduler private data, or NULL if not found.
*/
static inline void *scheduler_get_user_data(uint16_t type)
{
return scheduler_list_get_data(*arch_user_schedulers_get(), type);
}
-/** See scheduler_ops::schedule_task_running */
+/**
+ * @brief Notify the scheduler that a task is transitioning to the running state.
+ * @param[in,out] task Task being set to running.
+ * @return 0 on success, or negative error code from scheduler ops.
+ */
static inline int schedule_task_running(struct task *task)
{
struct schedule_data *sch;
@@ -252,7 +296,13 @@ static inline int schedule_task_running(struct task *task)
return sch->ops->schedule_task_running(sch->data, task);
}
-/** See scheduler_ops::schedule_task */
+/**
+ * @brief Schedule a task for execution with start delay and period.
+ * @param[in,out] task Task to schedule.
+ * @param[in] start Start delay in microseconds from now.
+ * @param[in] period Repetition period in microseconds (0 for one-shot execution).
+ * @return 0 on success, -EINVAL if task is NULL, or negative error code from scheduler ops.
+ */
static inline int schedule_task(struct task *task, uint64_t start,
uint64_t period)
{
@@ -266,7 +316,19 @@ static inline int schedule_task(struct task *task, uint64_t start,
return sch->ops->schedule_task(sch->data, task, start, period);
}
-/** See scheduler_ops::schedule_task_before */
+/**
+ * @brief Schedule a task to execute before a specified reference task.
+ *
+ * @note Relative task ordering is optional and scheduler-specific. If the underlying
+ * scheduler does not implement schedule_task_before, this wrapper falls back to
+ * ordinary schedule_task() and ignores @p before.
+ *
+ * @param[in,out] task Task to schedule.
+ * @param[in] start Start timing parameter (scheduler-specific).
+ * @param[in] period Repetition period in microseconds (scheduler-specific).
+ * @param[in] before Reference task before which this task must run.
+ * @return 0 on success, -EINVAL if arguments are invalid, or negative error code from scheduler ops.
+ */
static inline int schedule_task_before(struct task *task, uint64_t start,
uint64_t period, struct task *before)
{
@@ -284,7 +346,19 @@ static inline int schedule_task_before(struct task *task, uint64_t start,
return sch->ops->schedule_task(sch->data, task, start, period);
}
-/** See scheduler_ops::schedule_task_after */
+/**
+ * @brief Schedule a task to execute after a specified reference task.
+ *
+ * @note Relative task ordering is optional and scheduler-specific. If the underlying
+ * scheduler does not implement schedule_task_after, this wrapper falls back to
+ * ordinary schedule_task() and ignores @p after.
+ *
+ * @param[in,out] task Task to schedule.
+ * @param[in] start Start timing parameter (scheduler-specific).
+ * @param[in] period Repetition period in microseconds (scheduler-specific).
+ * @param[in] after Reference task after which this task must run.
+ * @return 0 on success, -EINVAL if arguments are invalid, or negative error code from scheduler ops.
+ */
static inline int schedule_task_after(struct task *task, uint64_t start,
uint64_t period, struct task *after)
{
@@ -302,7 +376,12 @@ static inline int schedule_task_after(struct task *task, uint64_t start,
return sch->ops->schedule_task(sch->data, task, start, period);
}
-/** See scheduler_ops::reschedule_task */
+/**
+ * @brief Reschedule an already scheduled task with an updated start time.
+ * @param[in,out] task Task to reschedule.
+ * @param[in] start New start delay in microseconds.
+ * @return 0 on success, or negative error code from scheduler ops.
+ */
static inline int reschedule_task(struct task *task, uint64_t start)
{
struct schedule_data *sch;
@@ -317,7 +396,11 @@ static inline int reschedule_task(struct task *task, uint64_t start)
return sch->ops->reschedule_task(sch->data, task, start);
}
-/** See scheduler_ops::schedule_task_cancel */
+/**
+ * @brief Cancel a scheduled or queued task.
+ * @param[in,out] task Task to cancel.
+ * @return 0 on success, -EINVAL if task or bound scheduler is NULL, or negative error code from scheduler ops.
+ */
static inline int schedule_task_cancel(struct task *task)
{
struct schedule_data *sch;
@@ -330,7 +413,11 @@ static inline int schedule_task_cancel(struct task *task)
return sch->ops->schedule_task_cancel(sch->data, task);
}
-/** See scheduler_ops::schedule_task_free */
+/**
+ * @brief Free scheduler resources associated with a task.
+ * @param[in,out] task Task whose resources should be freed.
+ * @return 0 on success, -EINVAL if task or bound scheduler is NULL, or negative error code from scheduler ops.
+ */
static inline int schedule_task_free(struct task *task)
{
struct schedule_data *sch;
@@ -345,7 +432,10 @@ static inline int schedule_task_free(struct task *task)
/* Only used in a stand-alone test and in a testbench test */
#if CONFIG_SOF_BOOT_TEST_STANDALONE || CONFIG_LIBRARY
-/** See scheduler_ops::scheduler_free */
+/**
+ * @brief Free all registered schedulers and their resources (testing/library only).
+ * @param[in] flags Scheduler-specific free flags (e.g. @ref SOF_SCHEDULER_FREE_IRQ_ONLY).
+ */
static inline void schedule_free(uint32_t flags)
{
struct schedulers *schedulers = *arch_schedulers_get();
@@ -360,7 +450,11 @@ static inline void schedule_free(uint32_t flags)
}
#endif
-/** See scheduler_ops::scheduler_init_context */
+/**
+ * @brief Initialize thread execution context for a task.
+ * @param[in,out] task Task requiring execution context initialization.
+ * @return Pointer to allocated Zephyr thread, or NULL if unsupported or failed.
+ */
static inline struct k_thread *scheduler_init_context(struct task *task)
{
struct schedule_data *sch;
@@ -375,16 +469,23 @@ static inline struct k_thread *scheduler_init_context(struct task *task)
}
/**
- * Initializes scheduling task.
- * @param task Task to be initialized.
- * @param uid Statically assigned task uuid.
- * @param type SOF_SCHEDULE_ type.
- * @param priority Task's priority.
- * @param run Pointer to task's execution function.
- * @param data Pointer to task's execution data.
- * @param core Core on which task should be run.
- * @param flags Special scheduling flags.
- * @return 0 if succeeded, error code otherwise.
+ * @brief Initialize a scheduling task and bind it to the registered scheduler for its type and core.
+ *
+ * Validates scheduler type and searches registered schedulers. User schedulers look up the
+ * target core via arch_user_schedulers_get_for_core(core), whereas kernel schedulers look up
+ * via arch_schedulers_get() on the calling core. Therefore, kernel task initialization must
+ * execute directly on the target core. Initializes task properties, priority, execution callback,
+ * and sets task state to @ref SOF_TASK_STATE_INIT.
+ *
+ * @param[out] task Task structure to initialize.
+ * @param[in] uid Statically assigned task UUID entry.
+ * @param[in] type Scheduler type (SOF_SCHEDULE_*).
+ * @param[in] priority Task scheduling priority (lower values indicate higher priority).
+ * @param[in] run Execution callback function returning @ref task_state.
+ * @param[in] data Private context pointer passed to run callback.
+ * @param[in] core DSP core ID on which the task should execute.
+ * @param[in] flags Task-specific scheduling flags.
+ * @return 0 on success, -EINVAL if type >= SOF_SCHEDULE_COUNT, -ENODEV if scheduler cannot be found.
*/
int schedule_task_init(struct task *task,
const struct sof_uuid_entry *uid, uint16_t type,
@@ -392,18 +493,26 @@ int schedule_task_init(struct task *task,
void *data, uint16_t core, uint32_t flags);
/**
- * Initializes scheduler
- * @param type SOF_SCHEDULE_ type.
- * @param ops Pointer to scheduler's operations.
- * @param data Scheduler's private data.
+ * @brief Register a scheduler type instance with its operations table and private context data.
+ *
+ * Allocates a @ref schedule_data container on the system (or user) heap, links it into
+ * the active core scheduler list, and associates the provided operations.
+ *
+ * @param[in] type Scheduler type identifier (SOF_SCHEDULE_*).
+ * @param[in] ops Pointer to scheduler operations table (must provide schedule_task, schedule_task_cancel, schedule_task_free).
+ * @param[in] data Pointer to scheduler private instance data.
*/
void scheduler_init(int type, const struct scheduler_ops *ops, void *data);
/**
- * Extract scheduler's task information from tasks
- * @param scheduler_props Structure to be filled
- * @param data_off_size Pointer to the current size of the scheduler_props, to be updated
- * @param tasks Scheduler's task list
+ * @brief Extract scheduler task telemetry and properties for IPC4 base firmware.
+ *
+ * Populates @ref scheduler_props with the calling core ID and total task count,
+ * appending @ref task_props structures for each active task in the list.
+ *
+ * @param[out] scheduler_props Properties structure to be filled.
+ * @param[in,out] data_off_size Pointer to running byte size of scheduler_props buffer.
+ * @param[in] tasks Linked list of tasks to inspect.
*/
void scheduler_get_task_info(struct scheduler_props *scheduler_props,
uint32_t *data_off_size, struct list_item *tasks);
diff --git a/src/include/sof/schedule/twb_schedule.h b/src/include/sof/schedule/twb_schedule.h
index be7c06d0706f..586c880123ff 100644
--- a/src/include/sof/schedule/twb_schedule.h
+++ b/src/include/sof/schedule/twb_schedule.h
@@ -5,78 +5,85 @@
* Author: Adrian Bonislawski
*/
+/**
+ * @file sof/schedule/twb_schedule.h
+ * @brief Thread With Budget (TWB) scheduler interface and cycle accounting.
+ * @ingroup scheduling_api
+ *
+ * The Thread With Budget (TWB) scheduler creates a separate preemptible Zephyr thread
+ * for each SOF task that has a pre-allocated MCPS budget renewed with every system tick.
+ *
+ * ### Key Architectural Properties
+ * - **Dynamic Priority Switching**: The TWB scheduler assigns either `MEDIUM_PRIORITY` or
+ * `LOW_PRIORITY` to the task thread based on the budget remaining in the current system tick.
+ * - **Opportunistic Execution**: If there is no higher-priority ready task, the thread can continue
+ * executing at low priority even after its budget is exhausted.
+ * - **Cycle & Tick Accounting**:
+ * - `cycles_granted`: Budget in Zephyr system clock ticks per period (passed to `k_thread_time_slice_set()`).
+ * - `cycles_consumed`: Actual execution time consumed during the current period, measured in DSP hardware clock cycles.
+ * - **Budget Exhaustion & Replenishment**:
+ * - When consumed cycles exceed granted cycles, Zephyr time slicing triggers `scheduler_twb_task_cb()`,
+ * which lowers thread priority to `CONFIG_TWB_THREAD_LOW_PRIORITY`.
+ * - On the next Low-Latency tick (`scheduler_twb_ll_tick()`), consumed cycles are reset to 0,
+ * and the original thread priority is restored. Unused budget is not carried over.
+ */
+
#ifndef __SOF_SCHEDULE_TWB_SCHEDULE_H__
#define __SOF_SCHEDULE_TWB_SCHEDULE_H__
#include
#include
-/**
- * @brief Task With Budget (TWB) Scheduler
- *
- * TWB scheduler is a scheduler that creates a separate preemptible Zephyr thread
- * for each SOF task that has a pre-allocated MCPS budget renewed with every system tick.
- * The TWB scheduler assigns either MEDIUM_PRIORITY or LOW_PRIORITY to the task thread
- * based on the budget left in the current system tick.
- * It allows for opportunistic execution if there is no other ready task
- * with a higher priority while the budget is already spent.
- *
- * Examples of tasks with budget include IPC Task and IDC Task.
- *
- * The TWB scheduler has two key parameters assigned:
- * - cycles granted: the budget per system tick
- * - cycles consumed: the number of cycles consumed in a given system tick for task execution
- *
- * The number of cycles consumed is reset to 0 at the beginning of each system tick,
- * renewing the TWB budget.
- * When the number of cycles consumed exceeds the cycles granted,
- * the task is switchedfrom MEDIUM to LOW priority.
- * When the task with budget thread is created, the MPP Scheduling is responsible
- * for setting the thread time slice equal to the task budget, along with
- * setting a callback on time slice timeout.
- * Thread time slicing guarantees that the Zephyr scheduler will interrupt execution
- * when the budget is spent,
- * so the MPP Scheduling timeout callback can re-evaluate the task priority.
- *
- * If there is a budget left in some system tick
- * (i.e., the task spent less time or started executing closeto the system tick
- * that preempts execution), it is reset and not carried over to the next tick.
- *
- * More info:
- * https://thesofproject.github.io/latest/architectures/firmware/sof-zephyr/mpp_layer/mpp_scheduling.html
+/** \addtogroup scheduling_api
+ * @{
*/
/**
- * \brief default static stack size for each TWB thread
+ * @brief Default static stack size in bytes for each TWB worker thread.
*/
#define ZEPHYR_TWB_STACK_SIZE 8192
/**
- * \brief max budget limit
+ * @brief Maximum budget limit in system clock ticks per period.
*/
#define ZEPHYR_TWB_BUDGET_MAX (CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000)
+/**
+ * @brief Convert Zephyr system clock ticks to DSP hardware clock cycles.
+ * @param[in] x System ticks.
+ */
#define SYS_TICKS_TO_HW_CYCLES(x) (x * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC)
+
+/**
+ * @brief Convert DSP hardware clock cycles to Zephyr system clock ticks.
+ * @param[in] x Hardware cycles.
+ */
#define HW_CYCLES_TO_SYS_TICKS(x) (x * CONFIG_SYS_CLOCK_TICKS_PER_SEC / CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC)
/**
- * \brief Init the Tasks with Budget scheduler
+ * @brief Initialize the Thread With Budget (TWB) scheduler on the calling core.
+ *
+ * Allocates per-core TWB scheduler state and binds its driving LL tick source task.
+ *
+ * @return 0 on success, negative error code (-ENOMEM) on failure.
*/
int scheduler_twb_init(void);
/**
- * \brief initialize a TWB task and add it to scheduling
- * It must be called on core the task is declared to run on
+ * @brief Initialize a TWB task with a dedicated Zephyr worker thread and cycle budget.
*
- * \param[out] task pointer, pointer to allocated task structure will be return
- * \param[in] uid pointer to UUID of the task
- * \param[in] ops pointer to task functions
- * \param[in] data pointer to the task data
- * \param[in] core CPU the thread should run on
- * \param[in] name zephyr thread name
- * \param[in] stack_size size of stack for a zephyr thread
- * \param[in] thread_priority priority of the zephyr thread
- * \param[in] cycles_granted cycles budget for the zephyr thread
+ * Must be invoked on the same core that the task is configured to execute on.
+ *
+ * @param[out] task Pointer to store the allocated @ref task structure.
+ * @param[in] uid UUID identifying the task.
+ * @param[in] ops Task operations callbacks (@ref task_ops).
+ * @param[in] data Private context pointer passed to task callbacks.
+ * @param[in] core DSP core affinity for the worker thread.
+ * @param[in] name Debug name assigned to the Zephyr thread.
+ * @param[in] stack_size Stack byte size for the worker thread.
+ * @param[in] thread_priority Default preemptible thread priority (must be >= 0).
+ * @param[in] cycles_granted Budget in Zephyr system clock ticks per period (0 or >= ZEPHYR_TWB_BUDGET_MAX for unlimited).
+ * @return 0 on success, negative error code (-EINVAL, -ENOMEM, -EFAULT) on failure.
*/
int scheduler_twb_task_init(struct task **task,
const struct sof_uuid_entry *uid,
@@ -88,4 +95,6 @@ int scheduler_twb_task_init(struct task **task,
int32_t thread_priority,
uint32_t cycles_granted);
+/** @}*/
+
#endif /* __SOF_SCHEDULE_TWB_SCHEDULE_H__ */
diff --git a/src/platform/library/include/platform/lib/ll_schedule.h b/src/platform/library/include/platform/lib/ll_schedule.h
index b5ba7f94da6a..0a5a2cf9d70a 100644
--- a/src/platform/library/include/platform/lib/ll_schedule.h
+++ b/src/platform/library/include/platform/lib/ll_schedule.h
@@ -3,6 +3,12 @@
* Copyright(c) 2016 Intel Corporation. All rights reserved.
*/
+/**
+ * @file platform/lib/ll_schedule.h
+ * @brief Platform library / testbench Low-Latency scheduler mock declarations.
+ * @ingroup scheduling_api
+ */
+
#ifndef __LIBRARY_INCLUDE_LIB_SCHEDULE_H__
#define __LIBRARY_INCLUDE_LIB_SCHEDULE_H__
@@ -13,10 +19,30 @@ struct task;
struct sof_uuid_entry;
struct ll_schedule_domain;
+/**
+ * @brief Run one iteration of all active Low-Latency tasks (library testbench harness).
+ */
void schedule_ll_run_tasks(void);
+/**
+ * @brief Initialize Low-Latency scheduler on library/testbench platform.
+ * @param[in,out] domain Low-Latency scheduling domain.
+ * @return 0 on success, negative error code on failure.
+ */
int scheduler_init_ll(struct ll_schedule_domain *domain);
+/**
+ * @brief Initialize a Low-Latency task descriptor for library/testbench execution.
+ * @param[out] task Task structure to initialize.
+ * @param[in] uid UUID identifying the task or associated component.
+ * @param[in] type Scheduler type identifier (SOF_SCHEDULE_LL_TIMER or SOF_SCHEDULE_LL_DMA).
+ * @param[in] priority Scheduling priority level (lower values run first).
+ * @param[in] run Main execution callback function.
+ * @param[in] data Context pointer passed to run callback.
+ * @param[in] core Target DSP core ID.
+ * @param[in] flags Task-specific scheduling flags.
+ * @return 0 on success, negative error code on failure.
+ */
int schedule_task_init_ll(struct task *task,
const struct sof_uuid_entry *uid, uint16_t type,
int16_t priority, enum task_state (*run)(void *data),
diff --git a/src/schedule/zephyr_dp_schedule.h b/src/schedule/zephyr_dp_schedule.h
index d33e6895507c..07d8ee4a4754 100644
--- a/src/schedule/zephyr_dp_schedule.h
+++ b/src/schedule/zephyr_dp_schedule.h
@@ -5,6 +5,12 @@
* Author: Marcin Szkudlinski
*/
+/**
+ * @file src/schedule/zephyr_dp_schedule.h
+ * @brief Internal Data Processing (DP) scheduler structures, memory partitions, and thread helpers.
+ * @ingroup scheduling_api
+ */
+
#include
#include
#include
@@ -15,46 +21,84 @@
#include
#include
+/**
+ * @brief Per-core Data Processing (DP) scheduler private state.
+ */
struct scheduler_dp_data {
- struct list_item tasks; /* list of active dp tasks */
- struct task ll_tick_src; /* LL task - source of DP tick */
- uint32_t last_ll_tick_timestamp;/* a timestamp as k_cycle_get_32 of last LL tick,
- * "NOW" for DP deadline calculation
- */
+ struct list_item tasks; /**< Head of the linked list of active DP tasks. */
+ struct task ll_tick_src; /**< Low-Latency driver task generating periodic DP tick notifications. */
+ uint32_t last_ll_tick_timestamp; /**< Timestamp (via k_cycle_get_32()) of last LL tick, defining "NOW" for DP deadline calculation. */
};
+/**
+ * @brief User-space memory partition types for isolated DP module execution.
+ */
enum sof_dp_part_type {
- SOF_DP_PART_HEAP,
- SOF_DP_PART_HEAP_CACHE,
- SOF_DP_PART_CFG,
- SOF_DP_PART_CFG_CACHE,
- SOF_DP_PART_TYPE_COUNT,
+ SOF_DP_PART_HEAP, /**< Heap memory partition for dynamic allocations. */
+ SOF_DP_PART_HEAP_CACHE, /**< Cached heap memory partition. */
+ SOF_DP_PART_CFG, /**< Module configuration and parameters memory partition. */
+ SOF_DP_PART_CFG_CACHE, /**< Cached module configuration partition. */
+ SOF_DP_PART_TYPE_COUNT, /**< Total number of DP partition types. */
};
struct ipc4_flat;
+/**
+ * @brief Private data container associated with a Data Processing (DP) task.
+ */
struct task_dp_pdata {
- k_tid_t thread_id; /* zephyr thread ID */
- struct k_thread *thread; /* pointer to the kernels' thread object */
- struct k_thread thread_struct; /* thread object for kernel threads */
- uint32_t deadline_clock_ticks; /* dp module deadline in Zephyr ticks */
- k_thread_stack_t *p_stack; /* pointer to thread stack */
- struct processing_module *mod; /* the module to be scheduled */
- uint32_t ll_cycles_to_start; /* current number of LL cycles till delayed start */
+ k_tid_t thread_id; /**< Zephyr thread identifier for the worker thread. */
+ struct k_thread *thread; /**< Pointer to the Zephyr kernel thread object. */
+ struct k_thread thread_struct; /**< Embedded thread control block for kernel-mode worker threads. */
+ uint32_t deadline_clock_ticks; /**< Processing module deadline in Zephyr system clock ticks. */
+ k_thread_stack_t *p_stack; /**< Pointer to dedicated stack memory allocated for the thread. */
+ struct processing_module *mod; /**< Processing module descriptor bound to this scheduling task. */
+ uint32_t ll_cycles_to_start; /**< Current count of LL cycles remaining until delayed start. */
#if CONFIG_SOF_USERSPACE_APPLICATION
- uint8_t *ipc_config_data;
- struct ipc4_flat *flat;
- struct k_mem_partition mpart[SOF_DP_PART_TYPE_COUNT];
+ uint8_t *ipc_config_data; /**< Staged IPC configuration buffer for user-space module. */
+ struct ipc4_flat *flat; /**< Flat IPC4 container for user-space parameter passing. */
+ struct k_mem_partition mpart[SOF_DP_PART_TYPE_COUNT]; /**< Memory partitions assigned to the user thread. */
#endif
- struct k_event *event; /* pointer to event for task scheduling */
- struct k_event event_struct; /* event for task scheduling for kernel threads */
+ struct k_event *event; /**< Pointer to Zephyr event object signaling work availability. */
+ struct k_event event_struct; /**< Embedded event object for kernel-mode worker threads. */
#if IS_ENABLED(CONFIG_SOF_USERSPACE_MOD_IPC_BY_DP_THREAD)
- struct k_work_user *ipc_work_item; /* work item for IPC handling */
+ struct k_work_user *ipc_work_item; /**< User work item for dispatching asynchronous module IPC commands. */
#endif
};
+/**
+ * @brief Recalculate deadlines and evaluate readiness for all active DP tasks on an LL tick.
+ * @param[in,out] dp_sch Pointer to per-core DP scheduler state container.
+ */
void scheduler_dp_recalculate(struct scheduler_dp_data *dp_sch);
+
+/**
+ * @brief Worker thread entry point function for Data Processing tasks.
+ *
+ * Runs an infinite event loop waiting on `pdata->event` for process, IPC, or cancel signals.
+ *
+ * @param[in] p1 Pointer to the bound @ref task structure.
+ * @param[in] p2 Unused parameter (NULL).
+ * @param[in] p3 Unused parameter (NULL).
+ */
void dp_thread_fn(void *p1, void *p2, void *p3);
+
+/**
+ * @brief Acquire the per-core Data Processing scheduler synchronization lock.
+ * @param[in] core DSP core ID whose lock should be acquired.
+ * @return Lock key (core ID) to be passed to @ref scheduler_dp_unlock.
+ */
unsigned int scheduler_dp_lock(uint16_t core);
+
+/**
+ * @brief Release the per-core Data Processing scheduler synchronization lock.
+ * @param[in] key Lock key returned by @ref scheduler_dp_lock.
+ */
void scheduler_dp_unlock(unsigned int key);
+
+/**
+ * @brief Grant user-space DP worker thread access to core synchronization primitives and events.
+ * @param[in] thread_id Target Zephyr thread ID.
+ * @param[in] core Target DSP core ID.
+ */
void scheduler_dp_grant(k_tid_t thread_id, uint16_t core);
diff --git a/zephyr/include/rtos/alloc.h b/zephyr/include/rtos/alloc.h
index a146aa0ead92..6b2d89b05b6d 100644
--- a/zephyr/include/rtos/alloc.h
+++ b/zephyr/include/rtos/alloc.h
@@ -6,7 +6,7 @@
/**
* @file rtos/alloc.h
* @brief Memory allocation API, zones, heaps, and alignment utilities.
- * @ingroup rtos_api
+ * @ingroup memory_api
*/
#ifndef __ZEPHYR_RTOS_ALLOC_H__
@@ -21,7 +21,7 @@
#include
#include
-/** \addtogroup rtos_api
+/** \addtogroup memory_api
* @{
*/
@@ -35,59 +35,114 @@
* @{
*/
- /** \brief Allocate DMA-able memory. */
+/** \brief Allocate memory accessible by DMA controllers (e.g. Host or DSP DMA). */
#define SOF_MEM_FLAG_DMA BIT(2)
-/** \brief realloc() skips copying the original content. */
+/**
+ * \brief realloc() skips copying the original content.
+ * @deprecated Legacy realloc optimization flag. rbrealloc() and rbrealloc_align()
+ * have been removed from the allocation API.
+ */
#define SOF_MEM_FLAG_NO_COPY BIT(3)
-/** \brief Allocate uncached address. */
+/**
+ * \brief Allocate uncached / coherent memory address.
+ *
+ * Directs the allocator to return an uncached pointer (e.g. bypassing cache alias
+ * or mapping uncached). Mandatory for DMA descriptors, mailboxes, and cross-core
+ * shared variables. Not supported for L3 memory.
+ */
#define SOF_MEM_FLAG_COHERENT BIT(4)
-/** \brief Allocate L3 address. */
+/**
+ * \brief Allocate from L3 address space (IMR / external DRAM heap).
+ *
+ * Allocates from the L3 heap (l3_heap). Only cached allocations are supported;
+ * requesting coherent L3 memory will fail and return NULL.
+ */
#define SOF_MEM_FLAG_L3 BIT(5)
-/** \brief Allocate Low power memory address. */
+/**
+ * \brief Allocate Low power memory address.
+ * @deprecated Legacy flag from XTOS memory partitions; no-op in modern Zephyr heap manager.
+ */
#define SOF_MEM_FLAG_LOW_POWER BIT(6)
-/** \brief Allocate kernel memory address. */
+/** \brief Base allocation flag denoting memory allocated for kernel-space data structures. */
#define SOF_MEM_FLAG_KERNEL BIT(7)
-/** \brief Allocate user memory address. */
+/** \brief Base allocation flag denoting memory allocated for user-space threads and module execution. */
#define SOF_MEM_FLAG_USER BIT(8)
-/** \brief Allocate shared user memory address. */
+/** \brief Allocate from shared user memory heap (shared_buffer_heap) accessible across user/kernel domains. */
#define SOF_MEM_FLAG_USER_SHARED_BUFFER BIT(9)
-/** \brief Use allocation method for large buffers. */
+/** \brief Route allocation to the Virtual Memory Heap (VMH / virtual_buffers_heap) for large stream buffers. */
#define SOF_MEM_FLAG_LARGE_BUFFER BIT(10)
/** @} */
/**
- * Allocates memory block.
- * @param flags Flags, see SOF_MEM_FLAG_....
- * @param bytes Size in bytes.
- * @param alignment Alignment in bytes.
- * @return Pointer to the allocated memory or NULL if failed.
+ * @brief Allocate memory block with explicit alignment and heap selection flags.
*
+ * Core RTOS memory allocator. Evaluates @p flags to select the appropriate heap:
+ * - #SOF_MEM_FLAG_L3: Allocates from the L3 IMR / external DRAM heap (cached only).
+ * - #SOF_MEM_FLAG_USER_SHARED_BUFFER: Allocates from shared_buffer_heap.
+ * - Default: Allocates from system heap (sof_heap).
+ *
+ * If #SOF_MEM_FLAG_COHERENT is specified, returns an uncached (coherent) pointer.
+ * Otherwise, returns a cached pointer. When CONFIG_VIRTUAL_HEAP is enabled and
+ * system heap allocation fails, transparently attempts fallback allocation from
+ * the Virtual Memory Heap (VMH).
+ *
+ * @param[in] flags Memory allocation flags, see SOF_MEM_FLAG_...
+ * @param[in] bytes Size in bytes to allocate.
+ * @param[in] alignment Required alignment in bytes (0 for default/natural alignment).
+ * @return Pointer to the allocated memory block, or NULL on allocation failure.
*/
void *rmalloc_align(uint32_t flags, size_t bytes, uint32_t alignment);
/**
- * Similar to rmalloc_align(), but no alignment can be specified.
+ * @brief Allocate memory block with default natural alignment.
+ *
+ * Convenience wrapper calling rmalloc_align() with alignment set to 0.
+ *
+ * @param[in] flags Memory allocation flags, see SOF_MEM_FLAG_...
+ * @param[in] bytes Size in bytes to allocate.
+ * @return Pointer to the allocated memory block, or NULL on allocation failure.
*/
void *rmalloc(uint32_t flags, size_t bytes);
/**
- * Similar to rmalloc(), guarantees that returned block is zeroed.
+ * @brief Allocate zero-initialized memory block with default natural alignment.
+ *
+ * Allocates memory via rmalloc() and, if successful, zeroes the entire block
+ * with memset() before returning.
+ *
+ * @param[in] flags Memory allocation flags, see SOF_MEM_FLAG_...
+ * @param[in] bytes Size in bytes to allocate.
+ * @return Pointer to zero-initialized memory block, or NULL on allocation failure.
*/
void *rzalloc(uint32_t flags, size_t bytes);
/**
- * Allocates memory block.
- * @param flags Flags, see SOF_MEM_FLAG_...
- * @param bytes Size in bytes.
- * @param alignment Alignment in bytes.
- * @return Pointer to the allocated memory or NULL if failed.
+ * @brief Allocate runtime stream buffer with explicit alignment.
+ *
+ * Runtime buffer allocator designed for audio stream buffers. Unlike rmalloc_align(),
+ * rballoc_align() actively prioritizes the Virtual Memory Heap (VMH / virtual_buffers_heap)
+ * when CONFIG_VIRTUAL_HEAP is enabled to preserve internal SRAM. Supports
+ * #SOF_MEM_FLAG_L3 and #SOF_MEM_FLAG_USER_SHARED_BUFFER. Respects
+ * #SOF_MEM_FLAG_COHERENT for system and shared heaps, but note that the L3 heap
+ * path returns cached memory directly and does not support coherent uncached views.
+ *
+ * @param[in] flags Memory allocation flags, see SOF_MEM_FLAG_...
+ * @param[in] bytes Size in bytes to allocate.
+ * @param[in] alignment Required alignment in bytes.
+ * @return Pointer to allocated buffer, or NULL on allocation failure.
*/
void *rballoc_align(uint32_t flags, size_t bytes,
uint32_t alignment);
/**
- * Similar to rballoc_align(), returns buffer aligned to PLATFORM_DCACHE_ALIGN.
+ * @brief Allocate runtime stream buffer aligned to platform data cache line size.
+ *
+ * Helper calling rballoc_align() with alignment set to PLATFORM_DCACHE_ALIGN.
+ *
+ * @param[in] flags Memory allocation flags, see SOF_MEM_FLAG_...
+ * @param[in] bytes Size in bytes to allocate.
+ * @return Pointer to allocated buffer aligned to cache line, or NULL on failure.
*/
static inline void *rballoc(uint32_t flags, size_t bytes)
{
@@ -95,22 +150,31 @@ static inline void *rballoc(uint32_t flags, size_t bytes)
}
/**
- * Frees the memory block.
- * @param ptr Pointer to the memory block.
+ * @brief Free memory block allocated by SOF RTOS allocators.
+ *
+ * Unified memory deallocator. Automatically determines the origin heap
+ * (L3 heap, Virtual Memory Heap, shared buffer heap, or system heap) using
+ * address boundary checks and returns memory to the respective pool.
+ * Passing a NULL pointer is safely treated as a no-op.
+ *
+ * @param[in,out] ptr Pointer to the memory block to free (can be NULL).
*/
void rfree(void *ptr);
/**
- * Save L3 heap over DSP reset
+ * @brief Save and flush L3 heap state and metadata across DSP reset or power gating.
+ *
+ * Flushes dirty cache lines for the L3 heap region and copies metadata into
+ * preserved storage to ensure data persistence across low-power reset cycles.
*/
void l3_heap_save(void);
/**
* @brief Allocate memory from a specified Zephyr heap or default system heap.
- * @param heap Target Zephyr k_heap (or NULL to let implementation choose).
- * @param flags Memory allocation flags (SOF_MEM_FLAG_...).
- * @param bytes Size in bytes to allocate.
- * @param alignment Required memory alignment in bytes.
+ * @param[in,out] heap Target Zephyr k_heap (or NULL to let implementation choose).
+ * @param[in] flags Memory allocation flags (SOF_MEM_FLAG_...).
+ * @param[in] bytes Size in bytes to allocate.
+ * @param[in] alignment Required memory alignment in bytes.
* @return Pointer to allocated buffer, or NULL on allocation failure.
*/
#ifdef CONFIG_SOF_USERSPACE_INTERFACE_ALLOC
@@ -118,25 +182,20 @@ __syscall void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes
size_t alignment);
/**
* @brief Free memory allocated via sof_heap_alloc().
- * @param heap Target Zephyr k_heap.
- * @param addr Address of allocated buffer to free.
+ * @param[in,out] heap Target Zephyr k_heap.
+ * @param[in,out] addr Address of allocated buffer to free.
*/
__syscall void sof_heap_free(struct k_heap *heap, void *addr);
#include
#else
void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes,
size_t alignment);
-/**
- * @brief Free memory allocated via sof_heap_alloc().
- * @param heap Target Zephyr k_heap.
- * @param addr Address of allocated buffer to free.
- */
void sof_heap_free(struct k_heap *heap, void *addr);
#endif
/**
* @brief Get the system kernel heap descriptor.
- * @return Pointer to the global system k_heap structure.
+ * @return Pointer to the global system k_heap structure (sof_heap), or NULL in unit test mode.
*/
#if CONFIG_SOF_FULL_ZEPHYR_APPLICATION
struct k_heap *sof_sys_heap_get(void);
@@ -149,41 +208,36 @@ static inline struct k_heap *sof_sys_heap_get(void)
#endif
/**
- * Returns heap object to use for SOF heap allocations
- * for audio application code.
+ * @brief Get the heap object to use for audio application allocations.
*
- * The returned value may be NULL. This matches with semantics
- * of sof_heap_alloc() that allows passing NULL as the 'heap'.
- * In this case, the heap implementation will choose the heap to
- * use.
+ * Returns zephyr_ll_user_heap() when CONFIG_SOF_USERSPACE_LL is enabled,
+ * or NULL to allow sof_heap_alloc() to pick the default heap.
*
- * The function should not be used for heap allocations for objects that
- * are only used in SOF kernel space.
+ * @note Audio processing modules should use mod_alloc() instead.
*
- * Note: audio modules should use mod_alloc() instead!
+ * @return Pointer to application k_heap, or NULL for default heap selection.
*/
struct k_heap *sof_sys_user_heap_get(void);
/**
* @brief Trace and log memory allocation statistics across all active heaps.
- * @param force Force dumping heap trace even if logging threshold is not met.
+ * @deprecated No-op stub. Heap diagnostics are tracked via Zephyr runtime
+ * statistics (CONFIG_SYS_HEAP_RUNTIME_STATS), IPC4 telemetry,
+ * and VMH diagnostics (vmh_log_stats()).
+ * @param[in] force Force dumping heap trace even if logging threshold is not met.
*/
static inline void heap_trace_all(int force) {}
-/** @}*/
-
#if CONFIG_SOF_USERSPACE_USE_SHARED_HEAP
/**
- * Returns the start address of shared memory heap for buffers.
- *
- * @return pointer to shared memory heap start
+ * @brief Returns the start address of shared memory heap for buffers.
+ * @return Pointer address to shared memory heap start.
*/
uintptr_t get_shared_buffer_heap_start(void);
/**
- * Returns the size of shared memory heap for buffers.
- *
- * @return size of shared memory heap start
+ * @brief Returns the total size of shared memory heap for buffers.
+ * @return Total size of shared memory heap in bytes.
*/
size_t get_shared_buffer_heap_size(void);
@@ -191,23 +245,27 @@ size_t get_shared_buffer_heap_size(void);
#include
+/**
+ * @brief Module and pipeline allocation context aggregating a Zephyr heap and optional virtual region.
+ */
struct mod_alloc_ctx {
- struct k_heap *heap;
- struct vregion *vreg;
+ struct k_heap *heap; /**< Underlying Zephyr heap descriptor. */
+ struct vregion *vreg; /**< Optional virtual region for interim/lifetime partitioning. */
};
/**
- * Allocate memory from a mod_alloc_ctx context.
+ * @brief Allocate memory from an allocation context.
*
- * When the context has a vregion, allocates from the vregion interim
- * partition. Coherent memory is used when SOF_MEM_FLAG_COHERENT is set
- * in flags. Falls back to sof_heap_alloc() otherwise.
+ * When the context has an associated vregion, allocates from the vregion interim
+ * partition using vregion_alloc_coherent_align() (if #SOF_MEM_FLAG_COHERENT is set)
+ * or vregion_alloc_align(). When no vregion is attached, falls back to
+ * sof_heap_alloc().
*
- * @param ctx Allocation context (heap + optional vregion).
- * @param flags Allocation flags (SOF_MEM_FLAG_*).
- * @param size Size in bytes.
- * @param alignment Required alignment in bytes.
- * @return Pointer to allocated memory or NULL on failure.
+ * @param[in,out] ctx Allocation context (heap + optional vregion).
+ * @param[in] flags Allocation flags (SOF_MEM_FLAG_*).
+ * @param[in] size Size in bytes to allocate.
+ * @param[in] alignment Required alignment in bytes.
+ * @return Pointer to allocated memory, or NULL on failure.
*/
static inline void *sof_ctx_alloc(struct mod_alloc_ctx *ctx, uint32_t flags,
size_t size, size_t alignment)
@@ -222,12 +280,15 @@ static inline void *sof_ctx_alloc(struct mod_alloc_ctx *ctx, uint32_t flags,
}
/**
- * Allocate zero-initialized memory from a mod_alloc_ctx context.
- * @param ctx Allocation context.
- * @param flags Allocation flags (SOF_MEM_FLAG_*).
- * @param size Size in bytes.
- * @param alignment Required alignment in bytes.
- * @return Pointer to allocated memory or NULL on failure.
+ * @brief Allocate zero-initialized memory from an allocation context.
+ *
+ * Allocates memory via sof_ctx_alloc() and clears it with memset() if successful.
+ *
+ * @param[in,out] ctx Allocation context.
+ * @param[in] flags Allocation flags (SOF_MEM_FLAG_*).
+ * @param[in] size Size in bytes to allocate.
+ * @param[in] alignment Required alignment in bytes.
+ * @return Pointer to zero-initialized allocated memory, or NULL on failure.
*/
static inline void *sof_ctx_zalloc(struct mod_alloc_ctx *ctx, uint32_t flags,
size_t size, size_t alignment)
@@ -241,9 +302,13 @@ static inline void *sof_ctx_zalloc(struct mod_alloc_ctx *ctx, uint32_t flags,
}
/**
- * Free memory allocated from a mod_alloc_ctx context.
- * @param ctx Allocation context.
- * @param ptr Pointer to free.
+ * @brief Free memory allocated from an allocation context.
+ *
+ * If the context contains a vregion, frees via vregion_free(); otherwise delegates
+ * to sof_heap_free(). Passing a NULL pointer is safely treated as a no-op.
+ *
+ * @param[in,out] ctx Allocation context.
+ * @param[in,out] ptr Pointer to memory to free (can be NULL).
*/
static inline void sof_ctx_free(struct mod_alloc_ctx *ctx, void *ptr)
{
@@ -256,4 +321,6 @@ static inline void sof_ctx_free(struct mod_alloc_ctx *ctx, void *ptr)
sof_heap_free(ctx ? ctx->heap : NULL, ptr);
}
+/** @}*/
+
#endif /* __ZEPHYR_RTOS_ALLOC_H__ */
diff --git a/zephyr/include/rtos/task.h b/zephyr/include/rtos/task.h
index 82fedcfff9fa..199f3e552156 100644
--- a/zephyr/include/rtos/task.h
+++ b/zephyr/include/rtos/task.h
@@ -5,6 +5,12 @@
* Author: Liam Girdwood
*/
+/**
+ * @file rtos/task.h
+ * @brief Core task descriptor, task operations, and task execution state machine.
+ * @ingroup scheduling_api rtos_api
+ */
+
#ifndef __ZEPHYR_RTOS_TASK_H__
#define __ZEPHYR_RTOS_TASK_H__
@@ -15,66 +21,90 @@
#include
#include
+/** \addtogroup scheduling_api
+ * @{
+ */
+
struct comp_dev;
struct sof;
struct schedule_data;
-/** \brief Predefined LL task priorities. */
-#define SOF_TASK_PRI_HIGH 0 /* priority level 0 - high */
-#define SOF_TASK_PRI_MED 4 /* priority level 4 - medium */
-#define SOF_TASK_PRI_LOW 9 /* priority level 9 - low */
+/** @brief Predefined Low-Latency task priority levels. */
+#define SOF_TASK_PRI_HIGH 0 /**< Priority level 0 - high (hard real-time). */
+#define SOF_TASK_PRI_MED 4 /**< Priority level 4 - medium. */
+#define SOF_TASK_PRI_LOW 9 /**< Priority level 9 - low (background/idle). */
-/** \brief Predefined EDF task deadlines. */
-#define SOF_TASK_DEADLINE_IDLE UINT64_MAX
-#define SOF_TASK_DEADLINE_ALMOST_IDLE (SOF_TASK_DEADLINE_IDLE - 1)
-#define SOF_TASK_DEADLINE_NOW 0
+/** @brief Predefined EDF task deadlines. */
+#define SOF_TASK_DEADLINE_IDLE UINT64_MAX /**< Idle deadline; run only when nothing else is ready. */
+#define SOF_TASK_DEADLINE_ALMOST_IDLE (SOF_TASK_DEADLINE_IDLE - 1) /**< Almost idle deadline. */
+#define SOF_TASK_DEADLINE_NOW 0 /**< Immediate deadline; run as soon as possible. */
-/** \brief Task counter initial value. */
+/** @brief Task counter initial value. */
#define SOF_TASK_SKIP_COUNT 0xFFFFu
-/** \brief Task states. */
+/**
+ * @brief Lifecycle and execution states of an SOF task.
+ */
enum task_state {
+ /** @brief Task allocated and initialized, not yet scheduled. */
SOF_TASK_STATE_INIT = 0,
+ /** @brief Task queued in scheduler run list awaiting tick or trigger. */
SOF_TASK_STATE_QUEUED,
+ /** @brief Task waiting for preconditions, audio data, or buffer space. */
SOF_TASK_STATE_PENDING,
+ /** @brief Task actively executing in thread or timer/DMA handler. */
SOF_TASK_STATE_RUNNING,
+ /** @brief Task preempted by higher priority thread or ISR. */
SOF_TASK_STATE_PREEMPTED,
+ /** @brief Task execution finished; removed from active scheduling. */
SOF_TASK_STATE_COMPLETED,
+ /** @brief Task resources released. */
SOF_TASK_STATE_FREE,
+ /** @brief Task cancelled, pending removal from scheduler. */
SOF_TASK_STATE_CANCEL,
+ /** @brief Return code from run callback requesting rescheduling in next period. */
SOF_TASK_STATE_RESCHEDULE,
};
-/** \brief Task operations. */
+/**
+ * @brief Operations and callbacks associated with a scheduling task.
+ */
struct task_ops {
- enum task_state (*run)(void *data); /**< task's main operation */
- void (*complete)(void *data); /**< executed on completion */
- uint64_t (*get_deadline)(void *data); /**< returns current deadline */
+ enum task_state (*run)(void *data); /**< Task's main execution callback function. */
+ void (*complete)(void *data); /**< Optional callback executed on task completion. */
+ uint64_t (*get_deadline)(void *data); /**< Optional callback returning current task deadline timestamp. */
};
-/** \brief Task used by schedulers. */
+/**
+ * @brief Core task structure managed by SOF schedulers.
+ */
struct task {
- uint64_t start; /**< start time in [ms] since now (LL only) */
- const struct sof_uuid_entry *uid; /**< Uuid */
- uint16_t type; /**< type of the task (LL or EDF) */
- int16_t priority; /**< priority of the task (used by LL); lower runs first */
- uint16_t core; /**< execution core */
- uint16_t flags; /**< custom flags */
- struct schedule_data *sch; /**< scheduler bound to task */
- enum task_state state; /**< current state */
- void *data; /**< custom data passed to all ops */
- struct list_item list; /**< used by schedulers to hold tasks */
- void *priv_data; /**< task private data */
- struct task_ops ops; /**< task operations */
- struct k_work_delayable z_delayed_work;
- uint32_t cycles_sum;
- uint32_t cycles_max;
- uint32_t cycles_cnt;
+ uint64_t start; /**< Scheduler/domain-specific start state (e.g. absolute next-run tick timestamp in LL). */
+ const struct sof_uuid_entry *uid; /**< UUID identifying the task or associated component. */
+ uint16_t type; /**< Scheduler type identifier (SOF_SCHEDULE_*). */
+ int16_t priority; /**< Priority of the task (lower values run first). */
+ uint16_t core; /**< Execution core ID affinity. */
+ uint16_t flags; /**< Custom task flags. */
+ struct schedule_data *sch; /**< Pointer to scheduler instance bound to this task. */
+ enum task_state state; /**< Current task lifecycle state. */
+ void *data; /**< Custom context pointer passed to task operations. */
+ struct list_item list; /**< List node linking task into scheduler run queue. */
+ void *priv_data; /**< Scheduler-specific private task context. */
+ struct task_ops ops; /**< Task operations callbacks table. */
+ struct k_work_delayable z_delayed_work; /**< Zephyr delayable work item (used by legacy EDF). */
+ uint32_t cycles_sum; /**< Cumulative execution cycles. */
+ uint32_t cycles_max; /**< Maximum cycle count recorded in a single run. */
+ uint32_t cycles_cnt; /**< Number of completed execution runs. */
#if CONFIG_PERFORMANCE_COUNTERS
- struct perf_cnt_data pcd;
+ struct perf_cnt_data pcd; /**< Performance counter telemetry data. */
#endif
};
+/**
+ * @brief Check whether a task is active (queued, running, pending, or rescheduling).
+ * @param[in] task Task to check.
+ * @return true if task is in an active execution state, false otherwise.
+ */
static inline bool task_is_active(struct task *task)
{
switch (task->state) {
@@ -89,6 +119,11 @@ static inline bool task_is_active(struct task *task)
}
}
+/**
+ * @brief Execute a task's run callback.
+ * @param[in,out] task Task to execute.
+ * @return Resulting task state returned by the run callback.
+ */
static inline enum task_state task_run(struct task *task)
{
assert(task->ops.run);
@@ -96,12 +131,21 @@ static inline enum task_state task_run(struct task *task)
return task->ops.run(task->data);
}
+/**
+ * @brief Execute a task's complete callback, if registered.
+ * @param[in,out] task Task whose completion callback should be invoked.
+ */
static inline void task_complete(struct task *task)
{
if (task->ops.complete)
task->ops.complete(task->data);
}
+/**
+ * @brief Retrieve a task's deadline timestamp.
+ * @param[in] task Task to query.
+ * @return Current deadline timestamp.
+ */
static inline uint64_t task_get_deadline(struct task *task)
{
assert(task->ops.get_deadline);
@@ -109,7 +153,19 @@ static inline uint64_t task_get_deadline(struct task *task)
return task->ops.get_deadline(task->data);
}
+/**
+ * @brief Start the main SOF background task.
+ * @param[in,out] sof Global SOF context pointer.
+ * @return 0 on success, negative error code on failure.
+ */
int task_main_start(struct sof *sof);
+
+/**
+ * @brief Signal completion of system startup.
+ * @return 0 on success, negative error code on failure.
+ */
int start_complete(void);
+/** @}*/
+
#endif /* __ZEPHYR_RTOS_TASK_H__ */
diff --git a/zephyr/include/sof/lib/memory.h b/zephyr/include/sof/lib/memory.h
index 2b5a225b7067..09bbaa0de627 100644
--- a/zephyr/include/sof/lib/memory.h
+++ b/zephyr/include/sof/lib/memory.h
@@ -3,16 +3,35 @@
* Copyright(c) 2024 Intel Corporation.
*/
+/**
+ * @file sof/lib/memory.h
+ * @brief Memory attributes, cold/hot execution paths, and platform memory inclusions.
+ * @ingroup memory_api
+ */
+
#ifndef __SOF_LIB_MEMORY_H__
#define __SOF_LIB_MEMORY_H__
#include
#include
+/** \addtogroup memory_api
+ * @{
+ */
+
+/**
+ * @brief Attribute marking non-latency-critical code for placement in cold memory sections.
+ *
+ * Cold code (e.g. initialization, IPC setup, or offload modules) may be placed in
+ * DRAM / L3 memory or powered-down banks to conserve high-speed internal SRAM.
+ */
#ifndef __cold
#define __cold
#endif
+/**
+ * @brief Attribute marking read-only constants for placement in cold memory sections.
+ */
#ifndef __cold_rodata
#define __cold_rodata
#endif
@@ -26,11 +45,31 @@ bool ll_sch_is_current(void);
#if CONFIG_COLD_STORE_EXECUTE_DEBUG
#include
+/**
+ * @brief Start monitoring hot execution paths for cold storage violations.
+ */
void dbg_path_hot_start_watching(void);
+
+/**
+ * @brief Stop monitoring hot execution paths.
+ */
void dbg_path_hot_stop_watching(void);
+
+/**
+ * @brief Confirm that execution remained on expected hot paths.
+ */
void dbg_path_hot_confirm(void);
+
+/**
+ * @brief Record entry into a cold execution function.
+ * @param[in] fn Calling function name.
+ */
void dbg_path_cold_enter(const char *fn);
+/**
+ * @brief Internal assertion validating that a function can safely execute on cold storage.
+ * @param[in] fn Calling function name.
+ */
static inline void __assert_can_be_cold(const char *fn)
{
if (k_is_user_context())
@@ -39,13 +78,22 @@ static inline void __assert_can_be_cold(const char *fn)
__ASSERT(!ll_sch_is_current(), "%s() called from an LL thread!", fn);
dbg_path_cold_enter(fn);
}
+
+/**
+ * @brief Assert that the current function is not executing from a latency-critical LL thread.
+ */
#define assert_can_be_cold() __assert_can_be_cold(__func__)
#else
#define dbg_path_hot_start_watching() do {} while (0)
#define dbg_path_hot_stop_watching() do {} while (0)
#define dbg_path_hot_confirm() do {} while (0)
#define dbg_path_cold_enter() do {} while (0)
+/**
+ * @brief Assert that the current function is not executing from a latency-critical LL thread.
+ */
#define assert_can_be_cold() do {} while (0)
#endif
+/** @}*/
+
#endif /* __SOF_LIB_MEMORY_H__ */
diff --git a/zephyr/include/sof/lib/mm_heap.h b/zephyr/include/sof/lib/mm_heap.h
index 634b336d9e40..d2423acdeb1e 100644
--- a/zephyr/include/sof/lib/mm_heap.h
+++ b/zephyr/include/sof/lib/mm_heap.h
@@ -3,6 +3,15 @@
* Copyright(c) 2024 Intel Corporation.
*/
+/**
+ * @file sof/lib/mm_heap.h
+ * @brief Legacy XTOS heap compatibility header.
+ * @ingroup memory_api
+ * @deprecated Legacy XTOS heap management header. On Zephyr platforms, heap operations
+ * are managed by RTOS allocators in `` and Zephyr k_heap;
+ * this header is retained solely as an empty compatibility shim.
+ */
+
#ifndef __SOF_LIB_MM_HEAP_H__
#define __SOF_LIB_MM_HEAP_H__
diff --git a/zephyr/include/sof/lib/regions_mm.h b/zephyr/include/sof/lib/regions_mm.h
index 0e3b51c8bdce..259091ab4df3 100644
--- a/zephyr/include/sof/lib/regions_mm.h
+++ b/zephyr/include/sof/lib/regions_mm.h
@@ -5,6 +5,12 @@
* Author: Jakub Dabek
*/
+/**
+ * @file sof/lib/regions_mm.h
+ * @brief Virtual Memory Heap (VMH) and multi-block region allocator API.
+ * @ingroup memory_api
+ */
+
#ifndef ZEPHYR_LIB_REGIONS_MM_H_
#define ZEPHYR_LIB_REGIONS_MM_H_
@@ -17,41 +23,43 @@
#include
#include
-/* Attributes for memory regions */
-#define VIRTUAL_REGION_SHARED_HEAP_ATTR 1U /*< region for shared virtual heap */
-#define VIRTUAL_REGION_LLEXT_LIBRARIES_ATTR 2U /*< region for LLEXT libraries */
-#define VIRTUAL_REGION_VPAGES_ATTR 3U /*< region for virtual page allocator */
-
-/* Dependency on ipc/topology.h created due to memory capability definitions
- * that are defined there
+/** \addtogroup memory_api
+ * @{
+ *
+ * @note **Re-entrancy Contract**: This API is **NOT re-entrant**. While runtime
+ * allocation and deallocation operations (vmh_alloc(), vmh_free()) synchronize
+ * internally via the heap mutex, heap lifecycle management operations (such as
+ * vmh_free_heap()) do not use mutual exclusion. It is assumed that only system
+ * management code performs heap lifecycle operations, and concurrent heap
+ * management with runtime allocations must be avoided.
*/
-/* API is NOT re-entry safe.
- * This is due to our assumption that only management code will ever handle
- * memory operations on heaps themselves.
- */
+/** @brief Region attribute for shared virtual memory heap. */
+#define VIRTUAL_REGION_SHARED_HEAP_ATTR 1U
+/** @brief Region attribute for loadable LLEXT libraries. */
+#define VIRTUAL_REGION_LLEXT_LIBRARIES_ATTR 2U
+/** @brief Region attribute for virtual page allocator. */
+#define VIRTUAL_REGION_VPAGES_ATTR 3U
-/* Defines maximum amount of memory block allocators in one heap
- * since minimum realistic block should be cache line size
- * and block sizes in allocator must be powers of 2
- * so logically it gives limited block sizes
- * eg allocator of block size 64 128 256 512 2048 4096 1024 8192
- * would end up in 8 allocators.
- * It is expected that allocations bigger than that would
- * either be spanned on specifically configured heap or have
- * individual configs with bigger block sizes.
+/**
+ * @brief Maximum amount of memory block allocators in one heap.
+ *
+ * Since minimum realistic block is cache line size and block sizes
+ * must be powers of 2 (e.g. 64, 128, 256, 512, 1024, 2048, 4096, 8192).
*/
#define MAX_MEMORY_ALLOCATORS_COUNT 10
-/* vmh_get_default_heap_config() function will try to split the region
- * down the given count. Only applicable when API client did not
- * use its config.
+/**
+ * @brief Default number of power-of-2 block allocators partitioned across a region.
*/
#define DEFAULT_CONFIG_ALOCATORS_COUNT 5
+/**
+ * @brief Descriptor for a power-of-2 block size bundle in a virtual memory heap.
+ */
struct vmh_block_bundle_descriptor {
- size_t block_size; /**< size of memory block. */
- size_t number_of_blocks; /**< number of memory blocks. */
+ size_t block_size; /**< Size of memory block in bytes. */
+ size_t number_of_blocks; /**< Number of memory blocks in this bundle. */
};
/*
@@ -72,22 +80,65 @@ struct vmh_heap_config {
struct vmh_block_bundle_descriptor block_bundles_table[MAX_MEMORY_ALLOCATORS_COUNT];
};
+/**
+ * @brief Initialize a virtual memory heap with the given bundle configuration.
+ * @param[in] cfg Pointer to heap bundle configuration.
+ * @param[in] allocating_continuously If true, allows allocations to span a contiguous run
+ * of VMH block slots within a bundle; does not guarantee
+ * contiguous physical backing pages.
+ * @return Pointer to initialized vmh_heap, or NULL on failure.
+ */
struct vmh_heap *vmh_init_heap(const struct vmh_heap_config *cfg, bool allocating_continuously);
+
+/**
+ * @brief Allocate a memory block from the virtual memory heap.
+ * @param[in,out] heap Pointer to target vmh_heap instance.
+ * @param[in] alloc_size Allocation size in bytes.
+ * @return Pointer to allocated buffer, or NULL on failure.
+ */
void *vmh_alloc(struct vmh_heap *heap, uint32_t alloc_size);
+
+/**
+ * @brief Destroy a virtual memory heap and unmap all backing pages.
+ * @param[in,out] heap Pointer to vmh_heap instance to destroy.
+ * @return 0 on success, negative error code on failure.
+ */
int vmh_free_heap(struct vmh_heap *heap);
+
+/**
+ * @brief Free a memory block previously allocated from a virtual memory heap.
+ * @param[in,out] heap Pointer to vmh_heap instance.
+ * @param[in,out] ptr Pointer to memory block to free.
+ * @return 0 on success, negative error code on failure.
+ */
int vmh_free(struct vmh_heap *heap, void *ptr);
+
+/**
+ * @brief Generate a default heap partition configuration for a memory driver region.
+ * @param[in] region Driver region describing base and size.
+ * @param[out] cfg Destination configuration structure to populate.
+ */
void vmh_get_default_heap_config(const struct sys_mm_drv_region *region,
struct vmh_heap_config *cfg);
#ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS
+/**
+ * @brief Log aggregate runtime statistics for the virtual memory heap.
+ * @param[in] heap Pointer to vmh_heap instance.
+ */
void vmh_log_stats(struct vmh_heap *heap);
+
+/**
+ * @brief Log per-bundle block allocation statistics for the virtual memory heap.
+ * @param[in] heap Pointer to vmh_heap instance.
+ */
void vmh_log_alloc_stats(struct vmh_heap *heap);
#endif
/**
- * @brief Checks if ptr is in range of given memory range
+ * @brief Checks if ptr is in range of given memory range.
*
- * @param ptr checked ptr
- * @param range_start start of checked memory range
- * @param range_size size of checked memory range.
+ * @param[in] ptr Checked pointer address.
+ * @param[in] range_start Start of checked memory range.
+ * @param[in] range_size Size of checked memory range in bytes.
*
* @retval false if no overlap detected.
* @retval true if any overlap detected.
@@ -98,4 +149,6 @@ static inline bool vmh_is_ptr_in_memory_range(uintptr_t ptr, uintptr_t range_sta
return ptr >= range_start && ptr < range_start + range_size;
}
+/** @}*/
+
#endif /* ZEPHYR_LIB_REGIONS_MM_H_ */
diff --git a/zephyr/include/sof/lib/vpage.h b/zephyr/include/sof/lib/vpage.h
index f3fc8b89e968..ef66ce0ae533 100644
--- a/zephyr/include/sof/lib/vpage.h
+++ b/zephyr/include/sof/lib/vpage.h
@@ -1,7 +1,12 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright(c) 2025 Intel Corporation.
-/* Virtual Page Allocator API */
+/**
+ * @file sof/lib/vpage.h
+ * @brief Virtual Page Allocator API for mapping contiguous memory pages.
+ * @ingroup memory_api
+ */
+
#ifndef __SOF_LIB_VPAGE_H__
#define __SOF_LIB_VPAGE_H__
@@ -12,25 +17,32 @@
extern "C" {
#endif
+/** \addtogroup memory_api
+ * @{
+ */
+
/**
- * @brief Allocate virtual pages
- * Allocates a specified number of contiguous virtual memory pages by mapping
- * physical pages.
+ * @brief Allocate contiguous virtual pages.
*
- * @param[in] pages Number of pages (usually 4kB large) to allocate.
+ * Allocates a specified number of contiguous virtual memory pages by mapping
+ * physical backing pages into the DSP page table.
*
+ * @param[in] pages Number of pages (typically 4KB per page) to allocate.
* @return Pointer to the allocated virtual memory region, or NULL on failure.
*/
void *vpage_alloc(unsigned int pages);
/**
- * @brief Free virtual pages
- * Frees previously allocated virtual memory pages and unmaps them.
+ * @brief Free virtual pages.
*
- * @param[in] ptr Pointer to the memory pages to free.
+ * Frees previously allocated virtual memory pages and unmaps them from the page table.
+ *
+ * @param[in,out] ptr Pointer to the virtual memory pages to free.
*/
void vpage_free(void *ptr);
+/** @}*/
+
#ifdef __cplusplus
}
#endif