static int fwspk_volume_put(struct snd_kcontrol *control, struct snd_ctl_elem_value *value) { struct fwspk *fwspk = control->private_data; unsigned int i, changed_channels; bool equal_values = true; s16 volume; int err; for (i = 0; i < fwspk->device_info->mixer_channels; ++i) { if (value->value.integer.value[i] < fwspk->volume_min || value->value.integer.value[i] > fwspk->volume_max) return -EINVAL; if (value->value.integer.value[i] != value->value.integer.value[0]) equal_values = false; } changed_channels = 0; for (i = 0; i < fwspk->device_info->mixer_channels; ++i) if (value->value.integer.value[channel_map[i]] != fwspk->volume[i]) changed_channels |= 1 << (i + 1); if (equal_values && changed_channels != 0) changed_channels = 1 << 0; for (i = 0; i <= fwspk->device_info->mixer_channels; ++i) { volume = value->value.integer.value[channel_map[i ? i - 1 : 0]]; if (changed_channels & (1 << i)) { err = fwspk_volume_command(fwspk, &volume, i, CTL_CURRENT, CTL_WRITE); if (err < 0) return err; } if (i > 0) fwspk->volume[i - 1] = volume; } return changed_channels != 0; }
.info = snd_ctl_boolean_mono_info, .get = fwspk_mute_get, .put = fwspk_mute_put, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", .info = fwspk_volume_info, .get = fwspk_volume_get, .put = fwspk_volume_put, }, }; unsigned int i, first_ch; int err; err = fwspk_volume_command(fwspk, &fwspk->volume_min, 0, CTL_MIN, CTL_READ); if (err < 0) return err; err = fwspk_volume_command(fwspk, &fwspk->volume_max, 0, CTL_MAX, CTL_READ); if (err < 0) return err; err = fwspk_mute_command(fwspk, &fwspk->mute, CTL_READ); if (err < 0) return err; first_ch = fwspk->device_info->mixer_channels == 1 ? 0 : 1; for (i = 0; i < fwspk->device_info->mixer_channels; ++i) { err = fwspk_volume_command(fwspk, &fwspk->volume[i], first_ch + i, CTL_CURRENT, CTL_READ);