Repository navigation
Conversation
Rework the RTNR module to only use the sink/source API to prepare SOF for the full transition to pipeline 2.0. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
…l send The primary-core watchdog timeout notification used the deprecated old-interface call intel_adsp_ipc_send_message_emergency() together with the Intel-specific INTEL_ADSP_IPC_HOST_DEV device handle. Route it instead through the generic ipc_platform_send_msg_direct(), which maps to ipc_service_send_critical() and the backend critical/emergency send, identical register behaviour (busy-wait, no ack, bypasses flow control), but expressed with the backend-agnostic ipc_service API and a struct ipc_msg, mirroring the secondary-core path. This removes the watchdog's dependency on the old interface and on the Intel host IPC device macro, dropping the intel_adsp_ipc*.h includes. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
The IPC4 fuzzer hit an out-of-bounds read in ipc4_find_all_dma_configs_tlvs_only() while parsing a copier gateway config blob as a TLV sequence. AddressSanitizer reports a SEGV on a wild address ~16 MB below the config buffer. Root cause: the per-TLV bounds check and the iterator both do pointer arithmetic on the host-controlled tlvs->length without guarding against overflow. On 32-bit targets (native_sim and the Xtensa DSPs) a large length wraps the pointer: if ((uintptr_t)tlvs->value + tlvs->length > end_addr) /* wraps */ return IPC4_INVALID_REQUEST; ... tlvs = tlv_next(tlvs); /* tlvs + 8 + length, also wraps */ With length = 0xff000000 and a 32-byte buffer, tlvs->value + length wraps to a value below end_addr, so the check passes; tlv_next() wraps to the same address, which is still below end_addr, so the loop continues and dereferences that wild pointer. config_length is already bounded to the init payload (so the buffer itself is small and valid) - this is a separate overflow inside the TLV walk, on the length field embedded in the blob. Compare tlvs->length against the remaining space using subtraction, which cannot overflow because the (tightened) loop condition guarantees the TLV header - and therefore tlvs->value - is within the buffer. tlv_next() is thus bounded by end_addr as well. The loop condition now also requires the full 8-byte header to fit before it is dereferenced. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
The debug_stream.py tool outputs exception records in a format that differs from the QEMU format the decoder originally targeted: - Register values can be (nil) instead of 0x0, e.g. 'A4 (nil)' - Backtrace entries are on separate lines after 'Backtrace:' rather than all on a single line - Additional registers LCOUNT and THREADPTR are present Update the parser to handle both formats: - Fix (nil) regex: the trailing word boundary anchor failed on the closing parenthesis; split hex and decimal into separate capture groups to avoid the issue - Parse backtrace entries across multiple lines after the Backtrace: header, stopping when a line contains non-backtrace content - Add LCOUNT and THREADPTR to the accepted register list The existing single-line backtrace and QEMU register formats continue to work unchanged. Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
This reverts commit 48cdc4d. struct sys_sem cannot be on heap and we can have many LL tasks so using a statically allocated pool of them doesn't look like a good idea either. Using k_sem is slower, but so far there don't seem to be good alternatives to that. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Total of 821 commits.
Changes include:
21a30f3f9a62 llext: correct got entry reads in xtensa elf
e0f04c284729 Revert "kernel: timeout: add sys_clock_idle_enter() for
low-power idle handoff"
7d0bb85adc29 kernel: timeout: add sys_clock_idle_enter() for low-power
idle handoff
3e93f462ac41 soc: nxp: use diamond include for non-local header files
a77fc1e6e870 boards: nxp: use diamond include for non-local header files
eec6a8f52a63 arch: x86, xtensa: support the idle-hook CPU load backend
25d08114e92e arch: gate idle notification hooks on SYS_IDLE_HOOKS
b8585ef254c1 soc: intel: use diamond include for non-local header files
715e6c494266 dts: arm: use diamond include for non-local header files
6e245d5d3704 lib/sys: add sys prefix to word granular access functions
439718a59814 xtensa: remove CPU mask pin only special code path
539fec76a346 logging: widen raw timestamp format to full uint width
c1c448133b57 modules: hal_nxp: fix i.MX943 Cortex-A device build
5c1758aed791 west.yml: remove unused files from hal_nxp
11b534905147 drivers: timer: declare 64-bit counter widths to the
generic core
0bbd4843faa3 drivers: timer: fix the equality-match compare catch-up
livelock
72d14283bda2 drivers: timer: intel_adsp_timer: use the generic timer
core
e8163a10525e drivers: timer: native_sim_timer: use the generic timer
core
4b0877cebe95 drivers: timer: xtensa_sys_timer: use the generic timer
core
945af04840a2 lib: os: cpu_load: close the idle window at ISR entry
3244b759ddf3 Revert "west.yml: update hal nxp to the latest version"
a9f8e1a2391f west.yml: update hal nxp to the latest version
Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
…URE_CH The BE DAI and all widgets in the capture path should honor the number of capture channels set by SDW_JACK_CAPTURE_CH. Before this change, the value of SDW_JACK_CAPTURE_CH only affected the min/max channels of the FE DAI but all the other widgets in the pipeline were defaulting to 2-channel. Because of this, the codec DAI was always asked for a 2-channel capture, which won't work on codecs that only support 1 channel. And the host-copier output was 2-channel audio that could not be connected to the 1-channel DAI. Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
module_set_large_config() reads a SET_LARGE_CONFIG payload out of the fixed-size HOSTBOX mailbox. For a single-fragment config (init_block && final_block) the number of bytes copied, fragment_size, is set verbatim to the host-controlled data_off_size (a 20-bit field, up to ~1 MB), without bounding it to the mailbox. The .set_configuration handler (e.g. comp_data_blob_set() -> memcpy_s()) then copies that many bytes from the ~4 KB mailbox; memcpy_s() only validates the destination size, so the source over-read is not caught and reads past MAILBOX_HOSTBOX_BASE. A fuzzer-crafted request (data_off_size = 64778 from a 4096-byte mailbox) triggers a global-buffer-overflow read reported by AddressSanitizer. Reject a single fragment larger than MAILBOX_HOSTBOX_SIZE, mirroring the range check already present on the GET path (commit f72dbb2) and the mailbox bound used at module init. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
This fixes a regression introduced by bde2726 ("ipc4: add user-space command-forwarding context") which replaced ipc_buf.comp.core = cpu_get_id(); with ipc_buf.comp.core = src->ipc_config.core; The replacement was needed to prepare the function to be called from user space, where cpu_get_id() is privileged. However, it broke the cross-core bind case: such a bind is always processed on the primary core, so the two expressions are not equivalent there. Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>
k_thread_cpu_pin() must not be called on a running thread, and the worker must not execute while its memory domain is being modified. Suspend the worker thread before pinning it to the module core and before the module memory domain is set up, and resume it once the domain has been configured. This fixes a crash in tests with a userspace DP module on a secondary core: the worker thread started by k_work_user_queue_start() was still running on another core and had not yet reached its queue wait condition by the time k_thread_cpu_pin() was called. Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>
The existing sof-ptl-rt713-l3-rt1320-l1.tplg includes 2ch PCH DMIC. And the '-2ch' suffix will be added in the Linux driver. Rename sof-ptl-rt713-l3-rt1320-l1 to sof-ptl-rt713-l3-rt1320-l1-2ch. It is fine because the sof-ptl-rt713-l3-rt1320-l1.tplg was not released to sof-bin yet. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Remove XTENSA_BACKTRACE_EXCEPTION_DUMP option from debug_stream_overlay.conf since its removed from Zephyr in commit: ba8bb9a20f97 arch: xtensa: change backtrace to use EXCEPTION_DUMP Signed-off-by: Jyri Sarha <jyri.sarha@linux.intel.com>
Rework the multiband drc module to only use the sink/source api to prepare sof for the full transition to pipeline 2.0. Signed-off-by: Piotr Hoppe <piotr.hoppe@intel.com>
Eliminate multiple instances of IPC4 data copying, use simple type- casts instead. This removes stack objects and replaces run-time copying with compile-time pointer substitution. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
copier_alh_assign_dai_index() reads alh_cfg.count from the host-supplied gateway config blob and walks alh_cfg.mapping[0..count). Count was only bounded by the mapping[] array size, not the actual blob size, so a malformed blob could make the mapping walk read past config_data and underflow dma_config_length in the HDA branch. Validate that the blob contains the fixed header before reading count, then ensure count is within the mapping[] bound and that its computed ALH configuration size fits in the blob. This rejects malformed configurations before any mapping[] access. HDA always reads mapping[0], including for a single gateway. Reject a zero count in this path so a header-only blob cannot cause that out-of-bounds read. Keep zero-count behavior unchanged for single ALH, which does not access mapping[]. Use %zu when logging blob_size to preserve size_t values on 64-bit builds. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
Update Zephyr to include 24f16b4f886c ("lib: os: p4wq: skip
k_thread_cpu_mask_clear() in PIN_ONLY mode").
Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
This patch fixes the issue with the Phase Vocoder module producing strong rattle with other than s16 format decoded output from compress decoders such as MP3 and AAC. The pipeline bind path only propagates the container frame_fmt into the shared buffer between two modules; it does not populate valid_sample_fmt. As a result source_get_valid_fmt() on the phase vocoder's input returned the zero-initialised value (S16_LE), so the wrong processing variant was selected whenever the topology declared a valid bit depth other than 16. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
The .cold section contains executable code, while .coldrodata contains data. Therefore their MMU flags have to be different, particularly when mapping for userspace. Add a page-size alignment to account for such cases. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
When the user changes the speed control the component preserves the polar analysis state across the reset so that the interpolation can continue smoothly, but the synthesis phase accumulator output_phase was left drifting. Each output IFFT in stft_do_fft_ifft() advances output_phase by an interpolated one-analysis-hop delta of the form (1 - frac) * angle_delta_prev + frac * angle_delta, where frac is the current interpolation position between two consecutive analysis frames. That delta is added irrespective of the current speed, so at non-unity speed output_phase runs faster than the true polar angle. On top of that, the first post-reset IFFT does not consume a new input FFT yet still applies its phase interpolation step (with frac = 0, so the added term equals angle_delta_prev), which adds one extra angle_delta_prev per reset. After a repeated excursion (for example 1.0 -> 0.5 -> 1.0 with several intermediate steps) both effects accumulate as a random per-bin phase offset that persists after returning to unity speed. Perceptually this smears transients and dulls the sound even though the audio is being processed at speed 1.0 again. The steady-state invariant at speed 1.0 is that after each IFFT's phase interpolation step output_phase equals polar_prev.angle. To preserve this invariant across a speed change, re-anchor output_phase to polar_prev.angle minus angle_delta_prev in reset_for_new_speed(). The first post-reset IFFT then lands output_phase exactly on polar_prev.angle, and all subsequent IFFTs advance normally with no cumulative offset. Existing NULL and channel-count guards keep the init-time call from touching buffers before they are allocated. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Without an explicit teardown a fuzz testcase that successfully creates
components, buffers or pipelines leaves them registered in
global_ipc->comp_list. The next LLVMFuzzerTestOneInput() then sees a
non-empty topology it never asked for, which both hides bugs (crashes
that depend on freshly-empty state are missed) and fabricates them
(crashes that only occur because of carry-over from a previous case are
unreproducible when the artifact is replayed on its own).
Add a posix-only teardown helper, called from posix_fuzz_case_begin()
once at the start of every testcase before the input is staged. The
helper:
* Runs a pre-pass that forces every COMP_TYPE_COMPONENT to
COMP_STATE_READY and initialises any NULL bsource_list/bsink_list
pointers, because ipc_comp_free() returns -EINVAL (and silently
leaks the entry) for a component that is not READY or whose buffer
lists were never list_init()'d - the latter happens when a
component was registered but its init failed partway through. The
pre-pass also cancels any active pipeline pipe_task so
ipc_pipeline_free() does not stall waiting for it (up to 100 LL
periods on native_sim).
* Drains each type in batches: it snapshots up to POSIX_TEARDOWN_BATCH
ids, frees them with the typed helper, and repeats until no entry of
that type remains, so the number of objects a testcase creates is not
bounded by the snapshot size (walking and freeing comp_list in one
pass is unsafe because the SOF free helpers unlink each entry). A
batch that frees nothing ends the loop so it cannot spin forever.
* Frees in dependency order COMPONENT -> BUFFER -> PIPELINE so the
topology layer never dereferences an already-freed parent. The
BUFFER pass is compiled out for IPC4 because ipc4/helper.c never
stores COMP_TYPE_BUFFER and ipc_buffer_free() does not exist there.
* Ends with a force-drain pass that walks the whole residual list with
list_for_item_safe() and removes each entry with list_item_del() +
rfree(), so comp_list is guaranteed empty on return regardless of how
many objects remained or of any future COMP_TYPE_* the typed passes
do not cover.
Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
The LL scheduler semaphore is used by the userspace, so it has to be allocated dynamically. On the other hand dynamic object freeing from the userspace is unsupported by design. To securely free the semaphore object we add two syscalls that guarantee, that object freeing cannot be abused. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
ipc4_get_comp_drv() returned NULL unconditionally on native_sim because the RIMAGE_MANIFEST guard (Intel ADSP ACE/CAVS only) was the sole path to a driver UUID lookup. Every INIT_INSTANCE call therefore failed with IPC4_MOD_NOT_INITIALIZED before creating any comp_dev, making the entire module instance verb surface (CONFIG_GET/SET, LARGE_CONFIG on real modules, BIND, UNBIND, DELETE_INSTANCE) unreachable from the fuzzer. Resolve module drivers on native_sim from a small fuzzer-only helper, ipc4_get_fuzzer_drv(), called from the CONFIG_ARCH_POSIX_LIBFUZZER branch of ipc4_get_comp_drv() so the heavily-used manifest lookup path is left untouched. It mirrors the IPC3 whitebox hack in posix/ipc.c: module_id is a 1-based index into the runtime component driver list, counting only instantiable module-adapter drivers so the fuzzer's module_id space matches what a real signed manifest exposes. Drivers with no ops.create, and internal gateway drivers (SOF_COMP_HOST/DAI) that are never IPC4 modules, are skipped (otherwise a module_id could land on an unconfigurable component or a NULL create op). module_id 0 (BaseFW) intentionally resolves to NULL: BaseFW is never created as a pipeline component, its messages are dispatched directly by base_fw.c. A tr_err() logs any module_id that maps to no driver to help developers and agents triage. The change is inactive in all non-fuzz builds. Measured impact (UBSan IPC4, seed=1, 20 s, small corpus): cov ~558 -> ~3974 (~7x lift from previously dead module instance paths) Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
The IPC fuzzer hit a NULL pointer dereference in the IPC3 path while triggering a pipeline that contains a selector component. Both AddressSanitizer and UBSan report a READ SEGV at address 0x30 in dev_comp_type() (src/include/sof/audio/component.h). 0x30 is the offset of comp_dev::ipc_config.type, i.e. the accessor was called on a NULL comp_dev. Root cause: a comp_buffer links a producer on its ->source side to a consumer on its ->sink side, and buffers are zero-initialised, so an unconnected side stays NULL. selector_trigger() checks only that its source buffer exists and then passes that buffer's producer component straight to dev_comp_type() to look for an upstream KPB: type = dev_comp_type(comp_buffer_get_source_component(sourceb)); When the source buffer is attached to the selector but never attached to an upstream producer, comp_buffer::source is NULL and dev_comp_type() dereferences it. The mirror-image lookup in kpb.c already guards against a missing peer component; selector_trigger() was the only site doing this without the check. Look up the producer component first and treat a missing producer as "not a KPB" instead of dereferencing it. Also honour the comp_set_state() return value: the crashing trigger was a PAUSE issued from COMP_STATE_READY, which comp_set_state() already rejects with -EINVAL, but selector_trigger() ignored the error and fell through to the dereference. Bail out on error like every other component trigger handler. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
The IPC fuzzer built an IPC3 pipeline whose component owned a half-connected buffer - present on the component's buffer list but with no component attached to its opposite end - and then issued a SOF_IPC_STREAM_POSITION request. ipc_stream_position() calls pipeline_get_timestamp(), which walks the graph with pipeline_get_dai_comp() to locate the DAI endpoint. For each hop the walk takes the buffer's peer component via buffer_get_comp() and immediately dereferences comp->pipeline. For a dangling buffer buffer_get_comp() returns NULL, so the read faults at NULL + 8 (the ->pipeline field). A comp_buffer only carries a peer on a side once both ends are attached, but the IPC3 graph is assembled incrementally (each COMP_CONNECT attaches a single end) so a buffer can be left half-connected. The STREAM_POSITION path reaches this walk directly, independent of the trigger path, and does not go through the pipeline-run connectivity checks: a pipeline can be completed and then have a half-connected buffer attached by a later COMP_CONNECT, and a subsequent POSITION request walks the dangling edge. Guard the peer before dereferencing it, mirroring the existing checks in the tree: the IPC4 sibling pipeline_get_dai_comp_latency() already checks "if (!source || !source->pipeline)", and the XRUN rewind walk in pipeline_trigger_xrun() checks "if (!buffer_comp || !buffer_comp->pipeline)". A fully-connected buffer always has a non-NULL peer and a cross-pipeline peer keeps a non-NULL pointer, so only a genuinely dangling buffer is rejected and valid topologies are unaffected. pipeline_get_timestamp() already tolerates a NULL DAI result. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
Qualify the source pointer of circular buffer as const in cir_buf_copy() and cir_buf_bytes_without_wrap() functions. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
Rework the pcm conversion and dma copy paths to operate on circular buffer source and sink descriptors instead of the legacy audio stream buffers. Signed-off-by: Adrian Warecki <adrian.warecki@intel.com>
scheduler_dp_ll_tick() is currently registered as a notifier callback, but it's always triggered deterministically, always with the same-core-only flag, which leads to it being called immediately. So the notifier only adds a layer of indirection and reduces clarity. Replace it with a direct function call. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
elf_error() negates its argument, so an already negative code was turned into a positive value that callers testing "ret < 0" take for success. Signed-off-by: Adrian Bonislawski <adrian.bonislawski@intel.com>
cpu_get_id() ultimately reads a privileged special register via arch_proc_id() (e.g. the Xtensa PRID register). When low-atency pipelines run in user-space threads (CONFIG_SOF_USERSPACE_LL), this read is issued from user mode and faults. While many direct usages of cpu_get_id() have been removed from SOF codebase, multiple usages remain. As the remaining usages are mostly on less frequently used code paths (most via cpu_is_me() call, which is used in IPC handling), opt to keep the remaining cpu_get_id() calls and make the function available as a system call. The system call machinery is gated on CONFIG_SOF_FULL_ZEPHYR_APPLICATION so unit-test builds keep the plain inline definition. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
When CONFIG_SOF_USERSPACE_USE_DRIVER_HEAP isn't selected, dynamically allocated driver objects should still be accessible to the userspace. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
Add an ALSA mixer switch control 'ecns_kpb_test_signal' and IPC4 handler to enable generating an incrementing-by-1 monotonic 16-bit integer test signal on the ECNS clean mono output pin (Pin 0) instead of microphone data. This provides an end-to-end mechanism to verify sample continuity and detect any sample drops, skips, or buffer corruption between ECNS, KPB, WoV arbiter, and host capture DMA. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
… on drain Explicitly configure sel_sink and host_sink buffer parameters to mono S16 during kpb_prepare(), preventing default 2-channel buffer configuration from halving draining throughput. Eliminate the transient KPB_STATE_BUFFERING state transition in kpb_buffer_data() so asynchronous keyword triggers arriving during the 1ms buffering cycle are not rejected with 'wrong KPB state'. Subscribe to NOTIFIER_ID_WOV_CTRL to handle WOV_ARB_CMD_RESUME, cancelling active draining tasks and resetting the history buffer cleanly back to KPB_STATE_RUN on stream reset. Also accept COMP_STATE_PREPARE in is_sink_ready, add buffer_stream_writeback() on sink updates, and align pacing calculations. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…ilence fill Configure stream parameters on sink and Pin 0 source buffers during wov_arb_prepare() to guarantee mono S16 layout. In wov_arb_copy(), simplify active source buffer discovery, compute copy frames using MIN(src_frames, dst_frames) with exact audio_stream_frame_bytes(), and add buffer_stream_invalidate() / buffer_stream_writeback() for cache coherency. Remove synthetic silence insertion (fill_bytes), which injected zero frames when the source momentarily had fewer frames than the sink had free space, corrupting continuous audio data streams. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…n 20-run suite Set avail_min to 160 frames (10ms) via snd_pcm_sw_params_set_avail_min() in wov_blocking_read.c to wake poll() promptly on drained audio arrival under SNDRV_PCM_INFO_NO_PERIOD_WAKEUP, and adopt a read-first capture loop before sleeping on -EAGAIN. In run_wov_10x.py, add check_wav_continuity() to mathematically verify 0 sample skips in recorded test signal WAV files across all S0 and D0i3 iterations, automatically enable ecns_kpb_test_signal, make control resets conditional, and tune runtime PM settling delays. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
When the host deletes a pipeline under IPC4 (e.g. during stream teardown), components may still be in PREPARE or ACTIVE state if an explicit RESET trigger was not issued beforehand. ipc_comp_free() previously rejected freeing any component not in COMP_STATE_READY with -EINVAL, causing SOF_IPC4_GLB_DELETE_PIPELINE to fail with IPC4_INVALID_RESOURCE_STATE (12). Attempt to stop and reset the component to release its resources and transition it to COMP_STATE_READY before proceeding with component freeing. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…esume - During draining of pre-roll history, newly buffered real-time frames (*rt_stream_update) need to be drained directly into the sink buffer before switching to HOST_COPY state so no frames are dropped at the history-to-realtime boundary. - Avoid forcefully setting kpb->sel_sink component state to COMP_STATE_ACTIVE on WOV_ARB_CMD_RESUME when selector copy was never paused by KPB. - Ensure host copier comp_copy is invoked after buffer production during drain bursts to update stream pointers in no-IRQ mode. - Prevent duplicate notifier registrations across prepare and reset cycles. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…port 32-bit audio - Implement wall-clock rate limiting (10ms) on phrase detection notifications to the host driver using sof_cycle_get_64() to prevent mailbox queue overflow and timeout during fast drain bursts. - Add support for 32-bit sample depth audio streams and channel/width conversion between 32-bit KPB drain buffers and host copier sinks. - In IPC4 mode, translate base module configuration to stream params directly via ipc4_base_module_cfg_to_stream_params(). Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…pins
- Add support for 32-bit sample formats across both output pins:
* Pin 0: Mono clean stream feeding 32-bit KPB circular buffer.
* Pin 1: Stereo clean stream feeding Host Copier 10 (supporting
S16_LE, S24_LE, S32_LE).
- Implement flexible sample width conversions between 16-bit and 32-bit
containers across input DMIC DAI copiers and downstream consumers.
- Ensure correct frame consumption tracking across active pins.
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…multi-slot WoV With 32-bit audio internalized across ECNS and KPB, the 2000ms KPB circular pre-roll history buffer requires 128KB of heap space. Instantiating 7 pipelines, 3 parallel microWakeWord instances, and 32-bit DMA buffers exceeded the default 256KB heap (resulting in buffer_alloc_range failures for DAI DMA buffers). Increase CONFIG_SOF_ZEPHYR_HEAP_SIZE to 0x80000 (512KB), matching intel_adsp_ace30_ptl.conf, and enable runtime heap statistics and arena sizing. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
- Update DMIC WoV feature and standalone PTL/WCL 4-channel manifests to internalize 32-bit audio data across DMIC DAI copier, ECNS, KPB, and WOV Arbiter pipelines. - Add S16_LE, S24_LE, and S32_LE multi-format capture capabilities on PCM 10 (ECNS) and PCM 11 (DMIC Multi-WOV). - Update prebuilt topology binaries for PTL and WCL in build/. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
- In wov_blocking_read, recover from -EPIPE on no-period-wakeup streams and retry active slot kcontrol query to ensure robust slot matching upon receiving audio. - In run_wov_10x.py, report subprogram stdout and stderr on test failure to aid rapid diagnosis. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Add PCAN (Per-Channel AGC Normalization) fixed-point math library for normalizing mel filterbank energies. PCAN estimates per-channel noise background, applies non-linear wide-dynamic-range AGC compression with fixed-point LUT gain lookup, and delivers scaled features for streaming keyword-spotting networks. Include ztest test suite with MATLAB reference models covering gain lookup, noise estimation, dynamic shrinking, stream processing, and corner cases. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Add 8-bit PCAN-normalized Mel feature extraction to the MFCC module. When CONFIG_COMP_MFCC_PCAN is enabled, MFCC applies Per-Channel Energy Normalization to its Mel filterbank outputs and quantizes the result to int8, matching microWakeWord input requirements. Ensure continuous frame delivery in compress mode by removing silence suppression from mfcc_output_compress(), as downstream streaming wake-word detectors require continuous feature hops without gaps. Update the MFCC setup tuning scripts and topology component configurations to provide 10 ms PCAN and non-PCAN configurations with VAD and DTX disabled. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Allow phrase detection modules to operate without an audio sink consumer. Detection modules emit event notifications rather than audio data streams. Guard against division by zero in module_adapter_calculate_dp_period() when sinks have no frame bytes or sample rate defined. Allow NULL sinks in module_adapter_prepare() when mod->max_sinks is zero, enabling event-only modules to prepare and run cleanly. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Update microWakeWord to consume 8-bit PCAN-normalized Mel features directly from the upstream MFCC module. Add built-in TFLM fruit model headers (strawberry, banana, orange) as well as hey_jarvis and hi_intel, and update the model loading and inference pipeline. Fix input data draining when paused by requesting available frames with source_get_data() before calling source_release_data(). Lower the warmup requirement and consecutive detect threshold to allow responsive detection. Clean up macro redefinitions in detect_test.c and update tuning scripts. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Add a Kconfig choice (CONFIG_ECNS_KPB_MONO_AVG_*) to select which input channels are averaged into the mono detection output sent to KPB. This allows boards where the first microphone pair is degraded to select the higher quality pair. Round and saturate 32-to-16 bit sample conversions so precision is preserved from the 32-bit detection path. Update output buffer format declarations to match topology requirements. Keep pin 0 (16 kHz detection) and pin 1 (48 kHz host) processing independent, and continuously drain unconsumed input pins when downstream consumer sinks are inactive or full to prevent DMIC hardware FIFO overflow. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
When downstream detector mixout buffers are full, KPB previously halted without buffering into its history ring or consuming from its source. This back-propagated full buffers upstream and froze the detection path. Consume available source frames and buffer them into the circular history buffer even if the selector sink has no free space. Forward samples to the selector sink when space is available, keeping both history recording and upstream data flow active. Remove the unused static function kpb_clear_history_buffer(). Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
…trol Setting wov_active_slot via kcontrol previously marked the chosen slot as active, transitioning the arbiter into draining mode and causing it to reject subsequent keyword detections. Leave the arbiter in listening mode (WOV_ARB_NO_ACTIVE) when setting a slot filter via kcontrol. The targeted slot remains armed while sibling slots are paused to reduce DSP load, allowing natural keyword detections to be accepted and processed. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
When a capture stream is starved or waiting for detection audio, logging every 20 ms floods the trace buffer and causes diagnostic log messages to be dropped. Increase SOF_MIN_NO_BYTES_INTERVAL_MS from 20 ms to 1000 ms so that trace transport bandwidth is conserved during idle capture periods. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Enable CONFIG_COMP_MFCC_PCAN, CONFIG_COMP_MWW_PCAN, and debug tracing on intel_adsp_cavs25, intel_adsp_cavs25_tgph, intel_adsp_ace30_ptl, and intel_adsp_ace30_wcl. On cavs25, select CONFIG_ECNS_KPB_MONO_AVG_CH_3_4 to average microphone channels 3 and 4 into the mono KPB output, avoiding degraded microphone pairs. Increase CONFIG_IDC_TIMEOUT_US to 100000 on cavs25 and cavs25_tgph to prevent secondary core bring-up timeouts during SMP boot. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
Configure dmic-wov-multi topologies and manifests to support 4-channel DMIC input on the detection path (dmic16k, eqiir, and ECNS pin 0) using 32-bit container formats. Offer the single 4-channel 32-bit input format matching the NHLT blob on dmic01, resolving channel duplication. Add conditional inclusion of 10 ms PCAN MFCC configuration blobs via IncludeByKey.MWW_PCAN. Update Brya targets in tplg-targets.cmake with DMIC_WOV_DAI_CHANNELS=4, and add a dmic16k 4-channel passthrough capture target for microphone diagnostics. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
When pipelines are cancelled via pipeline_schedule_cancel() during pause or stop triggers, sa_set_panic_on_delay() is called to enable panic on delay. In host testbench and library builds, the system agent timer is not initialized, leaving the sa pointer NULL. Add a NULL check in sa_set_panic_on_delay() before dereferencing the sa pointer so host testbench runs do not crash with a segmentation fault. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
When running host-testbench.sh inside containerized or snap-based editor environments, GTK_PATH may point to bundled GTK libraries from an older runtime environment. This can cause Octave to fail during startup with dynamic library symbol lookup errors. Unset GTK_PATH at the start of host-testbench.sh to prevent library path conflicts. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
…nces Lowering the startup warmup threshold previously allowed the model to evaluate detections on initial unprimed temporal buffer states during pipeline start. This produced a false trigger at t = 1s on startup transients before audio playback began. Restore MWW_WARMUP_INFERENCES to 33 inferences (~1 sec) and restore MWW_CONSECUTIVE_DETECTS_REQUIRED to 3 to align with training verification and suppress startup false triggers. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
mod_ipc_msg_w_ext_init() allocates the ipc_msg and its tx_data with mod_zalloc(), which uses SOF_MEM_FLAG_USER only and thus returns cached memory. Before the conversion the message was allocated with SOF_MEM_FLAG_COHERENT. msg->list is linked into the uncached ipc->msg_list by the module (possibly on a secondary core or DP thread) and unlinked by the IPC send worker on the primary core. With a cached msg the worker operates on stale list pointers, list_item_del() fails to unlink the message and the same notification is sent to the host over and over again. Allocate the message and its payload with SOF_MEM_FLAG_COHERENT, as it was done before. Fixes: 97dd710 ("ipc: make IPC message allocation userspace-safe") Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> (cherry picked from commit a5cb815) Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
…copy wov_arb_copy() resent SOF_IPC4_NOTIFY_PHRASE_DETECTED every 10ms (rate limited, but still continuous) for as long as a slot stayed active, i.e. for the entire remaining lifetime of the host PCM stream. This flooded the IPC mailbox and host dmesg (hundreds of notifications per capture) even though the notification has no functional purpose there: only a substream that actually opted into SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP depends on it to call snd_sof_pcm_period_elapsed(); a normal interrupt-driven capture is already woken by its regular hw pointer updates and ignores it. Drop the periodic resend and the last_notify_time throttle state it needed. PHRASE_DETECTED is now sent exactly once per detection, from arb_on_detect(), matching its role as a one-shot wake rather than a substitute for the host's own period-elapsed mechanism. Verified on DUT: arecord + wovdebug_111 trigger now produces exactly one notification (2 dmesg lines) instead of ~600 over a 5s capture, and the no-period-wakeup test tool (wov_blocking_read_tinyalsa) still unblocks immediately on trigger. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
The tinyalsa reader arms wovdebug_* before pcm_readi(). With start_threshold=1, tinyalsa may defer starting the PCM until that read, allowing the fake detection to race ahead of the host pipeline. Start the PCM explicitly before arming the control. PCM_NOIRQ is not needed for MMAP capture and makes tinyalsa wake on timed polls instead of normal period notifications. Drop it so the reader can wait for period wakeups. On the DUT, wovdebug_111 returned all 4000 frames with normal period wakeups in 0.258s. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
The alsa-lib capture tool opens the PCM in nonblocking mode and calls snd_pcm_wait() after EAGAIN. With no-period-wakeup set, it has neither regular period notifications nor a timed check of the hardware pointer. The wait times out even after a WoV trigger has made audio available. Leave period wakeups enabled so PCM readiness wakes the read loop. On the DUT, wovdebug_111 captured all 4000 frames in S0 and 8000 frames after a six-second idle delay. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Send one notification and drop the NO_PERIOD_WAKE from the tinyalsa / alsa-lib tools
The alsa-lib would break after 15s wait, it would need a polling thread to be able to work properly
The tinyalsa version was tight-loop polling in PCM_NOIRQ mode, which burns CPU. Waiting for period elapsed is better.