diff options
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 71 |
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) | |||
3081 | static void alc_auto_init_extra_out(struct hda_codec *codec) | 3090 | static 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 | ||
4502 | static 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 | |||
4487 | enum { | 4518 | enum { |
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 | ||
4499 | static const struct alc_fixup alc269_fixups[] = { | 4531 | static 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 | ||
4561 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 4597 | static 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), |