diff options
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 720 |
1 files changed, 628 insertions, 92 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 596ea2f12cf6..6ac53f7de549 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -256,6 +256,13 @@ enum { | |||
256 | ALC882_MODEL_LAST, | 256 | ALC882_MODEL_LAST, |
257 | }; | 257 | }; |
258 | 258 | ||
259 | /* ALC680 models */ | ||
260 | enum { | ||
261 | ALC680_BASE, | ||
262 | ALC680_AUTO, | ||
263 | ALC680_MODEL_LAST, | ||
264 | }; | ||
265 | |||
259 | /* for GPIO Poll */ | 266 | /* for GPIO Poll */ |
260 | #define GPIO_MASK 0x03 | 267 | #define GPIO_MASK 0x03 |
261 | 268 | ||
@@ -326,6 +333,12 @@ struct alc_spec { | |||
326 | hda_nid_t *capsrc_nids; | 333 | hda_nid_t *capsrc_nids; |
327 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | 334 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
328 | 335 | ||
336 | /* capture setup for dynamic dual-adc switch */ | ||
337 | unsigned int cur_adc_idx; | ||
338 | hda_nid_t cur_adc; | ||
339 | unsigned int cur_adc_stream_tag; | ||
340 | unsigned int cur_adc_format; | ||
341 | |||
329 | /* capture source */ | 342 | /* capture source */ |
330 | unsigned int num_mux_defs; | 343 | unsigned int num_mux_defs; |
331 | const struct hda_input_mux *input_mux; | 344 | const struct hda_input_mux *input_mux; |
@@ -367,6 +380,7 @@ struct alc_spec { | |||
367 | 380 | ||
368 | /* other flags */ | 381 | /* other flags */ |
369 | unsigned int no_analog :1; /* digital I/O only */ | 382 | unsigned int no_analog :1; /* digital I/O only */ |
383 | unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ | ||
370 | int init_amp; | 384 | int init_amp; |
371 | 385 | ||
372 | /* for virtual master */ | 386 | /* for virtual master */ |
@@ -833,9 +847,13 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, | |||
833 | 847 | ||
834 | if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { | 848 | if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { |
835 | unsigned int pincap; | 849 | unsigned int pincap; |
850 | unsigned int oldval; | ||
851 | oldval = snd_hda_codec_read(codec, nid, 0, | ||
852 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
836 | pincap = snd_hda_query_pin_caps(codec, nid); | 853 | pincap = snd_hda_query_pin_caps(codec, nid); |
837 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; | 854 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; |
838 | if (pincap & AC_PINCAP_VREF_80) | 855 | /* if the default pin setup is vref50, we give it priority */ |
856 | if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50) | ||
839 | val = PIN_VREF80; | 857 | val = PIN_VREF80; |
840 | else if (pincap & AC_PINCAP_VREF_50) | 858 | else if (pincap & AC_PINCAP_VREF_50) |
841 | val = PIN_VREF50; | 859 | val = PIN_VREF50; |
@@ -1003,6 +1021,29 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | |||
1003 | return -1; | 1021 | return -1; |
1004 | } | 1022 | } |
1005 | 1023 | ||
1024 | /* switch the current ADC according to the jack state */ | ||
1025 | static void alc_dual_mic_adc_auto_switch(struct hda_codec *codec) | ||
1026 | { | ||
1027 | struct alc_spec *spec = codec->spec; | ||
1028 | unsigned int present; | ||
1029 | hda_nid_t new_adc; | ||
1030 | |||
1031 | present = snd_hda_jack_detect(codec, spec->ext_mic.pin); | ||
1032 | if (present) | ||
1033 | spec->cur_adc_idx = 1; | ||
1034 | else | ||
1035 | spec->cur_adc_idx = 0; | ||
1036 | new_adc = spec->adc_nids[spec->cur_adc_idx]; | ||
1037 | if (spec->cur_adc && spec->cur_adc != new_adc) { | ||
1038 | /* stream is running, let's swap the current ADC */ | ||
1039 | snd_hda_codec_cleanup_stream(codec, spec->cur_adc); | ||
1040 | spec->cur_adc = new_adc; | ||
1041 | snd_hda_codec_setup_stream(codec, new_adc, | ||
1042 | spec->cur_adc_stream_tag, 0, | ||
1043 | spec->cur_adc_format); | ||
1044 | } | ||
1045 | } | ||
1046 | |||
1006 | static void alc_mic_automute(struct hda_codec *codec) | 1047 | static void alc_mic_automute(struct hda_codec *codec) |
1007 | { | 1048 | { |
1008 | struct alc_spec *spec = codec->spec; | 1049 | struct alc_spec *spec = codec->spec; |
@@ -1017,6 +1058,11 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
1017 | if (snd_BUG_ON(!spec->adc_nids)) | 1058 | if (snd_BUG_ON(!spec->adc_nids)) |
1018 | return; | 1059 | return; |
1019 | 1060 | ||
1061 | if (spec->dual_adc_switch) { | ||
1062 | alc_dual_mic_adc_auto_switch(codec); | ||
1063 | return; | ||
1064 | } | ||
1065 | |||
1020 | cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0]; | 1066 | cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0]; |
1021 | 1067 | ||
1022 | present = snd_hda_jack_detect(codec, spec->ext_mic.pin); | 1068 | present = snd_hda_jack_detect(codec, spec->ext_mic.pin); |
@@ -1499,6 +1545,63 @@ static int alc_read_coef_idx(struct hda_codec *codec, | |||
1499 | return val; | 1545 | return val; |
1500 | } | 1546 | } |
1501 | 1547 | ||
1548 | /* set right pin controls for digital I/O */ | ||
1549 | static void alc_auto_init_digital(struct hda_codec *codec) | ||
1550 | { | ||
1551 | struct alc_spec *spec = codec->spec; | ||
1552 | int i; | ||
1553 | hda_nid_t pin; | ||
1554 | |||
1555 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
1556 | pin = spec->autocfg.dig_out_pins[i]; | ||
1557 | if (pin) { | ||
1558 | snd_hda_codec_write(codec, pin, 0, | ||
1559 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
1560 | PIN_OUT); | ||
1561 | } | ||
1562 | } | ||
1563 | pin = spec->autocfg.dig_in_pin; | ||
1564 | if (pin) | ||
1565 | snd_hda_codec_write(codec, pin, 0, | ||
1566 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
1567 | PIN_IN); | ||
1568 | } | ||
1569 | |||
1570 | /* parse digital I/Os and set up NIDs in BIOS auto-parse mode */ | ||
1571 | static void alc_auto_parse_digital(struct hda_codec *codec) | ||
1572 | { | ||
1573 | struct alc_spec *spec = codec->spec; | ||
1574 | int i, err; | ||
1575 | hda_nid_t dig_nid; | ||
1576 | |||
1577 | /* support multiple SPDIFs; the secondary is set up as a slave */ | ||
1578 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
1579 | err = snd_hda_get_connections(codec, | ||
1580 | spec->autocfg.dig_out_pins[i], | ||
1581 | &dig_nid, 1); | ||
1582 | if (err < 0) | ||
1583 | continue; | ||
1584 | if (!i) { | ||
1585 | spec->multiout.dig_out_nid = dig_nid; | ||
1586 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
1587 | } else { | ||
1588 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
1589 | if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
1590 | break; | ||
1591 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
1592 | } | ||
1593 | } | ||
1594 | |||
1595 | if (spec->autocfg.dig_in_pin) { | ||
1596 | hda_nid_t dig_nid; | ||
1597 | err = snd_hda_get_connections(codec, | ||
1598 | spec->autocfg.dig_in_pin, | ||
1599 | &dig_nid, 1); | ||
1600 | if (err > 0) | ||
1601 | spec->dig_in_nid = dig_nid; | ||
1602 | } | ||
1603 | } | ||
1604 | |||
1502 | /* | 1605 | /* |
1503 | * ALC888 | 1606 | * ALC888 |
1504 | */ | 1607 | */ |
@@ -3607,6 +3710,41 @@ static int alc880_alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
3607 | return 0; | 3710 | return 0; |
3608 | } | 3711 | } |
3609 | 3712 | ||
3713 | /* analog capture with dynamic dual-adc changes */ | ||
3714 | static int dualmic_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
3715 | struct hda_codec *codec, | ||
3716 | unsigned int stream_tag, | ||
3717 | unsigned int format, | ||
3718 | struct snd_pcm_substream *substream) | ||
3719 | { | ||
3720 | struct alc_spec *spec = codec->spec; | ||
3721 | spec->cur_adc = spec->adc_nids[spec->cur_adc_idx]; | ||
3722 | spec->cur_adc_stream_tag = stream_tag; | ||
3723 | spec->cur_adc_format = format; | ||
3724 | snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); | ||
3725 | return 0; | ||
3726 | } | ||
3727 | |||
3728 | static int dualmic_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
3729 | struct hda_codec *codec, | ||
3730 | struct snd_pcm_substream *substream) | ||
3731 | { | ||
3732 | struct alc_spec *spec = codec->spec; | ||
3733 | snd_hda_codec_cleanup_stream(codec, spec->cur_adc); | ||
3734 | spec->cur_adc = 0; | ||
3735 | return 0; | ||
3736 | } | ||
3737 | |||
3738 | static struct hda_pcm_stream dualmic_pcm_analog_capture = { | ||
3739 | .substreams = 1, | ||
3740 | .channels_min = 2, | ||
3741 | .channels_max = 2, | ||
3742 | .nid = 0, /* fill later */ | ||
3743 | .ops = { | ||
3744 | .prepare = dualmic_capture_pcm_prepare, | ||
3745 | .cleanup = dualmic_capture_pcm_cleanup | ||
3746 | }, | ||
3747 | }; | ||
3610 | 3748 | ||
3611 | /* | 3749 | /* |
3612 | */ | 3750 | */ |
@@ -4936,7 +5074,7 @@ static void alc880_auto_init_input_src(struct hda_codec *codec) | |||
4936 | static int alc880_parse_auto_config(struct hda_codec *codec) | 5074 | static int alc880_parse_auto_config(struct hda_codec *codec) |
4937 | { | 5075 | { |
4938 | struct alc_spec *spec = codec->spec; | 5076 | struct alc_spec *spec = codec->spec; |
4939 | int i, err; | 5077 | int err; |
4940 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; | 5078 | static hda_nid_t alc880_ignore[] = { 0x1d, 0 }; |
4941 | 5079 | ||
4942 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 5080 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
@@ -4967,25 +5105,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
4967 | 5105 | ||
4968 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 5106 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
4969 | 5107 | ||
4970 | /* check multiple SPDIF-out (for recent codecs) */ | 5108 | alc_auto_parse_digital(codec); |
4971 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
4972 | hda_nid_t dig_nid; | ||
4973 | err = snd_hda_get_connections(codec, | ||
4974 | spec->autocfg.dig_out_pins[i], | ||
4975 | &dig_nid, 1); | ||
4976 | if (err < 0) | ||
4977 | continue; | ||
4978 | if (!i) | ||
4979 | spec->multiout.dig_out_nid = dig_nid; | ||
4980 | else { | ||
4981 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
4982 | if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
4983 | break; | ||
4984 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
4985 | } | ||
4986 | } | ||
4987 | if (spec->autocfg.dig_in_pin) | ||
4988 | spec->dig_in_nid = ALC880_DIGIN_NID; | ||
4989 | 5109 | ||
4990 | if (spec->kctls.list) | 5110 | if (spec->kctls.list) |
4991 | add_mixer(spec, spec->kctls.list); | 5111 | add_mixer(spec, spec->kctls.list); |
@@ -5008,6 +5128,7 @@ static void alc880_auto_init(struct hda_codec *codec) | |||
5008 | alc880_auto_init_extra_out(codec); | 5128 | alc880_auto_init_extra_out(codec); |
5009 | alc880_auto_init_analog_input(codec); | 5129 | alc880_auto_init_analog_input(codec); |
5010 | alc880_auto_init_input_src(codec); | 5130 | alc880_auto_init_input_src(codec); |
5131 | alc_auto_init_digital(codec); | ||
5011 | if (spec->unsol_event) | 5132 | if (spec->unsol_event) |
5012 | alc_inithook(codec); | 5133 | alc_inithook(codec); |
5013 | } | 5134 | } |
@@ -5045,6 +5166,39 @@ static void fixup_automic_adc(struct hda_codec *codec) | |||
5045 | spec->auto_mic = 0; /* disable auto-mic to be sure */ | 5166 | spec->auto_mic = 0; /* disable auto-mic to be sure */ |
5046 | } | 5167 | } |
5047 | 5168 | ||
5169 | /* select or unmute the given capsrc route */ | ||
5170 | static void select_or_unmute_capsrc(struct hda_codec *codec, hda_nid_t cap, | ||
5171 | int idx) | ||
5172 | { | ||
5173 | if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) { | ||
5174 | snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx, | ||
5175 | HDA_AMP_MUTE, 0); | ||
5176 | } else { | ||
5177 | snd_hda_codec_write_cache(codec, cap, 0, | ||
5178 | AC_VERB_SET_CONNECT_SEL, idx); | ||
5179 | } | ||
5180 | } | ||
5181 | |||
5182 | /* set the default connection to that pin */ | ||
5183 | static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin) | ||
5184 | { | ||
5185 | struct alc_spec *spec = codec->spec; | ||
5186 | int i; | ||
5187 | |||
5188 | for (i = 0; i < spec->num_adc_nids; i++) { | ||
5189 | hda_nid_t cap = spec->capsrc_nids ? | ||
5190 | spec->capsrc_nids[i] : spec->adc_nids[i]; | ||
5191 | int idx; | ||
5192 | |||
5193 | idx = get_connection_index(codec, cap, pin); | ||
5194 | if (idx < 0) | ||
5195 | continue; | ||
5196 | select_or_unmute_capsrc(codec, cap, idx); | ||
5197 | return i; /* return the found index */ | ||
5198 | } | ||
5199 | return -1; /* not found */ | ||
5200 | } | ||
5201 | |||
5048 | /* choose the ADC/MUX containing the input pin and initialize the setup */ | 5202 | /* choose the ADC/MUX containing the input pin and initialize the setup */ |
5049 | static void fixup_single_adc(struct hda_codec *codec) | 5203 | static void fixup_single_adc(struct hda_codec *codec) |
5050 | { | 5204 | { |
@@ -5061,33 +5215,24 @@ static void fixup_single_adc(struct hda_codec *codec) | |||
5061 | } | 5215 | } |
5062 | if (!pin) | 5216 | if (!pin) |
5063 | return; | 5217 | return; |
5064 | 5218 | i = init_capsrc_for_pin(codec, pin); | |
5065 | /* set the default connection to that pin */ | 5219 | if (i >= 0) { |
5066 | for (i = 0; i < spec->num_adc_nids; i++) { | ||
5067 | hda_nid_t cap = spec->capsrc_nids ? | ||
5068 | spec->capsrc_nids[i] : spec->adc_nids[i]; | ||
5069 | int idx; | ||
5070 | |||
5071 | idx = get_connection_index(codec, cap, pin); | ||
5072 | if (idx < 0) | ||
5073 | continue; | ||
5074 | /* use only this ADC */ | 5220 | /* use only this ADC */ |
5075 | if (spec->capsrc_nids) | 5221 | if (spec->capsrc_nids) |
5076 | spec->capsrc_nids += i; | 5222 | spec->capsrc_nids += i; |
5077 | spec->adc_nids += i; | 5223 | spec->adc_nids += i; |
5078 | spec->num_adc_nids = 1; | 5224 | spec->num_adc_nids = 1; |
5079 | /* select or unmute this route */ | ||
5080 | if (get_wcaps_type(get_wcaps(codec, cap)) == AC_WID_AUD_MIX) { | ||
5081 | snd_hda_codec_amp_stereo(codec, cap, HDA_INPUT, idx, | ||
5082 | HDA_AMP_MUTE, 0); | ||
5083 | } else { | ||
5084 | snd_hda_codec_write_cache(codec, cap, 0, | ||
5085 | AC_VERB_SET_CONNECT_SEL, idx); | ||
5086 | } | ||
5087 | return; | ||
5088 | } | 5225 | } |
5089 | } | 5226 | } |
5090 | 5227 | ||
5228 | /* initialize dual adcs */ | ||
5229 | static void fixup_dual_adc_switch(struct hda_codec *codec) | ||
5230 | { | ||
5231 | struct alc_spec *spec = codec->spec; | ||
5232 | init_capsrc_for_pin(codec, spec->ext_mic.pin); | ||
5233 | init_capsrc_for_pin(codec, spec->int_mic.pin); | ||
5234 | } | ||
5235 | |||
5091 | static void set_capture_mixer(struct hda_codec *codec) | 5236 | static void set_capture_mixer(struct hda_codec *codec) |
5092 | { | 5237 | { |
5093 | struct alc_spec *spec = codec->spec; | 5238 | struct alc_spec *spec = codec->spec; |
@@ -5101,7 +5246,10 @@ static void set_capture_mixer(struct hda_codec *codec) | |||
5101 | }; | 5246 | }; |
5102 | if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) { | 5247 | if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3) { |
5103 | int mux = 0; | 5248 | int mux = 0; |
5104 | if (spec->auto_mic) | 5249 | int num_adcs = spec->num_adc_nids; |
5250 | if (spec->dual_adc_switch) | ||
5251 | fixup_dual_adc_switch(codec); | ||
5252 | else if (spec->auto_mic) | ||
5105 | fixup_automic_adc(codec); | 5253 | fixup_automic_adc(codec); |
5106 | else if (spec->input_mux) { | 5254 | else if (spec->input_mux) { |
5107 | if (spec->input_mux->num_items > 1) | 5255 | if (spec->input_mux->num_items > 1) |
@@ -5109,7 +5257,9 @@ static void set_capture_mixer(struct hda_codec *codec) | |||
5109 | else if (spec->input_mux->num_items == 1) | 5257 | else if (spec->input_mux->num_items == 1) |
5110 | fixup_single_adc(codec); | 5258 | fixup_single_adc(codec); |
5111 | } | 5259 | } |
5112 | spec->cap_mixer = caps[mux][spec->num_adc_nids - 1]; | 5260 | if (spec->dual_adc_switch) |
5261 | num_adcs = 1; | ||
5262 | spec->cap_mixer = caps[mux][num_adcs - 1]; | ||
5113 | } | 5263 | } |
5114 | } | 5264 | } |
5115 | 5265 | ||
@@ -5183,6 +5333,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
5183 | 5333 | ||
5184 | static struct snd_pci_quirk beep_white_list[] = { | 5334 | static struct snd_pci_quirk beep_white_list[] = { |
5185 | SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), | 5335 | SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), |
5336 | SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1), | ||
5186 | {} | 5337 | {} |
5187 | }; | 5338 | }; |
5188 | 5339 | ||
@@ -6624,6 +6775,7 @@ static void alc260_auto_init(struct hda_codec *codec) | |||
6624 | alc260_auto_init_multi_out(codec); | 6775 | alc260_auto_init_multi_out(codec); |
6625 | alc260_auto_init_analog_input(codec); | 6776 | alc260_auto_init_analog_input(codec); |
6626 | alc260_auto_init_input_src(codec); | 6777 | alc260_auto_init_input_src(codec); |
6778 | alc_auto_init_digital(codec); | ||
6627 | if (spec->unsol_event) | 6779 | if (spec->unsol_event) |
6628 | alc_inithook(codec); | 6780 | alc_inithook(codec); |
6629 | } | 6781 | } |
@@ -6640,6 +6792,29 @@ static struct hda_amp_list alc260_loopbacks[] = { | |||
6640 | #endif | 6792 | #endif |
6641 | 6793 | ||
6642 | /* | 6794 | /* |
6795 | * Pin config fixes | ||
6796 | */ | ||
6797 | enum { | ||
6798 | PINFIX_HP_DC5750, | ||
6799 | }; | ||
6800 | |||
6801 | static struct alc_pincfg alc260_hp_dc5750_pinfix[] = { | ||
6802 | { 0x11, 0x90130110 }, /* speaker */ | ||
6803 | { } | ||
6804 | }; | ||
6805 | |||
6806 | static const struct alc_fixup alc260_fixups[] = { | ||
6807 | [PINFIX_HP_DC5750] = { | ||
6808 | .pins = alc260_hp_dc5750_pinfix | ||
6809 | }, | ||
6810 | }; | ||
6811 | |||
6812 | static struct snd_pci_quirk alc260_fixup_tbl[] = { | ||
6813 | SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750), | ||
6814 | {} | ||
6815 | }; | ||
6816 | |||
6817 | /* | ||
6643 | * ALC260 configurations | 6818 | * ALC260 configurations |
6644 | */ | 6819 | */ |
6645 | static const char *alc260_models[ALC260_MODEL_LAST] = { | 6820 | static const char *alc260_models[ALC260_MODEL_LAST] = { |
@@ -6838,6 +7013,9 @@ static int patch_alc260(struct hda_codec *codec) | |||
6838 | board_config = ALC260_AUTO; | 7013 | board_config = ALC260_AUTO; |
6839 | } | 7014 | } |
6840 | 7015 | ||
7016 | if (board_config == ALC260_AUTO) | ||
7017 | alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 1); | ||
7018 | |||
6841 | if (board_config == ALC260_AUTO) { | 7019 | if (board_config == ALC260_AUTO) { |
6842 | /* automatic parse from the BIOS config */ | 7020 | /* automatic parse from the BIOS config */ |
6843 | err = alc260_parse_auto_config(codec); | 7021 | err = alc260_parse_auto_config(codec); |
@@ -6883,6 +7061,9 @@ static int patch_alc260(struct hda_codec *codec) | |||
6883 | set_capture_mixer(codec); | 7061 | set_capture_mixer(codec); |
6884 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); | 7062 | set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); |
6885 | 7063 | ||
7064 | if (board_config == ALC260_AUTO) | ||
7065 | alc_pick_fixup(codec, alc260_fixup_tbl, alc260_fixups, 0); | ||
7066 | |||
6886 | spec->vmaster_nid = 0x08; | 7067 | spec->vmaster_nid = 0x08; |
6887 | 7068 | ||
6888 | codec->patch_ops = alc_patch_ops; | 7069 | codec->patch_ops = alc_patch_ops; |
@@ -7003,7 +7184,7 @@ static struct hda_input_mux alc883_lenovo_nb0763_capture_source = { | |||
7003 | .num_items = 4, | 7184 | .num_items = 4, |
7004 | .items = { | 7185 | .items = { |
7005 | { "Mic", 0x0 }, | 7186 | { "Mic", 0x0 }, |
7006 | { "iMic", 0x1 }, | 7187 | { "Int Mic", 0x1 }, |
7007 | { "Line", 0x2 }, | 7188 | { "Line", 0x2 }, |
7008 | { "CD", 0x4 }, | 7189 | { "CD", 0x4 }, |
7009 | }, | 7190 | }, |
@@ -8573,8 +8754,8 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = { | |||
8573 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 8754 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
8574 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 8755 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
8575 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 8756 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
8576 | HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT), | 8757 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), |
8577 | HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 8758 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
8578 | { } /* end */ | 8759 | { } /* end */ |
8579 | }; | 8760 | }; |
8580 | 8761 | ||
@@ -10265,7 +10446,8 @@ static struct alc_config_preset alc882_presets[] = { | |||
10265 | * Pin config fixes | 10446 | * Pin config fixes |
10266 | */ | 10447 | */ |
10267 | enum { | 10448 | enum { |
10268 | PINFIX_ABIT_AW9D_MAX | 10449 | PINFIX_ABIT_AW9D_MAX, |
10450 | PINFIX_PB_M5210, | ||
10269 | }; | 10451 | }; |
10270 | 10452 | ||
10271 | static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { | 10453 | static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { |
@@ -10275,13 +10457,22 @@ static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { | |||
10275 | { } | 10457 | { } |
10276 | }; | 10458 | }; |
10277 | 10459 | ||
10460 | static const struct hda_verb pb_m5210_verbs[] = { | ||
10461 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
10462 | {} | ||
10463 | }; | ||
10464 | |||
10278 | static const struct alc_fixup alc882_fixups[] = { | 10465 | static const struct alc_fixup alc882_fixups[] = { |
10279 | [PINFIX_ABIT_AW9D_MAX] = { | 10466 | [PINFIX_ABIT_AW9D_MAX] = { |
10280 | .pins = alc882_abit_aw9d_pinfix | 10467 | .pins = alc882_abit_aw9d_pinfix |
10281 | }, | 10468 | }, |
10469 | [PINFIX_PB_M5210] = { | ||
10470 | .verbs = pb_m5210_verbs | ||
10471 | }, | ||
10282 | }; | 10472 | }; |
10283 | 10473 | ||
10284 | static struct snd_pci_quirk alc882_fixup_tbl[] = { | 10474 | static struct snd_pci_quirk alc882_fixup_tbl[] = { |
10475 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), | ||
10285 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), | 10476 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), |
10286 | {} | 10477 | {} |
10287 | }; | 10478 | }; |
@@ -10446,7 +10637,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
10446 | { | 10637 | { |
10447 | struct alc_spec *spec = codec->spec; | 10638 | struct alc_spec *spec = codec->spec; |
10448 | static hda_nid_t alc882_ignore[] = { 0x1d, 0 }; | 10639 | static hda_nid_t alc882_ignore[] = { 0x1d, 0 }; |
10449 | int i, err; | 10640 | int err; |
10450 | 10641 | ||
10451 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 10642 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, |
10452 | alc882_ignore); | 10643 | alc882_ignore); |
@@ -10476,25 +10667,7 @@ static int alc882_parse_auto_config(struct hda_codec *codec) | |||
10476 | 10667 | ||
10477 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 10668 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
10478 | 10669 | ||
10479 | /* check multiple SPDIF-out (for recent codecs) */ | 10670 | alc_auto_parse_digital(codec); |
10480 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
10481 | hda_nid_t dig_nid; | ||
10482 | err = snd_hda_get_connections(codec, | ||
10483 | spec->autocfg.dig_out_pins[i], | ||
10484 | &dig_nid, 1); | ||
10485 | if (err < 0) | ||
10486 | continue; | ||
10487 | if (!i) | ||
10488 | spec->multiout.dig_out_nid = dig_nid; | ||
10489 | else { | ||
10490 | spec->multiout.slave_dig_outs = spec->slave_dig_outs; | ||
10491 | if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1) | ||
10492 | break; | ||
10493 | spec->slave_dig_outs[i - 1] = dig_nid; | ||
10494 | } | ||
10495 | } | ||
10496 | if (spec->autocfg.dig_in_pin) | ||
10497 | spec->dig_in_nid = ALC880_DIGIN_NID; | ||
10498 | 10671 | ||
10499 | if (spec->kctls.list) | 10672 | if (spec->kctls.list) |
10500 | add_mixer(spec, spec->kctls.list); | 10673 | add_mixer(spec, spec->kctls.list); |
@@ -10524,6 +10697,7 @@ static void alc882_auto_init(struct hda_codec *codec) | |||
10524 | alc882_auto_init_hp_out(codec); | 10697 | alc882_auto_init_hp_out(codec); |
10525 | alc882_auto_init_analog_input(codec); | 10698 | alc882_auto_init_analog_input(codec); |
10526 | alc882_auto_init_input_src(codec); | 10699 | alc882_auto_init_input_src(codec); |
10700 | alc_auto_init_digital(codec); | ||
10527 | if (spec->unsol_event) | 10701 | if (spec->unsol_event) |
10528 | alc_inithook(codec); | 10702 | alc_inithook(codec); |
10529 | } | 10703 | } |
@@ -12054,12 +12228,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
12054 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 12228 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
12055 | 12229 | ||
12056 | dig_only: | 12230 | dig_only: |
12057 | if (spec->autocfg.dig_outs) { | 12231 | alc_auto_parse_digital(codec); |
12058 | spec->multiout.dig_out_nid = ALC262_DIGOUT_NID; | ||
12059 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
12060 | } | ||
12061 | if (spec->autocfg.dig_in_pin) | ||
12062 | spec->dig_in_nid = ALC262_DIGIN_NID; | ||
12063 | 12232 | ||
12064 | if (spec->kctls.list) | 12233 | if (spec->kctls.list) |
12065 | add_mixer(spec, spec->kctls.list); | 12234 | add_mixer(spec, spec->kctls.list); |
@@ -12091,6 +12260,7 @@ static void alc262_auto_init(struct hda_codec *codec) | |||
12091 | alc262_auto_init_hp_out(codec); | 12260 | alc262_auto_init_hp_out(codec); |
12092 | alc262_auto_init_analog_input(codec); | 12261 | alc262_auto_init_analog_input(codec); |
12093 | alc262_auto_init_input_src(codec); | 12262 | alc262_auto_init_input_src(codec); |
12263 | alc_auto_init_digital(codec); | ||
12094 | if (spec->unsol_event) | 12264 | if (spec->unsol_event) |
12095 | alc_inithook(codec); | 12265 | alc_inithook(codec); |
12096 | } | 12266 | } |
@@ -13024,10 +13194,14 @@ static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, | |||
13024 | dac = 0x02; | 13194 | dac = 0x02; |
13025 | break; | 13195 | break; |
13026 | case 0x15: | 13196 | case 0x15: |
13197 | case 0x1a: /* ALC259/269 only */ | ||
13198 | case 0x1b: /* ALC259/269 only */ | ||
13027 | case 0x21: /* ALC269vb has this pin, too */ | 13199 | case 0x21: /* ALC269vb has this pin, too */ |
13028 | dac = 0x03; | 13200 | dac = 0x03; |
13029 | break; | 13201 | break; |
13030 | default: | 13202 | default: |
13203 | snd_printd(KERN_WARNING "hda_codec: " | ||
13204 | "ignoring pin 0x%x as unknown\n", nid); | ||
13031 | return 0; | 13205 | return 0; |
13032 | } | 13206 | } |
13033 | if (spec->multiout.dac_nids[0] != dac && | 13207 | if (spec->multiout.dac_nids[0] != dac && |
@@ -13078,7 +13252,7 @@ static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
13078 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | 13252 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); |
13079 | if (err < 0) | 13253 | if (err < 0) |
13080 | return err; | 13254 | return err; |
13081 | } else { | 13255 | } else if (nid) { |
13082 | err = alc268_new_analog_output(spec, nid, "Speaker", 0); | 13256 | err = alc268_new_analog_output(spec, nid, "Speaker", 0); |
13083 | if (err < 0) | 13257 | if (err < 0) |
13084 | return err; | 13258 | return err; |
@@ -13227,10 +13401,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
13227 | 13401 | ||
13228 | dig_only: | 13402 | dig_only: |
13229 | /* digital only support output */ | 13403 | /* digital only support output */ |
13230 | if (spec->autocfg.dig_outs) { | 13404 | alc_auto_parse_digital(codec); |
13231 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | ||
13232 | spec->dig_out_type = spec->autocfg.dig_out_type[0]; | ||
13233 | } | ||
13234 | if (spec->kctls.list) | 13405 | if (spec->kctls.list) |
13235 | add_mixer(spec, spec->kctls.list); | 13406 | add_mixer(spec, spec->kctls.list); |
13236 | 13407 | ||
@@ -13260,6 +13431,7 @@ static void alc268_auto_init(struct hda_codec *codec) | |||
13260 | alc268_auto_init_hp_out(codec); | 13431 | alc268_auto_init_hp_out(codec); |
13261 | alc268_auto_init_mono_speaker_out(codec); | 13432 | alc268_auto_init_mono_speaker_out(codec); |
13262 | alc268_auto_init_analog_input(codec); | 13433 | alc268_auto_init_analog_input(codec); |
13434 | alc_auto_init_digital(codec); | ||
13263 | if (spec->unsol_event) | 13435 | if (spec->unsol_event) |
13264 | alc_inithook(codec); | 13436 | alc_inithook(codec); |
13265 | } | 13437 | } |
@@ -14152,6 +14324,36 @@ static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid) | |||
14152 | } | 14324 | } |
14153 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | 14325 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ |
14154 | 14326 | ||
14327 | static int alc275_setup_dual_adc(struct hda_codec *codec) | ||
14328 | { | ||
14329 | struct alc_spec *spec = codec->spec; | ||
14330 | |||
14331 | if (codec->vendor_id != 0x10ec0275 || !spec->auto_mic) | ||
14332 | return 0; | ||
14333 | if ((spec->ext_mic.pin >= 0x18 && spec->int_mic.pin <= 0x13) || | ||
14334 | (spec->ext_mic.pin <= 0x12 && spec->int_mic.pin >= 0x18)) { | ||
14335 | if (spec->ext_mic.pin <= 0x12) { | ||
14336 | spec->private_adc_nids[0] = 0x08; | ||
14337 | spec->private_adc_nids[1] = 0x11; | ||
14338 | spec->private_capsrc_nids[0] = 0x23; | ||
14339 | spec->private_capsrc_nids[1] = 0x22; | ||
14340 | } else { | ||
14341 | spec->private_adc_nids[0] = 0x11; | ||
14342 | spec->private_adc_nids[1] = 0x08; | ||
14343 | spec->private_capsrc_nids[0] = 0x22; | ||
14344 | spec->private_capsrc_nids[1] = 0x23; | ||
14345 | } | ||
14346 | spec->adc_nids = spec->private_adc_nids; | ||
14347 | spec->capsrc_nids = spec->private_capsrc_nids; | ||
14348 | spec->num_adc_nids = 2; | ||
14349 | spec->dual_adc_switch = 1; | ||
14350 | snd_printdd("realtek: enabling dual ADC switchg (%02x:%02x)\n", | ||
14351 | spec->adc_nids[0], spec->adc_nids[1]); | ||
14352 | return 1; | ||
14353 | } | ||
14354 | return 0; | ||
14355 | } | ||
14356 | |||
14155 | /* | 14357 | /* |
14156 | * BIOS auto configuration | 14358 | * BIOS auto configuration |
14157 | */ | 14359 | */ |
@@ -14175,8 +14377,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
14175 | 14377 | ||
14176 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 14378 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
14177 | 14379 | ||
14178 | if (spec->autocfg.dig_outs) | 14380 | alc_auto_parse_digital(codec); |
14179 | spec->multiout.dig_out_nid = ALC269_DIGOUT_NID; | ||
14180 | 14381 | ||
14181 | if (spec->kctls.list) | 14382 | if (spec->kctls.list) |
14182 | add_mixer(spec, spec->kctls.list); | 14383 | add_mixer(spec, spec->kctls.list); |
@@ -14191,13 +14392,15 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
14191 | 14392 | ||
14192 | spec->num_mux_defs = 1; | 14393 | spec->num_mux_defs = 1; |
14193 | spec->input_mux = &spec->private_imux[0]; | 14394 | spec->input_mux = &spec->private_imux[0]; |
14194 | fillup_priv_adc_nids(codec, alc269_adc_candidates, | 14395 | |
14195 | sizeof(alc269_adc_candidates)); | 14396 | if (!alc275_setup_dual_adc(codec)) |
14397 | fillup_priv_adc_nids(codec, alc269_adc_candidates, | ||
14398 | sizeof(alc269_adc_candidates)); | ||
14196 | 14399 | ||
14197 | /* set default input source */ | 14400 | /* set default input source */ |
14198 | snd_hda_codec_write_cache(codec, spec->capsrc_nids[0], | 14401 | if (!spec->dual_adc_switch) |
14199 | 0, AC_VERB_SET_CONNECT_SEL, | 14402 | select_or_unmute_capsrc(codec, spec->capsrc_nids[0], |
14200 | spec->input_mux->items[0].index); | 14403 | spec->input_mux->items[0].index); |
14201 | 14404 | ||
14202 | err = alc_auto_add_mic_boost(codec); | 14405 | err = alc_auto_add_mic_boost(codec); |
14203 | if (err < 0) | 14406 | if (err < 0) |
@@ -14221,6 +14424,7 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
14221 | alc269_auto_init_multi_out(codec); | 14424 | alc269_auto_init_multi_out(codec); |
14222 | alc269_auto_init_hp_out(codec); | 14425 | alc269_auto_init_hp_out(codec); |
14223 | alc269_auto_init_analog_input(codec); | 14426 | alc269_auto_init_analog_input(codec); |
14427 | alc_auto_init_digital(codec); | ||
14224 | if (spec->unsol_event) | 14428 | if (spec->unsol_event) |
14225 | alc_inithook(codec); | 14429 | alc_inithook(codec); |
14226 | } | 14430 | } |
@@ -14493,6 +14697,10 @@ static int patch_alc269(struct hda_codec *codec) | |||
14493 | */ | 14697 | */ |
14494 | spec->stream_analog_playback = &alc269_44k_pcm_analog_playback; | 14698 | spec->stream_analog_playback = &alc269_44k_pcm_analog_playback; |
14495 | spec->stream_analog_capture = &alc269_44k_pcm_analog_capture; | 14699 | spec->stream_analog_capture = &alc269_44k_pcm_analog_capture; |
14700 | } else if (spec->dual_adc_switch) { | ||
14701 | spec->stream_analog_playback = &alc269_pcm_analog_playback; | ||
14702 | /* switch ADC dynamically */ | ||
14703 | spec->stream_analog_capture = &dualmic_pcm_analog_capture; | ||
14496 | } else { | 14704 | } else { |
14497 | spec->stream_analog_playback = &alc269_pcm_analog_playback; | 14705 | spec->stream_analog_playback = &alc269_pcm_analog_playback; |
14498 | spec->stream_analog_capture = &alc269_pcm_analog_capture; | 14706 | spec->stream_analog_capture = &alc269_pcm_analog_capture; |
@@ -15378,8 +15586,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
15378 | 15586 | ||
15379 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 15587 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
15380 | 15588 | ||
15381 | if (spec->autocfg.dig_outs) | 15589 | alc_auto_parse_digital(codec); |
15382 | spec->multiout.dig_out_nid = ALC861_DIGOUT_NID; | ||
15383 | 15590 | ||
15384 | if (spec->kctls.list) | 15591 | if (spec->kctls.list) |
15385 | add_mixer(spec, spec->kctls.list); | 15592 | add_mixer(spec, spec->kctls.list); |
@@ -15405,6 +15612,7 @@ static void alc861_auto_init(struct hda_codec *codec) | |||
15405 | alc861_auto_init_multi_out(codec); | 15612 | alc861_auto_init_multi_out(codec); |
15406 | alc861_auto_init_hp_out(codec); | 15613 | alc861_auto_init_hp_out(codec); |
15407 | alc861_auto_init_analog_input(codec); | 15614 | alc861_auto_init_analog_input(codec); |
15615 | alc_auto_init_digital(codec); | ||
15408 | if (spec->unsol_event) | 15616 | if (spec->unsol_event) |
15409 | alc_inithook(codec); | 15617 | alc_inithook(codec); |
15410 | } | 15618 | } |
@@ -16509,8 +16717,7 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec) | |||
16509 | 16717 | ||
16510 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 16718 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
16511 | 16719 | ||
16512 | if (spec->autocfg.dig_outs) | 16720 | alc_auto_parse_digital(codec); |
16513 | spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID; | ||
16514 | 16721 | ||
16515 | if (spec->kctls.list) | 16722 | if (spec->kctls.list) |
16516 | add_mixer(spec, spec->kctls.list); | 16723 | add_mixer(spec, spec->kctls.list); |
@@ -16537,6 +16744,7 @@ static void alc861vd_auto_init(struct hda_codec *codec) | |||
16537 | alc861vd_auto_init_hp_out(codec); | 16744 | alc861vd_auto_init_hp_out(codec); |
16538 | alc861vd_auto_init_analog_input(codec); | 16745 | alc861vd_auto_init_analog_input(codec); |
16539 | alc861vd_auto_init_input_src(codec); | 16746 | alc861vd_auto_init_input_src(codec); |
16747 | alc_auto_init_digital(codec); | ||
16540 | if (spec->unsol_event) | 16748 | if (spec->unsol_event) |
16541 | alc_inithook(codec); | 16749 | alc_inithook(codec); |
16542 | } | 16750 | } |
@@ -18520,7 +18728,7 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec, | |||
18520 | hda_nid_t dac) | 18728 | hda_nid_t dac) |
18521 | { | 18729 | { |
18522 | int i, num; | 18730 | int i, num; |
18523 | hda_nid_t srcs[4]; | 18731 | hda_nid_t srcs[HDA_MAX_CONNECTIONS]; |
18524 | 18732 | ||
18525 | alc_set_pin_output(codec, nid, pin_type); | 18733 | alc_set_pin_output(codec, nid, pin_type); |
18526 | /* need the manual connection? */ | 18734 | /* need the manual connection? */ |
@@ -18624,8 +18832,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
18624 | 18832 | ||
18625 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 18833 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
18626 | 18834 | ||
18627 | if (spec->autocfg.dig_outs) | 18835 | alc_auto_parse_digital(codec); |
18628 | spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; | ||
18629 | 18836 | ||
18630 | if (spec->kctls.list) | 18837 | if (spec->kctls.list) |
18631 | add_mixer(spec, spec->kctls.list); | 18838 | add_mixer(spec, spec->kctls.list); |
@@ -18635,7 +18842,7 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
18635 | 18842 | ||
18636 | add_verb(spec, alc662_init_verbs); | 18843 | add_verb(spec, alc662_init_verbs); |
18637 | if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || | 18844 | if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || |
18638 | codec->vendor_id == 0x10ec0665) | 18845 | codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670) |
18639 | add_verb(spec, alc663_init_verbs); | 18846 | add_verb(spec, alc663_init_verbs); |
18640 | 18847 | ||
18641 | if (codec->vendor_id == 0x10ec0272) | 18848 | if (codec->vendor_id == 0x10ec0272) |
@@ -18662,6 +18869,7 @@ static void alc662_auto_init(struct hda_codec *codec) | |||
18662 | alc662_auto_init_hp_out(codec); | 18869 | alc662_auto_init_hp_out(codec); |
18663 | alc662_auto_init_analog_input(codec); | 18870 | alc662_auto_init_analog_input(codec); |
18664 | alc662_auto_init_input_src(codec); | 18871 | alc662_auto_init_input_src(codec); |
18872 | alc_auto_init_digital(codec); | ||
18665 | if (spec->unsol_event) | 18873 | if (spec->unsol_event) |
18666 | alc_inithook(codec); | 18874 | alc_inithook(codec); |
18667 | } | 18875 | } |
@@ -18781,6 +18989,333 @@ static int patch_alc888(struct hda_codec *codec) | |||
18781 | } | 18989 | } |
18782 | 18990 | ||
18783 | /* | 18991 | /* |
18992 | * ALC680 support | ||
18993 | */ | ||
18994 | #define ALC680_DIGOUT_NID ALC880_DIGOUT_NID | ||
18995 | #define alc680_modes alc260_modes | ||
18996 | |||
18997 | static hda_nid_t alc680_dac_nids[3] = { | ||
18998 | /* Lout1, Lout2, hp */ | ||
18999 | 0x02, 0x03, 0x04 | ||
19000 | }; | ||
19001 | |||
19002 | static hda_nid_t alc680_adc_nids[3] = { | ||
19003 | /* ADC0-2 */ | ||
19004 | /* DMIC, MIC, Line-in*/ | ||
19005 | 0x07, 0x08, 0x09 | ||
19006 | }; | ||
19007 | |||
19008 | static struct snd_kcontrol_new alc680_base_mixer[] = { | ||
19009 | /* output mixer control */ | ||
19010 | HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), | ||
19011 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
19012 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT), | ||
19013 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT), | ||
19014 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
19015 | { } | ||
19016 | }; | ||
19017 | |||
19018 | static struct snd_kcontrol_new alc680_capture_mixer[] = { | ||
19019 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | ||
19020 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | ||
19021 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | ||
19022 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | ||
19023 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | ||
19024 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | ||
19025 | { } /* end */ | ||
19026 | }; | ||
19027 | |||
19028 | /* | ||
19029 | * generic initialization of ADC, input mixers and output mixers | ||
19030 | */ | ||
19031 | static struct hda_verb alc680_init_verbs[] = { | ||
19032 | /* Unmute DAC0-1 and set vol = 0 */ | ||
19033 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
19034 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
19035 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
19036 | |||
19037 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
19038 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
19039 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, | ||
19040 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
19041 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
19042 | |||
19043 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
19044 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
19045 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
19046 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
19047 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
19048 | { } | ||
19049 | }; | ||
19050 | |||
19051 | /* create input playback/capture controls for the given pin */ | ||
19052 | static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid, | ||
19053 | const char *ctlname, int idx) | ||
19054 | { | ||
19055 | hda_nid_t dac; | ||
19056 | int err; | ||
19057 | |||
19058 | switch (nid) { | ||
19059 | case 0x14: | ||
19060 | dac = 0x02; | ||
19061 | break; | ||
19062 | case 0x15: | ||
19063 | dac = 0x03; | ||
19064 | break; | ||
19065 | case 0x16: | ||
19066 | dac = 0x04; | ||
19067 | break; | ||
19068 | default: | ||
19069 | return 0; | ||
19070 | } | ||
19071 | if (spec->multiout.dac_nids[0] != dac && | ||
19072 | spec->multiout.dac_nids[1] != dac) { | ||
19073 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, | ||
19074 | HDA_COMPOSE_AMP_VAL(dac, 3, idx, | ||
19075 | HDA_OUTPUT)); | ||
19076 | if (err < 0) | ||
19077 | return err; | ||
19078 | |||
19079 | err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, | ||
19080 | HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT)); | ||
19081 | |||
19082 | if (err < 0) | ||
19083 | return err; | ||
19084 | spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac; | ||
19085 | } | ||
19086 | |||
19087 | return 0; | ||
19088 | } | ||
19089 | |||
19090 | /* add playback controls from the parsed DAC table */ | ||
19091 | static int alc680_auto_create_multi_out_ctls(struct alc_spec *spec, | ||
19092 | const struct auto_pin_cfg *cfg) | ||
19093 | { | ||
19094 | hda_nid_t nid; | ||
19095 | int err; | ||
19096 | |||
19097 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
19098 | |||
19099 | nid = cfg->line_out_pins[0]; | ||
19100 | if (nid) { | ||
19101 | const char *name; | ||
19102 | if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
19103 | name = "Speaker"; | ||
19104 | else | ||
19105 | name = "Front"; | ||
19106 | err = alc680_new_analog_output(spec, nid, name, 0); | ||
19107 | if (err < 0) | ||
19108 | return err; | ||
19109 | } | ||
19110 | |||
19111 | nid = cfg->speaker_pins[0]; | ||
19112 | if (nid) { | ||
19113 | err = alc680_new_analog_output(spec, nid, "Speaker", 0); | ||
19114 | if (err < 0) | ||
19115 | return err; | ||
19116 | } | ||
19117 | nid = cfg->hp_pins[0]; | ||
19118 | if (nid) { | ||
19119 | err = alc680_new_analog_output(spec, nid, "Headphone", 0); | ||
19120 | if (err < 0) | ||
19121 | return err; | ||
19122 | } | ||
19123 | |||
19124 | return 0; | ||
19125 | } | ||
19126 | |||
19127 | static void alc680_auto_set_output_and_unmute(struct hda_codec *codec, | ||
19128 | hda_nid_t nid, int pin_type) | ||
19129 | { | ||
19130 | alc_set_pin_output(codec, nid, pin_type); | ||
19131 | } | ||
19132 | |||
19133 | static void alc680_auto_init_multi_out(struct hda_codec *codec) | ||
19134 | { | ||
19135 | struct alc_spec *spec = codec->spec; | ||
19136 | hda_nid_t nid = spec->autocfg.line_out_pins[0]; | ||
19137 | if (nid) { | ||
19138 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | ||
19139 | alc680_auto_set_output_and_unmute(codec, nid, pin_type); | ||
19140 | } | ||
19141 | } | ||
19142 | |||
19143 | static void alc680_auto_init_hp_out(struct hda_codec *codec) | ||
19144 | { | ||
19145 | struct alc_spec *spec = codec->spec; | ||
19146 | hda_nid_t pin; | ||
19147 | |||
19148 | pin = spec->autocfg.hp_pins[0]; | ||
19149 | if (pin) | ||
19150 | alc680_auto_set_output_and_unmute(codec, pin, PIN_HP); | ||
19151 | pin = spec->autocfg.speaker_pins[0]; | ||
19152 | if (pin) | ||
19153 | alc680_auto_set_output_and_unmute(codec, pin, PIN_OUT); | ||
19154 | } | ||
19155 | |||
19156 | /* pcm configuration: identical with ALC880 */ | ||
19157 | #define alc680_pcm_analog_playback alc880_pcm_analog_playback | ||
19158 | #define alc680_pcm_analog_capture alc880_pcm_analog_capture | ||
19159 | #define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture | ||
19160 | #define alc680_pcm_digital_playback alc880_pcm_digital_playback | ||
19161 | |||
19162 | static struct hda_input_mux alc680_capture_source = { | ||
19163 | .num_items = 1, | ||
19164 | .items = { | ||
19165 | { "Mic", 0x0 }, | ||
19166 | }, | ||
19167 | }; | ||
19168 | |||
19169 | /* | ||
19170 | * BIOS auto configuration | ||
19171 | */ | ||
19172 | static int alc680_parse_auto_config(struct hda_codec *codec) | ||
19173 | { | ||
19174 | struct alc_spec *spec = codec->spec; | ||
19175 | int err; | ||
19176 | static hda_nid_t alc680_ignore[] = { 0 }; | ||
19177 | |||
19178 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | ||
19179 | alc680_ignore); | ||
19180 | if (err < 0) | ||
19181 | return err; | ||
19182 | if (!spec->autocfg.line_outs) { | ||
19183 | if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { | ||
19184 | spec->multiout.max_channels = 2; | ||
19185 | spec->no_analog = 1; | ||
19186 | goto dig_only; | ||
19187 | } | ||
19188 | return 0; /* can't find valid BIOS pin config */ | ||
19189 | } | ||
19190 | err = alc680_auto_create_multi_out_ctls(spec, &spec->autocfg); | ||
19191 | if (err < 0) | ||
19192 | return err; | ||
19193 | |||
19194 | spec->multiout.max_channels = 2; | ||
19195 | |||
19196 | dig_only: | ||
19197 | /* digital only support output */ | ||
19198 | alc_auto_parse_digital(codec); | ||
19199 | if (spec->kctls.list) | ||
19200 | add_mixer(spec, spec->kctls.list); | ||
19201 | |||
19202 | add_verb(spec, alc680_init_verbs); | ||
19203 | spec->num_mux_defs = 1; | ||
19204 | spec->input_mux = &alc680_capture_source; | ||
19205 | |||
19206 | err = alc_auto_add_mic_boost(codec); | ||
19207 | if (err < 0) | ||
19208 | return err; | ||
19209 | |||
19210 | return 1; | ||
19211 | } | ||
19212 | |||
19213 | #define alc680_auto_init_analog_input alc882_auto_init_analog_input | ||
19214 | |||
19215 | /* init callback for auto-configuration model -- overriding the default init */ | ||
19216 | static void alc680_auto_init(struct hda_codec *codec) | ||
19217 | { | ||
19218 | struct alc_spec *spec = codec->spec; | ||
19219 | alc680_auto_init_multi_out(codec); | ||
19220 | alc680_auto_init_hp_out(codec); | ||
19221 | alc680_auto_init_analog_input(codec); | ||
19222 | alc_auto_init_digital(codec); | ||
19223 | if (spec->unsol_event) | ||
19224 | alc_inithook(codec); | ||
19225 | } | ||
19226 | |||
19227 | /* | ||
19228 | * configuration and preset | ||
19229 | */ | ||
19230 | static const char *alc680_models[ALC680_MODEL_LAST] = { | ||
19231 | [ALC680_BASE] = "base", | ||
19232 | [ALC680_AUTO] = "auto", | ||
19233 | }; | ||
19234 | |||
19235 | static struct snd_pci_quirk alc680_cfg_tbl[] = { | ||
19236 | SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE), | ||
19237 | {} | ||
19238 | }; | ||
19239 | |||
19240 | static struct alc_config_preset alc680_presets[] = { | ||
19241 | [ALC680_BASE] = { | ||
19242 | .mixers = { alc680_base_mixer }, | ||
19243 | .cap_mixer = alc680_capture_mixer, | ||
19244 | .init_verbs = { alc680_init_verbs }, | ||
19245 | .num_dacs = ARRAY_SIZE(alc680_dac_nids), | ||
19246 | .dac_nids = alc680_dac_nids, | ||
19247 | .num_adc_nids = ARRAY_SIZE(alc680_adc_nids), | ||
19248 | .adc_nids = alc680_adc_nids, | ||
19249 | .hp_nid = 0x04, | ||
19250 | .dig_out_nid = ALC680_DIGOUT_NID, | ||
19251 | .num_channel_mode = ARRAY_SIZE(alc680_modes), | ||
19252 | .channel_mode = alc680_modes, | ||
19253 | .input_mux = &alc680_capture_source, | ||
19254 | }, | ||
19255 | }; | ||
19256 | |||
19257 | static int patch_alc680(struct hda_codec *codec) | ||
19258 | { | ||
19259 | struct alc_spec *spec; | ||
19260 | int board_config; | ||
19261 | int err; | ||
19262 | |||
19263 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
19264 | if (spec == NULL) | ||
19265 | return -ENOMEM; | ||
19266 | |||
19267 | codec->spec = spec; | ||
19268 | |||
19269 | board_config = snd_hda_check_board_config(codec, ALC680_MODEL_LAST, | ||
19270 | alc680_models, | ||
19271 | alc680_cfg_tbl); | ||
19272 | |||
19273 | if (board_config < 0 || board_config >= ALC680_MODEL_LAST) { | ||
19274 | printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", | ||
19275 | codec->chip_name); | ||
19276 | board_config = ALC680_AUTO; | ||
19277 | } | ||
19278 | |||
19279 | if (board_config == ALC680_AUTO) { | ||
19280 | /* automatic parse from the BIOS config */ | ||
19281 | err = alc680_parse_auto_config(codec); | ||
19282 | if (err < 0) { | ||
19283 | alc_free(codec); | ||
19284 | return err; | ||
19285 | } else if (!err) { | ||
19286 | printk(KERN_INFO | ||
19287 | "hda_codec: Cannot set up configuration " | ||
19288 | "from BIOS. Using base mode...\n"); | ||
19289 | board_config = ALC680_BASE; | ||
19290 | } | ||
19291 | } | ||
19292 | |||
19293 | if (board_config != ALC680_AUTO) | ||
19294 | setup_preset(codec, &alc680_presets[board_config]); | ||
19295 | |||
19296 | spec->stream_analog_playback = &alc680_pcm_analog_playback; | ||
19297 | spec->stream_analog_capture = &alc680_pcm_analog_capture; | ||
19298 | spec->stream_analog_alt_capture = &alc680_pcm_analog_alt_capture; | ||
19299 | spec->stream_digital_playback = &alc680_pcm_digital_playback; | ||
19300 | |||
19301 | if (!spec->adc_nids) { | ||
19302 | spec->adc_nids = alc680_adc_nids; | ||
19303 | spec->num_adc_nids = ARRAY_SIZE(alc680_adc_nids); | ||
19304 | } | ||
19305 | |||
19306 | if (!spec->cap_mixer) | ||
19307 | set_capture_mixer(codec); | ||
19308 | |||
19309 | spec->vmaster_nid = 0x02; | ||
19310 | |||
19311 | codec->patch_ops = alc_patch_ops; | ||
19312 | if (board_config == ALC680_AUTO) | ||
19313 | spec->init_hook = alc680_auto_init; | ||
19314 | |||
19315 | return 0; | ||
19316 | } | ||
19317 | |||
19318 | /* | ||
18784 | * patch entries | 19319 | * patch entries |
18785 | */ | 19320 | */ |
18786 | static struct hda_codec_preset snd_hda_preset_realtek[] = { | 19321 | static struct hda_codec_preset snd_hda_preset_realtek[] = { |
@@ -18804,6 +19339,7 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
18804 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, | 19339 | { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, |
18805 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, | 19340 | { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, |
18806 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, | 19341 | { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, |
19342 | { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, | ||
18807 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, | 19343 | { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, |
18808 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, | 19344 | { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, |
18809 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, | 19345 | { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 }, |