diff --git a/src/audio/base_fw_intel.c b/src/audio/base_fw_intel.c index 5c38d07960cc..f1c64a082098 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 @@ -33,6 +37,20 @@ struct ipc4_modules_info { struct sof_man_module modules[0]; } __packed __aligned(4); +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); + /* * TODO: default to value of ACE1.x platforms. This is defined * in multiple places in Zephyr, mm_drv_intel_adsp.h and @@ -61,7 +79,7 @@ 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, 1); tuple = tlv_next(tuple); tlv_value_uint32_set(tuple, IPC4_ALH_SUPPORT_LEVEL_FW_CFG, IPC4_ALH_CAVS_1_8); @@ -72,6 +90,41 @@ int basefw_vendor_fw_config(uint32_t *data_offset, char *data) return 0; } +#if CONFIG_UAOL_INTEL_ADSP + +#define UAOL_DEV(node) DEVICE_DT_GET(node), +static const struct device *uaol_devs[] = { + DT_FOREACH_STATUS_OKAY(intel_adsp_uaol, UAOL_DEV) +}; + +static void tlv_value_set_uaol_caps(struct sof_tlv *tuple, uint32_t type) +{ + const unsigned int 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]); + unsigned int 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); +} +#endif + int basefw_vendor_hw_config(uint32_t *data_offset, char *data) { struct sof_tlv *tuple = (struct sof_tlv *)data; @@ -100,6 +153,11 @@ int basefw_vendor_hw_config(uint32_t *data_offset, char *data) tlv_value_uint32_set(tuple, IPC4_I2S_CAPS_HW_CFG, I2S_VER_30_PTL); #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); @@ -376,6 +434,10 @@ int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, size_t case ipc4_i2s_link_input_class: type = DAI_INTEL_SSP; break; + case ipc4_alh_uaol_stream_link_output_class: + case ipc4_alh_uaol_stream_link_input_class: + type = DAI_INTEL_UAOL; + break; default: return IPC4_INVALID_RESOURCE_ID; } diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 0fe324cb78f3..979e1485e444 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -139,6 +139,8 @@ 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, ipc_pipe->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 587a133ebd75..06cac2c5d747 100644 --- a/src/audio/copier/copier_dai.c +++ b/src/audio/copier/copier_dai.c @@ -311,6 +311,19 @@ 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, (uint8_t *)cd->gtw_cfg, + copier->gtw_cfg.config_length * 4); + if (ret != IPC4_SUCCESS) { + comp_err(dev, "No uaol dma_config found in blob!"); + return -EINVAL; + } + dai.out_fmt = &copier->out_fmt; + 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 6c845ff19ea5..d2690fdeabfd 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -140,6 +140,7 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config, { const struct device *dev = dai->dev; const struct sof_ipc_dai_config *sof_cfg = spec_config; + const struct ipc4_copier_gateway_cfg *gtw_cfg = spec_config; struct dai_config cfg; const void *cfg_params; bool is_blob; @@ -149,11 +150,13 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config, cfg.format = sof_cfg->format; cfg.options = sof_cfg->flags; cfg.rate = common_config->sampling_frequency; + cfg.channels = common_config->out_fmt->channels_count; + cfg.word_size = common_config->out_fmt->valid_bit_depth; switch (common_config->type) { case SOF_DAI_INTEL_SSP: cfg.type = is_blob ? DAI_INTEL_SSP_NHLT : DAI_INTEL_SSP; - cfg_params = is_blob ? spec_config : &sof_cfg->ssp; + cfg_params = is_blob ? (void *)>w_cfg->config_data : (void *)&sof_cfg->ssp; dai_set_link_hda_config(&cfg.link_config, common_config, cfg_params); /* Store tdm slot group index*/ @@ -161,17 +164,17 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config, break; case SOF_DAI_INTEL_ALH: cfg.type = is_blob ? DAI_INTEL_ALH_NHLT : DAI_INTEL_ALH; - cfg_params = is_blob ? spec_config : &sof_cfg->alh; + cfg_params = is_blob ? (void *)>w_cfg->config_data : (void *)&sof_cfg->alh; break; case SOF_DAI_INTEL_DMIC: cfg.type = is_blob ? DAI_INTEL_DMIC_NHLT : DAI_INTEL_DMIC; - cfg_params = is_blob ? spec_config : &sof_cfg->dmic; + cfg_params = is_blob ? (void *)>w_cfg->config_data : (void *)&sof_cfg->dmic; dai_set_link_hda_config(&cfg.link_config, common_config, cfg_params); break; case SOF_DAI_INTEL_HDA: cfg.type = is_blob ? DAI_INTEL_HDA_NHLT : DAI_INTEL_HDA; - cfg_params = is_blob ? spec_config : &sof_cfg->hda; + cfg_params = is_blob ? (void *)>w_cfg->config_data : (void *)&sof_cfg->hda; break; case SOF_DAI_IMX_SAI: cfg.type = DAI_IMX_SAI; @@ -181,6 +184,11 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config, cfg.type = DAI_IMX_ESAI; cfg_params = &sof_cfg->esai; break; + case SOF_DAI_INTEL_UAOL: + cfg.type = DAI_INTEL_UAOL; + cfg_params = gtw_cfg; + dai_set_link_hda_config(&cfg.link_config, common_config, >w_cfg->config_data); + 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 = out_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; @@ -115,6 +121,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, "dai_config_dma_channel(): Unknown dai type %d", dai->type); @@ -177,6 +190,16 @@ int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev) dev->ipc_config.frame_fmt, dd->stream_id); break; + case SOF_DAI_INTEL_UAOL: +#ifdef CONFIG_ZEPHYR_NATIVE_DRIVERS + dd->stream_id = dai_get_stream_id(dai_p, dai->direction); + dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE; + dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction); + break; +#else + /* only native Zephyr driver supported */ + return -EINVAL; +#endif default: /* other types of DAIs not handled for now */ comp_warn(dev, "dai_data_config(): Unknown dai type %d", dai->type); @@ -393,7 +416,7 @@ int dai_config(struct dai_data *dd, struct comp_dev *dev, struct ipc_config_dai if (ret < 0) return ret; - return dai_set_config(dd->dai, common_config, copier_cfg->gtw_cfg.config_data); + return dai_set_config(dd->dai, common_config, &copier_cfg->gtw_cfg); } #if CONFIG_ZEPHYR_NATIVE_DRIVERS diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index eb08414b323f..6db8050f01e4 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -1055,6 +1055,18 @@ int ipc4_add_comp_dev(struct comp_dev *dev) int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size) { #if ACE_VERSION > ACE_VERSION_1_5 + if (dai->type == SOF_DAI_INTEL_UAOL) { + void *value_ptr = NULL; + uint32_t value_size; + + tlv_value_get(data_buffer, size, GTW_DMA_CONFIG_ID, &value_ptr, &value_size); + if (!value_ptr) + return IPC4_INVALID_REQUEST; + + dai->host_dma_config[0] = (struct ipc_dma_config *)value_ptr; + return IPC4_SUCCESS; + } + uint32_t *dma_config_id = GET_IPC_DMA_CONFIG_ID(data_buffer, size); if (*dma_config_id != GTW_DMA_CONFIG_ID) diff --git a/src/lib/dai.c b/src/lib/dai.c index 1a3a49ab3596..cbba21c3db47 100644 --- a/src/lib/dai.c +++ b/src/lib/dai.c @@ -149,6 +149,9 @@ const struct device *zephyr_dev[] = { #if CONFIG_DAI_NXP_ESAI DT_FOREACH_STATUS_OKAY(nxp_dai_esai, 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(uint32_t type, uint32_t index) @@ -157,7 +160,7 @@ const struct device *dai_get_device(uint32_t type, uint32_t index) int dir; int i; - dir = (type == SOF_DAI_INTEL_DMIC) ? DAI_DIR_RX : DAI_DIR_BOTH; + dir = (type == DAI_INTEL_DMIC) ? DAI_DIR_RX : DAI_DIR_BOTH; for (i = 0; i < ARRAY_SIZE(zephyr_dev); i++) { if (dai_config_get(zephyr_dev[i], &cfg, dir)) @@ -197,6 +200,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; @@ -210,8 +214,47 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags) { const struct device *dev; struct dai *d; + uint32_t z_type; + + switch (type) { + case SOF_DAI_INTEL_SSP: + z_type = DAI_INTEL_SSP; + break; + case SOF_DAI_INTEL_DMIC: + z_type = DAI_INTEL_DMIC; + break; + case SOF_DAI_INTEL_HDA: + z_type = DAI_INTEL_HDA; + break; + case SOF_DAI_INTEL_ALH: + z_type = DAI_INTEL_ALH; + break; + case SOF_DAI_IMX_SAI: + z_type = DAI_IMX_SAI; + break; + case SOF_DAI_IMX_ESAI: + z_type = DAI_IMX_ESAI; + break; + case SOF_DAI_AMD_BT: + z_type = DAI_AMD_BT; + break; + case SOF_DAI_AMD_SP: + z_type = DAI_AMD_SP; + break; + case SOF_DAI_AMD_DMIC: + z_type = DAI_AMD_DMIC; + break; + case SOF_DAI_MEDIATEK_AFE: + z_type = DAI_MEDIATEK_AFE; + break; + case SOF_DAI_INTEL_UAOL: + z_type = DAI_INTEL_UAOL; + break; + default: + return NULL; + } - dev = dai_get_device(type, index); + dev = dai_get_device(z_type, index); if (!dev) { tr_err(&dai_tr, "dai_get: failed to get dai with index %d type %d", index, type); diff --git a/west.yml b/west.yml index 93c803c8d725..2494943dec16 100644 --- a/west.yml +++ b/west.yml @@ -43,7 +43,7 @@ manifest: - name: zephyr repo-path: zephyr - revision: 36517253160663f5cdb0f496cb166236fe4ad4c4 + revision: pull/69906/head remote: zephyrproject # Import some projects listed in zephyr/west.yml@revision