This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / sound / pci / hda / patch_realtek.c
1 /*
2  * Universal Interface for Intel High Definition Audio Codec
3  *
4  * HD audio interface patch for ALC 260/880/882 codecs
5  *
6  * Copyright (c) 2004 PeiSen Hou <pshou@realtek.com.tw>
7  *                    Takashi Iwai <tiwai@suse.de>
8  *
9  *  This driver is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This driver is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22  */
23
24 #include <sound/driver.h>
25 #include <linux/init.h>
26 #include <linux/delay.h>
27 #include <linux/slab.h>
28 #include <linux/pci.h>
29 #include <sound/core.h>
30 #include "hda_codec.h"
31 #include "hda_local.h"
32
33
34 /* ALC880 board config type */
35 enum {
36         ALC880_MINIMAL,
37         ALC880_3ST,
38         ALC880_3ST_DIG,
39         ALC880_5ST,
40         ALC880_5ST_DIG,
41         ALC880_W810,
42 };
43
44 struct alc_spec {
45         /* codec parameterization */
46         unsigned int front_panel: 1;
47
48         snd_kcontrol_new_t* mixers[2];
49         unsigned int num_mixers;
50
51         struct hda_verb *init_verbs;
52
53         char* stream_name_analog;
54         struct hda_pcm_stream *stream_analog_playback;
55         struct hda_pcm_stream *stream_analog_capture;
56
57         char* stream_name_digital;
58         struct hda_pcm_stream *stream_digital_playback;
59         struct hda_pcm_stream *stream_digital_capture;
60
61         /* playback */
62         struct hda_multi_out multiout;
63
64         /* capture */
65         unsigned int num_adc_nids;
66         hda_nid_t *adc_nids;
67         hda_nid_t dig_in_nid;
68
69         /* capture source */
70         const struct hda_input_mux *input_mux;
71         unsigned int cur_mux[3];
72
73         /* channel model */
74         const struct alc_channel_mode *channel_mode;
75         int num_channel_mode;
76
77         /* PCM information */
78         struct hda_pcm pcm_rec[2];
79 };
80
81 /* DAC/ADC assignment */
82
83 static hda_nid_t alc880_dac_nids[4] = {
84         /* front, rear, clfe, rear_surr */
85         0x02, 0x05, 0x04, 0x03
86 };
87
88 static hda_nid_t alc880_w810_dac_nids[3] = {
89         /* front, rear/surround, clfe */
90         0x02, 0x03, 0x04
91 };
92
93 static hda_nid_t alc880_adc_nids[3] = {
94         /* ADC0-2 */
95         0x07, 0x08, 0x09,
96 };
97
98 #define ALC880_DIGOUT_NID       0x06
99 #define ALC880_DIGIN_NID        0x0a
100
101 static hda_nid_t alc260_dac_nids[1] = {
102         /* front */
103         0x02,
104 };
105
106 static hda_nid_t alc260_adc_nids[2] = {
107         /* ADC0-1 */
108         0x04, 0x05,
109 };
110
111 #define ALC260_DIGOUT_NID       0x03
112 #define ALC260_DIGIN_NID        0x06
113
114 static struct hda_input_mux alc880_capture_source = {
115         .num_items = 4,
116         .items = {
117                 { "Mic", 0x0 },
118                 { "Front Mic", 0x3 },
119                 { "Line", 0x2 },
120                 { "CD", 0x4 },
121         },
122 };
123
124 static struct hda_input_mux alc260_capture_source = {
125         .num_items = 4,
126         .items = {
127                 { "Mic", 0x0 },
128                 { "Front Mic", 0x1 },
129                 { "Line", 0x2 },
130                 { "CD", 0x4 },
131         },
132 };
133
134 /*
135  * input MUX handling
136  */
137 static int alc_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
138 {
139         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
140         struct alc_spec *spec = codec->spec;
141         return snd_hda_input_mux_info(spec->input_mux, uinfo);
142 }
143
144 static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
145 {
146         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
147         struct alc_spec *spec = codec->spec;
148         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
149
150         ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
151         return 0;
152 }
153
154 static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
155 {
156         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
157         struct alc_spec *spec = codec->spec;
158         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
159         return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
160                                      spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
161 }
162
163 /*
164  * channel mode setting
165  */
166 struct alc_channel_mode {
167         int channels;
168         const struct hda_verb *sequence;
169 };
170
171
172 /*
173  * channel source setting (2/6 channel selection for 3-stack)
174  */
175
176 /*
177  * set the path ways for 2 channel output
178  * need to set the codec line out and mic 1 pin widgets to inputs
179  */
180 static struct hda_verb alc880_threestack_ch2_init[] = {
181         /* set pin widget 1Ah (line in) for input */
182         { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
183         /* set pin widget 18h (mic1) for input, for mic also enable the vref */
184         { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
185         /* mute the output for Line In PW */
186         { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
187         /* mute for Mic1 PW */
188         { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
189         { } /* end */
190 };
191
192 /*
193  * 6ch mode
194  * need to set the codec line out and mic 1 pin widgets to outputs
195  */
196 static struct hda_verb alc880_threestack_ch6_init[] = {
197         /* set pin widget 1Ah (line in) for output */
198         { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
199         /* set pin widget 18h (mic1) for output */
200         { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
201         /* unmute the output for Line In PW */
202         { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
203         /* unmute for Mic1 PW */
204         { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
205         /* for rear channel output using Line In 1
206          * set select widget connection (nid = 0x12) - to summer node
207          * for rear NID = 0x0f...offset 3 in connection list
208          */
209         { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 },
210         /* for Mic1 - retask for center/lfe */
211         /* set select widget connection (nid = 0x10) - to summer node for
212          * front CLFE NID = 0x0e...offset 2 in connection list
213          */
214         { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 },
215         { } /* end */
216 };
217
218 static struct alc_channel_mode alc880_threestack_modes[2] = {
219         { 2, alc880_threestack_ch2_init },
220         { 6, alc880_threestack_ch6_init },
221 };
222
223
224 /*
225  * channel source setting (6/8 channel selection for 5-stack)
226  */
227
228 /* set the path ways for 6 channel output
229  * need to set the codec line out and mic 1 pin widgets to inputs
230  */
231 static struct hda_verb alc880_fivestack_ch6_init[] = {
232         /* set pin widget 1Ah (line in) for input */
233         { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
234         /* mute the output for Line In PW */
235         { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
236         { } /* end */
237 };
238
239 /* need to set the codec line out and mic 1 pin widgets to outputs */
240 static struct hda_verb alc880_fivestack_ch8_init[] = {
241         /* set pin widget 1Ah (line in) for output */
242         { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
243         /* unmute the output for Line In PW */
244         { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
245         /* output for surround channel output using Line In 1 */
246         /* set select widget connection (nid = 0x12) - to summer node
247          * for surr_rear NID = 0x0d...offset 1 in connection list
248          */
249         { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 },
250         { } /* end */
251 };
252
253 static struct alc_channel_mode alc880_fivestack_modes[2] = {
254         { 6, alc880_fivestack_ch6_init },
255         { 8, alc880_fivestack_ch8_init },
256 };
257
258 /*
259  * channel source setting for W810 system
260  *
261  * W810 has rear IO for:
262  * Front (DAC 02)
263  * Surround (DAC 03)
264  * Center/LFE (DAC 04)
265  * Digital out (06)
266  *
267  * The system also has a pair of internal speakers, and a headphone jack.
268  * These are both connected to Line2 on the codec, hence to DAC 02.
269  * 
270  * There is a variable resistor to control the speaker or headphone
271  * volume. This is a hardware-only device without a software API.
272  *
273  * Plugging headphones in will disable the internal speakers. This is
274  * implemented in hardware, not via the driver using jack sense. In
275  * a similar fashion, plugging into the rear socket marked "front" will
276  * disable both the speakers and headphones.
277  *
278  * For input, there's a microphone jack, and an "audio in" jack.
279  * These may not do anything useful with this driver yet, because I
280  * haven't setup any initialization verbs for these yet...
281  */
282
283 static struct alc_channel_mode alc880_w810_modes[1] = {
284         { 6, NULL }
285 };
286
287 /*
288  */
289 static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
290 {
291         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
292         struct alc_spec *spec = codec->spec;
293
294         snd_assert(spec->channel_mode, return -ENXIO);
295         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
296         uinfo->count = 1;
297         uinfo->value.enumerated.items = 2;
298         if (uinfo->value.enumerated.item >= 2)
299                 uinfo->value.enumerated.item = 1;
300         sprintf(uinfo->value.enumerated.name, "%dch",
301                 spec->channel_mode[uinfo->value.enumerated.item].channels);
302         return 0;
303 }
304
305 static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
306 {
307         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
308         struct alc_spec *spec = codec->spec;
309
310         snd_assert(spec->channel_mode, return -ENXIO);
311         ucontrol->value.enumerated.item[0] =
312                 (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1;
313         return 0;
314 }
315
316 static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
317 {
318         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
319         struct alc_spec *spec = codec->spec;
320         int mode;
321
322         snd_assert(spec->channel_mode, return -ENXIO);
323         mode = ucontrol->value.enumerated.item[0] ? 1 : 0;
324         if (spec->multiout.max_channels == spec->channel_mode[mode].channels &&
325             ! codec->in_resume)
326                 return 0;
327
328         /* change the current channel setting */
329         spec->multiout.max_channels = spec->channel_mode[mode].channels;
330         if (spec->channel_mode[mode].sequence)
331                 snd_hda_sequence_write(codec, spec->channel_mode[mode].sequence);
332
333         return 1;
334 }
335
336
337 /*
338  */
339
340 /* 3-stack mode
341  * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
342  *                 HP=0x19
343  */
344 static snd_kcontrol_new_t alc880_base_mixer[] = {
345         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
346         HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
347         HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
348         HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
349         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
350         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
351         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT),
352         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT),
353         HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
354         HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
355         HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
356         HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
357         HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
358         HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
359         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
360         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
361         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
362         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
363         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
364         HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
365         HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
366         HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
367         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
368         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
369         {
370                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
371                 /* The multiple "Capture Source" controls confuse alsamixer
372                  * So call somewhat different..
373                  * FIXME: the controls appear in the "playback" view!
374                  */
375                 /* .name = "Capture Source", */
376                 .name = "Input Source",
377                 .count = 2,
378                 .info = alc_mux_enum_info,
379                 .get = alc_mux_enum_get,
380                 .put = alc_mux_enum_put,
381         },
382         {
383                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
384                 .name = "Channel Mode",
385                 .info = alc880_ch_mode_info,
386                 .get = alc880_ch_mode_get,
387                 .put = alc880_ch_mode_put,
388         },
389         { } /* end */
390 };
391
392 /* 5-stack mode
393  * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
394  *                 Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
395  */
396 static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
397         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
398         HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
399         HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
400         HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT),
401         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
402         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
403         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
404         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
405         HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
406         HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
407         HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
408         HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
409         HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
410         HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
411         HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
412         HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
413         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
414         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
415         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
416         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
417         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
418         HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
419         HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
420         HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
421         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
422         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
423         {
424                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
425                 /* The multiple "Capture Source" controls confuse alsamixer
426                  * So call somewhat different..
427                  * FIXME: the controls appear in the "playback" view!
428                  */
429                 /* .name = "Capture Source", */
430                 .name = "Input Source",
431                 .count = 2,
432                 .info = alc_mux_enum_info,
433                 .get = alc_mux_enum_get,
434                 .put = alc_mux_enum_put,
435         },
436         {
437                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
438                 .name = "Channel Mode",
439                 .info = alc880_ch_mode_info,
440                 .get = alc880_ch_mode_get,
441                 .put = alc880_ch_mode_put,
442         },
443         { } /* end */
444 };
445
446 static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
447         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
448         HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
449         HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
450         HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
451         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
452         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
453         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
454         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
455         HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
456         HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
457         HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
458         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
459         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
460         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
461         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
462         {
463                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
464                 /* The multiple "Capture Source" controls confuse alsamixer
465                  * So call somewhat different..
466                  * FIXME: the controls appear in the "playback" view!
467                  */
468                 /* .name = "Capture Source", */
469                 .name = "Input Source",
470                 .count = 3,
471                 .info = alc_mux_enum_info,
472                 .get = alc_mux_enum_get,
473                 .put = alc_mux_enum_put,
474         },
475         { } /* end */
476 };
477
478 /*
479  */
480 static int alc_build_controls(struct hda_codec *codec)
481 {
482         struct alc_spec *spec = codec->spec;
483         int err;
484         int i;
485
486         for (i = 0; i < spec->num_mixers; i++) {
487                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
488                 if (err < 0)
489                         return err;
490         }
491
492         if (spec->multiout.dig_out_nid) {
493                 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
494                 if (err < 0)
495                         return err;
496         }
497         if (spec->dig_in_nid) {
498                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
499                 if (err < 0)
500                         return err;
501         }
502         return 0;
503 }
504
505 /*
506  * initialize the codec volumes, etc
507  */
508
509 static struct hda_verb alc880_init_verbs_three_stack[] = {
510         /* Line In pin widget for input */
511         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
512         /* CD pin widget for input */
513         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
514         /* Mic1 (rear panel) pin widget for input and vref at 80% */
515         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
516         /* Mic2 (front panel) pin widget for input and vref at 80% */
517         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
518         /* unmute amp left and right */
519         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
520         /* set connection select to line in (default select for this ADC) */
521         {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
522         /* unmute front mixer amp left (volume = 0) */
523         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
524         /* mute pin widget amp left and right (no gain on this amp) */
525         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
526         /* unmute rear mixer amp left and right (volume = 0) */
527         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
528         /* mute pin widget amp left and right (no gain on this amp) */
529         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
530         /* unmute rear mixer amp left and right (volume = 0) */
531         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
532         /* mute pin widget amp left and right (no gain on this amp) */
533         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
534
535         /* using rear surround as the path for headphone output */
536         /* unmute rear surround mixer amp left and right (volume = 0) */
537         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
538         /* PASD 3 stack boards use the Mic 2 as the headphone output */
539         /* need to program the selector associated with the Mic 2 pin widget to
540          * surround path (index 0x01) for headphone output */
541         {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
542         /* mute pin widget amp left and right (no gain on this amp) */
543         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
544         /* need to retask the Mic 2 pin widget to output */
545         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
546
547         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
548          * to support the input path of analog loopback
549          * Note: PASD motherboards uses the Line In 2 as the input for front panel
550          * mic (mic 2)
551          */
552         /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
553         /* unmute CD */
554         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
555         /* unmute Line In */
556         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
557         /* unmute Mic 1 */
558         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
559         /* unmute Line In 2 (for PASD boards Mic 2) */
560         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
561
562         /* Unmute input amps for the line out paths to support the output path of
563          * analog loopback
564          * the mixers on the output path has 2 inputs, one from the DAC and one
565          * from the mixer
566          */
567         /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
568         /* Unmute Front out path */
569         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
570         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
571         /* Unmute Surround (used as HP) out path */
572         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
573         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
574         /* Unmute C/LFE out path */
575         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
576         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
577         /* Unmute rear Surround out path */
578         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
579         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
580
581         { }
582 };
583
584 static struct hda_verb alc880_init_verbs_five_stack[] = {
585         /* Line In pin widget for input */
586         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
587         /* CD pin widget for input */
588         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
589         /* Mic1 (rear panel) pin widget for input and vref at 80% */
590         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
591         /* Mic2 (front panel) pin widget for input and vref at 80% */
592         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
593         /* unmute amp left and right */
594         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
595         /* set connection select to line in (default select for this ADC) */
596         {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
597         /* unmute front mixer amp left and right (volume = 0) */
598         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
599         /* mute pin widget amp left and right (no gain on this amp) */
600         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
601         /* five rear and clfe */
602         /* unmute rear mixer amp left and right (volume = 0)  */
603         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
604         /* mute pin widget amp left and right (no gain on this amp) */
605         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
606         /* unmute clfe mixer amp left and right (volume = 0) */
607         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
608         /* mute pin widget amp left and right (no gain on this amp) */
609         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
610
611         /* using rear surround as the path for headphone output */
612         /* unmute rear surround mixer amp left and right (volume = 0) */
613         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
614         /* PASD 3 stack boards use the Mic 2 as the headphone output */
615         /* need to program the selector associated with the Mic 2 pin widget to
616          * surround path (index 0x01) for headphone output
617          */
618         {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
619         /* mute pin widget amp left and right (no gain on this amp) */
620         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
621         /* need to retask the Mic 2 pin widget to output */
622         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
623
624         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
625          * widget(nid=0x0B) to support the input path of analog loopback
626          */
627         /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
628         /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
629         /* unmute CD */
630         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
631         /* unmute Line In */
632         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
633         /* unmute Mic 1 */
634         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
635         /* unmute Line In 2 (for PASD boards Mic 2) */
636         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
637
638         /* Unmute input amps for the line out paths to support the output path of
639          * analog loopback
640          * the mixers on the output path has 2 inputs, one from the DAC and
641          * one from the mixer
642          */
643         /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
644         /* Unmute Front out path */
645         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
646         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
647         /* Unmute Surround (used as HP) out path */
648         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
649         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
650         /* Unmute C/LFE out path */
651         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
652         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
653         /* Unmute rear Surround out path */
654         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
655         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
656
657         { }
658 };
659
660 static struct hda_verb alc880_w810_init_verbs[] = {
661         /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
662         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
663
664         /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
665         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
666
667         /* front channel selector/amp: output 0: unmuted, max volume */
668         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
669
670         /* front out pin: muted, (no volume selection)  */
671         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
672
673         /* front out pin: NOT headphone enable, out enable, vref disabled */
674         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
675
676
677         /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
678         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
679
680         /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
681         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
682
683         /* surround channel selector/amp: output 0: unmuted, max volume */
684         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
685
686         /* surround out pin: muted, (no volume selection)  */
687         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
688
689         /* surround out pin: NOT headphone enable, out enable, vref disabled */
690         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
691
692
693         /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
694         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
695
696         /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
697         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
698
699         /* c/lfe channel selector/amp: output 0: unmuted, max volume */
700         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
701
702         /* c/lfe out pin: muted, (no volume selection)  */
703         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
704
705         /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
706         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
707
708
709         /* hphone/speaker input selector: front DAC */
710         {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
711
712         /* hphone/speaker out pin: muted, (no volume selection)  */
713         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
714
715         /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
716         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
717
718
719         { }
720 };
721
722 static int alc_init(struct hda_codec *codec)
723 {
724         struct alc_spec *spec = codec->spec;
725         snd_hda_sequence_write(codec, spec->init_verbs);
726         return 0;
727 }
728
729 #ifdef CONFIG_PM
730 /*
731  * resume
732  */
733 static int alc_resume(struct hda_codec *codec)
734 {
735         struct alc_spec *spec = codec->spec;
736         int i;
737
738         alc_init(codec);
739         for (i = 0; i < spec->num_mixers; i++) {
740                 snd_hda_resume_ctls(codec, spec->mixers[i]);
741         }
742         if (spec->multiout.dig_out_nid)
743                 snd_hda_resume_spdif_out(codec);
744         if (spec->dig_in_nid)
745                 snd_hda_resume_spdif_in(codec);
746
747         return 0;
748 }
749 #endif
750
751 /*
752  * Analog playback callbacks
753  */
754 static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
755                                     struct hda_codec *codec,
756                                     snd_pcm_substream_t *substream)
757 {
758         struct alc_spec *spec = codec->spec;
759         return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
760 }
761
762 static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
763                                        struct hda_codec *codec,
764                                        unsigned int stream_tag,
765                                        unsigned int format,
766                                        snd_pcm_substream_t *substream)
767 {
768         struct alc_spec *spec = codec->spec;
769         return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
770                                                 format, substream);
771 }
772
773 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
774                                        struct hda_codec *codec,
775                                        snd_pcm_substream_t *substream)
776 {
777         struct alc_spec *spec = codec->spec;
778         return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
779 }
780
781 /*
782  * Digital out
783  */
784 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
785                                         struct hda_codec *codec,
786                                         snd_pcm_substream_t *substream)
787 {
788         struct alc_spec *spec = codec->spec;
789         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
790 }
791
792 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
793                                          struct hda_codec *codec,
794                                          snd_pcm_substream_t *substream)
795 {
796         struct alc_spec *spec = codec->spec;
797         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
798 }
799
800 /*
801  * Analog capture
802  */
803 static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
804                                       struct hda_codec *codec,
805                                       unsigned int stream_tag,
806                                       unsigned int format,
807                                       snd_pcm_substream_t *substream)
808 {
809         struct alc_spec *spec = codec->spec;
810
811         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
812                                    stream_tag, 0, format);
813         return 0;
814 }
815
816 static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
817                                       struct hda_codec *codec,
818                                       snd_pcm_substream_t *substream)
819 {
820         struct alc_spec *spec = codec->spec;
821
822         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
823         return 0;
824 }
825
826
827 /*
828  */
829 static struct hda_pcm_stream alc880_pcm_analog_playback = {
830         .substreams = 1,
831         .channels_min = 2,
832         .channels_max = 8,
833         .nid = 0x02, /* NID to query formats and rates */
834         .ops = {
835                 .open = alc880_playback_pcm_open,
836                 .prepare = alc880_playback_pcm_prepare,
837                 .cleanup = alc880_playback_pcm_cleanup
838         },
839 };
840
841 static struct hda_pcm_stream alc880_pcm_analog_capture = {
842         .substreams = 2,
843         .channels_min = 2,
844         .channels_max = 2,
845         .nid = 0x07, /* NID to query formats and rates */
846         .ops = {
847                 .prepare = alc880_capture_pcm_prepare,
848                 .cleanup = alc880_capture_pcm_cleanup
849         },
850 };
851
852 static struct hda_pcm_stream alc880_pcm_digital_playback = {
853         .substreams = 1,
854         .channels_min = 2,
855         .channels_max = 2,
856         /* NID is set in alc_build_pcms */
857         .ops = {
858                 .open = alc880_dig_playback_pcm_open,
859                 .close = alc880_dig_playback_pcm_close
860         },
861 };
862
863 static struct hda_pcm_stream alc880_pcm_digital_capture = {
864         .substreams = 1,
865         .channels_min = 2,
866         .channels_max = 2,
867         /* NID is set in alc_build_pcms */
868 };
869
870 static int alc_build_pcms(struct hda_codec *codec)
871 {
872         struct alc_spec *spec = codec->spec;
873         struct hda_pcm *info = spec->pcm_rec;
874         int i;
875
876         codec->num_pcms = 1;
877         codec->pcm_info = info;
878
879         info->name = spec->stream_name_analog;
880         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
881         info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
882
883         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
884         for (i = 0; i < spec->num_channel_mode; i++) {
885                 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
886                     info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
887                 }
888         }
889
890         if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
891                 codec->num_pcms++;
892                 info++;
893                 info->name = spec->stream_name_digital;
894                 if (spec->multiout.dig_out_nid) {
895                         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
896                         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
897                 }
898                 if (spec->dig_in_nid) {
899                         info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
900                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
901                 }
902         }
903
904         return 0;
905 }
906
907 static void alc_free(struct hda_codec *codec)
908 {
909         kfree(codec->spec);
910 }
911
912 /*
913  */
914 static struct hda_codec_ops alc_patch_ops = {
915         .build_controls = alc_build_controls,
916         .build_pcms = alc_build_pcms,
917         .init = alc_init,
918         .free = alc_free,
919 #ifdef CONFIG_PM
920         .resume = alc_resume,
921 #endif
922 };
923
924 /*
925  */
926
927 static struct hda_board_config alc880_cfg_tbl[] = {
928         /* Back 3 jack, front 2 jack */
929         { .modelname = "3stack", .config = ALC880_3ST },
930         { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
931         { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
932         { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
933         { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
934         { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
935         { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
936         { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
937         { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
938         { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
939         { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
940         { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
941         { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
942         { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
943         { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
944         { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
945         { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
946         { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
947         { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
948         { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
949         { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST },
950         { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST },
951         { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST },
952         { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST },
953         { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST },
954         { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
955         { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
956         { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
957         { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
958         { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
959         { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
960         { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
961         { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
962
963         /* Back 3 jack, front 2 jack (Internal add Aux-In) */
964         { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
965
966         /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
967         { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
968         { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG },
969
970         /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
971         { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG },
972         { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG },
973         { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG },
974
975         /* Back 5 jack, front 2 jack */
976         { .modelname = "5stack", .config = ALC880_5ST },
977         { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST },
978         { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST },
979         { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST },
980         { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST },
981
982         /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
983         { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
984         { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG },
985         { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG },
986         { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG },
987         { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG },
988         { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG },
989         { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG },
990         { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
991         { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
992
993         { .modelname = "w810", .config = ALC880_W810 },
994         { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
995
996         {}
997 };
998
999 static int patch_alc880(struct hda_codec *codec)
1000 {
1001         struct alc_spec *spec;
1002         int board_config;
1003
1004         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1005         if (spec == NULL)
1006                 return -ENOMEM;
1007
1008         codec->spec = spec;
1009
1010         board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
1011         if (board_config < 0) {
1012                 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
1013                 board_config = ALC880_MINIMAL;
1014         }
1015
1016         switch (board_config) {
1017         case ALC880_W810:
1018                 spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
1019                 spec->num_mixers++;
1020                 break;
1021         case ALC880_5ST:
1022         case ALC880_5ST_DIG:
1023                 spec->mixers[spec->num_mixers] = alc880_five_stack_mixer;
1024                 spec->num_mixers++;
1025                 break;
1026         default:
1027                 spec->mixers[spec->num_mixers] = alc880_base_mixer;
1028                 spec->num_mixers++;
1029                 break;
1030         }
1031
1032         switch (board_config) {
1033         case ALC880_3ST_DIG:
1034         case ALC880_5ST_DIG:
1035         case ALC880_W810:
1036                 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
1037                 break;
1038         default:
1039                 break;
1040         }
1041
1042         switch (board_config) {
1043         case ALC880_3ST:
1044         case ALC880_3ST_DIG:
1045         case ALC880_5ST:
1046         case ALC880_5ST_DIG:
1047         case ALC880_W810:
1048                 spec->front_panel = 1;
1049                 break;
1050         default:
1051                 break;
1052         }
1053
1054         switch (board_config) {
1055         case ALC880_5ST:
1056         case ALC880_5ST_DIG:
1057                 spec->init_verbs = alc880_init_verbs_five_stack;
1058                 spec->channel_mode = alc880_fivestack_modes;
1059                 spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
1060                 break;
1061         case ALC880_W810:
1062                 spec->init_verbs = alc880_w810_init_verbs;
1063                 spec->channel_mode = alc880_w810_modes;
1064                 spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
1065                 break;
1066         default:
1067                 spec->init_verbs = alc880_init_verbs_three_stack;
1068                 spec->channel_mode = alc880_threestack_modes;
1069                 spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
1070                 break;
1071         }
1072
1073         spec->stream_name_analog = "ALC880 Analog";
1074         spec->stream_analog_playback = &alc880_pcm_analog_playback;
1075         spec->stream_analog_capture = &alc880_pcm_analog_capture;
1076
1077         spec->stream_name_digital = "ALC880 Digital";
1078         spec->stream_digital_playback = &alc880_pcm_digital_playback;
1079         spec->stream_digital_capture = &alc880_pcm_digital_capture;
1080
1081         spec->multiout.max_channels = spec->channel_mode[0].channels;
1082
1083         switch (board_config) {
1084         case ALC880_W810:
1085                 spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
1086                 spec->multiout.dac_nids = alc880_w810_dac_nids;
1087                 // No dedicated headphone socket - it's shared with built-in speakers.
1088                 break;
1089         default:
1090                 spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
1091                 spec->multiout.dac_nids = alc880_dac_nids;
1092                 spec->multiout.hp_nid = 0x03; /* rear-surround NID */
1093                 break;
1094         }
1095
1096         spec->input_mux = &alc880_capture_source;
1097         spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
1098         spec->adc_nids = alc880_adc_nids;
1099
1100         codec->patch_ops = alc_patch_ops;
1101
1102         return 0;
1103 }
1104
1105 /*
1106  * ALC260 support
1107  */
1108
1109 /*
1110  * This is just place-holder, so there's something for alc_build_pcms to look
1111  * at when it calculates the maximum number of channels. ALC260 has no mixer
1112  * element which allows changing the channel mode, so the verb list is
1113  * never used.
1114  */
1115 static struct alc_channel_mode alc260_modes[1] = {
1116         { 2, NULL },
1117 };
1118
1119 snd_kcontrol_new_t alc260_base_mixer[] = {
1120         HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
1121         /* use LINE2 for the output */
1122         /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */
1123         HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
1124         HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
1125         HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
1126         HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
1127         HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
1128         HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
1129         HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
1130         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
1131         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
1132         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
1133         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
1134         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
1135         HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1136         HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
1137         HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
1138         HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
1139         HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
1140         {
1141                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1142                 .name = "Capture Source",
1143                 .info = alc_mux_enum_info,
1144                 .get = alc_mux_enum_get,
1145                 .put = alc_mux_enum_put,
1146         },
1147         { } /* end */
1148 };
1149
1150 static struct hda_verb alc260_init_verbs[] = {
1151         /* Line In pin widget for input */
1152         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1153         /* CD pin widget for input */
1154         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1155         /* Mic1 (rear panel) pin widget for input and vref at 80% */
1156         {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1157         /* Mic2 (front panel) pin widget for input and vref at 80% */
1158         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1159         /* LINE-2 is used for line-out in rear */
1160         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1161         /* select line-out */
1162         {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
1163         /* LINE-OUT pin */
1164         {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1165         /* enable HP */
1166         {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1167         /* enable Mono */
1168         {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1169         /* unmute amp left and right */
1170         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1171         /* set connection select to line in (default select for this ADC) */
1172         {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
1173         /* unmute Line-Out mixer amp left and right (volume = 0) */
1174         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1175         /* mute pin widget amp left and right (no gain on this amp) */
1176         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1177         /* unmute HP mixer amp left and right (volume = 0) */
1178         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1179         /* mute pin widget amp left and right (no gain on this amp) */
1180         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1181         /* unmute Mono mixer amp left and right (volume = 0) */
1182         {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1183         /* mute pin widget amp left and right (no gain on this amp) */
1184         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1185         /* mute LINE-2 out */
1186         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
1187         /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
1188         /* unmute CD */
1189         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
1190         /* unmute Line In */
1191         {0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
1192         /* unmute Mic */
1193         {0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1194         /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
1195         /* Unmute Front out path */
1196         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1197         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1198         /* Unmute Headphone out path */
1199         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1200         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1201         /* Unmute Mono out path */
1202         {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1203         {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1204         { }
1205 };
1206
1207 static struct hda_pcm_stream alc260_pcm_analog_playback = {
1208         .substreams = 1,
1209         .channels_min = 2,
1210         .channels_max = 2,
1211         .nid = 0x2,
1212 };
1213
1214 static struct hda_pcm_stream alc260_pcm_analog_capture = {
1215         .substreams = 1,
1216         .channels_min = 2,
1217         .channels_max = 2,
1218         .nid = 0x4,
1219 };
1220
1221 static int patch_alc260(struct hda_codec *codec)
1222 {
1223         struct alc_spec *spec;
1224
1225         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1226         if (spec == NULL)
1227                 return -ENOMEM;
1228
1229         codec->spec = spec;
1230
1231         spec->mixers[spec->num_mixers] = alc260_base_mixer;
1232         spec->num_mixers++;
1233
1234         spec->init_verbs = alc260_init_verbs;
1235         spec->channel_mode = alc260_modes;
1236         spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
1237
1238         spec->stream_name_analog = "ALC260 Analog";
1239         spec->stream_analog_playback = &alc260_pcm_analog_playback;
1240         spec->stream_analog_capture = &alc260_pcm_analog_capture;
1241
1242         spec->multiout.max_channels = spec->channel_mode[0].channels;
1243         spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
1244         spec->multiout.dac_nids = alc260_dac_nids;
1245
1246         spec->input_mux = &alc260_capture_source;
1247         spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
1248         spec->adc_nids = alc260_adc_nids;
1249
1250         codec->patch_ops = alc_patch_ops;
1251
1252         return 0;
1253 }
1254
1255 /*
1256  * ALC882 support
1257  *
1258  * ALC882 is almost identical with ALC880 but has cleaner and more flexible
1259  * configuration.  Each pin widget can choose any input DACs and a mixer.
1260  * Each ADC is connected from a mixer of all inputs.  This makes possible
1261  * 6-channel independent captures.
1262  *
1263  * In addition, an independent DAC for the multi-playback (not used in this
1264  * driver yet).
1265  */
1266
1267 static struct alc_channel_mode alc882_ch_modes[1] = {
1268         { 8, NULL }
1269 };
1270
1271 static hda_nid_t alc882_dac_nids[4] = {
1272         /* front, rear, clfe, rear_surr */
1273         0x02, 0x03, 0x04, 0x05
1274 };
1275
1276 static hda_nid_t alc882_adc_nids[3] = {
1277         /* ADC0-2 */
1278         0x07, 0x08, 0x09,
1279 };
1280
1281 /* input MUX */
1282 /* FIXME: should be a matrix-type input source selection */
1283
1284 static struct hda_input_mux alc882_capture_source = {
1285         .num_items = 4,
1286         .items = {
1287                 { "Mic", 0x0 },
1288                 { "Front Mic", 0x1 },
1289                 { "Line", 0x2 },
1290                 { "CD", 0x4 },
1291         },
1292 };
1293
1294 #define alc882_mux_enum_info alc_mux_enum_info
1295 #define alc882_mux_enum_get alc_mux_enum_get
1296
1297 static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1298 {
1299         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1300         struct alc_spec *spec = codec->spec;
1301         const struct hda_input_mux *imux = spec->input_mux;
1302         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1303         static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
1304         hda_nid_t nid = capture_mixers[adc_idx];
1305         unsigned int *cur_val = &spec->cur_mux[adc_idx];
1306         unsigned int i, idx;
1307
1308         idx = ucontrol->value.enumerated.item[0];
1309         if (idx >= imux->num_items)
1310                 idx = imux->num_items - 1;
1311         if (*cur_val == idx && ! codec->in_resume)
1312                 return 0;
1313         for (i = 0; i < imux->num_items; i++) {
1314                 unsigned int v = (i == idx) ? 0x7000 : 0x7080;
1315                 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1316                                     v | (imux->items[i].index << 8));
1317         }
1318         *cur_val = idx;
1319         return 1;
1320 }
1321
1322 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
1323  *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
1324  */
1325 static snd_kcontrol_new_t alc882_base_mixer[] = {
1326         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1327         HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
1328         HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1329         HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
1330         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1331         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1332         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
1333         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
1334         HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1335         HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT),
1336         HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
1337         HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1338         HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1339         HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1340         HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1341         HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1342         HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1343         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1344         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1345         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1346         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1347         HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
1348         HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
1349         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
1350         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
1351         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
1352         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
1353         {
1354                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1355                 /* .name = "Capture Source", */
1356                 .name = "Input Source",
1357                 .count = 3,
1358                 .info = alc882_mux_enum_info,
1359                 .get = alc882_mux_enum_get,
1360                 .put = alc882_mux_enum_put,
1361         },
1362         { } /* end */
1363 };
1364
1365 static struct hda_verb alc882_init_verbs[] = {
1366         /* Front mixer: unmute input/output amp left and right (volume = 0) */
1367         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1368         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1369         /* Rear mixer */
1370         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1371         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1372         /* CLFE mixer */
1373         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1374         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1375         /* Side mixer */
1376         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
1377         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1378
1379         /* Front Pin: to output mode */
1380         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1381         /* Front Pin: mute amp left and right (no volume) */
1382         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1383         /* select Front mixer (0x0c, index 0) */
1384         {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
1385         /* Rear Pin */
1386         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1387         /* Rear Pin: mute amp left and right (no volume) */
1388         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1389         /* select Rear mixer (0x0d, index 1) */
1390         {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
1391         /* CLFE Pin */
1392         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1393         /* CLFE Pin: mute amp left and right (no volume) */
1394         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1395         /* select CLFE mixer (0x0e, index 2) */
1396         {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
1397         /* Side Pin */
1398         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1399         /* Side Pin: mute amp left and right (no volume) */
1400         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1401         /* select Side mixer (0x0f, index 3) */
1402         {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
1403         /* Headphone Pin */
1404         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1405         /* Headphone Pin: mute amp left and right (no volume) */
1406         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
1407         /* select Front mixer (0x0c, index 0) */
1408         {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
1409         /* Mic (rear) pin widget for input and vref at 80% */
1410         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1411         /* Front Mic pin widget for input and vref at 80% */
1412         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
1413         /* Line In pin widget for input */
1414         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1415         /* CD pin widget for input */
1416         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1417
1418         /* FIXME: use matrix-type input source selection */
1419         /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
1420         /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
1421         {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1422         {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
1423         {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
1424         {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
1425         /* Input mixer2 */
1426         {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1427         {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
1428         {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
1429         {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
1430         /* Input mixer3 */
1431         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1432         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
1433         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
1434         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
1435         /* ADC1: unmute amp left and right */
1436         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1437         /* ADC2: unmute amp left and right */
1438         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1439         /* ADC3: unmute amp left and right */
1440         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
1441
1442         /* Unmute front loopback */
1443         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1444         /* Unmute rear loopback */
1445         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1446         /* Mute CLFE loopback */
1447         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
1448         /* Unmute side loopback */
1449         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1450
1451         { }
1452 };
1453
1454 static int patch_alc882(struct hda_codec *codec)
1455 {
1456         struct alc_spec *spec;
1457
1458         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1459         if (spec == NULL)
1460                 return -ENOMEM;
1461
1462         codec->spec = spec;
1463
1464         spec->mixers[spec->num_mixers] = alc882_base_mixer;
1465         spec->num_mixers++;
1466
1467         spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
1468         spec->dig_in_nid = ALC880_DIGIN_NID;
1469         spec->front_panel = 1;
1470         spec->init_verbs = alc882_init_verbs;
1471         spec->channel_mode = alc882_ch_modes;
1472         spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
1473
1474         spec->stream_name_analog = "ALC882 Analog";
1475         spec->stream_analog_playback = &alc880_pcm_analog_playback;
1476         spec->stream_analog_capture = &alc880_pcm_analog_capture;
1477
1478         spec->stream_name_digital = "ALC882 Digital";
1479         spec->stream_digital_playback = &alc880_pcm_digital_playback;
1480         spec->stream_digital_capture = &alc880_pcm_digital_capture;
1481
1482         spec->multiout.max_channels = spec->channel_mode[0].channels;
1483         spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids);
1484         spec->multiout.dac_nids = alc882_dac_nids;
1485
1486         spec->input_mux = &alc882_capture_source;
1487         spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
1488         spec->adc_nids = alc882_adc_nids;
1489
1490         codec->patch_ops = alc_patch_ops;
1491
1492         return 0;
1493 }
1494
1495 /*
1496  * patch entries
1497  */
1498 struct hda_codec_preset snd_hda_preset_realtek[] = {
1499         { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
1500         { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
1501         { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
1502         {} /* terminator */
1503 };