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))); /** 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,