module_adapter_ipc4: Save and pre-parse base_cfg_ext data

The kernel-provided "base_cfg_ext" data wasn't being handled correctly
by the module adapter layer.  These structs (packed wire formats) only
ever lived in the IPC memory.  The module would set them on an
"init_data" before calling into driver init, and then clear that
pointer afterwards.  That's a critical problem, because the values in
that struct need to be used at pipeline setup time to configure buffer
formats!

Save the data correctly.  Also pre-parse it so users don't need to do
byte math on raw buffers and can just use "in/output_pins[]" arrays on
the module_config struct.

Signed-off-by: Andy Ross <andyross@google.com>
This commit is contained in:
Andy Ross 2024-01-02 11:29:05 -08:00 committed by Liam Girdwood
parent 3a78701fb0
commit 7046004384
3 changed files with 37 additions and 9 deletions

View File

@ -1333,6 +1333,10 @@ int module_adapter_reset(struct comp_dev *dev)
rfree(mod->stream_params);
mod->stream_params = NULL;
#if CONFIG_IPC_MAJOR_4
rfree(mod->priv.cfg.input_pins);
#endif
comp_dbg(dev, "module_adapter_reset(): done");
return comp_set_state(dev, COMP_TRIGGER_RESET);

View File

@ -38,19 +38,39 @@ int module_adapter_init_data(struct comp_dev *dev,
const struct comp_ipc_config *config,
const void *spec)
{
if (dev->drv->type == SOF_COMP_MODULE_ADAPTER) {
const struct ipc_config_process *ipc_module_adapter = spec;
const struct ipc_config_process *args = spec;
const struct ipc4_base_module_extended_cfg *cfg = (void *)args->data;
size_t cfgsz = args->size;
dst->init_data = ipc_module_adapter->data;
dst->size = ipc_module_adapter->size;
dst->avail = true;
assert(dev->drv->type == SOF_COMP_MODULE_ADAPTER);
if (cfgsz < sizeof(cfg->base_cfg))
return -EINVAL;
memcpy_s(&dst->base_cfg, sizeof(dst->base_cfg), ipc_module_adapter->data,
sizeof(dst->base_cfg));
} else {
dst->init_data = spec;
dst->base_cfg = cfg->base_cfg;
dst->size = cfgsz;
if (cfgsz >= sizeof(*cfg)) {
int n_in = cfg->base_cfg_ext.nb_input_pins;
int n_out = cfg->base_cfg_ext.nb_output_pins;
size_t pinsz = (n_in * sizeof(*dst->input_pins))
+ (n_out * sizeof(*dst->output_pins));
if (cfgsz == (sizeof(*cfg) + pinsz)) {
dst->nb_input_pins = n_in;
dst->nb_output_pins = n_out;
dst->input_pins = rmalloc(SOF_MEM_ZONE_RUNTIME_SHARED,
0, SOF_MEM_CAPS_RAM, pinsz);
if (!dst->input_pins)
return -ENOMEM;
dst->output_pins = (void *)&dst->input_pins[n_in];
memcpy_s(dst->input_pins, pinsz,
&cfg->base_cfg_ext.pin_formats[0], pinsz);
}
}
dst->init_data = cfg; /* legacy API */
dst->avail = true;
return 0;
}

View File

@ -30,6 +30,10 @@ struct module_config {
const void *init_data; /**< Initial IPC configuration. */
#if CONFIG_IPC_MAJOR_4
struct ipc4_base_module_cfg base_cfg;
uint8_t nb_input_pins;
uint8_t nb_output_pins;
struct ipc4_input_pin_format *input_pins;
struct ipc4_output_pin_format *output_pins;
#endif
};