diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index a3d638c8c1f..88a1c6acbcb 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1539,6 +1539,17 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec) EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp); #endif /* SND_HDA_NEEDS_RESUME */ +static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir, + unsigned int ofs) +{ + u32 caps = query_amp_caps(codec, nid, dir); + /* get num steps */ + caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; + if (ofs < caps) + caps -= ofs; + return caps; +} + /** * snd_hda_mixer_amp_volume_info - Info callback for a standard AMP mixer * @@ -1553,23 +1564,17 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, u8 chs = get_amp_channels(kcontrol); int dir = get_amp_direction(kcontrol); unsigned int ofs = get_amp_offset(kcontrol); - u32 caps; - caps = query_amp_caps(codec, nid, dir); - /* num steps */ - caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; - if (!caps) { + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = chs == 3 ? 2 : 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = get_amp_max_value(codec, nid, dir, ofs); + if (!uinfo->value.integer.max) { printk(KERN_WARNING "hda_codec: " "num_steps = 0 for NID=0x%x (ctl = %s)\n", nid, kcontrol->id.name); return -EINVAL; } - if (ofs < caps) - caps -= ofs; - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = chs == 3 ? 2 : 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = caps; return 0; } EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info); @@ -1594,8 +1599,13 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid, int ch, int dir, int idx, unsigned int ofs, unsigned int val) { + unsigned int maxval; + if (val > 0) val += ofs; + maxval = get_amp_max_value(codec, nid, dir, ofs); + if (val > maxval) + val = maxval; return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, HDA_AMP_VOLMASK, val); } |