From 44b00d24d132e3cf451d0be3e6ed7140bc6e32da Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 12 Sep 2025 12:49:48 +0300 Subject: [PATCH 1/2] ipc4: header: Add support for generic bytes control Add definition for generic bytes control and extend the sof_ipc4_control_msg_payload struct to be able to handle bytes data as well. In other terms, the generic bytes control can be handled in similar way as the ENUM or SWITCH generic control. Signed-off-by: Peter Ujfalusi --- src/include/ipc4/header.h | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/include/ipc4/header.h b/src/include/ipc4/header.h index a9bb5676e71f..643ded46050a 100644 --- a/src/include/ipc4/header.h +++ b/src/include/ipc4/header.h @@ -173,8 +173,9 @@ struct ipc4_message_reply { } extension; } __attribute((packed, aligned(4))); -#define SOF_IPC4_SWITCH_CONTROL_PARAM_ID 200 -#define SOF_IPC4_ENUM_CONTROL_PARAM_ID 201 +#define SOF_IPC4_SWITCH_CONTROL_PARAM_ID 200 +#define SOF_IPC4_ENUM_CONTROL_PARAM_ID 201 +#define SOF_IPC4_BYTES_CONTROL_PARAM_ID 202 #define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL ((uint32_t)(0xA15A << 16)) /** @@ -190,15 +191,19 @@ struct sof_ipc4_ctrl_value_chan { /** * struct sof_ipc4_control_msg_payload - IPC payload for kcontrol parameters * @id: unique id of the control - * @num_elems: Number of elememnts in the chanv array + * @num_elems: Number of elements in the chanv array or number of bytes in data * @reserved: reserved for future use, must be set to 0 * @chanv: channel ID and value array + * @data: binary payload */ struct sof_ipc4_control_msg_payload { uint16_t id; uint16_t num_elems; uint32_t reserved[4]; - struct sof_ipc4_ctrl_value_chan chanv[]; + union { + struct sof_ipc4_ctrl_value_chan chanv[0]; + uint8_t data[0]; + }; } __attribute((packed, aligned(4))); /** From 5990229b57e02e1b1bac105acaf1685e4e2ae7e1 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 12 Sep 2025 13:00:18 +0300 Subject: [PATCH 2/2] ipc4: handler: Add support for rx payload with LARGE_CONFIG_GET messages Some LARGE_CONFIG_GET message includes payload to provide instructions to the handler modules on how to fulfill the request. The generic control messages are such examples (they are not related to VENDOR_CONFIG_PARAM messages): The payload from host includes the sof_ipc4_control_msg_payload struct to describe the ID of the control for example. Alone the type (enum, switch or bytes) is not enough to know _which_ control's information is requested. Similarly, the control's ID does not identify the control's type. When such generic control message is received, the payload is copied from hostbox to the comp_data and the handler module can inspect it before overwriting it with the requested data. Note: currently we don't have modules which would handle generic control get functionality, but they would not have worked, because the information was not available to them to decide which control's data needs to be returned. Signed-off-by: Peter Ujfalusi --- src/ipc/ipc4/handler.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/ipc/ipc4/handler.c b/src/ipc/ipc4/handler.c index b2ddb3c3f742..3eea8f623081 100644 --- a/src/ipc/ipc4/handler.c +++ b/src/ipc/ipc4/handler.c @@ -996,6 +996,36 @@ static int ipc4_set_get_config_module_instance(struct ipc4_message_request *ipc4 return ret; } +__cold static void ipc4_prepare_for_kcontrol_get(struct comp_dev *dev, uint8_t param_id, + char *data_out, uint32_t data_size) +{ + const char *hostbox; + +#if CONFIG_LIBRARY + hostbox = (const char *)ipc_get()->comp_data + sizeof(struct ipc4_module_large_config); +#else + hostbox = (const char *)MAILBOX_HOSTBOX_BASE; +#endif + + assert_can_be_cold(); + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + case SOF_IPC4_BYTES_CONTROL_PARAM_ID: + /* We have payload in hostbox */ + dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE, + data_size); + + /* Copy the control payload header from inbox to outbox */ + memcpy_s(data_out, data_size, hostbox, + sizeof(struct sof_ipc4_control_msg_payload)); + break; + default: + break; + } +} + __cold static int ipc4_get_vendor_config_module_instance(struct comp_dev *dev, const struct comp_driver *drv, bool init_block, @@ -1154,6 +1184,9 @@ __cold static int ipc4_get_large_config_module_instance(struct ipc4_message_requ #if CONFIG_LIBRARY data += sizeof(reply); #endif + ipc4_prepare_for_kcontrol_get(dev, config.extension.r.large_param_id, + data, data_offset); + ret = drv->ops.get_large_config(dev, config.extension.r.large_param_id, config.extension.r.init_block, config.extension.r.final_block,