diff options
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 87 |
1 files changed, 64 insertions, 23 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0db1dc49382b..1358987c49d8 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, |
@@ -1843,6 +1855,8 @@ static const char * const alc_slave_vols[] = { | |||
1843 | "Speaker Playback Volume", | 1855 | "Speaker Playback Volume", |
1844 | "Mono Playback Volume", | 1856 | "Mono Playback Volume", |
1845 | "Line-Out Playback Volume", | 1857 | "Line-Out Playback Volume", |
1858 | "CLFE Playback Volume", | ||
1859 | "Bass Speaker Playback Volume", | ||
1846 | "PCM Playback Volume", | 1860 | "PCM Playback Volume", |
1847 | NULL, | 1861 | NULL, |
1848 | }; | 1862 | }; |
@@ -1858,6 +1872,8 @@ static const char * const alc_slave_sws[] = { | |||
1858 | "Mono Playback Switch", | 1872 | "Mono Playback Switch", |
1859 | "IEC958 Playback Switch", | 1873 | "IEC958 Playback Switch", |
1860 | "Line-Out Playback Switch", | 1874 | "Line-Out Playback Switch", |
1875 | "CLFE Playback Switch", | ||
1876 | "Bass Speaker Playback Switch", | ||
1861 | "PCM Playback Switch", | 1877 | "PCM Playback Switch", |
1862 | NULL, | 1878 | NULL, |
1863 | }; | 1879 | }; |
@@ -2306,7 +2322,7 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
2306 | "%s Analog", codec->chip_name); | 2322 | "%s Analog", codec->chip_name); |
2307 | info->name = spec->stream_name_analog; | 2323 | info->name = spec->stream_name_analog; |
2308 | 2324 | ||
2309 | if (spec->multiout.dac_nids > 0) { | 2325 | if (spec->multiout.num_dacs > 0) { |
2310 | p = spec->stream_analog_playback; | 2326 | p = spec->stream_analog_playback; |
2311 | if (!p) | 2327 | if (!p) |
2312 | p = &alc_pcm_analog_playback; | 2328 | p = &alc_pcm_analog_playback; |
@@ -4358,6 +4374,7 @@ enum { | |||
4358 | ALC882_FIXUP_ACER_ASPIRE_8930G, | 4374 | ALC882_FIXUP_ACER_ASPIRE_8930G, |
4359 | ALC882_FIXUP_ASPIRE_8930G_VERBS, | 4375 | ALC882_FIXUP_ASPIRE_8930G_VERBS, |
4360 | ALC885_FIXUP_MACPRO_GPIO, | 4376 | ALC885_FIXUP_MACPRO_GPIO, |
4377 | ALC889_FIXUP_DAC_ROUTE, | ||
4361 | }; | 4378 | }; |
4362 | 4379 | ||
4363 | static void alc889_fixup_coef(struct hda_codec *codec, | 4380 | static void alc889_fixup_coef(struct hda_codec *codec, |
@@ -4411,6 +4428,23 @@ static void alc885_fixup_macpro_gpio(struct hda_codec *codec, | |||
4411 | alc882_gpio_mute(codec, 1, 0); | 4428 | alc882_gpio_mute(codec, 1, 0); |
4412 | } | 4429 | } |
4413 | 4430 | ||
4431 | /* Fix the connection of some pins for ALC889: | ||
4432 | * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't | ||
4433 | * work correctly (bko#42740) | ||
4434 | */ | ||
4435 | static void alc889_fixup_dac_route(struct hda_codec *codec, | ||
4436 | const struct alc_fixup *fix, int action) | ||
4437 | { | ||
4438 | if (action == ALC_FIXUP_ACT_PRE_PROBE) { | ||
4439 | hda_nid_t conn1[2] = { 0x0c, 0x0d }; | ||
4440 | hda_nid_t conn2[2] = { 0x0e, 0x0f }; | ||
4441 | snd_hda_override_conn_list(codec, 0x14, 2, conn1); | ||
4442 | snd_hda_override_conn_list(codec, 0x15, 2, conn1); | ||
4443 | snd_hda_override_conn_list(codec, 0x18, 2, conn2); | ||
4444 | snd_hda_override_conn_list(codec, 0x1a, 2, conn2); | ||
4445 | } | ||
4446 | } | ||
4447 | |||
4414 | static const struct alc_fixup alc882_fixups[] = { | 4448 | static const struct alc_fixup alc882_fixups[] = { |
4415 | [ALC882_FIXUP_ABIT_AW9D_MAX] = { | 4449 | [ALC882_FIXUP_ABIT_AW9D_MAX] = { |
4416 | .type = ALC_FIXUP_PINS, | 4450 | .type = ALC_FIXUP_PINS, |
@@ -4558,6 +4592,10 @@ static const struct alc_fixup alc882_fixups[] = { | |||
4558 | .type = ALC_FIXUP_FUNC, | 4592 | .type = ALC_FIXUP_FUNC, |
4559 | .v.func = alc885_fixup_macpro_gpio, | 4593 | .v.func = alc885_fixup_macpro_gpio, |
4560 | }, | 4594 | }, |
4595 | [ALC889_FIXUP_DAC_ROUTE] = { | ||
4596 | .type = ALC_FIXUP_FUNC, | ||
4597 | .v.func = alc889_fixup_dac_route, | ||
4598 | }, | ||
4561 | }; | 4599 | }; |
4562 | 4600 | ||
4563 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { | 4601 | static const struct snd_pci_quirk alc882_fixup_tbl[] = { |
@@ -4582,6 +4620,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { | |||
4582 | SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G", | 4620 | SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G", |
4583 | ALC882_FIXUP_ACER_ASPIRE_4930G), | 4621 | ALC882_FIXUP_ACER_ASPIRE_4930G), |
4584 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210), | 4622 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210), |
4623 | SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE), | ||
4585 | SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736), | 4624 | SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736), |
4586 | SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD), | 4625 | SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD), |
4587 | SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V), | 4626 | SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V), |
@@ -4735,7 +4774,6 @@ enum { | |||
4735 | ALC262_FIXUP_FSC_H270, | 4774 | ALC262_FIXUP_FSC_H270, |
4736 | ALC262_FIXUP_HP_Z200, | 4775 | ALC262_FIXUP_HP_Z200, |
4737 | ALC262_FIXUP_TYAN, | 4776 | ALC262_FIXUP_TYAN, |
4738 | ALC262_FIXUP_TOSHIBA_RX1, | ||
4739 | ALC262_FIXUP_LENOVO_3000, | 4777 | ALC262_FIXUP_LENOVO_3000, |
4740 | ALC262_FIXUP_BENQ, | 4778 | ALC262_FIXUP_BENQ, |
4741 | ALC262_FIXUP_BENQ_T31, | 4779 | ALC262_FIXUP_BENQ_T31, |
@@ -4765,16 +4803,6 @@ static const struct alc_fixup alc262_fixups[] = { | |||
4765 | { } | 4803 | { } |
4766 | } | 4804 | } |
4767 | }, | 4805 | }, |
4768 | [ALC262_FIXUP_TOSHIBA_RX1] = { | ||
4769 | .type = ALC_FIXUP_PINS, | ||
4770 | .v.pins = (const struct alc_pincfg[]) { | ||
4771 | { 0x14, 0x90170110 }, /* speaker */ | ||
4772 | { 0x15, 0x0421101f }, /* HP */ | ||
4773 | { 0x1a, 0x40f000f0 }, /* N/A */ | ||
4774 | { 0x1b, 0x40f000f0 }, /* N/A */ | ||
4775 | { 0x1e, 0x40f000f0 }, /* N/A */ | ||
4776 | } | ||
4777 | }, | ||
4778 | [ALC262_FIXUP_LENOVO_3000] = { | 4806 | [ALC262_FIXUP_LENOVO_3000] = { |
4779 | .type = ALC_FIXUP_VERBS, | 4807 | .type = ALC_FIXUP_VERBS, |
4780 | .v.verbs = (const struct hda_verb[]) { | 4808 | .v.verbs = (const struct hda_verb[]) { |
@@ -4807,8 +4835,6 @@ static const struct snd_pci_quirk alc262_fixup_tbl[] = { | |||
4807 | SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ), | 4835 | SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ), |
4808 | SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ), | 4836 | SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ), |
4809 | SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN), | 4837 | SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN), |
4810 | SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1", | ||
4811 | ALC262_FIXUP_TOSHIBA_RX1), | ||
4812 | SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270), | 4838 | SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270), |
4813 | SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000), | 4839 | SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000), |
4814 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ), | 4840 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ), |
@@ -5377,7 +5403,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
5377 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", | 5403 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", |
5378 | ALC269_FIXUP_AMIC), | 5404 | ALC269_FIXUP_AMIC), |
5379 | SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC), | 5405 | SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC), |
5380 | SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269_FIXUP_AMIC), | ||
5381 | SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC), | 5406 | SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC), |
5382 | SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC), | 5407 | SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC), |
5383 | SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC), | 5408 | SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC), |
@@ -5589,6 +5614,25 @@ enum { | |||
5589 | PINFIX_ASUS_A6RP, | 5614 | PINFIX_ASUS_A6RP, |
5590 | }; | 5615 | }; |
5591 | 5616 | ||
5617 | /* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */ | ||
5618 | static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec, | ||
5619 | const struct alc_fixup *fix, int action) | ||
5620 | { | ||
5621 | struct alc_spec *spec = codec->spec; | ||
5622 | unsigned int val; | ||
5623 | |||
5624 | if (action != ALC_FIXUP_ACT_INIT) | ||
5625 | return; | ||
5626 | val = snd_hda_codec_read(codec, 0x0f, 0, | ||
5627 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5628 | if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))) | ||
5629 | val |= AC_PINCTL_IN_EN; | ||
5630 | val |= AC_PINCTL_VREF_50; | ||
5631 | snd_hda_codec_write(codec, 0x0f, 0, | ||
5632 | AC_VERB_SET_PIN_WIDGET_CONTROL, val); | ||
5633 | spec->keep_vref_in_automute = 1; | ||
5634 | } | ||
5635 | |||
5592 | static const struct alc_fixup alc861_fixups[] = { | 5636 | static const struct alc_fixup alc861_fixups[] = { |
5593 | [PINFIX_FSC_AMILO_PI1505] = { | 5637 | [PINFIX_FSC_AMILO_PI1505] = { |
5594 | .type = ALC_FIXUP_PINS, | 5638 | .type = ALC_FIXUP_PINS, |
@@ -5599,17 +5643,14 @@ static const struct alc_fixup alc861_fixups[] = { | |||
5599 | } | 5643 | } |
5600 | }, | 5644 | }, |
5601 | [PINFIX_ASUS_A6RP] = { | 5645 | [PINFIX_ASUS_A6RP] = { |
5602 | .type = ALC_FIXUP_VERBS, | 5646 | .type = ALC_FIXUP_FUNC, |
5603 | .v.verbs = (const struct hda_verb[]) { | 5647 | .v.func = alc861_fixup_asus_amp_vref_0f, |
5604 | /* node 0x0f VREF seems controlling the master output */ | ||
5605 | { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
5606 | { } | ||
5607 | }, | ||
5608 | }, | 5648 | }, |
5609 | }; | 5649 | }; |
5610 | 5650 | ||
5611 | static const struct snd_pci_quirk alc861_fixup_tbl[] = { | 5651 | static const struct snd_pci_quirk alc861_fixup_tbl[] = { |
5612 | SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", PINFIX_ASUS_A6RP), | 5652 | SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP), |
5653 | SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", PINFIX_ASUS_A6RP), | ||
5613 | SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP), | 5654 | SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP), |
5614 | SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505), | 5655 | SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505), |
5615 | {} | 5656 | {} |