Skip to content

Commit

Permalink
ipc4: Add Vendor Config Set
Browse files Browse the repository at this point in the history
Add Vendor Config Set, a special case of Large Config Set. Large Config Set
handling now checks for this case and extracts extended param_id from ipc
payload as param_id and handles the rest of the payload as usual. KPB now
uses extended param_id. Necessary for fast mode task configuration in KPB.

Signed-off-by: Tobiasz Dryjanski <[email protected]>
  • Loading branch information
tobonex committed Sep 19, 2023
1 parent dac982a commit 28ce21d
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 12 deletions.
9 changes: 8 additions & 1 deletion src/audio/kpb.c
Original file line number Diff line number Diff line change
Expand Up @@ -2384,9 +2384,16 @@ static int kpb_set_large_config(struct comp_dev *dev, uint32_t param_id,
uint32_t data_offset,
const char *data)
{
/* We can use extended param id for both extended
* and standard param id
*/
union ipc4_extended_param_id extended_param_id;

comp_info(dev, "kpb_set_large_config()");

switch (param_id) {
extended_param_id.full = param_id;

switch (extended_param_id.part.parameter_type) {
case KP_BUF_CLIENT_MIC_SELECT:
return kpb_set_micselect(dev, data, data_offset);
default:
Expand Down
15 changes: 15 additions & 0 deletions src/include/ipc4/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
#define SOF_IPC4_DST_QUEUE_ID_BITFIELD_SIZE 3
#define SOF_IPC4_SRC_QUEUE_ID_BITFIELD_SIZE 3

/* Special large_param_id values */
#define VENDOR_CONFIG_PARAM 0xFF

enum sof_ipc4_module_type {
SOF_IPC4_MOD_INIT_INSTANCE = 0,
SOF_IPC4_MOD_CONFIG_GET = 1,
Expand All @@ -51,6 +54,18 @@ enum sof_ipc4_module_type {
SOF_IPC4_MOD_DELETE_INSTANCE = 11,
};

/*
* Structs for Vendor Config Set
*/

union ipc4_extended_param_id {
uint32_t full;
struct{
uint32_t parameter_type : 8;
uint32_t parameter_instance : 24;
} part;
} __packed __aligned(4);

/*
* Host Driver sends this message to create a new module instance.
*/
Expand Down
96 changes: 85 additions & 11 deletions src/ipc/ipc4/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <sof/lib/mailbox.h>
#include <sof/lib/pm_runtime.h>
#include <sof/math/numbers.h>
#include <sof/tlv.h>
#include <sof/trace/trace.h>
#include <ipc4/error_status.h>
#include <ipc/header.h>
Expand Down Expand Up @@ -872,7 +873,8 @@ static int ipc4_get_large_config_module_instance(struct ipc4_message_request *ip
if (config.primary.r.module_id) {
uint32_t comp_id;

comp_id = IPC4_COMP_ID(config.primary.r.module_id, config.primary.r.instance_id);
comp_id = IPC4_COMP_ID(config.primary.r.module_id,
config.primary.r.instance_id);
dev = ipc4_get_comp_dev(comp_id);
if (!dev)
return IPC4_MOD_INVALID_ID;
Expand Down Expand Up @@ -921,6 +923,69 @@ static int ipc4_get_large_config_module_instance(struct ipc4_message_request *ip
return ret;
}

static int ipc4_set_vendor_config_module_instance(struct comp_dev *dev,
const struct comp_driver *drv,
uint32_t module_id,
uint32_t instance_id,
bool init_block,
bool final_block,
uint32_t data_off_size,
const char *data)
{
int ret;

/* Old FW comment: bursted configs */
if (init_block && final_block) {
const struct sof_tlv *tlv = (struct sof_tlv *)data;
/* if there is no payload in this large config set
* (4 bytes type | 4 bytes length=0 | no value)
* we do not handle such case
*/
if (data_off_size < sizeof(struct sof_tlv))
return IPC4_INVALID_CONFIG_DATA_STRUCT;

/* ===Iterate over payload===
* Payload can have multiple sof_tlv structures inside,
* You can find how many by checking payload size (data_off_size)
* Here we just set pointer end_offset to the end of data
* and iterate until we reach that
*/
const uint8_t *end_offset = data + data_off_size;

while ((const uint8_t *)tlv < end_offset) {
/* check for invalid length */
if (!tlv->length)
return IPC4_INVALID_CONFIG_DATA_LEN;

ret = drv->ops.set_large_config(dev, tlv->type, init_block,
final_block, tlv->length, tlv->value);
if (ret < 0) {
ipc_cmd_err(&ipc_tr, "failed to set large_config_module_instance %x : %x",
(uint32_t)module_id, (uint32_t)instance_id);
return IPC4_INVALID_RESOURCE_ID;
}
/* Move pointer to the end of this tlv */
tlv = (struct sof_tlv *)((const uint8_t *)tlv +
sizeof(struct sof_tlv) + ALIGN_UP(tlv->length, 4));
}
return IPC4_SUCCESS;
}
/* else, !(init_block && final_block) */
const struct sof_tlv *tlv = (struct sof_tlv *)data;
uint32_t param_id = 0;

if (init_block) {
/* for initial block use param_id from tlv
* move pointer and size to end of the tlv
*/
param_id = tlv->type;
data += sizeof(struct sof_tlv);
data_off_size -= sizeof(struct sof_tlv);
}
return drv->ops.set_large_config(dev, param_id, init_block, final_block,
data_off_size, (uint8_t *)data);
}

static int ipc4_set_large_config_module_instance(struct ipc4_message_request *ipc4)
{
struct ipc4_module_large_config config;
Expand Down Expand Up @@ -956,16 +1021,25 @@ static int ipc4_set_large_config_module_instance(struct ipc4_message_request *ip
return ipc4_process_on_core(dev->ipc_config.core, false);
}

ret = drv->ops.set_large_config(dev, config.extension.r.large_param_id,
config.extension.r.init_block,
config.extension.r.final_block,
config.extension.r.data_off_size,
(const char *)MAILBOX_HOSTBOX_BASE);
if (ret < 0) {
ipc_cmd_err(&ipc_tr, "failed to set large_config_module_instance %x : %x",
(uint32_t)config.primary.r.module_id,
(uint32_t)config.primary.r.instance_id);
ret = IPC4_INVALID_RESOURCE_ID;
/* check for vendor param first */
if (config.extension.r.large_param_id == VENDOR_CONFIG_PARAM) {
ret = ipc4_set_vendor_config_module_instance(dev, drv,
(uint32_t)config.primary.r.module_id,
(uint32_t)config.primary.r.instance_id,
config.extension.r.init_block,
config.extension.r.final_block,
config.extension.r.data_off_size,
(const char *)MAILBOX_HOSTBOX_BASE);
} else {
ret = drv->ops.set_large_config(dev, config.extension.r.large_param_id,
config.extension.r.init_block, config.extension.r.final_block,
config.extension.r.data_off_size, (const char *)MAILBOX_HOSTBOX_BASE);
if (ret < 0) {
ipc_cmd_err(&ipc_tr, "failed to set large_config_module_instance %x : %x",
(uint32_t)config.primary.r.module_id,
(uint32_t)config.primary.r.instance_id);
ret = IPC4_INVALID_RESOURCE_ID;
}
}

return ret;
Expand Down

0 comments on commit 28ce21d

Please sign in to comment.