diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-09-07 07:38:49 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-09-08 02:26:15 -0400 |
commit | fe6ce80ae25953d95ebaf9bce27b585218cda25c (patch) | |
tree | 89857c2174ec46f6c5eff8c4c81f09a554ae3836 | |
parent | 4c25b93223340deff73381cc47f9244fb379a74d (diff) |
ALSA: virtuoso: fix setting of Xonar DS line-in/mic-in controls
The Line and Mic inputs cannot be used at the same time, so the driver
has to automatically disable one of them if both are set. However, it
forgot to notify userspace about this change, so the mixer state would
be inconsistent. To fix this, check if the other control gets muted,
and send a notification event in this case.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Reported-and-tested-by: Nathan Schagen
Cc: <stable@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/oxygen/xonar_wm87x6.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c index 0b89932fb8c4..b82c1cfa96f5 100644 --- a/sound/pci/oxygen/xonar_wm87x6.c +++ b/sound/pci/oxygen/xonar_wm87x6.c | |||
@@ -53,6 +53,8 @@ struct xonar_wm87x6 { | |||
53 | struct xonar_generic generic; | 53 | struct xonar_generic generic; |
54 | u16 wm8776_regs[0x17]; | 54 | u16 wm8776_regs[0x17]; |
55 | u16 wm8766_regs[0x10]; | 55 | u16 wm8766_regs[0x10]; |
56 | struct snd_kcontrol *line_adcmux_control; | ||
57 | struct snd_kcontrol *mic_adcmux_control; | ||
56 | struct snd_kcontrol *lc_controls[13]; | 58 | struct snd_kcontrol *lc_controls[13]; |
57 | }; | 59 | }; |
58 | 60 | ||
@@ -604,6 +606,7 @@ static int wm8776_input_mux_put(struct snd_kcontrol *ctl, | |||
604 | { | 606 | { |
605 | struct oxygen *chip = ctl->private_data; | 607 | struct oxygen *chip = ctl->private_data; |
606 | struct xonar_wm87x6 *data = chip->model_data; | 608 | struct xonar_wm87x6 *data = chip->model_data; |
609 | struct snd_kcontrol *other_ctl; | ||
607 | unsigned int mux_bit = ctl->private_value; | 610 | unsigned int mux_bit = ctl->private_value; |
608 | u16 reg; | 611 | u16 reg; |
609 | int changed; | 612 | int changed; |
@@ -611,8 +614,18 @@ static int wm8776_input_mux_put(struct snd_kcontrol *ctl, | |||
611 | mutex_lock(&chip->mutex); | 614 | mutex_lock(&chip->mutex); |
612 | reg = data->wm8776_regs[WM8776_ADCMUX]; | 615 | reg = data->wm8776_regs[WM8776_ADCMUX]; |
613 | if (value->value.integer.value[0]) { | 616 | if (value->value.integer.value[0]) { |
614 | reg &= ~0x003; | ||
615 | reg |= mux_bit; | 617 | reg |= mux_bit; |
618 | /* line-in and mic-in are exclusive */ | ||
619 | mux_bit ^= 3; | ||
620 | if (reg & mux_bit) { | ||
621 | reg &= ~mux_bit; | ||
622 | if (mux_bit == 1) | ||
623 | other_ctl = data->line_adcmux_control; | ||
624 | else | ||
625 | other_ctl = data->mic_adcmux_control; | ||
626 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
627 | &other_ctl->id); | ||
628 | } | ||
616 | } else | 629 | } else |
617 | reg &= ~mux_bit; | 630 | reg &= ~mux_bit; |
618 | changed = reg != data->wm8776_regs[WM8776_ADCMUX]; | 631 | changed = reg != data->wm8776_regs[WM8776_ADCMUX]; |
@@ -964,7 +977,13 @@ static int xonar_ds_mixer_init(struct oxygen *chip) | |||
964 | err = snd_ctl_add(chip->card, ctl); | 977 | err = snd_ctl_add(chip->card, ctl); |
965 | if (err < 0) | 978 | if (err < 0) |
966 | return err; | 979 | return err; |
980 | if (!strcmp(ctl->id.name, "Line Capture Switch")) | ||
981 | data->line_adcmux_control = ctl; | ||
982 | else if (!strcmp(ctl->id.name, "Mic Capture Switch")) | ||
983 | data->mic_adcmux_control = ctl; | ||
967 | } | 984 | } |
985 | if (!data->line_adcmux_control || !data->mic_adcmux_control) | ||
986 | return -ENXIO; | ||
968 | BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls)); | 987 | BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls)); |
969 | for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) { | 988 | for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) { |
970 | ctl = snd_ctl_new1(&lc_controls[i], chip); | 989 | ctl = snd_ctl_new1(&lc_controls[i], chip); |