aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-01-30 04:54:08 -0500
committerTakashi Iwai <tiwai@suse.de>2012-01-30 10:26:07 -0500
commit31150f2327cbb66363f38e13ca1be973d2f9203a (patch)
treec12fbc5b2beaf9f763897786426bc82834cbd37e /sound/pci/hda/patch_realtek.c
parent8422fa110334cea79ab16c474902edb21a8b3168 (diff)
ALSA: hda - Apply 0x0f-VREF fix to all ASUS laptops with ALC861/660
It turned out that other ASUS laptops require the similar fix to enable the VREF on the pin 0x0f for the secret output amp, not only ASUS A6Rp. Moreover, it's required even when the pin is being used as the output. Thus, writing a fixed value doesn't work always. This patch applies the VREF-fix for all ASUS laptops with ALC861/660 in a fixup function that checks the current value and turns on only the VREF value no matter whether input or output direction is set. The automute function is modified as well to keep the pin VREF upon muting/unmuting via pin-control; otherwise the pin VREF is reset at plugging/unplugging a jack. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42588 Cc: <stable@kernel.org> [v3.2+] Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index a7f17becbd7c..42b6a01e17db 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -177,6 +177,7 @@ struct alc_spec {
177 unsigned int detect_lo:1; /* Line-out detection enabled */ 177 unsigned int detect_lo:1; /* Line-out detection enabled */
178 unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */ 178 unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
179 unsigned int automute_lo_possible:1; /* there are line outs and HP */ 179 unsigned int automute_lo_possible:1; /* there are line outs and HP */
180 unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
180 181
181 /* other flags */ 182 /* other flags */
182 unsigned int no_analog :1; /* digital I/O only */ 183 unsigned int no_analog :1; /* digital I/O only */
@@ -495,13 +496,24 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
495 496
496 for (i = 0; i < num_pins; i++) { 497 for (i = 0; i < num_pins; i++) {
497 hda_nid_t nid = pins[i]; 498 hda_nid_t nid = pins[i];
499 unsigned int val;
498 if (!nid) 500 if (!nid)
499 break; 501 break;
500 switch (spec->automute_mode) { 502 switch (spec->automute_mode) {
501 case ALC_AUTOMUTE_PIN: 503 case ALC_AUTOMUTE_PIN:
504 /* don't reset VREF value in case it's controlling
505 * the amp (see alc861_fixup_asus_amp_vref_0f())
506 */
507 if (spec->keep_vref_in_automute) {
508 val = snd_hda_codec_read(codec, nid, 0,
509 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
510 val &= ~PIN_HP;
511 } else
512 val = 0;
513 val |= pin_bits;
502 snd_hda_codec_write(codec, nid, 0, 514 snd_hda_codec_write(codec, nid, 0,
503 AC_VERB_SET_PIN_WIDGET_CONTROL, 515 AC_VERB_SET_PIN_WIDGET_CONTROL,
504 pin_bits); 516 val);
505 break; 517 break;
506 case ALC_AUTOMUTE_AMP: 518 case ALC_AUTOMUTE_AMP:
507 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, 519 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
@@ -5588,6 +5600,25 @@ enum {
5588 PINFIX_ASUS_A6RP, 5600 PINFIX_ASUS_A6RP,
5589}; 5601};
5590 5602
5603/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
5604static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
5605 const struct alc_fixup *fix, int action)
5606{
5607 struct alc_spec *spec = codec->spec;
5608 unsigned int val;
5609
5610 if (action != ALC_FIXUP_ACT_INIT)
5611 return;
5612 val = snd_hda_codec_read(codec, 0x0f, 0,
5613 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
5614 if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
5615 val |= AC_PINCTL_IN_EN;
5616 val |= AC_PINCTL_VREF_50;
5617 snd_hda_codec_write(codec, 0x0f, 0,
5618 AC_VERB_SET_PIN_WIDGET_CONTROL, val);
5619 spec->keep_vref_in_automute = 1;
5620}
5621
5591static const struct alc_fixup alc861_fixups[] = { 5622static const struct alc_fixup alc861_fixups[] = {
5592 [PINFIX_FSC_AMILO_PI1505] = { 5623 [PINFIX_FSC_AMILO_PI1505] = {
5593 .type = ALC_FIXUP_PINS, 5624 .type = ALC_FIXUP_PINS,
@@ -5598,17 +5629,13 @@ static const struct alc_fixup alc861_fixups[] = {
5598 } 5629 }
5599 }, 5630 },
5600 [PINFIX_ASUS_A6RP] = { 5631 [PINFIX_ASUS_A6RP] = {
5601 .type = ALC_FIXUP_VERBS, 5632 .type = ALC_FIXUP_FUNC,
5602 .v.verbs = (const struct hda_verb[]) { 5633 .v.func = alc861_fixup_asus_amp_vref_0f,
5603 /* node 0x0f VREF seems controlling the master output */
5604 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
5605 { }
5606 },
5607 }, 5634 },
5608}; 5635};
5609 5636
5610static const struct snd_pci_quirk alc861_fixup_tbl[] = { 5637static const struct snd_pci_quirk alc861_fixup_tbl[] = {
5611 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", PINFIX_ASUS_A6RP), 5638 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP),
5612 SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP), 5639 SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
5613 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505), 5640 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
5614 {} 5641 {}