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
85 changes: 71 additions & 14 deletions src/audio/volume/volume_ipc4.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ static int set_volume_ipc4(struct vol_data *cd, uint32_t const channel,
cd->tvolume[channel] = target_volume;
/* init ramp start volume*/
cd->rvolume[channel] = 0;
/* init muted volume */
cd->mvolume[channel] = 0;
/* set muted as false*/
cd->muted[channel] = false;

/* ATM there is support for the same ramp for all channels */
cd->ramp_type = ipc4_curve_type_convert((enum ipc4_curve_type)curve_type);
Expand Down Expand Up @@ -164,6 +160,9 @@ int volume_init(struct processing_module *mod)
target_volume[channel_cfg],
vol->config[channel_cfg].curve_type,
vol->config[channel_cfg].curve_duration);

/* set muted as false*/
cd->muted[channel] = false;
}

init_ramp(cd, vol->config[0].curve_duration, target_volume[0]);
Expand Down Expand Up @@ -224,21 +223,30 @@ static int volume_set_volume(struct processing_module *mod, const uint8_t *data,

if (cdata.channel_id == IPC4_ALL_CHANNELS_MASK) {
for (i = 0; i < channels_count; i++) {
set_volume_ipc4(cd, i, cdata.target_volume,
cdata.curve_type,
cdata.curve_duration);

volume_set_chan(mod, i, cd->tvolume[i], true);
if (cd->muted[i]) {
cd->mvolume[i] = cdata.target_volume;
} else {
set_volume_ipc4(cd, i, cdata.target_volume,
cdata.curve_type,
cdata.curve_duration);

volume_set_chan(mod, i, cd->tvolume[i], true);
}
if (cd->volume[i] != cd->tvolume[i])
cd->ramp_finished = false;
}
} else {
set_volume_ipc4(cd, cdata.channel_id, cdata.target_volume,
cdata.curve_type,
cdata.curve_duration);
if (cd->muted[cdata.channel_id]) {
cd->mvolume[cdata.channel_id] = cdata.target_volume;
} else {
set_volume_ipc4(cd, cdata.channel_id,
cdata.target_volume,
cdata.curve_type,
cdata.curve_duration);

volume_set_chan(mod, cdata.channel_id, cd->tvolume[cdata.channel_id],
true);
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;
}
Expand Down Expand Up @@ -297,6 +305,53 @@ static int volume_set_attenuation(struct processing_module *mod, const uint8_t *
return 0;
}

static int volume_set_switch(struct processing_module *mod, const uint8_t *data,
int data_size)
{
struct vol_data *cd = module_get_private_data(mod);
struct comp_dev *dev = mod->dev;
struct sof_ipc4_control_msg_payload *ctl;
unsigned int channels_count, num_elems;
unsigned int i, val;

if (data_size < sizeof(struct sof_ipc4_control_msg_payload)) {
comp_err(dev, "error: data_size %d should be bigger than %d", data_size,
sizeof(struct sof_ipc4_control_msg_payload));
return -EINVAL;
}

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);
return -EINVAL;
}

num_elems = ctl->num_elems;
if (num_elems > channels_count) {
comp_warn(dev, "limit num_elems %d to %d", num_elems, channels_count);
num_elems = channels_count;
}

for (i = 0; i < num_elems; i++) {
val = ctl->chanv[i].value;
comp_dbg(dev, "channel %i, value %u", i, val);

if (val)
volume_set_chan_unmute(mod, i);
else
volume_set_chan_mute(mod, i);

if (cd->volume[i] != cd->tvolume[i])
cd->ramp_finished = false;
}

return 0;
}

int volume_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,
Expand All @@ -321,6 +376,8 @@ int volume_set_config(struct processing_module *mod, uint32_t config_id,
return volume_set_volume(mod, fragment, fragment_size);
case IPC4_SET_ATTENUATION:
return volume_set_attenuation(mod, fragment, fragment_size);
case SOF_IPC4_SWITCH_CONTROL_PARAM_ID:
return volume_set_switch(mod, fragment, fragment_size);
default:
comp_err(dev, "unsupported param %d", config_id);
return -EINVAL;
Expand Down
35 changes: 35 additions & 0 deletions tools/topology/topology2/include/components/gain.conf
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,41 @@ Class.Widget."gain" {
}
}
}

# mute switch control
mixer."2" {
Object.Base.channel.1 {
name "flw"
reg 2
shift 0
}
Object.Base.channel.2 {
name "fl"
reg 2
shift 1
}
Object.Base.channel.3 {
name "fr"
reg 2
shift 2
}
Object.Base.channel.4 {
name "frw"
reg 2
shift 3
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also have no understanding of what this is.

Are you trying to enable a per-channel mute?

IIRC the mute button and the LED applies to all channels, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's from the SWITCH_CHANNEL_MAP defined in tools/topology/topology1/platform/intel/intel-generic-dmic-m4 but I believe SOF Linux driver do not use the reg/shift values to control the switch.

You could also find same definitions in tools/topology/topology2/include/components/volume.conf but I'm told that IPC4 does not use this conf file. I guess the writer just translate the definitions from topology1 to topology2.

In IPC3, mute is per channel but in UCM it should applies to all channels.


Object.Base.ops.1 {
name "ctl"
info "volsw"
## get = 259 binds the mixer control to switch get/put handlers
get 259
put 259
}

#max 1 indicates switch type control
max 1
}
}

# Default attribute values for gain widget
Expand Down
8 changes: 7 additions & 1 deletion tools/topology/topology2/platform/intel/dmic-generic.conf
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,13 @@ IncludeByKey.PASSTHROUGH {
}
]
Object.Control.mixer.1 {
name '$DMIC0_PCM_NAME Capture Volume'
name 'Dmic0 Capture Volume'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is for sure correct for the hda-generic case and the SDW tplgs we have shipped in SOF2.8 did not have dmic so that is good as well.

So this leaves the Chrome sof-mtl-max98357a-rt5682*tplg .that have DMICs and are using this definition. FYI @yongzhi1 @jairaj-arava , this will change the ALSA mixer control name for dmic volume control. This aligns the change to existing UCM files in https://github.com/alsa-project/alsa-ucm-conf/blob/master/ucm2/Intel/sof-hda-dsp/HiFi.conf

}
Object.Control.mixer.2 {
name 'Dmic0 Capture Switch'

mute_led_use 1
mute_led_direction 1
}
}

Expand Down