Skip to content

Commit 45efb5c

Browse files
serhiy-katsyuba-intellgirdwood
authored andcommitted
ipc4: uaol: add ipc4_find_all_dma_configs_tlvs_only()
This adds yet another function to parse DMA config supplied by the host. Unfortunately, we now have three functions for this purpose. Unlike the existing ipc4_find_dma_config(), ipc4_find_all_dma_configs_tlvs_only() can find multiple DMA configs. For example, a UAOL copier may use two DMA channels: one for the audio USB endpoint and one for the feedback USB endpoint. ipc4_find_all_dma_configs_tlvs_only() can only work when all data in data_buffer is in TLV format; unfortunately, this is not always the case with IPC4 for all gateway types. Therefore, the existing ipc4_find_dma_config() is still needed as it can skip non-TLV blob data at the beginning of data_buffer. The other function, ipc4_find_dma_config_multiple(), works differently: it searches for DMA config for a given ALH stream ID in ALH multi-gateway case. Hence, this third function -- ipc4_find_all_dma_configs_tlvs_only() -- is added to the family. Signed-off-by: Serhiy Katsyuba <serhiy.katsyuba@intel.com>
1 parent 317e234 commit 45efb5c

3 files changed

Lines changed: 46 additions & 1 deletion

File tree

‎src/audio/copier/copier_dai.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ __cold int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
337337
dai.type = SOF_DAI_INTEL_UAOL;
338338
dai.is_config_blob = true;
339339
cd->gtw_type = ipc4_gtw_alh;
340-
ret = ipc4_find_dma_config(&dai, gtw_cfg_data, gtw_cfg_size);
340+
ret = ipc4_find_all_dma_configs_tlvs_only(&dai, gtw_cfg_data, gtw_cfg_size);
341341
if (ret != IPC4_SUCCESS) {
342342
comp_err(dev, "No uaol dma_config found in blob!");
343343
return -EINVAL;

‎src/include/sof/ipc/topology.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma, bool *d
5656
int ipc4_process_on_core(uint32_t core, bool blocking);
5757
int ipc4_pipeline_complete(struct ipc *ipc, uint32_t comp_id, uint32_t cmd);
5858
int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size);
59+
int ipc4_find_all_dma_configs_tlvs_only(struct ipc_config_dai *dai,
60+
uint8_t *data_buffer, size_t size);
5961
int ipc4_pipeline_prepare(struct ipc_comp_dev *ppl_icd, uint32_t cmd);
6062
int ipc4_pipeline_trigger(struct ipc_comp_dev *ppl_icd, uint32_t cmd, bool *delayed);
6163
int ipc4_find_dma_config_multiple(struct ipc_config_dai *dai, uint8_t *data_buffer,

‎src/ipc/ipc4/helper.c‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,49 @@ int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint3
13111311
return IPC4_SUCCESS;
13121312
}
13131313

1314+
/* Unlike the above ipc4_find_dma_config(), this can find multiple DMA configs.
1315+
* For example, a UAOL copier may use two DMA channels: one for audio and one
1316+
* for clock feedback. This function can only work when all data in data_buffer
1317+
* is in TLV format; however, this is not always the case for all gateway types.
1318+
* Therefore, the above ipc4_find_dma_config() is still used as it can skip non-TLV
1319+
* blob data at the beginning of data_buffer.
1320+
*/
1321+
int ipc4_find_all_dma_configs_tlvs_only(struct ipc_config_dai *dai,
1322+
uint8_t *data_buffer, size_t size)
1323+
{
1324+
uintptr_t end_addr = (uintptr_t)data_buffer + size;
1325+
struct sof_tlv *tlvs;
1326+
struct ipc_dma_config *dma_cfg;
1327+
int count = 0;
1328+
1329+
for (tlvs = (struct sof_tlv *)data_buffer; tlvs && (uintptr_t)tlvs < end_addr;
1330+
tlvs = tlv_next(tlvs)) {
1331+
if ((uintptr_t)tlvs->value + tlvs->length > end_addr) {
1332+
tr_err(&ipc_tr, "Unexpected TLV length %d: exceeds buffer size", tlvs->length);
1333+
return IPC4_INVALID_REQUEST;
1334+
}
1335+
1336+
dma_cfg = tlv_value_ptr_get(tlvs, GTW_DMA_CONFIG_ID);
1337+
if (!dma_cfg)
1338+
continue;
1339+
1340+
if (count >= GTW_DMA_DEVICE_MAX_COUNT) {
1341+
tr_err(&ipc_tr, "Unexpected DMA config count %d, max %d",
1342+
count, GTW_DMA_DEVICE_MAX_COUNT);
1343+
return IPC4_INVALID_REQUEST;
1344+
}
1345+
1346+
dai->host_dma_config[count++] = dma_cfg;
1347+
}
1348+
1349+
if (count == 0) {
1350+
tr_err(&ipc_tr, "No DMA config found");
1351+
return IPC4_INVALID_REQUEST;
1352+
}
1353+
1354+
return IPC4_SUCCESS;
1355+
}
1356+
13141357
int ipc4_find_dma_config_multiple(struct ipc_config_dai *dai, uint8_t *data_buffer,
13151358
uint32_t size, uint32_t device_id, int dma_cfg_idx)
13161359
{

0 commit comments

Comments
 (0)