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