From f22c5751f8bf8f4b772263d890f47fdf0af6c192 Mon Sep 17 00:00:00 2001 From: SurajSonawane2415 Date: Thu, 31 Jul 2025 22:23:07 +0530 Subject: [PATCH 1/3] dai: Add support for Virtual DAI on i.MX8MP Introduce a new DAI type, SOF_DAI_VIRTUAL, to enable rapid prototyping, software loopback, and testing without requiring physical DAI hardware. Define the IPC config structure for the virtual DAI and update the Zephyr DAI mapping logic to recognize and configure this backend. Enable virtual DAI for i.MX8MP to support software-based audio pipelines. Signed-off-by: Suraj Sonawane --- src/audio/dai-zephyr.c | 4 ++++ src/include/ipc/dai.h | 25 ++++++++++++++++++++++++- src/ipc/ipc3/dai.c | 4 ++++ src/lib/dai.c | 5 +++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c index 0512b92abc87..c24de01debfb 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -194,6 +194,10 @@ __cold int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config, cfg.type = DAI_IMX_MICFIL; cfg_params = &sof_cfg->micfil; break; + case SOF_DAI_VIRTUAL: + cfg.type = DAI_VIRTUAL; + cfg_params = &sof_cfg->virtual_dai; + break; default: return -EINVAL; } diff --git a/src/include/ipc/dai.h b/src/include/ipc/dai.h index b5b29316f9e6..1d86f8173962 100644 --- a/src/include/ipc/dai.h +++ b/src/include/ipc/dai.h @@ -94,9 +94,31 @@ enum sof_ipc_dai_type { SOF_DAI_AMD_SP_VIRTUAL, /**dai, dai->direction, dd->stream_id); + case SOF_DAI_VIRTUAL: + handshake = dai_get_handshake(dd->dai, dai->direction, + dd->stream_id); /* TODO: remove this when transition to native drivers is complete on all NXP platforms */ #ifndef CONFIG_ZEPHYR_NATIVE_DRIVERS channel = EDMA_HS_GET_CHAN(handshake); @@ -171,6 +174,7 @@ int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev) case SOF_DAI_IMX_MICFIL: case SOF_DAI_IMX_SAI: case SOF_DAI_IMX_ESAI: + case SOF_DAI_VIRTUAL: dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction); break; case SOF_DAI_AMD_BT: diff --git a/src/lib/dai.c b/src/lib/dai.c index c4daf2b06918..b90d1fe6c555 100644 --- a/src/lib/dai.c +++ b/src/lib/dai.c @@ -185,6 +185,9 @@ const struct device *zephyr_dev[] = { #if CONFIG_DAI_NXP_MICFIL DT_FOREACH_STATUS_OKAY(nxp_dai_micfil, GET_DEVICE_LIST) #endif +#if CONFIG_DAI_VIRTUAL + DT_FOREACH_STATUS_OKAY(virtual_dai, GET_DEVICE_LIST) +#endif }; /* convert sof_ipc_dai_type to Zephyr dai_type */ @@ -218,6 +221,8 @@ static int sof_dai_type_to_zephyr(uint32_t type) case SOF_DAI_AMD_HS_VIRTUAL: case SOF_DAI_AMD_SW_AUDIO: return -ENOTSUP; + case SOF_DAI_VIRTUAL: + return DAI_VIRTUAL; default: return -EINVAL; } From 67398e1fccd6ad8ad4b17bf453ca92dd2a2a4e1c Mon Sep 17 00:00:00 2001 From: SurajSonawane2415 Date: Fri, 22 Aug 2025 15:28:32 +0530 Subject: [PATCH 2/3] topology1: Add support for Virtual DAI for i.MX8 Add a new topology file for i.MX8 platforms that enables Virtual DAI support, allowing software-based audio pipelines without physical DAI hardware. Signed-off-by: Suraj Sonawane --- tools/topology/topology1/CMakeLists.txt | 1 + tools/topology/topology1/m4/dai.m4 | 2 +- .../topology1/platform/common/virtual-dai.m4 | 45 ++++++++++++ tools/topology/topology1/sof-imx8-virtual.m4 | 71 +++++++++++++++++++ tools/topology/topology1/sof/tokens.m4 | 4 ++ .../topology2/include/common/tokens.conf | 5 ++ 6 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 tools/topology/topology1/platform/common/virtual-dai.m4 create mode 100644 tools/topology/topology1/sof-imx8-virtual.m4 diff --git a/tools/topology/topology1/CMakeLists.txt b/tools/topology/topology1/CMakeLists.txt index c6ae06d0be04..0c77ef6afbe5 100644 --- a/tools/topology/topology1/CMakeLists.txt +++ b/tools/topology/topology1/CMakeLists.txt @@ -71,6 +71,7 @@ set(TPLGS "sof-imx8mp-compr-pcm-cap-wm8960\;sof-imx8mp-compr-pcm-cap-wm8960" "sof-imx8mp-compr-wm8960\;sof-imx8mp-compr-wm8960\;-DCODEC=wm8960\;-DRATE=48000" "sof-imx8mp-compr-wm8960\;sof-imx8mp-compr-wm8962\;-DCODEC=wm8962\;-DRATE=48000" + "sof-imx8-virtual\;sof-imx8-virtual" ## end i.MX8MP topologies ## i.MX8ULP topologies diff --git a/tools/topology/topology1/m4/dai.m4 b/tools/topology/topology1/m4/dai.m4 index cd968c6c61fd..5ae7aac24f03 100644 --- a/tools/topology/topology1/m4/dai.m4 +++ b/tools/topology/topology1/m4/dai.m4 @@ -155,7 +155,7 @@ define(`DO_DAI_CONFIG', `' ` id "'$3`"' `' -` ifelse($1, `SSP', $5, $1, `HDA', $5, $1, `ALH', $5, $1, `ESAI', $5, $1, `SAI', $5, $1, `MICFIL', $5, $1, `AFE', $5, $1, `ACP', $5, $1, `ACPSP', $5, $1,`ACPSP_VIRTUAL', $5, $1, `ACPHS', $5, $1, `ACPHS_VIRTUAL', $5, $1, `ACP_SDW', $5, $1, `ACPDMIC', $5, `}')' +` ifelse($1, `SSP', $5, $1, `HDA', $5, $1, `ALH', $5, $1, `ESAI', $5, $1, `SAI', $5, $1, `MICFIL', $5, $1, `AFE', $5, $1, `ACP', $5, $1, `ACPSP', $5, $1,`ACPSP_VIRTUAL', $5, $1, `ACPHS', $5, $1, `ACPHS_VIRTUAL', $5, $1, `ACP_SDW', $5, $1, `ACPDMIC', $5, $1, `DAI_VIRTUAL', $5, `}')' `ifelse($1, `DMIC', $5, `')' `SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples_common" {' ` tokens "sof_dai_tokens"' diff --git a/tools/topology/topology1/platform/common/virtual-dai.m4 b/tools/topology/topology1/platform/common/virtual-dai.m4 new file mode 100644 index 000000000000..7c12f9a85f42 --- /dev/null +++ b/tools/topology/topology1/platform/common/virtual-dai.m4 @@ -0,0 +1,45 @@ +divert(-1) + +dnl Virtual DAI related macros + +dnl DAI_VIRTUAL_CLOCK(clock, freq, codec_provider, polarity) +dnl polarity is optional +define(`DAI_VIRTUAL_CLOCK', + $1 STR($3) + $1_freq STR($2)) + `ifelse($4, `inverted', `$1_invert "true"',`')') + +dnl DAI_VIRTUAL_TDM(slots, width, tx_mask, rx_mask) +define(`DAI_VIRTUAL_TDM', +` tdm_slots 'STR($1) +` tdm_slot_width 'STR($2) +` tx_slots 'STR($3) +` rx_slots 'STR($4) +) + +dnl DAI_VIRTUAL_CONFIG(format, mclk, bclk, fsync, tdm, config_data) +define(`DAI_VIRTUAL_CONFIG', +` format "'$1`"' +` '$2 +` '$3 +` '$4 +` '$5 +`}' +$6 +) + +dnl DAI_VIRTUAL_CONFIG_DATA(type, idx, dummy_id) +dnl dummy_id is optional +define(`DAI_VIRTUAL_CONFIG_DATA', +`SectionVendorTuples."'N_DAI_CONFIG($1$2)`_tuples" {' +` tokens "sof_virtual_tokens"' +` tuples."short" {' +` SOF_TKN_DAI_VIRTUAL_MCLK_ID' ifelse($3, `', "0", STR($3)) +` }' +`}' +`SectionData."'N_DAI_CONFIG($1$2)`_data" {' +` tuples "'N_DAI_CONFIG($1$2)`_tuples"' +`}' +) + +divert(0)dnl diff --git a/tools/topology/topology1/sof-imx8-virtual.m4 b/tools/topology/topology1/sof-imx8-virtual.m4 new file mode 100644 index 000000000000..2cfbfd449c61 --- /dev/null +++ b/tools/topology/topology1/sof-imx8-virtual.m4 @@ -0,0 +1,71 @@ +# +# Topology for i.MX8 board using Virtual DAI (no physical codec) +# + +# Include topology builder +include(`utils.m4') +include(`dai.m4') +include(`pipeline.m4') +include(`virtual-dai.m4') +include(`pcm.m4') +include(`buffer.m4') + +# Include TLV library +include(`common/tlv.m4') + +# Include Token library +include(`sof/tokens.m4') + +# Include DSP configuration +include(`platform/imx/imx8.m4') + +# +# Define the pipelines +# +# PCM0 ---> Volume ---> Virtual DAI0 (NoCodec) +# + +dnl PIPELINE_PCM_ADD(pipeline, +dnl pipe id, pcm, max channels, format, +dnl period, priority, core, +dnl pcm_min_rate, pcm_max_rate, pipeline_rate, +dnl time_domain, sched_comp) + +# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le +PIPELINE_PCM_ADD(sof/pipe-volume-playback.m4, + 1, 0, 2, s32le, + 1000, 0, 0, + 8000, 96000, 48000) + +# +# DAIs configuration +# + +dnl DAI_ADD(pipeline, +dnl pipe id, dai type, dai_index, dai_be, +dnl buffer, periods, format, +dnl deadline, priority, core, time_domain) + +DAI_ADD(sof/pipe-dai-playback.m4, + 1, DAI_VIRTUAL, 7, NoCodec-0, + PIPELINE_SOURCE_1, 2, s32le, + 1000, 0, 0, SCHEDULE_TIME_DOMAIN_TIMER) + +# +# PCM interface +# + +dnl PCM_PLAYBACK_ADD(name, pcm_id, playback) +PCM_PLAYBACK_ADD(Port0, 0, PIPELINE_PCM_1) + +# +# DAI Configuration +# + +dnl DAI_CONFIG(type, dai_index, link_id, name, config) +DAI_CONFIG(DAI_VIRTUAL, 7, 0, NoCodec-0, + DAI_VIRTUAL_CONFIG(I2S, DAI_VIRTUAL_CLOCK(mclk, 0, dai_provider), + DAI_VIRTUAL_CLOCK(bclk, 0, dai_provider), + DAI_VIRTUAL_CLOCK(fsync, 0, dai_provider), + DAI_VIRTUAL_TDM(2, 32, 3, 3), + DAI_VIRTUAL_CONFIG_DATA(DAI_VIRTUAL, 7, 0))) diff --git a/tools/topology/topology1/sof/tokens.m4 b/tools/topology/topology1/sof/tokens.m4 index b9748bb52fbc..6b2951934326 100644 --- a/tools/topology/topology1/sof/tokens.m4 +++ b/tools/topology/topology1/sof/tokens.m4 @@ -157,3 +157,7 @@ SectionVendorTokens."sof_acp_sdw_tokens" { SOF_TKN_AMD_ACP_SDW_SAMPLERATE "2100" SOF_TKN_AMD_ACP_SDW_CH "2101" } + +SectionVendorTokens."sof_virtual_tokens" { + SOF_TKN_DAI_VIRTUAL_MCLK_ID "2102" +} diff --git a/tools/topology/topology2/include/common/tokens.conf b/tools/topology/topology2/include/common/tokens.conf index d1b986ab01d4..80c907d84b5d 100644 --- a/tools/topology/topology2/include/common/tokens.conf +++ b/tools/topology/topology2/include/common/tokens.conf @@ -190,4 +190,9 @@ Object.Base.VendorToken { node_type 1980 deep_buffer_dma_ms 1981 } + + "19" { + name "dai_virtual" + mclk_id 2102 + } } From dace2065cc6317433ad54420bd491b5e0f6946ff Mon Sep 17 00:00:00 2001 From: SurajSonawane2415 Date: Fri, 22 Aug 2025 15:28:59 +0530 Subject: [PATCH 3/3] zephyr: Use emul_dma for Virtual DAI on i.MX8MP Add emul_dma configuration to enable Virtual DAI with memory-to-memory DMA for software-based audio pipelines on i.MX8MP. Signed-off-by: Suraj Sonawane --- app/boards/imx8mp_evk_mimx8ml8_adsp.overlay | 4 ++++ src/audio/dai-zephyr.c | 4 ++++ zephyr/include/sof/lib/dma.h | 1 + zephyr/lib/dma.c | 11 +++++++++++ 4 files changed, 20 insertions(+) diff --git a/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay b/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay index 6748b621985a..773fecc25bdb 100644 --- a/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay +++ b/app/boards/imx8mp_evk_mimx8ml8_adsp.overlay @@ -12,6 +12,10 @@ }; }; +&emul_dma { + status = "okay"; +}; + &sdma3 { status = "okay"; }; diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c index c24de01debfb..836763314601 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -496,8 +496,12 @@ __cold int dai_common_new(struct dai_data *dd, struct comp_dev *dev, dd->ipc_config = *dai_cfg; /* request GP LP DMA with shared access privilege */ +#if CONFIG_DAI_VIRTUAL + dir = SOF_DMA_DIR_MEM_TO_MEM; +#else dir = dai_cfg->direction == SOF_IPC_STREAM_PLAYBACK ? SOF_DMA_DIR_MEM_TO_DEV : SOF_DMA_DIR_DEV_TO_MEM; +#endif dd->dma = sof_dma_get(dir, dd->dai->dma_caps, dd->dai->dma_dev, SOF_DMA_ACCESS_SHARED); if (!dd->dma) { diff --git a/zephyr/include/sof/lib/dma.h b/zephyr/include/sof/lib/dma.h index 1b384412b123..4e5b31d4ae7d 100644 --- a/zephyr/include/sof/lib/dma.h +++ b/zephyr/include/sof/lib/dma.h @@ -99,6 +99,7 @@ struct comp_dev; #define SOF_DMA_DEV_HS BIT(13) /**< connectable to ACP HS I2S */ #define SOF_DMA_DEV_MICFIL BIT(14) /**< connectable to MICFIL fifo */ #define SOF_DMA_DEV_SW BIT(15) /**< connectable to ACP SW */ +#define SOF_DMA_DEV_DAI_VIRTUAL BIT(16) /**< connectable to Virtual DAI */ /* DMA access privilege flag */ #define SOF_DMA_ACCESS_EXCLUSIVE 1 diff --git a/zephyr/lib/dma.c b/zephyr/lib/dma.c index c72e26cf57cf..4cb521bcf1dc 100644 --- a/zephyr/lib/dma.c +++ b/zephyr/lib/dma.c @@ -151,6 +151,17 @@ SHARED_DATA struct sof_dma dma[] = { }, #endif #if defined(CONFIG_SOC_MIMX8ML8_ADSP) +#if CONFIG_DAI_VIRTUAL +{ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_MEM, + .devs = SOF_DMA_DEV_DAI_VIRTUAL, + .channels = 32, + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(emul_dma)), +}, +#endif /* CONFIG_DAI_VIRTUAL */ { .plat_data = { .dir = SOF_DMA_DIR_MEM_TO_DEV | SOF_DMA_DIR_DEV_TO_MEM,