aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r--sound/pci/hda/patch_realtek.c71
1 files changed, 56 insertions, 15 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e125c60fe352..7a73621a8909 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -168,7 +168,7 @@ struct alc_spec {
168 unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */ 168 unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */
169 unsigned int automute:1; /* HP automute enabled */ 169 unsigned int automute:1; /* HP automute enabled */
170 unsigned int detect_line:1; /* Line-out detection enabled */ 170 unsigned int detect_line:1; /* Line-out detection enabled */
171 unsigned int automute_lines:1; /* automute line-out as well */ 171 unsigned int automute_lines:1; /* automute line-out as well; NOP when automute_hp_lo isn't set */
172 unsigned int automute_hp_lo:1; /* both HP and LO available */ 172 unsigned int automute_hp_lo:1; /* both HP and LO available */
173 173
174 /* other flags */ 174 /* other flags */
@@ -551,7 +551,7 @@ static void update_speakers(struct hda_codec *codec)
551 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] || 551 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
552 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0]) 552 spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
553 return; 553 return;
554 if (!spec->automute_lines || !spec->automute) 554 if (!spec->automute || (spec->automute_hp_lo && !spec->automute_lines))
555 on = 0; 555 on = 0;
556 else 556 else
557 on = spec->jack_present; 557 on = spec->jack_present;
@@ -565,11 +565,11 @@ static void alc_hp_automute(struct hda_codec *codec)
565{ 565{
566 struct alc_spec *spec = codec->spec; 566 struct alc_spec *spec = codec->spec;
567 567
568 if (!spec->automute)
569 return;
570 spec->jack_present = 568 spec->jack_present =
571 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins), 569 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
572 spec->autocfg.hp_pins); 570 spec->autocfg.hp_pins);
571 if (!spec->automute)
572 return;
573 update_speakers(codec); 573 update_speakers(codec);
574} 574}
575 575
@@ -578,11 +578,15 @@ static void alc_line_automute(struct hda_codec *codec)
578{ 578{
579 struct alc_spec *spec = codec->spec; 579 struct alc_spec *spec = codec->spec;
580 580
581 if (!spec->automute || !spec->detect_line) 581 /* check LO jack only when it's different from HP */
582 if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
582 return; 583 return;
584
583 spec->line_jack_present = 585 spec->line_jack_present =
584 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins), 586 detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
585 spec->autocfg.line_out_pins); 587 spec->autocfg.line_out_pins);
588 if (!spec->automute || !spec->detect_line)
589 return;
586 update_speakers(codec); 590 update_speakers(codec);
587} 591}
588 592
@@ -803,7 +807,7 @@ static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
803 unsigned int val; 807 unsigned int val;
804 if (!spec->automute) 808 if (!spec->automute)
805 val = 0; 809 val = 0;
806 else if (!spec->automute_lines) 810 else if (!spec->automute_hp_lo || !spec->automute_lines)
807 val = 1; 811 val = 1;
808 else 812 else
809 val = 2; 813 val = 2;
@@ -824,7 +828,8 @@ static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
824 spec->automute = 0; 828 spec->automute = 0;
825 break; 829 break;
826 case 1: 830 case 1:
827 if (spec->automute && !spec->automute_lines) 831 if (spec->automute &&
832 (!spec->automute_hp_lo || !spec->automute_lines))
828 return 0; 833 return 0;
829 spec->automute = 1; 834 spec->automute = 1;
830 spec->automute_lines = 0; 835 spec->automute_lines = 0;
@@ -1320,7 +1325,9 @@ do_sku:
1320 * 15 : 1 --> enable the function "Mute internal speaker 1325 * 15 : 1 --> enable the function "Mute internal speaker
1321 * when the external headphone out jack is plugged" 1326 * when the external headphone out jack is plugged"
1322 */ 1327 */
1323 if (!spec->autocfg.hp_pins[0]) { 1328 if (!spec->autocfg.hp_pins[0] &&
1329 !(spec->autocfg.line_out_pins[0] &&
1330 spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
1324 hda_nid_t nid; 1331 hda_nid_t nid;
1325 tmp = (ass >> 11) & 0x3; /* HP to chassis */ 1332 tmp = (ass >> 11) & 0x3; /* HP to chassis */
1326 if (tmp == 0) 1333 if (tmp == 0)
@@ -1784,6 +1791,7 @@ static const char * const alc_slave_vols[] = {
1784 "Speaker Playback Volume", 1791 "Speaker Playback Volume",
1785 "Mono Playback Volume", 1792 "Mono Playback Volume",
1786 "Line-Out Playback Volume", 1793 "Line-Out Playback Volume",
1794 "PCM Playback Volume",
1787 NULL, 1795 NULL,
1788}; 1796};
1789 1797
@@ -1798,6 +1806,7 @@ static const char * const alc_slave_sws[] = {
1798 "Mono Playback Switch", 1806 "Mono Playback Switch",
1799 "IEC958 Playback Switch", 1807 "IEC958 Playback Switch",
1800 "Line-Out Playback Switch", 1808 "Line-Out Playback Switch",
1809 "PCM Playback Switch",
1801 NULL, 1810 NULL,
1802}; 1811};
1803 1812
@@ -3081,16 +3090,22 @@ static void alc_auto_init_multi_out(struct hda_codec *codec)
3081static void alc_auto_init_extra_out(struct hda_codec *codec) 3090static void alc_auto_init_extra_out(struct hda_codec *codec)
3082{ 3091{
3083 struct alc_spec *spec = codec->spec; 3092 struct alc_spec *spec = codec->spec;
3084 hda_nid_t pin; 3093 hda_nid_t pin, dac;
3085 3094
3086 pin = spec->autocfg.hp_pins[0]; 3095 pin = spec->autocfg.hp_pins[0];
3087 if (pin) 3096 if (pin) {
3088 alc_auto_set_output_and_unmute(codec, pin, PIN_HP, 3097 dac = spec->multiout.hp_nid;
3089 spec->multiout.hp_nid); 3098 if (!dac)
3099 dac = spec->multiout.dac_nids[0];
3100 alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
3101 }
3090 pin = spec->autocfg.speaker_pins[0]; 3102 pin = spec->autocfg.speaker_pins[0];
3091 if (pin) 3103 if (pin) {
3092 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, 3104 dac = spec->multiout.extra_out_nid[0];
3093 spec->multiout.extra_out_nid[0]); 3105 if (!dac)
3106 dac = spec->multiout.dac_nids[0];
3107 alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
3108 }
3094} 3109}
3095 3110
3096/* 3111/*
@@ -4484,6 +4499,22 @@ static void alc269_fixup_pcm_44k(struct hda_codec *codec,
4484 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture; 4499 spec->stream_analog_capture = &alc269_44k_pcm_analog_capture;
4485} 4500}
4486 4501
4502static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
4503 const struct alc_fixup *fix, int action)
4504{
4505 int coef;
4506
4507 if (action != ALC_FIXUP_ACT_INIT)
4508 return;
4509 /* The digital-mic unit sends PDM (differential signal) instead of
4510 * the standard PCM, thus you can't record a valid mono stream as is.
4511 * Below is a workaround specific to ALC269 to control the dmic
4512 * signal source as mono.
4513 */
4514 coef = alc_read_coef_idx(codec, 0x07);
4515 alc_write_coef_idx(codec, 0x07, coef | 0x80);
4516}
4517
4487enum { 4518enum {
4488 ALC269_FIXUP_SONY_VAIO, 4519 ALC269_FIXUP_SONY_VAIO,
4489 ALC275_FIXUP_SONY_VAIO_GPIO2, 4520 ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -4494,6 +4525,7 @@ enum {
4494 ALC275_FIXUP_SONY_HWEQ, 4525 ALC275_FIXUP_SONY_HWEQ,
4495 ALC271_FIXUP_DMIC, 4526 ALC271_FIXUP_DMIC,
4496 ALC269_FIXUP_PCM_44K, 4527 ALC269_FIXUP_PCM_44K,
4528 ALC269_FIXUP_STEREO_DMIC,
4497}; 4529};
4498 4530
4499static const struct alc_fixup alc269_fixups[] = { 4531static const struct alc_fixup alc269_fixups[] = {
@@ -4556,10 +4588,19 @@ static const struct alc_fixup alc269_fixups[] = {
4556 .type = ALC_FIXUP_FUNC, 4588 .type = ALC_FIXUP_FUNC,
4557 .v.func = alc269_fixup_pcm_44k, 4589 .v.func = alc269_fixup_pcm_44k,
4558 }, 4590 },
4591 [ALC269_FIXUP_STEREO_DMIC] = {
4592 .type = ALC_FIXUP_FUNC,
4593 .v.func = alc269_fixup_stereo_dmic,
4594 },
4559}; 4595};
4560 4596
4561static const struct snd_pci_quirk alc269_fixup_tbl[] = { 4597static const struct snd_pci_quirk alc269_fixup_tbl[] = {
4562 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), 4598 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
4599 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
4600 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4601 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4602 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4603 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4563 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2), 4604 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4564 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), 4605 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4565 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), 4606 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),