From 2efe5719559be82f0248efd0f07bf035e415d243 Mon Sep 17 00:00:00 2001 From: Johny Lin Date: Wed, 23 Apr 2025 04:13:49 +0200 Subject: [PATCH] Add switch control on module_adapter Signed-off-by: Johny Lin --- src/audio/module_adapter/module/waves/waves.c | 79 ++++++++++++++++++- tools/topology/topology1/m4/codec_adapter.m4 | 5 +- .../sof/pipe-codec-adapter-playback.m4 | 23 +++++- .../sof/pipe-waves-codec-playback.m4 | 1 + 4 files changed, 102 insertions(+), 6 deletions(-) diff --git a/src/audio/module_adapter/module/waves/waves.c b/src/audio/module_adapter/module/waves/waves.c index 76311508f69a..6368113ee470 100644 --- a/src/audio/module_adapter/module/waves/waves.c +++ b/src/audio/module_adapter/module/waves/waves.c @@ -44,6 +44,7 @@ struct waves_codec_data { uint32_t config_blob_size; void *config_blob; bool initialized; + bool enabled; }; enum waves_codec_params { @@ -699,6 +700,7 @@ static int waves_codec_init(struct processing_module *mod) } waves_codec->response = response; waves_codec->initialized = false; + waves_codec->enabled = true; comp_dbg(dev, "waves_codec_init() done"); return ret; @@ -770,6 +772,10 @@ waves_codec_process(struct processing_module *mod, if (!codec->mpd.init_done) waves_codec_init_process(mod); + /* TODO(waves): handle the enabled/disabled state */ + if (!waves_codec->enabled) + comp_dbg(dev, "waves_codec_process() is disabled"); + memcpy_s(codec->mpd.in_buff, codec->mpd.in_buff_size, input_buffers[0].data, codec->mpd.in_buff_size); codec->mpd.avail = codec->mpd.in_buff_size; @@ -862,8 +868,37 @@ static int waves_codec_free(struct processing_module *mod) return 0; } +static int waves_codec_set_value(struct processing_module *mod, void *ctl_data) +{ +#if CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = ctl_data; +#elif CONFIG_IPC_MAJOR_4 + struct sof_ipc4_control_msg_payload *cdata = ctl_data; +#endif + struct module_data *md = &mod->priv; + struct waves_codec_data *waves_codec = md->private; + struct comp_dev *dev = mod->dev; + uint32_t val = 0; + int32_t j; + + for (j = 0; j < cdata->num_elems; j++) { + val |= cdata->chanv[j].value; + comp_dbg(dev, "waves_codec_set_value(), value = %u", val); + } + + if (val) { + comp_info(dev, "waves_codec_set_value(): enabled"); + waves_codec->enabled = true; + } else { + comp_info(dev, "waves_codec_set_value(): disabled"); + waves_codec->enabled = false; + } + + return 0; +} + static int -waves_codec_set_configuration(struct processing_module *mod, uint32_t config_id, +waves_codec_set_bytes_control(struct processing_module *mod, uint32_t config_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) @@ -885,21 +920,57 @@ waves_codec_set_configuration(struct processing_module *mod, uint32_t config_id, /* whole configuration received, apply it now */ ret = waves_effect_apply_config(mod); if (ret) { - comp_err(dev, "waves_codec_set_configuration(): error %x: runtime config apply failed", + comp_err(dev, "waves_codec_set_bytes_control(): error %x: runtime config apply failed", ret); return ret; } - comp_dbg(dev, "waves_codec_set_configuration(): config applied"); + comp_dbg(dev, "waves_codec_set_bytes_control(): config applied"); return 0; } +static int waves_codec_set_config(struct processing_module *mod, uint32_t config_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 comp_dev *dev = mod->dev; + int ret; + +#if CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment; + + switch (cdata->cmd) { + case SOF_CTRL_CMD_BINARY: + return waves_codec_set_bytes_control(mod, config_id, pos, data_offset_size, + fragment, fragment_size, response, + response_size); + + case SOF_CTRL_CMD_SWITCH: + return waves_codec_set_value(mod, cdata); + } + + comp_err(dev, "waves_codec_set_config() error: invalid command %d", cdata->cmd); + return -EINVAL; + +#elif CONFIG_IPC_MAJOR_4 + struct sof_ipc4_control_msg_payload *ctl = (struct sof_ipc4_control_msg_payload *)fragment; + + if (config_id == SOF_IPC4_SWITCH_CONTROL_PARAM_ID) + return waves_codec_set_value(mod, ctl); + + return waves_codec_set_bytes_control(mod, config_id, pos, data_offset_size, + fragment, fragment_size, response, + response_size); +#endif +} + static const struct module_interface waves_interface = { .init = waves_codec_init, .prepare = waves_codec_prepare, .process_raw_data = waves_codec_process, - .set_configuration = waves_codec_set_configuration, + .set_configuration = waves_codec_set_config, .reset = waves_codec_reset, .free = waves_codec_free }; diff --git a/tools/topology/topology1/m4/codec_adapter.m4 b/tools/topology/topology1/m4/codec_adapter.m4 index 8387867e2ef5..5e0fc581914d 100644 --- a/tools/topology/topology1/m4/codec_adapter.m4 +++ b/tools/topology/topology1/m4/codec_adapter.m4 @@ -52,7 +52,10 @@ define(`W_CODEC_ADAPTER', ` bytes [' $6 ` ]' - +`ifelse(`$#', `7', +` mixer [' + $7 +` ]',)' `}') divert(0)dnl diff --git a/tools/topology/topology1/sof/pipe-codec-adapter-playback.m4 b/tools/topology/topology1/sof/pipe-codec-adapter-playback.m4 index dcfe4d75dbe6..53db5e55d001 100644 --- a/tools/topology/topology1/sof/pipe-codec-adapter-playback.m4 +++ b/tools/topology/topology1/sof/pipe-codec-adapter-playback.m4 @@ -12,6 +12,7 @@ include(`dai.m4') include(`pipeline.m4') include(`codec_adapter.m4') include(`bytecontrol.m4') +include(`mixercontrol.m4') # # Controls @@ -61,6 +62,22 @@ C_CONTROLBYTES(CA_SETUP_CONTROLBYTES_NAME_PIPE, PIPELINE_ID, , CA_SETUP_CONFIG) +# For codec developers, rename bytes control names if necessary. +ifdef(`CA_SWITCH_NAME',`', + `define(`CA_SWITCH_NAME', `CA Enable')') + +define(CA_SWITCH_NAME_PIPE, concat(CA_SWITCH_NAME, PIPELINE_ID)) +define(`CONTROL_NAME', `CA_SWITCH_NAME_PIPE') +C_CONTROLMIXER(CA_SWITCH_NAME_PIPE, PIPELINE_ID, + CONTROLMIXER_OPS(volsw, 259 binds the mixer control to switch get/put handlers, 259, 259), + CONTROLMIXER_MAX(max 1 indicates switch type control, 1), + false, + , + Channel register and shift for Front Center, + LIST(` ', KCONTROL_CHANNEL(FC, 3, 0)), + "1") +undefine(`CONTROL_NAME') + # # Components and Buffers # @@ -74,7 +91,8 @@ ifdef(`CA_SCHEDULE_CORE',`', `define(`CA_SCHEDULE_CORE', `SCHEDULE_CORE')') W_PCM_PLAYBACK(PCM_ID, Passthrough Playback, DAI_PERIODS, 0, SCHEDULE_CORE) W_CODEC_ADAPTER(0, PIPELINE_FORMAT, DAI_PERIODS, DAI_PERIODS, CA_SCHEDULE_CORE, - LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE")) + LIST(` ', "CA_SETUP_CONTROLBYTES_NAME_PIPE"), + LIST(` ', "CA_SWITCH_NAME_PIPE")) # Playback Buffers W_BUFFER(0, COMP_BUFFER_SIZE(DAI_PERIODS, @@ -107,6 +125,9 @@ indir(`define', concat(`PIPELINE_PCM_', PIPELINE_ID), Passthrough Playback PCM_I PCM_CAPABILITIES(Passthrough Playback PCM_ID, CAPABILITY_FORMAT_NAME(PIPELINE_FORMAT), PCM_MIN_RATE, PCM_MAX_RATE, 2, PIPELINE_CHANNELS, 2, 16, 192, 16384, 65536, 65536) +undefine(`CA_SWITCH_NAME_PIPE') +undefine(`CA_SWITCH_NAME') + undefine(`CA_SETUP_CONTROLBYTES_NAME_PIPE') undefine(`CA_SETUP_PARAMS') diff --git a/tools/topology/topology1/sof/pipe-waves-codec-playback.m4 b/tools/topology/topology1/sof/pipe-waves-codec-playback.m4 index 2c19ec0f19a2..cc702f48473c 100644 --- a/tools/topology/topology1/sof/pipe-waves-codec-playback.m4 +++ b/tools/topology/topology1/sof/pipe-waves-codec-playback.m4 @@ -23,6 +23,7 @@ define(`CA_SETUP_CONTROLBYTES', ) define(`CA_SETUP_CONTROLBYTES_MAX', 8192) define(`CA_SETUP_CONTROLBYTES_NAME', `Waves' `ENDPOINT_NAME' `Setup ') +define(`CA_SWITCH_NAME', `Waves' `ENDPOINT_NAME' `Enable ') define(`CA_SCHEDULE_CORE', 0)