aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/ac97_codec.h1
-rw-r--r--sound/pci/ac97/ac97_codec.c36
-rw-r--r--sound/pci/atiixp.c6
-rw-r--r--sound/pci/intel8x0.c24
4 files changed, 67 insertions, 0 deletions
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index a1814cd9549..b0b3ea7b365 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -541,6 +541,7 @@ enum {
AC97_TUNE_ALC_JACK, /* for Realtek, enable JACK detection */
AC97_TUNE_INV_EAPD, /* inverted EAPD implementation */
AC97_TUNE_MUTE_LED, /* EAPD bit works as mute LED */
+ AC97_TUNE_HP_MUTE_LED, /* EAPD bit works as mute LED, use headphone control as master */
};
struct ac97_quirk {
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 33d7a1fc2f9..3020ca2b602 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -2457,6 +2457,41 @@ static int tune_mute_led(struct snd_ac97 *ac97)
return 0;
}
+static int hp_master_mute_sw_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int err = bind_hp_volsw_put(kcontrol, ucontrol);
+ if (err > 0) {
+ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
+ int shift = (kcontrol->private_value >> 8) & 0x0f;
+ int rshift = (kcontrol->private_value >> 12) & 0x0f;
+ unsigned short mask;
+ if (shift != rshift)
+ mask = 0x8080;
+ else
+ mask = 0x8000;
+ snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000,
+ (ac97->regs[AC97_MASTER] & mask) == mask ?
+ 0x8000 : 0);
+ }
+ return err;
+}
+
+static int tune_hp_mute_led(struct snd_ac97 *ac97)
+{
+ struct snd_kcontrol *msw = ctl_find(ac97, "Master Playback Switch", NULL);
+ struct snd_kcontrol *mvol = ctl_find(ac97, "Master Playback Volume", NULL);
+ if (! msw || ! mvol)
+ return -ENOENT;
+ msw->put = hp_master_mute_sw_put;
+ mvol->put = bind_hp_volsw_put;
+ snd_ac97_remove_ctl(ac97, "External Amplifier", NULL);
+ snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch");
+ snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume");
+ snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */
+ return 0;
+}
+
struct quirk_table {
const char *name;
int (*func)(struct snd_ac97 *);
@@ -2471,6 +2506,7 @@ static struct quirk_table applicable_quirks[] = {
{ "alc_jack", tune_alc_jack },
{ "inv_eapd", tune_inv_eapd },
{ "mute_led", tune_mute_led },
+ { "hp_mute_led", tune_hp_mute_led },
};
/* apply the quirk with the given type */
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 33e0664a192..b7217adaf1d 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1353,6 +1353,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
.name = "HP Pavilion ZV5030US",
.type = AC97_TUNE_MUTE_LED
},
+ {
+ .subvendor = 0x103c,
+ .subdevice = 0x308b,
+ .name = "HP nx6125",
+ .type = AC97_TUNE_MUTE_LED
+ },
{ } /* terminator */
};
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index d3a4e5e8e04..5466b1fa0cd 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -1859,6 +1859,30 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
},
{
.subvendor = 0x103c,
+ .subdevice = 0x0938,
+ .name = "HP nc4200",
+ .type = AC97_TUNE_HP_MUTE_LED
+ },
+ {
+ .subvendor = 0x103c,
+ .subdevice = 0x099c,
+ .name = "HP nc6120",
+ .type = AC97_TUNE_HP_MUTE_LED
+ },
+ {
+ .subvendor = 0x103c,
+ .subdevice = 0x0944,
+ .name = "HP nc6220",
+ .type = AC97_TUNE_HP_MUTE_LED
+ },
+ {
+ .subvendor = 0x103c,
+ .subdevice = 0x0934,
+ .name = "HP nc8220",
+ .type = AC97_TUNE_HP_MUTE_LED
+ },
+ {
+ .subvendor = 0x103c,
.subdevice = 0x12f1,
.name = "HP xw8200", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY