ALSA: hda - Fix 'Beep Playback Switch' with no underlying mute switch
authorDavid Henningsson <david.henningsson@canonical.com>
Mon, 13 Aug 2012 15:10:46 +0000 (17:10 +0200)
committerTakashi Iwai <tiwai@suse.de>
Tue, 14 Aug 2012 08:22:31 +0000 (10:22 +0200)
Some Conexant devices (e g CX20590) have no mute capability on
their Beep widgets.
This patch makes sure we don't try setting mutes on those widgets.

Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/hda_beep.c

index d26ae65..0849aac 100644 (file)
@@ -231,15 +231,22 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
 }
 EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device);
 
+static bool ctl_has_mute(struct snd_kcontrol *kcontrol)
+{
+       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       return query_amp_caps(codec, get_amp_nid(kcontrol),
+                             get_amp_direction(kcontrol)) & AC_AMPCAP_MUTE;
+}
+
 /* get/put callbacks for beep mute mixer switches */
 int snd_hda_mixer_amp_switch_get_beep(struct snd_kcontrol *kcontrol,
                                      struct snd_ctl_elem_value *ucontrol)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
        struct hda_beep *beep = codec->beep;
-       if (beep && !beep->enabled) {
+       if (beep && (!beep->enabled || !ctl_has_mute(kcontrol))) {
                ucontrol->value.integer.value[0] =
-                       ucontrol->value.integer.value[1] = 0;
+                       ucontrol->value.integer.value[1] = beep->enabled;
                return 0;
        }
        return snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
@@ -263,6 +270,8 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
                        enable |= *valp;
                snd_hda_enable_beep_device(codec, enable);
        }
+       if (!ctl_has_mute(kcontrol))
+               return 0;
        return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
 }
 EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep);