Skip to content

[CI TEST] audio, topology2: multi-slot Wake-on-Voice with PDM DMICs and D0i3 support - #11240

Draft
lgirdwood wants to merge 17 commits into
thesofproject:wcl-uaol-wov-002from
lgirdwood:wov-d0i3
Draft

lgirdwood wants to merge 17 commits into
thesofproject:wcl-uaol-wov-002from
lgirdwood:wov-d0i3

Conversation

@lgirdwood

Copy link
Copy Markdown
Member

Description

This PR introduces multi-slot Wake-on-Voice (WoV) with low-power D0i3 sleep/wake capability, hardware PDM DMIC input, and modular topology feature integration across Panther Lake (PTL), Wildcat Lake (WCL), and Tiger Lake (TGL).

Highlights

  1. Hardware PDM DMIC Wake-on-Voice:

    • Ensures WoV always connects to native 16 kHz 4-channel hardware PDM DMICs (dmic16k, DAI index 1) directly from the SoC PDM decimator, avoiding software resampling.
    • Co-exists with primary 48 kHz DMIC enhanced capture (dmic01) and external SoundWire microphones (Capture-SmartMic).
    • Generates and embeds complete ACPI NHLT tables with 48 kHz and 16 kHz hardware FIR/CIC filter coefficients in topology manifests.
  2. Multi-Slot WoV Pipeline Architecture:

    • ECNS DP Module (Pipeline 115): 20ms period, dual output pins (mono clean to KPB, stereo clean to PCM 10).
    • Keyphrase Buffer (Pipeline 116): 2000ms circular history buffer supporting multi-sink topology binding and drain streaming.
    • 3 Concurrent Detector Slots (Pipelines 111–113): Independent MFCC feature extraction + MicroWakeWord instances with 2 Hz scoring kcontrols.
    • WoV Arbiter (Pipeline 114): Multi-keyword arbitration, host notification on detection, and pre-roll drain triggering to PCM 11 (DMIC Multi-WOV).
  3. D0i3 Low-Power Sleep & Wake:

    • Flagged host copier on PCM 11 with capture_compatible_d0i3 1 to maintain low-power DSP SRAM retention across host S0ix sleep.
    • Added D0ix state notifier to IPC4 pipeline handler to manage COMP_STATE_PREPARE and suppress telemetry during D0i3.
    • Switched MicroWakeWord op resolver and interpreter to static storage to eliminate heap allocation leaks across sleep/wake cycles.
  4. Topology Integration & Modularity:

    • Added dmic-wov-feature.conf allowing multi-slot WoV to be included as a feature module into functional topologies (INCLUDE_WOV=multi).
    • Integrated and validated functional SoundWire topologies: sof-ptl-rt721-4ch-wov-multi, sof-ptl-rt722-4ch-wov-multi, and WCL equivalents.
    • Aligned WCL topologies with verified PTL topologies.
  5. Toolchain & Compiler Fixes:

    • Fixed Xtensa CALL8 out-of-range relocation in the libc shim by unifying .text section placement.
    • Conditionally compile ibuffer_allocator.cc to support both upstream TFLM and trees carrying Xtensa ICF vtable fixes.
    • Disabled USB Audio Offload (UAOL) by default to prevent interference during WoV validation.

Validation

  • Panther Lake Silicon (Aphid):
    • Verified 10/10 consecutive S0ix/D0i3 sleep/wake cycles with test_start and wov_blocking_read.
    • Verified multi-slot keyword detection and 2-second audio history drain.
    • Verified clean DMIC ECNS capture on PCM 10.
  • Topology Verification:
    • Compiled and verified topologies for PTL, WCL, and TGL via alsatplg.
    • Inspected binary structures to confirm BE DAI link IDs match kernel machine driver enumeration.

@lgirdwood lgirdwood changed the title audio, topology2: multi-slot Wake-on-Voice with PDM DMICs and D0i3 support [CI TEST] audio, topology2: multi-slot Wake-on-Voice with PDM DMICs and D0i3 support Sep 26, 2026
@lgirdwood

Copy link
Copy Markdown
Member Author

@naveen-manohar @harajend @bardliao @ujfalusi this is just for testing on the CI, it has a lot of patches not for upstream, just for debug. Will allow us to roll out WOV test alongside other WOV PR in flow.

@naveen-manohar

Copy link
Copy Markdown
Contributor

Thanks @lgirdwood
seems drc can be removed
[ 12.990644] sof-audio-pci-intel-ptl 0000:00:1f.3: failed to find module info for widget drc.100.1 with UUID B36EE4DA-006F-47F9-A06D-FECBE2D8B6CE

…overy

Support building microWakeWord with external or dynamic toolchain configurations
where libc.a / libm.a archive layouts differ between Xtensa toolchain versions.
Specifically:
- Check for XTENSA_SYSTEM libc archive path when not found in standard Zephyr paths.
- Check libc archive member names to extract either Newlib (lib_a-*.o) or standard
  libc/libm members into the shim archive.
- Run mww_shim_flatten.py to flatten .text.* and .literal.* sections into .text
  and .literal to prevent CALL8 out-of-range relocation overflows.
- Enable -mlongcalls and -mtext-section-literals on Xtensa architecture builds.
- Conditionally include ibuffer_allocator.cc when present in the TFLM tree.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
tlv_value_set_uaol_caps() set link_count to the devicetree device count
unconditionally and indexed link_caps[] by device index, so a link whose
uaol_get_capabilities() call failed was still advertised to the host as a
present link with all-zero capabilities.

That matters now that the driver rejects the query when the host has not
set UAOLCTL.OFLEN: without this, a firmware that cannot read any link
still reports link_count = 1 with zeroed stream counts and FIFO sizes.

Count only the links that answered, pack them from index 0, and size the
TLV to match.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
… on IPC4

kpb.c drives both a sel_sink (buf_id 0, the real-time feed to detectors)
and a host_sink (buf_id 1, the drain that bursts pre-roll to the host).
Declare two sink pins in kpb.toml so the drain path can be bound from
topology.

Additionally, under IPC4 pipeline state transitions and resets are
synchronous; returning -EBUSY on reset breaks the host teardown state
machine and causes widget free failures. Guard the deferred -EBUSY
drain check under #if !CONFIG_IPC_MAJOR_4.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Add NOTIFIER_ID_D0IX_STATE to notify registered DSP components when the host
changes the DSP D0 substate via SOF_IPC4_MOD_SET_D0IX.

Components such as microWakeWord that keep running while the host sleeps in
S0iX / D0i3 can use this event to adjust telemetry reporting or power
characteristics.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
When source or sink component is not a processing_module (such as a host
copier or non-module comp_dev), comp_mod() returns NULL.
Safely guard src_module_data and dst_module_data before accessing
mpd.in_buff_size and mpd.out_buff_size to prevent NULL pointer dereferences
when configuring DP ring buffers.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Hostless internal pipelines (such as background keyword detection or
internal audio processing chains that feed an arbiter or buffer without
a host copier) do not have a host dev.

Allow ipc4_pipeline_prepare() and ipc4_pipeline_trigger() to operate
on pipelines where host is NULL by falling back to source_comp or
sink_comp. Furthermore, allow stopping pipelines that are currently in
COMP_STATE_PREPARE.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…drain streaming

Improve the WoV Arbiter component:
- Host Notification: send IPC4 notification to host upon keyword detection
  and periodically during pre-roll buffer drain.
- Active Slot Reset: reset active_slot to WOV_ARB_NO_ACTIVE and notify host/kcontrols
  on stream stop, reset, and free. Also emit WOV_ARB_CMD_RESUME to unpause detectors.
- Drain Streaming: ensure the arbiter only produces data when an active slot is
  triggered, leaving the host PCM idle/blocked during low-power listening so the
  platform can enter D0i3.
- Update wov_arbiter README documentation.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Adapt the ECNS module to support the dual-rate DMIC architecture:
- Input pin 0: 16 kHz stream from dmic16k (up to 320 frames per 20ms period).
  Extracts left channel to mono output pin 0 feeding KPB.
- Input pin 1: 48 kHz stream from dmic01 (up to 960 frames per 20ms period).
  Copies stereo 48 kHz output to pin 1 feeding Host Copier PCM 11.
- Operates in 20ms DP mode with independent buffer tracking per pin.
- Update ECNS header and README documentation.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…ter to fix heap leak

TFLite Micro defines TF_LITE_REMOVE_VIRTUAL_DELETE on MicroMutableOpResolver,
which expands to a no-op 'void operator delete(void* p) {}'. Consequently,
calling 'delete inst->op_resolver' in MWW_Free() never returned the memory
to the heap, leaking ~600 bytes per slot on every stream open/close cycle.
Across multi-slot configurations (3 detector slots), repeated stream cycles
exhausted the DSP system heap, failing on run 10 with -ENOMEM in
MWW_InitOps() and returning -22 (IPC4_INVALID_REQUEST) to snd_pcm_start().

Eliminate heap allocations from MWW model initialization by allocating
both MwwOpResolver and MicroInterpreter in aligned static storage using
placement new and explicit destructor invocation.

Verified with 10 consecutive D0i3 sleep-and-wake test cycles on Panther Lake
hardware (Aphid), achieving 10/10 passes with zero errors.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…er controls

Add power and testing enhancements to microWakeWord:
- D0i3 Power State: listen for NOTIFIER_ID_D0IX_STATE and suppress score
  telemetry notifications while the host is in D0i3 to prevent spurious
  wakeups.
- Test Trigger Controls: implement SOF_IPC4_SWITCH_CONTROL_PARAM_ID to expose
  a volatile 'wovdebug' switch kcontrol per slot. Setting this control arms
  a fake wake timer (MWW_FAKE_WAKE_DELAY_MS) that triggers a keyword detect
  event and automatically resets the control upon firing.
- Add CONFIG_MICROWAKEWORD_FAKE_WAKE and app/wov-d0i3-fake-wake.conf test overlay.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Disable UAOL on Intel ADSP targets in boards/intel_adsp/Kconfig.defconfig
(default n).

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…odules

Functional and feature topologies (such as SoundWire RT721/RT722 and DMIC
pipelines) require open audio processing components like DRC, TDFB,
Multiband DRC, Aria, and MUX.

Ensure these modules are enabled in both PTL and WCL board configurations
and module overlays so they are built into sof-ptl-openmodules.ri and
sof-wcl-openmodules.ri.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…slot WoV pipelines

Implement the dual-rate DMIC topology architecture with multi-slot WoV:
- Provide dual PDM DAI endpoints:
  - dmic01 on PDM0: 48 kHz stereo 16-bit
  - dmic16k on PDM1: 16 kHz stereo 16-bit
- Connect dmic16k into ECNS (pin 0) and dmic01 into ECNS (pin 1).
- Connect ECNS output pin 0 (16k mono clean) to KPB and multi-slot WoV
  detectors (slots 0-2: OK Google, Alexa, Hey Jarvis), feeding WoV Arbiter
  and Host Copier PCM 12 (16 kHz mono WoV capture).
- Connect ECNS output pin 1 (48k stereo clean) to Host Copier PCM 11
  (48 kHz stereo capture).
- Remove deprecated raw PCM 10 host copier.
- Add volatile wovdebug switch controls and score enum controls per slot.
- Set capture_compatible_d0i3 to true on WoV PCMs.
- Update 4ch and multi manifests for PTL, WCL, and generic Intel platforms.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…topologies

Integrate the multi-slot WoV pipelines and feature flags into SoundWire
and HDA topologies:
- Wire multi-slot WoV feature inclusion into cavs-sdw.conf, cavs-rt5682.conf,
  and sof-hda-generic.conf.
- Ensure Speaker and other primary PCMs are preserved when WoV features are
  instantiated.
- Add CMake topology build targets for Panther Lake (PTL) ACE 3.0, Wildcat Lake
  (WCL), and Tiger Lake (TGL) with multi-slot WoV SoundWire and HDA targets
  in production and development CMake files.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…PTL, TGL, and WCL

Provide prebuilt topology binary files for quick testing and hardware bring-up:
- build/sof-ptl-dmic-wov-multi-4ch.tplg
- build/sof-tgl-dmic-wov-multi-4ch.tplg
- build/sof-wcl-dmic-wov-multi-4ch.tplg

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Add test utilities for verifying Wake-on-Voice capture pipelines:
- wov_blocking_read.c: alsa-lib utility that opens the WoV capture PCM
  in blocking read mode with SND_PCM_NO_IRQ_WAITEVENT or mmap to ensure
  the driver does not generate periodic IRQs during listening.
- wov_blocking_read_tinyalsa.c: TinyALSA version of the blocking reader.
- test_wov_no_irq.py: automated test runner validating WoV capture and wake
  across all slots in S0 and D0i3 (idle suspend) states.
- Makefile: build targets for wov_blocking_read and wov_blocking_read_tinyalsa.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
…i3 verification

Comprehensive documentation updates for multi-slot Wake-on-Voice and dual-rate DMIC:
- tools/topology/topology2/README.md:
  - Document complete pipeline architecture and DMIC routing diagrams.
  - Document dual-rate DMIC PDM DAI structure (dmic01 @ 48k, dmic16k @ 16k).
  - Document ECNS 20ms DP processing and pin mappings.
  - Document KPB circular buffering, pre-roll drain, and WoV Arbiter slot routing.
  - Document multi-slot WoV detector pipeline (OK Google, Alexa, Hey Jarvis).
  - Document PCM endpoints: PCM 11 (48k stereo clean), PCM 12 (16k mono WoV).
  - Add build steps with alsatplg and verification runbooks.
- doc/developer_guides/wov_ecns_integration_guide.md:
  - Update integration guide with dual-rate DMIC architecture and D0i3 verification.
- README.md:
  - Update top-level README with microWakeWord and WoV documentation references.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants