aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_realtek.c
diff options
context:
space:
mode:
authorKailang Yang <kailang@realtek.com.tw>2005-12-05 13:42:22 -0500
committerJaroslav Kysela <perex@suse.cz>2006-01-03 06:30:20 -0500
commitdf694daa3c0135202e4702cb2d11e68a43f6c51e (patch)
tree1c274f376771ec0ace88200dc97141702ef42a38 /sound/pci/hda/patch_realtek.c
parent59acf76e0268e3f0156ef5113e89d838a8c02bb6 (diff)
[ALSA] hda-codec - Add the support of ALC262,ALC883,ALC885,ALC861
Modules: HDA Codec driver,HDA generic driver This patch adds the support of ALC262,ALC883,ALC885,ALC861 to driver More models and improvements for ALC880, ALC260 and ALC882 codecs, too. Signed-off-by: Kailang Yang <kailang@realtek.com.tw> 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.c2367
1 files changed, 2177 insertions, 190 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index c5fb141f6222..a98c0e4da0ac 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -3,7 +3,8 @@
3 * 3 *
4 * HD audio interface patch for ALC 260/880/882 codecs 4 * HD audio interface patch for ALC 260/880/882 codecs
5 * 5 *
6 * Copyright (c) 2004 PeiSen Hou <pshou@realtek.com.tw> 6 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
7 * Takashi Iwai <tiwai@suse.de> 8 * Takashi Iwai <tiwai@suse.de>
8 * 9 *
9 * This driver is free software; you can redistribute it and/or modify 10 * This driver is free software; you can redistribute it and/or modify
@@ -39,17 +40,20 @@ enum {
39 ALC880_5ST_DIG, 40 ALC880_5ST_DIG,
40 ALC880_W810, 41 ALC880_W810,
41 ALC880_Z71V, 42 ALC880_Z71V,
42 ALC880_AUTO,
43 ALC880_6ST, 43 ALC880_6ST,
44 ALC880_6ST_DIG, 44 ALC880_6ST_DIG,
45 ALC880_F1734, 45 ALC880_F1734,
46 ALC880_ASUS, 46 ALC880_ASUS,
47 ALC880_ASUS_DIG, 47 ALC880_ASUS_DIG,
48 ALC880_ASUS_W1V, 48 ALC880_ASUS_W1V,
49 ALC880_ASUS_DIG2,
49 ALC880_UNIWILL_DIG, 50 ALC880_UNIWILL_DIG,
51 ALC880_CLEVO,
52 ALC880_TCL_S700,
50#ifdef CONFIG_SND_DEBUG 53#ifdef CONFIG_SND_DEBUG
51 ALC880_TEST, 54 ALC880_TEST,
52#endif 55#endif
56 ALC880_AUTO,
53 ALC880_MODEL_LAST /* last tag */ 57 ALC880_MODEL_LAST /* last tag */
54}; 58};
55 59
@@ -57,16 +61,45 @@ enum {
57enum { 61enum {
58 ALC260_BASIC, 62 ALC260_BASIC,
59 ALC260_HP, 63 ALC260_HP,
60 ALC260_FUJITSU_S702x, 64 ALC260_HP_3013,
65 ALC260_FUJITSU_S702X,
66 ALC260_AUTO,
61 ALC260_MODEL_LAST /* last tag */ 67 ALC260_MODEL_LAST /* last tag */
62}; 68};
63 69
70/* ALC262 models */
71enum {
72 ALC262_BASIC,
73 ALC262_AUTO,
74 ALC262_MODEL_LAST /* last tag */
75};
76
77/* ALC861 models */
78enum {
79 ALC861_3ST,
80 ALC861_3ST_DIG,
81 ALC861_6ST_DIG,
82 ALC861_AUTO,
83 ALC861_MODEL_LAST,
84};
85
86/* ALC882 models */
87enum {
88 ALC882_3ST_DIG,
89 ALC882_6ST_DIG,
90 ALC882_AUTO,
91 ALC882_MODEL_LAST,
92};
93
94/* for GPIO Poll */
95#define GPIO_MASK 0x03
96
64struct alc_spec { 97struct alc_spec {
65 /* codec parameterization */ 98 /* codec parameterization */
66 struct snd_kcontrol_new *mixers[3]; /* mixer arrays */ 99 struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
67 unsigned int num_mixers; 100 unsigned int num_mixers;
68 101
69 const struct hda_verb *init_verbs[3]; /* initialization verbs 102 const struct hda_verb *init_verbs[5]; /* initialization verbs
70 * don't forget NULL termination! 103 * don't forget NULL termination!
71 */ 104 */
72 unsigned int num_init_verbs; 105 unsigned int num_init_verbs;
@@ -106,7 +139,25 @@ struct alc_spec {
106 unsigned int num_kctl_alloc, num_kctl_used; 139 unsigned int num_kctl_alloc, num_kctl_used;
107 struct snd_kcontrol_new *kctl_alloc; 140 struct snd_kcontrol_new *kctl_alloc;
108 struct hda_input_mux private_imux; 141 struct hda_input_mux private_imux;
109 hda_nid_t private_dac_nids[4]; 142 hda_nid_t private_dac_nids[5];
143};
144
145/*
146 * configuration template - to be copied to the spec instance
147 */
148struct alc_config_preset {
149 struct snd_kcontrol_new *mixers[5]; /* should be identical size with spec */
150 const struct hda_verb *init_verbs[5];
151 unsigned int num_dacs;
152 hda_nid_t *dac_nids;
153 hda_nid_t dig_out_nid; /* optional */
154 hda_nid_t hp_nid; /* optional */
155 unsigned int num_adc_nids;
156 hda_nid_t *adc_nids;
157 hda_nid_t dig_in_nid;
158 unsigned int num_channel_mode;
159 const struct hda_channel_mode *channel_mode;
160 const struct hda_input_mux *input_mux;
110}; 161};
111 162
112 163
@@ -143,7 +194,7 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
143/* 194/*
144 * channel mode setting 195 * channel mode setting
145 */ 196 */
146static int alc880_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 197static int alc_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
147{ 198{
148 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 199 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
149 struct alc_spec *spec = codec->spec; 200 struct alc_spec *spec = codec->spec;
@@ -151,7 +202,7 @@ static int alc880_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
151 spec->num_channel_mode); 202 spec->num_channel_mode);
152} 203}
153 204
154static int alc880_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 205static int alc_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
155{ 206{
156 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 207 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
157 struct alc_spec *spec = codec->spec; 208 struct alc_spec *spec = codec->spec;
@@ -159,7 +210,7 @@ static int alc880_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
159 spec->num_channel_mode, spec->multiout.max_channels); 210 spec->num_channel_mode, spec->multiout.max_channels);
160} 211}
161 212
162static int alc880_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 213static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
163{ 214{
164 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 215 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
165 struct alc_spec *spec = codec->spec; 216 struct alc_spec *spec = codec->spec;
@@ -217,6 +268,36 @@ static int alc_pinctl_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
217 .put = alc_pinctl_switch_put, \ 268 .put = alc_pinctl_switch_put, \
218 .private_value = (nid) | (mask<<16) } 269 .private_value = (nid) | (mask<<16) }
219 270
271
272/*
273 * set up from the preset table
274 */
275static void setup_preset(struct alc_spec *spec, const struct alc_config_preset *preset)
276{
277 int i;
278
279 for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
280 spec->mixers[spec->num_mixers++] = preset->mixers[i];
281 for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i]; i++)
282 spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
283
284 spec->channel_mode = preset->channel_mode;
285 spec->num_channel_mode = preset->num_channel_mode;
286
287 spec->multiout.max_channels = spec->channel_mode[0].channels;
288
289 spec->multiout.num_dacs = preset->num_dacs;
290 spec->multiout.dac_nids = preset->dac_nids;
291 spec->multiout.dig_out_nid = preset->dig_out_nid;
292 spec->multiout.hp_nid = preset->hp_nid;
293
294 spec->input_mux = preset->input_mux;
295
296 spec->num_adc_nids = preset->num_adc_nids;
297 spec->adc_nids = preset->adc_nids;
298 spec->dig_in_nid = preset->dig_in_nid;
299}
300
220/* 301/*
221 * ALC880 3-stack model 302 * ALC880 3-stack model
222 * 303 *
@@ -237,6 +318,7 @@ static hda_nid_t alc880_adc_nids[3] = {
237 318
238/* The datasheet says the node 0x07 is connected from inputs, 319/* The datasheet says the node 0x07 is connected from inputs,
239 * but it shows zero connection in the real implementation on some devices. 320 * but it shows zero connection in the real implementation on some devices.
321 * Note: this is a 915GAV bug, fixed on 915GLV
240 */ 322 */
241static hda_nid_t alc880_adc_nids_alt[2] = { 323static hda_nid_t alc880_adc_nids_alt[2] = {
242 /* ADC1-2 */ 324 /* ADC1-2 */
@@ -307,9 +389,9 @@ static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
307 { 389 {
308 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 390 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
309 .name = "Channel Mode", 391 .name = "Channel Mode",
310 .info = alc880_ch_mode_info, 392 .info = alc_ch_mode_info,
311 .get = alc880_ch_mode_get, 393 .get = alc_ch_mode_get,
312 .put = alc880_ch_mode_put, 394 .put = alc_ch_mode_put,
313 }, 395 },
314 { } /* end */ 396 { } /* end */
315}; 397};
@@ -452,9 +534,9 @@ static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
452 { 534 {
453 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 535 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
454 .name = "Channel Mode", 536 .name = "Channel Mode",
455 .info = alc880_ch_mode_info, 537 .info = alc_ch_mode_info,
456 .get = alc880_ch_mode_get, 538 .get = alc_ch_mode_get,
457 .put = alc880_ch_mode_put, 539 .put = alc_ch_mode_put,
458 }, 540 },
459 { } /* end */ 541 { } /* end */
460}; 542};
@@ -596,9 +678,9 @@ static struct snd_kcontrol_new alc880_asus_mixer[] = {
596 { 678 {
597 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 679 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
598 .name = "Channel Mode", 680 .name = "Channel Mode",
599 .info = alc880_ch_mode_info, 681 .info = alc_ch_mode_info,
600 .get = alc880_ch_mode_get, 682 .get = alc_ch_mode_get,
601 .put = alc880_ch_mode_put, 683 .put = alc_ch_mode_put,
602 }, 684 },
603 { } /* end */ 685 { } /* end */
604}; 686};
@@ -626,6 +708,33 @@ static struct snd_kcontrol_new alc880_pcbeep_mixer[] = {
626 { } /* end */ 708 { } /* end */
627}; 709};
628 710
711/* TCL S700 */
712static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
713 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
714 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
715 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
716 HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
717 HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
718 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
719 HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
720 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
721 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
722 {
723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
724 /* The multiple "Capture Source" controls confuse alsamixer
725 * So call somewhat different..
726 * FIXME: the controls appear in the "playback" view!
727 */
728 /* .name = "Capture Source", */
729 .name = "Input Source",
730 .count = 1,
731 .info = alc_mux_enum_info,
732 .get = alc_mux_enum_get,
733 .put = alc_mux_enum_put,
734 },
735 { } /* end */
736};
737
629/* 738/*
630 * build control elements 739 * build control elements
631 */ 740 */
@@ -925,6 +1034,8 @@ static struct hda_verb alc880_gpio1_init_verbs[] = {
925 {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, 1034 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
926 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, 1035 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
927 {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, 1036 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
1037
1038 { }
928}; 1039};
929 1040
930/* Enable GPIO mask and set output */ 1041/* Enable GPIO mask and set output */
@@ -932,8 +1043,59 @@ static struct hda_verb alc880_gpio2_init_verbs[] = {
932 {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, 1043 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
933 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, 1044 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
934 {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, 1045 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
1046
1047 { }
935}; 1048};
936 1049
1050/* Clevo m520g init */
1051static struct hda_verb alc880_pin_clevo_init_verbs[] = {
1052 /* headphone output */
1053 {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
1054 /* line-out */
1055 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1056 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1057 /* Line-in */
1058 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1059 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1060 /* CD */
1061 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1062 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1063 /* Mic1 (rear panel) */
1064 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1065 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1066 /* Mic2 (front panel) */
1067 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1068 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1069 /* headphone */
1070 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1071 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1072 /* change to EAPD mode */
1073 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1074 {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
1075
1076 { }
1077};
1078
1079static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
1080 /* Headphone output */
1081 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1082 /* Front output*/
1083 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1084 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1085
1086 /* Line In pin widget for input */
1087 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1088 /* CD pin widget for input */
1089 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1090 /* Mic1 (rear panel) pin widget for input and vref at 80% */
1091 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1092
1093 /* change to EAPD mode */
1094 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
1095 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
1096
1097 { }
1098};
937 1099
938/* 1100/*
939 */ 1101 */
@@ -1344,9 +1506,9 @@ static struct snd_kcontrol_new alc880_test_mixer[] = {
1344 { 1506 {
1345 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1507 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1346 .name = "Channel Mode", 1508 .name = "Channel Mode",
1347 .info = alc880_ch_mode_info, 1509 .info = alc_ch_mode_info,
1348 .get = alc880_ch_mode_get, 1510 .get = alc_ch_mode_get,
1349 .put = alc880_ch_mode_put, 1511 .put = alc_ch_mode_put,
1350 }, 1512 },
1351 { } /* end */ 1513 { } /* end */
1352}; 1514};
@@ -1442,6 +1604,8 @@ static struct hda_board_config alc880_cfg_tbl[] = {
1442 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST }, 1604 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
1443 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, 1605 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
1444 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, 1606 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
1607 /* TCL S700 */
1608 { .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 },
1445 1609
1446 /* Back 3 jack, front 2 jack (Internal add Aux-In) */ 1610 /* Back 3 jack, front 2 jack (Internal add Aux-In) */
1447 { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST }, 1611 { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
@@ -1452,6 +1616,8 @@ static struct hda_board_config alc880_cfg_tbl[] = {
1452 { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, 1616 { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
1453 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, 1617 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
1454 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG }, 1618 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG },
1619 /* Clevo m520G NB */
1620 { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, .config = ALC880_CLEVO },
1455 1621
1456 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ 1622 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
1457 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, 1623 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
@@ -1489,6 +1655,7 @@ static struct hda_board_config alc880_cfg_tbl[] = {
1489 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V }, 1655 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
1490 1656
1491 { .modelname = "6stack", .config = ALC880_6ST }, 1657 { .modelname = "6stack", .config = ALC880_6ST },
1658 { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b4, .config = ALC880_6ST },
1492 { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */ 1659 { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
1493 1660
1494 { .modelname = "6stack-digout", .config = ALC880_6ST_DIG }, 1661 { .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
@@ -1496,6 +1663,10 @@ static struct hda_board_config alc880_cfg_tbl[] = {
1496 { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG }, 1663 { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
1497 { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG }, 1664 { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
1498 { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG }, 1665 { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
1666 { .pci_subvendor = 0x1039, .pci_subdevice = 0x1234, .config = ALC880_6ST_DIG },
1667 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0077, .config = ALC880_6ST_DIG },
1668 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0078, .config = ALC880_6ST_DIG },
1669 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG },
1499 1670
1500 { .modelname = "asus", .config = ALC880_ASUS }, 1671 { .modelname = "asus", .config = ALC880_ASUS },
1501 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG }, 1672 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
@@ -1509,37 +1680,26 @@ static struct hda_board_config alc880_cfg_tbl[] = {
1509 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, 1680 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
1510 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, 1681 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
1511 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, 1682 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
1683 { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 },
1512 1684
1513 { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, 1685 { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
1514 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG }, 1686 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
1515 1687
1516 { .modelname = "F1734", .config = ALC880_F1734 }, 1688 { .modelname = "F1734", .config = ALC880_F1734 },
1517 { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 }, 1689 { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
1690 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9054, .config = ALC880_F1734 },
1518 1691
1519#ifdef CONFIG_SND_DEBUG 1692#ifdef CONFIG_SND_DEBUG
1520 { .modelname = "test", .config = ALC880_TEST }, 1693 { .modelname = "test", .config = ALC880_TEST },
1521#endif 1694#endif
1695 { .modelname = "auto", .config = ALC880_AUTO },
1522 1696
1523 {} 1697 {}
1524}; 1698};
1525 1699
1526/* 1700/*
1527 * configuration template - to be copied to the spec instance 1701 * ALC880 codec presets
1528 */ 1702 */
1529struct alc_config_preset {
1530 struct snd_kcontrol_new *mixers[4];
1531 const struct hda_verb *init_verbs[4];
1532 unsigned int num_dacs;
1533 hda_nid_t *dac_nids;
1534 hda_nid_t dig_out_nid; /* optional */
1535 hda_nid_t hp_nid; /* optional */
1536 unsigned int num_adc_nids;
1537 hda_nid_t *adc_nids;
1538 unsigned int num_channel_mode;
1539 const struct hda_channel_mode *channel_mode;
1540 const struct hda_input_mux *input_mux;
1541};
1542
1543static struct alc_config_preset alc880_presets[] = { 1703static struct alc_config_preset alc880_presets[] = {
1544 [ALC880_3ST] = { 1704 [ALC880_3ST] = {
1545 .mixers = { alc880_three_stack_mixer }, 1705 .mixers = { alc880_three_stack_mixer },
@@ -1560,6 +1720,18 @@ static struct alc_config_preset alc880_presets[] = {
1560 .channel_mode = alc880_threestack_modes, 1720 .channel_mode = alc880_threestack_modes,
1561 .input_mux = &alc880_capture_source, 1721 .input_mux = &alc880_capture_source,
1562 }, 1722 },
1723 [ALC880_TCL_S700] = {
1724 .mixers = { alc880_tcl_s700_mixer },
1725 .init_verbs = { alc880_volume_init_verbs,
1726 alc880_pin_tcl_S700_init_verbs,
1727 alc880_gpio2_init_verbs },
1728 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1729 .dac_nids = alc880_dac_nids,
1730 .hp_nid = 0x03,
1731 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1732 .channel_mode = alc880_2_jack_modes,
1733 .input_mux = &alc880_capture_source,
1734 },
1563 [ALC880_5ST] = { 1735 [ALC880_5ST] = {
1564 .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer}, 1736 .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
1565 .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs }, 1737 .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
@@ -1651,6 +1823,17 @@ static struct alc_config_preset alc880_presets[] = {
1651 .channel_mode = alc880_asus_modes, 1823 .channel_mode = alc880_asus_modes,
1652 .input_mux = &alc880_capture_source, 1824 .input_mux = &alc880_capture_source,
1653 }, 1825 },
1826 [ALC880_ASUS_DIG2] = {
1827 .mixers = { alc880_asus_mixer },
1828 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1829 alc880_gpio2_init_verbs }, /* use GPIO2 */
1830 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1831 .dac_nids = alc880_asus_dac_nids,
1832 .dig_out_nid = ALC880_DIGOUT_NID,
1833 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1834 .channel_mode = alc880_asus_modes,
1835 .input_mux = &alc880_capture_source,
1836 },
1654 [ALC880_ASUS_W1V] = { 1837 [ALC880_ASUS_W1V] = {
1655 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer }, 1838 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
1656 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs, 1839 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
@@ -1672,6 +1855,17 @@ static struct alc_config_preset alc880_presets[] = {
1672 .channel_mode = alc880_asus_modes, 1855 .channel_mode = alc880_asus_modes,
1673 .input_mux = &alc880_capture_source, 1856 .input_mux = &alc880_capture_source,
1674 }, 1857 },
1858 [ALC880_CLEVO] = {
1859 .mixers = { alc880_three_stack_mixer },
1860 .init_verbs = { alc880_volume_init_verbs,
1861 alc880_pin_clevo_init_verbs },
1862 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1863 .dac_nids = alc880_dac_nids,
1864 .hp_nid = 0x03,
1865 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1866 .channel_mode = alc880_threestack_modes,
1867 .input_mux = &alc880_capture_source,
1868 },
1675#ifdef CONFIG_SND_DEBUG 1869#ifdef CONFIG_SND_DEBUG
1676 [ALC880_TEST] = { 1870 [ALC880_TEST] = {
1677 .mixers = { alc880_test_mixer }, 1871 .mixers = { alc880_test_mixer },
@@ -1783,7 +1977,8 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pi
1783} 1977}
1784 1978
1785/* add playback controls from the parsed DAC table */ 1979/* add playback controls from the parsed DAC table */
1786static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) 1980static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
1981 const struct auto_pin_cfg *cfg)
1787{ 1982{
1788 char name[32]; 1983 char name[32];
1789 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; 1984 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
@@ -1871,35 +2066,38 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
1871} 2066}
1872 2067
1873/* create input playback/capture controls for the given pin */ 2068/* create input playback/capture controls for the given pin */
1874static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname) 2069static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname,
2070 int idx, hda_nid_t mix_nid)
1875{ 2071{
1876 char name[32]; 2072 char name[32];
1877 int err, idx; 2073 int err;
1878 2074
1879 sprintf(name, "%s Playback Volume", ctlname); 2075 sprintf(name, "%s Playback Volume", ctlname);
1880 idx = alc880_input_pin_idx(pin);
1881 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, 2076 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
1882 HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0) 2077 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
1883 return err; 2078 return err;
1884 sprintf(name, "%s Playback Switch", ctlname); 2079 sprintf(name, "%s Playback Switch", ctlname);
1885 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, 2080 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
1886 HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0) 2081 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
1887 return err; 2082 return err;
1888 return 0; 2083 return 0;
1889} 2084}
1890 2085
1891/* create playback/capture controls for input pins */ 2086/* create playback/capture controls for input pins */
1892static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) 2087static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
2088 const struct auto_pin_cfg *cfg)
1893{ 2089{
1894 static char *labels[AUTO_PIN_LAST] = { 2090 static char *labels[AUTO_PIN_LAST] = {
1895 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" 2091 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
1896 }; 2092 };
1897 struct hda_input_mux *imux = &spec->private_imux; 2093 struct hda_input_mux *imux = &spec->private_imux;
1898 int i, err; 2094 int i, err, idx;
1899 2095
1900 for (i = 0; i < AUTO_PIN_LAST; i++) { 2096 for (i = 0; i < AUTO_PIN_LAST; i++) {
1901 if (alc880_is_input_pin(cfg->input_pins[i])) { 2097 if (alc880_is_input_pin(cfg->input_pins[i])) {
1902 err = new_analog_input(spec, cfg->input_pins[i], labels[i]); 2098 idx = alc880_input_pin_idx(cfg->input_pins[i]);
2099 err = new_analog_input(spec, cfg->input_pins[i], labels[i],
2100 idx, 0x0b);
1903 if (err < 0) 2101 if (err < 0)
1904 return err; 2102 return err;
1905 imux->items[imux->num_items].label = labels[i]; 2103 imux->items[imux->num_items].label = labels[i];
@@ -1910,7 +2108,8 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const str
1910 return 0; 2108 return 0;
1911} 2109}
1912 2110
1913static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type, 2111static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
2112 hda_nid_t nid, int pin_type,
1914 int dac_idx) 2113 int dac_idx)
1915{ 2114{
1916 /* set as output */ 2115 /* set as output */
@@ -1973,15 +2172,17 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
1973{ 2172{
1974 struct alc_spec *spec = codec->spec; 2173 struct alc_spec *spec = codec->spec;
1975 int err; 2174 int err;
2175 static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
1976 2176
1977 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0) 2177 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
1978 return err; 2178 alc880_ignore)) < 0)
1979 if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0)
1980 return err; 2179 return err;
1981 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && 2180 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
1982 ! spec->autocfg.hp_pin) 2181 ! spec->autocfg.hp_pin)
1983 return 0; /* can't find valid BIOS pin config */ 2182 return 0; /* can't find valid BIOS pin config */
1984 if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || 2183
2184 if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
2185 (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
1985 (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin, 2186 (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
1986 "Speaker")) < 0 || 2187 "Speaker")) < 0 ||
1987 (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin, 2188 (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
@@ -2024,7 +2225,7 @@ static int patch_alc880(struct hda_codec *codec)
2024{ 2225{
2025 struct alc_spec *spec; 2226 struct alc_spec *spec;
2026 int board_config; 2227 int board_config;
2027 int i, err; 2228 int err;
2028 2229
2029 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 2230 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2030 if (spec == NULL) 2231 if (spec == NULL)
@@ -2050,36 +2251,8 @@ static int patch_alc880(struct hda_codec *codec)
2050 } 2251 }
2051 } 2252 }
2052 2253
2053 if (board_config != ALC880_AUTO) { 2254 if (board_config != ALC880_AUTO)
2054 /* set up from the preset table */ 2255 setup_preset(spec, &alc880_presets[board_config]);
2055 const struct alc_config_preset *preset;
2056
2057 preset = &alc880_presets[board_config];
2058
2059 for (i = 0; preset->mixers[i]; i++) {
2060 snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break);
2061 spec->mixers[spec->num_mixers++] = preset->mixers[i];
2062 }
2063 for (i = 0; preset->init_verbs[i]; i++) {
2064 snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break);
2065 spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
2066 }
2067
2068 spec->channel_mode = preset->channel_mode;
2069 spec->num_channel_mode = preset->num_channel_mode;
2070
2071 spec->multiout.max_channels = spec->channel_mode[0].channels;
2072
2073 spec->multiout.num_dacs = preset->num_dacs;
2074 spec->multiout.dac_nids = preset->dac_nids;
2075 spec->multiout.dig_out_nid = preset->dig_out_nid;
2076 spec->multiout.hp_nid = preset->hp_nid;
2077
2078 spec->input_mux = preset->input_mux;
2079
2080 spec->num_adc_nids = preset->num_adc_nids;
2081 spec->adc_nids = preset->adc_nids;
2082 }
2083 2256
2084 spec->stream_name_analog = "ALC880 Analog"; 2257 spec->stream_name_analog = "ALC880 Analog";
2085 spec->stream_analog_playback = &alc880_pcm_analog_playback; 2258 spec->stream_analog_playback = &alc880_pcm_analog_playback;
@@ -2128,11 +2301,16 @@ static hda_nid_t alc260_adc_nids[1] = {
2128 0x04, 2301 0x04,
2129}; 2302};
2130 2303
2131static hda_nid_t alc260_hp_adc_nids[1] = { 2304static hda_nid_t alc260_adc_nids_alt[1] = {
2132 /* ADC1 */ 2305 /* ADC1 */
2133 0x05, 2306 0x05,
2134}; 2307};
2135 2308
2309static hda_nid_t alc260_hp_adc_nids[2] = {
2310 /* ADC1, 0 */
2311 0x05, 0x04
2312};
2313
2136#define ALC260_DIGOUT_NID 0x03 2314#define ALC260_DIGOUT_NID 0x03
2137#define ALC260_DIGIN_NID 0x06 2315#define ALC260_DIGIN_NID 0x06
2138 2316
@@ -2167,38 +2345,26 @@ static struct hda_channel_mode alc260_modes[1] = {
2167 { 2, NULL }, 2345 { 2, NULL },
2168}; 2346};
2169 2347
2170static struct snd_kcontrol_new alc260_base_mixer[] = { 2348
2349/* Mixer combinations
2350 *
2351 * basic: base_output + input + pc_beep + capture
2352 * HP: base_output + input + capture_alt
2353 * HP_3013: hp_3013 + input + capture
2354 * fujitsu: fujitsu + capture
2355 */
2356
2357static struct snd_kcontrol_new alc260_base_output_mixer[] = {
2171 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT), 2358 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2172 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT), 2359 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
2173 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2174 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2175 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
2176 HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
2177 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
2178 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
2179 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
2180 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
2181 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
2182 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
2183 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), 2360 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2184 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), 2361 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
2185 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 2362 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2186 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), 2363 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2187 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
2188 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
2189 {
2190 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2191 .name = "Capture Source",
2192 .info = alc_mux_enum_info,
2193 .get = alc_mux_enum_get,
2194 .put = alc_mux_enum_put,
2195 },
2196 { } /* end */ 2364 { } /* end */
2197}; 2365};
2198 2366
2199static struct snd_kcontrol_new alc260_hp_mixer[] = { 2367static struct snd_kcontrol_new alc260_input_mixer[] = {
2200 HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2201 HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
2202 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 2368 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2203 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 2369 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2204 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT), 2370 HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
@@ -2207,19 +2373,24 @@ static struct snd_kcontrol_new alc260_hp_mixer[] = {
2207 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT), 2373 HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
2208 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT), 2374 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
2209 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT), 2375 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
2210 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT), 2376 { } /* end */
2211 HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT), 2377};
2212 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT), 2378
2213 HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT), 2379static struct snd_kcontrol_new alc260_pc_beep_mixer[] = {
2214 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT), 2380 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
2215 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT), 2381 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
2216 { 2382 { } /* end */
2217 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2383};
2218 .name = "Capture Source", 2384
2219 .info = alc_mux_enum_info, 2385static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
2220 .get = alc_mux_enum_get, 2386 HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2221 .put = alc_mux_enum_put, 2387 HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
2222 }, 2388 HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
2389 HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
2390 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2391 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
2392 HDA_CODEC_VOLUME_MONO("iSpeaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2393 HDA_CODEC_MUTE_MONO("iSpeaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
2223 { } /* end */ 2394 { } /* end */
2224}; 2395};
2225 2396
@@ -2235,11 +2406,24 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
2235 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT), 2406 HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
2236 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT), 2407 HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2237 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT), 2408 HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),
2409 { } /* end */
2410};
2411
2412/* capture mixer elements */
2413static struct snd_kcontrol_new alc260_capture_mixer[] = {
2238 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT), 2414 HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
2239 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT), 2415 HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
2416 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),
2417 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),
2240 { 2418 {
2241 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2419 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2242 .name = "Capture Source", 2420 /* The multiple "Capture Source" controls confuse alsamixer
2421 * So call somewhat different..
2422 * FIXME: the controls appear in the "playback" view!
2423 */
2424 /* .name = "Capture Source", */
2425 .name = "Input Source",
2426 .count = 2,
2243 .info = alc_mux_enum_info, 2427 .info = alc_mux_enum_info,
2244 .get = alc_mux_enum_get, 2428 .get = alc_mux_enum_get,
2245 .put = alc_mux_enum_put, 2429 .put = alc_mux_enum_put,
@@ -2247,6 +2431,28 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
2247 { } /* end */ 2431 { } /* end */
2248}; 2432};
2249 2433
2434static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {
2435 HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
2436 HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
2437 {
2438 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2439 /* The multiple "Capture Source" controls confuse alsamixer
2440 * So call somewhat different..
2441 * FIXME: the controls appear in the "playback" view!
2442 */
2443 /* .name = "Capture Source", */
2444 .name = "Input Source",
2445 .count = 1,
2446 .info = alc_mux_enum_info,
2447 .get = alc_mux_enum_get,
2448 .put = alc_mux_enum_put,
2449 },
2450 { } /* end */
2451};
2452
2453/*
2454 * initialization verbs
2455 */
2250static struct hda_verb alc260_init_verbs[] = { 2456static struct hda_verb alc260_init_verbs[] = {
2251 /* Line In pin widget for input */ 2457 /* Line In pin widget for input */
2252 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 2458 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
@@ -2308,6 +2514,100 @@ static struct hda_verb alc260_init_verbs[] = {
2308 { } 2514 { }
2309}; 2515};
2310 2516
2517static struct hda_verb alc260_hp_init_verbs[] = {
2518 /* Headphone and output */
2519 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
2520 /* mono output */
2521 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2522 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2523 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2524 /* Mic2 (front panel) pin widget for input and vref at 80% */
2525 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2526 /* Line In pin widget for input */
2527 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2528 /* Line-2 pin widget for output */
2529 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2530 /* CD pin widget for input */
2531 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2532 /* unmute amp left and right */
2533 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
2534 /* set connection select to line in (default select for this ADC) */
2535 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2536 /* unmute Line-Out mixer amp left and right (volume = 0) */
2537 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2538 /* mute pin widget amp left and right (no gain on this amp) */
2539 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2540 /* unmute HP mixer amp left and right (volume = 0) */
2541 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2542 /* mute pin widget amp left and right (no gain on this amp) */
2543 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2544 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2545 /* unmute CD */
2546 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
2547 /* unmute Line In */
2548 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
2549 /* unmute Mic */
2550 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2551 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2552 /* Unmute Front out path */
2553 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2554 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2555 /* Unmute Headphone out path */
2556 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2557 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2558 /* Unmute Mono out path */
2559 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2560 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2561 { }
2562};
2563
2564static struct hda_verb alc260_hp_3013_init_verbs[] = {
2565 /* Line out and output */
2566 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2567 /* mono output */
2568 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2569 /* Mic1 (rear panel) pin widget for input and vref at 80% */
2570 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2571 /* Mic2 (front panel) pin widget for input and vref at 80% */
2572 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
2573 /* Line In pin widget for input */
2574 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2575 /* Headphone pin widget for output */
2576 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
2577 /* CD pin widget for input */
2578 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2579 /* unmute amp left and right */
2580 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
2581 /* set connection select to line in (default select for this ADC) */
2582 {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2583 /* unmute Line-Out mixer amp left and right (volume = 0) */
2584 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2585 /* mute pin widget amp left and right (no gain on this amp) */
2586 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2587 /* unmute HP mixer amp left and right (volume = 0) */
2588 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
2589 /* mute pin widget amp left and right (no gain on this amp) */
2590 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
2591 /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2592 /* unmute CD */
2593 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
2594 /* unmute Line In */
2595 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
2596 /* unmute Mic */
2597 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2598 /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2599 /* Unmute Front out path */
2600 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2601 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2602 /* Unmute Headphone out path */
2603 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2604 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2605 /* Unmute Mono out path */
2606 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
2607 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
2608 { }
2609};
2610
2311/* Initialisation sequence for ALC260 as configured in Fujitsu S702x 2611/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
2312 * laptops. 2612 * laptops.
2313 */ 2613 */
@@ -2374,18 +2674,337 @@ static struct hda_pcm_stream alc260_pcm_analog_capture = {
2374 .channels_max = 2, 2674 .channels_max = 2,
2375}; 2675};
2376 2676
2677/*
2678 * for BIOS auto-configuration
2679 */
2680
2681static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
2682 const char *pfx)
2683{
2684 hda_nid_t nid_vol;
2685 unsigned long vol_val, sw_val;
2686 char name[32];
2687 int err;
2688
2689 if (nid >= 0x0f && nid < 0x11) {
2690 nid_vol = nid - 0x7;
2691 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
2692 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2693 } else if (nid == 0x11) {
2694 nid_vol = nid - 0x7;
2695 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT);
2696 sw_val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
2697 } else if (nid >= 0x12 && nid <= 0x15) {
2698 nid_vol = 0x08;
2699 vol_val = HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT);
2700 sw_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2701 } else
2702 return 0; /* N/A */
2703
2704 snprintf(name, sizeof(name), "%s Playback Volume", pfx);
2705 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val)) < 0)
2706 return err;
2707 snprintf(name, sizeof(name), "%s Playback Switch", pfx);
2708 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val)) < 0)
2709 return err;
2710 return 1;
2711}
2712
2713/* add playback controls from the parsed DAC table */
2714static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
2715 const struct auto_pin_cfg *cfg)
2716{
2717 hda_nid_t nid;
2718 int err;
2719
2720 spec->multiout.num_dacs = 1;
2721 spec->multiout.dac_nids = spec->private_dac_nids;
2722 spec->multiout.dac_nids[0] = 0x02;
2723
2724 nid = cfg->line_out_pins[0];
2725 if (nid) {
2726 err = alc260_add_playback_controls(spec, nid, "Front");
2727 if (err < 0)
2728 return err;
2729 }
2730
2731 nid = cfg->speaker_pin;
2732 if (nid) {
2733 err = alc260_add_playback_controls(spec, nid, "Speaker");
2734 if (err < 0)
2735 return err;
2736 }
2737
2738 nid = cfg->hp_pin;
2739 if (nid) {
2740 err = alc260_add_playback_controls(spec, nid, "Headphone");
2741 if (err < 0)
2742 return err;
2743 }
2744 return 0;
2745}
2746
2747/* create playback/capture controls for input pins */
2748static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
2749 const struct auto_pin_cfg *cfg)
2750{
2751 static char *labels[AUTO_PIN_LAST] = {
2752 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
2753 };
2754 struct hda_input_mux *imux = &spec->private_imux;
2755 int i, err, idx;
2756
2757 for (i = 0; i < AUTO_PIN_LAST; i++) {
2758 if (cfg->input_pins[i] >= 0x12) {
2759 idx = cfg->input_pins[i] - 0x12;
2760 err = new_analog_input(spec, cfg->input_pins[i], labels[i], idx, 0x07);
2761 if (err < 0)
2762 return err;
2763 imux->items[imux->num_items].label = labels[i];
2764 imux->items[imux->num_items].index = idx;
2765 imux->num_items++;
2766 }
2767 if ((cfg->input_pins[i] >= 0x0f) && (cfg->input_pins[i] <= 0x10)){
2768 idx = cfg->input_pins[i] - 0x09;
2769 err = new_analog_input(spec, cfg->input_pins[i], labels[i], idx, 0x07);
2770 if (err < 0)
2771 return err;
2772 imux->items[imux->num_items].label = labels[i];
2773 imux->items[imux->num_items].index = idx;
2774 imux->num_items++;
2775 }
2776 }
2777 return 0;
2778}
2779
2780static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
2781 hda_nid_t nid, int pin_type,
2782 int sel_idx)
2783{
2784 /* set as output */
2785 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
2786 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
2787 /* need the manual connection? */
2788 if (nid >= 0x12) {
2789 int idx = nid - 0x12;
2790 snd_hda_codec_write(codec, idx + 0x0b, 0,
2791 AC_VERB_SET_CONNECT_SEL, sel_idx);
2792
2793 }
2794}
2795
2796static void alc260_auto_init_multi_out(struct hda_codec *codec)
2797{
2798 struct alc_spec *spec = codec->spec;
2799 hda_nid_t nid;
2800
2801 nid = spec->autocfg.line_out_pins[0];
2802 if (nid)
2803 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
2804
2805 nid = spec->autocfg.speaker_pin;
2806 if (nid)
2807 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
2808
2809 nid = spec->autocfg.hp_pin;
2810 if (nid)
2811 alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
2812}
2813
2814#define ALC260_PIN_CD_NID 0x16
2815static void alc260_auto_init_analog_input(struct hda_codec *codec)
2816{
2817 struct alc_spec *spec = codec->spec;
2818 int i;
2819
2820 for (i = 0; i < AUTO_PIN_LAST; i++) {
2821 hda_nid_t nid = spec->autocfg.input_pins[i];
2822 if (nid >= 0x12) {
2823 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
2824 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
2825 if (nid != ALC260_PIN_CD_NID)
2826 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2827 AMP_OUT_MUTE);
2828 }
2829 }
2830}
2831
2832/*
2833 * generic initialization of ADC, input mixers and output mixers
2834 */
2835static struct hda_verb alc260_volume_init_verbs[] = {
2836 /*
2837 * Unmute ADC0-1 and set the default input to mic-in
2838 */
2839 {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
2840 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2841 {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
2842 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2843
2844 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
2845 * mixer widget
2846 * Note: PASD motherboards uses the Line In 2 as the input for front panel
2847 * mic (mic 2)
2848 */
2849 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
2850 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2851 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2852 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2853 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
2854 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
2855
2856 /*
2857 * Set up output mixers (0x08 - 0x0a)
2858 */
2859 /* set vol=0 to output mixers */
2860 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2861 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2862 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2863 /* set up input amps for analog loopback */
2864 /* Amp Indices: DAC = 0, mixer = 1 */
2865 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2866 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2867 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2868 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2869 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2870 {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2871
2872 { }
2873};
2874
2875static int alc260_parse_auto_config(struct hda_codec *codec)
2876{
2877 struct alc_spec *spec = codec->spec;
2878 unsigned int wcap;
2879 int err;
2880 static hda_nid_t alc260_ignore[] = { 0x17, 0 };
2881
2882 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
2883 alc260_ignore)) < 0)
2884 return err;
2885 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
2886 ! spec->autocfg.hp_pin)
2887 return 0; /* can't find valid BIOS pin config */
2888 if ((err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
2889 (err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
2890 return err;
2891
2892 spec->multiout.max_channels = 2;
2893
2894 if (spec->autocfg.dig_out_pin)
2895 spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
2896 if (spec->kctl_alloc)
2897 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2898
2899 spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
2900
2901 spec->input_mux = &spec->private_imux;
2902
2903 /* check whether NID 0x04 is valid */
2904 wcap = snd_hda_param_read(codec, alc260_adc_nids[0], AC_PAR_AUDIO_WIDGET_CAP);
2905 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
2906 if (wcap != AC_WID_AUD_IN) {
2907 spec->adc_nids = alc260_adc_nids_alt;
2908 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
2909 spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
2910 spec->num_mixers++;
2911 } else {
2912 spec->adc_nids = alc260_adc_nids;
2913 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
2914 spec->mixers[spec->num_mixers] = alc260_capture_mixer;
2915 spec->num_mixers++;
2916 }
2917
2918 return 1;
2919}
2920
2921/* init callback for auto-configuration model -- overriding the default init */
2922static int alc260_auto_init(struct hda_codec *codec)
2923{
2924 alc_init(codec);
2925 alc260_auto_init_multi_out(codec);
2926 alc260_auto_init_analog_input(codec);
2927 return 0;
2928}
2929
2930/*
2931 * ALC260 configurations
2932 */
2377static struct hda_board_config alc260_cfg_tbl[] = { 2933static struct hda_board_config alc260_cfg_tbl[] = {
2934 { .modelname = "basic", .config = ALC260_BASIC },
2378 { .modelname = "hp", .config = ALC260_HP }, 2935 { .modelname = "hp", .config = ALC260_HP },
2379 { .pci_subvendor = 0x103c, .config = ALC260_HP }, 2936 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP },
2380 { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702x }, 2937 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
2381 { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702x }, 2938 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP },
2939 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 },
2940 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP },
2941 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP },
2942 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP },
2943 { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X },
2944 { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X },
2945 { .modelname = "auto", .config = ALC260_AUTO },
2382 {} 2946 {}
2383}; 2947};
2384 2948
2949static struct alc_config_preset alc260_presets[] = {
2950 [ALC260_BASIC] = {
2951 .mixers = { alc260_base_output_mixer,
2952 alc260_input_mixer,
2953 alc260_pc_beep_mixer,
2954 alc260_capture_mixer },
2955 .init_verbs = { alc260_init_verbs },
2956 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
2957 .dac_nids = alc260_dac_nids,
2958 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
2959 .adc_nids = alc260_adc_nids,
2960 .num_channel_mode = ARRAY_SIZE(alc260_modes),
2961 .channel_mode = alc260_modes,
2962 .input_mux = &alc260_capture_source,
2963 },
2964 [ALC260_HP] = {
2965 .mixers = { alc260_base_output_mixer,
2966 alc260_input_mixer,
2967 alc260_capture_alt_mixer },
2968 .init_verbs = { alc260_hp_init_verbs },
2969 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
2970 .dac_nids = alc260_dac_nids,
2971 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
2972 .adc_nids = alc260_hp_adc_nids,
2973 .num_channel_mode = ARRAY_SIZE(alc260_modes),
2974 .channel_mode = alc260_modes,
2975 .input_mux = &alc260_capture_source,
2976 },
2977 [ALC260_HP_3013] = {
2978 .mixers = { alc260_hp_3013_mixer,
2979 alc260_input_mixer,
2980 alc260_capture_alt_mixer },
2981 .init_verbs = { alc260_hp_3013_init_verbs },
2982 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
2983 .dac_nids = alc260_dac_nids,
2984 .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
2985 .adc_nids = alc260_hp_adc_nids,
2986 .num_channel_mode = ARRAY_SIZE(alc260_modes),
2987 .channel_mode = alc260_modes,
2988 .input_mux = &alc260_capture_source,
2989 },
2990 [ALC260_FUJITSU_S702X] = {
2991 .mixers = { alc260_fujitsu_mixer,
2992 alc260_capture_mixer },
2993 .init_verbs = { alc260_fujitsu_init_verbs },
2994 .num_dacs = ARRAY_SIZE(alc260_dac_nids),
2995 .dac_nids = alc260_dac_nids,
2996 .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
2997 .adc_nids = alc260_adc_nids,
2998 .num_channel_mode = ARRAY_SIZE(alc260_modes),
2999 .channel_mode = alc260_modes,
3000 .input_mux = &alc260_fujitsu_capture_source,
3001 },
3002};
3003
2385static int patch_alc260(struct hda_codec *codec) 3004static int patch_alc260(struct hda_codec *codec)
2386{ 3005{
2387 struct alc_spec *spec; 3006 struct alc_spec *spec;
2388 int board_config; 3007 int err, board_config;
2389 3008
2390 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3009 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2391 if (spec == NULL) 3010 if (spec == NULL)
@@ -2396,60 +3015,31 @@ static int patch_alc260(struct hda_codec *codec)
2396 board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl); 3015 board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
2397 if (board_config < 0 || board_config >= ALC260_MODEL_LAST) { 3016 if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
2398 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n"); 3017 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
2399 board_config = ALC260_BASIC; 3018 board_config = ALC260_AUTO;
2400 } 3019 }
2401 3020
2402 switch (board_config) { 3021 if (board_config == ALC260_AUTO) {
2403 case ALC260_HP: 3022 /* automatic parse from the BIOS config */
2404 spec->mixers[spec->num_mixers] = alc260_hp_mixer; 3023 err = alc260_parse_auto_config(codec);
2405 spec->num_mixers++; 3024 if (err < 0) {
2406 break; 3025 alc_free(codec);
2407 case ALC260_FUJITSU_S702x: 3026 return err;
2408 spec->mixers[spec->num_mixers] = alc260_fujitsu_mixer; 3027 } else if (! err) {
2409 spec->num_mixers++; 3028 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
2410 break; 3029 board_config = ALC260_BASIC;
2411 default: 3030 }
2412 spec->mixers[spec->num_mixers] = alc260_base_mixer;
2413 spec->num_mixers++;
2414 break;
2415 }
2416
2417 if (board_config != ALC260_FUJITSU_S702x) {
2418 spec->init_verbs[0] = alc260_init_verbs;
2419 spec->num_init_verbs = 1;
2420 } else {
2421 spec->init_verbs[0] = alc260_fujitsu_init_verbs;
2422 spec->num_init_verbs = 1;
2423 } 3031 }
2424 3032
2425 spec->channel_mode = alc260_modes; 3033 if (board_config != ALC260_AUTO)
2426 spec->num_channel_mode = ARRAY_SIZE(alc260_modes); 3034 setup_preset(spec, &alc260_presets[board_config]);
2427 3035
2428 spec->stream_name_analog = "ALC260 Analog"; 3036 spec->stream_name_analog = "ALC260 Analog";
2429 spec->stream_analog_playback = &alc260_pcm_analog_playback; 3037 spec->stream_analog_playback = &alc260_pcm_analog_playback;
2430 spec->stream_analog_capture = &alc260_pcm_analog_capture; 3038 spec->stream_analog_capture = &alc260_pcm_analog_capture;
2431 3039
2432 spec->multiout.max_channels = spec->channel_mode[0].channels;
2433 spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
2434 spec->multiout.dac_nids = alc260_dac_nids;
2435
2436 if (board_config != ALC260_FUJITSU_S702x) {
2437 spec->input_mux = &alc260_capture_source;
2438 } else {
2439 spec->input_mux = &alc260_fujitsu_capture_source;
2440 }
2441 switch (board_config) {
2442 case ALC260_HP:
2443 spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids);
2444 spec->adc_nids = alc260_hp_adc_nids;
2445 break;
2446 default:
2447 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
2448 spec->adc_nids = alc260_adc_nids;
2449 break;
2450 }
2451
2452 codec->patch_ops = alc_patch_ops; 3040 codec->patch_ops = alc_patch_ops;
3041 if (board_config == ALC260_AUTO)
3042 codec->patch_ops.init = alc260_auto_init;
2453 3043
2454 return 0; 3044 return 0;
2455} 3045}
@@ -2466,6 +3056,8 @@ static int patch_alc260(struct hda_codec *codec)
2466 * In addition, an independent DAC for the multi-playback (not used in this 3056 * In addition, an independent DAC for the multi-playback (not used in this
2467 * driver yet). 3057 * driver yet).
2468 */ 3058 */
3059#define ALC882_DIGOUT_NID 0x06
3060#define ALC882_DIGIN_NID 0x0a
2469 3061
2470static struct hda_channel_mode alc882_ch_modes[1] = { 3062static struct hda_channel_mode alc882_ch_modes[1] = {
2471 { 8, NULL } 3063 { 8, NULL }
@@ -2476,10 +3068,9 @@ static hda_nid_t alc882_dac_nids[4] = {
2476 0x02, 0x03, 0x04, 0x05 3068 0x02, 0x03, 0x04, 0x05
2477}; 3069};
2478 3070
2479static hda_nid_t alc882_adc_nids[3] = { 3071/* identical with ALC880 */
2480 /* ADC0-2 */ 3072#define alc882_adc_nids alc880_adc_nids
2481 0x07, 0x08, 0x09, 3073#define alc882_adc_nids_alt alc880_adc_nids_alt
2482};
2483 3074
2484/* input MUX */ 3075/* input MUX */
2485/* FIXME: should be a matrix-type input source selection */ 3076/* FIXME: should be a matrix-type input source selection */
@@ -2522,6 +3113,33 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
2522 return 1; 3113 return 1;
2523} 3114}
2524 3115
3116/*
3117 * 6ch mode
3118 */
3119static struct hda_verb alc882_sixstack_ch6_init[] = {
3120 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
3121 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3122 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3123 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3124 { } /* end */
3125};
3126
3127/*
3128 * 8ch mode
3129 */
3130static struct hda_verb alc882_sixstack_ch8_init[] = {
3131 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3132 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3133 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3134 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
3135 { } /* end */
3136};
3137
3138static struct hda_channel_mode alc882_sixstack_modes[2] = {
3139 { 6, alc882_sixstack_ch6_init },
3140 { 8, alc882_sixstack_ch8_init },
3141};
3142
2525/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 3143/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
2526 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 3144 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
2527 */ 3145 */
@@ -2565,6 +3183,17 @@ static struct snd_kcontrol_new alc882_base_mixer[] = {
2565 { } /* end */ 3183 { } /* end */
2566}; 3184};
2567 3185
3186static struct snd_kcontrol_new alc882_chmode_mixer[] = {
3187 {
3188 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3189 .name = "Channel Mode",
3190 .info = alc_ch_mode_info,
3191 .get = alc_ch_mode_get,
3192 .put = alc_ch_mode_put,
3193 },
3194 { } /* end */
3195};
3196
2568static struct hda_verb alc882_init_verbs[] = { 3197static struct hda_verb alc882_init_verbs[] = {
2569 /* Front mixer: unmute input/output amp left and right (volume = 0) */ 3198 /* Front mixer: unmute input/output amp left and right (volume = 0) */
2570 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, 3199 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
@@ -2645,9 +3274,263 @@ static struct hda_verb alc882_init_verbs[] = {
2645 { } 3274 { }
2646}; 3275};
2647 3276
3277/*
3278 * generic initialization of ADC, input mixers and output mixers
3279 */
3280static struct hda_verb alc882_auto_init_verbs[] = {
3281 /*
3282 * Unmute ADC0-2 and set the default input to mic-in
3283 */
3284 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3285 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3286 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3287 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3288 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3289 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3290
3291 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3292 * mixer widget
3293 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3294 * mic (mic 2)
3295 */
3296 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3297 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3298 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3299 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3300 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3301 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3302
3303 /*
3304 * Set up output mixers (0x0c - 0x0f)
3305 */
3306 /* set vol=0 to output mixers */
3307 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3308 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3309 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3310 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3311 /* set up input amps for analog loopback */
3312 /* Amp Indices: DAC = 0, mixer = 1 */
3313 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3314 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3315 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3316 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3317 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3318 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3319 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3320 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3321 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3322 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3323
3324 /* FIXME: use matrix-type input source selection */
3325 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3326 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3327 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3328 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3329 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3330 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3331 /* Input mixer2 */
3332 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3333 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3334 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3335 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3336 /* Input mixer3 */
3337 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3338 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3339 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3340 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3341
3342 { }
3343};
3344
3345/* capture mixer elements */
3346static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
3347 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3348 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3349 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
3350 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
3351 {
3352 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3353 /* The multiple "Capture Source" controls confuse alsamixer
3354 * So call somewhat different..
3355 * FIXME: the controls appear in the "playback" view!
3356 */
3357 /* .name = "Capture Source", */
3358 .name = "Input Source",
3359 .count = 2,
3360 .info = alc882_mux_enum_info,
3361 .get = alc882_mux_enum_get,
3362 .put = alc882_mux_enum_put,
3363 },
3364 { } /* end */
3365};
3366
3367static struct snd_kcontrol_new alc882_capture_mixer[] = {
3368 HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
3369 HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
3370 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
3371 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
3372 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
3373 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
3374 {
3375 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3376 /* The multiple "Capture Source" controls confuse alsamixer
3377 * So call somewhat different..
3378 * FIXME: the controls appear in the "playback" view!
3379 */
3380 /* .name = "Capture Source", */
3381 .name = "Input Source",
3382 .count = 3,
3383 .info = alc882_mux_enum_info,
3384 .get = alc882_mux_enum_get,
3385 .put = alc882_mux_enum_put,
3386 },
3387 { } /* end */
3388};
3389
3390/* pcm configuration: identiacal with ALC880 */
3391#define alc882_pcm_analog_playback alc880_pcm_analog_playback
3392#define alc882_pcm_analog_capture alc880_pcm_analog_capture
3393#define alc882_pcm_digital_playback alc880_pcm_digital_playback
3394#define alc882_pcm_digital_capture alc880_pcm_digital_capture
3395
3396/*
3397 * configuration and preset
3398 */
3399static struct hda_board_config alc882_cfg_tbl[] = {
3400 { .modelname = "3stack-dig", .config = ALC861_3ST_DIG },
3401 { .modelname = "6stack-dig", .config = ALC861_6ST_DIG },
3402 { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* MSI */
3403 { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* Foxconn */
3404 { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS */
3405 { .modelname = "auto", .config = ALC861_AUTO },
3406 {}
3407};
3408
3409static struct alc_config_preset alc882_presets[] = {
3410 [ALC882_3ST_DIG] = {
3411 .mixers = { alc882_base_mixer },
3412 .init_verbs = { alc882_init_verbs },
3413 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
3414 .dac_nids = alc882_dac_nids,
3415 .dig_out_nid = ALC882_DIGOUT_NID,
3416 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
3417 .adc_nids = alc882_adc_nids,
3418 .dig_in_nid = ALC882_DIGIN_NID,
3419 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
3420 .channel_mode = alc882_ch_modes,
3421 .input_mux = &alc882_capture_source,
3422 },
3423 [ALC882_6ST_DIG] = {
3424 .mixers = { alc882_base_mixer, alc882_chmode_mixer },
3425 .init_verbs = { alc882_init_verbs },
3426 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
3427 .dac_nids = alc882_dac_nids,
3428 .dig_out_nid = ALC882_DIGOUT_NID,
3429 .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
3430 .adc_nids = alc882_adc_nids,
3431 .dig_in_nid = ALC882_DIGIN_NID,
3432 .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
3433 .channel_mode = alc882_sixstack_modes,
3434 .input_mux = &alc882_capture_source,
3435 },
3436};
3437
3438
3439/*
3440 * BIOS auto configuration
3441 */
3442static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
3443 hda_nid_t nid, int pin_type,
3444 int dac_idx)
3445{
3446 /* set as output */
3447 struct alc_spec *spec = codec->spec;
3448 int idx;
3449
3450 if (spec->multiout.dac_nids[dac_idx] == 0x25)
3451 idx = 4;
3452 else
3453 idx = spec->multiout.dac_nids[dac_idx] - 2;
3454
3455 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
3456 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
3457 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
3458
3459}
3460
3461static void alc882_auto_init_multi_out(struct hda_codec *codec)
3462{
3463 struct alc_spec *spec = codec->spec;
3464 int i;
3465
3466 for (i = 0; i <= HDA_SIDE; i++) {
3467 hda_nid_t nid = spec->autocfg.line_out_pins[i];
3468 if (nid)
3469 alc882_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
3470 }
3471}
3472
3473static void alc882_auto_init_hp_out(struct hda_codec *codec)
3474{
3475 struct alc_spec *spec = codec->spec;
3476 hda_nid_t pin;
3477
3478 pin = spec->autocfg.hp_pin;
3479 if (pin) /* connect to front */
3480 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */
3481}
3482
3483#define alc882_is_input_pin(nid) alc880_is_input_pin(nid)
3484#define ALC882_PIN_CD_NID ALC880_PIN_CD_NID
3485
3486static void alc882_auto_init_analog_input(struct hda_codec *codec)
3487{
3488 struct alc_spec *spec = codec->spec;
3489 int i;
3490
3491 for (i = 0; i < AUTO_PIN_LAST; i++) {
3492 hda_nid_t nid = spec->autocfg.input_pins[i];
3493 if (alc882_is_input_pin(nid)) {
3494 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3495 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
3496 if (nid != ALC882_PIN_CD_NID)
3497 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3498 AMP_OUT_MUTE);
3499 }
3500 }
3501}
3502
3503/* almost identical with ALC880 parser... */
3504static int alc882_parse_auto_config(struct hda_codec *codec)
3505{
3506 struct alc_spec *spec = codec->spec;
3507 int err = alc880_parse_auto_config(codec);
3508
3509 if (err < 0)
3510 return err;
3511 /* hack - override the init verbs */
3512 spec->init_verbs[0] = alc882_auto_init_verbs;
3513 return 0;
3514}
3515
3516/* init callback for auto-configuration model -- overriding the default init */
3517static int alc882_auto_init(struct hda_codec *codec)
3518{
3519 alc_init(codec);
3520 alc882_auto_init_multi_out(codec);
3521 alc882_auto_init_hp_out(codec);
3522 alc882_auto_init_analog_input(codec);
3523 return 0;
3524}
3525
3526/*
3527 * ALC882 Headphone poll in 3.5.1a or 3.5.2
3528 */
3529
2648static int patch_alc882(struct hda_codec *codec) 3530static int patch_alc882(struct hda_codec *codec)
2649{ 3531{
2650 struct alc_spec *spec; 3532 struct alc_spec *spec;
3533 int err, board_config;
2651 3534
2652 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 3535 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2653 if (spec == NULL) 3536 if (spec == NULL)
@@ -2655,35 +3538,1135 @@ static int patch_alc882(struct hda_codec *codec)
2655 3538
2656 codec->spec = spec; 3539 codec->spec = spec;
2657 3540
2658 spec->mixers[spec->num_mixers] = alc882_base_mixer; 3541 board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl);
2659 spec->num_mixers++;
2660 3542
2661 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID; 3543 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
2662 spec->dig_in_nid = ALC880_DIGIN_NID; 3544 printk(KERN_INFO "hda_codec: Unknown model for ALC882, trying auto-probe from BIOS...\n");
2663 spec->init_verbs[0] = alc882_init_verbs; 3545 board_config = ALC882_AUTO;
2664 spec->num_init_verbs = 1; 3546 }
3547
3548 if (board_config == ALC882_AUTO) {
3549 /* automatic parse from the BIOS config */
3550 err = alc882_parse_auto_config(codec);
3551 if (err < 0) {
3552 alc_free(codec);
3553 return err;
3554 } else if (! err) {
3555 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3556 board_config = ALC882_3ST_DIG;
3557 }
3558 }
2665 3559
2666 spec->channel_mode = alc882_ch_modes; 3560 if (board_config != ALC882_AUTO)
2667 spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes); 3561 setup_preset(spec, &alc882_presets[board_config]);
2668 3562
2669 spec->stream_name_analog = "ALC882 Analog"; 3563 spec->stream_name_analog = "ALC882 Analog";
2670 spec->stream_analog_playback = &alc880_pcm_analog_playback; 3564 spec->stream_analog_playback = &alc882_pcm_analog_playback;
2671 spec->stream_analog_capture = &alc880_pcm_analog_capture; 3565 spec->stream_analog_capture = &alc882_pcm_analog_capture;
2672 3566
2673 spec->stream_name_digital = "ALC882 Digital"; 3567 spec->stream_name_digital = "ALC882 Digital";
2674 spec->stream_digital_playback = &alc880_pcm_digital_playback; 3568 spec->stream_digital_playback = &alc882_pcm_digital_playback;
2675 spec->stream_digital_capture = &alc880_pcm_digital_capture; 3569 spec->stream_digital_capture = &alc882_pcm_digital_capture;
2676 3570
2677 spec->multiout.max_channels = spec->channel_mode[0].channels; 3571 if (! spec->adc_nids && spec->input_mux) {
2678 spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids); 3572 /* check whether NID 0x07 is valid */
2679 spec->multiout.dac_nids = alc882_dac_nids; 3573 unsigned int wcap = snd_hda_param_read(codec, 0x07,
3574 AC_PAR_AUDIO_WIDGET_CAP);
3575 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3576 if (wcap != AC_WID_AUD_IN) {
3577 spec->adc_nids = alc882_adc_nids_alt;
3578 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
3579 spec->mixers[spec->num_mixers] = alc882_capture_alt_mixer;
3580 spec->num_mixers++;
3581 } else {
3582 spec->adc_nids = alc882_adc_nids;
3583 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
3584 spec->mixers[spec->num_mixers] = alc882_capture_mixer;
3585 spec->num_mixers++;
3586 }
3587 }
3588
3589 codec->patch_ops = alc_patch_ops;
3590 if (board_config == ALC882_AUTO)
3591 codec->patch_ops.init = alc882_auto_init;
2680 3592
2681 spec->input_mux = &alc882_capture_source; 3593 return 0;
2682 spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids); 3594}
2683 spec->adc_nids = alc882_adc_nids; 3595
3596/*
3597 * ALC262 support
3598 */
3599
3600#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
3601#define ALC262_DIGIN_NID ALC880_DIGIN_NID
3602
3603#define alc262_dac_nids alc260_dac_nids
3604#define alc262_adc_nids alc882_adc_nids
3605#define alc262_adc_nids_alt alc882_adc_nids_alt
3606
3607#define alc262_modes alc260_modes
3608
3609static struct snd_kcontrol_new alc262_base_mixer[] = {
3610 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
3611 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
3612 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
3613 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
3614 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
3615 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
3616 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
3617 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
3618 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
3619 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
3620 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
3621 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
3622 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
3623 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
3624 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
3625 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
3626 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
3627 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
3628 {
3629 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3630 .name = "Capture Source",
3631 .count = 1,
3632 .info = alc882_mux_enum_info,
3633 .get = alc882_mux_enum_get,
3634 .put = alc882_mux_enum_put,
3635 },
3636 { } /* end */
3637};
3638
3639#define alc262_capture_mixer alc882_capture_mixer
3640#define alc262_capture_alt_mixer alc882_capture_alt_mixer
3641
3642/*
3643 * generic initialization of ADC, input mixers and output mixers
3644 */
3645static struct hda_verb alc262_init_verbs[] = {
3646 /*
3647 * Unmute ADC0-2 and set the default input to mic-in
3648 */
3649 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3650 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3651 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3652 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3653 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3654 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3655
3656 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3657 * mixer widget
3658 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3659 * mic (mic 2)
3660 */
3661 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3662 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3663 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3664 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3665 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3666 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3667
3668 /*
3669 * Set up output mixers (0x0c - 0x0e)
3670 */
3671 /* set vol=0 to output mixers */
3672 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3673 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3674 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3675 /* set up input amps for analog loopback */
3676 /* Amp Indices: DAC = 0, mixer = 1 */
3677 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3678 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3679 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3680 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3681 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3682 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3683
3684 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3685 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
3686 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
3687 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
3688 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3689 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
3690
3691 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3692 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3693 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3694 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3695 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
3696
3697 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
3698 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
3699
3700 /* FIXME: use matrix-type input source selection */
3701 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3702 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3703 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3704 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3705 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3706 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3707 /* Input mixer2 */
3708 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3709 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3710 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3711 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3712 /* Input mixer3 */
3713 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3714 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3715 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3716 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3717
3718 { }
3719};
3720
3721/* add playback controls from the parsed DAC table */
3722static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
3723{
3724 hda_nid_t nid;
3725 int err;
3726
3727 spec->multiout.num_dacs = 1; /* only use one dac */
3728 spec->multiout.dac_nids = spec->private_dac_nids;
3729 spec->multiout.dac_nids[0] = 2;
3730
3731 nid = cfg->line_out_pins[0];
3732 if (nid) {
3733 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Front Playback Volume",
3734 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
3735 return err;
3736 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Front Playback Switch",
3737 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
3738 return err;
3739 }
3740
3741 nid = cfg->speaker_pin;
3742 if (nid) {
3743 if (nid == 0x16) {
3744 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
3745 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
3746 return err;
3747 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
3748 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
3749 return err;
3750 } else {
3751 if (! cfg->line_out_pins[0])
3752 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
3753 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
3754 return err;
3755 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
3756 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
3757 return err;
3758 }
3759 }
3760 nid = cfg->hp_pin;
3761 if (nid) {
3762 /* spec->multiout.hp_nid = 2; */
3763 if (nid == 0x16) {
3764 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
3765 HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
3766 return err;
3767 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
3768 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
3769 return err;
3770 } else {
3771 if (! cfg->line_out_pins[0])
3772 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
3773 HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
3774 return err;
3775 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
3776 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
3777 return err;
3778 }
3779 }
3780 return 0;
3781}
3782
3783/* identical with ALC880 */
3784#define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls
3785
3786/*
3787 * generic initialization of ADC, input mixers and output mixers
3788 */
3789static struct hda_verb alc262_volume_init_verbs[] = {
3790 /*
3791 * Unmute ADC0-2 and set the default input to mic-in
3792 */
3793 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
3794 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3795 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
3796 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3797 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
3798 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3799
3800 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
3801 * mixer widget
3802 * Note: PASD motherboards uses the Line In 2 as the input for front panel
3803 * mic (mic 2)
3804 */
3805 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
3806 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3807 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3808 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
3809 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
3810 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
3811
3812 /*
3813 * Set up output mixers (0x0c - 0x0f)
3814 */
3815 /* set vol=0 to output mixers */
3816 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3817 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3818 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
3819
3820 /* set up input amps for analog loopback */
3821 /* Amp Indices: DAC = 0, mixer = 1 */
3822 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3823 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3824 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3825 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3826 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
3827 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
3828
3829 /* FIXME: use matrix-type input source selection */
3830 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
3831 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
3832 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3833 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3834 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3835 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3836 /* Input mixer2 */
3837 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3838 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3839 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3840 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3841 /* Input mixer3 */
3842 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
3843 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
3844 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
3845 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
3846
3847 { }
3848};
3849
3850/* pcm configuration: identiacal with ALC880 */
3851#define alc262_pcm_analog_playback alc880_pcm_analog_playback
3852#define alc262_pcm_analog_capture alc880_pcm_analog_capture
3853#define alc262_pcm_digital_playback alc880_pcm_digital_playback
3854#define alc262_pcm_digital_capture alc880_pcm_digital_capture
3855
3856/*
3857 * BIOS auto configuration
3858 */
3859static int alc262_parse_auto_config(struct hda_codec *codec)
3860{
3861 struct alc_spec *spec = codec->spec;
3862 int err;
3863 static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
3864
3865 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3866 alc262_ignore)) < 0)
3867 return err;
3868 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
3869 ! spec->autocfg.hp_pin)
3870 return 0; /* can't find valid BIOS pin config */
3871 if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
3872 (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
3873 return err;
3874
3875 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3876
3877 if (spec->autocfg.dig_out_pin)
3878 spec->multiout.dig_out_nid = ALC262_DIGOUT_NID;
3879 if (spec->autocfg.dig_in_pin)
3880 spec->dig_in_nid = ALC262_DIGIN_NID;
3881
3882 if (spec->kctl_alloc)
3883 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
3884
3885 spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
3886 spec->input_mux = &spec->private_imux;
3887
3888 return 1;
3889}
3890
3891#define alc262_auto_init_multi_out alc882_auto_init_multi_out
3892#define alc262_auto_init_hp_out alc882_auto_init_hp_out
3893#define alc262_auto_init_analog_input alc882_auto_init_analog_input
3894
3895
3896/* init callback for auto-configuration model -- overriding the default init */
3897static int alc262_auto_init(struct hda_codec *codec)
3898{
3899 alc_init(codec);
3900 alc262_auto_init_multi_out(codec);
3901 alc262_auto_init_hp_out(codec);
3902 alc262_auto_init_analog_input(codec);
3903 return 0;
3904}
3905
3906/*
3907 * configuration and preset
3908 */
3909static struct hda_board_config alc262_cfg_tbl[] = {
3910 { .modelname = "basic", .config = ALC262_BASIC },
3911 { .modelname = "auto", .config = ALC262_AUTO },
3912 {}
3913};
3914
3915static struct alc_config_preset alc262_presets[] = {
3916 [ALC262_BASIC] = {
3917 .mixers = { alc262_base_mixer },
3918 .init_verbs = { alc262_init_verbs },
3919 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
3920 .dac_nids = alc262_dac_nids,
3921 .hp_nid = 0x03,
3922 .num_channel_mode = ARRAY_SIZE(alc262_modes),
3923 .channel_mode = alc262_modes,
3924 },
3925};
3926
3927static int patch_alc262(struct hda_codec *codec)
3928{
3929 struct alc_spec *spec;
3930 int board_config;
3931 int err;
3932
3933 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
3934 if (spec == NULL)
3935 return -ENOMEM;
3936
3937 codec->spec = spec;
3938#if 0
3939 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is under-run */
3940 {
3941 int tmp;
3942 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
3943 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
3944 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
3945 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
3946 }
3947#endif
3948
3949 board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl);
3950 if (board_config < 0 || board_config >= ALC262_MODEL_LAST) {
3951 printk(KERN_INFO "hda_codec: Unknown model for ALC262, trying auto-probe from BIOS...\n");
3952 board_config = ALC262_AUTO;
3953 }
3954
3955 if (board_config == ALC262_AUTO) {
3956 /* automatic parse from the BIOS config */
3957 err = alc262_parse_auto_config(codec);
3958 if (err < 0) {
3959 alc_free(codec);
3960 return err;
3961 } else if (! err) {
3962 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
3963 board_config = ALC262_BASIC;
3964 }
3965 }
3966
3967 if (board_config != ALC262_AUTO)
3968 setup_preset(spec, &alc262_presets[board_config]);
3969
3970 spec->stream_name_analog = "ALC262 Analog";
3971 spec->stream_analog_playback = &alc262_pcm_analog_playback;
3972 spec->stream_analog_capture = &alc262_pcm_analog_capture;
3973
3974 spec->stream_name_digital = "ALC262 Digital";
3975 spec->stream_digital_playback = &alc262_pcm_digital_playback;
3976 spec->stream_digital_capture = &alc262_pcm_digital_capture;
3977
3978 if (! spec->adc_nids && spec->input_mux) {
3979 /* check whether NID 0x07 is valid */
3980 unsigned int wcap = snd_hda_param_read(codec, 0x07,
3981 AC_PAR_AUDIO_WIDGET_CAP);
3982 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
3983 if (wcap != AC_WID_AUD_IN) {
3984 spec->adc_nids = alc262_adc_nids_alt;
3985 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
3986 spec->mixers[spec->num_mixers] = alc262_capture_alt_mixer;
3987 spec->num_mixers++;
3988 } else {
3989 spec->adc_nids = alc262_adc_nids;
3990 spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
3991 spec->mixers[spec->num_mixers] = alc262_capture_mixer;
3992 spec->num_mixers++;
3993 }
3994 }
2684 3995
2685 codec->patch_ops = alc_patch_ops; 3996 codec->patch_ops = alc_patch_ops;
3997 if (board_config == ALC262_AUTO)
3998 codec->patch_ops.init = alc262_auto_init;
3999
4000 return 0;
4001}
4002
4003
4004/*
4005 * ALC861 channel source setting (2/6 channel selection for 3-stack)
4006 */
4007
4008/*
4009 * set the path ways for 2 channel output
4010 * need to set the codec line out and mic 1 pin widgets to inputs
4011 */
4012static struct hda_verb alc861_threestack_ch2_init[] = {
4013 /* set pin widget 1Ah (line in) for input */
4014 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4015 /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
4016 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4017
4018 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
4019 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, //mic
4020 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, //line in
4021 { } /* end */
4022};
4023/*
4024 * 6ch mode
4025 * need to set the codec line out and mic 1 pin widgets to outputs
4026 */
4027static struct hda_verb alc861_threestack_ch6_init[] = {
4028 /* set pin widget 1Ah (line in) for output (Back Surround)*/
4029 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4030 /* set pin widget 18h (mic1) for output (CLFE)*/
4031 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4032
4033 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
4034 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
4035
4036 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
4037 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, //mic
4038 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, //line in
4039 { } /* end */
4040};
4041
4042static struct hda_channel_mode alc861_threestack_modes[2] = {
4043 { 2, alc861_threestack_ch2_init },
4044 { 6, alc861_threestack_ch6_init },
4045};
4046
4047/* patch-ALC861 */
4048
4049static struct snd_kcontrol_new alc861_base_mixer[] = {
4050 /* output mixer control */
4051 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
4052 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
4053 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
4054 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
4055 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
4056
4057 /*Input mixer control */
4058 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4059 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4060 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
4061 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
4062 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
4063 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
4064 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
4065 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
4066 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
4067 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
4068
4069 /* Capture mixer control */
4070 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4071 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4072 {
4073 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4074 .name = "Capture Source",
4075 .count = 1,
4076 .info = alc_mux_enum_info,
4077 .get = alc_mux_enum_get,
4078 .put = alc_mux_enum_put,
4079 },
4080 { } /* end */
4081};
4082
4083static struct snd_kcontrol_new alc861_3ST_mixer[] = {
4084 /* output mixer control */
4085 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
4086 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
4087 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
4088 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
4089 /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
4090
4091 /* Input mixer control */
4092 /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
4093 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
4094 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
4095 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
4096 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
4097 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
4098 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
4099 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
4100 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
4101 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
4102
4103 /* Capture mixer control */
4104 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4105 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4106 {
4107 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4108 .name = "Capture Source",
4109 .count = 1,
4110 .info = alc_mux_enum_info,
4111 .get = alc_mux_enum_get,
4112 .put = alc_mux_enum_put,
4113 },
4114 {
4115 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4116 .name = "Channel Mode",
4117 .info = alc_ch_mode_info,
4118 .get = alc_ch_mode_get,
4119 .put = alc_ch_mode_put,
4120 .private_value = ARRAY_SIZE(alc861_threestack_modes),
4121 },
4122 { } /* end */
4123};
4124
4125/*
4126 * generic initialization of ADC, input mixers and output mixers
4127 */
4128static struct hda_verb alc861_base_init_verbs[] = {
4129 /*
4130 * Unmute ADC0 and set the default input to mic-in
4131 */
4132 /* port-A for surround (rear panel) */
4133 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4134 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
4135 /* port-B for mic-in (rear panel) with vref */
4136 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4137 /* port-C for line-in (rear panel) */
4138 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4139 /* port-D for Front */
4140 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4141 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
4142 /* port-E for HP out (front panel) */
4143 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
4144 /* route front PCM to HP */
4145 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
4146 /* port-F for mic-in (front panel) with vref */
4147 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4148 /* port-G for CLFE (rear panel) */
4149 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4150 { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
4151 /* port-H for side (rear panel) */
4152 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4153 { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
4154 /* CD-in */
4155 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4156 /* route front mic to ADC1*/
4157 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4158 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4159
4160 /* Unmute DAC0~3 & spdif out*/
4161 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4162 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4163 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4164 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4165 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4166
4167 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4168 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4169 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4170 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4171 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4172
4173 /* Unmute Stereo Mixer 15 */
4174 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4175 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4176 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4177 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step
4178
4179 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4180 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4181 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4182 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4183 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4184 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4185 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4186 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4187 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4188 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4189
4190 { }
4191};
2686 4192
4193static struct hda_verb alc861_threestack_init_verbs[] = {
4194 /*
4195 * Unmute ADC0 and set the default input to mic-in
4196 */
4197 /* port-A for surround (rear panel) */
4198 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4199 /* port-B for mic-in (rear panel) with vref */
4200 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4201 /* port-C for line-in (rear panel) */
4202 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4203 /* port-D for Front */
4204 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
4205 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
4206 /* port-E for HP out (front panel) */
4207 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
4208 /* route front PCM to HP */
4209 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 },
4210 /* port-F for mic-in (front panel) with vref */
4211 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
4212 /* port-G for CLFE (rear panel) */
4213 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4214 /* port-H for side (rear panel) */
4215 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
4216 /* CD-in */
4217 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
4218 /* route front mic to ADC1*/
4219 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4220 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4221 /* Unmute DAC0~3 & spdif out*/
4222 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4223 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4224 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4225 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4226 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4227
4228 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4229 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4230 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4231 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4232 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4233
4234 /* Unmute Stereo Mixer 15 */
4235 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4236 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4237 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4238 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step
4239
4240 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4241 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4242 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4243 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4244 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4245 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4246 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4247 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4248 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
4249 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4250 { }
4251};
4252/*
4253 * generic initialization of ADC, input mixers and output mixers
4254 */
4255static struct hda_verb alc861_auto_init_verbs[] = {
4256 /*
4257 * Unmute ADC0 and set the default input to mic-in
4258 */
4259// {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4260 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4261
4262 /* Unmute DAC0~3 & spdif out*/
4263 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4264 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4265 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4266 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4267 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4268
4269 /* Unmute Mixer 14 (mic) 1c (Line in)*/
4270 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4271 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4272 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4273 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4274
4275 /* Unmute Stereo Mixer 15 */
4276 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4277 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4278 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4279 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c},
4280
4281 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4282 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4283 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4284 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4285 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4286 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4287 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4288 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
4289
4290 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4291 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4292 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4293 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4294 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4295 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4296 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
4297 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
4298
4299 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, // set Mic 1
4300
4301 { }
4302};
4303
4304/* pcm configuration: identiacal with ALC880 */
4305#define alc861_pcm_analog_playback alc880_pcm_analog_playback
4306#define alc861_pcm_analog_capture alc880_pcm_analog_capture
4307#define alc861_pcm_digital_playback alc880_pcm_digital_playback
4308#define alc861_pcm_digital_capture alc880_pcm_digital_capture
4309
4310
4311#define ALC861_DIGOUT_NID 0x07
4312
4313static struct hda_channel_mode alc861_8ch_modes[1] = {
4314 { 8, NULL }
4315};
4316
4317static hda_nid_t alc861_dac_nids[4] = {
4318 /* front, surround, clfe, side */
4319 0x03, 0x06, 0x05, 0x04
4320};
4321
4322static hda_nid_t alc861_adc_nids[1] = {
4323 /* ADC0-2 */
4324 0x08,
4325};
4326
4327static struct hda_input_mux alc861_capture_source = {
4328 .num_items = 5,
4329 .items = {
4330 { "Mic", 0x0 },
4331 { "Front Mic", 0x3 },
4332 { "Line", 0x1 },
4333 { "CD", 0x4 },
4334 { "Mixer", 0x5 },
4335 },
4336};
4337
4338/* fill in the dac_nids table from the parsed pin configuration */
4339static int alc861_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4340{
4341 int i;
4342 hda_nid_t nid;
4343
4344 spec->multiout.dac_nids = spec->private_dac_nids;
4345 for (i = 0; i < cfg->line_outs; i++) {
4346 nid = cfg->line_out_pins[i];
4347 if (nid) {
4348 if (i >= ARRAY_SIZE(alc861_dac_nids))
4349 continue;
4350 spec->multiout.dac_nids[i] = alc861_dac_nids[i];
4351 }
4352 }
4353 spec->multiout.num_dacs = cfg->line_outs;
4354 return 0;
4355}
4356
4357/* add playback controls from the parsed DAC table */
4358static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
4359 const struct auto_pin_cfg *cfg)
4360{
4361 char name[32];
4362 static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
4363 hda_nid_t nid;
4364 int i, idx, err;
4365
4366 for (i = 0; i < cfg->line_outs; i++) {
4367 nid = spec->multiout.dac_nids[i];
4368 if (! nid)
4369 continue;
4370 if (nid == 0x05) {
4371 /* Center/LFE */
4372 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
4373 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
4374 return err;
4375 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
4376 HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
4377 return err;
4378 } else {
4379 for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; idx++)
4380 if (nid == alc861_dac_nids[idx])
4381 break;
4382 sprintf(name, "%s Playback Switch", chname[idx]);
4383 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
4384 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4385 return err;
4386 }
4387 }
4388 return 0;
4389}
4390
4391static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
4392{
4393 int err;
4394 hda_nid_t nid;
4395
4396 if (! pin)
4397 return 0;
4398
4399 if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
4400 nid = 0x03;
4401 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
4402 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
4403 return err;
4404 spec->multiout.hp_nid = nid;
4405 }
4406 return 0;
4407}
4408
4409/* create playback/capture controls for input pins */
4410static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
4411{
4412 static char *labels[AUTO_PIN_LAST] = {
4413 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
4414 };
4415 struct hda_input_mux *imux = &spec->private_imux;
4416 int i, err, idx, idx1;
4417
4418 for (i = 0; i < AUTO_PIN_LAST; i++) {
4419 switch(cfg->input_pins[i]) {
4420 case 0x0c:
4421 idx1 = 1;
4422 idx = 2; // Line In
4423 break;
4424 case 0x0f:
4425 idx1 = 2;
4426 idx = 2; // Line In
4427 break;
4428 case 0x0d:
4429 idx1 = 0;
4430 idx = 1; // Mic In
4431 break;
4432 case 0x10:
4433 idx1 = 3;
4434 idx = 1; // Mic In
4435 break;
4436 case 0x11:
4437 idx1 = 4;
4438 idx = 0; // CD
4439 break;
4440 default:
4441 continue;
4442 }
4443
4444 err = new_analog_input(spec, cfg->input_pins[i], labels[i], idx, 0x15);
4445 if (err < 0)
4446 return err;
4447
4448 imux->items[imux->num_items].label = labels[i];
4449 imux->items[imux->num_items].index = idx1;
4450 imux->num_items++;
4451 }
4452 return 0;
4453}
4454
4455static struct snd_kcontrol_new alc861_capture_mixer[] = {
4456 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
4457 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
4458
4459 {
4460 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4461 /* The multiple "Capture Source" controls confuse alsamixer
4462 * So call somewhat different..
4463 *FIXME: the controls appear in the "playback" view!
4464 */
4465 /* .name = "Capture Source", */
4466 .name = "Input Source",
4467 .count = 1,
4468 .info = alc_mux_enum_info,
4469 .get = alc_mux_enum_get,
4470 .put = alc_mux_enum_put,
4471 },
4472 { } /* end */
4473};
4474
4475static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid,
4476 int pin_type, int dac_idx)
4477{
4478 /* set as output */
4479
4480 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
4481 snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
4482
4483}
4484
4485static void alc861_auto_init_multi_out(struct hda_codec *codec)
4486{
4487 struct alc_spec *spec = codec->spec;
4488 int i;
4489
4490 for (i = 0; i < spec->autocfg.line_outs; i++) {
4491 hda_nid_t nid = spec->autocfg.line_out_pins[i];
4492 if (nid)
4493 alc861_auto_set_output_and_unmute(codec, nid, PIN_OUT, spec->multiout.dac_nids[i]);
4494 }
4495}
4496
4497static void alc861_auto_init_hp_out(struct hda_codec *codec)
4498{
4499 struct alc_spec *spec = codec->spec;
4500 hda_nid_t pin;
4501
4502 pin = spec->autocfg.hp_pin;
4503 if (pin) /* connect to front */
4504 alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]);
4505}
4506
4507static void alc861_auto_init_analog_input(struct hda_codec *codec)
4508{
4509 struct alc_spec *spec = codec->spec;
4510 int i;
4511
4512 for (i = 0; i < AUTO_PIN_LAST; i++) {
4513 hda_nid_t nid = spec->autocfg.input_pins[i];
4514 if ((nid>=0x0c) && (nid <=0x11)) {
4515 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4516 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
4517 }
4518 }
4519}
4520
4521/* parse the BIOS configuration and set up the alc_spec */
4522/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
4523static int alc861_parse_auto_config(struct hda_codec *codec)
4524{
4525 struct alc_spec *spec = codec->spec;
4526 int err;
4527 static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
4528
4529 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
4530 alc861_ignore)) < 0)
4531 return err;
4532 if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
4533 ! spec->autocfg.hp_pin)
4534 return 0; /* can't find valid BIOS pin config */
4535
4536 if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
4537 (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
4538 (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
4539 (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
4540 return err;
4541
4542 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
4543
4544 if (spec->autocfg.dig_out_pin)
4545 spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
4546
4547 if (spec->kctl_alloc)
4548 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
4549
4550 spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
4551
4552 spec->input_mux = &spec->private_imux;
4553
4554 spec->adc_nids = alc861_adc_nids;
4555 spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
4556 spec->mixers[spec->num_mixers] = alc861_capture_mixer;
4557 spec->num_mixers++;
4558
4559 return 1;
4560}
4561
4562/* init callback for auto-configuration model -- overriding the default init */
4563static int alc861_auto_init(struct hda_codec *codec)
4564{
4565 alc_init(codec);
4566 alc861_auto_init_multi_out(codec);
4567 alc861_auto_init_hp_out(codec);
4568 alc861_auto_init_analog_input(codec);
4569
4570 return 0;
4571}
4572
4573
4574/*
4575 * configuration and preset
4576 */
4577static struct hda_board_config alc861_cfg_tbl[] = {
4578 { .modelname = "3stack", .config = ALC861_3ST },
4579 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, .config = ALC861_3ST },
4580 { .modelname = "3stack-dig", .config = ALC861_3ST_DIG },
4581 { .modelname = "6stack-dig", .config = ALC861_6ST_DIG },
4582 { .modelname = "auto", .config = ALC861_AUTO },
4583 {}
4584};
4585
4586static struct alc_config_preset alc861_presets[] = {
4587 [ALC861_3ST] = {
4588 .mixers = { alc861_3ST_mixer },
4589 .init_verbs = { alc861_threestack_init_verbs },
4590 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4591 .dac_nids = alc861_dac_nids,
4592 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
4593 .channel_mode = alc861_threestack_modes,
4594 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4595 .adc_nids = alc861_adc_nids,
4596 .input_mux = &alc861_capture_source,
4597 },
4598 [ALC861_3ST_DIG] = {
4599 .mixers = { alc861_base_mixer },
4600 .init_verbs = { alc861_threestack_init_verbs },
4601 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4602 .dac_nids = alc861_dac_nids,
4603 .dig_out_nid = ALC861_DIGOUT_NID,
4604 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
4605 .channel_mode = alc861_threestack_modes,
4606 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4607 .adc_nids = alc861_adc_nids,
4608 .input_mux = &alc861_capture_source,
4609 },
4610 [ALC861_6ST_DIG] = {
4611 .mixers = { alc861_base_mixer },
4612 .init_verbs = { alc861_base_init_verbs },
4613 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
4614 .dac_nids = alc861_dac_nids,
4615 .dig_out_nid = ALC861_DIGOUT_NID,
4616 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
4617 .channel_mode = alc861_8ch_modes,
4618 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
4619 .adc_nids = alc861_adc_nids,
4620 .input_mux = &alc861_capture_source,
4621 },
4622};
4623
4624
4625static int patch_alc861(struct hda_codec *codec)
4626{
4627 struct alc_spec *spec;
4628 int board_config;
4629 int err;
4630
4631 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
4632 if (spec == NULL)
4633 return -ENOMEM;
4634
4635 codec->spec = spec;
4636
4637 board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl);
4638 if (board_config < 0 || board_config >= ALC861_MODEL_LAST) {
4639 printk(KERN_INFO "hda_codec: Unknown model for ALC861, trying auto-probe from BIOS...\n");
4640 board_config = ALC861_AUTO;
4641 }
4642
4643 if (board_config == ALC861_AUTO) {
4644 /* automatic parse from the BIOS config */
4645 err = alc861_parse_auto_config(codec);
4646 if (err < 0) {
4647 alc_free(codec);
4648 return err;
4649 } else if (! err) {
4650 printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using base mode...\n");
4651 board_config = ALC861_3ST_DIG;
4652 }
4653 }
4654
4655 if (board_config != ALC861_AUTO)
4656 setup_preset(spec, &alc861_presets[board_config]);
4657
4658 spec->stream_name_analog = "ALC861 Analog";
4659 spec->stream_analog_playback = &alc861_pcm_analog_playback;
4660 spec->stream_analog_capture = &alc861_pcm_analog_capture;
4661
4662 spec->stream_name_digital = "ALC861 Digital";
4663 spec->stream_digital_playback = &alc861_pcm_digital_playback;
4664 spec->stream_digital_capture = &alc861_pcm_digital_capture;
4665
4666 codec->patch_ops = alc_patch_ops;
4667 if (board_config == ALC861_AUTO)
4668 codec->patch_ops.init = alc861_auto_init;
4669
2687 return 0; 4670 return 0;
2688} 4671}
2689 4672
@@ -2692,7 +4675,11 @@ static int patch_alc882(struct hda_codec *codec)
2692 */ 4675 */
2693struct hda_codec_preset snd_hda_preset_realtek[] = { 4676struct hda_codec_preset snd_hda_preset_realtek[] = {
2694 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, 4677 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
4678 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
2695 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, 4679 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
2696 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, 4680 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
4681 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
4682 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
4683 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
2697 {} /* terminator */ 4684 {} /* terminator */
2698}; 4685};