dai: Add support for Virtual DAI for rapid prototyping and software loopback
This PR is part of the GSoC 2025 Project: Add Virtual DAI Component to SOF and is based on SOF Issue #9349.
We introduce a new SOF_DAI_VIRTUAL type and its associated support to enable audio pipelines that do not rely on physical DAI hardware. This is useful in the following scenarios:
- Debugging and rapid prototyping: Quickly create and test audio pipelines without needing actual hardware.
- Software loopback preparation: Lays the groundwork for a memory-to-memory audio pipeline within SOF.
Virtual DAI Behavior
- Playback: Acts like
/dev/null— consumes data from the source and logs or discards it. - Capture: Acts like
/dev/zero— generates dummy data (currently zero-filled) and passes it to the sink.
Key Changes
- Added Virtual DAI support on i.MX8MP
- Added a new DAI type SOF_DAI_VIRTUAL for rapid prototyping and software loopback.
- Defined IPC config structure and updated Zephyr DAI mapping for Virtual DAI recognition.
- Enabled software-based audio pipelines without requiring physical DAI hardware.
- Topology support for i.MX8
- Introduced a new topology file enabling Virtual DAI on i.MX8 platforms.
- DMA configuration update
- Integrated emul_dma to enable Virtual DAI functionality on i.MX8MP.
- Allows playback/record flows in the absence of real hardware DMA.
Testing
- Platform: i.MX8MP EVK with Virtual DAI topology.
- Environment: Zephyr-based SOF build.
- Results:
- NoCodec card + Virtual DAI detected.
- Probe, config, and removal flows working as expected.
- All test cases executed successfully, all tests passed
Logs:
*** Booting Zephyr OS build 6e3ea447cbfb ***
[00:00:00.046,014] <inf> main: SOF on imx8mp_evk
[00:00:00.051,043] <inf> main: SOF initialized
[00:00:00.055,909] <inf> ipc: ipc: new cmd 0x90030000
[00:00:00.061,749] <inf> ipc: ipc: new cmd 0x30100000
[00:00:00.066,973] <inf> pipe: pipeline new pipe_id 1 priority 0
[00:00:00.074,086] <inf> ipc: ipc: new cmd 0x30010000
[00:00:00.079,312] <inf> ipc: comp new 0x924549b4U type 2 id 1.4
[00:00:00.085,734] <inf> dai_comp: DAIZ: dai_new()
[00:00:00.090,941] <inf> dai_comp: DAIZ: dai_common_new()
[00:00:00.096,757] <inf> virtual_dai: virtual_dai_config_get
[00:00:00.102,833] <inf> virtual_dai: virtual_dai_probe
[00:00:00.108,476] <inf> dma: sof_dma_get: dir=0, cap=0x0, dev=0x0, flags=0x0
[00:00:00.116,028] <inf> dma: dma_init
[00:00:00.120,198] <inf> dma: sof_dma_get(): Final selection -> ID 0, sref=1, busy=0
[00:00:00.129,043] <inf> ipc: ipc: new cmd 0x80010000
[00:00:00.134,266] <inf> ipc: ipc: dai 16.7 -> config
[00:00:00.139,820] <inf> virtual_dai: virtual_dai_config_get
[00:00:00.145,896] <inf> virtual_dai: virtual_dai_probe
[00:00:00.151,539] <inf> dai_comp: DAIZ: dai_set_config()
[00:00:00.157,354] <inf> virtual_dai: virtual_dai_config_set
[00:00:00.163,429] <inf> virtual_dai: virtual_dai_remove
[00:00:00.169,163] <inf> ipc: ipc_comp_dai_config() dai type = 16 index = 7
[00:00:00.176,541] <inf> ipc: comp:1.4 dai_config() dai type = 16 index = 7 dd 0x92c05ee0
[00:00:00.185,132] <inf> dai_comp: DAIZ: dai_get_handshake()
[00:00:00.191,208] <inf> virtual_dai: virtual_dai_get_properties
Related PR & Commits
-
Zephyr PR: #95233 drivers: dai: Add virtual DAI driver and tests
Includes Virtual DAI driver, DTS binding, Kconfig/CMake updates, and ztest-based API tests. -
linux-imx PR: #30 ASoC: SOF: Add Virtual DAI support for i.MX8M
IntroducesSOF_DAI_VIRTUALtype and configuration, adds topology tokens, extends IPC3 parsing, and registers a Virtual DAI backend for i.MX8M. Enables prototyping and loopback pipelines without physical DAI hardware. -
linux-imx nocodec feature commit: Enabled NoCodec support for the i.MX8M platform to allow pipeline testing without real codecs.
Link: nocodec-commit
Future Work
- Implement playback and record:
- Playback: log output frames and discard.
- Record: generate frames filled with zeroes.
(Current limitation: To get
aplayandarecordworking, I replaced the real DMA withemul_dmafor Virtual DAI. All functions execute, but data is not being copied indma_emul_work_handlerduring playback.)