Skip to content

Commit

Permalink
ALSA: hda - Limit the amp value to write
Browse files Browse the repository at this point in the history
Check the amp max value at put callbacks and set the upper limit
so that the driver won't write any invalid value over the defined
range.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai committed Jul 9, 2010
1 parent 3507e2a commit afbd9b8
Showing 1 changed file with 21 additions and 11 deletions.
32 changes: 21 additions & 11 deletions sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand All @@ -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);
Expand All @@ -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);
}
Expand Down

0 comments on commit afbd9b8

Please sign in to comment.