Repository navigation
Conversation
2fc03a7 to
5c11182
Compare
lgirdwood
left a comment
There was a problem hiding this comment.
Lets split this patch into patch per feature. Need to LOG_ERR any errors and IPC3 support not needed
5c11182 to
b0df45d
Compare
There was a problem hiding this comment.
🟡 Changes recommended
It contains compilation failures plus multiple unsafe initialization, triggering, control, and format-handling defects.
16 open findings
ABI header size and payload bounds are not validated · New Application-tier loader performs privileged DAI configuration · New Selector callback accepts invalid channel indexes · New Unchecked volume channel count can overflow arrays · New Unchecked mute channel count can overflow arrays · New Runtime processing ignores updated enable switch · New EQ re-enable selects wrong routine for S24 and S32 · New S16-in-32-bit format incorrectly reports 32 valid bits · New U8 format incorrectly mapped as signed integer · New Unsupported channel counts produce inconsistent IPC4 maps · New UAC2 unity volume uses incorrect fixed-point representation · New Volume interpolation is non-monotonic at 6 dB boundaries · New UAC2 channel index ignored by volume setter · New UAC2 query ignores requested channel · New UAC2 GET_CUR returns linear gain instead of dB · New Volume example uses incorrect Q1.16 unity value · New
What changed in this PR
Introduces declarative, boot-time audio topology construction for hostless SOF platforms.
Changes:
- Adds static topology descriptors, module registry, loader, controls, and UAC2 integration.
- Registers static operations for supported processing modules.
- Adds configuration, build integration, and developer documentation.
| File | Description |
|---|---|
src/include/sof/audio/pipeline/static_pipeline.h |
Defines the public static topology API. |
src/include/sof/audio/component.h |
Declares component-driver lookup. |
src/audio/component.c |
Implements component-driver lookup. |
src/audio/pipeline/static_pipeline_loader.c |
Builds, configures, controls, and triggers static graphs. |
src/audio/pipeline/static_pipeline_modules.c |
Implements module registration and IPC4 config synthesis. |
src/audio/pipeline/static_pipeline_modules.h |
Declares internal module helpers. |
src/audio/pipeline/static_pipeline_uac2.c |
Bridges UAC2 controls and triggers. |
src/audio/pipeline/CMakeLists.txt |
Adds static pipeline sources. |
src/audio/pipeline/README.md |
Documents architecture and usage. |
src/audio/Kconfig |
Adds feature and capacity options. |
src/audio/volume/volume.c |
Adds Volume and Gain operations. |
src/audio/src/src.c |
Adds SRC creation support. |
src/audio/asrc/asrc.c |
Adds ASRC creation support. |
src/audio/selector/selector.c |
Adds Selector creation and controls. |
src/audio/level_multiplier/level_multiplier.c |
Adds gain and switch controls. |
src/audio/eq_iir/eq_iir.c |
Adds EQ bypass control. |
src/audio/drc/drc.c |
Adds DRC enable control. |
src/audio/tdfb/tdfb.c |
Adds beamforming switch control. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| /* Validate component pointer and configuration blob payload */ | ||
| if (!dev || !abi_blob || abi_blob_total_size == 0) { | ||
| LOG_ERR("send_comp_config: invalid parameter or empty blob"); | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| const struct sof_abi_hdr *hdr = (const struct sof_abi_hdr *)abi_blob; |
There was a problem hiding this comment.
Fixed. Added strict validation requiring abi_blob_total_size >= sizeof(struct sof_abi_hdr) and verifying that hdr->size <= abi_blob_total_size - sizeof(struct sof_abi_hdr) before dereferencing or forwarding payload data, logging LOG_ERR and returning -EINVAL on truncated or oversized blobs.
| /* Configure underlying physical DAI controller instance */ | ||
| struct dai *dai = dai_get(cdesc->ep.dai.dai_type, cdesc->ep.dai.dai_index, DAI_CREAT); | ||
|
|
||
| if (dai) { | ||
| dai_set_config(dai, &dai_cfg, &spec_cfg, sizeof(spec_cfg)); |
There was a problem hiding this comment.
Fixed. Removed direct application-tier dai_get(), dai_set_config(), and dai_put() HAL calls. DAI endpoint creation and hardware configuration are now delegated exclusively to the standard component driver framework via drv->ops.create and comp_dai_config(), preserving userspace/HAL privilege boundaries.
| return -EINVAL; | ||
| } | ||
|
|
||
| cd->config.sel_channel = val; |
There was a problem hiding this comment.
Fixed. sel_static_apply_enum() now checks val >= 0, enforces val < SEL_SOURCE_4CH, and queries the producer stream/configured channel width to ensure val < src_channels, logging comp_err and returning -EINVAL on out-of-range selection.
| for (uint32_t ch = 0; ch < channels; ch++) | ||
| volume_set_chan(mod, ch, val, true); |
There was a problem hiding this comment.
Fixed. Added bounds validation in vol_static_apply_volume() verifying channels > 0 && channels <= SOF_IPC_MAX_CHANNELS and returning -EINVAL on invalid counts.
| for (uint32_t ch = 0; ch < channels; ch++) { | ||
| if (val == 0) | ||
| volume_set_chan_mute(mod, ch); | ||
| else | ||
| volume_set_chan_unmute(mod, ch); | ||
| } |
There was a problem hiding this comment.
Fixed. Added bounds validation in vol_static_apply_switch() verifying channels > 0 && channels <= SOF_IPC_MAX_CHANNELS prior to channel mute/unmute iteration.
| /* Linear interpolation between 6 dB bit shifts */ | ||
| int rem = db_x10 % 60; | ||
| uint64_t v = (uint64_t)SOF_VOL_ZERO_DB >> shift; | ||
| v = (v * (60 - rem)) / 60; | ||
| return (int32_t)v; |
There was a problem hiding this comment.
Fixed. Corrected interpolation in uac2_to_sof_volume() to interpolate monotonically between v and v_next = v >> 1: val = v_next + (((v - v_next) * (60 - rem)) / 60).
| * \param[in] is_volume True for volume command, false for mute switch command. | ||
| * \return 0 on success, negative errno on failure. | ||
| */ | ||
| int sof_static_kcontrol_set_by_uac2(uint8_t entity_id, uint8_t channel, int32_t val, bool is_volume) |
There was a problem hiding this comment.
Fixed. Added sof_static_kcontrol_set_chan() and wired per-channel .apply_volume_chan and .apply_switch_chan callbacks. When channel == 0 (master), all channels are updated; when channel > 0, the request routes to the specific channel.
| * \param[in] is_volume True for volume query, false for mute query. | ||
| * \return 0 on success, negative errno on failure. | ||
| */ | ||
| int sof_static_kcontrol_get_by_uac2(uint8_t entity_id, uint8_t channel, int32_t *val, bool is_volume) |
There was a problem hiding this comment.
Fixed. Added per-channel storage in s_uac2_cache indexed by UAC2 channel number, enabling channel-accurate GET_CUR responses.
| if (is_volume && ctl->type == SOF_STATIC_CTRL_VOLUME) { | ||
| *val = ctl_val; | ||
| return 0; |
There was a problem hiding this comment.
Fixed. s_uac2_cache now caches the original UAC2 8.8 dB signed value on SET_CUR and returns it directly on GET_CUR, preventing precision loss and returning exact UAC2 format.
| .min = 0, | ||
| .max = 65536, | ||
| .def = 65536, /* 0 dB default */ |
There was a problem hiding this comment.
Fixed. Updated the Volume kcontrol example in README.md to use .max = INT32_MAX, .def = INT32_MAX (0 dB default in Q1.31).
Add a standard driver lookup API comp_driver_find() to search registered component drivers by UUID (for audio processing modules) or by driver type (for Host and DAI endpoints). Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…d headers Add <sof/audio/pipeline/static_pipeline.h> providing declarative topology descriptors, capability bitmasks (rates and frame formats), component constructor macros, ops-driven static module interface, and public control and trigger APIs. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
… config synthesizer Add static_pipeline_modules.c and static_pipeline_modules.h providing generic module operations registration, UUID lookup, and IPC4 base module configuration synthesis. Contains purely generic infrastructure with zero per-module logic and no IPC3 dependencies. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Implement static_pipeline_loader.c to parse declarative static audio topologies and instantiate native SOF pipelines, components, intermediate buffers, routes, and kcontrols at boot. Features: - Purely IPC4 based architecture with no IPC3 dependencies - Modular multi-stage initialization with explicit LOG_ERR on all failures - Per-pipeline sample rate negotiation and tracking across pipelines, streams, and DAI/host endpoints - Configurable tracking table limits via Kconfig (STATIC_PIPELINE_MAX_*) to support memory-constrained embedded devices - Runtime kcontrol dispatch to registered module ops with error checking Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…ol operations Add static_pipeline_uac2.c providing translation between USB Audio Class 2.0 (UAC2) requests (8.8 dB volume representation, mute switches, streaming terminal trigger events) and SOF static pipelines and kcontrols. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Register static module operations (struct sof_static_module_ops) across core audio processing components (Volume, Gain, Level Multiplier, SRC, ASRC, Selector, EQ IIR, DRC, and TDFB) for IPC4 static pipeline execution. Includes explicit error logging on invalid module pointers or private data. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Add comprehensive documentation for the static audio pipeline subsystem in src/audio/pipeline/README.md covering: - Architectural motivations for microcontroller and hostless systems - Core concepts and declarative topology structures - Step-by-step tutorial with multi-rate SRC playback examples - Ops-driven module interface and UAC2 integration - Custom kcontrol handlers with named identifiers Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
b0df45d to
a9ed44c
Compare
PR 11266: test resultsRun date: 2026-10-11 13:33 UTC Tested commit: a9ed44c17dff0f89be0e5d626ba7b4a9ee1d818c |



Summary
Add support for declarative static audio pipelines in Sound Open Firmware.
In microcontroller, hostless, and standalone embedded environments (such as ESP32-P4/S3/C6, PJRC Teensy 4.1, Nordic nRF54, RP2350, smart speakers, and audio bridges), there is no dynamic IPC host driver (Linux ALSA/SoundWire or Windows) to construct topologies at runtime.
Key Additions & Features
Declarative Topology Structures & Macros (
<sof/audio/pipeline/static_pipeline.h>):SOF_STATIC_RATE_*) aligned withSOF_RATE_*and format bitmasks (SOF_STATIC_FMT_*) aligned withenum sof_ipc_frame.SOF_STATIC_MODULE,SOF_STATIC_MODULE_RATE_CONV,SOF_STATIC_ENDPOINT_DAI,SOF_STATIC_ENDPOINT_USB) for clean declarative pipeline definition.Ops-Driven Decoupled Architecture:
struct sof_static_module_ops) providing.create,.apply_volume,.apply_switch, and.apply_enumcallbacks directly in their own source files (SRC, ASRC, Volume/Gain, Level Multiplier, Selector, EQ IIR, DRC, and TDFB) usingDECLARE_STATIC_MODULE_OPS().Generic Module Registry & Base IPC4 Config Synthesizer (
static_pipeline_modules.c):sof_static_init_base_cfg) generating standard IPC4 base module configurations (struct ipc4_base_module_cfg) on behalf of the absent host, calculating IBS/OBS and channel mapping from declarative capabilities and periods.Dynamic Format & Rate Negotiation:
Static Topology Loader Engine (
static_pipeline_loader.c):Dedicated Pipeline Control & Trigger Safety:
sof_static_pipeline_start,sof_static_pipeline_stop).pipeline_prepare()failure preventing triggers on uninitialized circular buffers.Kconfig & Build Integration:
CONFIG_STATIC_PIPELINEKconfig option and CMakeLists integration.Developer Documentation:
src/audio/pipeline/README.md.