|
@@ -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);
|
|
|
}
|