diff --git a/src/audio/drc/drc.c b/src/audio/drc/drc.c index f27e5096576e..9eff93d79019 100644 --- a/src/audio/drc/drc.c +++ b/src/audio/drc/drc.c @@ -184,6 +184,13 @@ static int drc_init(struct processing_module *mod) } drc_reset_state(&cd->state); + + /* Initialize DRC to enabled. If defined by topology, a control may set + * enabled to false before prepare() or during streaming with the switch + * control from user space. + */ + cd->enabled = true; + cd->enable_switch = true; return 0; cd_fail: @@ -203,15 +210,40 @@ static int drc_free(struct processing_module *mod) return 0; } -static int drc_set_config(struct processing_module *mod, uint32_t config_id, +static int drc_set_config(struct processing_module *mod, uint32_t param_id, enum module_cfg_fragment_position pos, uint32_t data_offset_size, const uint8_t *fragment, size_t fragment_size, uint8_t *response, size_t response_size) { struct drc_comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "drc_set_config()"); - comp_info(mod->dev, "drc_set_config()"); +#if CONFIG_IPC_MAJOR_4 + struct sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + + switch (param_id) { + case SOF_IPC4_SWITCH_CONTROL_PARAM_ID: + if (ctl->id == SOF_DRC_CTRL_INDEX_ENABLE_SWITCH && + ctl->num_elems == SOF_DRC_NUM_ELEMS_ENABLE_SWITCH) { + cd->enable_switch = ctl->chanv[0].value; + comp_info(dev, "drc_set_config(), enable_switch = %d", cd->enable_switch); + } else { + comp_err(dev, "Illegal switch control id = %d, num_elems = %d", + ctl->id, ctl->num_elems); + return -EINVAL; + } + return 0; + + case SOF_IPC4_ENUM_CONTROL_PARAM_ID: + comp_err(dev, "drc_set_config(), illegal control."); + return -EINVAL; + } +#endif + + comp_info(dev, "drc_set_config(), bytes control"); return comp_data_blob_set(cd->model_handler, pos, data_offset_size, fragment, fragment_size); } @@ -262,6 +294,9 @@ static int drc_process(struct processing_module *mod, } } + /* Control pass-though in processing function with switch control */ + cd->enabled = cd->config && cd->config->params.enabled && cd->enable_switch; + cd->drc_func(mod, source, sink, frames); /* calc new free and available */ diff --git a/src/audio/drc/drc.h b/src/audio/drc/drc.h index 667dd1ada0df..01236243359a 100644 --- a/src/audio/drc/drc.h +++ b/src/audio/drc/drc.h @@ -33,6 +33,12 @@ struct comp_dev; #define DRC_DIVISION_FRAMES 32 #define DRC_DIVISION_FRAMES_MASK (DRC_DIVISION_FRAMES - 1) +/* First switch control instance is zero (SOF_IPC4_SWITCH_CONTROL_PARAM_ID), and the + * control is common for all channels. + */ +#define SOF_DRC_CTRL_INDEX_ENABLE_SWITCH 0 +#define SOF_DRC_NUM_ELEMS_ENABLE_SWITCH 1 + /* Stores the state of DRC */ struct drc_state { /* The detector_average is the target gain obtained by looking at the @@ -71,8 +77,10 @@ struct drc_comp_data { struct comp_data_blob_handler *model_handler; struct sof_drc_config *config; /**< pointer to setup blob */ bool config_ready; /**< set when fully received */ + bool enabled; /**< control processing via blob and switch */ + bool enable_switch; /**< enable switch state */ enum sof_ipc_frame source_format; /**< source frame format */ - drc_func drc_func; /**< processing function */ + drc_func drc_func; /**< processing function */ }; struct drc_proc_fnmap { diff --git a/src/audio/drc/drc_generic.c b/src/audio/drc/drc_generic.c index 1d60f6686e09..1ad0c50734a1 100644 --- a/src/audio/drc/drc_generic.c +++ b/src/audio/drc/drc_generic.c @@ -544,7 +544,7 @@ static void drc_s16_default(struct processing_module *mod, int fragment_samples; int fragment; - if (!p->enabled) { + if (!cd->enabled) { /* Delay the input sample only and don't do other processing. This is used when the * DRC is disabled. We want to do this to match the processing delay of other bands * in multi-band DRC kernel case. @@ -690,7 +690,7 @@ static void drc_s24_default(struct processing_module *mod, int fragment_samples; int fragment; - if (!p->enabled) { + if (!cd->enabled) { /* Delay the input sample only and don't do other processing. This is used when the * DRC is disabled. We want to do this to match the processing delay of other bands * in multi-band DRC kernel case. Note: use 32 bit delay function. @@ -738,7 +738,7 @@ static void drc_s32_default(struct processing_module *mod, int fragment_samples; int fragment; - if (!p->enabled) { + if (!cd->enabled) { /* Delay the input sample only and don't do other processing. This is used when the * DRC is disabled. We want to do this to match the processing delay of other bands * in multi-band DRC kernel case.