Skip to content

Commit f9575cd

Browse files
tmlemankv2019i
authored andcommitted
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 55ae145 commit f9575cd

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

src/audio/base_fw.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,50 @@ static int basefw_get_large_config(struct comp_dev *dev,
525525
data_offset, data);
526526
};
527527

528+
/**
529+
* Handles the DMA Control IPC message to initialize or modify DMA gateway configuration.
530+
*
531+
* @param first_block Indicates if this is the first data block in the message.
532+
* @param last_block Indicates if this is the last data block in the message.
533+
* @param data_offset The offset of the data in the message.
534+
* @param data Pointer to the data buffer containing the DMA Control message.
535+
* @return 0 on success, error code on failure.
536+
*/
537+
static int basefw_dma_control(bool first_block,
538+
bool last_block,
539+
uint32_t data_offset,
540+
const char *data)
541+
{
542+
struct ipc4_dma_control *dma_control;
543+
size_t data_size;
544+
int ret;
545+
546+
/* Ensure that the message is atomic and contains all necessary information */
547+
if (!first_block || !last_block) {
548+
tr_err(&ipc_tr, "Non-atomic DMA Control message received");
549+
return IPC4_ERROR_INVALID_PARAM;
550+
}
551+
552+
dma_control = (struct ipc4_dma_control *)data;
553+
data_size = data_offset - (sizeof(struct ipc4_dma_control) - sizeof(uint32_t));
554+
555+
if (data_size < (dma_control->config_length * sizeof(uint32_t))) {
556+
tr_err(&ipc_tr, "DMA Control data too short: got %u, expected %u",
557+
data_size, dma_control->config_length);
558+
return IPC4_ERROR_INVALID_PARAM;
559+
}
560+
561+
ret = basefw_vendor_dma_control(dma_control->node_id,
562+
(const char *)dma_control->config_data,
563+
data_size);
564+
if (ret > 0) {
565+
tr_err(&ipc_tr, "DMA gateway configuration failed, error: %d", ret);
566+
return ret;
567+
}
568+
569+
return IPC4_SUCCESS;
570+
}
571+
528572
static int basefw_set_large_config(struct comp_dev *dev,
529573
uint32_t param_id,
530574
bool first_block,
@@ -533,6 +577,8 @@ static int basefw_set_large_config(struct comp_dev *dev,
533577
const char *data)
534578
{
535579
switch (param_id) {
580+
case IPC4_DMA_CONTROL:
581+
return basefw_dma_control(first_block, last_block, data_offset, data);
536582
case IPC4_PERF_MEASUREMENTS_STATE:
537583
return set_perf_meas_state(data);
538584
case IPC4_SYSTEM_TIME:

src/audio/base_fw_intel.c

Lines changed: 50 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,52 @@ 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+
enum dai_type type;
329+
330+
tr_info(&basefw_comp_tr, "node_id 0x%x, config_data 0x%x, data_size %u",
331+
node_id, (uint32_t)config_data, data_size);
332+
switch (node.f.dma_type) {
333+
case ipc4_i2s_link_output_class:
334+
case ipc4_i2s_link_input_class:
335+
type = DAI_INTEL_SSP;
336+
break;
337+
default:
338+
return IPC4_INVALID_RESOURCE_ID;
339+
}
340+
341+
const struct device *dev = dai_get_device(type, node.f.v_index);
342+
343+
if (!dev) {
344+
tr_err(&basefw_comp_tr,
345+
"Failed to find the DAI device for node_id: 0x%x",
346+
node_id);
347+
return IPC4_INVALID_RESOURCE_ID;
348+
}
349+
350+
ret = pm_device_runtime_get(dev);
351+
if (ret < 0) {
352+
tr_err(&basefw_comp_tr, "Failed to get resume device, error: %d",
353+
ret);
354+
return IPC4_FAILURE;
355+
}
356+
357+
result = dai_config_update(dev, config_data, data_size);
358+
if (result < 0) {
359+
tr_err(&basefw_comp_tr,
360+
"Failed to set DMA control for DAI, error: %d",
361+
result);
362+
result = IPC4_FAILURE;
363+
}
364+
365+
ret = pm_device_runtime_put(dev);
366+
if (ret < 0)
367+
tr_err(&basefw_comp_tr, "Failed to suspend device, error: %d",
368+
ret);
369+
370+
return result;
371+
}

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)