Skip to content

Commit

Permalink
audio: base_fw: Implement IPC4_DMA_CONTROL message handling
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
tmleman committed May 22, 2024
1 parent 344352d commit 44775e6
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/audio/base_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,54 @@ static int basefw_get_large_config(struct comp_dev *dev,
data_offset, data);
};

/**
* Handles the DMA Control IPC message to initialize or modify DMA gateway configuration.
*
* @param first_block Indicates if this is the first data block in the message.
* @param last_block Indicates if this is the last data block in the message.
* @param data_offset The offset of the data in the message.
* @param data Pointer to the data buffer containing the DMA Control message.
* @return 0 on success, negative error code on failure.
*/
static int basefw_dma_control(bool first_block,
bool last_block,
uint32_t data_offset,
const char *data)
{
/* Ensure that the message is atomic and contains all necessary information */
if (!first_block || !last_block) {
tr_err(&ipc_tr, "Non-atomic DMA Control message received");
return -EINVAL;
}

/* Cast the data buffer to the ipc4_dma_control structure */
struct ipc4_dma_control *dma_control = (struct ipc4_dma_control *)data;

tr_info(&ipc_tr, "Processing DMA Control, node_id: 0x%x, config_length: %u",
dma_control->node_id, dma_control->config_length);

if (dma_control->config_length > 0) {
/* DMA Control is passed using a structure with the same construction as in DAI
* configuration. There is an additional section whose size is not accounted for in
* the config_length field. As a result, the configuration size will always be 0.
*/
tr_err(&ipc_tr, "The expected size of the data is 0.");
return -EINVAL;
}

size_t data_size = data_offset - (sizeof(struct ipc4_dma_control) - sizeof(uint32_t));

int result = basefw_vendor_dma_control(dma_control->node_id, (const char *)dma_control->config_data, data_size);
if (result < 0) {
tr_err(&ipc_tr, "DMA gateway configuration failed, error: %d", result);
return result;
}

tr_info(&ipc_tr, "DMA Control configuration applied successfully");
/* If the configuration is successful, return 0 */
return 0;
}

static int basefw_set_large_config(struct comp_dev *dev,
uint32_t param_id,
bool first_block,
Expand All @@ -491,6 +539,8 @@ static int basefw_set_large_config(struct comp_dev *dev,
const char *data)
{
switch (param_id) {
case IPC4_DMA_CONTROL:
return basefw_dma_control(first_block, last_block, data_offset, data);
case IPC4_PERF_MEASUREMENTS_STATE:
return set_perf_meas_state(data);
case IPC4_SYSTEM_TIME:
Expand Down
43 changes: 43 additions & 0 deletions src/audio/base_fw_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,46 @@ int basefw_vendor_set_large_config(struct comp_dev *dev,

return IPC4_UNKNOWN_MESSAGE_TYPE;
}

inline static bool is_ssp_node_id(uint32_t dma_type)
{
return dma_type == ipc4_i2s_link_output_class ||
dma_type == ipc4_i2s_link_input_class;
}

int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, size_t data_size)
{
/* This function will handle the DMA Control configuration for SSP DAI.
* The actual implementation will depend on the platform specifics and
* the format of the configuration data.
*/

union ipc4_connector_node_id node = (union ipc4_connector_node_id) node_id;

tr_info(&basefw_comp_tr, "node_id 0x%x, config_data, data_size", node_id, config_data, data_size);
if (is_ssp_node_id(node.f.dma_type)) {
/* Parse the configuration data specific to SSP DAI and apply settings */
const struct device * dev = dai_get_device(DAI_INTEL_SSP, node.f.v_index);

if (dev) {
tr_info(&basefw_comp_tr, "pm_device_runtime_get");
int ret = pm_device_runtime_get(dev);
if (ret == 0) {
ret = dai_dma_control_set(dev, config_data);
tr_info(&basefw_comp_tr, "dma control ret = %d, pm_device_runtime_put", ret);
ret = pm_device_runtime_put(dev);
}

tr_info(&basefw_comp_tr, "ret = %d", ret);
}
else {
tr_err(&basefw_comp_tr, "Failed to find the device!");
}

tr_info(&basefw_comp_tr, "SSP DAI DMA Control configuration applied for node_id: 0x%x (index: %d)", node_id, node.f.v_index);
return 0;
}

tr_err(&basefw_comp_tr, "Unsupported or invalid node_id: 0x%x for DMA Control", node_id);
return -EINVAL;
}

0 comments on commit 44775e6

Please sign in to comment.