Skip to content

Commit 913972e

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. The implementation includes a new function `basefw_vendor_dma_control` to process the DMA Control configuration for any DAI type. 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. If the `dai_config_update` operation is not implemented by the DAI driver, the function will return `-ENOSYS`. 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 f0eed62 commit 913972e

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

src/audio/base_fw.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,52 @@ static int basefw_get_large_config(struct comp_dev *dev,
481481
data_offset, data);
482482
};
483483

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

src/audio/base_fw_intel.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <zephyr/device.h>
1919
#include <zephyr/drivers/counter.h>
2020
#endif
21+
#include <zephyr/pm/device_runtime.h>
2122

2223
#include <ipc4/base_fw.h>
2324
#include <rimage/sof/user/manifest.h>
@@ -319,3 +320,41 @@ int basefw_vendor_set_large_config(struct comp_dev *dev,
319320

320321
return IPC4_UNKNOWN_MESSAGE_TYPE;
321322
}
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+
node_id, (uint32_t)config_data, data_size);
331+
332+
const struct device *dev = dai_get_device(DAI_INTEL_SSP, node.f.v_index);
333+
334+
if (!dev) {
335+
tr_err(&basefw_comp_tr,
336+
"Failed to find the DAI device for node_id: 0x%x",
337+
node_id);
338+
return -EINVAL;
339+
}
340+
341+
ret = pm_device_runtime_get(dev);
342+
if (ret < 0) {
343+
tr_err(&basefw_comp_tr, "Failed to get resume device, error: %d",
344+
ret);
345+
return ret;
346+
}
347+
348+
result = dai_config_update(dev, config_data, data_size);
349+
if (result < 0)
350+
tr_err(&basefw_comp_tr,
351+
"Failed to set DMA control for DAI, error: %d",
352+
result);
353+
354+
ret = pm_device_runtime_put(dev);
355+
if (ret < 0)
356+
tr_err(&basefw_comp_tr, "Failed to suspend device, error: %d",
357+
ret);
358+
359+
return result;
360+
}

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 gateway 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+
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)