[ALSA] sound/: possible cleanups
[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_3ST,
37         ALC880_3ST_DIG,
38         ALC880_5ST,
39         ALC880_5ST_DIG,
40         ALC880_W810,
41         ALC880_Z71V,
42         ALC880_AUTO,
43         ALC880_6ST,
44         ALC880_6ST_DIG,
45         ALC880_F1734,
46         ALC880_ASUS,
47         ALC880_ASUS_DIG,
48         ALC880_ASUS_W1V,
49         ALC880_UNIWILL_DIG,
50 #ifdef CONFIG_SND_DEBUG
51         ALC880_TEST,
52 #endif
53         ALC880_MODEL_LAST /* last tag */
54 };
55
56 /* ALC260 models */
57 enum {
58         ALC260_BASIC,
59         ALC260_HP,
60         ALC260_FUJITSU_S702x,
61         ALC260_MODEL_LAST /* last tag */
62 };
63
64 struct alc_spec {
65         /* codec parameterization */
66         struct snd_kcontrol_new *mixers[3];     /* mixer arrays */
67         unsigned int num_mixers;
68
69         const struct hda_verb *init_verbs[3];   /* initialization verbs
70                                                  * don't forget NULL termination!
71                                                  */
72         unsigned int num_init_verbs;
73
74         char *stream_name_analog;       /* analog PCM stream */
75         struct hda_pcm_stream *stream_analog_playback;
76         struct hda_pcm_stream *stream_analog_capture;
77
78         char *stream_name_digital;      /* digital PCM stream */ 
79         struct hda_pcm_stream *stream_digital_playback;
80         struct hda_pcm_stream *stream_digital_capture;
81
82         /* playback */
83         struct hda_multi_out multiout;  /* playback set-up
84                                          * max_channels, dacs must be set
85                                          * dig_out_nid and hp_nid are optional
86                                          */
87
88         /* capture */
89         unsigned int num_adc_nids;
90         hda_nid_t *adc_nids;
91         hda_nid_t dig_in_nid;           /* digital-in NID; optional */
92
93         /* capture source */
94         const struct hda_input_mux *input_mux;
95         unsigned int cur_mux[3];
96
97         /* channel model */
98         const struct hda_channel_mode *channel_mode;
99         int num_channel_mode;
100
101         /* PCM information */
102         struct hda_pcm pcm_rec[2];      /* used in alc_build_pcms() */
103
104         /* dynamic controls, init_verbs and input_mux */
105         struct auto_pin_cfg autocfg;
106         unsigned int num_kctl_alloc, num_kctl_used;
107         struct snd_kcontrol_new *kctl_alloc;
108         struct hda_input_mux private_imux;
109         hda_nid_t private_dac_nids[4];
110 };
111
112
113 /*
114  * input MUX handling
115  */
116 static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
117 {
118         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
119         struct alc_spec *spec = codec->spec;
120         return snd_hda_input_mux_info(spec->input_mux, uinfo);
121 }
122
123 static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
124 {
125         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
126         struct alc_spec *spec = codec->spec;
127         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
128
129         ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
130         return 0;
131 }
132
133 static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
134 {
135         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
136         struct alc_spec *spec = codec->spec;
137         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
138         return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
139                                      spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
140 }
141
142
143 /*
144  * channel mode setting
145  */
146 static int alc880_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
147 {
148         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
149         struct alc_spec *spec = codec->spec;
150         return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
151                                     spec->num_channel_mode);
152 }
153
154 static int alc880_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
155 {
156         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
157         struct alc_spec *spec = codec->spec;
158         return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
159                                    spec->num_channel_mode, spec->multiout.max_channels);
160 }
161
162 static int alc880_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
163 {
164         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
165         struct alc_spec *spec = codec->spec;
166         return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
167                                    spec->num_channel_mode, &spec->multiout.max_channels);
168 }
169
170
171 /*
172  * Control of pin widget settings via the mixer.  Only boolean settings are
173  * supported, so VrefEn can't be controlled using these functions as they
174  * stand.
175  */
176 static int alc_pinctl_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
177 {
178         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
179         uinfo->count = 1;
180         uinfo->value.integer.min = 0;
181         uinfo->value.integer.max = 1;
182         return 0;
183 }
184
185 static int alc_pinctl_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
186 {
187         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
188         hda_nid_t nid = kcontrol->private_value & 0xffff;
189         long mask = (kcontrol->private_value >> 16) & 0xff;
190         long *valp = ucontrol->value.integer.value;
191
192         *valp = 0;
193         if (snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00) & mask)
194                 *valp = 1;
195         return 0;
196 }
197
198 static int alc_pinctl_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
199 {
200         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
201         hda_nid_t nid = kcontrol->private_value & 0xffff;
202         long mask = (kcontrol->private_value >> 16) & 0xff;
203         long *valp = ucontrol->value.integer.value;
204         unsigned int pinctl = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_PIN_WIDGET_CONTROL,0x00);
205         int change = ((pinctl & mask)!=0) != *valp;
206
207         if (change)
208                 snd_hda_codec_write(codec,nid,0,AC_VERB_SET_PIN_WIDGET_CONTROL,
209                         *valp?(pinctl|mask):(pinctl&~mask));
210         return change;
211 }
212
213 #define ALC_PINCTL_SWITCH(xname, nid, mask) \
214         { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
215           .info = alc_pinctl_switch_info, \
216           .get = alc_pinctl_switch_get, \
217           .put = alc_pinctl_switch_put, \
218           .private_value = (nid) | (mask<<16) }
219
220 /*
221  * ALC880 3-stack model
222  *
223  * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
224  * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
225  *                 HP = 0x19
226  */
227
228 static hda_nid_t alc880_dac_nids[4] = {
229         /* front, rear, clfe, rear_surr */
230         0x02, 0x05, 0x04, 0x03
231 };
232
233 static hda_nid_t alc880_adc_nids[3] = {
234         /* ADC0-2 */
235         0x07, 0x08, 0x09,
236 };
237
238 /* The datasheet says the node 0x07 is connected from inputs,
239  * but it shows zero connection in the real implementation on some devices.
240  */
241 static hda_nid_t alc880_adc_nids_alt[2] = {
242         /* ADC1-2 */
243         0x08, 0x09,
244 };
245
246 #define ALC880_DIGOUT_NID       0x06
247 #define ALC880_DIGIN_NID        0x0a
248
249 static struct hda_input_mux alc880_capture_source = {
250         .num_items = 4,
251         .items = {
252                 { "Mic", 0x0 },
253                 { "Front Mic", 0x3 },
254                 { "Line", 0x2 },
255                 { "CD", 0x4 },
256         },
257 };
258
259 /* channel source setting (2/6 channel selection for 3-stack) */
260 /* 2ch mode */
261 static struct hda_verb alc880_threestack_ch2_init[] = {
262         /* set line-in to input, mute it */
263         { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
264         { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
265         /* set mic-in to input vref 80%, mute it */
266         { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
267         { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
268         { } /* end */
269 };
270
271 /* 6ch mode */
272 static struct hda_verb alc880_threestack_ch6_init[] = {
273         /* set line-in to output, unmute it */
274         { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
275         { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
276         /* set mic-in to output, unmute it */
277         { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
278         { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
279         { } /* end */
280 };
281
282 static struct hda_channel_mode alc880_threestack_modes[2] = {
283         { 2, alc880_threestack_ch2_init },
284         { 6, alc880_threestack_ch6_init },
285 };
286
287 static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
288         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
289         HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
290         HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
291         HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
292         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
293         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
294         HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
295         HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
296         HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
297         HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
298         HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
299         HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
300         HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
301         HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
302         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
303         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
304         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
305         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
306         HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
307         {
308                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
309                 .name = "Channel Mode",
310                 .info = alc880_ch_mode_info,
311                 .get = alc880_ch_mode_get,
312                 .put = alc880_ch_mode_put,
313         },
314         { } /* end */
315 };
316
317 /* capture mixer elements */
318 static struct snd_kcontrol_new alc880_capture_mixer[] = {
319         HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
320         HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
321         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
322         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
323         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
324         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
325         {
326                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
327                 /* The multiple "Capture Source" controls confuse alsamixer
328                  * So call somewhat different..
329                  * FIXME: the controls appear in the "playback" view!
330                  */
331                 /* .name = "Capture Source", */
332                 .name = "Input Source",
333                 .count = 3,
334                 .info = alc_mux_enum_info,
335                 .get = alc_mux_enum_get,
336                 .put = alc_mux_enum_put,
337         },
338         { } /* end */
339 };
340
341 /* capture mixer elements (in case NID 0x07 not available) */
342 static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {
343         HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
344         HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
345         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
346         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
347         {
348                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
349                 /* The multiple "Capture Source" controls confuse alsamixer
350                  * So call somewhat different..
351                  * FIXME: the controls appear in the "playback" view!
352                  */
353                 /* .name = "Capture Source", */
354                 .name = "Input Source",
355                 .count = 2,
356                 .info = alc_mux_enum_info,
357                 .get = alc_mux_enum_get,
358                 .put = alc_mux_enum_put,
359         },
360         { } /* end */
361 };
362
363
364
365 /*
366  * ALC880 5-stack model
367  *
368  * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
369  * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
370  *                 Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
371  */
372
373 /* additional mixers to alc880_three_stack_mixer */
374 static struct snd_kcontrol_new alc880_five_stack_mixer[] = {
375         HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
376         HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
377         { } /* end */
378 };
379
380 /* channel source setting (6/8 channel selection for 5-stack) */
381 /* 6ch mode */
382 static struct hda_verb alc880_fivestack_ch6_init[] = {
383         /* set line-in to input, mute it */
384         { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
385         { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
386         { } /* end */
387 };
388
389 /* 8ch mode */
390 static struct hda_verb alc880_fivestack_ch8_init[] = {
391         /* set line-in to output, unmute it */
392         { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
393         { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
394         { } /* end */
395 };
396
397 static struct hda_channel_mode alc880_fivestack_modes[2] = {
398         { 6, alc880_fivestack_ch6_init },
399         { 8, alc880_fivestack_ch8_init },
400 };
401
402
403 /*
404  * ALC880 6-stack model
405  *
406  * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
407  * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
408  *   Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
409  */
410
411 static hda_nid_t alc880_6st_dac_nids[4] = {
412         /* front, rear, clfe, rear_surr */
413         0x02, 0x03, 0x04, 0x05
414 };      
415
416 static struct hda_input_mux alc880_6stack_capture_source = {
417         .num_items = 4,
418         .items = {
419                 { "Mic", 0x0 },
420                 { "Front Mic", 0x1 },
421                 { "Line", 0x2 },
422                 { "CD", 0x4 },
423         },
424 };
425
426 /* fixed 8-channels */
427 static struct hda_channel_mode alc880_sixstack_modes[1] = {
428         { 8, NULL },
429 };
430
431 static struct snd_kcontrol_new alc880_six_stack_mixer[] = {
432         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
433         HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
434         HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
435         HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
436         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
437         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
438         HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
439         HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
440         HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
441         HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
442         HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
443         HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
444         HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
445         HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
446         HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
447         HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
448         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
449         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
450         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
451         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
452         {
453                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
454                 .name = "Channel Mode",
455                 .info = alc880_ch_mode_info,
456                 .get = alc880_ch_mode_get,
457                 .put = alc880_ch_mode_put,
458         },
459         { } /* end */
460 };
461
462
463 /*
464  * ALC880 W810 model
465  *
466  * W810 has rear IO for:
467  * Front (DAC 02)
468  * Surround (DAC 03)
469  * Center/LFE (DAC 04)
470  * Digital out (06)
471  *
472  * The system also has a pair of internal speakers, and a headphone jack.
473  * These are both connected to Line2 on the codec, hence to DAC 02.
474  * 
475  * There is a variable resistor to control the speaker or headphone
476  * volume. This is a hardware-only device without a software API.
477  *
478  * Plugging headphones in will disable the internal speakers. This is
479  * implemented in hardware, not via the driver using jack sense. In
480  * a similar fashion, plugging into the rear socket marked "front" will
481  * disable both the speakers and headphones.
482  *
483  * For input, there's a microphone jack, and an "audio in" jack.
484  * These may not do anything useful with this driver yet, because I
485  * haven't setup any initialization verbs for these yet...
486  */
487
488 static hda_nid_t alc880_w810_dac_nids[3] = {
489         /* front, rear/surround, clfe */
490         0x02, 0x03, 0x04
491 };
492
493 /* fixed 6 channels */
494 static struct hda_channel_mode alc880_w810_modes[1] = {
495         { 6, NULL }
496 };
497
498 /* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
499 static struct snd_kcontrol_new alc880_w810_base_mixer[] = {
500         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
501         HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
502         HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
503         HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
504         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
505         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
506         HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
507         HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
508         HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
509         { } /* end */
510 };
511
512
513 /*
514  * Z710V model
515  *
516  * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
517  * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
518  */
519
520 static hda_nid_t alc880_z71v_dac_nids[1] = {
521         0x02
522 };
523 #define ALC880_Z71V_HP_DAC      0x03
524
525 /* fixed 2 channels */
526 static struct hda_channel_mode alc880_2_jack_modes[1] = {
527         { 2, NULL }
528 };
529
530 static struct snd_kcontrol_new alc880_z71v_mixer[] = {
531         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
532         HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
533         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
534         HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
535         HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
536         HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
537         HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
538         HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
539         { } /* end */
540 };
541
542
543 /* FIXME! */
544 /*
545  * ALC880 F1734 model
546  *
547  * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
548  * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
549  */
550
551 static hda_nid_t alc880_f1734_dac_nids[1] = {
552         0x03
553 };
554 #define ALC880_F1734_HP_DAC     0x02
555
556 static struct snd_kcontrol_new alc880_f1734_mixer[] = {
557         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
558         HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
559         HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
560         HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
561         HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
562         HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
563         HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
564         HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
565         { } /* end */
566 };
567
568
569 /* FIXME! */
570 /*
571  * ALC880 ASUS model
572  *
573  * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
574  * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
575  *  Mic = 0x18, Line = 0x1a
576  */
577
578 #define alc880_asus_dac_nids    alc880_w810_dac_nids    /* identical with w810 */
579 #define alc880_asus_modes       alc880_threestack_modes /* 2/6 channel mode */
580
581 static struct snd_kcontrol_new alc880_asus_mixer[] = {
582         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
583         HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
584         HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
585         HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
586         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
587         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
588         HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
589         HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
590         HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
591         HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
592         HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
593         HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
594         HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
595         HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
596         {
597                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
598                 .name = "Channel Mode",
599                 .info = alc880_ch_mode_info,
600                 .get = alc880_ch_mode_get,
601                 .put = alc880_ch_mode_put,
602         },
603         { } /* end */
604 };
605
606 /* FIXME! */
607 /*
608  * ALC880 ASUS W1V model
609  *
610  * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
611  * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
612  *  Mic = 0x18, Line = 0x1a, Line2 = 0x1b
613  */
614
615 /* additional mixers to alc880_asus_mixer */
616 static struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
617         HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
618         HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
619         { } /* end */
620 };
621
622 /* additional mixers to alc880_asus_mixer */
623 static struct snd_kcontrol_new alc880_pcbeep_mixer[] = {
624         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
625         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
626         { } /* end */
627 };
628
629 /*
630  * build control elements
631  */
632 static int alc_build_controls(struct hda_codec *codec)
633 {
634         struct alc_spec *spec = codec->spec;
635         int err;
636         int i;
637
638         for (i = 0; i < spec->num_mixers; i++) {
639                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
640                 if (err < 0)
641                         return err;
642         }
643
644         if (spec->multiout.dig_out_nid) {
645                 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
646                 if (err < 0)
647                         return err;
648         }
649         if (spec->dig_in_nid) {
650                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
651                 if (err < 0)
652                         return err;
653         }
654         return 0;
655 }
656
657
658 /*
659  * initialize the codec volumes, etc
660  */
661
662 /*
663  * generic initialization of ADC, input mixers and output mixers
664  */
665 static struct hda_verb alc880_volume_init_verbs[] = {
666         /*
667          * Unmute ADC0-2 and set the default input to mic-in
668          */
669         {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
670         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
671         {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
672         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
673         {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
674         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
675
676         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
677          * mixer widget
678          * Note: PASD motherboards uses the Line In 2 as the input for front panel
679          * mic (mic 2)
680          */
681         /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
682         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
683         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
684         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
685         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
686         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
687
688         /*
689          * Set up output mixers (0x0c - 0x0f)
690          */
691         /* set vol=0 to output mixers */
692         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
693         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
694         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
695         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
696         /* set up input amps for analog loopback */
697         /* Amp Indices: DAC = 0, mixer = 1 */
698         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
699         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
700         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
701         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
702         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
703         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
704         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
705         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
706
707         { }
708 };
709
710 /*
711  * 3-stack pin configuration:
712  * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
713  */
714 static struct hda_verb alc880_pin_3stack_init_verbs[] = {
715         /*
716          * preset connection lists of input pins
717          * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
718          */
719         {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
720         {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
721         {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
722
723         /*
724          * Set pin mode and muting
725          */
726         /* set front pin widgets 0x14 for output */
727         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
728         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
729         /* Mic1 (rear panel) pin widget for input and vref at 80% */
730         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
731         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
732         /* Mic2 (as headphone out) for HP output */
733         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
734         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
735         /* Line In pin widget for input */
736         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
737         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
738         /* Line2 (as front mic) pin widget for input and vref at 80% */
739         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
740         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
741         /* CD pin widget for input */
742         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
743
744         { }
745 };
746
747 /*
748  * 5-stack pin configuration:
749  * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
750  * line-in/side = 0x1a, f-mic = 0x1b
751  */
752 static struct hda_verb alc880_pin_5stack_init_verbs[] = {
753         /*
754          * preset connection lists of input pins
755          * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
756          */
757         {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
758         {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
759
760         /*
761          * Set pin mode and muting
762          */
763         /* set pin widgets 0x14-0x17 for output */
764         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
765         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
766         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
767         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
768         /* unmute pins for output (no gain on this amp) */
769         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
770         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
771         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
772         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
773
774         /* Mic1 (rear panel) pin widget for input and vref at 80% */
775         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
776         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
777         /* Mic2 (as headphone out) for HP output */
778         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
779         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
780         /* Line In pin widget for input */
781         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
782         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
783         /* Line2 (as front mic) pin widget for input and vref at 80% */
784         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
785         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
786         /* CD pin widget for input */
787         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
788
789         { }
790 };
791
792 /*
793  * W810 pin configuration:
794  * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
795  */
796 static struct hda_verb alc880_pin_w810_init_verbs[] = {
797         /* hphone/speaker input selector: front DAC */
798         {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
799
800         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
801         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
802         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
803         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
804         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
805         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
806
807         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
808         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
809
810         { }
811 };
812
813 /*
814  * Z71V pin configuration:
815  * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
816  */
817 static struct hda_verb alc880_pin_z71v_init_verbs[] = {
818         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
819         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
820         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
821         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
822
823         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
824         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
825         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
826         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
827
828         { }
829 };
830
831 /*
832  * 6-stack pin configuration:
833  * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
834  * line = 0x1a, HP = 0x1b
835  */
836 static struct hda_verb alc880_pin_6stack_init_verbs[] = {
837         {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
838
839         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
840         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
841         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
842         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
843         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
844         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
845         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
846         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
847
848         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
849         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
850         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
851         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
852         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
853         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
854         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
855         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
856         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
857         
858         { }
859 };
860
861 /* FIXME! */
862 /*
863  * F1734 pin configuration:
864  * HP = 0x14, speaker-out = 0x15, mic = 0x18
865  */
866 static struct hda_verb alc880_pin_f1734_init_verbs[] = {
867         {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
868         {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
869         {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
870         {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
871
872         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
873         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
874         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
875         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
876
877         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
878         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
879         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
880         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
881         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
882         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
883         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
884         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
885         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
886
887         { }
888 };
889
890 /* FIXME! */
891 /*
892  * ASUS pin configuration:
893  * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
894  */
895 static struct hda_verb alc880_pin_asus_init_verbs[] = {
896         {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
897         {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
898         {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
899         {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
900
901         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
902         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
903         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
904         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
905         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
906         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
907         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
908         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
909
910         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
911         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
912         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
913         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
914         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
915         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
916         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
917         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
918         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
919         
920         { }
921 };
922
923 /* Enable GPIO mask and set output */
924 static struct hda_verb alc880_gpio1_init_verbs[] = {
925         {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
926         {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
927         {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
928 };
929
930 /* Enable GPIO mask and set output */
931 static struct hda_verb alc880_gpio2_init_verbs[] = {
932         {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
933         {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
934         {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
935 };
936
937
938 /*
939  */
940
941 static int alc_init(struct hda_codec *codec)
942 {
943         struct alc_spec *spec = codec->spec;
944         unsigned int i;
945
946         for (i = 0; i < spec->num_init_verbs; i++)
947                 snd_hda_sequence_write(codec, spec->init_verbs[i]);
948         return 0;
949 }
950
951 #ifdef CONFIG_PM
952 /*
953  * resume
954  */
955 static int alc_resume(struct hda_codec *codec)
956 {
957         struct alc_spec *spec = codec->spec;
958         int i;
959
960         alc_init(codec);
961         for (i = 0; i < spec->num_mixers; i++)
962                 snd_hda_resume_ctls(codec, spec->mixers[i]);
963         if (spec->multiout.dig_out_nid)
964                 snd_hda_resume_spdif_out(codec);
965         if (spec->dig_in_nid)
966                 snd_hda_resume_spdif_in(codec);
967
968         return 0;
969 }
970 #endif
971
972 /*
973  * Analog playback callbacks
974  */
975 static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
976                                     struct hda_codec *codec,
977                                     struct snd_pcm_substream *substream)
978 {
979         struct alc_spec *spec = codec->spec;
980         return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
981 }
982
983 static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
984                                        struct hda_codec *codec,
985                                        unsigned int stream_tag,
986                                        unsigned int format,
987                                        struct snd_pcm_substream *substream)
988 {
989         struct alc_spec *spec = codec->spec;
990         return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
991                                                 format, substream);
992 }
993
994 static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
995                                        struct hda_codec *codec,
996                                        struct snd_pcm_substream *substream)
997 {
998         struct alc_spec *spec = codec->spec;
999         return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
1000 }
1001
1002 /*
1003  * Digital out
1004  */
1005 static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
1006                                         struct hda_codec *codec,
1007                                         struct snd_pcm_substream *substream)
1008 {
1009         struct alc_spec *spec = codec->spec;
1010         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
1011 }
1012
1013 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
1014                                          struct hda_codec *codec,
1015                                          struct snd_pcm_substream *substream)
1016 {
1017         struct alc_spec *spec = codec->spec;
1018         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
1019 }
1020
1021 /*
1022  * Analog capture
1023  */
1024 static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
1025                                       struct hda_codec *codec,
1026                                       unsigned int stream_tag,
1027                                       unsigned int format,
1028                                       struct snd_pcm_substream *substream)
1029 {
1030         struct alc_spec *spec = codec->spec;
1031
1032         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
1033                                    stream_tag, 0, format);
1034         return 0;
1035 }
1036
1037 static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
1038                                       struct hda_codec *codec,
1039                                       struct snd_pcm_substream *substream)
1040 {
1041         struct alc_spec *spec = codec->spec;
1042
1043         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
1044         return 0;
1045 }
1046
1047
1048 /*
1049  */
1050 static struct hda_pcm_stream alc880_pcm_analog_playback = {
1051         .substreams = 1,
1052         .channels_min = 2,
1053         .channels_max = 8,
1054         /* NID is set in alc_build_pcms */
1055         .ops = {
1056                 .open = alc880_playback_pcm_open,
1057                 .prepare = alc880_playback_pcm_prepare,
1058                 .cleanup = alc880_playback_pcm_cleanup
1059         },
1060 };
1061
1062 static struct hda_pcm_stream alc880_pcm_analog_capture = {
1063         .substreams = 2,
1064         .channels_min = 2,
1065         .channels_max = 2,
1066         /* NID is set in alc_build_pcms */
1067         .ops = {
1068                 .prepare = alc880_capture_pcm_prepare,
1069                 .cleanup = alc880_capture_pcm_cleanup
1070         },
1071 };
1072
1073 static struct hda_pcm_stream alc880_pcm_digital_playback = {
1074         .substreams = 1,
1075         .channels_min = 2,
1076         .channels_max = 2,
1077         /* NID is set in alc_build_pcms */
1078         .ops = {
1079                 .open = alc880_dig_playback_pcm_open,
1080                 .close = alc880_dig_playback_pcm_close
1081         },
1082 };
1083
1084 static struct hda_pcm_stream alc880_pcm_digital_capture = {
1085         .substreams = 1,
1086         .channels_min = 2,
1087         .channels_max = 2,
1088         /* NID is set in alc_build_pcms */
1089 };
1090
1091 static int alc_build_pcms(struct hda_codec *codec)
1092 {
1093         struct alc_spec *spec = codec->spec;
1094         struct hda_pcm *info = spec->pcm_rec;
1095         int i;
1096
1097         codec->num_pcms = 1;
1098         codec->pcm_info = info;
1099
1100         info->name = spec->stream_name_analog;
1101         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
1102         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
1103         info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
1104         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
1105
1106         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
1107         for (i = 0; i < spec->num_channel_mode; i++) {
1108                 if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
1109                     info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
1110                 }
1111         }
1112
1113         if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
1114                 codec->num_pcms++;
1115                 info++;
1116                 info->name = spec->stream_name_digital;
1117                 if (spec->multiout.dig_out_nid) {
1118                         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
1119                         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
1120                 }
1121                 if (spec->dig_in_nid) {
1122                         info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
1123                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
1124                 }
1125         }
1126
1127         return 0;
1128 }
1129
1130 static void alc_free(struct hda_codec *codec)
1131 {
1132         struct alc_spec *spec = codec->spec;
1133         unsigned int i;
1134
1135         if (! spec)
1136                 return;
1137
1138         if (spec->kctl_alloc) {
1139                 for (i = 0; i < spec->num_kctl_used; i++)
1140                         kfree(spec->kctl_alloc[i].name);
1141                 kfree(spec->kctl_alloc);
1142         }
1143         kfree(spec);
1144 }
1145
1146 /*
1147  */
1148 static struct hda_codec_ops alc_patch_ops = {
1149         .build_controls = alc_build_controls,
1150         .build_pcms = alc_build_pcms,
1151         .init = alc_init,
1152         .free = alc_free,
1153 #ifdef CONFIG_PM
1154         .resume = alc_resume,
1155 #endif
1156 };
1157
1158
1159 /*
1160  * Test configuration for debugging
1161  *
1162  * Almost all inputs/outputs are enabled.  I/O pins can be configured via
1163  * enum controls.
1164  */
1165 #ifdef CONFIG_SND_DEBUG
1166 static hda_nid_t alc880_test_dac_nids[4] = {
1167         0x02, 0x03, 0x04, 0x05
1168 };
1169
1170 static struct hda_input_mux alc880_test_capture_source = {
1171         .num_items = 5,
1172         .items = {
1173                 { "In-1", 0x0 },
1174                 { "In-2", 0x1 },
1175                 { "In-3", 0x2 },
1176                 { "In-4", 0x3 },
1177                 { "CD", 0x4 },
1178         },
1179 };
1180
1181 static struct hda_channel_mode alc880_test_modes[4] = {
1182         { 2, NULL },
1183         { 4, NULL },
1184         { 6, NULL },
1185         { 8, NULL },
1186 };
1187
1188 static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1189 {
1190         static char *texts[] = {
1191                 "N/A", "Line Out", "HP Out",
1192                 "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
1193         };
1194         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1195         uinfo->count = 1;
1196         uinfo->value.enumerated.items = 8;
1197         if (uinfo->value.enumerated.item >= 8)
1198                 uinfo->value.enumerated.item = 7;
1199         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1200         return 0;
1201 }
1202
1203 static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1204 {
1205         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1206         hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1207         unsigned int pin_ctl, item = 0;
1208
1209         pin_ctl = snd_hda_codec_read(codec, nid, 0,
1210                                      AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1211         if (pin_ctl & AC_PINCTL_OUT_EN) {
1212                 if (pin_ctl & AC_PINCTL_HP_EN)
1213                         item = 2;
1214                 else
1215                         item = 1;
1216         } else if (pin_ctl & AC_PINCTL_IN_EN) {
1217                 switch (pin_ctl & AC_PINCTL_VREFEN) {
1218                 case AC_PINCTL_VREF_HIZ: item = 3; break;
1219                 case AC_PINCTL_VREF_50:  item = 4; break;
1220                 case AC_PINCTL_VREF_GRD: item = 5; break;
1221                 case AC_PINCTL_VREF_80:  item = 6; break;
1222                 case AC_PINCTL_VREF_100: item = 7; break;
1223                 }
1224         }
1225         ucontrol->value.enumerated.item[0] = item;
1226         return 0;
1227 }
1228
1229 static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1230 {
1231         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1232         hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1233         static unsigned int ctls[] = {
1234                 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
1235                 AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
1236                 AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
1237                 AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
1238                 AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
1239                 AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
1240         };
1241         unsigned int old_ctl, new_ctl;
1242
1243         old_ctl = snd_hda_codec_read(codec, nid, 0,
1244                                      AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1245         new_ctl = ctls[ucontrol->value.enumerated.item[0]];
1246         if (old_ctl != new_ctl) {
1247                 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
1248                 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1249                                     ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000);
1250                 return 1;
1251         }
1252         return 0;
1253 }
1254
1255 static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1256 {
1257         static char *texts[] = {
1258                 "Front", "Surround", "CLFE", "Side"
1259         };
1260         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1261         uinfo->count = 1;
1262         uinfo->value.enumerated.items = 4;
1263         if (uinfo->value.enumerated.item >= 4)
1264                 uinfo->value.enumerated.item = 3;
1265         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1266         return 0;
1267 }
1268
1269 static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1270 {
1271         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1272         hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1273         unsigned int sel;
1274
1275         sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
1276         ucontrol->value.enumerated.item[0] = sel & 3;
1277         return 0;
1278 }
1279
1280 static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1281 {
1282         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1283         hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
1284         unsigned int sel;
1285
1286         sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
1287         if (ucontrol->value.enumerated.item[0] != sel) {
1288                 sel = ucontrol->value.enumerated.item[0] & 3;
1289                 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
1290                 return 1;
1291         }
1292         return 0;
1293 }
1294
1295 #define PIN_CTL_TEST(xname,nid) {                       \
1296                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    \
1297                         .name = xname,                 \
1298                         .info = alc_test_pin_ctl_info, \
1299                         .get = alc_test_pin_ctl_get,   \
1300                         .put = alc_test_pin_ctl_put,   \
1301                         .private_value = nid           \
1302                         }
1303
1304 #define PIN_SRC_TEST(xname,nid) {                       \
1305                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,    \
1306                         .name = xname,                 \
1307                         .info = alc_test_pin_src_info, \
1308                         .get = alc_test_pin_src_get,   \
1309                         .put = alc_test_pin_src_put,   \
1310                         .private_value = nid           \
1311                         }
1312
1313 static struct snd_kcontrol_new alc880_test_mixer[] = {
1314         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1315         HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1316         HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
1317         HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
1318         HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
1319         HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
1320         HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
1321         HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
1322         PIN_CTL_TEST("Front Pin Mode", 0x14),
1323         PIN_CTL_TEST("Surround Pin Mode", 0x15),
1324         PIN_CTL_TEST("CLFE Pin Mode", 0x16),
1325         PIN_CTL_TEST("Side Pin Mode", 0x17),
1326         PIN_CTL_TEST("In-1 Pin Mode", 0x18),
1327         PIN_CTL_TEST("In-2 Pin Mode", 0x19),
1328         PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
1329         PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
1330         PIN_SRC_TEST("In-1 Pin Source", 0x18),
1331         PIN_SRC_TEST("In-2 Pin Source", 0x19),
1332         PIN_SRC_TEST("In-3 Pin Source", 0x1a),
1333         PIN_SRC_TEST("In-4 Pin Source", 0x1b),
1334         HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
1335         HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
1336         HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
1337         HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
1338         HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
1339         HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
1340         HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
1341         HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
1342         HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
1343         HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
1344         {
1345                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1346                 .name = "Channel Mode",
1347                 .info = alc880_ch_mode_info,
1348                 .get = alc880_ch_mode_get,
1349                 .put = alc880_ch_mode_put,
1350         },
1351         { } /* end */
1352 };
1353
1354 static struct hda_verb alc880_test_init_verbs[] = {
1355         /* Unmute inputs of 0x0c - 0x0f */
1356         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1357         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1358         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1359         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1360         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1361         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1362         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1363         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1364         /* Vol output for 0x0c-0x0f */
1365         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1366         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1367         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1368         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1369         /* Set output pins 0x14-0x17 */
1370         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1371         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1372         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1373         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1374         /* Unmute output pins 0x14-0x17 */
1375         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1376         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1377         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1378         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1379         /* Set input pins 0x18-0x1c */
1380         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1381         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1382         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1383         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1384         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1385         /* Mute input pins 0x18-0x1b */
1386         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1387         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1388         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1389         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1390         /* ADC set up */
1391         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1392         {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
1393         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1394         {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
1395         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1396         {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
1397         /* Analog input/passthru */
1398         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1399         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1400         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1401         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1402         {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1403         { }
1404 };
1405 #endif
1406
1407 /*
1408  */
1409
1410 static struct hda_board_config alc880_cfg_tbl[] = {
1411         /* Back 3 jack, front 2 jack */
1412         { .modelname = "3stack", .config = ALC880_3ST },
1413         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST },
1414         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST },
1415         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST },
1416         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST },
1417         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST },
1418         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST },
1419         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST },
1420         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST },
1421         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST },
1422         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST },
1423         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST },
1424         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST },
1425         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST },
1426         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST },
1427         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST },
1428         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST },
1429         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST },
1430         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST },
1431         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
1432         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
1433         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
1434         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
1435         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
1436         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
1437         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
1438         { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
1439         { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
1440         { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
1441         { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
1442         { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
1443         { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
1444         { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
1445
1446         /* Back 3 jack, front 2 jack (Internal add Aux-In) */
1447         { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
1448         { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST }, 
1449         { .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST },
1450
1451         /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
1452         { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
1453         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
1454         { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG },
1455
1456         /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
1457         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
1458         { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
1459         { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
1460
1461         /* Back 5 jack, front 2 jack */
1462         { .modelname = "5stack", .config = ALC880_5ST },
1463         { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
1464         { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
1465         { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
1466         { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
1467         { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
1468
1469         /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
1470         { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
1471         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
1472         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
1473         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
1474         { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
1475         { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
1476         { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
1477         { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
1478         { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
1479         { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
1480         /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */
1481         { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
1482         /* note subvendor = 0 below */
1483         /* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */
1484
1485         { .modelname = "w810", .config = ALC880_W810 },
1486         { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
1487
1488         { .modelname = "z71v", .config = ALC880_Z71V },
1489         { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
1490
1491         { .modelname = "6stack", .config = ALC880_6ST },
1492         { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
1493
1494         { .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
1495         { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
1496         { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
1497         { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
1498         { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
1499
1500         { .modelname = "asus", .config = ALC880_ASUS },
1501         { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
1502         { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
1503         { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
1504         { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
1505         { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG },
1506         { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
1507         { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
1508         { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
1509         { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
1510         { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
1511         { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
1512
1513         { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
1514         { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },     
1515
1516         { .modelname = "F1734", .config = ALC880_F1734 },
1517         { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
1518
1519 #ifdef CONFIG_SND_DEBUG
1520         { .modelname = "test", .config = ALC880_TEST },
1521 #endif
1522
1523         {}
1524 };
1525
1526 /*
1527  * configuration template - to be copied to the spec instance
1528  */
1529 struct alc_config_preset {
1530         struct snd_kcontrol_new *mixers[4];
1531         const struct hda_verb *init_verbs[4];
1532         unsigned int num_dacs;
1533         hda_nid_t *dac_nids;
1534         hda_nid_t dig_out_nid;          /* optional */
1535         hda_nid_t hp_nid;               /* optional */
1536         unsigned int num_adc_nids;
1537         hda_nid_t *adc_nids;
1538         unsigned int num_channel_mode;
1539         const struct hda_channel_mode *channel_mode;
1540         const struct hda_input_mux *input_mux;
1541 };
1542
1543 static struct alc_config_preset alc880_presets[] = {
1544         [ALC880_3ST] = {
1545                 .mixers = { alc880_three_stack_mixer },
1546                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
1547                 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1548                 .dac_nids = alc880_dac_nids,
1549                 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1550                 .channel_mode = alc880_threestack_modes,
1551                 .input_mux = &alc880_capture_source,
1552         },
1553         [ALC880_3ST_DIG] = {
1554                 .mixers = { alc880_three_stack_mixer },
1555                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
1556                 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1557                 .dac_nids = alc880_dac_nids,
1558                 .dig_out_nid = ALC880_DIGOUT_NID,
1559                 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
1560                 .channel_mode = alc880_threestack_modes,
1561                 .input_mux = &alc880_capture_source,
1562         },
1563         [ALC880_5ST] = {
1564                 .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
1565                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
1566                 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1567                 .dac_nids = alc880_dac_nids,
1568                 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
1569                 .channel_mode = alc880_fivestack_modes,
1570                 .input_mux = &alc880_capture_source,
1571         },
1572         [ALC880_5ST_DIG] = {
1573                 .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
1574                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
1575                 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
1576                 .dac_nids = alc880_dac_nids,
1577                 .dig_out_nid = ALC880_DIGOUT_NID,
1578                 .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
1579                 .channel_mode = alc880_fivestack_modes,
1580                 .input_mux = &alc880_capture_source,
1581         },
1582         [ALC880_6ST] = {
1583                 .mixers = { alc880_six_stack_mixer },
1584                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
1585                 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
1586                 .dac_nids = alc880_6st_dac_nids,
1587                 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
1588                 .channel_mode = alc880_sixstack_modes,
1589                 .input_mux = &alc880_6stack_capture_source,
1590         },
1591         [ALC880_6ST_DIG] = {
1592                 .mixers = { alc880_six_stack_mixer },
1593                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
1594                 .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
1595                 .dac_nids = alc880_6st_dac_nids,
1596                 .dig_out_nid = ALC880_DIGOUT_NID,
1597                 .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
1598                 .channel_mode = alc880_sixstack_modes,
1599                 .input_mux = &alc880_6stack_capture_source,
1600         },
1601         [ALC880_W810] = {
1602                 .mixers = { alc880_w810_base_mixer },
1603                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs,
1604                                 alc880_gpio2_init_verbs },
1605                 .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
1606                 .dac_nids = alc880_w810_dac_nids,
1607                 .dig_out_nid = ALC880_DIGOUT_NID,
1608                 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
1609                 .channel_mode = alc880_w810_modes,
1610                 .input_mux = &alc880_capture_source,
1611         },
1612         [ALC880_Z71V] = {
1613                 .mixers = { alc880_z71v_mixer },
1614                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs },
1615                 .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
1616                 .dac_nids = alc880_z71v_dac_nids,
1617                 .dig_out_nid = ALC880_DIGOUT_NID,
1618                 .hp_nid = 0x03,
1619                 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1620                 .channel_mode = alc880_2_jack_modes,
1621                 .input_mux = &alc880_capture_source,
1622         },
1623         [ALC880_F1734] = {
1624                 .mixers = { alc880_f1734_mixer },
1625                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
1626                 .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
1627                 .dac_nids = alc880_f1734_dac_nids,
1628                 .hp_nid = 0x02,
1629                 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
1630                 .channel_mode = alc880_2_jack_modes,
1631                 .input_mux = &alc880_capture_source,
1632         },
1633         [ALC880_ASUS] = {
1634                 .mixers = { alc880_asus_mixer },
1635                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1636                                 alc880_gpio1_init_verbs },
1637                 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1638                 .dac_nids = alc880_asus_dac_nids,
1639                 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1640                 .channel_mode = alc880_asus_modes,
1641                 .input_mux = &alc880_capture_source,
1642         },
1643         [ALC880_ASUS_DIG] = {
1644                 .mixers = { alc880_asus_mixer },
1645                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1646                                 alc880_gpio1_init_verbs },
1647                 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1648                 .dac_nids = alc880_asus_dac_nids,
1649                 .dig_out_nid = ALC880_DIGOUT_NID,
1650                 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1651                 .channel_mode = alc880_asus_modes,
1652                 .input_mux = &alc880_capture_source,
1653         },
1654         [ALC880_ASUS_W1V] = {
1655                 .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
1656                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
1657                                 alc880_gpio1_init_verbs },
1658                 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1659                 .dac_nids = alc880_asus_dac_nids,
1660                 .dig_out_nid = ALC880_DIGOUT_NID,
1661                 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1662                 .channel_mode = alc880_asus_modes,
1663                 .input_mux = &alc880_capture_source,
1664         },
1665         [ALC880_UNIWILL_DIG] = {
1666                 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
1667                 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
1668                 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
1669                 .dac_nids = alc880_asus_dac_nids,
1670                 .dig_out_nid = ALC880_DIGOUT_NID,
1671                 .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
1672                 .channel_mode = alc880_asus_modes,
1673                 .input_mux = &alc880_capture_source,
1674         },
1675 #ifdef CONFIG_SND_DEBUG
1676         [ALC880_TEST] = {
1677                 .mixers = { alc880_test_mixer },
1678                 .init_verbs = { alc880_test_init_verbs },
1679                 .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
1680                 .dac_nids = alc880_test_dac_nids,
1681                 .dig_out_nid = ALC880_DIGOUT_NID,
1682                 .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
1683                 .channel_mode = alc880_test_modes,
1684                 .input_mux = &alc880_test_capture_source,
1685         },
1686 #endif
1687 };
1688
1689 /*
1690  * Automatic parse of I/O pins from the BIOS configuration
1691  */
1692
1693 #define NUM_CONTROL_ALLOC       32
1694 #define NUM_VERB_ALLOC          32
1695
1696 enum {
1697         ALC_CTL_WIDGET_VOL,
1698         ALC_CTL_WIDGET_MUTE,
1699         ALC_CTL_BIND_MUTE,
1700 };
1701 static struct snd_kcontrol_new alc880_control_templates[] = {
1702         HDA_CODEC_VOLUME(NULL, 0, 0, 0),
1703         HDA_CODEC_MUTE(NULL, 0, 0, 0),
1704         HDA_BIND_MUTE(NULL, 0, 0, 0),
1705 };
1706
1707 /* add dynamic controls */
1708 static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
1709 {
1710         struct snd_kcontrol_new *knew;
1711
1712         if (spec->num_kctl_used >= spec->num_kctl_alloc) {
1713                 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
1714
1715                 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
1716                 if (! knew)
1717                         return -ENOMEM;
1718                 if (spec->kctl_alloc) {
1719                         memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
1720                         kfree(spec->kctl_alloc);
1721                 }
1722                 spec->kctl_alloc = knew;
1723                 spec->num_kctl_alloc = num;
1724         }
1725
1726         knew = &spec->kctl_alloc[spec->num_kctl_used];
1727         *knew = alc880_control_templates[type];
1728         knew->name = kstrdup(name, GFP_KERNEL);
1729         if (! knew->name)
1730                 return -ENOMEM;
1731         knew->private_value = val;
1732         spec->num_kctl_used++;
1733         return 0;
1734 }
1735
1736 #define alc880_is_fixed_pin(nid)        ((nid) >= 0x14 && (nid) <= 0x17)
1737 #define alc880_fixed_pin_idx(nid)       ((nid) - 0x14)
1738 #define alc880_is_multi_pin(nid)        ((nid) >= 0x18)
1739 #define alc880_multi_pin_idx(nid)       ((nid) - 0x18)
1740 #define alc880_is_input_pin(nid)        ((nid) >= 0x18)
1741 #define alc880_input_pin_idx(nid)       ((nid) - 0x18)
1742 #define alc880_idx_to_dac(nid)          ((nid) + 0x02)
1743 #define alc880_dac_to_idx(nid)          ((nid) - 0x02)
1744 #define alc880_idx_to_mixer(nid)        ((nid) + 0x0c)
1745 #define alc880_idx_to_selector(nid)     ((nid) + 0x10)
1746 #define ALC880_PIN_CD_NID               0x1c
1747
1748 /* fill in the dac_nids table from the parsed pin configuration */
1749 static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
1750 {
1751         hda_nid_t nid;
1752         int assigned[4];
1753         int i, j;
1754
1755         memset(assigned, 0, sizeof(assigned));
1756         spec->multiout.dac_nids = spec->private_dac_nids;
1757
1758         /* check the pins hardwired to audio widget */
1759         for (i = 0; i < cfg->line_outs; i++) {
1760                 nid = cfg->line_out_pins[i];
1761                 if (alc880_is_fixed_pin(nid)) {
1762                         int idx = alc880_fixed_pin_idx(nid);
1763                         spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx);
1764                         assigned[idx] = 1;
1765                 }
1766         }
1767         /* left pins can be connect to any audio widget */
1768         for (i = 0; i < cfg->line_outs; i++) {
1769                 nid = cfg->line_out_pins[i];
1770                 if (alc880_is_fixed_pin(nid))
1771                         continue;
1772                 /* search for an empty channel */
1773                 for (j = 0; j < cfg->line_outs; j++) {
1774                         if (! assigned[j]) {
1775                                 spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
1776                                 assigned[j] = 1;
1777                                 break;
1778                         }
1779                 }
1780         }
1781         spec->multiout.num_dacs = cfg->line_outs;
1782         return 0;
1783 }
1784
1785 /* add playback controls from the parsed DAC table */
1786 static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
1787 {
1788         char name[32];
1789         static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
1790         hda_nid_t nid;
1791         int i, err;
1792
1793         for (i = 0; i < cfg->line_outs; i++) {
1794                 if (! spec->multiout.dac_nids[i])
1795                         continue;
1796                 nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
1797                 if (i == 2) {
1798                         /* Center/LFE */
1799                         if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
1800                                                HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
1801                                 return err;
1802                         if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
1803                                                HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
1804                                 return err;
1805                         if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
1806                                                HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
1807                                 return err;
1808                         if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
1809                                                HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
1810                                 return err;
1811                 } else {
1812                         sprintf(name, "%s Playback Volume", chname[i]);
1813                         if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
1814                                                HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
1815                                 return err;
1816                         sprintf(name, "%s Playback Switch", chname[i]);
1817                         if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
1818                                                HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
1819                                 return err;
1820                 }
1821         }
1822         return 0;
1823 }
1824
1825 /* add playback controls for speaker and HP outputs */
1826 static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
1827                                         const char *pfx)
1828 {
1829         hda_nid_t nid;
1830         int err;
1831         char name[32];
1832
1833         if (! pin)
1834                 return 0;
1835
1836         if (alc880_is_fixed_pin(pin)) {
1837                 nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
1838                 if (! spec->multiout.dac_nids[0]) {
1839                         /* use this as the primary output */
1840                         spec->multiout.dac_nids[0] = nid;
1841                         if (! spec->multiout.num_dacs)
1842                                 spec->multiout.num_dacs = 1;
1843                 } else 
1844                         /* specify the DAC as the extra output */
1845                         spec->multiout.hp_nid = nid;
1846                 /* control HP volume/switch on the output mixer amp */
1847                 nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
1848                 sprintf(name, "%s Playback Volume", pfx);
1849                 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
1850                                        HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
1851                         return err;
1852                 sprintf(name, "%s Playback Switch", pfx);
1853                 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
1854                                        HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
1855                         return err;
1856         } else if (alc880_is_multi_pin(pin)) {
1857                 /* set manual connection */
1858                 if (! spec->multiout.dac_nids[0]) {
1859                         /* use this as the primary output */
1860                         spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin));
1861                         if (! spec->multiout.num_dacs)
1862                                 spec->multiout.num_dacs = 1;
1863                 }
1864                 /* we have only a switch on HP-out PIN */
1865                 sprintf(name, "%s Playback Switch", pfx);
1866                 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
1867                                        HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
1868                         return err;
1869         }
1870         return 0;
1871 }
1872
1873 /* create input playback/capture controls for the given pin */
1874 static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname)
1875 {
1876         char name[32];
1877         int err, idx;
1878
1879         sprintf(name, "%s Playback Volume", ctlname);
1880         idx = alc880_input_pin_idx(pin);
1881         if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
1882                                HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
1883                 return err;
1884         sprintf(name, "%s Playback Switch", ctlname);
1885         if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
1886                                HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
1887                 return err;
1888         return 0;
1889 }
1890
1891 /* create playback/capture controls for input pins */
1892 static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
1893 {
1894         static char *labels[AUTO_PIN_LAST] = {
1895                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
1896         };
1897         struct hda_input_mux *imux = &spec->private_imux;
1898         int i, err;
1899
1900         for (i = 0; i < AUTO_PIN_LAST; i++) {
1901                 if (alc880_is_input_pin(cfg->input_pins[i])) {
1902                         err = new_analog_input(spec, cfg->input_pins[i], labels[i]);
1903                         if (err < 0)
1904                                 return err;
1905                         imux->items[imux->num_items].label = labels[i];
1906                         imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
1907                         imux->num_items++;
1908                 }
1909         }
1910         return 0;
1911 }
1912
1913 static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type,
1914                                               int dac_idx)
1915 {
1916         /* set as output */
1917         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
1918         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
1919         /* need the manual connection? */
1920         if (alc880_is_multi_pin(nid)) {
1921                 struct alc_spec *spec = codec->spec;
1922                 int idx = alc880_multi_pin_idx(nid);
1923                 snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
1924                                     AC_VERB_SET_CONNECT_SEL,
1925                                     alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
1926         }
1927 }
1928
1929 static void alc880_auto_init_multi_out(struct hda_codec *codec)
1930 {
1931         struct alc_spec *spec = codec->spec;
1932         int i;
1933
1934         for (i = 0; i < spec->autocfg.line_outs; i++) {
1935                 hda_nid_t nid = spec->autocfg.line_out_pins[i];
1936                 alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
1937         }
1938 }
1939
1940 static void alc880_auto_init_extra_out(struct hda_codec *codec)
1941 {
1942         struct alc_spec *spec = codec->spec;
1943         hda_nid_t pin;
1944
1945         pin = spec->autocfg.speaker_pin;
1946         if (pin) /* connect to front */
1947                 alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0);
1948         pin = spec->autocfg.hp_pin;
1949         if (pin) /* connect to front */
1950                 alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
1951 }
1952
1953 static void alc880_auto_init_analog_input(struct hda_codec *codec)
1954 {
1955         struct alc_spec *spec = codec->spec;
1956         int i;
1957
1958         for (i = 0; i < AUTO_PIN_LAST; i++) {
1959                 hda_nid_t nid = spec->autocfg.input_pins[i];
1960                 if (alc880_is_input_pin(nid)) {
1961                         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
1962                                             i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
1963                         if (nid != ALC880_PIN_CD_NID)
1964                                 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1965                                                     AMP_OUT_MUTE);
1966                 }
1967         }
1968 }
1969
1970 /* parse the BIOS configuration and set up the alc_spec */
1971 /* return 1 if successful, 0 if the proper config is not found, or a negative error code */
1972 static int alc880_parse_auto_config(struct hda_codec *codec)
1973 {
1974         struct alc_spec *spec = codec->spec;
1975         int err;
1976
1977         if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0)
1978                 return err;
1979         if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0)
1980                 return err;
1981         if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin &&
1982             ! spec->autocfg.hp_pin)
1983                 return 0; /* can't find valid BIOS pin config */
1984         if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
1985             (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
1986                                                 "Speaker")) < 0 ||
1987             (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin,
1988                                                 "Headphone")) < 0 ||
1989             (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
1990                 return err;
1991
1992         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1993
1994         if (spec->autocfg.dig_out_pin)
1995                 spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
1996         if (spec->autocfg.dig_in_pin)
1997                 spec->dig_in_nid = ALC880_DIGIN_NID;
1998
1999         if (spec->kctl_alloc)
2000                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2001
2002         spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
2003
2004         spec->input_mux = &spec->private_imux;
2005
2006         return 1;
2007 }
2008
2009 /* init callback for auto-configuration model -- overriding the default init */
2010 static int alc880_auto_init(struct hda_codec *codec)
2011 {
2012         alc_init(codec);
2013         alc880_auto_init_multi_out(codec);
2014         alc880_auto_init_extra_out(codec);
2015         alc880_auto_init_analog_input(codec);
2016         return 0;
2017 }
2018
2019 /*
2020  * OK, here we have finally the patch for ALC880
2021  */
2022
2023 static int patch_alc880(struct hda_codec *codec)
2024 {
2025         struct alc_spec *spec;
2026         int board_config;
2027         int i, err;
2028
2029         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2030         if (spec == NULL)
2031                 return -ENOMEM;
2032
2033         codec->spec = spec;
2034
2035         board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
2036         if (board_config < 0 || board_config >= ALC880_MODEL_LAST) {
2037                 printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
2038                 board_config = ALC880_AUTO;
2039         }
2040
2041         if (board_config == ALC880_AUTO) {
2042                 /* automatic parse from the BIOS config */
2043                 err = alc880_parse_auto_config(codec);
2044                 if (err < 0) {
2045                         alc_free(codec);
2046                         return err;
2047                 } else if (! err) {
2048                         printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS.  Using 3-stack mode...\n");
2049                         board_config = ALC880_3ST;
2050                 }
2051         }
2052
2053         if (board_config != ALC880_AUTO) {
2054                 /* set up from the preset table */
2055                 const struct alc_config_preset *preset;
2056
2057                 preset = &alc880_presets[board_config];
2058
2059                 for (i = 0; preset->mixers[i]; i++) {
2060                         snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break);
2061                         spec->mixers[spec->num_mixers++] = preset->mixers[i];
2062                 }
2063                 for (i = 0; preset->init_verbs[i]; i++) {
2064                         snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break);
2065                         spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
2066                 }
2067
2068                 spec->channel_mode = preset->channel_mode;
2069                 spec->num_channel_mode = preset->num_channel_mode;
2070
2071                 spec->multiout.max_channels = spec->channel_mode[0].channels;
2072
2073                 spec->multiout.num_dacs = preset->num_dacs;
2074                 spec->multiout.dac_nids = preset->dac_nids;
2075                 spec->multiout.dig_out_nid = preset->dig_out_nid;
2076                 spec->multiout.hp_nid = preset->hp_nid;
2077
2078                 spec->input_mux = preset->input_mux;
2079
2080                 spec->num_adc_nids = preset->num_adc_nids;
2081                 spec->adc_nids = preset->adc_nids;
2082         }
2083
2084         spec->stream_name_analog = "ALC880 Analog";
2085         spec->stream_analog_playback = &alc880_pcm_analog_playback;
2086         spec->stream_analog_capture = &alc880_pcm_analog_capture;
2087
2088         spec->stream_name_digital = "ALC880 Digital";
2089         spec->stream_digital_playback = &alc880_pcm_digital_playback;
2090         spec->stream_digital_capture = &alc880_pcm_digital_capture;
2091
2092         if (! spec->adc_nids && spec->input_mux) {
2093                 /* check whether NID 0x07 is valid */
2094                 unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
2095                 wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
2096                 if (wcap != AC_WID_AUD_IN) {
2097                         spec->adc_nids = alc880_adc_nids_alt;
2098                         spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
2099                         spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
2100                         spec->num_mixers++;
2101                 } else {
2102                         spec->adc_nids = alc880_adc_nids;
2103                         spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
2104                         spec->mixers[spec->num_mixers] = alc880_capture_mixer;
2105                         spec->num_mixers++;
2106                 }
2107         }
2108
2109         codec->patch_ops = alc_patch_ops;
2110         if (board_config == ALC880_AUTO)
2111                 codec->patch_ops.init = alc880_auto_init;
2112
2113         return 0;
2114 }
2115
2116
2117 /*
2118  * ALC260 support
2119  */
2120
2121 static hda_nid_t alc260_dac_nids[1] = {
2122         /* front */
2123         0x02,
2124 };
2125
2126 static hda_nid_t alc260_adc_nids[1] = {
2127         /* ADC0 */
2128         0x04,
2129 };
2130
2131 static hda_nid_t alc260_hp_adc_nids[1] = {
2132         /* ADC1 */
2133         0x05,
2134 };
2135
2136 #define ALC260_DIGOUT_NID       0x03
2137 #define ALC260_DIGIN_NID        0x06
2138
2139 static struct hda_input_mux alc260_capture_source = {
2140         .num_items = 4,
2141         .items = {
2142                 { "Mic", 0x0 },
2143                 { "Front Mic", 0x1 },
2144                 { "Line", 0x2 },
2145                 { "CD", 0x4 },
2146         },
2147 };
2148
2149 /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack
2150  * and the internal CD lines.
2151  */
2152 static struct hda_input_mux alc260_fujitsu_capture_source = {
2153         .num_items = 2,
2154         .items = {
2155                 { "Mic/Line", 0x0 },
2156                 { "CD", 0x4 },
2157         },
2158 };
2159
2160 /*
2161  * This is just place-holder, so there's something for alc_build_pcms to look
2162  * at when it calculates the maximum number of channels. ALC260 has no mixer
2163  * element which allows changing the channel mode, so the verb list is
2164  * never used.
2165  */
2166 static struct hda_channel_mode alc260_modes[1] = {
2167         { 2, NULL },
2168 };
2169
2170 static struct snd_kcontrol_new alc260_base_mixer[] = {
2171         HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2172         HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
2173         HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2174         HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2175         HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
2176         HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
2177         HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
2178         HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
2179         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
2180         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
2181         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
2182         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
2183         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2184         HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
2185         HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2186         HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2187         HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
2188         HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
2189         {
2190                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2191                 .name = "Capture Source",
2192                 .info = alc_mux_enum_info,
2193                 .get = alc_mux_enum_get,
2194                 .put = alc_mux_enum_put,
2195         },
2196         { } /* end */
2197 };
2198
2199 static struct snd_kcontrol_new alc260_hp_mixer[] = {
2200         HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2201         HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
2202         HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2203         HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2204         HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
2205         HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
2206         HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
2207         HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
2208         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
2209         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
2210         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2211         HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
2212         HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
2213         HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
2214         HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
2215         HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
2216         {
2217                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2218                 .name = "Capture Source",
2219                 .info = alc_mux_enum_info,
2220                 .get = alc_mux_enum_get,
2221                 .put = alc_mux_enum_put,
2222         },
2223         { } /* end */
2224 };
2225
2226 static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
2227         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
2228         HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
2229         ALC_PINCTL_SWITCH("Headphone Amp Switch", 0x14, PIN_HP_AMP),
2230         HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
2231         HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
2232         HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
2233         HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
2234         HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
2235         HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
2236         HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
2237         HDA_BIND_MUTE("Internal Speaker Playback Switch", 0x09, 2, HDA_INPUT),
2238         HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
2239         HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
2240         {
2241                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2242                 .name = "Capture Source",
2243                 .info = alc_mux_enum_info,
2244                 .get = alc_mux_enum_get,
2245                 .put = alc_mux_enum_put,
2246         },
2247         { } /* end */
2248 };
2249
2250 static struct hda_verb alc260_init_verbs[] = {
2251         /* Line In pin widget for input */
2252         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2253         /* CD pin widget for input */
2254         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2255         /* Mic1 (rear panel) pin widget for input and vref at 80% */
2256         {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2257         /* Mic2 (front panel) pin widget for input and vref at 80% */
2258         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2259         /* LINE-2 is used for line-out in rear */
2260         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2261         /* select line-out */
2262         {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
2263         /* LINE-OUT pin */
2264         {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2265         /* enable HP */
2266         {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2267         /* enable Mono */
2268         {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2269         /* mute capture amp left and right */
2270         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2271         /* set connection select to line in (default select for this ADC) */
2272         {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
2273         /* mute capture amp left and right */
2274         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2275         /* set connection select to line in (default select for this ADC) */
2276         {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
2277         /* set vol=0 Line-Out mixer amp left and right */
2278         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2279         /* unmute pin widget amp left and right (no gain on this amp) */
2280         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2281         /* set vol=0 HP mixer amp left and right */
2282         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2283         /* unmute pin widget amp left and right (no gain on this amp) */
2284         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2285         /* set vol=0 Mono mixer amp left and right */
2286         {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2287         /* unmute pin widget amp left and right (no gain on this amp) */
2288         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2289         /* unmute LINE-2 out pin */
2290         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2291         /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
2292         /* mute CD */
2293         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
2294         /* mute Line In */
2295         {0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2296         /* mute Mic */
2297         {0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2298         /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
2299         /* mute Front out path */
2300         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2301         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2302         /* mute Headphone out path */
2303         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2304         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2305         /* mute Mono out path */
2306         {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2307         {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2308         { }
2309 };
2310
2311 /* Initialisation sequence for ALC260 as configured in Fujitsu S702x
2312  * laptops.
2313  */
2314 static struct hda_verb alc260_fujitsu_init_verbs[] = {
2315         /* Disable all GPIOs */
2316         {0x01, AC_VERB_SET_GPIO_MASK, 0},
2317         /* Internal speaker is connected to headphone pin */
2318         {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2319         /* Headphone/Line-out jack connects to Line1 pin; make it an output */
2320         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2321         /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
2322         {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2323         /* Ensure all other unused pins are disabled and muted.
2324          * Note: trying to set widget 0x15 to anything blocks all audio
2325          * output for some reason, so just leave that at the default.
2326          */
2327         {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2328         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2329         {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2330         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2331         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
2332         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2333         /* Disable digital (SPDIF) pins */
2334         {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
2335         {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
2336
2337         /* Start with mixer outputs muted */
2338         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2339         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2340         {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2341
2342         /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
2343         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2344         /* Unmute Line1 pin widget amp left and right (no equiv mixer ctrl) */
2345         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2346         /* Unmute pin widget used for Line-in (no equiv mixer ctrl) */
2347         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2348
2349         /* Mute capture amp left and right */
2350         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2351         /* Set ADC connection select to line in (on mic1 pin) */
2352         {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
2353
2354         /* Mute all inputs to mixer widget (even unconnected ones) */
2355         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
2356         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
2357         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
2358         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
2359         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
2360         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
2361         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
2362         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
2363 };
2364
2365 static struct hda_pcm_stream alc260_pcm_analog_playback = {
2366         .substreams = 1,
2367         .channels_min = 2,
2368         .channels_max = 2,
2369 };
2370
2371 static struct hda_pcm_stream alc260_pcm_analog_capture = {
2372         .substreams = 1,
2373         .channels_min = 2,
2374         .channels_max = 2,
2375 };
2376
2377 static struct hda_board_config alc260_cfg_tbl[] = {
2378         { .modelname = "hp", .config = ALC260_HP },
2379         { .pci_subvendor = 0x103c, .config = ALC260_HP },
2380         { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702x },
2381         { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702x },
2382         {}
2383 };
2384
2385 static int patch_alc260(struct hda_codec *codec)
2386 {
2387         struct alc_spec *spec;
2388         int board_config;
2389
2390         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2391         if (spec == NULL)
2392                 return -ENOMEM;
2393
2394         codec->spec = spec;
2395
2396         board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
2397         if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
2398                 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
2399                 board_config = ALC260_BASIC;
2400         }
2401
2402         switch (board_config) {
2403         case ALC260_HP:
2404                 spec->mixers[spec->num_mixers] = alc260_hp_mixer;
2405                 spec->num_mixers++;
2406                 break;
2407         case ALC260_FUJITSU_S702x:
2408                 spec->mixers[spec->num_mixers] = alc260_fujitsu_mixer;
2409                 spec->num_mixers++;
2410                 break;
2411         default:
2412                 spec->mixers[spec->num_mixers] = alc260_base_mixer;
2413                 spec->num_mixers++;
2414                 break;
2415         }
2416
2417         if (board_config != ALC260_FUJITSU_S702x) {
2418                 spec->init_verbs[0] = alc260_init_verbs;
2419                 spec->num_init_verbs = 1;
2420         } else {
2421                 spec->init_verbs[0] = alc260_fujitsu_init_verbs;
2422                 spec->num_init_verbs = 1;
2423         }
2424
2425         spec->channel_mode = alc260_modes;
2426         spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
2427
2428         spec->stream_name_analog = "ALC260 Analog";
2429         spec->stream_analog_playback = &alc260_pcm_analog_playback;
2430         spec->stream_analog_capture = &alc260_pcm_analog_capture;
2431
2432         spec->multiout.max_channels = spec->channel_mode[0].channels;
2433         spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
2434         spec->multiout.dac_nids = alc260_dac_nids;
2435
2436         if (board_config != ALC260_FUJITSU_S702x) {
2437                 spec->input_mux = &alc260_capture_source;
2438         } else {
2439                 spec->input_mux = &alc260_fujitsu_capture_source;
2440         }
2441         switch (board_config) {
2442         case ALC260_HP:
2443                 spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids);
2444                 spec->adc_nids = alc260_hp_adc_nids;
2445                 break;
2446         default:
2447                 spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
2448                 spec->adc_nids = alc260_adc_nids;
2449                 break;
2450         }
2451
2452         codec->patch_ops = alc_patch_ops;
2453
2454         return 0;
2455 }
2456
2457
2458 /*
2459  * ALC882 support
2460  *
2461  * ALC882 is almost identical with ALC880 but has cleaner and more flexible
2462  * configuration.  Each pin widget can choose any input DACs and a mixer.
2463  * Each ADC is connected from a mixer of all inputs.  This makes possible
2464  * 6-channel independent captures.
2465  *
2466  * In addition, an independent DAC for the multi-playback (not used in this
2467  * driver yet).
2468  */
2469
2470 static struct hda_channel_mode alc882_ch_modes[1] = {
2471         { 8, NULL }
2472 };
2473
2474 static hda_nid_t alc882_dac_nids[4] = {
2475         /* front, rear, clfe, rear_surr */
2476         0x02, 0x03, 0x04, 0x05
2477 };
2478
2479 static hda_nid_t alc882_adc_nids[3] = {
2480         /* ADC0-2 */
2481         0x07, 0x08, 0x09,
2482 };
2483
2484 /* input MUX */
2485 /* FIXME: should be a matrix-type input source selection */
2486
2487 static struct hda_input_mux alc882_capture_source = {
2488         .num_items = 4,
2489         .items = {
2490                 { "Mic", 0x0 },
2491                 { "Front Mic", 0x1 },
2492                 { "Line", 0x2 },
2493                 { "CD", 0x4 },
2494         },
2495 };
2496
2497 #define alc882_mux_enum_info alc_mux_enum_info
2498 #define alc882_mux_enum_get alc_mux_enum_get
2499
2500 static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
2501 {
2502         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2503         struct alc_spec *spec = codec->spec;
2504         const struct hda_input_mux *imux = spec->input_mux;
2505         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2506         static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
2507         hda_nid_t nid = capture_mixers[adc_idx];
2508         unsigned int *cur_val = &spec->cur_mux[adc_idx];
2509         unsigned int i, idx;
2510
2511         idx = ucontrol->value.enumerated.item[0];
2512         if (idx >= imux->num_items)
2513                 idx = imux->num_items - 1;
2514         if (*cur_val == idx && ! codec->in_resume)
2515                 return 0;
2516         for (i = 0; i < imux->num_items; i++) {
2517                 unsigned int v = (i == idx) ? 0x7000 : 0x7080;
2518                 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
2519                                     v | (imux->items[i].index << 8));
2520         }
2521         *cur_val = idx;
2522         return 1;
2523 }
2524
2525 /* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
2526  *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
2527  */
2528 static struct snd_kcontrol_new alc882_base_mixer[] = {
2529         HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
2530         HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
2531         HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
2532         HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
2533         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
2534         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
2535         HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
2536         HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
2537         HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
2538         HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
2539         HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
2540         HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
2541         HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
2542         HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
2543         HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
2544         HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
2545         HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
2546         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
2547         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
2548         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
2549         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
2550         HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
2551         HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
2552         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
2553         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
2554         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
2555         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
2556         {
2557                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2558                 /* .name = "Capture Source", */
2559                 .name = "Input Source",
2560                 .count = 3,
2561                 .info = alc882_mux_enum_info,
2562                 .get = alc882_mux_enum_get,
2563                 .put = alc882_mux_enum_put,
2564         },
2565         { } /* end */
2566 };
2567
2568 static struct hda_verb alc882_init_verbs[] = {
2569         /* Front mixer: unmute input/output amp left and right (volume = 0) */
2570         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2571         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2572         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2573         /* Rear mixer */
2574         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2575         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2576         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2577         /* CLFE mixer */
2578         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2579         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2580         {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2581         /* Side mixer */
2582         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2583         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2584         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2585
2586         /* Front Pin: output 0 (0x0c) */
2587         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2588         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2589         {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
2590         /* Rear Pin: output 1 (0x0d) */
2591         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2592         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2593         {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
2594         /* CLFE Pin: output 2 (0x0e) */
2595         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2596         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2597         {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
2598         /* Side Pin: output 3 (0x0f) */
2599         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
2600         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2601         {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
2602         /* Mic (rear) pin: input vref at 80% */
2603         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2604         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2605         /* Front Mic pin: input vref at 80% */
2606         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
2607         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2608         /* Line In pin: input */
2609         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2610         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
2611         /* Line-2 In: Headphone output (output 0 - 0x0c) */
2612         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
2613         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
2614         {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
2615         /* CD pin widget for input */
2616         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
2617
2618         /* FIXME: use matrix-type input source selection */
2619         /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
2620         /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
2621         {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2622         {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2623         {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2624         {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2625         /* Input mixer2 */
2626         {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2627         {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2628         {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2629         {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2630         /* Input mixer3 */
2631         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2632         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
2633         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
2634         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2635         /* ADC1: mute amp left and right */
2636         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2637         {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
2638         /* ADC2: mute amp left and right */
2639         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2640         {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
2641         /* ADC3: mute amp left and right */
2642         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
2643         {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
2644
2645         { }
2646 };
2647
2648 static int patch_alc882(struct hda_codec *codec)
2649 {
2650         struct alc_spec *spec;
2651
2652         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2653         if (spec == NULL)
2654                 return -ENOMEM;
2655
2656         codec->spec = spec;
2657
2658         spec->mixers[spec->num_mixers] = alc882_base_mixer;
2659         spec->num_mixers++;
2660
2661         spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
2662         spec->dig_in_nid = ALC880_DIGIN_NID;
2663         spec->init_verbs[0] = alc882_init_verbs;
2664         spec->num_init_verbs = 1;
2665
2666         spec->channel_mode = alc882_ch_modes;
2667         spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
2668
2669         spec->stream_name_analog = "ALC882 Analog";
2670         spec->stream_analog_playback = &alc880_pcm_analog_playback;
2671         spec->stream_analog_capture = &alc880_pcm_analog_capture;
2672
2673         spec->stream_name_digital = "ALC882 Digital";
2674         spec->stream_digital_playback = &alc880_pcm_digital_playback;
2675         spec->stream_digital_capture = &alc880_pcm_digital_capture;
2676
2677         spec->multiout.max_channels = spec->channel_mode[0].channels;
2678         spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids);
2679         spec->multiout.dac_nids = alc882_dac_nids;
2680
2681         spec->input_mux = &alc882_capture_source;
2682         spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
2683         spec->adc_nids = alc882_adc_nids;
2684
2685         codec->patch_ops = alc_patch_ops;
2686
2687         return 0;
2688 }
2689
2690 /*
2691  * patch entries
2692  */
2693 struct hda_codec_preset snd_hda_preset_realtek[] = {
2694         { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
2695         { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
2696         { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
2697         {} /* terminator */
2698 };