Skip to content

Commit dd5bc2f

Browse files
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 a2f2fe5 commit dd5bc2f

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
@@ -327,7 +327,7 @@ __cold int copier_dai_create(struct comp_dev *dev, struct copier_data *cd,
327327
dai.type = SOF_DAI_INTEL_UAOL;
328328
dai.is_config_blob = true;
329329
cd->gtw_type = ipc4_gtw_alh;
330-
ret = ipc4_find_dma_config(&dai, gtw_cfg_data, gtw_cfg_size);
330+
ret = ipc4_find_all_dma_configs_tlvs_only(&dai, gtw_cfg_data, gtw_cfg_size);
331331
if (ret != IPC4_SUCCESS) {
332332
comp_err(dev, "No uaol dma_config found in blob!");
333333
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
@@ -1299,6 +1299,49 @@ int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint3
12991299
return IPC4_SUCCESS;
13001300
}
13011301

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

0 commit comments

Comments
 (0)