Merge branch 'for-linus' of master.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband
[pandora-kernel.git] / sound / pci / hda / patch_via.c
1 /*
2  * Universal Interface for Intel High Definition Audio Codec
3  *
4  * HD audio interface patch for VIA VT1708 codec
5  *
6  * Copyright (c) 2006 Lydia Wang <lydiawang@viatech.com>
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 /* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
25 /*                                                                           */
26 /* 2006-03-03  Lydia Wang  Create the basic patch to support VT1708 codec    */
27 /* 2006-03-14  Lydia Wang  Modify hard code for some pin widget nid          */
28 /* 2006-08-02  Lydia Wang  Add support to VT1709 codec                       */
29 /* 2006-09-08  Lydia Wang  Fix internal loopback recording source select bug */
30 /*                                                                           */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32
33
34 #include <sound/driver.h>
35 #include <linux/init.h>
36 #include <linux/delay.h>
37 #include <linux/slab.h>
38 #include <sound/core.h>
39 #include "hda_codec.h"
40 #include "hda_local.h"
41
42
43 /* amp values */
44 #define AMP_VAL_IDX_SHIFT       19
45 #define AMP_VAL_IDX_MASK        (0x0f<<19)
46
47 #define NUM_CONTROL_ALLOC       32
48 #define NUM_VERB_ALLOC          32
49
50 /* Pin Widget NID */
51 #define VT1708_HP_NID           0x13
52 #define VT1708_DIGOUT_NID       0x14
53 #define VT1708_DIGIN_NID        0x16
54
55 #define VT1709_HP_DAC_NID       0x28
56 #define VT1709_DIGOUT_NID       0x13
57 #define VT1709_DIGIN_NID        0x17
58
59 #define IS_VT1708_VENDORID(x)           ((x) >= 0x11061708 && (x) <= 0x1106170b)
60 #define IS_VT1709_10CH_VENDORID(x)      ((x) >= 0x1106e710 && (x) <= 0x1106e713)
61 #define IS_VT1709_6CH_VENDORID(x)       ((x) >= 0x1106e714 && (x) <= 0x1106e717)
62
63
64 enum {
65         VIA_CTL_WIDGET_VOL,
66         VIA_CTL_WIDGET_MUTE,
67 };
68
69 enum {
70         AUTO_SEQ_FRONT,
71         AUTO_SEQ_SURROUND,
72         AUTO_SEQ_CENLFE,
73         AUTO_SEQ_SIDE
74 };
75
76 static struct snd_kcontrol_new vt1708_control_templates[] = {
77         HDA_CODEC_VOLUME(NULL, 0, 0, 0),
78         HDA_CODEC_MUTE(NULL, 0, 0, 0),
79 };
80
81
82 struct via_spec {
83         /* codec parameterization */
84         struct snd_kcontrol_new *mixers[3];
85         unsigned int num_mixers;
86
87         struct hda_verb *init_verbs;
88
89         char *stream_name_analog;
90         struct hda_pcm_stream *stream_analog_playback;
91         struct hda_pcm_stream *stream_analog_capture;
92
93         char *stream_name_digital;
94         struct hda_pcm_stream *stream_digital_playback;
95         struct hda_pcm_stream *stream_digital_capture;
96
97         /* playback */
98         struct hda_multi_out multiout;
99
100         /* capture */
101         unsigned int num_adc_nids;
102         hda_nid_t *adc_nids;
103         hda_nid_t dig_in_nid;
104
105         /* capture source */
106         const struct hda_input_mux *input_mux;
107         unsigned int cur_mux[3];
108
109         /* PCM information */
110         struct hda_pcm pcm_rec[2];
111
112         /* dynamic controls, init_verbs and input_mux */
113         struct auto_pin_cfg autocfg;
114         unsigned int num_kctl_alloc, num_kctl_used;
115         struct snd_kcontrol_new *kctl_alloc;
116         struct hda_input_mux private_imux;
117         hda_nid_t private_dac_nids[4];  
118 };
119
120 static hda_nid_t vt1708_adc_nids[2] = {
121         /* ADC1-2 */
122         0x15, 0x27
123 };
124
125 static hda_nid_t vt1709_adc_nids[3] = {
126         /* ADC1-2 */
127         0x14, 0x15, 0x16
128 };
129
130 /* add dynamic controls */
131 static int via_add_control(struct via_spec *spec, int type, const char *name,
132                            unsigned long val)
133 {
134         struct snd_kcontrol_new *knew;
135
136         if (spec->num_kctl_used >= spec->num_kctl_alloc) {
137                 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
138
139                 /* array + terminator */
140                 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
141                 if (!knew)
142                         return -ENOMEM;
143                 if (spec->kctl_alloc) {
144                         memcpy(knew, spec->kctl_alloc,
145                                sizeof(*knew) * spec->num_kctl_alloc);
146                         kfree(spec->kctl_alloc);
147                 }
148                 spec->kctl_alloc = knew;
149                 spec->num_kctl_alloc = num;
150         }
151
152         knew = &spec->kctl_alloc[spec->num_kctl_used];
153         *knew = vt1708_control_templates[type];
154         knew->name = kstrdup(name, GFP_KERNEL);
155
156         if (!knew->name)
157                 return -ENOMEM;
158         knew->private_value = val;
159         spec->num_kctl_used++;
160         return 0;
161 }
162
163 /* create input playback/capture controls for the given pin */
164 static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
165                                 const char *ctlname, int idx, int mix_nid)
166 {
167         char name[32];
168         int err;
169
170         sprintf(name, "%s Playback Volume", ctlname);
171         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
172                               HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
173         if (err < 0)
174                 return err;
175         sprintf(name, "%s Playback Switch", ctlname);
176         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
177                               HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
178         if (err < 0)
179                 return err;
180         return 0;
181 }
182
183 static void via_auto_set_output_and_unmute(struct hda_codec *codec,
184                                            hda_nid_t nid, int pin_type,
185                                            int dac_idx)
186 {
187         /* set as output */
188         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
189                             pin_type);
190         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
191                             AMP_OUT_UNMUTE);
192 }
193
194
195 static void via_auto_init_multi_out(struct hda_codec *codec)
196 {
197         struct via_spec *spec = codec->spec;
198         int i;
199
200         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
201                 hda_nid_t nid = spec->autocfg.line_out_pins[i];
202                 if (nid)
203                         via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
204         }
205 }
206
207 static void via_auto_init_hp_out(struct hda_codec *codec)
208 {
209         struct via_spec *spec = codec->spec;
210         hda_nid_t pin;
211
212         pin = spec->autocfg.hp_pins[0];
213         if (pin) /* connect to front */
214                 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
215 }
216
217 static void via_auto_init_analog_input(struct hda_codec *codec)
218 {
219         struct via_spec *spec = codec->spec;
220         int i;
221
222         for (i = 0; i < AUTO_PIN_LAST; i++) {
223                 hda_nid_t nid = spec->autocfg.input_pins[i];
224
225                 snd_hda_codec_write(codec, nid, 0,
226                                     AC_VERB_SET_PIN_WIDGET_CONTROL,
227                                     (i <= AUTO_PIN_FRONT_MIC ?
228                                      PIN_VREF50 : PIN_IN));
229
230         }
231 }
232 /*
233  * input MUX handling
234  */
235 static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
236                              struct snd_ctl_elem_info *uinfo)
237 {
238         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
239         struct via_spec *spec = codec->spec;
240         return snd_hda_input_mux_info(spec->input_mux, uinfo);
241 }
242
243 static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
244                             struct snd_ctl_elem_value *ucontrol)
245 {
246         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
247         struct via_spec *spec = codec->spec;
248         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
249
250         ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
251         return 0;
252 }
253
254 static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
255                             struct snd_ctl_elem_value *ucontrol)
256 {
257         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
258         struct via_spec *spec = codec->spec;
259         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
260         unsigned int vendor_id = codec->vendor_id;
261
262         /* AIW0  lydia 060801 add for correct sw0 input select */
263         if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
264                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
265                                              0x18, &spec->cur_mux[adc_idx]);
266         else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
267                   IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0) )
268                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
269                                              0x19, &spec->cur_mux[adc_idx]);
270         else
271                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
272                                              spec->adc_nids[adc_idx],
273                                              &spec->cur_mux[adc_idx]);
274 }
275
276 /* capture mixer elements */
277 static struct snd_kcontrol_new vt1708_capture_mixer[] = {
278         HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
279         HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
280         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
281         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
282         {
283                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
284                 /* The multiple "Capture Source" controls confuse alsamixer
285                  * So call somewhat different..
286                  * FIXME: the controls appear in the "playback" view!
287                  */
288                 /* .name = "Capture Source", */
289                 .name = "Input Source",
290                 .count = 1,
291                 .info = via_mux_enum_info,
292                 .get = via_mux_enum_get,
293                 .put = via_mux_enum_put,
294         },
295         { } /* end */
296 };
297 /*
298  * generic initialization of ADC, input mixers and output mixers
299  */
300 static struct hda_verb vt1708_volume_init_verbs[] = {
301         /*
302          * Unmute ADC0-1 and set the default input to mic-in
303          */
304         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
305         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
306
307
308         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
309          * mixer widget
310          */
311         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
312         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
313         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
314         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
315         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
316         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
317
318         /*
319          * Set up output mixers (0x19 - 0x1b)
320          */
321         /* set vol=0 to output mixers */
322         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
323         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
324         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
325         
326         /* Setup default input to PW4 */
327         {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
328         /* Set mic as default input of sw0 */
329         {0x18, AC_VERB_SET_CONNECT_SEL, 0x2},
330         /* PW9 Output enable */
331         {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
332 };
333
334 static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
335                                  struct hda_codec *codec,
336                                  struct snd_pcm_substream *substream)
337 {
338         struct via_spec *spec = codec->spec;
339         return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
340 }
341
342 static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
343                                     struct hda_codec *codec,
344                                     unsigned int stream_tag,
345                                     unsigned int format,
346                                     struct snd_pcm_substream *substream)
347 {
348         struct via_spec *spec = codec->spec;
349         return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
350                                                 stream_tag, format, substream);
351 }
352
353 static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
354                                     struct hda_codec *codec,
355                                     struct snd_pcm_substream *substream)
356 {
357         struct via_spec *spec = codec->spec;
358         return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
359 }
360
361 /*
362  * Digital out
363  */
364 static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
365                                      struct hda_codec *codec,
366                                      struct snd_pcm_substream *substream)
367 {
368         struct via_spec *spec = codec->spec;
369         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
370 }
371
372 static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
373                                       struct hda_codec *codec,
374                                       struct snd_pcm_substream *substream)
375 {
376         struct via_spec *spec = codec->spec;
377         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
378 }
379
380 /*
381  * Analog capture
382  */
383 static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
384                                    struct hda_codec *codec,
385                                    unsigned int stream_tag,
386                                    unsigned int format,
387                                    struct snd_pcm_substream *substream)
388 {
389         struct via_spec *spec = codec->spec;
390
391         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
392                                    stream_tag, 0, format);
393         return 0;
394 }
395
396 static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
397                                    struct hda_codec *codec,
398                                    struct snd_pcm_substream *substream)
399 {
400         struct via_spec *spec = codec->spec;
401         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
402                                    0, 0, 0);
403         return 0;
404 }
405
406 static struct hda_pcm_stream vt1708_pcm_analog_playback = {
407         .substreams = 1,
408         .channels_min = 2,
409         .channels_max = 8,
410         .nid = 0x10, /* NID to query formats and rates */
411         .ops = {
412                 .open = via_playback_pcm_open,
413                 .prepare = via_playback_pcm_prepare,
414                 .cleanup = via_playback_pcm_cleanup
415         },
416 };
417
418 static struct hda_pcm_stream vt1708_pcm_analog_capture = {
419         .substreams = 2,
420         .channels_min = 2,
421         .channels_max = 2,
422         .nid = 0x15, /* NID to query formats and rates */
423         .ops = {
424                 .prepare = via_capture_pcm_prepare,
425                 .cleanup = via_capture_pcm_cleanup
426         },
427 };
428
429 static struct hda_pcm_stream vt1708_pcm_digital_playback = {
430         .substreams = 1,
431         .channels_min = 2,
432         .channels_max = 2,
433         /* NID is set in via_build_pcms */
434         .ops = {
435                 .open = via_dig_playback_pcm_open,
436                 .close = via_dig_playback_pcm_close
437         },
438 };
439
440 static struct hda_pcm_stream vt1708_pcm_digital_capture = {
441         .substreams = 1,
442         .channels_min = 2,
443         .channels_max = 2,
444 };
445
446 static int via_build_controls(struct hda_codec *codec)
447 {
448         struct via_spec *spec = codec->spec;
449         int err;
450         int i;
451
452         for (i = 0; i < spec->num_mixers; i++) {
453                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
454                 if (err < 0)
455                         return err;
456         }
457
458         if (spec->multiout.dig_out_nid) {
459                 err = snd_hda_create_spdif_out_ctls(codec,
460                                                     spec->multiout.dig_out_nid);
461                 if (err < 0)
462                         return err;
463         }
464         if (spec->dig_in_nid) {
465                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
466                 if (err < 0)
467                         return err;
468         }
469         return 0;
470 }
471
472 static int via_build_pcms(struct hda_codec *codec)
473 {
474         struct via_spec *spec = codec->spec;
475         struct hda_pcm *info = spec->pcm_rec;
476
477         codec->num_pcms = 1;
478         codec->pcm_info = info;
479
480         info->name = spec->stream_name_analog;
481         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
482         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
483         info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
484         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
485
486         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
487                 spec->multiout.max_channels;
488
489         if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
490                 codec->num_pcms++;
491                 info++;
492                 info->name = spec->stream_name_digital;
493                 if (spec->multiout.dig_out_nid) {
494                         info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
495                                 *(spec->stream_digital_playback);
496                         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
497                                 spec->multiout.dig_out_nid;
498                 }
499                 if (spec->dig_in_nid) {
500                         info->stream[SNDRV_PCM_STREAM_CAPTURE] =
501                                 *(spec->stream_digital_capture);
502                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
503                                 spec->dig_in_nid;
504                 }
505         }
506
507         return 0;
508 }
509
510 static void via_free(struct hda_codec *codec)
511 {
512         struct via_spec *spec = codec->spec;
513         unsigned int i;
514
515         if (!spec)
516                 return;
517
518         if (spec->kctl_alloc) {
519                 for (i = 0; i < spec->num_kctl_used; i++)
520                         kfree(spec->kctl_alloc[i].name);
521                 kfree(spec->kctl_alloc);
522         }
523
524         kfree(codec->spec);
525 }
526
527 static int via_init(struct hda_codec *codec)
528 {
529         struct via_spec *spec = codec->spec;
530         snd_hda_sequence_write(codec, spec->init_verbs);
531         return 0;
532 }
533
534 #ifdef CONFIG_PM
535 /*
536  * resume
537  */
538 static int via_resume(struct hda_codec *codec)
539 {
540         struct via_spec *spec = codec->spec;
541         int i;
542
543         via_init(codec);
544         for (i = 0; i < spec->num_mixers; i++)
545                 snd_hda_resume_ctls(codec, spec->mixers[i]);
546         if (spec->multiout.dig_out_nid)
547                 snd_hda_resume_spdif_out(codec);
548         if (spec->dig_in_nid)
549                 snd_hda_resume_spdif_in(codec);
550
551         return 0;
552 }
553 #endif
554
555 /*
556  */
557 static struct hda_codec_ops via_patch_ops = {
558         .build_controls = via_build_controls,
559         .build_pcms = via_build_pcms,
560         .init = via_init,
561         .free = via_free,
562 #ifdef CONFIG_PM
563         .resume = via_resume,
564 #endif
565 };
566
567 /* fill in the dac_nids table from the parsed pin configuration */
568 static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
569                                      const struct auto_pin_cfg *cfg)
570 {
571         int i;
572         hda_nid_t nid;
573
574         spec->multiout.num_dacs = cfg->line_outs;
575
576         spec->multiout.dac_nids = spec->private_dac_nids;
577         
578         for(i = 0; i < 4; i++) {
579                 nid = cfg->line_out_pins[i];
580                 if (nid) {
581                         /* config dac list */
582                         switch (i) {
583                         case AUTO_SEQ_FRONT:
584                                 spec->multiout.dac_nids[i] = 0x10;
585                                 break;
586                         case AUTO_SEQ_CENLFE:
587                                 spec->multiout.dac_nids[i] = 0x12;
588                                 break;
589                         case AUTO_SEQ_SURROUND:
590                                 spec->multiout.dac_nids[i] = 0x13;
591                                 break;
592                         case AUTO_SEQ_SIDE:
593                                 spec->multiout.dac_nids[i] = 0x11;
594                                 break;
595                         }
596                 }
597         }
598
599         return 0;
600 }
601
602 /* add playback controls from the parsed DAC table */
603 static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
604                                              const struct auto_pin_cfg *cfg)
605 {
606         char name[32];
607         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
608         hda_nid_t nid, nid_vol = 0;
609         int i, err;
610
611         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
612                 nid = cfg->line_out_pins[i];
613
614                 if (!nid)
615                         continue;
616                 
617                 if (i != AUTO_SEQ_FRONT)
618                         nid_vol = 0x1b - i + 1;
619
620                 if (i == AUTO_SEQ_CENLFE) {
621                         /* Center/LFE */
622                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
623                                               "Center Playback Volume",
624                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
625                         if (err < 0)
626                                 return err;
627                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
628                                               "LFE Playback Volume",
629                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
630                         if (err < 0)
631                                 return err;
632                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
633                                               "Center Playback Switch",
634                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
635                         if (err < 0)
636                                 return err;
637                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
638                                               "LFE Playback Switch",
639                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
640                         if (err < 0)
641                                 return err;
642                 } else if (i == AUTO_SEQ_FRONT){
643                         /* add control to mixer index 0 */
644                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
645                                               "Master Front Playback Volume",
646                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
647                         if (err < 0)
648                                 return err;
649                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
650                                               "Master Front Playback Switch",
651                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
652                         if (err < 0)
653                                 return err;
654                         
655                         /* add control to PW3 */
656                         sprintf(name, "%s Playback Volume", chname[i]);
657                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
658                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
659                         if (err < 0)
660                                 return err;
661                         sprintf(name, "%s Playback Switch", chname[i]);
662                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
663                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
664                         if (err < 0)
665                                 return err;
666                 } else {
667                         sprintf(name, "%s Playback Volume", chname[i]);
668                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
669                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
670                         if (err < 0)
671                                 return err;
672                         sprintf(name, "%s Playback Switch", chname[i]);
673                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
674                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
675                         if (err < 0)
676                                 return err;
677                 }
678         }
679
680         return 0;
681 }
682
683 static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
684 {
685         int err;
686
687         if (!pin)
688                 return 0;
689
690         spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
691
692         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
693                               "Headphone Playback Volume",
694                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
695         if (err < 0)
696                 return err;
697         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
698                               "Headphone Playback Switch",
699                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
700         if (err < 0)
701                 return err;
702
703         return 0;
704 }
705
706 /* create playback/capture controls for input pins */
707 static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
708                                                 const struct auto_pin_cfg *cfg)
709 {
710         static char *labels[] = {
711                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
712         };
713         struct hda_input_mux *imux = &spec->private_imux;
714         int i, err, idx = 0;
715
716         /* for internal loopback recording select */
717         imux->items[imux->num_items].label = "Stereo Mixer";
718         imux->items[imux->num_items].index = idx;
719         imux->num_items++;
720
721         for (i = 0; i < AUTO_PIN_LAST; i++) {
722                 if (!cfg->input_pins[i])
723                         continue;
724
725                 switch (cfg->input_pins[i]) {
726                 case 0x1d: /* Mic */
727                         idx = 2;
728                         break;
729                                 
730                 case 0x1e: /* Line In */
731                         idx = 3;
732                         break;
733
734                 case 0x21: /* Front Mic */
735                         idx = 4;
736                         break;
737
738                 case 0x24: /* CD */
739                         idx = 1;
740                         break;
741                 }
742                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
743                                            idx, 0x17);
744                 if (err < 0)
745                         return err;
746                 imux->items[imux->num_items].label = labels[i];
747                 imux->items[imux->num_items].index = idx;
748                 imux->num_items++;
749         }
750         return 0;
751 }
752
753 static int vt1708_parse_auto_config(struct hda_codec *codec)
754 {
755         struct via_spec *spec = codec->spec;
756         int err;
757
758         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
759         if (err < 0)
760                 return err;
761         err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
762         if (err < 0)
763                 return err;
764         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
765                 return 0; /* can't find valid BIOS pin config */
766
767         err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
768         if (err < 0)
769                 return err;
770         err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
771         if (err < 0)
772                 return err;
773         err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
774         if (err < 0)
775                 return err;
776
777         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
778
779         if (spec->autocfg.dig_out_pin)
780                 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
781         if (spec->autocfg.dig_in_pin)
782                 spec->dig_in_nid = VT1708_DIGIN_NID;
783
784         if (spec->kctl_alloc)
785                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
786
787         spec->init_verbs = vt1708_volume_init_verbs;    
788
789         spec->input_mux = &spec->private_imux;
790
791         return 1;
792 }
793
794 /* init callback for auto-configuration model -- overriding the default init */
795 static int via_auto_init(struct hda_codec *codec)
796 {
797         via_init(codec);
798         via_auto_init_multi_out(codec);
799         via_auto_init_hp_out(codec);
800         via_auto_init_analog_input(codec);
801         return 0;
802 }
803
804 static int patch_vt1708(struct hda_codec *codec)
805 {
806         struct via_spec *spec;
807         int err;
808
809         /* create a codec specific record */
810         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
811         if (spec == NULL)
812                 return -ENOMEM;
813
814         codec->spec = spec;
815
816         /* automatic parse from the BIOS config */
817         err = vt1708_parse_auto_config(codec);
818         if (err < 0) {
819                 via_free(codec);
820                 return err;
821         } else if (!err) {
822                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
823                        "from BIOS.  Using genenic mode...\n");
824         }
825
826         
827         spec->stream_name_analog = "VT1708 Analog";
828         spec->stream_analog_playback = &vt1708_pcm_analog_playback;
829         spec->stream_analog_capture = &vt1708_pcm_analog_capture;
830
831         spec->stream_name_digital = "VT1708 Digital";
832         spec->stream_digital_playback = &vt1708_pcm_digital_playback;
833         spec->stream_digital_capture = &vt1708_pcm_digital_capture;
834
835         
836         if (!spec->adc_nids && spec->input_mux) {
837                 spec->adc_nids = vt1708_adc_nids;
838                 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
839                 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
840                 spec->num_mixers++;
841         }
842
843         codec->patch_ops = via_patch_ops;
844
845         codec->patch_ops.init = via_auto_init;
846
847         return 0;
848 }
849
850 /* capture mixer elements */
851 static struct snd_kcontrol_new vt1709_capture_mixer[] = {
852         HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
853         HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
854         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
855         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
856         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
857         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
858         {
859                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
860                 /* The multiple "Capture Source" controls confuse alsamixer
861                  * So call somewhat different..
862                  * FIXME: the controls appear in the "playback" view!
863                  */
864                 /* .name = "Capture Source", */
865                 .name = "Input Source",
866                 .count = 1,
867                 .info = via_mux_enum_info,
868                 .get = via_mux_enum_get,
869                 .put = via_mux_enum_put,
870         },
871         { } /* end */
872 };
873
874 /*
875  * generic initialization of ADC, input mixers and output mixers
876  */
877 static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
878         /*
879          * Unmute ADC0-2 and set the default input to mic-in
880          */
881         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
882         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
883         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
884
885
886         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
887          * mixer widget
888          */
889         /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
890         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
891         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
892         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
893         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
894         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
895
896         /*
897          * Set up output selector (0x1a, 0x1b, 0x29)
898          */
899         /* set vol=0 to output mixers */
900         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
901         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
902         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
903
904         /*
905          *  Unmute PW3 and PW4
906          */
907         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
908         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
909
910         /* Set input of PW4 as AOW4 */
911         {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
912         /* Set mic as default input of sw0 */
913         {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
914         /* PW9 Output enable */
915         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
916         { }
917 };
918
919 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
920         .substreams = 1,
921         .channels_min = 2,
922         .channels_max = 10,
923         .nid = 0x10, /* NID to query formats and rates */
924         .ops = {
925                 .open = via_playback_pcm_open,
926                 .prepare = via_playback_pcm_prepare,
927                 .cleanup = via_playback_pcm_cleanup
928         },
929 };
930
931 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
932         .substreams = 1,
933         .channels_min = 2,
934         .channels_max = 6,
935         .nid = 0x10, /* NID to query formats and rates */
936         .ops = {
937                 .open = via_playback_pcm_open,
938                 .prepare = via_playback_pcm_prepare,
939                 .cleanup = via_playback_pcm_cleanup
940         },
941 };
942
943 static struct hda_pcm_stream vt1709_pcm_analog_capture = {
944         .substreams = 2,
945         .channels_min = 2,
946         .channels_max = 2,
947         .nid = 0x14, /* NID to query formats and rates */
948         .ops = {
949                 .prepare = via_capture_pcm_prepare,
950                 .cleanup = via_capture_pcm_cleanup
951         },
952 };
953
954 static struct hda_pcm_stream vt1709_pcm_digital_playback = {
955         .substreams = 1,
956         .channels_min = 2,
957         .channels_max = 2,
958         /* NID is set in via_build_pcms */
959         .ops = {
960                 .open = via_dig_playback_pcm_open,
961                 .close = via_dig_playback_pcm_close
962         },
963 };
964
965 static struct hda_pcm_stream vt1709_pcm_digital_capture = {
966         .substreams = 1,
967         .channels_min = 2,
968         .channels_max = 2,
969 };
970
971 static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
972                                      const struct auto_pin_cfg *cfg)
973 {
974         int i;
975         hda_nid_t nid;
976
977         if (cfg->line_outs == 4)  /* 10 channels */
978                 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
979         else if (cfg->line_outs == 3) /* 6 channels */
980                 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
981
982         spec->multiout.dac_nids = spec->private_dac_nids;
983
984         if (cfg->line_outs == 4) { /* 10 channels */
985                 for (i = 0; i < cfg->line_outs; i++) {
986                         nid = cfg->line_out_pins[i];
987                         if (nid) {
988                                 /* config dac list */
989                                 switch (i) {
990                                 case AUTO_SEQ_FRONT:
991                                         /* AOW0 */
992                                         spec->multiout.dac_nids[i] = 0x10;
993                                         break;
994                                 case AUTO_SEQ_CENLFE:
995                                         /* AOW2 */
996                                         spec->multiout.dac_nids[i] = 0x12;
997                                         break;
998                                 case AUTO_SEQ_SURROUND:
999                                         /* AOW3 */
1000                                         spec->multiout.dac_nids[i] = 0x27;
1001                                         break;
1002                                 case AUTO_SEQ_SIDE:
1003                                         /* AOW1 */
1004                                         spec->multiout.dac_nids[i] = 0x11;
1005                                         break;
1006                                 default:
1007                                         break;
1008                                 }
1009                         }
1010                 }
1011                 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1012
1013         } else if (cfg->line_outs == 3) { /* 6 channels */
1014                 for(i = 0; i < cfg->line_outs; i++) {
1015                         nid = cfg->line_out_pins[i];
1016                         if (nid) {
1017                                 /* config dac list */
1018                                 switch(i) {
1019                                 case AUTO_SEQ_FRONT:
1020                                         /* AOW0 */
1021                                         spec->multiout.dac_nids[i] = 0x10;
1022                                         break;
1023                                 case AUTO_SEQ_CENLFE:
1024                                         /* AOW2 */
1025                                         spec->multiout.dac_nids[i] = 0x12;
1026                                         break;
1027                                 case AUTO_SEQ_SURROUND:
1028                                         /* AOW1 */
1029                                         spec->multiout.dac_nids[i] = 0x11;
1030                                         break;
1031                                 default:
1032                                         break;
1033                                 }
1034                         }
1035                 }
1036         }
1037
1038         return 0;
1039 }
1040
1041 /* add playback controls from the parsed DAC table */
1042 static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1043                                              const struct auto_pin_cfg *cfg)
1044 {
1045         char name[32];
1046         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1047         hda_nid_t nid = 0;
1048         int i, err;
1049
1050         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1051                 nid = cfg->line_out_pins[i];
1052
1053                 if (!nid)       
1054                         continue;
1055
1056                 if (i == AUTO_SEQ_CENLFE) {
1057                         /* Center/LFE */
1058                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1059                                               "Center Playback Volume",
1060                                               HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
1061                         if (err < 0)
1062                                 return err;
1063                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1064                                               "LFE Playback Volume",
1065                                               HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
1066                         if (err < 0)
1067                                 return err;
1068                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1069                                               "Center Playback Switch",
1070                                               HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
1071                         if (err < 0)
1072                                 return err;
1073                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1074                                               "LFE Playback Switch",
1075                                               HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
1076                         if (err < 0)
1077                                 return err;
1078                 } else if (i == AUTO_SEQ_FRONT){
1079                         /* add control to mixer index 0 */
1080                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1081                                               "Master Front Playback Volume",
1082                                               HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
1083                         if (err < 0)
1084                                 return err;
1085                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1086                                               "Master Front Playback Switch",
1087                                               HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
1088                         if (err < 0)
1089                                 return err;
1090                         
1091                         /* add control to PW3 */
1092                         sprintf(name, "%s Playback Volume", chname[i]);
1093                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1094                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
1095                         if (err < 0)
1096                                 return err;
1097                         sprintf(name, "%s Playback Switch", chname[i]);
1098                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1099                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
1100                         if (err < 0)
1101                                 return err;
1102                 } else if (i == AUTO_SEQ_SURROUND) {
1103                         sprintf(name, "%s Playback Volume", chname[i]);
1104                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1105                                               HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
1106                         if (err < 0)
1107                                 return err;
1108                         sprintf(name, "%s Playback Switch", chname[i]);
1109                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1110                                               HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
1111                         if (err < 0)
1112                                 return err;
1113                 } else if (i == AUTO_SEQ_SIDE) {
1114                         sprintf(name, "%s Playback Volume", chname[i]);
1115                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1116                                               HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
1117                         if (err < 0)
1118                                 return err;
1119                         sprintf(name, "%s Playback Switch", chname[i]);
1120                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1121                                               HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
1122                         if (err < 0)
1123                                 return err;
1124                 }
1125         }
1126
1127         return 0;
1128 }
1129
1130 static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1131 {
1132         int err;
1133
1134         if (!pin)
1135                 return 0;
1136
1137         if (spec->multiout.num_dacs == 5) /* 10 channels */
1138                 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1139         else if (spec->multiout.num_dacs == 3) /* 6 channels */
1140                 spec->multiout.hp_nid = 0;
1141
1142         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1143                               "Headphone Playback Volume",
1144                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1145         if (err < 0)
1146                 return err;
1147         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1148                               "Headphone Playback Switch",
1149                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1150         if (err < 0)
1151                 return err;
1152
1153         return 0;
1154 }
1155
1156 /* create playback/capture controls for input pins */
1157 static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1158                                                 const struct auto_pin_cfg *cfg)
1159 {
1160         static char *labels[] = {
1161                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1162         };
1163         struct hda_input_mux *imux = &spec->private_imux;
1164         int i, err, idx = 0;
1165
1166         /* for internal loopback recording select */
1167         imux->items[imux->num_items].label = "Stereo Mixer";
1168         imux->items[imux->num_items].index = idx;
1169         imux->num_items++;
1170
1171         for (i = 0; i < AUTO_PIN_LAST; i++) {
1172                 if (!cfg->input_pins[i])
1173                         continue;
1174
1175                 switch (cfg->input_pins[i]) {
1176                 case 0x1d: /* Mic */
1177                         idx = 2;
1178                         break;
1179                                 
1180                 case 0x1e: /* Line In */
1181                         idx = 3;
1182                         break;
1183
1184                 case 0x21: /* Front Mic */
1185                         idx = 4;
1186                         break;
1187
1188                 case 0x23: /* CD */
1189                         idx = 1;
1190                         break;
1191                 }
1192                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1193                                            idx, 0x18);
1194                 if (err < 0)
1195                         return err;
1196                 imux->items[imux->num_items].label = labels[i];
1197                 imux->items[imux->num_items].index = idx;
1198                 imux->num_items++;
1199         }
1200         return 0;
1201 }
1202
1203 static int vt1709_parse_auto_config(struct hda_codec *codec)
1204 {
1205         struct via_spec *spec = codec->spec;
1206         int err;
1207
1208         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1209         if (err < 0)
1210                 return err;
1211         err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1212         if (err < 0)
1213                 return err;
1214         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1215                 return 0; /* can't find valid BIOS pin config */
1216
1217         err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1218         if (err < 0)
1219                 return err;
1220         err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1221         if (err < 0)
1222                 return err;
1223         err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1224         if (err < 0)
1225                 return err;
1226
1227         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1228
1229         if (spec->autocfg.dig_out_pin)
1230                 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1231         if (spec->autocfg.dig_in_pin)
1232                 spec->dig_in_nid = VT1709_DIGIN_NID;
1233
1234         if (spec->kctl_alloc)
1235                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1236
1237         spec->input_mux = &spec->private_imux;
1238
1239         return 1;
1240 }
1241
1242 static int patch_vt1709_10ch(struct hda_codec *codec)
1243 {
1244         struct via_spec *spec;
1245         int err;
1246
1247         /* create a codec specific record */
1248         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1249         if (spec == NULL)
1250                 return -ENOMEM;
1251
1252         codec->spec = spec;
1253
1254         err = vt1709_parse_auto_config(codec);
1255         if (err < 0) {
1256                 via_free(codec);
1257                 return err;
1258         } else if (!err) {
1259                 printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1260                        "Using genenic mode...\n");
1261         }
1262
1263         spec->init_verbs = vt1709_10ch_volume_init_verbs;       
1264
1265         spec->stream_name_analog = "VT1709 Analog";
1266         spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1267         spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1268
1269         spec->stream_name_digital = "VT1709 Digital";
1270         spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1271         spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1272
1273         
1274         if (!spec->adc_nids && spec->input_mux) {
1275                 spec->adc_nids = vt1709_adc_nids;
1276                 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1277                 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1278                 spec->num_mixers++;
1279         }
1280
1281         codec->patch_ops = via_patch_ops;
1282
1283         codec->patch_ops.init = via_auto_init;
1284
1285         return 0;
1286 }
1287 /*
1288  * generic initialization of ADC, input mixers and output mixers
1289  */
1290 static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1291         /*
1292          * Unmute ADC0-2 and set the default input to mic-in
1293          */
1294         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1295         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1296         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1297
1298
1299         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1300          * mixer widget
1301          */
1302         /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1303         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1304         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1305         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1306         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1307         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1308
1309         /*
1310          * Set up output selector (0x1a, 0x1b, 0x29)
1311          */
1312         /* set vol=0 to output mixers */
1313         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1314         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1315         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1316
1317         /*
1318          *  Unmute PW3 and PW4
1319          */
1320         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1321         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1322
1323         /* Set input of PW4 as MW0 */
1324         {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1325         /* Set mic as default input of sw0 */
1326         {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
1327         /* PW9 Output enable */
1328         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1329         { }
1330 };
1331
1332 static int patch_vt1709_6ch(struct hda_codec *codec)
1333 {
1334         struct via_spec *spec;
1335         int err;
1336
1337         /* create a codec specific record */
1338         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1339         if (spec == NULL)
1340                 return -ENOMEM;
1341
1342         codec->spec = spec;
1343
1344         err = vt1709_parse_auto_config(codec);
1345         if (err < 0) {
1346                 via_free(codec);
1347                 return err;
1348         } else if (!err) {
1349                 printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1350                        "Using genenic mode...\n");
1351         }
1352
1353         spec->init_verbs = vt1709_6ch_volume_init_verbs;        
1354
1355         spec->stream_name_analog = "VT1709 Analog";
1356         spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1357         spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1358
1359         spec->stream_name_digital = "VT1709 Digital";
1360         spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1361         spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1362
1363         
1364         if (!spec->adc_nids && spec->input_mux) {
1365                 spec->adc_nids = vt1709_adc_nids;
1366                 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1367                 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1368                 spec->num_mixers++;
1369         }
1370
1371         codec->patch_ops = via_patch_ops;
1372
1373         codec->patch_ops.init = via_auto_init;
1374
1375         return 0;
1376 }
1377
1378 /*
1379  * patch entries
1380  */
1381 struct hda_codec_preset snd_hda_preset_via[] = {
1382         { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1383         { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1384         { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1385         { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
1386         { .id = 0x1106E710, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1387         { .id = 0x1106E711, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1388         { .id = 0x1106E712, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1389         { .id = 0x1106E713, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1390         { .id = 0x1106E714, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1391         { .id = 0x1106E715, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1392         { .id = 0x1106E716, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1393         { .id = 0x1106E717, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1394         {} /* terminator */
1395 };