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