From 51c686f9532aecb1d79031f5d835d018dd856916 Mon Sep 17 00:00:00 2001 From: Seppo Ingalsuo Date: Thu, 14 Mar 2024 19:21:54 +0200 Subject: [PATCH] Audio: Volume: Fix ongoing gain ramp stop and wrong final gain In IPC4 the individual channel gains are passed in separate messages. One channel may have started to ramp to a new gain while a new channel gain arrives for other channel. If the gain is same as the previous control value, the ongoing ramp is stopped and the gain remains at a transition value. The incorrect code is not fixed but instead the volume_set_volume() function is simplified. When a volume control is received, it is assumed that pass-through mode is disabled and ramp is prepared. If the control is received but gains are not changed, the ramp mode is finished and pass-through is restored in ramp function. The volume_set_switch() function is updated similarly to ensure similar operation. Signed-off-by: Seppo Ingalsuo --- src/audio/volume/volume_ipc4.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/src/audio/volume/volume_ipc4.c b/src/audio/volume/volume_ipc4.c index d12eed346..ddac8dac0 100644 --- a/src/audio/volume/volume_ipc4.c +++ b/src/audio/volume/volume_ipc4.c @@ -79,6 +79,8 @@ static uint32_t convert_volume_ipc3_to_ipc4(uint32_t volume) static void init_ramp(struct vol_data *cd, uint32_t curve_duration, uint32_t target_volume) { + cd->ramp_finished = false; + /* In IPC4 driver sends curve_duration in hundred of ns - it should be * converted into ms value required by firmware */ @@ -213,8 +215,6 @@ static int volume_set_volume(struct processing_module *mod, const uint8_t *data, } init_ramp(cd, cdata.curve_duration, cdata.target_volume); - cd->ramp_finished = true; - channels_count = mod->priv.cfg.base_cfg.audio_fmt.channels_count; if (channels_count > SOF_IPC_MAX_CHANNELS) { comp_err(dev, "Invalid channels count %u", channels_count); @@ -232,8 +232,6 @@ static int volume_set_volume(struct processing_module *mod, const uint8_t *data, volume_set_chan(mod, i, cd->tvolume[i], true); } - if (cd->volume[i] != cd->tvolume[i]) - cd->ramp_finished = false; } } else { if (cd->muted[cdata.channel_id]) { @@ -247,25 +245,12 @@ static int volume_set_volume(struct processing_module *mod, const uint8_t *data, volume_set_chan(mod, cdata.channel_id, cd->tvolume[cdata.channel_id], true); } - if (cd->volume[cdata.channel_id] != cd->tvolume[cdata.channel_id]) - cd->ramp_finished = false; - } - - cd->is_passthrough = cd->ramp_finished; - - for (i = 0; i < channels_count; i++) { - if (cd->volume[i] != VOL_ZERO_DB) { - cd->is_passthrough = false; - break; - } } + cd->is_passthrough = false; volume_set_ramp_channel_counter(cd, channels_count); - cd->scale_vol = vol_get_processing_function(dev, cd); - volume_prepare_ramp(dev, cd); - return 0; } @@ -322,8 +307,6 @@ static int volume_set_switch(struct processing_module *mod, const uint8_t *data, ctl = (struct sof_ipc4_control_msg_payload *)data; - cd->ramp_finished = true; - channels_count = mod->priv.cfg.base_cfg.audio_fmt.channels_count; if (channels_count > SOF_IPC_MAX_CHANNELS) { comp_err(dev, "Invalid channels count %u", channels_count); @@ -344,11 +327,13 @@ static int volume_set_switch(struct processing_module *mod, const uint8_t *data, volume_set_chan_unmute(mod, i); else volume_set_chan_mute(mod, i); - - if (cd->volume[i] != cd->tvolume[i]) - cd->ramp_finished = false; } + cd->ramp_finished = false; + cd->is_passthrough = false; + volume_set_ramp_channel_counter(cd, channels_count); + cd->scale_vol = vol_get_processing_function(dev, cd); + volume_prepare_ramp(dev, cd); return 0; }