Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6] / 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 static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
381                                         struct hda_codec *codec,
382                                         unsigned int stream_tag,
383                                         unsigned int format,
384                                         struct snd_pcm_substream *substream)
385 {
386         struct via_spec *spec = codec->spec;
387         return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
388                                              stream_tag, format, substream);
389 }
390
391 /*
392  * Analog capture
393  */
394 static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
395                                    struct hda_codec *codec,
396                                    unsigned int stream_tag,
397                                    unsigned int format,
398                                    struct snd_pcm_substream *substream)
399 {
400         struct via_spec *spec = codec->spec;
401
402         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
403                                    stream_tag, 0, format);
404         return 0;
405 }
406
407 static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
408                                    struct hda_codec *codec,
409                                    struct snd_pcm_substream *substream)
410 {
411         struct via_spec *spec = codec->spec;
412         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
413                                    0, 0, 0);
414         return 0;
415 }
416
417 static struct hda_pcm_stream vt1708_pcm_analog_playback = {
418         .substreams = 1,
419         .channels_min = 2,
420         .channels_max = 8,
421         .nid = 0x10, /* NID to query formats and rates */
422         .ops = {
423                 .open = via_playback_pcm_open,
424                 .prepare = via_playback_pcm_prepare,
425                 .cleanup = via_playback_pcm_cleanup
426         },
427 };
428
429 static struct hda_pcm_stream vt1708_pcm_analog_capture = {
430         .substreams = 2,
431         .channels_min = 2,
432         .channels_max = 2,
433         .nid = 0x15, /* NID to query formats and rates */
434         .ops = {
435                 .prepare = via_capture_pcm_prepare,
436                 .cleanup = via_capture_pcm_cleanup
437         },
438 };
439
440 static struct hda_pcm_stream vt1708_pcm_digital_playback = {
441         .substreams = 1,
442         .channels_min = 2,
443         .channels_max = 2,
444         /* NID is set in via_build_pcms */
445         .ops = {
446                 .open = via_dig_playback_pcm_open,
447                 .close = via_dig_playback_pcm_close,
448                 .prepare = via_dig_playback_pcm_prepare
449         },
450 };
451
452 static struct hda_pcm_stream vt1708_pcm_digital_capture = {
453         .substreams = 1,
454         .channels_min = 2,
455         .channels_max = 2,
456 };
457
458 static int via_build_controls(struct hda_codec *codec)
459 {
460         struct via_spec *spec = codec->spec;
461         int err;
462         int i;
463
464         for (i = 0; i < spec->num_mixers; i++) {
465                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
466                 if (err < 0)
467                         return err;
468         }
469
470         if (spec->multiout.dig_out_nid) {
471                 err = snd_hda_create_spdif_out_ctls(codec,
472                                                     spec->multiout.dig_out_nid);
473                 if (err < 0)
474                         return err;
475         }
476         if (spec->dig_in_nid) {
477                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
478                 if (err < 0)
479                         return err;
480         }
481         return 0;
482 }
483
484 static int via_build_pcms(struct hda_codec *codec)
485 {
486         struct via_spec *spec = codec->spec;
487         struct hda_pcm *info = spec->pcm_rec;
488
489         codec->num_pcms = 1;
490         codec->pcm_info = info;
491
492         info->name = spec->stream_name_analog;
493         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
494         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
495         info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
496         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
497
498         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
499                 spec->multiout.max_channels;
500
501         if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
502                 codec->num_pcms++;
503                 info++;
504                 info->name = spec->stream_name_digital;
505                 if (spec->multiout.dig_out_nid) {
506                         info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
507                                 *(spec->stream_digital_playback);
508                         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
509                                 spec->multiout.dig_out_nid;
510                 }
511                 if (spec->dig_in_nid) {
512                         info->stream[SNDRV_PCM_STREAM_CAPTURE] =
513                                 *(spec->stream_digital_capture);
514                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
515                                 spec->dig_in_nid;
516                 }
517         }
518
519         return 0;
520 }
521
522 static void via_free(struct hda_codec *codec)
523 {
524         struct via_spec *spec = codec->spec;
525         unsigned int i;
526
527         if (!spec)
528                 return;
529
530         if (spec->kctl_alloc) {
531                 for (i = 0; i < spec->num_kctl_used; i++)
532                         kfree(spec->kctl_alloc[i].name);
533                 kfree(spec->kctl_alloc);
534         }
535
536         kfree(codec->spec);
537 }
538
539 static int via_init(struct hda_codec *codec)
540 {
541         struct via_spec *spec = codec->spec;
542         snd_hda_sequence_write(codec, spec->init_verbs);
543         return 0;
544 }
545
546 #ifdef CONFIG_PM
547 /*
548  * resume
549  */
550 static int via_resume(struct hda_codec *codec)
551 {
552         struct via_spec *spec = codec->spec;
553         int i;
554
555         via_init(codec);
556         for (i = 0; i < spec->num_mixers; i++)
557                 snd_hda_resume_ctls(codec, spec->mixers[i]);
558         if (spec->multiout.dig_out_nid)
559                 snd_hda_resume_spdif_out(codec);
560         if (spec->dig_in_nid)
561                 snd_hda_resume_spdif_in(codec);
562
563         return 0;
564 }
565 #endif
566
567 /*
568  */
569 static struct hda_codec_ops via_patch_ops = {
570         .build_controls = via_build_controls,
571         .build_pcms = via_build_pcms,
572         .init = via_init,
573         .free = via_free,
574 #ifdef CONFIG_PM
575         .resume = via_resume,
576 #endif
577 };
578
579 /* fill in the dac_nids table from the parsed pin configuration */
580 static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
581                                      const struct auto_pin_cfg *cfg)
582 {
583         int i;
584         hda_nid_t nid;
585
586         spec->multiout.num_dacs = cfg->line_outs;
587
588         spec->multiout.dac_nids = spec->private_dac_nids;
589         
590         for(i = 0; i < 4; i++) {
591                 nid = cfg->line_out_pins[i];
592                 if (nid) {
593                         /* config dac list */
594                         switch (i) {
595                         case AUTO_SEQ_FRONT:
596                                 spec->multiout.dac_nids[i] = 0x10;
597                                 break;
598                         case AUTO_SEQ_CENLFE:
599                                 spec->multiout.dac_nids[i] = 0x12;
600                                 break;
601                         case AUTO_SEQ_SURROUND:
602                                 spec->multiout.dac_nids[i] = 0x13;
603                                 break;
604                         case AUTO_SEQ_SIDE:
605                                 spec->multiout.dac_nids[i] = 0x11;
606                                 break;
607                         }
608                 }
609         }
610
611         return 0;
612 }
613
614 /* add playback controls from the parsed DAC table */
615 static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
616                                              const struct auto_pin_cfg *cfg)
617 {
618         char name[32];
619         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
620         hda_nid_t nid, nid_vol = 0;
621         int i, err;
622
623         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
624                 nid = cfg->line_out_pins[i];
625
626                 if (!nid)
627                         continue;
628                 
629                 if (i != AUTO_SEQ_FRONT)
630                         nid_vol = 0x1b - i + 1;
631
632                 if (i == AUTO_SEQ_CENLFE) {
633                         /* Center/LFE */
634                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
635                                               "Center Playback Volume",
636                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
637                         if (err < 0)
638                                 return err;
639                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
640                                               "LFE Playback Volume",
641                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
642                         if (err < 0)
643                                 return err;
644                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
645                                               "Center Playback Switch",
646                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
647                         if (err < 0)
648                                 return err;
649                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
650                                               "LFE Playback Switch",
651                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
652                         if (err < 0)
653                                 return err;
654                 } else if (i == AUTO_SEQ_FRONT){
655                         /* add control to mixer index 0 */
656                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
657                                               "Master Front Playback Volume",
658                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
659                         if (err < 0)
660                                 return err;
661                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
662                                               "Master Front Playback Switch",
663                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
664                         if (err < 0)
665                                 return err;
666                         
667                         /* add control to PW3 */
668                         sprintf(name, "%s Playback Volume", chname[i]);
669                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
670                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
671                         if (err < 0)
672                                 return err;
673                         sprintf(name, "%s Playback Switch", chname[i]);
674                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
675                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
676                         if (err < 0)
677                                 return err;
678                 } else {
679                         sprintf(name, "%s Playback Volume", chname[i]);
680                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
681                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
682                         if (err < 0)
683                                 return err;
684                         sprintf(name, "%s Playback Switch", chname[i]);
685                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
686                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
687                         if (err < 0)
688                                 return err;
689                 }
690         }
691
692         return 0;
693 }
694
695 static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
696 {
697         int err;
698
699         if (!pin)
700                 return 0;
701
702         spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
703
704         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
705                               "Headphone Playback Volume",
706                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
707         if (err < 0)
708                 return err;
709         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
710                               "Headphone Playback Switch",
711                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
712         if (err < 0)
713                 return err;
714
715         return 0;
716 }
717
718 /* create playback/capture controls for input pins */
719 static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
720                                                 const struct auto_pin_cfg *cfg)
721 {
722         static char *labels[] = {
723                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
724         };
725         struct hda_input_mux *imux = &spec->private_imux;
726         int i, err, idx = 0;
727
728         /* for internal loopback recording select */
729         imux->items[imux->num_items].label = "Stereo Mixer";
730         imux->items[imux->num_items].index = idx;
731         imux->num_items++;
732
733         for (i = 0; i < AUTO_PIN_LAST; i++) {
734                 if (!cfg->input_pins[i])
735                         continue;
736
737                 switch (cfg->input_pins[i]) {
738                 case 0x1d: /* Mic */
739                         idx = 2;
740                         break;
741                                 
742                 case 0x1e: /* Line In */
743                         idx = 3;
744                         break;
745
746                 case 0x21: /* Front Mic */
747                         idx = 4;
748                         break;
749
750                 case 0x24: /* CD */
751                         idx = 1;
752                         break;
753                 }
754                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
755                                            idx, 0x17);
756                 if (err < 0)
757                         return err;
758                 imux->items[imux->num_items].label = labels[i];
759                 imux->items[imux->num_items].index = idx;
760                 imux->num_items++;
761         }
762         return 0;
763 }
764
765 static int vt1708_parse_auto_config(struct hda_codec *codec)
766 {
767         struct via_spec *spec = codec->spec;
768         int err;
769
770         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
771         if (err < 0)
772                 return err;
773         err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
774         if (err < 0)
775                 return err;
776         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
777                 return 0; /* can't find valid BIOS pin config */
778
779         err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
780         if (err < 0)
781                 return err;
782         err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
783         if (err < 0)
784                 return err;
785         err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
786         if (err < 0)
787                 return err;
788
789         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
790
791         if (spec->autocfg.dig_out_pin)
792                 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
793         if (spec->autocfg.dig_in_pin)
794                 spec->dig_in_nid = VT1708_DIGIN_NID;
795
796         if (spec->kctl_alloc)
797                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
798
799         spec->init_verbs = vt1708_volume_init_verbs;    
800
801         spec->input_mux = &spec->private_imux;
802
803         return 1;
804 }
805
806 /* init callback for auto-configuration model -- overriding the default init */
807 static int via_auto_init(struct hda_codec *codec)
808 {
809         via_init(codec);
810         via_auto_init_multi_out(codec);
811         via_auto_init_hp_out(codec);
812         via_auto_init_analog_input(codec);
813         return 0;
814 }
815
816 static int patch_vt1708(struct hda_codec *codec)
817 {
818         struct via_spec *spec;
819         int err;
820
821         /* create a codec specific record */
822         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
823         if (spec == NULL)
824                 return -ENOMEM;
825
826         codec->spec = spec;
827
828         /* automatic parse from the BIOS config */
829         err = vt1708_parse_auto_config(codec);
830         if (err < 0) {
831                 via_free(codec);
832                 return err;
833         } else if (!err) {
834                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
835                        "from BIOS.  Using genenic mode...\n");
836         }
837
838         
839         spec->stream_name_analog = "VT1708 Analog";
840         spec->stream_analog_playback = &vt1708_pcm_analog_playback;
841         spec->stream_analog_capture = &vt1708_pcm_analog_capture;
842
843         spec->stream_name_digital = "VT1708 Digital";
844         spec->stream_digital_playback = &vt1708_pcm_digital_playback;
845         spec->stream_digital_capture = &vt1708_pcm_digital_capture;
846
847         
848         if (!spec->adc_nids && spec->input_mux) {
849                 spec->adc_nids = vt1708_adc_nids;
850                 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
851                 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
852                 spec->num_mixers++;
853         }
854
855         codec->patch_ops = via_patch_ops;
856
857         codec->patch_ops.init = via_auto_init;
858
859         return 0;
860 }
861
862 /* capture mixer elements */
863 static struct snd_kcontrol_new vt1709_capture_mixer[] = {
864         HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
865         HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
866         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
867         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
868         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
869         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
870         {
871                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
872                 /* The multiple "Capture Source" controls confuse alsamixer
873                  * So call somewhat different..
874                  * FIXME: the controls appear in the "playback" view!
875                  */
876                 /* .name = "Capture Source", */
877                 .name = "Input Source",
878                 .count = 1,
879                 .info = via_mux_enum_info,
880                 .get = via_mux_enum_get,
881                 .put = via_mux_enum_put,
882         },
883         { } /* end */
884 };
885
886 /*
887  * generic initialization of ADC, input mixers and output mixers
888  */
889 static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
890         /*
891          * Unmute ADC0-2 and set the default input to mic-in
892          */
893         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
894         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
895         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
896
897
898         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
899          * mixer widget
900          */
901         /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
902         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
903         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
904         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
905         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
906         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
907
908         /*
909          * Set up output selector (0x1a, 0x1b, 0x29)
910          */
911         /* set vol=0 to output mixers */
912         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
913         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
914         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
915
916         /*
917          *  Unmute PW3 and PW4
918          */
919         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
920         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
921
922         /* Set input of PW4 as AOW4 */
923         {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
924         /* Set mic as default input of sw0 */
925         {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
926         /* PW9 Output enable */
927         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
928         { }
929 };
930
931 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
932         .substreams = 1,
933         .channels_min = 2,
934         .channels_max = 10,
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_6ch_pcm_analog_playback = {
944         .substreams = 1,
945         .channels_min = 2,
946         .channels_max = 6,
947         .nid = 0x10, /* NID to query formats and rates */
948         .ops = {
949                 .open = via_playback_pcm_open,
950                 .prepare = via_playback_pcm_prepare,
951                 .cleanup = via_playback_pcm_cleanup
952         },
953 };
954
955 static struct hda_pcm_stream vt1709_pcm_analog_capture = {
956         .substreams = 2,
957         .channels_min = 2,
958         .channels_max = 2,
959         .nid = 0x14, /* NID to query formats and rates */
960         .ops = {
961                 .prepare = via_capture_pcm_prepare,
962                 .cleanup = via_capture_pcm_cleanup
963         },
964 };
965
966 static struct hda_pcm_stream vt1709_pcm_digital_playback = {
967         .substreams = 1,
968         .channels_min = 2,
969         .channels_max = 2,
970         /* NID is set in via_build_pcms */
971         .ops = {
972                 .open = via_dig_playback_pcm_open,
973                 .close = via_dig_playback_pcm_close
974         },
975 };
976
977 static struct hda_pcm_stream vt1709_pcm_digital_capture = {
978         .substreams = 1,
979         .channels_min = 2,
980         .channels_max = 2,
981 };
982
983 static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
984                                      const struct auto_pin_cfg *cfg)
985 {
986         int i;
987         hda_nid_t nid;
988
989         if (cfg->line_outs == 4)  /* 10 channels */
990                 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
991         else if (cfg->line_outs == 3) /* 6 channels */
992                 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
993
994         spec->multiout.dac_nids = spec->private_dac_nids;
995
996         if (cfg->line_outs == 4) { /* 10 channels */
997                 for (i = 0; i < cfg->line_outs; i++) {
998                         nid = cfg->line_out_pins[i];
999                         if (nid) {
1000                                 /* config dac list */
1001                                 switch (i) {
1002                                 case AUTO_SEQ_FRONT:
1003                                         /* AOW0 */
1004                                         spec->multiout.dac_nids[i] = 0x10;
1005                                         break;
1006                                 case AUTO_SEQ_CENLFE:
1007                                         /* AOW2 */
1008                                         spec->multiout.dac_nids[i] = 0x12;
1009                                         break;
1010                                 case AUTO_SEQ_SURROUND:
1011                                         /* AOW3 */
1012                                         spec->multiout.dac_nids[i] = 0x27;
1013                                         break;
1014                                 case AUTO_SEQ_SIDE:
1015                                         /* AOW1 */
1016                                         spec->multiout.dac_nids[i] = 0x11;
1017                                         break;
1018                                 default:
1019                                         break;
1020                                 }
1021                         }
1022                 }
1023                 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1024
1025         } else if (cfg->line_outs == 3) { /* 6 channels */
1026                 for(i = 0; i < cfg->line_outs; i++) {
1027                         nid = cfg->line_out_pins[i];
1028                         if (nid) {
1029                                 /* config dac list */
1030                                 switch(i) {
1031                                 case AUTO_SEQ_FRONT:
1032                                         /* AOW0 */
1033                                         spec->multiout.dac_nids[i] = 0x10;
1034                                         break;
1035                                 case AUTO_SEQ_CENLFE:
1036                                         /* AOW2 */
1037                                         spec->multiout.dac_nids[i] = 0x12;
1038                                         break;
1039                                 case AUTO_SEQ_SURROUND:
1040                                         /* AOW1 */
1041                                         spec->multiout.dac_nids[i] = 0x11;
1042                                         break;
1043                                 default:
1044                                         break;
1045                                 }
1046                         }
1047                 }
1048         }
1049
1050         return 0;
1051 }
1052
1053 /* add playback controls from the parsed DAC table */
1054 static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1055                                              const struct auto_pin_cfg *cfg)
1056 {
1057         char name[32];
1058         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1059         hda_nid_t nid = 0;
1060         int i, err;
1061
1062         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1063                 nid = cfg->line_out_pins[i];
1064
1065                 if (!nid)       
1066                         continue;
1067
1068                 if (i == AUTO_SEQ_CENLFE) {
1069                         /* Center/LFE */
1070                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1071                                               "Center Playback Volume",
1072                                               HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
1073                         if (err < 0)
1074                                 return err;
1075                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1076                                               "LFE Playback Volume",
1077                                               HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
1078                         if (err < 0)
1079                                 return err;
1080                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1081                                               "Center Playback Switch",
1082                                               HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
1083                         if (err < 0)
1084                                 return err;
1085                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1086                                               "LFE Playback Switch",
1087                                               HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
1088                         if (err < 0)
1089                                 return err;
1090                 } else if (i == AUTO_SEQ_FRONT){
1091                         /* add control to mixer index 0 */
1092                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1093                                               "Master Front Playback Volume",
1094                                               HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
1095                         if (err < 0)
1096                                 return err;
1097                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1098                                               "Master Front Playback Switch",
1099                                               HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
1100                         if (err < 0)
1101                                 return err;
1102                         
1103                         /* add control to PW3 */
1104                         sprintf(name, "%s Playback Volume", chname[i]);
1105                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1106                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
1107                         if (err < 0)
1108                                 return err;
1109                         sprintf(name, "%s Playback Switch", chname[i]);
1110                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1111                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
1112                         if (err < 0)
1113                                 return err;
1114                 } else if (i == AUTO_SEQ_SURROUND) {
1115                         sprintf(name, "%s Playback Volume", chname[i]);
1116                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1117                                               HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
1118                         if (err < 0)
1119                                 return err;
1120                         sprintf(name, "%s Playback Switch", chname[i]);
1121                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1122                                               HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
1123                         if (err < 0)
1124                                 return err;
1125                 } else if (i == AUTO_SEQ_SIDE) {
1126                         sprintf(name, "%s Playback Volume", chname[i]);
1127                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1128                                               HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
1129                         if (err < 0)
1130                                 return err;
1131                         sprintf(name, "%s Playback Switch", chname[i]);
1132                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1133                                               HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
1134                         if (err < 0)
1135                                 return err;
1136                 }
1137         }
1138
1139         return 0;
1140 }
1141
1142 static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1143 {
1144         int err;
1145
1146         if (!pin)
1147                 return 0;
1148
1149         if (spec->multiout.num_dacs == 5) /* 10 channels */
1150                 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1151         else if (spec->multiout.num_dacs == 3) /* 6 channels */
1152                 spec->multiout.hp_nid = 0;
1153
1154         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1155                               "Headphone Playback Volume",
1156                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1157         if (err < 0)
1158                 return err;
1159         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1160                               "Headphone Playback Switch",
1161                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1162         if (err < 0)
1163                 return err;
1164
1165         return 0;
1166 }
1167
1168 /* create playback/capture controls for input pins */
1169 static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1170                                                 const struct auto_pin_cfg *cfg)
1171 {
1172         static char *labels[] = {
1173                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1174         };
1175         struct hda_input_mux *imux = &spec->private_imux;
1176         int i, err, idx = 0;
1177
1178         /* for internal loopback recording select */
1179         imux->items[imux->num_items].label = "Stereo Mixer";
1180         imux->items[imux->num_items].index = idx;
1181         imux->num_items++;
1182
1183         for (i = 0; i < AUTO_PIN_LAST; i++) {
1184                 if (!cfg->input_pins[i])
1185                         continue;
1186
1187                 switch (cfg->input_pins[i]) {
1188                 case 0x1d: /* Mic */
1189                         idx = 2;
1190                         break;
1191                                 
1192                 case 0x1e: /* Line In */
1193                         idx = 3;
1194                         break;
1195
1196                 case 0x21: /* Front Mic */
1197                         idx = 4;
1198                         break;
1199
1200                 case 0x23: /* CD */
1201                         idx = 1;
1202                         break;
1203                 }
1204                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1205                                            idx, 0x18);
1206                 if (err < 0)
1207                         return err;
1208                 imux->items[imux->num_items].label = labels[i];
1209                 imux->items[imux->num_items].index = idx;
1210                 imux->num_items++;
1211         }
1212         return 0;
1213 }
1214
1215 static int vt1709_parse_auto_config(struct hda_codec *codec)
1216 {
1217         struct via_spec *spec = codec->spec;
1218         int err;
1219
1220         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1221         if (err < 0)
1222                 return err;
1223         err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1224         if (err < 0)
1225                 return err;
1226         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1227                 return 0; /* can't find valid BIOS pin config */
1228
1229         err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1230         if (err < 0)
1231                 return err;
1232         err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1233         if (err < 0)
1234                 return err;
1235         err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1236         if (err < 0)
1237                 return err;
1238
1239         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1240
1241         if (spec->autocfg.dig_out_pin)
1242                 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1243         if (spec->autocfg.dig_in_pin)
1244                 spec->dig_in_nid = VT1709_DIGIN_NID;
1245
1246         if (spec->kctl_alloc)
1247                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1248
1249         spec->input_mux = &spec->private_imux;
1250
1251         return 1;
1252 }
1253
1254 static int patch_vt1709_10ch(struct hda_codec *codec)
1255 {
1256         struct via_spec *spec;
1257         int err;
1258
1259         /* create a codec specific record */
1260         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1261         if (spec == NULL)
1262                 return -ENOMEM;
1263
1264         codec->spec = spec;
1265
1266         err = vt1709_parse_auto_config(codec);
1267         if (err < 0) {
1268                 via_free(codec);
1269                 return err;
1270         } else if (!err) {
1271                 printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1272                        "Using genenic mode...\n");
1273         }
1274
1275         spec->init_verbs = vt1709_10ch_volume_init_verbs;       
1276
1277         spec->stream_name_analog = "VT1709 Analog";
1278         spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1279         spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1280
1281         spec->stream_name_digital = "VT1709 Digital";
1282         spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1283         spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1284
1285         
1286         if (!spec->adc_nids && spec->input_mux) {
1287                 spec->adc_nids = vt1709_adc_nids;
1288                 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1289                 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1290                 spec->num_mixers++;
1291         }
1292
1293         codec->patch_ops = via_patch_ops;
1294
1295         codec->patch_ops.init = via_auto_init;
1296
1297         return 0;
1298 }
1299 /*
1300  * generic initialization of ADC, input mixers and output mixers
1301  */
1302 static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1303         /*
1304          * Unmute ADC0-2 and set the default input to mic-in
1305          */
1306         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1307         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1308         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1309
1310
1311         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1312          * mixer widget
1313          */
1314         /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1315         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1316         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1317         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1318         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1319         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1320
1321         /*
1322          * Set up output selector (0x1a, 0x1b, 0x29)
1323          */
1324         /* set vol=0 to output mixers */
1325         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1326         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1327         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1328
1329         /*
1330          *  Unmute PW3 and PW4
1331          */
1332         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1333         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1334
1335         /* Set input of PW4 as MW0 */
1336         {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1337         /* Set mic as default input of sw0 */
1338         {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
1339         /* PW9 Output enable */
1340         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1341         { }
1342 };
1343
1344 static int patch_vt1709_6ch(struct hda_codec *codec)
1345 {
1346         struct via_spec *spec;
1347         int err;
1348
1349         /* create a codec specific record */
1350         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1351         if (spec == NULL)
1352                 return -ENOMEM;
1353
1354         codec->spec = spec;
1355
1356         err = vt1709_parse_auto_config(codec);
1357         if (err < 0) {
1358                 via_free(codec);
1359                 return err;
1360         } else if (!err) {
1361                 printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1362                        "Using genenic mode...\n");
1363         }
1364
1365         spec->init_verbs = vt1709_6ch_volume_init_verbs;        
1366
1367         spec->stream_name_analog = "VT1709 Analog";
1368         spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1369         spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1370
1371         spec->stream_name_digital = "VT1709 Digital";
1372         spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1373         spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1374
1375         
1376         if (!spec->adc_nids && spec->input_mux) {
1377                 spec->adc_nids = vt1709_adc_nids;
1378                 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1379                 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1380                 spec->num_mixers++;
1381         }
1382
1383         codec->patch_ops = via_patch_ops;
1384
1385         codec->patch_ops.init = via_auto_init;
1386
1387         return 0;
1388 }
1389
1390 /*
1391  * patch entries
1392  */
1393 struct hda_codec_preset snd_hda_preset_via[] = {
1394         { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1395         { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1396         { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1397         { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
1398         { .id = 0x1106E710, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1399         { .id = 0x1106E711, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1400         { .id = 0x1106E712, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1401         { .id = 0x1106E713, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1402         { .id = 0x1106E714, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1403         { .id = 0x1106E715, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1404         { .id = 0x1106E716, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1405         { .id = 0x1106E717, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1406         {} /* terminator */
1407 };