From 78bbc45353d37e159558240ea36962686f4666e2 Mon Sep 17 00:00:00 2001 From: Serhiy Katsyuba Date: Mon, 2 Feb 2026 14:56:53 +0100 Subject: [PATCH 1/2] [DNM] west.yml: switch to private UAOL Zephyr *** DO NOT MERGE *** Switches Zephyr to private branch with UAOL support. This commit will be updated once https://github.com/zephyrproject-rtos/zephyr/pull/104137 is merged. Signed-off-by: Serhiy Katsyuba --- west.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/west.yml b/west.yml index d5a72f1f3c35..b4c618ed2882 100644 --- a/west.yml +++ b/west.yml @@ -11,6 +11,8 @@ manifest: url-base: https://github.com/thesofproject - name: zephyrproject url-base: https://github.com/zephyrproject-rtos + - name: sk + url-base: https://github.com/serhiy-katsyuba-intel # When upgrading projects here please run git log --oneline in the # project and if not too long then include the output in your commit @@ -43,8 +45,8 @@ manifest: - name: zephyr repo-path: zephyr - revision: b246d3f3f987f5ddfa6530bea2082c09ce1f00d8 - remote: zephyrproject + revision: uaol + remote: sk # Import some projects listed in zephyr/west.yml@revision # From a2901a136345e2f10e62262b5ddf3505995f51a7 Mon Sep 17 00:00:00 2001 From: Tomasz Lissowski Date: Thu, 13 Jun 2024 19:33:41 +0200 Subject: [PATCH 2/2] dai: uaol: add support for Intel UAOL Adds support for Intel USB Audio Offload Link (UAOL) DAI. Signed-off-by: Tomasz Lissowski Signed-off-by: Serhiy Katsyuba --- src/audio/base_fw_intel.c | 93 ++++++++++++++++++++++++++++++++++- src/audio/copier/copier.c | 2 + src/audio/copier/copier_dai.c | 11 +++++ src/audio/dai-zephyr.c | 12 +++++ src/include/ipc/dai.h | 3 +- src/ipc/ipc4/dai.c | 15 ++++++ src/lib/dai.c | 6 +++ 7 files changed, 139 insertions(+), 3 deletions(-) diff --git a/src/audio/base_fw_intel.c b/src/audio/base_fw_intel.c index 3601d0c5bd72..6b2659133359 100644 --- a/src/audio/base_fw_intel.c +++ b/src/audio/base_fw_intel.c @@ -23,6 +23,10 @@ #include +#if CONFIG_UAOL_INTEL_ADSP +#include +#endif + #include #include #include @@ -37,6 +41,22 @@ struct ipc4_modules_info { struct sof_man_module modules[0]; } __packed __aligned(4); +#if CONFIG_UAOL_INTEL_ADSP +struct ipc4_uaol_link_capabilities { + uint32_t input_streams_supported : 4; + uint32_t output_streams_supported : 4; + uint32_t bidirectional_streams_supported : 5; + uint32_t rsvd : 19; + uint32_t max_tx_fifo_size; + uint32_t max_rx_fifo_size; +} __packed __aligned(4); + +struct ipc4_uaol_capabilities { + uint32_t link_count; + struct ipc4_uaol_link_capabilities link_caps[]; +} __packed __aligned(4); +#endif /* CONFIG_UAOL_INTEL_ADSP */ + /* * TODO: default to value of ACE1.x platforms. This is defined * in multiple places in Zephyr, mm_drv_intel_adsp.h and @@ -67,7 +87,7 @@ __cold int basefw_vendor_fw_config(uint32_t *data_offset, char *data) tlv_value_uint32_set(tuple, IPC4_SLOW_CLOCK_FREQ_HZ_FW_CFG, IPC4_ALH_CAVS_1_8); tuple = tlv_next(tuple); - tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, 0); + tlv_value_uint32_set(tuple, IPC4_UAOL_SUPPORT, IS_ENABLED(CONFIG_UAOL_INTEL_ADSP)); tuple = tlv_next(tuple); tlv_value_uint32_set(tuple, IPC4_ALH_SUPPORT_LEVEL_FW_CFG, IPC4_ALH_CAVS_1_8); @@ -78,6 +98,55 @@ __cold int basefw_vendor_fw_config(uint32_t *data_offset, char *data) return 0; } +#if CONFIG_UAOL_INTEL_ADSP +#define DEV_AND_COMMA(node) DEVICE_DT_GET(node), +static const struct device *uaol_devs[] = { + DT_FOREACH_STATUS_OKAY(intel_adsp_uaol, DEV_AND_COMMA) +}; + +static void tlv_value_set_uaol_caps(struct sof_tlv *tuple, uint32_t type) +{ + const size_t dev_count = ARRAY_SIZE(uaol_devs); + struct uaol_capabilities dev_cap; + struct ipc4_uaol_capabilities *caps = (struct ipc4_uaol_capabilities *)tuple->value; + size_t caps_size = offsetof(struct ipc4_uaol_capabilities, link_caps[dev_count]); + size_t i; + int ret; + + memset(caps, 0, caps_size); + + caps->link_count = dev_count; + for (i = 0; i < dev_count; i++) { + ret = uaol_get_capabilities(uaol_devs[i], &dev_cap); + if (ret) + continue; + + caps->link_caps[i].input_streams_supported = dev_cap.input_streams; + caps->link_caps[i].output_streams_supported = dev_cap.output_streams; + caps->link_caps[i].bidirectional_streams_supported = dev_cap.bidirectional_streams; + caps->link_caps[i].max_tx_fifo_size = dev_cap.max_tx_fifo_size; + caps->link_caps[i].max_rx_fifo_size = dev_cap.max_rx_fifo_size; + } + + tlv_value_set(tuple, type, caps_size, caps); +} + +static int uaol_stream_id_to_hda_link_stream_id(int uaol_stream_id) +{ + size_t dev_count = ARRAY_SIZE(uaol_devs); + size_t i; + + for (i = 0; i < dev_count; i++) { + int hda_link_stream_id = uaol_get_mapped_hda_link_stream_id(uaol_devs[i], + uaol_stream_id); + if (hda_link_stream_id >= 0) + return hda_link_stream_id; + } + + return -1; +} +#endif /* CONFIG_UAOL_INTEL_ADSP */ + __cold int basefw_vendor_hw_config(uint32_t *data_offset, char *data) { struct sof_tlv *tuple = (struct sof_tlv *)data; @@ -120,6 +189,11 @@ __cold int basefw_vendor_hw_config(uint32_t *data_offset, char *data) tlv_value_set(tuple, IPC4_INTEL_MIC_PRIVACY_CAPS_HW_CFG, sizeof(priv_caps), &priv_caps); #endif +#if CONFIG_UAOL_INTEL_ADSP + tuple = tlv_next(tuple); + tlv_value_set_uaol_caps(tuple, IPC4_UAOL_CAPS_HW_CFG); +#endif + tuple = tlv_next(tuple); *data_offset = (int)((char *)tuple - data); @@ -421,6 +495,7 @@ __cold int basefw_vendor_set_large_config(struct comp_dev *dev, uint32_t param_i __cold int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, size_t data_size) { union ipc4_connector_node_id node = (union ipc4_connector_node_id)node_id; + int dai_index = node.f.v_index; int ret, result; enum sof_ipc_dai_type type; @@ -444,11 +519,25 @@ __cold int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, case ipc4_i2s_link_input_class: type = SOF_DAI_INTEL_SSP; break; + +#if CONFIG_UAOL_INTEL_ADSP + case ipc4_alh_uaol_stream_link_output_class: + case ipc4_alh_uaol_stream_link_input_class: + type = SOF_DAI_INTEL_UAOL; + dai_index = uaol_stream_id_to_hda_link_stream_id(node.f.v_index); + if (dai_index < 0) { + tr_err(&basefw_comp_tr, + "HDA link stream not found! UAOL node ID: 0x%x", node_id); + return IPC4_INVALID_RESOURCE_ID; + } + break; +#endif + default: return IPC4_INVALID_RESOURCE_ID; } - const struct device *dev = dai_get_device(type, node.f.v_index); + const struct device *dev = dai_get_device(type, dai_index); if (!dev) { tr_err(&basefw_comp_tr, diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 0468664c0634..d2aefcb13be6 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -191,6 +191,8 @@ __cold static int copier_init(struct processing_module *mod) case ipc4_i2s_link_input_class: case ipc4_alh_link_output_class: case ipc4_alh_link_input_class: + case ipc4_alh_uaol_stream_link_output_class: + case ipc4_alh_uaol_stream_link_input_class: ret = copier_dai_create(dev, cd, copier, dev->pipeline); if (ret < 0) { comp_err(dev, "unable to create dai"); diff --git a/src/audio/copier/copier_dai.c b/src/audio/copier/copier_dai.c index ceb93b2a22bf..facceccbe8a3 100644 --- a/src/audio/copier/copier_dai.c +++ b/src/audio/copier/copier_dai.c @@ -322,6 +322,17 @@ __cold int copier_dai_create(struct comp_dev *dev, struct copier_data *cd, if (ret) return ret; break; + case ipc4_alh_uaol_stream_link_output_class: + case ipc4_alh_uaol_stream_link_input_class: + dai.type = SOF_DAI_INTEL_UAOL; + dai.is_config_blob = true; + cd->gtw_type = ipc4_gtw_alh; + ret = ipc4_find_dma_config(&dai, gtw_cfg_data, gtw_cfg_szie); + if (ret != IPC4_SUCCESS) { + comp_err(dev, "No uaol dma_config found in blob!"); + return -EINVAL; + } + break; case ipc4_dmic_link_input_class: dai.type = SOF_DAI_INTEL_DMIC; dai.is_config_blob = true; diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c index a082e8c40650..a653953ff3b8 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -192,6 +192,18 @@ __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_INTEL_UAOL: + cfg.type = DAI_INTEL_UAOL; + cfg.channels = common_config->gtw_fmt->channels_count; + /* + * FIXME: The spec says HW expects container size here, not valid_bit_depth. + * However, tests fail if container size is used and work fine with + * valid_bit_depth. Needs investigation. Perhaps tests have a bug? + */ + cfg.word_size = common_config->gtw_fmt->valid_bit_depth; + cfg_params = spec_config; + dai_set_link_hda_config(&cfg.link_config, common_config, spec_config); + break; default: return -EINVAL; } diff --git a/src/include/ipc/dai.h b/src/include/ipc/dai.h index b5b29316f9e6..14c49b75681b 100644 --- a/src/include/ipc/dai.h +++ b/src/include/ipc/dai.h @@ -94,7 +94,8 @@ enum sof_ipc_dai_type { SOF_DAI_AMD_SP_VIRTUAL, /**host_dma_config[0]->stream_id; break; + case SOF_DAI_INTEL_UAOL: + link_cfg.full = 0; + link_cfg.part.hchan = gtw_fmt->channels_count - 1; + link_cfg.part.dir = common_config->direction; + link_cfg.part.stream = common_config->host_dma_config[0]->stream_id; + break; default: /* other types of DAIs not need link_config */ return; @@ -112,6 +118,13 @@ int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void */ channel = 0; break; +#if ACE_VERSION > ACE_VERSION_1_5 + case SOF_DAI_INTEL_UAOL: + channel = 0; + if (dai->host_dma_config[0]->pre_allocated_by_host) + channel = dai->host_dma_config[0]->dma_channel_id; + break; +#endif default: /* other types of DAIs not handled for now */ comp_err(dev, "Unknown dai type %d", dai->type); @@ -173,6 +186,8 @@ int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev) comp_dbg(dev, "dai_data_config() SOF_DAI_INTEL_ALH dev->ipc_config.frame_fmt: %d, stream_id: %d", dev->ipc_config.frame_fmt, dd->stream_id); + break; + case SOF_DAI_INTEL_UAOL: break; default: /* other types of DAIs not handled for now */ diff --git a/src/lib/dai.c b/src/lib/dai.c index 8e45f8a4bb97..58ff68a2e57e 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_INTEL_UAOL + DT_FOREACH_STATUS_OKAY(intel_uaol_dai, GET_DEVICE_LIST) +#endif }; const struct device **dai_get_device_list(size_t *count) @@ -207,6 +210,8 @@ static int sof_dai_type_to_zephyr(uint32_t type) return DAI_INTEL_HDA; case SOF_DAI_INTEL_ALH: return DAI_INTEL_ALH; + case SOF_DAI_INTEL_UAOL: + return DAI_INTEL_UAOL; case SOF_DAI_IMX_SAI: return DAI_IMX_SAI; case SOF_DAI_IMX_ESAI: @@ -285,6 +290,7 @@ static void dai_set_device_params(struct dai *d) #endif break; case SOF_DAI_INTEL_HDA: + case SOF_DAI_INTEL_UAOL: d->dma_dev = SOF_DMA_DEV_HDA; d->dma_caps = SOF_DMA_CAP_HDA; break;