diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index a1814cd954913ef3668a3e6525da0e272a25ecd3..b0b3ea7b365e81668594eae8db8831144072d405 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 33d7a1fc2f9f493f8c2cb458ea1e430eb63f869f..3020ca2b602bd10d16d575d7c011bd792e7a762a 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 33e0664a1925a1c33682ee490bf92358554e6e72..b7217adaf1d76b69ee63685cce59d029ebecc77f 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 d3a4e5e8e0446d62abe2fa80ae4bf3bc47be6314..5466b1fa0cd58d7baaead97bad5d8eac6355447a 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -1857,6 +1857,30 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "HP xw8000", .type = AC97_TUNE_HP_ONLY }, + { + .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,