]> git.karo-electronics.de Git - karo-tx-linux.git/blob - sound/pci/hda/patch_analog.c
[ALSA] hda-codec - Add AD1988 support
[karo-tx-linux.git] / sound / pci / hda / patch_analog.c
1 /*
2  * HD audio interface patch for AD1981HD, AD1983, AD1986A
3  *
4  * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
5  *
6  *  This driver is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This driver is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19  */
20
21 #include <sound/driver.h>
22 #include <linux/init.h>
23 #include <linux/delay.h>
24 #include <linux/slab.h>
25 #include <linux/pci.h>
26 #include <sound/core.h>
27 #include "hda_codec.h"
28 #include "hda_local.h"
29
30 struct ad198x_spec {
31         struct snd_kcontrol_new *mixers[5];
32         int num_mixers;
33
34         const struct hda_verb *init_verbs[3];   /* initialization verbs
35                                                  * don't forget NULL termination!
36                                                  */
37         unsigned int num_init_verbs;
38
39         /* playback */
40         struct hda_multi_out multiout;  /* playback set-up
41                                          * max_channels, dacs must be set
42                                          * dig_out_nid and hp_nid are optional
43                                          */
44         unsigned int cur_eapd;
45
46         /* capture */
47         unsigned int num_adc_nids;
48         hda_nid_t *adc_nids;
49         hda_nid_t dig_in_nid;           /* digital-in NID; optional */
50
51         /* capture source */
52         const struct hda_input_mux *input_mux;
53         unsigned int cur_mux[3];
54
55         /* channel model */
56         const struct hda_channel_mode *channel_mode;
57         int num_channel_mode;
58
59         /* PCM information */
60         struct hda_pcm pcm_rec[2];      /* used in alc_build_pcms() */
61
62         struct semaphore amp_mutex;     /* PCM volume/mute control mutex */
63         unsigned int spdif_route;
64 };
65
66 /*
67  * input MUX handling (common part)
68  */
69 static int ad198x_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
70 {
71         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
72         struct ad198x_spec *spec = codec->spec;
73
74         return snd_hda_input_mux_info(spec->input_mux, uinfo);
75 }
76
77 static int ad198x_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
78 {
79         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
80         struct ad198x_spec *spec = codec->spec;
81         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
82
83         ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
84         return 0;
85 }
86
87 static int ad198x_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
88 {
89         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
90         struct ad198x_spec *spec = codec->spec;
91         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
92
93         return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
94                                      spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
95 }
96
97 /*
98  * initialization (common callbacks)
99  */
100 static int ad198x_init(struct hda_codec *codec)
101 {
102         struct ad198x_spec *spec = codec->spec;
103         int i;
104
105         for (i = 0; i < spec->num_init_verbs; i++)
106                 snd_hda_sequence_write(codec, spec->init_verbs[i]);
107         return 0;
108 }
109
110 static int ad198x_build_controls(struct hda_codec *codec)
111 {
112         struct ad198x_spec *spec = codec->spec;
113         unsigned int i;
114         int err;
115
116         for (i = 0; i < spec->num_mixers; i++) {
117                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
118                 if (err < 0)
119                         return err;
120         }
121         if (spec->multiout.dig_out_nid) {
122                 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
123                 if (err < 0)
124                         return err;
125         } 
126         if (spec->dig_in_nid) {
127                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
128                 if (err < 0)
129                         return err;
130         }
131         return 0;
132 }
133
134 /*
135  * Analog playback callbacks
136  */
137 static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
138                                     struct hda_codec *codec,
139                                     struct snd_pcm_substream *substream)
140 {
141         struct ad198x_spec *spec = codec->spec;
142         return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
143 }
144
145 static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
146                                        struct hda_codec *codec,
147                                        unsigned int stream_tag,
148                                        unsigned int format,
149                                        struct snd_pcm_substream *substream)
150 {
151         struct ad198x_spec *spec = codec->spec;
152         return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
153                                                 format, substream);
154 }
155
156 static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
157                                        struct hda_codec *codec,
158                                        struct snd_pcm_substream *substream)
159 {
160         struct ad198x_spec *spec = codec->spec;
161         return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
162 }
163
164 /*
165  * Digital out
166  */
167 static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
168                                         struct hda_codec *codec,
169                                         struct snd_pcm_substream *substream)
170 {
171         struct ad198x_spec *spec = codec->spec;
172         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
173 }
174
175 static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
176                                          struct hda_codec *codec,
177                                          struct snd_pcm_substream *substream)
178 {
179         struct ad198x_spec *spec = codec->spec;
180         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
181 }
182
183 /*
184  * Analog capture
185  */
186 static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
187                                       struct hda_codec *codec,
188                                       unsigned int stream_tag,
189                                       unsigned int format,
190                                       struct snd_pcm_substream *substream)
191 {
192         struct ad198x_spec *spec = codec->spec;
193         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
194                                    stream_tag, 0, format);
195         return 0;
196 }
197
198 static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
199                                       struct hda_codec *codec,
200                                       struct snd_pcm_substream *substream)
201 {
202         struct ad198x_spec *spec = codec->spec;
203         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
204                                    0, 0, 0);
205         return 0;
206 }
207
208
209 /*
210  */
211 static struct hda_pcm_stream ad198x_pcm_analog_playback = {
212         .substreams = 1,
213         .channels_min = 2,
214         .channels_max = 6, /* changed later */
215         .nid = 0, /* fill later */
216         .ops = {
217                 .open = ad198x_playback_pcm_open,
218                 .prepare = ad198x_playback_pcm_prepare,
219                 .cleanup = ad198x_playback_pcm_cleanup
220         },
221 };
222
223 static struct hda_pcm_stream ad198x_pcm_analog_capture = {
224         .substreams = 1,
225         .channels_min = 2,
226         .channels_max = 2,
227         .nid = 0, /* fill later */
228         .ops = {
229                 .prepare = ad198x_capture_pcm_prepare,
230                 .cleanup = ad198x_capture_pcm_cleanup
231         },
232 };
233
234 static struct hda_pcm_stream ad198x_pcm_digital_playback = {
235         .substreams = 1,
236         .channels_min = 2,
237         .channels_max = 2,
238         .nid = 0, /* fill later */
239         .ops = {
240                 .open = ad198x_dig_playback_pcm_open,
241                 .close = ad198x_dig_playback_pcm_close
242         },
243 };
244
245 static struct hda_pcm_stream ad198x_pcm_digital_capture = {
246         .substreams = 1,
247         .channels_min = 2,
248         .channels_max = 2,
249         /* NID is set in alc_build_pcms */
250 };
251
252 static int ad198x_build_pcms(struct hda_codec *codec)
253 {
254         struct ad198x_spec *spec = codec->spec;
255         struct hda_pcm *info = spec->pcm_rec;
256
257         codec->num_pcms = 1;
258         codec->pcm_info = info;
259
260         info->name = "AD198x Analog";
261         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
262         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
263         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
264         info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
265         info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
266         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
267
268         if (spec->multiout.dig_out_nid) {
269                 info++;
270                 codec->num_pcms++;
271                 info->name = "AD198x Digital";
272                 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
273                 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
274                 if (spec->dig_in_nid) {
275                         info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_digital_capture;
276                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
277                 }
278         }
279
280         return 0;
281 }
282
283 static void ad198x_free(struct hda_codec *codec)
284 {
285         kfree(codec->spec);
286 }
287
288 #ifdef CONFIG_PM
289 static int ad198x_resume(struct hda_codec *codec)
290 {
291         struct ad198x_spec *spec = codec->spec;
292         int i;
293
294         ad198x_init(codec);
295         for (i = 0; i < spec->num_mixers; i++)
296                 snd_hda_resume_ctls(codec, spec->mixers[i]);
297         if (spec->multiout.dig_out_nid)
298                 snd_hda_resume_spdif_out(codec);
299         if (spec->dig_in_nid)
300                 snd_hda_resume_spdif_in(codec);
301         return 0;
302 }
303 #endif
304
305 static struct hda_codec_ops ad198x_patch_ops = {
306         .build_controls = ad198x_build_controls,
307         .build_pcms = ad198x_build_pcms,
308         .init = ad198x_init,
309         .free = ad198x_free,
310 #ifdef CONFIG_PM
311         .resume = ad198x_resume,
312 #endif
313 };
314
315
316 /*
317  * AD1986A specific
318  */
319
320 #define AD1986A_SPDIF_OUT       0x02
321 #define AD1986A_FRONT_DAC       0x03
322 #define AD1986A_SURR_DAC        0x04
323 #define AD1986A_CLFE_DAC        0x05
324 #define AD1986A_ADC             0x06
325
326 static hda_nid_t ad1986a_dac_nids[3] = {
327         AD1986A_FRONT_DAC, AD1986A_SURR_DAC, AD1986A_CLFE_DAC
328 };
329 static hda_nid_t ad1986a_adc_nids[1] = { AD1986A_ADC };
330
331 static struct hda_input_mux ad1986a_capture_source = {
332         .num_items = 7,
333         .items = {
334                 { "Mic", 0x0 },
335                 { "CD", 0x1 },
336                 { "Aux", 0x3 },
337                 { "Line", 0x4 },
338                 { "Mix", 0x5 },
339                 { "Mono", 0x6 },
340                 { "Phone", 0x7 },
341         },
342 };
343
344 /*
345  * PCM control
346  *
347  * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
348  */
349
350 #define ad1986a_pcm_amp_vol_info        snd_hda_mixer_amp_volume_info
351
352 static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
353 {
354         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
355         struct ad198x_spec *ad = codec->spec;
356
357         down(&ad->amp_mutex);
358         snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
359         up(&ad->amp_mutex);
360         return 0;
361 }
362
363 static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
364 {
365         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
366         struct ad198x_spec *ad = codec->spec;
367         int i, change = 0;
368
369         down(&ad->amp_mutex);
370         for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
371                 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
372                 change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
373         }
374         kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
375         up(&ad->amp_mutex);
376         return change;
377 }
378
379 #define ad1986a_pcm_amp_sw_info         snd_hda_mixer_amp_switch_info
380
381 static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
382 {
383         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
384         struct ad198x_spec *ad = codec->spec;
385
386         down(&ad->amp_mutex);
387         snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
388         up(&ad->amp_mutex);
389         return 0;
390 }
391
392 static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
393 {
394         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
395         struct ad198x_spec *ad = codec->spec;
396         int i, change = 0;
397
398         down(&ad->amp_mutex);
399         for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) {
400                 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT);
401                 change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
402         }
403         kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
404         up(&ad->amp_mutex);
405         return change;
406 }
407
408 /*
409  * mixers
410  */
411 static struct snd_kcontrol_new ad1986a_mixers[] = {
412         {
413                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
414                 .name = "PCM Playback Volume",
415                 .info = ad1986a_pcm_amp_vol_info,
416                 .get = ad1986a_pcm_amp_vol_get,
417                 .put = ad1986a_pcm_amp_vol_put,
418                 .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
419         },
420         {
421                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
422                 .name = "PCM Playback Switch",
423                 .info = ad1986a_pcm_amp_sw_info,
424                 .get = ad1986a_pcm_amp_sw_get,
425                 .put = ad1986a_pcm_amp_sw_put,
426                 .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
427         },
428         HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
429         HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
430         HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
431         HDA_CODEC_MUTE("Surround Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
432         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x1d, 1, 0x0, HDA_OUTPUT),
433         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x1d, 2, 0x0, HDA_OUTPUT),
434         HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x1d, 1, 0x0, HDA_OUTPUT),
435         HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x1d, 2, 0x0, HDA_OUTPUT),
436         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x1a, 0x0, HDA_OUTPUT),
437         HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
438         HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_OUTPUT),
439         HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_OUTPUT),
440         HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x0, HDA_OUTPUT),
441         HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x0, HDA_OUTPUT),
442         HDA_CODEC_VOLUME("Aux Playback Volume", 0x16, 0x0, HDA_OUTPUT),
443         HDA_CODEC_MUTE("Aux Playback Switch", 0x16, 0x0, HDA_OUTPUT),
444         HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
445         HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
446         HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x18, 0x0, HDA_OUTPUT),
447         HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x18, 0x0, HDA_OUTPUT),
448         HDA_CODEC_VOLUME("Mono Playback Volume", 0x1e, 0x0, HDA_OUTPUT),
449         HDA_CODEC_MUTE("Mono Playback Switch", 0x1e, 0x0, HDA_OUTPUT),
450         HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
451         HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
452         {
453                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
454                 .name = "Capture Source",
455                 .info = ad198x_mux_enum_info,
456                 .get = ad198x_mux_enum_get,
457                 .put = ad198x_mux_enum_put,
458         },
459         HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
460         { } /* end */
461 };
462
463 /*
464  * initialization verbs
465  */
466 static struct hda_verb ad1986a_init_verbs[] = {
467         /* Front, Surround, CLFE DAC; mute as default */
468         {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
469         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
470         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
471         /* Downmix - off */
472         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
473         /* HP, Line-Out, Surround, CLFE selectors */
474         {0x0a, AC_VERB_SET_CONNECT_SEL, 0x0},
475         {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0},
476         {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
477         {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
478         /* Mono selector */
479         {0x0e, AC_VERB_SET_CONNECT_SEL, 0x0},
480         /* Mic selector: Mic 1/2 pin */
481         {0x0f, AC_VERB_SET_CONNECT_SEL, 0x0},
482         /* Line-in selector: Line-in */
483         {0x10, AC_VERB_SET_CONNECT_SEL, 0x0},
484         /* Mic 1/2 swap */
485         {0x11, AC_VERB_SET_CONNECT_SEL, 0x0},
486         /* Record selector: mic */
487         {0x12, AC_VERB_SET_CONNECT_SEL, 0x0},
488         /* Mic, Phone, CD, Aux, Line-In amp; mute as default */
489         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
490         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
491         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
492         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
493         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
494         /* PC beep */
495         {0x18, AC_VERB_SET_CONNECT_SEL, 0x0},
496         /* HP, Line-Out, Surround, CLFE, Mono pins; mute as default */
497         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
498         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
499         {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
500         {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
501         {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
502         /* HP Pin */
503         {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
504         /* Front, Surround, CLFE Pins */
505         {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
506         {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
507         {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
508         /* Mono Pin */
509         {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
510         /* Mic Pin */
511         {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
512         /* Line, Aux, CD, Beep-In Pin */
513         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
514         {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
515         {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
516         {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
517         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
518         { } /* end */
519 };
520
521
522 static int patch_ad1986a(struct hda_codec *codec)
523 {
524         struct ad198x_spec *spec;
525
526         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
527         if (spec == NULL)
528                 return -ENOMEM;
529
530         init_MUTEX(&spec->amp_mutex);
531         codec->spec = spec;
532
533         spec->multiout.max_channels = 6;
534         spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
535         spec->multiout.dac_nids = ad1986a_dac_nids;
536         spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
537         spec->num_adc_nids = 1;
538         spec->adc_nids = ad1986a_adc_nids;
539         spec->input_mux = &ad1986a_capture_source;
540         spec->num_mixers = 1;
541         spec->mixers[0] = ad1986a_mixers;
542         spec->num_init_verbs = 1;
543         spec->init_verbs[0] = ad1986a_init_verbs;
544
545         codec->patch_ops = ad198x_patch_ops;
546
547         return 0;
548 }
549
550 /*
551  * AD1983 specific
552  */
553
554 #define AD1983_SPDIF_OUT        0x02
555 #define AD1983_DAC              0x03
556 #define AD1983_ADC              0x04
557
558 static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
559 static hda_nid_t ad1983_adc_nids[1] = { AD1983_ADC };
560
561 static struct hda_input_mux ad1983_capture_source = {
562         .num_items = 4,
563         .items = {
564                 { "Mic", 0x0 },
565                 { "Line", 0x1 },
566                 { "Mix", 0x2 },
567                 { "Mix Mono", 0x3 },
568         },
569 };
570
571 /*
572  * SPDIF playback route
573  */
574 static int ad1983_spdif_route_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
575 {
576         static char *texts[] = { "PCM", "ADC" };
577
578         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
579         uinfo->count = 1;
580         uinfo->value.enumerated.items = 2;
581         if (uinfo->value.enumerated.item > 1)
582                 uinfo->value.enumerated.item = 1;
583         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
584         return 0;
585 }
586
587 static int ad1983_spdif_route_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
588 {
589         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
590         struct ad198x_spec *spec = codec->spec;
591
592         ucontrol->value.enumerated.item[0] = spec->spdif_route;
593         return 0;
594 }
595
596 static int ad1983_spdif_route_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
597 {
598         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
599         struct ad198x_spec *spec = codec->spec;
600
601         if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
602                 spec->spdif_route = ucontrol->value.enumerated.item[0];
603                 snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0,
604                                     AC_VERB_SET_CONNECT_SEL, spec->spdif_route);
605                 return 1;
606         }
607         return 0;
608 }
609
610 static struct snd_kcontrol_new ad1983_mixers[] = {
611         HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
612         HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
613         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
614         HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
615         HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
616         HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
617         HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
618         HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
619         HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
620         HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
621         HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
622         HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
623         HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
624         HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
625         HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
626         HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
627         HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
628         {
629                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
630                 .name = "Capture Source",
631                 .info = ad198x_mux_enum_info,
632                 .get = ad198x_mux_enum_get,
633                 .put = ad198x_mux_enum_put,
634         },
635         {
636                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
637                 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
638                 .info = ad1983_spdif_route_info,
639                 .get = ad1983_spdif_route_get,
640                 .put = ad1983_spdif_route_put,
641         },
642         { } /* end */
643 };
644
645 static struct hda_verb ad1983_init_verbs[] = {
646         /* Front, HP, Mono; mute as default */
647         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
648         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
649         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
650         /* Beep, PCM, Mic, Line-In: mute */
651         {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
652         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
653         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
654         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
655         /* Front, HP selectors; from Mix */
656         {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
657         {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
658         /* Mono selector; from Mix */
659         {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
660         /* Mic selector; Mic */
661         {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
662         /* Line-in selector: Line-in */
663         {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
664         /* Mic boost: 0dB */
665         {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
666         /* Record selector: mic */
667         {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
668         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
669         /* SPDIF route: PCM */
670         {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
671         /* Front Pin */
672         {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
673         /* HP Pin */
674         {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
675         /* Mono Pin */
676         {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
677         /* Mic Pin */
678         {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
679         /* Line Pin */
680         {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
681         { } /* end */
682 };
683
684
685 static int patch_ad1983(struct hda_codec *codec)
686 {
687         struct ad198x_spec *spec;
688
689         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
690         if (spec == NULL)
691                 return -ENOMEM;
692
693         init_MUTEX(&spec->amp_mutex);
694         codec->spec = spec;
695
696         spec->multiout.max_channels = 2;
697         spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
698         spec->multiout.dac_nids = ad1983_dac_nids;
699         spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
700         spec->num_adc_nids = 1;
701         spec->adc_nids = ad1983_adc_nids;
702         spec->input_mux = &ad1983_capture_source;
703         spec->num_mixers = 1;
704         spec->mixers[0] = ad1983_mixers;
705         spec->num_init_verbs = 1;
706         spec->init_verbs[0] = ad1983_init_verbs;
707         spec->spdif_route = 0;
708
709         codec->patch_ops = ad198x_patch_ops;
710
711         return 0;
712 }
713
714
715 /*
716  * AD1981 HD specific
717  */
718
719 #define AD1981_SPDIF_OUT        0x02
720 #define AD1981_DAC              0x03
721 #define AD1981_ADC              0x04
722
723 static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
724 static hda_nid_t ad1981_adc_nids[1] = { AD1981_ADC };
725
726 /* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
727 static struct hda_input_mux ad1981_capture_source = {
728         .num_items = 7,
729         .items = {
730                 { "Front Mic", 0x0 },
731                 { "Line", 0x1 },
732                 { "Mix", 0x2 },
733                 { "Mix Mono", 0x3 },
734                 { "CD", 0x4 },
735                 { "Mic", 0x6 },
736                 { "Aux", 0x7 },
737         },
738 };
739
740 static struct snd_kcontrol_new ad1981_mixers[] = {
741         HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
742         HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
743         HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
744         HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
745         HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
746         HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
747         HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
748         HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
749         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
750         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
751         HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
752         HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
753         HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
754         HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
755         HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
756         HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
757         HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
758         HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
759         HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
760         HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
761         HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
762         HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
763         HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
764         HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
765         {
766                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
767                 .name = "Capture Source",
768                 .info = ad198x_mux_enum_info,
769                 .get = ad198x_mux_enum_get,
770                 .put = ad198x_mux_enum_put,
771         },
772         /* identical with AD1983 */
773         {
774                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
775                 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
776                 .info = ad1983_spdif_route_info,
777                 .get = ad1983_spdif_route_get,
778                 .put = ad1983_spdif_route_put,
779         },
780         { } /* end */
781 };
782
783 static struct hda_verb ad1981_init_verbs[] = {
784         /* Front, HP, Mono; mute as default */
785         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
786         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
787         {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
788         /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
789         {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
790         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
791         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
792         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
793         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
794         {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
795         {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
796         /* Front, HP selectors; from Mix */
797         {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
798         {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
799         /* Mono selector; from Mix */
800         {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
801         /* Mic Mixer; select Front Mic */
802         {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
803         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
804         /* Mic boost: 0dB */
805         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
806         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
807         /* Record selector: Front mic */
808         {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
809         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
810         /* SPDIF route: PCM */
811         {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
812         /* Front Pin */
813         {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
814         /* HP Pin */
815         {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
816         /* Mono Pin */
817         {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
818         /* Front & Rear Mic Pins */
819         {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
820         {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
821         /* Line Pin */
822         {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
823         /* Digital Beep */
824         {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
825         /* Line-Out as Input: disabled */
826         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
827         { } /* end */
828 };
829
830 static int patch_ad1981(struct hda_codec *codec)
831 {
832         struct ad198x_spec *spec;
833
834         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
835         if (spec == NULL)
836                 return -ENOMEM;
837
838         init_MUTEX(&spec->amp_mutex);
839         codec->spec = spec;
840
841         spec->multiout.max_channels = 2;
842         spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
843         spec->multiout.dac_nids = ad1981_dac_nids;
844         spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
845         spec->num_adc_nids = 1;
846         spec->adc_nids = ad1981_adc_nids;
847         spec->input_mux = &ad1981_capture_source;
848         spec->num_mixers = 1;
849         spec->mixers[0] = ad1981_mixers;
850         spec->num_init_verbs = 1;
851         spec->init_verbs[0] = ad1981_init_verbs;
852         spec->spdif_route = 0;
853
854         codec->patch_ops = ad198x_patch_ops;
855
856         return 0;
857 }
858
859
860 /*
861  * AD1988
862  *
863  * Output pins and routes
864  *
865  *        Pin               Mix     Sel     DAC
866  * port-A 0x11 (mute/hp) <- 0x22 <- 0x37 <- 03/04/06
867  * port-B 0x14 (mute/hp) <- 0x2b <- 0x30 <- 03/04/06
868  * port-C 0x15 (mute)    <- 0x2c <- 0x31 <- 05/0a
869  * port-D 0x12 (mute/hp) <- 0x29         <- 04
870  * port-E 0x17 (mute/hp) <- 0x26 <- 0x32 <- 05/0a
871  * port-F 0x16 (mute)    <- 0x2a         <- 06
872  * port-G 0x24 (mute)    <- 0x27         <- 05
873  * port-H 0x25 (mute)    <- 0x28         <- 0a
874  * mono   0x13 (mute/amp)<- 0x1e <- 0x36 <- 03/04/06
875  *
876  *
877  * Input pins and routes
878  *
879  *        pin     boost   mix input # / adc input #
880  * port-A 0x11 -> 0x38 -> mix 2, ADC 0
881  * port-B 0x14 -> 0x39 -> mix 0, ADC 1
882  * port-C 0x15 -> 0x3a -> 33:0 - mix 1, ADC 2
883  * port-D 0x12 -> 0x3d -> mix 3, ADC 8
884  * port-E 0x17 -> 0x3c -> 34:0 - mix 4, ADC 4
885  * port-F 0x16 -> 0x3b -> mix 5, ADC 3
886  * port-G 0x24 -> N/A  -> 33:1 - mix 1, 34:1 - mix 4, ADC 6
887  * port-H 0x25 -> N/A  -> 33:2 - mix 1, 34:2 - mix 4, ADC 7
888  *
889  *
890  * DAC assignment
891  *   front DAC - 04
892  *   surr DAC  - 06
893  *   CLFE DAC  - 05
894  *   side DAC  - 0a
895  *   opt DAC   - 03
896  *
897  * Inputs of Analog Mix (0x20)
898  *   0:Port-B (front mic)
899  *   1:Port-C/G/H (line-in)
900  *   2:Port-A
901  *   3:Port-D (line-in/2)
902  *   4:Port-E/G/H (mic-in)
903  *   5:Port-F (mic2-in)
904  *   6:CD
905  *   7:Beep
906  *
907  * ADC selection
908  *   0:Port-A
909  *   1:Port-B (front mic-in)
910  *   2:Port-C (line-in)
911  *   3:Port-F (mic2-in)
912  *   4:Port-E (mic-in)
913  *   5:CD
914  *   6:Port-G
915  *   7:Port-H
916  *   8:Port-D (line-in/2)
917  *   9:Mix
918  *
919  * Proposed pin assignments by the datasheet
920  *
921  * 6-stack
922  * Port-A front headphone
923  *      B front mic-in
924  *      C rear line-in
925  *      D rear front-out
926  *      E rear mic-in
927  *      F rear surround
928  *      G rear CLFE
929  *      H rear side
930  *
931  * 3-stack
932  * Port-A front headphone
933  *      B front mic
934  *      C rear line-in/surround
935  *      D rear front-out
936  *      E rear mic-in/CLFE
937  *
938  * laptop
939  * Port-A headphone
940  *      B mic-in
941  *      C docking station
942  *      D internal speaker (with EAPD)
943  *      E/F quad mic array
944  */
945
946
947 /* models */
948 enum {
949         AD1988_6STACK,
950         AD1988_6STACK_DIG,
951         AD1988_3STACK,
952         AD1988_3STACK_DIG,
953         AD1988_LAPTOP,
954         AD1988_LAPTOP_DIG,
955         AD1988_MODEL_LAST,
956 };
957
958
959 /*
960  * mixers
961  */
962
963 static hda_nid_t ad1988_dac_nids[4] = {
964         0x04, 0x06, 0x05, 0x0a
965 };
966
967 static hda_nid_t ad1988_adc_nids[3] = {
968         0x08, 0x09, 0x0f
969 };
970
971 #define AD1988_SPDIF_OUT        0x02
972 #define AD1988_SPDIF_IN         0x07
973
974 static struct hda_input_mux ad1988_6stack_capture_source = {
975         .num_items = 5,
976         .items = {
977                 { "Front Mic", 0x0 },
978                 { "Line", 0x1 },
979                 { "Mic", 0x4 },
980                 { "CD", 0x5 },
981                 { "Mix", 0x9 },
982         },
983 };
984
985 static struct hda_input_mux ad1988_laptop_capture_source = {
986         .num_items = 3,
987         .items = {
988                 { "Mic/Line", 0x0 },
989                 { "CD", 0x5 },
990                 { "Mix", 0x9 },
991         },
992 };
993
994 /*
995  */
996 static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
997                                struct snd_ctl_elem_info *uinfo)
998 {
999         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1000         struct ad198x_spec *spec = codec->spec;
1001         return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
1002                                     spec->num_channel_mode);
1003 }
1004
1005 static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
1006                               struct snd_ctl_elem_value *ucontrol)
1007 {
1008         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1009         struct ad198x_spec *spec = codec->spec;
1010         return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
1011                                    spec->num_channel_mode, spec->multiout.max_channels);
1012 }
1013
1014 static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
1015                               struct snd_ctl_elem_value *ucontrol)
1016 {
1017         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1018         struct ad198x_spec *spec = codec->spec;
1019         return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
1020                                    spec->num_channel_mode, &spec->multiout.max_channels);
1021 }
1022
1023 /*
1024  * EAPD control
1025  */
1026 static int ad1988_eapd_info(struct snd_kcontrol *kcontrol,
1027                             struct snd_ctl_elem_info *uinfo)
1028 {
1029         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1030         uinfo->count = 1;
1031         uinfo->value.integer.min = 0;
1032         uinfo->value.integer.max = 1;
1033         return 0;
1034 }
1035
1036 static int ad1988_eapd_get(struct snd_kcontrol *kcontrol,
1037                            struct snd_ctl_elem_value *ucontrol)
1038 {
1039         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1040         struct ad198x_spec *spec = codec->spec;
1041         ucontrol->value.enumerated.item[0] = ! spec->cur_eapd;
1042         return 0;
1043 }
1044
1045 static int ad1988_eapd_put(struct snd_kcontrol *kcontrol,
1046                            struct snd_ctl_elem_value *ucontrol)
1047 {
1048         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1049         struct ad198x_spec *spec = codec->spec;
1050         unsigned int eapd;
1051         eapd = ! ucontrol->value.enumerated.item[0];
1052         if (eapd == spec->cur_eapd && ! codec->in_resume)
1053                 return 0;
1054         spec->cur_eapd = eapd;
1055         snd_hda_codec_write(codec, 0x12 /* port-D */,
1056                             0, AC_VERB_SET_EAPD_BTLENABLE,
1057                             eapd ? 0x02 : 0x00);
1058         return 0;
1059 }
1060
1061 /* 6-stack mode */
1062 static struct snd_kcontrol_new ad1988_6stack_mixers[] = {
1063         HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1064         HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1065         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1066         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1067         HDA_CODEC_VOLUME("Side Playback Volume", 0x0a, 0x0, HDA_OUTPUT),
1068
1069         HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1070         HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1071         HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1072         HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1073         HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
1074         HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1075         HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1076
1077         HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1078         HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1079         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1080         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1081         HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1082         HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1083         HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1084         HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1085
1086         HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1087         HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1088
1089         HDA_CODEC_VOLUME("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1090         HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1091
1092         HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1093         HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1094
1095         { } /* end */
1096 };
1097
1098 /* 3-stack mode */
1099 static struct snd_kcontrol_new ad1988_3stack_mixers[] = {
1100         HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1101         HDA_CODEC_VOLUME("Surround Playback Volume", 0x06, 0x0, HDA_OUTPUT),
1102         HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT),
1103         HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT),
1104
1105         HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
1106         HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
1107         HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
1108         HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
1109         HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
1110         HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1111
1112         HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1113         HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1114         HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1115         HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1116         HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1117         HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1118         HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
1119         HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
1120
1121         HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1122         HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1123
1124         HDA_CODEC_VOLUME("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1125         HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1126
1127         HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1128         HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT),
1129         {
1130                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1131                 .name = "Channel Mode",
1132                 .info = ad198x_ch_mode_info,
1133                 .get = ad198x_ch_mode_get,
1134                 .put = ad198x_ch_mode_put,
1135         },
1136
1137         { } /* end */
1138 };
1139
1140 /* laptop mode */
1141 static struct snd_kcontrol_new ad1988_laptop_mixers[] = {
1142         HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
1143         HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
1144         HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
1145
1146         HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
1147         HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
1148         HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
1149         HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
1150         HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
1151         HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
1152
1153         HDA_CODEC_VOLUME("Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT),
1154         HDA_CODEC_MUTE("Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT),
1155
1156         HDA_CODEC_VOLUME("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1157         HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
1158
1159         HDA_CODEC_VOLUME("Mic Boost", 0x39, 0x0, HDA_OUTPUT),
1160
1161         {
1162                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1163                 .name = "External Amplifier",
1164                 .info = ad1988_eapd_info,
1165                 .get = ad1988_eapd_get,
1166                 .put = ad1988_eapd_put,
1167         },
1168
1169         { } /* end */
1170 };
1171
1172 /* capture */
1173 static struct snd_kcontrol_new ad1988_capture_mixers[] = {
1174         HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
1175         HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
1176         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT),
1177         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT),
1178         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x0e, 0x0, HDA_OUTPUT),
1179         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x0e, 0x0, HDA_OUTPUT),
1180         {
1181                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1182                 /* The multiple "Capture Source" controls confuse alsamixer
1183                  * So call somewhat different..
1184                  * FIXME: the controls appear in the "playback" view!
1185                  */
1186                 /* .name = "Capture Source", */
1187                 .name = "Input Source",
1188                 .count = 3,
1189                 .info = ad198x_mux_enum_info,
1190                 .get = ad198x_mux_enum_get,
1191                 .put = ad198x_mux_enum_put,
1192         },
1193         { } /* end */
1194 };
1195
1196 static int ad1988_spdif_playback_source_info(struct snd_kcontrol *kcontrol,
1197                                              struct snd_ctl_elem_info *uinfo)
1198 {
1199         static char *texts[] = {
1200                 "PCM", "ADC1", "ADC2", "ADC3"
1201         };
1202         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1203         uinfo->count = 1;
1204         uinfo->value.enumerated.items = 4;
1205         if (uinfo->value.enumerated.item >= 4)
1206                 uinfo->value.enumerated.item = 3;
1207         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1208         return 0;
1209 }
1210
1211 static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
1212                                             struct snd_ctl_elem_value *ucontrol)
1213 {
1214         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1215         unsigned int sel;
1216
1217         sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
1218         if (sel > 0) {
1219                 sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0);
1220                 if (sel <= 3)
1221                         sel++;
1222                 else
1223                         sel = 0;
1224         }
1225         ucontrol->value.enumerated.item[0] = sel;
1226         return 0;
1227 }
1228
1229 static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
1230                                             struct snd_ctl_elem_value *ucontrol)
1231 {
1232         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1233         unsigned int sel;
1234         int change;
1235
1236         sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
1237         if (! ucontrol->value.enumerated.item[0]) {
1238                 change = sel != 0;
1239                 if (change)
1240                         snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 0);
1241         } else {
1242                 change = sel == 0;
1243                 if (change)
1244                         snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 1);
1245                 sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0) + 1;
1246                 change |= sel == ucontrol->value.enumerated.item[0];
1247                 if (change)
1248                         snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL,
1249                                             ucontrol->value.enumerated.item[0] - 1);
1250         }
1251         return change;
1252 }
1253
1254 static struct snd_kcontrol_new ad1988_spdif_out_mixers[] = {
1255         HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
1256         {
1257                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1258                 .name = "IEC958 Playback Source",
1259                 .info = ad1988_spdif_playback_source_info,
1260                 .get = ad1988_spdif_playback_source_get,
1261                 .put = ad1988_spdif_playback_source_put,
1262         },
1263         { } /* end */
1264 };
1265
1266 static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = {
1267         HDA_CODEC_VOLUME("IEC958 Capture Volume", 0x1c, 0x0, HDA_INPUT),
1268         { } /* end */
1269 };
1270
1271
1272 /*
1273  * initialization verbs
1274  */
1275
1276 /*
1277  * for 6-stack (+dig)
1278  */
1279 static struct hda_verb ad1988_6stack_init_verbs[] = {
1280         /* Front, Surround, CLFE, side DAC; mute as default */
1281         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1282         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1283         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1284         {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1285         /* Port-A front headphon path */
1286         {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1287         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1288         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1289         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1290         {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1291         /* Port-D line-out path */
1292         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1293         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1294         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1295         {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1296         /* Port-F surround path */
1297         {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1298         {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1299         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1300         {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1301         /* Port-G CLFE path */
1302         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1303         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1304         {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1305         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1306         /* Port-H side path */
1307         {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1308         {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1309         {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1310         {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1311         /* Mono out path */
1312         {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1313         {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1314         {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1315         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1316         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1317         /* Port-B front mic-in path */
1318         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1319         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1320         {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1321         /* Port-C line-in path */
1322         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1323         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1324         {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1325         {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1326         /* Port-E mic-in path */
1327         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1328         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1329         {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1330         {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
1331
1332         { }
1333 };
1334
1335 static struct hda_verb ad1988_capture_init_verbs[] = {
1336         /* mute analog mix */
1337         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1338         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1339         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1340         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1341         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1342         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1343         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1344         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1345         /* select ADCs - front-mic */
1346         {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1347         {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1348         {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1349         /* ADCs; muted */
1350         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1351         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1352         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1353
1354         { }
1355 };
1356
1357 static struct hda_verb ad1988_spdif_init_verbs[] = {
1358         /* SPDIF out sel */
1359         {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */
1360         {0x0b, AC_VERB_SET_CONNECT_SEL, 0x0}, /* ADC1 */
1361         {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1362         {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1363         /* SPDIF out pin */
1364         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */
1365         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x17}, /* 0dB */
1366
1367         { }
1368 };
1369
1370 /*
1371  * verbs for 3stack (+dig)
1372  */
1373 static struct hda_verb ad1988_3stack_ch2_init[] = {
1374         /* set port-C to line-in */
1375         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1376         { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1377         /* set port-E to mic-in */
1378         { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1379         { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
1380         { } /* end */
1381 };
1382
1383 static struct hda_verb ad1988_3stack_ch6_init[] = {
1384         /* set port-C to surround out */
1385         { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1386         { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1387         /* set port-E to CLFE out */
1388         { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1389         { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1390         { } /* end */
1391 };
1392
1393 static struct hda_channel_mode ad1988_3stack_modes[2] = {
1394         { 2, ad1988_3stack_ch2_init },
1395         { 6, ad1988_3stack_ch6_init },
1396 };
1397
1398 static struct hda_verb ad1988_3stack_init_verbs[] = {
1399         /* Front, Surround, CLFE, side DAC; mute as default */
1400         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1401         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1402         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1403         {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1404         /* Port-A front headphon path */
1405         {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1406         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1407         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1408         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1409         {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1410         /* Port-D line-out path */
1411         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1412         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1413         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1414         {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1415         /* Mono out path */
1416         {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1417         {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1418         {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1419         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1420         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1421         /* Port-B front mic-in path */
1422         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1423         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1424         {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1425         /* Port-C line-in/surround path */
1426         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1427         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1428         {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1429         {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1430         /* Port-E mic-in/CLFE path */
1431         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1432         {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1433         {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1434         {0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
1435         /* mute analog mix */
1436         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1437         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1438         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1439         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1440         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1441         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1442         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1443         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1444         /* select ADCs - front-mic */
1445         {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1446         {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1447         {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1448         /* ADCs; muted */
1449         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1450         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1451         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1452         { }
1453 };
1454
1455 /*
1456  * verbs for laptop mode (+dig)
1457  */
1458 static struct hda_verb ad1988_laptop_hp_on[] = {
1459         /* unmute port-A and mute port-D */
1460         { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1461         { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1462         { } /* end */
1463 };
1464 static struct hda_verb ad1988_laptop_hp_off[] = {
1465         /* mute port-A and unmute port-D */
1466         { 0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
1467         { 0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
1468         { } /* end */
1469 };
1470
1471 #define AD1988_HP_EVENT 0x01
1472
1473 static struct hda_verb ad1988_laptop_init_verbs[] = {
1474         /* Front, Surround, CLFE, side DAC; mute as default */
1475         {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1476         {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1477         {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1478         {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1479         /* Port-A front headphon path */
1480         {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
1481         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1482         {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1483         {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1484         {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1485         /* unsolicited event for pin-sense */
1486         {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1988_HP_EVENT },
1487         /* Port-D line-out path + EAPD */
1488         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1489         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1490         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1491         {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1492         {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, /* EAPD-off */
1493         /* Mono out path */
1494         {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
1495         {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1496         {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1497         {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1498         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
1499         /* Port-B mic-in path */
1500         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1501         {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1502         {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1503         /* Port-C docking station - try to output */
1504         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1505         {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1506         {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1507         {0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
1508         /* mute analog mix */
1509         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1510         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1511         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
1512         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
1513         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
1514         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
1515         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
1516         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
1517         /* select ADCs - mic */
1518         {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
1519         {0x0d, AC_VERB_SET_CONNECT_SEL, 0x1},
1520         {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1},
1521         /* ADCs; muted */
1522         {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1523         {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1524         {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1525         { }
1526 };
1527
1528 static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res)
1529 {
1530         if ((res >> 26) != AD1988_HP_EVENT)
1531                 return;
1532         if (snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) & (1 << 31))
1533                 snd_hda_sequence_write(codec, ad1988_laptop_hp_on);
1534         else
1535                 snd_hda_sequence_write(codec, ad1988_laptop_hp_off);
1536
1537
1538
1539 /*
1540  */
1541
1542 static struct hda_board_config ad1988_cfg_tbl[] = {
1543         { .modelname = "6stack",        .config = AD1988_6STACK },
1544         { .modelname = "6stack-dig",    .config = AD1988_6STACK_DIG },
1545         { .modelname = "3stack",        .config = AD1988_3STACK },
1546         { .modelname = "3stack-dig",    .config = AD1988_3STACK_DIG },
1547         { .modelname = "laptop",        .config = AD1988_LAPTOP },
1548         { .modelname = "laptop-dig",    .config = AD1988_LAPTOP_DIG },
1549         {}
1550 };
1551
1552 static int patch_ad1988(struct hda_codec *codec)
1553 {
1554         struct ad198x_spec *spec;
1555         int board_config;
1556
1557         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1558         if (spec == NULL)
1559                 return -ENOMEM;
1560
1561         init_MUTEX(&spec->amp_mutex);
1562         codec->spec = spec;
1563
1564         board_config = snd_hda_check_board_config(codec, ad1988_cfg_tbl);
1565         if (board_config < 0 || board_config >= AD1988_MODEL_LAST) {
1566                 printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
1567                 board_config = AD1988_6STACK;
1568         }
1569
1570         switch (board_config) {
1571         case AD1988_6STACK:
1572         case AD1988_6STACK_DIG:
1573                 spec->multiout.max_channels = 8;
1574                 spec->multiout.num_dacs = 4;
1575                 spec->multiout.dac_nids = ad1988_dac_nids;
1576                 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
1577                 spec->adc_nids = ad1988_adc_nids;
1578                 spec->input_mux = &ad1988_6stack_capture_source;
1579                 spec->num_mixers = 1;
1580                 spec->mixers[0] = ad1988_6stack_mixers;
1581                 spec->num_init_verbs = 1;
1582                 spec->init_verbs[0] = ad1988_6stack_init_verbs;
1583                 if (board_config == AD1988_6STACK_DIG) {
1584                         spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
1585                         spec->dig_in_nid = AD1988_SPDIF_IN;
1586                 }
1587                 break;
1588         case AD1988_3STACK:
1589         case AD1988_3STACK_DIG:
1590                 spec->multiout.max_channels = 6;
1591                 spec->multiout.num_dacs = 3;
1592                 spec->multiout.dac_nids = ad1988_dac_nids;
1593                 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
1594                 spec->adc_nids = ad1988_adc_nids;
1595                 spec->input_mux = &ad1988_6stack_capture_source;
1596                 spec->channel_mode = ad1988_3stack_modes;
1597                 spec->num_channel_mode = ARRAY_SIZE(ad1988_3stack_modes);
1598                 spec->num_mixers = 1;
1599                 spec->mixers[0] = ad1988_3stack_mixers;
1600                 spec->num_init_verbs = 1;
1601                 spec->init_verbs[0] = ad1988_3stack_init_verbs;
1602                 if (board_config == AD1988_3STACK_DIG)
1603                         spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
1604                 break;
1605         case AD1988_LAPTOP:
1606         case AD1988_LAPTOP_DIG:
1607                 spec->multiout.max_channels = 2;
1608                 spec->multiout.num_dacs = 1;
1609                 spec->multiout.dac_nids = ad1988_dac_nids;
1610                 spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
1611                 spec->adc_nids = ad1988_adc_nids;
1612                 spec->input_mux = &ad1988_laptop_capture_source;
1613                 spec->num_mixers = 1;
1614                 spec->mixers[0] = ad1988_laptop_mixers;
1615                 spec->num_init_verbs = 1;
1616                 spec->init_verbs[0] = ad1988_laptop_init_verbs;
1617                 if (board_config == AD1988_LAPTOP_DIG)
1618                         spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
1619                 break;
1620         }
1621
1622         spec->mixers[spec->num_mixers++] = ad1988_capture_mixers;
1623         spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs;
1624         if (spec->multiout.dig_out_nid) {
1625                 spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers;
1626                 spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs;
1627         }
1628         if (spec->dig_in_nid)
1629                 spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers;
1630
1631         codec->patch_ops = ad198x_patch_ops;
1632         switch (board_config) {
1633         case AD1988_LAPTOP:
1634         case AD1988_LAPTOP_DIG:
1635                 codec->patch_ops.unsol_event = ad1988_laptop_unsol_event;
1636                 break;
1637         }
1638
1639         return 0;
1640 }
1641
1642
1643 /*
1644  * patch entries
1645  */
1646 struct hda_codec_preset snd_hda_preset_analog[] = {
1647         { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
1648         { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
1649         { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
1650         { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 },
1651         {} /* terminator */
1652 };