]> git.karo-electronics.de Git - karo-tx-linux.git/blob - sound/pci/hda/alc861_quirks.c
Merge branch 'master' into devel and apply fixup from Stephen Rothwell:
[karo-tx-linux.git] / sound / pci / hda / alc861_quirks.c
1 /*
2  * ALC660/ALC861 quirk models
3  * included by patch_realtek.c
4  */
5
6 /* ALC861 models */
7 enum {
8         ALC861_AUTO,
9         ALC861_3ST,
10         ALC660_3ST,
11         ALC861_3ST_DIG,
12         ALC861_6ST_DIG,
13         ALC861_UNIWILL_M31,
14         ALC861_TOSHIBA,
15         ALC861_ASUS,
16         ALC861_ASUS_LAPTOP,
17         ALC861_MODEL_LAST,
18 };
19
20 /*
21  *  ALC861 channel source setting (2/6 channel selection for 3-stack)
22  */
23
24 /*
25  * set the path ways for 2 channel output
26  * need to set the codec line out and mic 1 pin widgets to inputs
27  */
28 static const struct hda_verb alc861_threestack_ch2_init[] = {
29         /* set pin widget 1Ah (line in) for input */
30         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
31         /* set pin widget 18h (mic1/2) for input, for mic also enable
32          * the vref
33          */
34         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
35
36         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
37 #if 0
38         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
39         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
40 #endif
41         { } /* end */
42 };
43 /*
44  * 6ch mode
45  * need to set the codec line out and mic 1 pin widgets to outputs
46  */
47 static const struct hda_verb alc861_threestack_ch6_init[] = {
48         /* set pin widget 1Ah (line in) for output (Back Surround)*/
49         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
50         /* set pin widget 18h (mic1) for output (CLFE)*/
51         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
52
53         { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
54         { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
55
56         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
57 #if 0
58         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
59         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
60 #endif
61         { } /* end */
62 };
63
64 static const struct hda_channel_mode alc861_threestack_modes[2] = {
65         { 2, alc861_threestack_ch2_init },
66         { 6, alc861_threestack_ch6_init },
67 };
68 /* Set mic1 as input and unmute the mixer */
69 static const struct hda_verb alc861_uniwill_m31_ch2_init[] = {
70         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
71         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
72         { } /* end */
73 };
74 /* Set mic1 as output and mute mixer */
75 static const struct hda_verb alc861_uniwill_m31_ch4_init[] = {
76         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
77         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
78         { } /* end */
79 };
80
81 static const struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
82         { 2, alc861_uniwill_m31_ch2_init },
83         { 4, alc861_uniwill_m31_ch4_init },
84 };
85
86 /* Set mic1 and line-in as input and unmute the mixer */
87 static const struct hda_verb alc861_asus_ch2_init[] = {
88         /* set pin widget 1Ah (line in) for input */
89         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
90         /* set pin widget 18h (mic1/2) for input, for mic also enable
91          * the vref
92          */
93         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
94
95         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
96 #if 0
97         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
98         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
99 #endif
100         { } /* end */
101 };
102 /* Set mic1 nad line-in as output and mute mixer */
103 static const struct hda_verb alc861_asus_ch6_init[] = {
104         /* set pin widget 1Ah (line in) for output (Back Surround)*/
105         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
106         /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
107         /* set pin widget 18h (mic1) for output (CLFE)*/
108         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
109         /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
110         { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
111         { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
112
113         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
114 #if 0
115         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
116         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
117 #endif
118         { } /* end */
119 };
120
121 static const struct hda_channel_mode alc861_asus_modes[2] = {
122         { 2, alc861_asus_ch2_init },
123         { 6, alc861_asus_ch6_init },
124 };
125
126 /* patch-ALC861 */
127
128 static const struct snd_kcontrol_new alc861_base_mixer[] = {
129         /* output mixer control */
130         HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
131         HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
132         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
133         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
134         HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
135
136         /*Input mixer control */
137         /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
138            HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
139         HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
140         HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
141         HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
142         HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
143         HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
144         HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
145         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
146         HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
147
148         { } /* end */
149 };
150
151 static const struct snd_kcontrol_new alc861_3ST_mixer[] = {
152         /* output mixer control */
153         HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
154         HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
155         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
156         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
157         /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
158
159         /* Input mixer control */
160         /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
161            HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
162         HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
163         HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
164         HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
165         HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
166         HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
167         HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
168         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
169         HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
170
171         {
172                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
173                 .name = "Channel Mode",
174                 .info = alc_ch_mode_info,
175                 .get = alc_ch_mode_get,
176                 .put = alc_ch_mode_put,
177                 .private_value = ARRAY_SIZE(alc861_threestack_modes),
178         },
179         { } /* end */
180 };
181
182 static const struct snd_kcontrol_new alc861_toshiba_mixer[] = {
183         /* output mixer control */
184         HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
185         HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
186         HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
187
188         { } /* end */
189 };
190
191 static const struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
192         /* output mixer control */
193         HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
194         HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
195         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
196         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
197         /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
198
199         /* Input mixer control */
200         /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
201            HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
202         HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
203         HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
204         HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
205         HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
206         HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
207         HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
208         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
209         HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
210
211         {
212                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
213                 .name = "Channel Mode",
214                 .info = alc_ch_mode_info,
215                 .get = alc_ch_mode_get,
216                 .put = alc_ch_mode_put,
217                 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
218         },
219         { } /* end */
220 };
221
222 static const struct snd_kcontrol_new alc861_asus_mixer[] = {
223         /* output mixer control */
224         HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
225         HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
226         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
227         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
228         HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
229
230         /* Input mixer control */
231         HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
232         HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
233         HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
234         HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
235         HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
236         HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
237         HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
238         HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
239         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
240         HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
241
242         {
243                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
244                 .name = "Channel Mode",
245                 .info = alc_ch_mode_info,
246                 .get = alc_ch_mode_get,
247                 .put = alc_ch_mode_put,
248                 .private_value = ARRAY_SIZE(alc861_asus_modes),
249         },
250         { }
251 };
252
253 /* additional mixer */
254 static const struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
255         HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
256         HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
257         { }
258 };
259
260 /*
261  * generic initialization of ADC, input mixers and output mixers
262  */
263 static const struct hda_verb alc861_base_init_verbs[] = {
264         /*
265          * Unmute ADC0 and set the default input to mic-in
266          */
267         /* port-A for surround (rear panel) */
268         { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
269         { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
270         /* port-B for mic-in (rear panel) with vref */
271         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
272         /* port-C for line-in (rear panel) */
273         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
274         /* port-D for Front */
275         { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
276         { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
277         /* port-E for HP out (front panel) */
278         { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
279         /* route front PCM to HP */
280         { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
281         /* port-F for mic-in (front panel) with vref */
282         { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
283         /* port-G for CLFE (rear panel) */
284         { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
285         { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
286         /* port-H for side (rear panel) */
287         { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
288         { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
289         /* CD-in */
290         { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
291         /* route front mic to ADC1*/
292         {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
293         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
294
295         /* Unmute DAC0~3 & spdif out*/
296         {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
297         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
298         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
299         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
300         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
301
302         /* Unmute Mixer 14 (mic) 1c (Line in)*/
303         {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
304         {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
305         {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
306         {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
307
308         /* Unmute Stereo Mixer 15 */
309         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
310         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
311         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
312         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
313
314         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
315         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
316         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
317         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
318         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
319         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
320         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
321         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
322         /* hp used DAC 3 (Front) */
323         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
324         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
325
326         { }
327 };
328
329 static const struct hda_verb alc861_threestack_init_verbs[] = {
330         /*
331          * Unmute ADC0 and set the default input to mic-in
332          */
333         /* port-A for surround (rear panel) */
334         { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
335         /* port-B for mic-in (rear panel) with vref */
336         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
337         /* port-C for line-in (rear panel) */
338         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
339         /* port-D for Front */
340         { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
341         { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
342         /* port-E for HP out (front panel) */
343         { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
344         /* route front PCM to HP */
345         { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
346         /* port-F for mic-in (front panel) with vref */
347         { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
348         /* port-G for CLFE (rear panel) */
349         { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
350         /* port-H for side (rear panel) */
351         { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
352         /* CD-in */
353         { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
354         /* route front mic to ADC1*/
355         {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
356         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
357         /* Unmute DAC0~3 & spdif out*/
358         {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
359         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
360         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
361         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
362         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
363
364         /* Unmute Mixer 14 (mic) 1c (Line in)*/
365         {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
366         {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
367         {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
368         {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
369
370         /* Unmute Stereo Mixer 15 */
371         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
372         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
373         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
374         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
375
376         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
377         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
378         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
379         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
380         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
381         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
382         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
383         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
384         /* hp used DAC 3 (Front) */
385         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
386         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
387         { }
388 };
389
390 static const struct hda_verb alc861_uniwill_m31_init_verbs[] = {
391         /*
392          * Unmute ADC0 and set the default input to mic-in
393          */
394         /* port-A for surround (rear panel) */
395         { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
396         /* port-B for mic-in (rear panel) with vref */
397         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
398         /* port-C for line-in (rear panel) */
399         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
400         /* port-D for Front */
401         { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
402         { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
403         /* port-E for HP out (front panel) */
404         /* this has to be set to VREF80 */
405         { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
406         /* route front PCM to HP */
407         { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
408         /* port-F for mic-in (front panel) with vref */
409         { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
410         /* port-G for CLFE (rear panel) */
411         { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
412         /* port-H for side (rear panel) */
413         { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
414         /* CD-in */
415         { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
416         /* route front mic to ADC1*/
417         {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
418         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
419         /* Unmute DAC0~3 & spdif out*/
420         {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
421         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
422         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
423         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
424         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
425
426         /* Unmute Mixer 14 (mic) 1c (Line in)*/
427         {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
428         {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
429         {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
430         {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
431
432         /* Unmute Stereo Mixer 15 */
433         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
434         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
435         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
436         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
437
438         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
439         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
440         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
441         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
442         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
443         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
444         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
445         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
446         /* hp used DAC 3 (Front) */
447         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
448         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
449         { }
450 };
451
452 static const struct hda_verb alc861_asus_init_verbs[] = {
453         /*
454          * Unmute ADC0 and set the default input to mic-in
455          */
456         /* port-A for surround (rear panel)
457          * according to codec#0 this is the HP jack
458          */
459         { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
460         /* route front PCM to HP */
461         { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
462         /* port-B for mic-in (rear panel) with vref */
463         { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
464         /* port-C for line-in (rear panel) */
465         { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
466         /* port-D for Front */
467         { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
468         { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
469         /* port-E for HP out (front panel) */
470         /* this has to be set to VREF80 */
471         { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
472         /* route front PCM to HP */
473         { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
474         /* port-F for mic-in (front panel) with vref */
475         { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
476         /* port-G for CLFE (rear panel) */
477         { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
478         /* port-H for side (rear panel) */
479         { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
480         /* CD-in */
481         { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
482         /* route front mic to ADC1*/
483         {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
484         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
485         /* Unmute DAC0~3 & spdif out*/
486         {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
487         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
488         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
489         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
490         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
491         /* Unmute Mixer 14 (mic) 1c (Line in)*/
492         {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
493         {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
494         {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
495         {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
496
497         /* Unmute Stereo Mixer 15 */
498         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
499         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
500         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
501         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
502
503         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
504         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
505         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
506         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
507         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
508         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
509         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
510         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
511         /* hp used DAC 3 (Front) */
512         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
513         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
514         { }
515 };
516
517 /* additional init verbs for ASUS laptops */
518 static const struct hda_verb alc861_asus_laptop_init_verbs[] = {
519         { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
520         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
521         { }
522 };
523
524 static const struct hda_verb alc861_toshiba_init_verbs[] = {
525         {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
526
527         { }
528 };
529
530 /* toggle speaker-output according to the hp-jack state */
531 static void alc861_toshiba_automute(struct hda_codec *codec)
532 {
533         unsigned int present = snd_hda_jack_detect(codec, 0x0f);
534
535         snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
536                                  HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
537         snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
538                                  HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
539 }
540
541 static void alc861_toshiba_unsol_event(struct hda_codec *codec,
542                                        unsigned int res)
543 {
544         if ((res >> 26) == ALC_HP_EVENT)
545                 alc861_toshiba_automute(codec);
546 }
547
548 #define ALC861_DIGOUT_NID       0x07
549
550 static const struct hda_channel_mode alc861_8ch_modes[1] = {
551         { 8, NULL }
552 };
553
554 static const hda_nid_t alc861_dac_nids[4] = {
555         /* front, surround, clfe, side */
556         0x03, 0x06, 0x05, 0x04
557 };
558
559 static const hda_nid_t alc660_dac_nids[3] = {
560         /* front, clfe, surround */
561         0x03, 0x05, 0x06
562 };
563
564 static const hda_nid_t alc861_adc_nids[1] = {
565         /* ADC0-2 */
566         0x08,
567 };
568
569 static const struct hda_input_mux alc861_capture_source = {
570         .num_items = 5,
571         .items = {
572                 { "Mic", 0x0 },
573                 { "Front Mic", 0x3 },
574                 { "Line", 0x1 },
575                 { "CD", 0x4 },
576                 { "Mixer", 0x5 },
577         },
578 };
579
580 /*
581  * configuration and preset
582  */
583 static const char * const alc861_models[ALC861_MODEL_LAST] = {
584         [ALC861_3ST]            = "3stack",
585         [ALC660_3ST]            = "3stack-660",
586         [ALC861_3ST_DIG]        = "3stack-dig",
587         [ALC861_6ST_DIG]        = "6stack-dig",
588         [ALC861_UNIWILL_M31]    = "uniwill-m31",
589         [ALC861_TOSHIBA]        = "toshiba",
590         [ALC861_ASUS]           = "asus",
591         [ALC861_ASUS_LAPTOP]    = "asus-laptop",
592         [ALC861_AUTO]           = "auto",
593 };
594
595 static const struct snd_pci_quirk alc861_cfg_tbl[] = {
596         SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
597         SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
598         SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
599         SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
600         SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
601         SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
602         SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
603         /* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
604          *        Any other models that need this preset?
605          */
606         /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
607         SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
608         SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
609         SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
610         SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
611         SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
612         /* FIXME: the below seems conflict */
613         /* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */
614         SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
615         SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
616         {}
617 };
618
619 static const struct alc_config_preset alc861_presets[] = {
620         [ALC861_3ST] = {
621                 .mixers = { alc861_3ST_mixer },
622                 .init_verbs = { alc861_threestack_init_verbs },
623                 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
624                 .dac_nids = alc861_dac_nids,
625                 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
626                 .channel_mode = alc861_threestack_modes,
627                 .need_dac_fix = 1,
628                 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
629                 .adc_nids = alc861_adc_nids,
630                 .input_mux = &alc861_capture_source,
631         },
632         [ALC861_3ST_DIG] = {
633                 .mixers = { alc861_base_mixer },
634                 .init_verbs = { alc861_threestack_init_verbs },
635                 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
636                 .dac_nids = alc861_dac_nids,
637                 .dig_out_nid = ALC861_DIGOUT_NID,
638                 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
639                 .channel_mode = alc861_threestack_modes,
640                 .need_dac_fix = 1,
641                 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
642                 .adc_nids = alc861_adc_nids,
643                 .input_mux = &alc861_capture_source,
644         },
645         [ALC861_6ST_DIG] = {
646                 .mixers = { alc861_base_mixer },
647                 .init_verbs = { alc861_base_init_verbs },
648                 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
649                 .dac_nids = alc861_dac_nids,
650                 .dig_out_nid = ALC861_DIGOUT_NID,
651                 .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
652                 .channel_mode = alc861_8ch_modes,
653                 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
654                 .adc_nids = alc861_adc_nids,
655                 .input_mux = &alc861_capture_source,
656         },
657         [ALC660_3ST] = {
658                 .mixers = { alc861_3ST_mixer },
659                 .init_verbs = { alc861_threestack_init_verbs },
660                 .num_dacs = ARRAY_SIZE(alc660_dac_nids),
661                 .dac_nids = alc660_dac_nids,
662                 .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
663                 .channel_mode = alc861_threestack_modes,
664                 .need_dac_fix = 1,
665                 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
666                 .adc_nids = alc861_adc_nids,
667                 .input_mux = &alc861_capture_source,
668         },
669         [ALC861_UNIWILL_M31] = {
670                 .mixers = { alc861_uniwill_m31_mixer },
671                 .init_verbs = { alc861_uniwill_m31_init_verbs },
672                 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
673                 .dac_nids = alc861_dac_nids,
674                 .dig_out_nid = ALC861_DIGOUT_NID,
675                 .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
676                 .channel_mode = alc861_uniwill_m31_modes,
677                 .need_dac_fix = 1,
678                 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
679                 .adc_nids = alc861_adc_nids,
680                 .input_mux = &alc861_capture_source,
681         },
682         [ALC861_TOSHIBA] = {
683                 .mixers = { alc861_toshiba_mixer },
684                 .init_verbs = { alc861_base_init_verbs,
685                                 alc861_toshiba_init_verbs },
686                 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
687                 .dac_nids = alc861_dac_nids,
688                 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
689                 .channel_mode = alc883_3ST_2ch_modes,
690                 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
691                 .adc_nids = alc861_adc_nids,
692                 .input_mux = &alc861_capture_source,
693                 .unsol_event = alc861_toshiba_unsol_event,
694                 .init_hook = alc861_toshiba_automute,
695         },
696         [ALC861_ASUS] = {
697                 .mixers = { alc861_asus_mixer },
698                 .init_verbs = { alc861_asus_init_verbs },
699                 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
700                 .dac_nids = alc861_dac_nids,
701                 .dig_out_nid = ALC861_DIGOUT_NID,
702                 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
703                 .channel_mode = alc861_asus_modes,
704                 .need_dac_fix = 1,
705                 .hp_nid = 0x06,
706                 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
707                 .adc_nids = alc861_adc_nids,
708                 .input_mux = &alc861_capture_source,
709         },
710         [ALC861_ASUS_LAPTOP] = {
711                 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
712                 .init_verbs = { alc861_asus_init_verbs,
713                                 alc861_asus_laptop_init_verbs },
714                 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
715                 .dac_nids = alc861_dac_nids,
716                 .dig_out_nid = ALC861_DIGOUT_NID,
717                 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
718                 .channel_mode = alc883_3ST_2ch_modes,
719                 .need_dac_fix = 1,
720                 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
721                 .adc_nids = alc861_adc_nids,
722                 .input_mux = &alc861_capture_source,
723         },
724 };
725