From 8900ca1a0753351fc16c334b390ef4ec55df2e8c Mon Sep 17 00:00:00 2001 From: Ievgen Ganakov Date: Fri, 8 Sep 2023 12:09:44 +0200 Subject: [PATCH] ipc4: add helper function to parse dma config Add helper function to parse DMA config tlv structure added to copier Init Instance IPC when it has gateway config. Retrieve proper config when multiple gateway configs are present in IPC payload using device address value. Signed-off-by: Ievgen Ganakov --- src/include/sof/audio/ipc-config.h | 3 ++- src/include/sof/ipc/topology.h | 3 ++- src/ipc/ipc4/dai.c | 8 +++---- src/ipc/ipc4/helper.c | 36 +++++++++++++++++++++++++++++- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/include/sof/audio/ipc-config.h b/src/include/sof/audio/ipc-config.h index 8bedb7002e0c..ccabb8628e35 100644 --- a/src/include/sof/audio/ipc-config.h +++ b/src/include/sof/audio/ipc-config.h @@ -75,7 +75,8 @@ struct ipc_config_dai { uint32_t feature_mask; /**< copier feature mask (set directly from * ipc4_copier_module_cfg on init) */ - struct ipc_dma_config *host_dma_config; /**< DMA config - required for ACE 2.0 and newer */ + /**< DMA configs - required for ACE 2.0 and newer */ + struct ipc_dma_config *host_dma_config[GTW_DMA_DEVICE_MAX_COUNT]; const struct ipc4_audio_format *out_fmt;/**< audio format for output pin 0 - required * for ACE 2.0 and newer */ diff --git a/src/include/sof/ipc/topology.h b/src/include/sof/ipc/topology.h index f4caf828d7a2..a41e2e3e6128 100644 --- a/src/include/sof/ipc/topology.h +++ b/src/include/sof/ipc/topology.h @@ -60,7 +60,8 @@ int ipc4_pipeline_complete(struct ipc *ipc, uint32_t comp_id, uint32_t cmd); int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size); int ipc4_pipeline_prepare(struct ipc_comp_dev *ppl_icd, uint32_t cmd); int ipc4_pipeline_trigger(struct ipc_comp_dev *ppl_icd, uint32_t cmd, bool *delayed); - +int ipc4_find_dma_config_multiple(struct ipc_config_dai *dai, uint8_t *data_buffer, + uint32_t size, uint32_t device_id); #else #error "No or invalid IPC MAJOR version selected." #endif diff --git a/src/ipc/ipc4/dai.c b/src/ipc/ipc4/dai.c index 69a4bdf0569a..bb47a6172811 100644 --- a/src/ipc/ipc4/dai.c +++ b/src/ipc/ipc4/dai.c @@ -44,7 +44,7 @@ void dai_set_link_hda_config(uint16_t *link_config, case SOF_DAI_INTEL_SSP: link_cfg.full = 0; link_cfg.part.dir = common_config->direction; - link_cfg.part.stream = common_config->host_dma_config->stream_id; + link_cfg.part.stream = common_config->host_dma_config[0]->stream_id; break; case SOF_DAI_INTEL_DMIC: link_cfg.full = 0; @@ -57,7 +57,7 @@ void dai_set_link_hda_config(uint16_t *link_config, } else { link_cfg.part.hchan = out_fmt->channels_count - 1; } - link_cfg.part.stream = common_config->host_dma_config->stream_id; + link_cfg.part.stream = common_config->host_dma_config[0]->stream_id; break; default: /* other types of DAIs not need link_config */ @@ -79,8 +79,8 @@ int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void case SOF_DAI_INTEL_DMIC: channel = 0; #if defined(CONFIG_ACE_VERSION_2_0) - if (dai->host_dma_config->pre_allocated_by_host) - channel = dai->host_dma_config->dma_channel_id; + if (dai->host_dma_config[0]->pre_allocated_by_host) + channel = dai->host_dma_config[0]->dma_channel_id; #endif break; case SOF_DAI_INTEL_HDA: diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 4006ce82be8d..b73f5029ed0f 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -1002,11 +1003,44 @@ int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint3 if (*dma_config_id != GTW_DMA_CONFIG_ID) return IPC4_INVALID_REQUEST; - dai->host_dma_config = GET_IPC_DMA_CONFIG(data_buffer, size); + dai->host_dma_config[0] = GET_IPC_DMA_CONFIG(data_buffer, size); #endif return IPC4_SUCCESS; } +int ipc4_find_dma_config_multiple(struct ipc_config_dai *dai, uint8_t *data_buffer, + uint32_t size, uint32_t device_id) +{ + uint32_t end_addr = (uint32_t)data_buffer + size; + struct ipc_dma_config *dma_cfg; + struct sof_tlv *tlvs; + int dma_cfg_count = 0; + + for (tlvs = (struct sof_tlv *)data_buffer; (uint32_t)tlvs < end_addr; + tlvs = tlv_next(tlvs)) { + + dma_cfg = tlv_value_ptr_get(tlvs, GTW_DMA_CONFIG_ID); + if (!dma_cfg) + continue; + + if (dma_cfg->channel_map.device_count == 0) { + dai->host_dma_config[dma_cfg_count] = dma_cfg; + return IPC4_SUCCESS; + } + + for (uint32_t i = 0; i < dma_cfg->channel_map.device_count; i++) { + if (dma_cfg->channel_map.map[i].device_address == device_id) { + dai->host_dma_config[dma_cfg_count] = dma_cfg; + return IPC4_SUCCESS; + } + } + + dma_cfg_count++; + } + + return IPC4_INVALID_REQUEST; +} + void ipc4_base_module_cfg_to_stream_params(const struct ipc4_base_module_cfg *base_cfg, struct sof_ipc_stream_params *params) {