From 8d63a38efbf614bfe77159c44fa1e7197533cf34 Mon Sep 17 00:00:00 2001 From: Chao Song Date: Sat, 18 Feb 2023 13:05:55 +0800 Subject: [PATCH] selector: extend selector module to use base config extension This patch extend the selector module to use base config extension for module init, which ensures only base_cfg and base_cfg_ext is received in module init on linux side and align the init blob format with other modules. However, on Windows side, the payload base config with output format style payload is still used, this payload should be supported before Windows doing the payload format migration. Signed-off-by: Chao Song --- src/audio/selector/selector.c | 64 +++++++++++++++++++++++++++----- src/include/sof/audio/selector.h | 39 ++++++++++++++++++- 2 files changed, 92 insertions(+), 11 deletions(-) diff --git a/src/audio/selector/selector.c b/src/audio/selector/selector.c index 9c167ce70f5c..2ef5ad48d13e 100644 --- a/src/audio/selector/selector.c +++ b/src/audio/selector/selector.c @@ -577,22 +577,27 @@ SOF_MODULE_INIT(selector, sys_comp_selector_init); static void build_config(struct comp_data *cd, struct module_config *cfg) { enum sof_ipc_frame __sparse_cache frame_fmt, valid_fmt; + const struct sof_selector_ipc4_config *sel_cfg = &cd->sel_ipc4_cfg; + const struct ipc4_audio_format *out_fmt; int i; + if (cd->sel_ipc4_cfg.init_payload_fmt == IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT) + out_fmt = &sel_cfg->pin_cfg.out_pin.audio_fmt; + else + out_fmt = &sel_cfg->output_format; + audio_stream_fmt_conversion(cfg->base_cfg.audio_fmt.depth, cfg->base_cfg.audio_fmt.valid_bit_depth, &frame_fmt, &valid_fmt, cfg->base_cfg.audio_fmt.s_type); cd->source_format = frame_fmt; - audio_stream_fmt_conversion(cd->output_format.depth, - cd->output_format.valid_bit_depth, - &frame_fmt, &valid_fmt, - cd->output_format.s_type); + audio_stream_fmt_conversion(out_fmt->depth, out_fmt->valid_bit_depth, + &frame_fmt, &valid_fmt, out_fmt->s_type); cd->sink_format = frame_fmt; cd->config.in_channels_count = cfg->base_cfg.audio_fmt.channels_count; - cd->config.out_channels_count = cd->output_format.channels_count; + cd->config.out_channels_count = out_fmt->channels_count; /* Build default coefficient array (unity Q10 on diagonal, i.e. pass-through mode) */ memset(&cd->coeffs_config, 0, sizeof(cd->coeffs_config)); @@ -604,20 +609,54 @@ static int selector_init(struct processing_module *mod) { struct module_data *md = &mod->priv; struct module_config *cfg = &md->cfg; - const struct ipc4_base_module_cfg *base_cfg = cfg->init_data; + const struct ipc4_base_module_extended_cfg *init_cfg_ext; + const struct sof_selector_avs_ipc4_config *init_cfg_out_fmt; + enum ipc4_selector_init_payload_fmt payload_fmt; struct comp_data *cd; + size_t base_cfg_size; + size_t bs[2]; int ret; comp_dbg(mod->dev, "selector_init()"); + init_cfg_ext = cfg->init_data; + init_cfg_out_fmt = cfg->init_data; + base_cfg_size = sizeof(struct ipc4_base_module_cfg); + bs[0] = ipc4_calc_base_module_cfg_ext_size(SEL_NUM_IN_PIN_FMTS, + SEL_NUM_OUT_PIN_FMTS); + bs[1] = sizeof(struct ipc4_audio_format); + + if (cfg->size == base_cfg_size + bs[0]) { + payload_fmt = IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT; + + if (init_cfg_ext->base_cfg_ext.nb_input_pins != SEL_NUM_IN_PIN_FMTS || + init_cfg_ext->base_cfg_ext.nb_output_pins != SEL_NUM_OUT_PIN_FMTS) { + comp_err(mod->dev, "selector_init(): Invalid pin configuration"); + return -EINVAL; + } + } else if (cfg->size == base_cfg_size + bs[1]) { + payload_fmt = IPC4_SEL_INIT_PAYLOAD_BASE_WITH_OUT_FMT; + } else { + comp_err(mod->dev, "selector_init(): Invalid configuration size"); + return -EINVAL; + } + cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); if (!cd) return -ENOMEM; + cd->sel_ipc4_cfg.init_payload_fmt = payload_fmt; md->private = cd; - ret = memcpy_s(&cd->output_format, sizeof(cd->output_format), - base_cfg + 1, sizeof(struct ipc4_audio_format)); + if (payload_fmt == IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT) { + size_t size = sizeof(struct sof_selector_ipc4_pin_config); + + ret = memcpy_s(&cd->sel_ipc4_cfg.pin_cfg, size, + init_cfg_ext->base_cfg_ext.pin_formats, size); + } else { + ret = memcpy_s(&cd->sel_ipc4_cfg.output_format, bs[1], + &init_cfg_out_fmt->output_format, bs[1]); + } assert(!ret); build_config(cd, cfg); @@ -631,11 +670,17 @@ static void set_selector_params(struct processing_module *mod, struct comp_dev *dev = mod->dev; struct comp_data *cd = module_get_private_data(mod); struct comp_buffer __sparse_cache *source; - struct ipc4_audio_format *out_fmt; + const struct sof_selector_ipc4_config *sel_cfg = &cd->sel_ipc4_cfg; + const struct ipc4_audio_format *out_fmt = NULL; struct comp_buffer *src_buf; struct list_item *sink_list; int i; + if (cd->sel_ipc4_cfg.init_payload_fmt == IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT) + out_fmt = &sel_cfg->pin_cfg.out_pin.audio_fmt; + else + out_fmt = &sel_cfg->output_format; + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) params->channels = cd->config.in_channels_count; else @@ -644,7 +689,6 @@ static void set_selector_params(struct processing_module *mod, params->rate = mod->priv.cfg.base_cfg.audio_fmt.sampling_frequency; params->frame_fmt = cd->source_format; - out_fmt = &cd->output_format; for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) params->chmap[i] = (out_fmt->ch_map >> i * 4) & 0xf; diff --git a/src/include/sof/audio/selector.h b/src/include/sof/audio/selector.h index b504d6ae3113..e07576430322 100644 --- a/src/include/sof/audio/selector.h +++ b/src/include/sof/audio/selector.h @@ -42,6 +42,10 @@ struct comp_dev; /** \brief Maximum supported channel count on output. */ #define SEL_SINK_CHANNELS_MAX 8 + +#define SEL_NUM_IN_PIN_FMTS 1 +#define SEL_NUM_OUT_PIN_FMTS 1 + #endif #if CONFIG_IPC_MAJOR_4 @@ -62,6 +66,39 @@ struct ipc4_selector_coeffs_config { /** Mixing coefficients in Q10 fixed point format */ int16_t coeffs[SEL_SINK_CHANNELS_MAX][SEL_SOURCE_CHANNELS_MAX]; }; + +enum ipc4_selector_init_payload_fmt { + IPC4_SEL_INIT_PAYLOAD_BASE_WITH_EXT, + IPC4_SEL_INIT_PAYLOAD_BASE_WITH_OUT_FMT, +}; + +struct sof_selector_ipc4_pin_config { + struct ipc4_input_pin_format in_pin; + struct ipc4_output_pin_format out_pin; +}; + +/* + * Base module config is not added in this structure because it is handled + * by module adapter. + */ +struct sof_selector_ipc4_config { + /* + * Windows will send the base_config + output_format payload, but Linux will + * send the base_config + base_config_ext payload, use a union to make the + * selector module be compatible for both OSes. + */ + union { + struct sof_selector_ipc4_pin_config pin_cfg; + struct ipc4_audio_format output_format; + }; + enum ipc4_selector_init_payload_fmt init_payload_fmt; +}; + +struct sof_selector_avs_ipc4_config { + struct ipc4_base_module_cfg base_cfg; + struct ipc4_audio_format output_format; +}; + #else typedef void (*sel_func)(struct comp_dev *dev, struct audio_stream __sparse_cache *sink, const struct audio_stream __sparse_cache *source, uint32_t frames); @@ -70,7 +107,7 @@ typedef void (*sel_func)(struct comp_dev *dev, struct audio_stream __sparse_cach /** \brief Selector component private data. */ struct comp_data { #if CONFIG_IPC_MAJOR_4 - struct ipc4_audio_format output_format; + struct sof_selector_ipc4_config sel_ipc4_cfg; struct ipc4_selector_coeffs_config coeffs_config; #endif