Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

basefw: Add handling of IPC4_DMA_CONTROL messages #9156

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/audio/base_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,50 @@ 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, error code on failure.
*/
static int basefw_dma_control(bool first_block,
bool last_block,
uint32_t data_offset,
const char *data)
{
struct ipc4_dma_control *dma_control;
size_t data_size;
int ret;

/* 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 IPC4_ERROR_INVALID_PARAM;
}

dma_control = (struct ipc4_dma_control *)data;
data_size = data_offset - (sizeof(struct ipc4_dma_control) - sizeof(uint32_t));

if (data_size < (dma_control->config_length * sizeof(uint32_t))) {
tr_err(&ipc_tr, "DMA Control data too short: got %u, expected %u",
data_size, dma_control->config_length);
return IPC4_ERROR_INVALID_PARAM;
}

ret = basefw_vendor_dma_control(dma_control->node_id,
(const char *)dma_control->config_data,
tmleman marked this conversation as resolved.
Show resolved Hide resolved
data_size);
if (ret > 0) {
tr_err(&ipc_tr, "DMA gateway configuration failed, error: %d", ret);
return ret;
}

return IPC4_SUCCESS;
}

static int basefw_set_large_config(struct comp_dev *dev,
uint32_t param_id,
bool first_block,
Expand All @@ -533,6 +577,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
50 changes: 50 additions & 0 deletions src/audio/base_fw_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <zephyr/device.h>
#include <zephyr/drivers/counter.h>
#endif
#include <zephyr/pm/device_runtime.h>

#include <ipc4/base_fw.h>
#include <rimage/sof/user/manifest.h>
Expand Down Expand Up @@ -319,3 +320,52 @@ int basefw_vendor_set_large_config(struct comp_dev *dev,

return IPC4_UNKNOWN_MESSAGE_TYPE;
}

int basefw_vendor_dma_control(uint32_t node_id, const char *config_data, size_t data_size)
{
union ipc4_connector_node_id node = (union ipc4_connector_node_id)node_id;
int ret, result;
enum dai_type type;

tr_info(&basefw_comp_tr, "node_id 0x%x, config_data 0x%x, data_size %u",
node_id, (uint32_t)config_data, data_size);
switch (node.f.dma_type) {
case ipc4_i2s_link_output_class:
case ipc4_i2s_link_input_class:
type = DAI_INTEL_SSP;
break;
default:
return IPC4_INVALID_RESOURCE_ID;
}

const struct device *dev = dai_get_device(type, node.f.v_index);

if (!dev) {
tr_err(&basefw_comp_tr,
"Failed to find the DAI device for node_id: 0x%x",
node_id);
return IPC4_INVALID_RESOURCE_ID;
}

ret = pm_device_runtime_get(dev);
if (ret < 0) {
tr_err(&basefw_comp_tr, "Failed to get resume device, error: %d",
ret);
return IPC4_FAILURE;
}

result = dai_config_update(dev, config_data, data_size);
if (result < 0) {
tr_err(&basefw_comp_tr,
"Failed to set DMA control for DAI, error: %d",
result);
result = IPC4_FAILURE;
}

ret = pm_device_runtime_put(dev);
if (ret < 0)
tr_err(&basefw_comp_tr, "Failed to suspend device, error: %d",
ret);

return result;
}
19 changes: 19 additions & 0 deletions src/include/ipc4/base_fw_vendor.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ int basefw_vendor_set_large_config(struct comp_dev *dev,
uint32_t data_offset,
const char *data);

/**
* @brief Vendor specific routine to configure DMA gateway.
*
* @param node_id The node ID of the DMA gateway to configure.
* @param config_data pointer to the configuration data.
* @param data_size Size of the configuration data.
* @return 0 if successful, error code otherwise.
*/
int basefw_vendor_dma_control(uint32_t node_id,
const char *config_data,
size_t data_size);

#else /* !CONFIG_IPC4_BASE_FW_INTEL */

static inline int basefw_vendor_fw_config(uint32_t *data_offset, char *data)
Expand Down Expand Up @@ -133,6 +145,13 @@ static inline int basefw_vendor_set_large_config(struct comp_dev *dev,
return IPC4_UNKNOWN_MESSAGE_TYPE;
}

static inline int basefw_vendor_dma_control(uint32_t node_id,
const char *config_data,
size_t data_size)
{
return IPC4_UNKNOWN_MESSAGE_TYPE;
}

#endif

#endif /* __SOF_IPC4_BASE_FW_VENDOR_H__ */
5 changes: 5 additions & 0 deletions src/include/sof/lib/dai-zephyr.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ void dai_dma_position_update(struct dai_data *dd, struct comp_dev *dev);
* \brief release llp slot
*/
void dai_release_llp_slot(struct dai_data *dd);

/**
* \brief Retrieve a pointer to the Zephyr device structure for a DAI of a given type and index.
*/
const struct device *dai_get_device(uint32_t type, uint32_t index);
/** @}*/

#endif /* __SOF_LIB_DAI_ZEPHYR_H__ */
4 changes: 2 additions & 2 deletions src/lib/dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ const struct device *zephyr_dev[] = {
#endif
};

static const struct device *dai_get_zephyr_device(uint32_t type, uint32_t index)
const struct device *dai_get_device(uint32_t type, uint32_t index)
{
struct dai_config cfg;
int dir;
Expand Down Expand Up @@ -211,7 +211,7 @@ struct dai *dai_get(uint32_t type, uint32_t index, uint32_t flags)
const struct device *dev;
struct dai *d;

dev = dai_get_zephyr_device(type, index);
dev = dai_get_device(type, index);
if (!dev) {
tr_err(&dai_tr, "dai_get: failed to get dai with index %d type %d",
index, type);
Expand Down