From 5fc436001f587a63bdac57a6a8611e60e0c2fd2e Mon Sep 17 00:00:00 2001 From: Sivasubramanian678 Date: Tue, 5 May 2026 18:27:56 +0530 Subject: [PATCH] acp: add TDM DAI and DMA support for ACP 7.0 Add TDM DAI and DMA support for the AMD ACP 7.0 platform with three instances: HS, SP, and BT. Signed-off-by: Siva Subramanian Ravi Saravanan --- app/boards/acp_7_0_adsp.conf | 2 ++ src/audio/dai-zephyr.c | 8 ++++++++ src/include/ipc/dai-amd.h | 1 + src/include/ipc/dai.h | 3 ++- src/ipc/ipc3/dai.c | 31 ++++++++++++++++++++++++------- src/lib/dai.c | 25 ++++++++++++++++++------- zephyr/lib/dma.c | 13 +++++++++++++ 7 files changed, 68 insertions(+), 15 deletions(-) diff --git a/app/boards/acp_7_0_adsp.conf b/app/boards/acp_7_0_adsp.conf index 3c5f791fdcb6..3f170d8a5a8c 100644 --- a/app/boards/acp_7_0_adsp.conf +++ b/app/boards/acp_7_0_adsp.conf @@ -14,6 +14,8 @@ CONFIG_INTC_AMD_ACP=y CONFIG_DMA_AMD_ACP_HOST=y CONFIG_DMA_AMD_ACP_SDW=y CONFIG_DAI_AMD_SDW=y +CONFIG_DMA_AMD_ACP_TDM=y +CONFIG_DAI_AMD_TDM=y CONFIG_AMS=n CONFIG_WRAP_ACTUAL_POSITION=y CONFIG_TRACE=n diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c index 19e1ccd58eec..5ea079da6095 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -196,6 +196,14 @@ __cold int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config, cfg.type = DAI_AMD_SDW; cfg_params = &sof_cfg->acpsdw; break; + case SOF_DAI_AMD_HS: + case SOF_DAI_AMD_HS_VIRTUAL: + case SOF_DAI_AMD_SP: + case SOF_DAI_AMD_SP_VIRTUAL: + case SOF_DAI_AMD_BT: + cfg.type = DAI_AMD_TDM; + cfg_params = &sof_cfg->acptdm; + break; case SOF_DAI_INTEL_UAOL: cfg.type = DAI_INTEL_UAOL; cfg.channels = common_config->gtw_fmt->channels_count; diff --git a/src/include/ipc/dai-amd.h b/src/include/ipc/dai-amd.h index ceeb870c163e..b167f03eed7e 100644 --- a/src/include/ipc/dai-amd.h +++ b/src/include/ipc/dai-amd.h @@ -23,6 +23,7 @@ struct sof_ipc_dai_acp_params { uint32_t reserved0; uint32_t fsync_rate; uint32_t tdm_slots; + uint32_t tdm_mode; } __attribute__((packed, aligned(4))); /* ACP Configuration Request - SOF_IPC_DAI_AMD_SDW_CONFIG */ diff --git a/src/include/ipc/dai.h b/src/include/ipc/dai.h index dfc2a3e9ffb0..49ffa5d5fa94 100644 --- a/src/include/ipc/dai.h +++ b/src/include/ipc/dai.h @@ -97,6 +97,7 @@ enum sof_ipc_dai_type { SOF_DAI_IMX_MICFIL, /**< i.MX MICFIL */ SOF_DAI_AMD_SDW, /**< Amd SDW */ SOF_DAI_INTEL_UAOL, /**< Intel UAOL */ + SOF_DAI_AMD_TDM /**< Amd TDM */ }; #define SOF_DAI_CONFIG_HW_SPEC_OFFSET offsetof(struct sof_ipc_dai_config, ssp) @@ -126,7 +127,7 @@ struct sof_ipc_dai_config { struct sof_ipc_dai_acp_params acpbt; struct sof_ipc_dai_acp_params acpsp; struct sof_ipc_dai_acpdmic_params acpdmic; - struct sof_ipc_dai_acp_params acphs; + struct sof_ipc_dai_acp_params acptdm; struct sof_ipc_dai_afe_params afe; struct sof_ipc_dai_micfil_params micfil; struct sof_ipc_dai_acp_sdw_params acpsdw; diff --git a/src/ipc/ipc3/dai.c b/src/ipc/ipc3/dai.c index c2faa73163d8..600c052969cd 100644 --- a/src/ipc/ipc3/dai.c +++ b/src/ipc/ipc3/dai.c @@ -178,21 +178,38 @@ int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev) case SOF_DAI_IMX_ESAI: dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction); break; - case SOF_DAI_AMD_BT: - dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S16_LE; - break; - case SOF_DAI_AMD_SP: - case SOF_DAI_AMD_SP_VIRTUAL: - dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S16_LE; - break; case SOF_DAI_AMD_DMIC: dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE; if (dd->dma_buffer) audio_stream_set_frm_fmt(&dd->dma_buffer->stream, dev->ipc_config.frame_fmt); break; + case SOF_DAI_AMD_BT: + case SOF_DAI_AMD_SP: + case SOF_DAI_AMD_SP_VIRTUAL: case SOF_DAI_AMD_HS: case SOF_DAI_AMD_HS_VIRTUAL: +#if defined(CONFIG_AMD) && !defined(CONFIG_SOC_ACP_6_0) + { + struct acp_dma_dev_data *tdm_data = dd->dma->z_dev->data; + struct tdm_context *tdm_ctx; + + /* Allocate coherent memory for TDM context shared between + * IPC and DMA contexts. + */ + if (!tdm_data->dai_index_ptr) { + tdm_ctx = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + sizeof(*tdm_ctx)); + if (!tdm_ctx) + return -ENOMEM; + tdm_data->dai_index_ptr = tdm_ctx; + } else { + tdm_ctx = (struct tdm_context *)tdm_data->dai_index_ptr; + } + tdm_ctx->index = dd->dai->index; + } +#endif + break; case SOF_DAI_AMD_SDW: #if defined(CONFIG_AMD) && !defined(CONFIG_SOC_ACP_6_0) { diff --git a/src/lib/dai.c b/src/lib/dai.c index bd7c02edcb2d..22b2786a3098 100644 --- a/src/lib/dai.c +++ b/src/lib/dai.c @@ -188,6 +188,9 @@ const struct device *zephyr_dev[] = { #if CONFIG_DAI_AMD_SDW DT_FOREACH_STATUS_OKAY(amd_acp_sdw_dai, GET_DEVICE_LIST) #endif +#if CONFIG_DAI_AMD_TDM + DT_FOREACH_STATUS_OKAY(amd_tdm_dai, GET_DEVICE_LIST) +#endif #if CONFIG_DAI_INTEL_UAOL DT_FOREACH_STATUS_OKAY(intel_uaol_dai, GET_DEVICE_LIST) #endif @@ -219,21 +222,20 @@ static int sof_dai_type_to_zephyr(uint32_t type) return DAI_IMX_SAI; case SOF_DAI_IMX_ESAI: return DAI_IMX_ESAI; - case SOF_DAI_AMD_BT: - return DAI_AMD_BT; - case SOF_DAI_AMD_SP: - return DAI_AMD_SP; case SOF_DAI_AMD_DMIC: return DAI_AMD_DMIC; case SOF_DAI_MEDIATEK_AFE: return DAI_MEDIATEK_AFE; case SOF_DAI_IMX_MICFIL: return DAI_IMX_MICFIL; - case SOF_DAI_AMD_HS: - case SOF_DAI_AMD_SP_VIRTUAL: - case SOF_DAI_AMD_HS_VIRTUAL: case SOF_DAI_AMD_SDW: return DAI_AMD_SDW; + case SOF_DAI_AMD_HS: + case SOF_DAI_AMD_HS_VIRTUAL: + case SOF_DAI_AMD_SP: + case SOF_DAI_AMD_SP_VIRTUAL: + case SOF_DAI_AMD_BT: + return DAI_AMD_TDM; default: return -EINVAL; } @@ -301,6 +303,15 @@ static void dai_set_device_params(struct dai *d) d->dma_dev = SOF_DMA_DEV_SW; d->dma_caps = SOF_DMA_CAP_SW; break; + /* All TDM-capable AMD DAIs share acp_tdm_dma. */ + case SOF_DAI_AMD_HS: + case SOF_DAI_AMD_HS_VIRTUAL: + case SOF_DAI_AMD_SP: + case SOF_DAI_AMD_SP_VIRTUAL: + case SOF_DAI_AMD_BT: + d->dma_dev = SOF_DMA_DEV_HS | SOF_DMA_DEV_SP | SOF_DMA_DEV_BT; + d->dma_caps = SOF_DMA_CAP_HS | SOF_DMA_CAP_SP | SOF_DMA_CAP_BT; + break; default: break; } diff --git a/zephyr/lib/dma.c b/zephyr/lib/dma.c index 380c31d48843..3e43d65e2a00 100644 --- a/zephyr/lib/dma.c +++ b/zephyr/lib/dma.c @@ -238,6 +238,19 @@ SHARED_DATA struct sof_dma dma[] = { }, .z_dev = DEVICE_DT_GET(DT_NODELABEL(acp_sdw_dma)), }, +{ + .plat_data = { + .dir = SOF_DMA_DIR_MEM_TO_DEV | + SOF_DMA_DIR_DEV_TO_MEM, + .devs = SOF_DMA_DEV_HS | SOF_DMA_DEV_SP | SOF_DMA_DEV_BT, + .caps = SOF_DMA_CAP_HS | SOF_DMA_CAP_SP | SOF_DMA_CAP_BT, + .base = DMA0_BASE, + .chan_size = DMA0_SIZE, + .channels = 6, + .period_count = 2, + }, + .z_dev = DEVICE_DT_GET(DT_NODELABEL(acp_tdm_dma)), +}, #endif };