Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 54 additions & 10 deletions src/audio/selector/selector.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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);
Expand All @@ -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
Expand All @@ -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;

Expand Down
39 changes: 38 additions & 1 deletion src/include/sof/audio/selector.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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

Expand Down