aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-11-04 09:51:00 -0500
committerTakashi Iwai <tiwai@suse.de>2013-11-05 01:48:04 -0500
commit485e3e0cdf353e2e37570eafaad7208138bb6620 (patch)
tree679eedb9338d6c7e92d1d7510d0b9f6083a4a8df /sound/pci/hda
parenta4e7a121685a137eeeb01f05d5ed570c1b45017a (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.c16
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 */
2664static int get_kctl_0dB_offset(struct snd_kcontrol *kctl) 2664static 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 */
2704static int init_slave_0dB(void *data, struct snd_kcontrol *slave) 2710static 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;