diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-11-04 09:51:00 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-11-05 01:48:04 -0500 |
commit | 485e3e0cdf353e2e37570eafaad7208138bb6620 (patch) | |
tree | 679eedb9338d6c7e92d1d7510d0b9f6083a4a8df /sound/pci/hda | |
parent | a4e7a121685a137eeeb01f05d5ed570c1b45017a (diff) |
ALSA: hda - Add sanity check of vmaster slave dB steps
Check whether all vmaster slaves have the same dB steps. Otherwise
the behavior would become inconsistent.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 33c01d551aa4..dd5403d40830 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2661,7 +2661,7 @@ static int check_slave_present(void *data, struct snd_kcontrol *sctl) | |||
2661 | } | 2661 | } |
2662 | 2662 | ||
2663 | /* guess the value corresponding to 0dB */ | 2663 | /* guess the value corresponding to 0dB */ |
2664 | static int get_kctl_0dB_offset(struct snd_kcontrol *kctl) | 2664 | static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check) |
2665 | { | 2665 | { |
2666 | int _tlv[4]; | 2666 | int _tlv[4]; |
2667 | const int *tlv = NULL; | 2667 | const int *tlv = NULL; |
@@ -2681,6 +2681,12 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *kctl) | |||
2681 | step &= ~TLV_DB_SCALE_MUTE; | 2681 | step &= ~TLV_DB_SCALE_MUTE; |
2682 | if (!step) | 2682 | if (!step) |
2683 | return -1; | 2683 | return -1; |
2684 | if (*step_to_check && *step_to_check != step) { | ||
2685 | snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n", | ||
2686 | *step_to_check, step); | ||
2687 | return -1; | ||
2688 | } | ||
2689 | *step_to_check = step; | ||
2684 | val = -tlv[2] / step; | 2690 | val = -tlv[2] / step; |
2685 | } | 2691 | } |
2686 | return val; | 2692 | return val; |
@@ -2703,7 +2709,7 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val) | |||
2703 | /* initialize the slave volume with 0dB */ | 2709 | /* initialize the slave volume with 0dB */ |
2704 | static int init_slave_0dB(void *data, struct snd_kcontrol *slave) | 2710 | static int init_slave_0dB(void *data, struct snd_kcontrol *slave) |
2705 | { | 2711 | { |
2706 | int offset = get_kctl_0dB_offset(slave); | 2712 | int offset = get_kctl_0dB_offset(slave, data); |
2707 | if (offset > 0) | 2713 | if (offset > 0) |
2708 | put_kctl_with_value(slave, offset); | 2714 | put_kctl_with_value(slave, offset); |
2709 | return 0; | 2715 | return 0; |
@@ -2764,9 +2770,11 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name, | |||
2764 | 2770 | ||
2765 | /* init with master mute & zero volume */ | 2771 | /* init with master mute & zero volume */ |
2766 | put_kctl_with_value(kctl, 0); | 2772 | put_kctl_with_value(kctl, 0); |
2767 | if (init_slave_vol) | 2773 | if (init_slave_vol) { |
2774 | int step = 0; | ||
2768 | map_slaves(codec, slaves, suffix, | 2775 | map_slaves(codec, slaves, suffix, |
2769 | tlv ? init_slave_0dB : init_slave_unmute, kctl); | 2776 | tlv ? init_slave_0dB : init_slave_unmute, &step); |
2777 | } | ||
2770 | 2778 | ||
2771 | if (ctl_ret) | 2779 | if (ctl_ret) |
2772 | *ctl_ret = kctl; | 2780 | *ctl_ret = kctl; |