Skip to content

Commit cc6a12c

Browse files
committed
audio: base_fw: Implement IPC4_DMA_CONTROL message handling
This patch introduces handling for the IPC4_DMA_CONTROL message type in the base firmware, specifically for the SSP DAI driver. The implementation includes a new inline function `is_ssp_node_id` to check whether the node ID corresponds to an SSP DAI, and a new function `basefw_vendor_dma_control` to process the DMA Control configuration. The `basefw_dma_control` function has been added to handle the IPC4_DMA_CONTROL message. It ensures the message is atomic and contains all necessary information before casting the data buffer to the `ipc4_dma_control` structure and processing it. The function also calls `basefw_vendor_dma_control` to apply the DMA Control configuration to the hardware. The `basefw_set_large_config` function in `src/audio/base_fw.c` has been updated to call `basefw_dma_control` when an IPC4_DMA_CONTROL message is received. This change allows the base firmware to initialize or modify DMA gateway configurations dynamically, improving the flexibility of DMA management in response to IPC messages. Signed-off-by: Tomasz Leman <tomasz.m.leman@intel.com>
1 parent db1c601 commit cc6a12c

File tree

3 files changed

+117
-0
lines changed

3 files changed

+117
-0
lines changed

src/audio/base_fw.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,53 @@ static int basefw_get_large_config(struct comp_dev *dev,
483483
data_offset, data);
484484
};
485485

486+
/**
487+
* Handles the DMA Control IPC message to initialize or modify DMA gateway configuration.
488+
*
489+
* @param first_block Indicates if this is the first data block in the message.
490+
* @param last_block Indicates if this is the last data block in the message.
491+
* @param data_offset The offset of the data in the message.
492+
* @param data Pointer to the data buffer containing the DMA Control message.
493+
* @return 0 on success, negative error code on failure.
494+
*/
495+
static int basefw_dma_control(bool first_block,
496+
bool last_block,
497+
uint32_t data_offset,
498+
const char *data)
499+
{
500+
struct ipc4_dma_control *dma_control;
501+
size_t data_size;
502+
int ret;
503+
504+
/* Ensure that the message is atomic and contains all necessary information */
505+
if (!first_block || !last_block) {
506+
tr_err(&ipc_tr, "Non-atomic DMA Control message received");
507+
return -EINVAL;
508+
}
509+
510+
/* Cast the data buffer to the ipc4_dma_control structure */
511+
dma_control = (struct ipc4_dma_control *)data;
512+
if (dma_control->config_length > 0) {
513+
/* DMA Control is passed using a structure with the same construction as in DAI
514+
* configuration. There is an additional section whose size is not accounted for in
515+
* the config_length field. As a result, the configuration size will always be 0.
516+
*/
517+
tr_err(&ipc_tr, "The expected size of the data is 0.");
518+
return -EINVAL;
519+
}
520+
521+
data_size = data_offset - (sizeof(struct ipc4_dma_control) - sizeof(uint32_t));
522+
ret = basefw_vendor_dma_control(dma_control->node_id,
523+
(const char *)dma_control->config_data,
524+
data_size);
525+
if (ret < 0) {
526+
tr_err(&ipc_tr, "DMA gateway configuration failed, error: %d", ret);
527+
return ret;
528+
}
529+
530+
return 0;
531+
}
532+
486533
static int basefw_set_large_config(struct comp_dev *dev,
487534
uint32_t param_id,
488535
bool first_block,
@@ -491,6 +538,8 @@ static int basefw_set_large_config(struct comp_dev *dev,
491538
const char *data)
492539
{
493540
switch (param_id) {
541+
case IPC4_DMA_CONTROL:
542+
return basefw_dma_control(first_block, last_block, data_offset, data);
494543
case IPC4_PERF_MEASUREMENTS_STATE:
495544
return set_perf_meas_state(data);
496545
case IPC4_SYSTEM_TIME:

src/audio/base_fw_intel.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,52 @@ int basefw_vendor_set_large_config(struct comp_dev *dev,
314314

315315
return IPC4_UNKNOWN_MESSAGE_TYPE;
316316
}
317+
318+
static inline bool is_ssp_node_id(uint32_t dma_type)
319+
{
320+
return dma_type == ipc4_i2s_link_output_class ||
321+
dma_type == ipc4_i2s_link_input_class;
322+
}
323+
324+
int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, size_t data_size)
325+
{
326+
union ipc4_connector_node_id node = (union ipc4_connector_node_id)node_id;
327+
int ret, result;
328+
329+
tr_info(&basefw_comp_tr, "node_id 0x%x, config_data 0x%x, data_size %u",
330+
(uint32_t)node_id, config_data, data_size);
331+
if (is_ssp_node_id(node.f.dma_type)) {
332+
const struct device *dev = dai_get_device(DAI_INTEL_SSP, node.f.v_index);
333+
334+
if (dev) {
335+
ret = pm_device_runtime_get(dev);
336+
337+
if (ret < 0) {
338+
tr_err(&basefw_comp_tr, "Failed to get resume device, error: %d",
339+
ret);
340+
return ret;
341+
}
342+
343+
result = dai_dma_control_set(dev, config_data, data_size);
344+
if (result < 0)
345+
tr_err(&basefw_comp_tr,
346+
"Failed to set DMA control for SSP DAI, error: %d",
347+
result);
348+
349+
ret = pm_device_runtime_put(dev);
350+
if (ret < 0)
351+
tr_err(&basefw_comp_tr, "Failed to suspend device, error: %d",
352+
ret);
353+
} else {
354+
tr_err(&basefw_comp_tr,
355+
"Failed to find the SSP DAI device for node_id: 0x%x",
356+
node_id);
357+
return -EINVAL;
358+
}
359+
360+
return result;
361+
}
362+
363+
tr_err(&basefw_comp_tr, "Unsupported or invalid node_id: 0x%x for DMA Control", node_id);
364+
return -EINVAL;
365+
}

src/include/ipc4/base_fw_vendor.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ int basefw_vendor_set_large_config(struct comp_dev *dev,
8383
uint32_t data_offset,
8484
const char *data);
8585

86+
/**
87+
* @brief Vendor specific routine to configure DMA gateway.
88+
*
89+
* @param node_id The node ID of the DMA gatway to configure.
90+
* @param config_data pointer to the configuration data.
91+
* @param data_size Size of the configuration data.
92+
* @return 0 if successful, error code otherwise.
93+
*/
94+
static inline int basefw_vendor_dma_control(uint32_t node_id,
95+
const char *config_data,
96+
size_t data_size);
97+
8698
#else /* !CONFIG_IPC4_BASE_FW_INTEL */
8799

88100
static inline int basefw_vendor_fw_config(uint32_t *data_offset, char *data)
@@ -133,6 +145,13 @@ static inline int basefw_vendor_set_large_config(struct comp_dev *dev,
133145
return IPC4_UNKNOWN_MESSAGE_TYPE;
134146
}
135147

148+
static inline int basefw_vendor_dma_control(uint32_t node_id,
149+
const char *config_data,
150+
size_t data_size)
151+
{
152+
return IPC4_UNKNOWN_MESSAGE_TYPE;
153+
}
154+
136155
#endif
137156

138157
#endif /* __SOF_IPC4_BASE_FW_VENDOR_H__ */

0 commit comments

Comments
 (0)