Conversation
Adds documentation detailing the ZEPHYR user space and Intel ADSP third party integration mechanisms via the Module Adapter architecture. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Adds documentation detailing the Cadence codec, generic, and Intel API adapter shims. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Adds architecture processing flows and state transition documentation for the generic component API. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
There was a problem hiding this comment.
Pull request overview
Adds new high-level documentation for SOF’s modern audio processing module architecture and the module adapter subcomponents, clarifying interfaces, state transitions, and data flow patterns.
Changes:
- Added an overview README for the core
src/modulearchitecture (interfaces, state machine, data flow). - Added adapter-specific READMEs describing
generic,modules(IADK shim),cadence, userspace proxy/library, and IADK integration. - Included mermaid diagrams for architecture, state transitions, and processing sequences.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/module/README.md | Documents modern module API concepts (interfaces/state machine/data flow). |
| src/audio/module_adapter/module/README.md | Explains concrete module_interface adapter implementations and responsibilities. |
| src/audio/module_adapter/library/README.md | Describes LLEXT/userspace proxy sandbox architecture and IPC handling. |
| src/audio/module_adapter/iadk/README.md | Documents IADK adapter flow and buffer translation responsibilities. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| - modules request data by calling `source_get_data_s16` or `s32`. This establishes an active read lock. | ||
| - Once done, the module must call `source_release_data()` releasing only the frames actually consumed. | ||
|
|
||
| ### Sink API (`src/module/audio/sink_api.c`) | ||
| - modules request destination buffers by calling `sink_get_buffer_s16` or `s32`. |
There was a problem hiding this comment.
The function references look incomplete/ambiguous: source_get_data_s16/sink_get_buffer_s16 are missing () and the 's32' variant is not named (it reads like a suffix rather than an API). Please spell out the exact function names for both widths (and include parentheses) so readers can grep/click them reliably.
| - modules request data by calling `source_get_data_s16` or `s32`. This establishes an active read lock. | |
| - Once done, the module must call `source_release_data()` releasing only the frames actually consumed. | |
| ### Sink API (`src/module/audio/sink_api.c`) | |
| - modules request destination buffers by calling `sink_get_buffer_s16` or `s32`. | |
| - modules request data by calling `source_get_data_s16()` or `source_get_data_s32()`. This establishes an active read lock. | |
| - Once done, the module must call `source_release_data()` releasing only the frames actually consumed. | |
| ### Sink API (`src/module/audio/sink_api.c`) | |
| - modules request destination buffers by calling `sink_get_buffer_s16()` or `sink_get_buffer_s32()`. |
| Mod->>Src: source_get_data(req_size) | ||
| Src-->>Mod: Provides read_ptr, available_bytes | ||
|
|
||
| Mod->>Snk: sink_get_buffer(req_size) | ||
| Snk-->>Mod: Provides write_ptr, free_bytes | ||
|
|
||
| note over Mod: Execute DSP Algorithm <br> (Read from read_ptr -> Write to write_ptr) | ||
|
|
||
| Mod->>Src: source_release_data(consumed_bytes) | ||
| Mod->>Snk: sink_commit_buffer(produced_bytes) |
There was a problem hiding this comment.
This sequence diagram uses consumed_bytes / produced_bytes, but the subsequent bullets in the Source/Sink API sections describe releasing/committing 'frames'. Please make the unit consistent (bytes vs frames) across the diagram and the bullet points to avoid incorrect usage.
| Mod->>Src: source_get_data(req_size) | |
| Src-->>Mod: Provides read_ptr, available_bytes | |
| Mod->>Snk: sink_get_buffer(req_size) | |
| Snk-->>Mod: Provides write_ptr, free_bytes | |
| note over Mod: Execute DSP Algorithm <br> (Read from read_ptr -> Write to write_ptr) | |
| Mod->>Src: source_release_data(consumed_bytes) | |
| Mod->>Snk: sink_commit_buffer(produced_bytes) | |
| Mod->>Src: source_get_data(req_frames) | |
| Src-->>Mod: Provides read_ptr, available_frames | |
| Mod->>Snk: sink_get_buffer(req_frames) | |
| Snk-->>Mod: Provides write_ptr, free_frames | |
| note over Mod: Execute DSP Algorithm <br> (Read from read_ptr -> Write to write_ptr) | |
| Mod->>Src: source_release_data(consumed_frames) | |
| Mod->>Snk: sink_commit_buffer(produced_frames) |
|
|
||
| It implements the full `struct module_interface` contract: | ||
|
|
||
| * **Memory Management**: It intercepts memory allocation mappings using `mod_balloc_align` and tracks memory requests in a module-specific resource pool (`module_resource`). When the module goes out of scope, the framework garbage-collects any leaked allocations automatically via `mod_free_all()`. |
There was a problem hiding this comment.
This refers to a module_resource pool, but the new src/module/README.md describes memory allocations as module_resources (plural). Within this PR’s docs, please standardize the naming (and ideally match the actual struct/type name in the codebase) to avoid confusion.
| * **Memory Management**: It intercepts memory allocation mappings using `mod_balloc_align` and tracks memory requests in a module-specific resource pool (`module_resource`). When the module goes out of scope, the framework garbage-collects any leaked allocations automatically via `mod_free_all()`. | |
| * **Memory Management**: It intercepts memory allocation mappings using `mod_balloc_align` and tracks memory requests in a module-specific resource pool (`module_resources`). When the module goes out of scope, the framework garbage-collects any leaked allocations automatically via `mod_free_all()`. |
|
|
||
| The `library` directory within the module adapter manages the lifecycle and execution isolation for dynamically loaded algorithms, often referred to as "LLEXT modules" or "Userspace Modules". | ||
|
|
||
| It acts as a secure intermediary layer between the native SOF/Zephyr kernel execution mode (supervisor mode) and the 3rd-party module running in an isolated user-mode context. By relying on Zephyr's Userspace mechanisms (`k_mem_domain`, `K_USER` threads), a faulting or misbehaving loadable extension cannot crash the entire firmware. |
There was a problem hiding this comment.
The statement 'cannot crash the entire firmware' is an absolute guarantee that may be stronger than what userspace isolation typically provides (it can reduce impact, but not necessarily prevent all failure modes like resource exhaustion). Consider rephrasing to a bounded/accurate claim (e.g., 'helps prevent a fault from taking down the whole firmware' / 'reduces the blast radius').
| It acts as a secure intermediary layer between the native SOF/Zephyr kernel execution mode (supervisor mode) and the 3rd-party module running in an isolated user-mode context. By relying on Zephyr's Userspace mechanisms (`k_mem_domain`, `K_USER` threads), a faulting or misbehaving loadable extension cannot crash the entire firmware. | |
| It acts as a secure intermediary layer between the native SOF/Zephyr kernel execution mode (supervisor mode) and the 3rd-party module running in an isolated user-mode context. By relying on Zephyr's Userspace mechanisms (`k_mem_domain`, `K_USER` threads), a faulting or misbehaving loadable extension is less likely to take down the entire firmware and its impact is better contained. |
Add some further high level information on the module interfaces.