]> err.no Git - linux-2.6/blob - sound/pci/hda/patch_via.c
[ALSA] hda-codec - Add internal mic item for ALC268 acer model
[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 /* 2007-09-12  Lydia Wang  Add EAPD enable during driver initialization      */
31 /* 2007-09-17  Lydia Wang  Add VT1708B codec support                        */
32 /*                                                                           */
33 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
34
35
36 #include <linux/init.h>
37 #include <linux/delay.h>
38 #include <linux/slab.h>
39 #include <sound/core.h>
40 #include "hda_codec.h"
41 #include "hda_local.h"
42 #include "hda_patch.h"
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 #define VT1708_DIGIN_PIN        0x26
56
57 #define VT1709_HP_DAC_NID       0x28
58 #define VT1709_DIGOUT_NID       0x13
59 #define VT1709_DIGIN_NID        0x17
60 #define VT1709_DIGIN_PIN        0x25
61
62 #define VT1708B_HP_NID          0x25
63 #define VT1708B_DIGOUT_NID      0x12
64 #define VT1708B_DIGIN_NID       0x15
65 #define VT1708B_DIGIN_PIN       0x21
66
67 #define IS_VT1708_VENDORID(x)           ((x) >= 0x11061708 && (x) <= 0x1106170b)
68 #define IS_VT1709_10CH_VENDORID(x)      ((x) >= 0x1106e710 && (x) <= 0x1106e713)
69 #define IS_VT1709_6CH_VENDORID(x)       ((x) >= 0x1106e714 && (x) <= 0x1106e717)
70 #define IS_VT1708B_8CH_VENDORID(x)      ((x) >= 0x1106e720 && (x) <= 0x1106e723)
71 #define IS_VT1708B_4CH_VENDORID(x)      ((x) >= 0x1106e724 && (x) <= 0x1106e727)
72
73
74 enum {
75         VIA_CTL_WIDGET_VOL,
76         VIA_CTL_WIDGET_MUTE,
77 };
78
79 enum {
80         AUTO_SEQ_FRONT,
81         AUTO_SEQ_SURROUND,
82         AUTO_SEQ_CENLFE,
83         AUTO_SEQ_SIDE
84 };
85
86 static struct snd_kcontrol_new vt1708_control_templates[] = {
87         HDA_CODEC_VOLUME(NULL, 0, 0, 0),
88         HDA_CODEC_MUTE(NULL, 0, 0, 0),
89 };
90
91
92 struct via_spec {
93         /* codec parameterization */
94         struct snd_kcontrol_new *mixers[3];
95         unsigned int num_mixers;
96
97         struct hda_verb *init_verbs;
98
99         char *stream_name_analog;
100         struct hda_pcm_stream *stream_analog_playback;
101         struct hda_pcm_stream *stream_analog_capture;
102
103         char *stream_name_digital;
104         struct hda_pcm_stream *stream_digital_playback;
105         struct hda_pcm_stream *stream_digital_capture;
106
107         /* playback */
108         struct hda_multi_out multiout;
109
110         /* capture */
111         unsigned int num_adc_nids;
112         hda_nid_t *adc_nids;
113         hda_nid_t dig_in_nid;
114
115         /* capture source */
116         const struct hda_input_mux *input_mux;
117         unsigned int cur_mux[3];
118
119         /* PCM information */
120         struct hda_pcm pcm_rec[2];
121
122         /* dynamic controls, init_verbs and input_mux */
123         struct auto_pin_cfg autocfg;
124         unsigned int num_kctl_alloc, num_kctl_used;
125         struct snd_kcontrol_new *kctl_alloc;
126         struct hda_input_mux private_imux;
127         hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
128
129 #ifdef CONFIG_SND_HDA_POWER_SAVE
130         struct hda_loopback_check loopback;
131 #endif
132 };
133
134 static hda_nid_t vt1708_adc_nids[2] = {
135         /* ADC1-2 */
136         0x15, 0x27
137 };
138
139 static hda_nid_t vt1709_adc_nids[3] = {
140         /* ADC1-2 */
141         0x14, 0x15, 0x16
142 };
143
144 static hda_nid_t vt1708B_adc_nids[2] = {
145         /* ADC1-2 */
146         0x13, 0x14
147 };
148
149 /* add dynamic controls */
150 static int via_add_control(struct via_spec *spec, int type, const char *name,
151                            unsigned long val)
152 {
153         struct snd_kcontrol_new *knew;
154
155         if (spec->num_kctl_used >= spec->num_kctl_alloc) {
156                 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
157
158                 /* array + terminator */
159                 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
160                 if (!knew)
161                         return -ENOMEM;
162                 if (spec->kctl_alloc) {
163                         memcpy(knew, spec->kctl_alloc,
164                                sizeof(*knew) * spec->num_kctl_alloc);
165                         kfree(spec->kctl_alloc);
166                 }
167                 spec->kctl_alloc = knew;
168                 spec->num_kctl_alloc = num;
169         }
170
171         knew = &spec->kctl_alloc[spec->num_kctl_used];
172         *knew = vt1708_control_templates[type];
173         knew->name = kstrdup(name, GFP_KERNEL);
174
175         if (!knew->name)
176                 return -ENOMEM;
177         knew->private_value = val;
178         spec->num_kctl_used++;
179         return 0;
180 }
181
182 /* create input playback/capture controls for the given pin */
183 static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
184                                 const char *ctlname, int idx, int mix_nid)
185 {
186         char name[32];
187         int err;
188
189         sprintf(name, "%s Playback Volume", ctlname);
190         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
191                               HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
192         if (err < 0)
193                 return err;
194         sprintf(name, "%s Playback Switch", ctlname);
195         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
196                               HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
197         if (err < 0)
198                 return err;
199         return 0;
200 }
201
202 static void via_auto_set_output_and_unmute(struct hda_codec *codec,
203                                            hda_nid_t nid, int pin_type,
204                                            int dac_idx)
205 {
206         /* set as output */
207         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
208                             pin_type);
209         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
210                             AMP_OUT_UNMUTE);
211 }
212
213
214 static void via_auto_init_multi_out(struct hda_codec *codec)
215 {
216         struct via_spec *spec = codec->spec;
217         int i;
218
219         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
220                 hda_nid_t nid = spec->autocfg.line_out_pins[i];
221                 if (nid)
222                         via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
223         }
224 }
225
226 static void via_auto_init_hp_out(struct hda_codec *codec)
227 {
228         struct via_spec *spec = codec->spec;
229         hda_nid_t pin;
230
231         pin = spec->autocfg.hp_pins[0];
232         if (pin) /* connect to front */
233                 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
234 }
235
236 static void via_auto_init_analog_input(struct hda_codec *codec)
237 {
238         struct via_spec *spec = codec->spec;
239         int i;
240
241         for (i = 0; i < AUTO_PIN_LAST; i++) {
242                 hda_nid_t nid = spec->autocfg.input_pins[i];
243
244                 snd_hda_codec_write(codec, nid, 0,
245                                     AC_VERB_SET_PIN_WIDGET_CONTROL,
246                                     (i <= AUTO_PIN_FRONT_MIC ?
247                                      PIN_VREF50 : PIN_IN));
248
249         }
250 }
251 /*
252  * input MUX handling
253  */
254 static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
255                              struct snd_ctl_elem_info *uinfo)
256 {
257         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
258         struct via_spec *spec = codec->spec;
259         return snd_hda_input_mux_info(spec->input_mux, uinfo);
260 }
261
262 static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
263                             struct snd_ctl_elem_value *ucontrol)
264 {
265         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
266         struct via_spec *spec = codec->spec;
267         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
268
269         ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
270         return 0;
271 }
272
273 static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
274                             struct snd_ctl_elem_value *ucontrol)
275 {
276         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
277         struct via_spec *spec = codec->spec;
278         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
279         unsigned int vendor_id = codec->vendor_id;
280
281         /* AIW0  lydia 060801 add for correct sw0 input select */
282         if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
283                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
284                                              0x18, &spec->cur_mux[adc_idx]);
285         else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
286                   IS_VT1709_6CH_VENDORID(vendor_id)) && adc_idx == 0)
287                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
288                                              0x19, &spec->cur_mux[adc_idx]);
289         else if ((IS_VT1708B_8CH_VENDORID(vendor_id) ||
290                   IS_VT1708B_4CH_VENDORID(vendor_id)) && adc_idx == 0)
291                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
292                                              0x17, &spec->cur_mux[adc_idx]);
293         else
294                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
295                                              spec->adc_nids[adc_idx],
296                                              &spec->cur_mux[adc_idx]);
297 }
298
299 /* capture mixer elements */
300 static struct snd_kcontrol_new vt1708_capture_mixer[] = {
301         HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
302         HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
303         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
304         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
305         {
306                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
307                 /* The multiple "Capture Source" controls confuse alsamixer
308                  * So call somewhat different..
309                  */
310                 /* .name = "Capture Source", */
311                 .name = "Input Source",
312                 .count = 1,
313                 .info = via_mux_enum_info,
314                 .get = via_mux_enum_get,
315                 .put = via_mux_enum_put,
316         },
317         { } /* end */
318 };
319 /*
320  * generic initialization of ADC, input mixers and output mixers
321  */
322 static struct hda_verb vt1708_volume_init_verbs[] = {
323         /*
324          * Unmute ADC0-1 and set the default input to mic-in
325          */
326         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
327         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
328
329
330         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
331          * mixer widget
332          */
333         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
334         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
335         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
336         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
337         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
338         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
339
340         /*
341          * Set up output mixers (0x19 - 0x1b)
342          */
343         /* set vol=0 to output mixers */
344         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
345         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
346         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
347         
348         /* Setup default input to PW4 */
349         {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
350         /* PW9 Output enable */
351         {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
352         { }
353 };
354
355 static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
356                                  struct hda_codec *codec,
357                                  struct snd_pcm_substream *substream)
358 {
359         struct via_spec *spec = codec->spec;
360         return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
361                                              hinfo);
362 }
363
364 static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
365                                     struct hda_codec *codec,
366                                     unsigned int stream_tag,
367                                     unsigned int format,
368                                     struct snd_pcm_substream *substream)
369 {
370         struct via_spec *spec = codec->spec;
371         return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
372                                                 stream_tag, format, substream);
373 }
374
375 static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
376                                     struct hda_codec *codec,
377                                     struct snd_pcm_substream *substream)
378 {
379         struct via_spec *spec = codec->spec;
380         return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
381 }
382
383 /*
384  * Digital out
385  */
386 static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
387                                      struct hda_codec *codec,
388                                      struct snd_pcm_substream *substream)
389 {
390         struct via_spec *spec = codec->spec;
391         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
392 }
393
394 static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
395                                       struct hda_codec *codec,
396                                       struct snd_pcm_substream *substream)
397 {
398         struct via_spec *spec = codec->spec;
399         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
400 }
401
402 static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
403                                         struct hda_codec *codec,
404                                         unsigned int stream_tag,
405                                         unsigned int format,
406                                         struct snd_pcm_substream *substream)
407 {
408         struct via_spec *spec = codec->spec;
409         return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
410                                              stream_tag, format, substream);
411 }
412
413 /*
414  * Analog capture
415  */
416 static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
417                                    struct hda_codec *codec,
418                                    unsigned int stream_tag,
419                                    unsigned int format,
420                                    struct snd_pcm_substream *substream)
421 {
422         struct via_spec *spec = codec->spec;
423
424         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
425                                    stream_tag, 0, format);
426         return 0;
427 }
428
429 static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
430                                    struct hda_codec *codec,
431                                    struct snd_pcm_substream *substream)
432 {
433         struct via_spec *spec = codec->spec;
434         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
435                                    0, 0, 0);
436         return 0;
437 }
438
439 static struct hda_pcm_stream vt1708_pcm_analog_playback = {
440         .substreams = 1,
441         .channels_min = 2,
442         .channels_max = 8,
443         .nid = 0x10, /* NID to query formats and rates */
444         .ops = {
445                 .open = via_playback_pcm_open,
446                 .prepare = via_playback_pcm_prepare,
447                 .cleanup = via_playback_pcm_cleanup
448         },
449 };
450
451 static struct hda_pcm_stream vt1708_pcm_analog_capture = {
452         .substreams = 2,
453         .channels_min = 2,
454         .channels_max = 2,
455         .nid = 0x15, /* NID to query formats and rates */
456         .ops = {
457                 .prepare = via_capture_pcm_prepare,
458                 .cleanup = via_capture_pcm_cleanup
459         },
460 };
461
462 static struct hda_pcm_stream vt1708_pcm_digital_playback = {
463         .substreams = 1,
464         .channels_min = 2,
465         .channels_max = 2,
466         /* NID is set in via_build_pcms */
467         .ops = {
468                 .open = via_dig_playback_pcm_open,
469                 .close = via_dig_playback_pcm_close,
470                 .prepare = via_dig_playback_pcm_prepare
471         },
472 };
473
474 static struct hda_pcm_stream vt1708_pcm_digital_capture = {
475         .substreams = 1,
476         .channels_min = 2,
477         .channels_max = 2,
478 };
479
480 static int via_build_controls(struct hda_codec *codec)
481 {
482         struct via_spec *spec = codec->spec;
483         int err;
484         int i;
485
486         for (i = 0; i < spec->num_mixers; i++) {
487                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
488                 if (err < 0)
489                         return err;
490         }
491
492         if (spec->multiout.dig_out_nid) {
493                 err = snd_hda_create_spdif_out_ctls(codec,
494                                                     spec->multiout.dig_out_nid);
495                 if (err < 0)
496                         return err;
497                 err = snd_hda_create_spdif_share_sw(codec,
498                                                     &spec->multiout);
499                 if (err < 0)
500                         return err;
501                 spec->multiout.share_spdif = 1;
502         }
503         if (spec->dig_in_nid) {
504                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
505                 if (err < 0)
506                         return err;
507         }
508         return 0;
509 }
510
511 static int via_build_pcms(struct hda_codec *codec)
512 {
513         struct via_spec *spec = codec->spec;
514         struct hda_pcm *info = spec->pcm_rec;
515
516         codec->num_pcms = 1;
517         codec->pcm_info = info;
518
519         info->name = spec->stream_name_analog;
520         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
521         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
522         info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
523         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
524
525         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
526                 spec->multiout.max_channels;
527
528         if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
529                 codec->num_pcms++;
530                 info++;
531                 info->name = spec->stream_name_digital;
532                 info->pcm_type = HDA_PCM_TYPE_SPDIF;
533                 if (spec->multiout.dig_out_nid) {
534                         info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
535                                 *(spec->stream_digital_playback);
536                         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
537                                 spec->multiout.dig_out_nid;
538                 }
539                 if (spec->dig_in_nid) {
540                         info->stream[SNDRV_PCM_STREAM_CAPTURE] =
541                                 *(spec->stream_digital_capture);
542                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
543                                 spec->dig_in_nid;
544                 }
545         }
546
547         return 0;
548 }
549
550 static void via_free(struct hda_codec *codec)
551 {
552         struct via_spec *spec = codec->spec;
553         unsigned int i;
554
555         if (!spec)
556                 return;
557
558         if (spec->kctl_alloc) {
559                 for (i = 0; i < spec->num_kctl_used; i++)
560                         kfree(spec->kctl_alloc[i].name);
561                 kfree(spec->kctl_alloc);
562         }
563
564         kfree(codec->spec);
565 }
566
567 static int via_init(struct hda_codec *codec)
568 {
569         struct via_spec *spec = codec->spec;
570         snd_hda_sequence_write(codec, spec->init_verbs);
571         /* Lydia Add for EAPD enable */
572         if (!spec->dig_in_nid) { /* No Digital In connection */
573                 if (IS_VT1708_VENDORID(codec->vendor_id)) {
574                         snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
575                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
576                                             PIN_OUT);
577                         snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
578                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
579                 } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
580                            IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
581                         snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
582                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
583                                             PIN_OUT);
584                         snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
585                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
586                 } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
587                            IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
588                         snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
589                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
590                                             PIN_OUT);
591                         snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
592                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
593                 }
594         } else /* enable SPDIF-input pin */
595                 snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
596                                     AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
597
598         return 0;
599 }
600
601 #ifdef CONFIG_SND_HDA_POWER_SAVE
602 static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
603 {
604         struct via_spec *spec = codec->spec;
605         return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
606 }
607 #endif
608
609 /*
610  */
611 static struct hda_codec_ops via_patch_ops = {
612         .build_controls = via_build_controls,
613         .build_pcms = via_build_pcms,
614         .init = via_init,
615         .free = via_free,
616 #ifdef CONFIG_SND_HDA_POWER_SAVE
617         .check_power_status = via_check_power_status,
618 #endif
619 };
620
621 /* fill in the dac_nids table from the parsed pin configuration */
622 static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
623                                      const struct auto_pin_cfg *cfg)
624 {
625         int i;
626         hda_nid_t nid;
627
628         spec->multiout.num_dacs = cfg->line_outs;
629
630         spec->multiout.dac_nids = spec->private_dac_nids;
631         
632         for(i = 0; i < 4; i++) {
633                 nid = cfg->line_out_pins[i];
634                 if (nid) {
635                         /* config dac list */
636                         switch (i) {
637                         case AUTO_SEQ_FRONT:
638                                 spec->multiout.dac_nids[i] = 0x10;
639                                 break;
640                         case AUTO_SEQ_CENLFE:
641                                 spec->multiout.dac_nids[i] = 0x12;
642                                 break;
643                         case AUTO_SEQ_SURROUND:
644                                 spec->multiout.dac_nids[i] = 0x13;
645                                 break;
646                         case AUTO_SEQ_SIDE:
647                                 spec->multiout.dac_nids[i] = 0x11;
648                                 break;
649                         }
650                 }
651         }
652
653         return 0;
654 }
655
656 /* add playback controls from the parsed DAC table */
657 static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
658                                              const struct auto_pin_cfg *cfg)
659 {
660         char name[32];
661         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
662         hda_nid_t nid, nid_vol = 0;
663         int i, err;
664
665         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
666                 nid = cfg->line_out_pins[i];
667
668                 if (!nid)
669                         continue;
670                 
671                 if (i != AUTO_SEQ_FRONT)
672                         nid_vol = 0x1b - i + 1;
673
674                 if (i == AUTO_SEQ_CENLFE) {
675                         /* Center/LFE */
676                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
677                                         "Center Playback Volume",
678                                         HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
679                                                             HDA_OUTPUT));
680                         if (err < 0)
681                                 return err;
682                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
683                                               "LFE Playback Volume",
684                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
685                                                                   HDA_OUTPUT));
686                         if (err < 0)
687                                 return err;
688                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
689                                               "Center Playback Switch",
690                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
691                                                                   HDA_OUTPUT));
692                         if (err < 0)
693                                 return err;
694                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
695                                               "LFE Playback Switch",
696                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
697                                                                   HDA_OUTPUT));
698                         if (err < 0)
699                                 return err;
700                 } else if (i == AUTO_SEQ_FRONT){
701                         /* add control to mixer index 0 */
702                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
703                                               "Master Front Playback Volume",
704                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
705                                                                   HDA_INPUT));
706                         if (err < 0)
707                                 return err;
708                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
709                                               "Master Front Playback Switch",
710                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
711                                                                   HDA_INPUT));
712                         if (err < 0)
713                                 return err;
714                         
715                         /* add control to PW3 */
716                         sprintf(name, "%s Playback Volume", chname[i]);
717                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
718                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
719                                                                   HDA_OUTPUT));
720                         if (err < 0)
721                                 return err;
722                         sprintf(name, "%s Playback Switch", chname[i]);
723                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
724                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
725                                                                   HDA_OUTPUT));
726                         if (err < 0)
727                                 return err;
728                 } else {
729                         sprintf(name, "%s Playback Volume", chname[i]);
730                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
731                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
732                                                                   HDA_OUTPUT));
733                         if (err < 0)
734                                 return err;
735                         sprintf(name, "%s Playback Switch", chname[i]);
736                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
737                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
738                                                                   HDA_OUTPUT));
739                         if (err < 0)
740                                 return err;
741                 }
742         }
743
744         return 0;
745 }
746
747 static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
748 {
749         int err;
750
751         if (!pin)
752                 return 0;
753
754         spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
755
756         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
757                               "Headphone Playback Volume",
758                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
759         if (err < 0)
760                 return err;
761         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
762                               "Headphone Playback Switch",
763                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
764         if (err < 0)
765                 return err;
766
767         return 0;
768 }
769
770 /* create playback/capture controls for input pins */
771 static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
772                                                 const struct auto_pin_cfg *cfg)
773 {
774         static char *labels[] = {
775                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
776         };
777         struct hda_input_mux *imux = &spec->private_imux;
778         int i, err, idx = 0;
779
780         /* for internal loopback recording select */
781         imux->items[imux->num_items].label = "Stereo Mixer";
782         imux->items[imux->num_items].index = idx;
783         imux->num_items++;
784
785         for (i = 0; i < AUTO_PIN_LAST; i++) {
786                 if (!cfg->input_pins[i])
787                         continue;
788
789                 switch (cfg->input_pins[i]) {
790                 case 0x1d: /* Mic */
791                         idx = 2;
792                         break;
793                                 
794                 case 0x1e: /* Line In */
795                         idx = 3;
796                         break;
797
798                 case 0x21: /* Front Mic */
799                         idx = 4;
800                         break;
801
802                 case 0x24: /* CD */
803                         idx = 1;
804                         break;
805                 }
806                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
807                                            idx, 0x17);
808                 if (err < 0)
809                         return err;
810                 imux->items[imux->num_items].label = labels[i];
811                 imux->items[imux->num_items].index = idx;
812                 imux->num_items++;
813         }
814         return 0;
815 }
816
817 #ifdef CONFIG_SND_HDA_POWER_SAVE
818 static struct hda_amp_list vt1708_loopbacks[] = {
819         { 0x17, HDA_INPUT, 1 },
820         { 0x17, HDA_INPUT, 2 },
821         { 0x17, HDA_INPUT, 3 },
822         { 0x17, HDA_INPUT, 4 },
823         { } /* end */
824 };
825 #endif
826
827 static int vt1708_parse_auto_config(struct hda_codec *codec)
828 {
829         struct via_spec *spec = codec->spec;
830         int err;
831
832         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
833         if (err < 0)
834                 return err;
835         err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
836         if (err < 0)
837                 return err;
838         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
839                 return 0; /* can't find valid BIOS pin config */
840
841         err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
842         if (err < 0)
843                 return err;
844         err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
845         if (err < 0)
846                 return err;
847         err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
848         if (err < 0)
849                 return err;
850
851         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
852
853         if (spec->autocfg.dig_out_pin)
854                 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
855         if (spec->autocfg.dig_in_pin)
856                 spec->dig_in_nid = VT1708_DIGIN_NID;
857
858         if (spec->kctl_alloc)
859                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
860
861         spec->init_verbs = vt1708_volume_init_verbs;    
862
863         spec->input_mux = &spec->private_imux;
864
865         return 1;
866 }
867
868 /* init callback for auto-configuration model -- overriding the default init */
869 static int via_auto_init(struct hda_codec *codec)
870 {
871         via_init(codec);
872         via_auto_init_multi_out(codec);
873         via_auto_init_hp_out(codec);
874         via_auto_init_analog_input(codec);
875         return 0;
876 }
877
878 static int patch_vt1708(struct hda_codec *codec)
879 {
880         struct via_spec *spec;
881         int err;
882
883         /* create a codec specific record */
884         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
885         if (spec == NULL)
886                 return -ENOMEM;
887
888         codec->spec = spec;
889
890         /* automatic parse from the BIOS config */
891         err = vt1708_parse_auto_config(codec);
892         if (err < 0) {
893                 via_free(codec);
894                 return err;
895         } else if (!err) {
896                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
897                        "from BIOS.  Using genenic mode...\n");
898         }
899
900         
901         spec->stream_name_analog = "VT1708 Analog";
902         spec->stream_analog_playback = &vt1708_pcm_analog_playback;
903         spec->stream_analog_capture = &vt1708_pcm_analog_capture;
904
905         spec->stream_name_digital = "VT1708 Digital";
906         spec->stream_digital_playback = &vt1708_pcm_digital_playback;
907         spec->stream_digital_capture = &vt1708_pcm_digital_capture;
908
909         
910         if (!spec->adc_nids && spec->input_mux) {
911                 spec->adc_nids = vt1708_adc_nids;
912                 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
913                 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
914                 spec->num_mixers++;
915         }
916
917         codec->patch_ops = via_patch_ops;
918
919         codec->patch_ops.init = via_auto_init;
920 #ifdef CONFIG_SND_HDA_POWER_SAVE
921         spec->loopback.amplist = vt1708_loopbacks;
922 #endif
923
924         return 0;
925 }
926
927 /* capture mixer elements */
928 static struct snd_kcontrol_new vt1709_capture_mixer[] = {
929         HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
930         HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
931         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
932         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
933         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
934         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
935         {
936                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
937                 /* The multiple "Capture Source" controls confuse alsamixer
938                  * So call somewhat different..
939                  */
940                 /* .name = "Capture Source", */
941                 .name = "Input Source",
942                 .count = 1,
943                 .info = via_mux_enum_info,
944                 .get = via_mux_enum_get,
945                 .put = via_mux_enum_put,
946         },
947         { } /* end */
948 };
949
950 /*
951  * generic initialization of ADC, input mixers and output mixers
952  */
953 static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
954         /*
955          * Unmute ADC0-2 and set the default input to mic-in
956          */
957         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
958         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
959         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
960
961
962         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
963          * mixer widget
964          */
965         /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
966         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
967         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
968         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
969         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
970         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
971
972         /*
973          * Set up output selector (0x1a, 0x1b, 0x29)
974          */
975         /* set vol=0 to output mixers */
976         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
977         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
978         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
979
980         /*
981          *  Unmute PW3 and PW4
982          */
983         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
984         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
985
986         /* Set input of PW4 as AOW4 */
987         {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
988         /* PW9 Output enable */
989         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
990         { }
991 };
992
993 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
994         .substreams = 1,
995         .channels_min = 2,
996         .channels_max = 10,
997         .nid = 0x10, /* NID to query formats and rates */
998         .ops = {
999                 .open = via_playback_pcm_open,
1000                 .prepare = via_playback_pcm_prepare,
1001                 .cleanup = via_playback_pcm_cleanup
1002         },
1003 };
1004
1005 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
1006         .substreams = 1,
1007         .channels_min = 2,
1008         .channels_max = 6,
1009         .nid = 0x10, /* NID to query formats and rates */
1010         .ops = {
1011                 .open = via_playback_pcm_open,
1012                 .prepare = via_playback_pcm_prepare,
1013                 .cleanup = via_playback_pcm_cleanup
1014         },
1015 };
1016
1017 static struct hda_pcm_stream vt1709_pcm_analog_capture = {
1018         .substreams = 2,
1019         .channels_min = 2,
1020         .channels_max = 2,
1021         .nid = 0x14, /* NID to query formats and rates */
1022         .ops = {
1023                 .prepare = via_capture_pcm_prepare,
1024                 .cleanup = via_capture_pcm_cleanup
1025         },
1026 };
1027
1028 static struct hda_pcm_stream vt1709_pcm_digital_playback = {
1029         .substreams = 1,
1030         .channels_min = 2,
1031         .channels_max = 2,
1032         /* NID is set in via_build_pcms */
1033         .ops = {
1034                 .open = via_dig_playback_pcm_open,
1035                 .close = via_dig_playback_pcm_close
1036         },
1037 };
1038
1039 static struct hda_pcm_stream vt1709_pcm_digital_capture = {
1040         .substreams = 1,
1041         .channels_min = 2,
1042         .channels_max = 2,
1043 };
1044
1045 static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
1046                                      const struct auto_pin_cfg *cfg)
1047 {
1048         int i;
1049         hda_nid_t nid;
1050
1051         if (cfg->line_outs == 4)  /* 10 channels */
1052                 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
1053         else if (cfg->line_outs == 3) /* 6 channels */
1054                 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
1055
1056         spec->multiout.dac_nids = spec->private_dac_nids;
1057
1058         if (cfg->line_outs == 4) { /* 10 channels */
1059                 for (i = 0; i < cfg->line_outs; i++) {
1060                         nid = cfg->line_out_pins[i];
1061                         if (nid) {
1062                                 /* config dac list */
1063                                 switch (i) {
1064                                 case AUTO_SEQ_FRONT:
1065                                         /* AOW0 */
1066                                         spec->multiout.dac_nids[i] = 0x10;
1067                                         break;
1068                                 case AUTO_SEQ_CENLFE:
1069                                         /* AOW2 */
1070                                         spec->multiout.dac_nids[i] = 0x12;
1071                                         break;
1072                                 case AUTO_SEQ_SURROUND:
1073                                         /* AOW3 */
1074                                         spec->multiout.dac_nids[i] = 0x27;
1075                                         break;
1076                                 case AUTO_SEQ_SIDE:
1077                                         /* AOW1 */
1078                                         spec->multiout.dac_nids[i] = 0x11;
1079                                         break;
1080                                 default:
1081                                         break;
1082                                 }
1083                         }
1084                 }
1085                 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1086
1087         } else if (cfg->line_outs == 3) { /* 6 channels */
1088                 for(i = 0; i < cfg->line_outs; i++) {
1089                         nid = cfg->line_out_pins[i];
1090                         if (nid) {
1091                                 /* config dac list */
1092                                 switch(i) {
1093                                 case AUTO_SEQ_FRONT:
1094                                         /* AOW0 */
1095                                         spec->multiout.dac_nids[i] = 0x10;
1096                                         break;
1097                                 case AUTO_SEQ_CENLFE:
1098                                         /* AOW2 */
1099                                         spec->multiout.dac_nids[i] = 0x12;
1100                                         break;
1101                                 case AUTO_SEQ_SURROUND:
1102                                         /* AOW1 */
1103                                         spec->multiout.dac_nids[i] = 0x11;
1104                                         break;
1105                                 default:
1106                                         break;
1107                                 }
1108                         }
1109                 }
1110         }
1111
1112         return 0;
1113 }
1114
1115 /* add playback controls from the parsed DAC table */
1116 static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1117                                              const struct auto_pin_cfg *cfg)
1118 {
1119         char name[32];
1120         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1121         hda_nid_t nid = 0;
1122         int i, err;
1123
1124         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1125                 nid = cfg->line_out_pins[i];
1126
1127                 if (!nid)       
1128                         continue;
1129
1130                 if (i == AUTO_SEQ_CENLFE) {
1131                         /* Center/LFE */
1132                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1133                                               "Center Playback Volume",
1134                                               HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1135                                                                   HDA_OUTPUT));
1136                         if (err < 0)
1137                                 return err;
1138                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1139                                               "LFE Playback Volume",
1140                                               HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1141                                                                   HDA_OUTPUT));
1142                         if (err < 0)
1143                                 return err;
1144                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1145                                               "Center Playback Switch",
1146                                               HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1147                                                                   HDA_OUTPUT));
1148                         if (err < 0)
1149                                 return err;
1150                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1151                                               "LFE Playback Switch",
1152                                               HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1153                                                                   HDA_OUTPUT));
1154                         if (err < 0)
1155                                 return err;
1156                 } else if (i == AUTO_SEQ_FRONT){
1157                         /* add control to mixer index 0 */
1158                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1159                                               "Master Front Playback Volume",
1160                                               HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1161                                                                   HDA_INPUT));
1162                         if (err < 0)
1163                                 return err;
1164                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1165                                               "Master Front Playback Switch",
1166                                               HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1167                                                                   HDA_INPUT));
1168                         if (err < 0)
1169                                 return err;
1170                         
1171                         /* add control to PW3 */
1172                         sprintf(name, "%s Playback Volume", chname[i]);
1173                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1174                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1175                                                                   HDA_OUTPUT));
1176                         if (err < 0)
1177                                 return err;
1178                         sprintf(name, "%s Playback Switch", chname[i]);
1179                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1180                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1181                                                                   HDA_OUTPUT));
1182                         if (err < 0)
1183                                 return err;
1184                 } else if (i == AUTO_SEQ_SURROUND) {
1185                         sprintf(name, "%s Playback Volume", chname[i]);
1186                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1187                                               HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1188                                                                   HDA_OUTPUT));
1189                         if (err < 0)
1190                                 return err;
1191                         sprintf(name, "%s Playback Switch", chname[i]);
1192                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1193                                               HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1194                                                                   HDA_OUTPUT));
1195                         if (err < 0)
1196                                 return err;
1197                 } else if (i == AUTO_SEQ_SIDE) {
1198                         sprintf(name, "%s Playback Volume", chname[i]);
1199                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1200                                               HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1201                                                                   HDA_OUTPUT));
1202                         if (err < 0)
1203                                 return err;
1204                         sprintf(name, "%s Playback Switch", chname[i]);
1205                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1206                                               HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1207                                                                   HDA_OUTPUT));
1208                         if (err < 0)
1209                                 return err;
1210                 }
1211         }
1212
1213         return 0;
1214 }
1215
1216 static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1217 {
1218         int err;
1219
1220         if (!pin)
1221                 return 0;
1222
1223         if (spec->multiout.num_dacs == 5) /* 10 channels */
1224                 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1225         else if (spec->multiout.num_dacs == 3) /* 6 channels */
1226                 spec->multiout.hp_nid = 0;
1227
1228         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1229                               "Headphone Playback Volume",
1230                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1231         if (err < 0)
1232                 return err;
1233         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1234                               "Headphone Playback Switch",
1235                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1236         if (err < 0)
1237                 return err;
1238
1239         return 0;
1240 }
1241
1242 /* create playback/capture controls for input pins */
1243 static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1244                                                 const struct auto_pin_cfg *cfg)
1245 {
1246         static char *labels[] = {
1247                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1248         };
1249         struct hda_input_mux *imux = &spec->private_imux;
1250         int i, err, idx = 0;
1251
1252         /* for internal loopback recording select */
1253         imux->items[imux->num_items].label = "Stereo Mixer";
1254         imux->items[imux->num_items].index = idx;
1255         imux->num_items++;
1256
1257         for (i = 0; i < AUTO_PIN_LAST; i++) {
1258                 if (!cfg->input_pins[i])
1259                         continue;
1260
1261                 switch (cfg->input_pins[i]) {
1262                 case 0x1d: /* Mic */
1263                         idx = 2;
1264                         break;
1265                                 
1266                 case 0x1e: /* Line In */
1267                         idx = 3;
1268                         break;
1269
1270                 case 0x21: /* Front Mic */
1271                         idx = 4;
1272                         break;
1273
1274                 case 0x23: /* CD */
1275                         idx = 1;
1276                         break;
1277                 }
1278                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1279                                            idx, 0x18);
1280                 if (err < 0)
1281                         return err;
1282                 imux->items[imux->num_items].label = labels[i];
1283                 imux->items[imux->num_items].index = idx;
1284                 imux->num_items++;
1285         }
1286         return 0;
1287 }
1288
1289 static int vt1709_parse_auto_config(struct hda_codec *codec)
1290 {
1291         struct via_spec *spec = codec->spec;
1292         int err;
1293
1294         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1295         if (err < 0)
1296                 return err;
1297         err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1298         if (err < 0)
1299                 return err;
1300         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1301                 return 0; /* can't find valid BIOS pin config */
1302
1303         err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1304         if (err < 0)
1305                 return err;
1306         err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1307         if (err < 0)
1308                 return err;
1309         err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1310         if (err < 0)
1311                 return err;
1312
1313         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1314
1315         if (spec->autocfg.dig_out_pin)
1316                 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1317         if (spec->autocfg.dig_in_pin)
1318                 spec->dig_in_nid = VT1709_DIGIN_NID;
1319
1320         if (spec->kctl_alloc)
1321                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1322
1323         spec->input_mux = &spec->private_imux;
1324
1325         return 1;
1326 }
1327
1328 #ifdef CONFIG_SND_HDA_POWER_SAVE
1329 static struct hda_amp_list vt1709_loopbacks[] = {
1330         { 0x18, HDA_INPUT, 1 },
1331         { 0x18, HDA_INPUT, 2 },
1332         { 0x18, HDA_INPUT, 3 },
1333         { 0x18, HDA_INPUT, 4 },
1334         { } /* end */
1335 };
1336 #endif
1337
1338 static int patch_vt1709_10ch(struct hda_codec *codec)
1339 {
1340         struct via_spec *spec;
1341         int err;
1342
1343         /* create a codec specific record */
1344         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1345         if (spec == NULL)
1346                 return -ENOMEM;
1347
1348         codec->spec = spec;
1349
1350         err = vt1709_parse_auto_config(codec);
1351         if (err < 0) {
1352                 via_free(codec);
1353                 return err;
1354         } else if (!err) {
1355                 printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1356                        "Using genenic mode...\n");
1357         }
1358
1359         spec->init_verbs = vt1709_10ch_volume_init_verbs;       
1360
1361         spec->stream_name_analog = "VT1709 Analog";
1362         spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1363         spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1364
1365         spec->stream_name_digital = "VT1709 Digital";
1366         spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1367         spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1368
1369         
1370         if (!spec->adc_nids && spec->input_mux) {
1371                 spec->adc_nids = vt1709_adc_nids;
1372                 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1373                 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1374                 spec->num_mixers++;
1375         }
1376
1377         codec->patch_ops = via_patch_ops;
1378
1379         codec->patch_ops.init = via_auto_init;
1380 #ifdef CONFIG_SND_HDA_POWER_SAVE
1381         spec->loopback.amplist = vt1709_loopbacks;
1382 #endif
1383
1384         return 0;
1385 }
1386 /*
1387  * generic initialization of ADC, input mixers and output mixers
1388  */
1389 static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1390         /*
1391          * Unmute ADC0-2 and set the default input to mic-in
1392          */
1393         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1394         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1395         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1396
1397
1398         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1399          * mixer widget
1400          */
1401         /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1402         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1403         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1404         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1405         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1406         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1407
1408         /*
1409          * Set up output selector (0x1a, 0x1b, 0x29)
1410          */
1411         /* set vol=0 to output mixers */
1412         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1413         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1414         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1415
1416         /*
1417          *  Unmute PW3 and PW4
1418          */
1419         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1420         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1421
1422         /* Set input of PW4 as MW0 */
1423         {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1424         /* PW9 Output enable */
1425         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1426         { }
1427 };
1428
1429 static int patch_vt1709_6ch(struct hda_codec *codec)
1430 {
1431         struct via_spec *spec;
1432         int err;
1433
1434         /* create a codec specific record */
1435         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1436         if (spec == NULL)
1437                 return -ENOMEM;
1438
1439         codec->spec = spec;
1440
1441         err = vt1709_parse_auto_config(codec);
1442         if (err < 0) {
1443                 via_free(codec);
1444                 return err;
1445         } else if (!err) {
1446                 printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1447                        "Using genenic mode...\n");
1448         }
1449
1450         spec->init_verbs = vt1709_6ch_volume_init_verbs;        
1451
1452         spec->stream_name_analog = "VT1709 Analog";
1453         spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1454         spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1455
1456         spec->stream_name_digital = "VT1709 Digital";
1457         spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1458         spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1459
1460         
1461         if (!spec->adc_nids && spec->input_mux) {
1462                 spec->adc_nids = vt1709_adc_nids;
1463                 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1464                 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1465                 spec->num_mixers++;
1466         }
1467
1468         codec->patch_ops = via_patch_ops;
1469
1470         codec->patch_ops.init = via_auto_init;
1471 #ifdef CONFIG_SND_HDA_POWER_SAVE
1472         spec->loopback.amplist = vt1709_loopbacks;
1473 #endif
1474         return 0;
1475 }
1476
1477 /* capture mixer elements */
1478 static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
1479         HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
1480         HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
1481         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
1482         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
1483         {
1484                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1485                 /* The multiple "Capture Source" controls confuse alsamixer
1486                  * So call somewhat different..
1487                  */
1488                 /* .name = "Capture Source", */
1489                 .name = "Input Source",
1490                 .count = 1,
1491                 .info = via_mux_enum_info,
1492                 .get = via_mux_enum_get,
1493                 .put = via_mux_enum_put,
1494         },
1495         { } /* end */
1496 };
1497 /*
1498  * generic initialization of ADC, input mixers and output mixers
1499  */
1500 static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
1501         /*
1502          * Unmute ADC0-1 and set the default input to mic-in
1503          */
1504         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1505         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1506
1507
1508         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1509          * mixer widget
1510          */
1511         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1512         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1513         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1514         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1515         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1516         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1517
1518         /*
1519          * Set up output mixers
1520          */
1521         /* set vol=0 to output mixers */
1522         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1523         {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1524         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1525
1526         /* Setup default input to PW4 */
1527         {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1},
1528         /* PW9 Output enable */
1529         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1530         /* PW10 Input enable */
1531         {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1532         { }
1533 };
1534
1535 static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
1536         /*
1537          * Unmute ADC0-1 and set the default input to mic-in
1538          */
1539         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1540         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1541
1542
1543         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1544          * mixer widget
1545          */
1546         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1547         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1548         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1549         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1550         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1551         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1552
1553         /*
1554          * Set up output mixers
1555          */
1556         /* set vol=0 to output mixers */
1557         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1558         {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1559         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1560
1561         /* Setup default input of PW4 to MW0 */
1562         {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
1563         /* PW9 Output enable */
1564         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1565         /* PW10 Input enable */
1566         {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1567         { }
1568 };
1569
1570 static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
1571         .substreams = 1,
1572         .channels_min = 2,
1573         .channels_max = 8,
1574         .nid = 0x10, /* NID to query formats and rates */
1575         .ops = {
1576                 .open = via_playback_pcm_open,
1577                 .prepare = via_playback_pcm_prepare,
1578                 .cleanup = via_playback_pcm_cleanup
1579         },
1580 };
1581
1582 static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
1583         .substreams = 1,
1584         .channels_min = 2,
1585         .channels_max = 4,
1586         .nid = 0x10, /* NID to query formats and rates */
1587         .ops = {
1588                 .open = via_playback_pcm_open,
1589                 .prepare = via_playback_pcm_prepare,
1590                 .cleanup = via_playback_pcm_cleanup
1591         },
1592 };
1593
1594 static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
1595         .substreams = 2,
1596         .channels_min = 2,
1597         .channels_max = 2,
1598         .nid = 0x13, /* NID to query formats and rates */
1599         .ops = {
1600                 .prepare = via_capture_pcm_prepare,
1601                 .cleanup = via_capture_pcm_cleanup
1602         },
1603 };
1604
1605 static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
1606         .substreams = 1,
1607         .channels_min = 2,
1608         .channels_max = 2,
1609         /* NID is set in via_build_pcms */
1610         .ops = {
1611                 .open = via_dig_playback_pcm_open,
1612                 .close = via_dig_playback_pcm_close,
1613                 .prepare = via_dig_playback_pcm_prepare
1614         },
1615 };
1616
1617 static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
1618         .substreams = 1,
1619         .channels_min = 2,
1620         .channels_max = 2,
1621 };
1622
1623 /* fill in the dac_nids table from the parsed pin configuration */
1624 static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
1625                                      const struct auto_pin_cfg *cfg)
1626 {
1627         int i;
1628         hda_nid_t nid;
1629
1630         spec->multiout.num_dacs = cfg->line_outs;
1631
1632         spec->multiout.dac_nids = spec->private_dac_nids;
1633
1634         for (i = 0; i < 4; i++) {
1635                 nid = cfg->line_out_pins[i];
1636                 if (nid) {
1637                         /* config dac list */
1638                         switch (i) {
1639                         case AUTO_SEQ_FRONT:
1640                                 spec->multiout.dac_nids[i] = 0x10;
1641                                 break;
1642                         case AUTO_SEQ_CENLFE:
1643                                 spec->multiout.dac_nids[i] = 0x24;
1644                                 break;
1645                         case AUTO_SEQ_SURROUND:
1646                                 spec->multiout.dac_nids[i] = 0x25;
1647                                 break;
1648                         case AUTO_SEQ_SIDE:
1649                                 spec->multiout.dac_nids[i] = 0x11;
1650                                 break;
1651                         }
1652                 }
1653         }
1654
1655         return 0;
1656 }
1657
1658 /* add playback controls from the parsed DAC table */
1659 static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
1660                                              const struct auto_pin_cfg *cfg)
1661 {
1662         char name[32];
1663         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1664         hda_nid_t nid_vols[] = {0x16, 0x27, 0x26, 0x18};
1665         hda_nid_t nid, nid_vol = 0;
1666         int i, err;
1667
1668         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1669                 nid = cfg->line_out_pins[i];
1670
1671                 if (!nid)
1672                         continue;
1673
1674                 nid_vol = nid_vols[i];
1675
1676                 if (i == AUTO_SEQ_CENLFE) {
1677                         /* Center/LFE */
1678                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1679                                               "Center Playback Volume",
1680                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1681                                                                   HDA_OUTPUT));
1682                         if (err < 0)
1683                                 return err;
1684                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1685                                               "LFE Playback Volume",
1686                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1687                                                                   HDA_OUTPUT));
1688                         if (err < 0)
1689                                 return err;
1690                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1691                                               "Center Playback Switch",
1692                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1693                                                                   HDA_OUTPUT));
1694                         if (err < 0)
1695                                 return err;
1696                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1697                                               "LFE Playback Switch",
1698                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1699                                                                   HDA_OUTPUT));
1700                         if (err < 0)
1701                                 return err;
1702                 } else if (i == AUTO_SEQ_FRONT) {
1703                         /* add control to mixer index 0 */
1704                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1705                                               "Master Front Playback Volume",
1706                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1707                                                                   HDA_INPUT));
1708                         if (err < 0)
1709                                 return err;
1710                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1711                                               "Master Front Playback Switch",
1712                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1713                                                                   HDA_INPUT));
1714                         if (err < 0)
1715                                 return err;
1716
1717                         /* add control to PW3 */
1718                         sprintf(name, "%s Playback Volume", chname[i]);
1719                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1720                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1721                                                                   HDA_OUTPUT));
1722                         if (err < 0)
1723                                 return err;
1724                         sprintf(name, "%s Playback Switch", chname[i]);
1725                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1726                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1727                                                                   HDA_OUTPUT));
1728                         if (err < 0)
1729                                 return err;
1730                 } else {
1731                         sprintf(name, "%s Playback Volume", chname[i]);
1732                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1733                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1734                                                                   HDA_OUTPUT));
1735                         if (err < 0)
1736                                 return err;
1737                         sprintf(name, "%s Playback Switch", chname[i]);
1738                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1739                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1740                                                                   HDA_OUTPUT));
1741                         if (err < 0)
1742                                 return err;
1743                 }
1744         }
1745
1746         return 0;
1747 }
1748
1749 static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1750 {
1751         int err;
1752
1753         if (!pin)
1754                 return 0;
1755
1756         spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
1757
1758         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1759                               "Headphone Playback Volume",
1760                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1761         if (err < 0)
1762                 return err;
1763         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1764                               "Headphone Playback Switch",
1765                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1766         if (err < 0)
1767                 return err;
1768
1769         return 0;
1770 }
1771
1772 /* create playback/capture controls for input pins */
1773 static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
1774                                                 const struct auto_pin_cfg *cfg)
1775 {
1776         static char *labels[] = {
1777                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1778         };
1779         struct hda_input_mux *imux = &spec->private_imux;
1780         int i, err, idx = 0;
1781
1782         /* for internal loopback recording select */
1783         imux->items[imux->num_items].label = "Stereo Mixer";
1784         imux->items[imux->num_items].index = idx;
1785         imux->num_items++;
1786
1787         for (i = 0; i < AUTO_PIN_LAST; i++) {
1788                 if (!cfg->input_pins[i])
1789                         continue;
1790
1791                 switch (cfg->input_pins[i]) {
1792                 case 0x1a: /* Mic */
1793                         idx = 2;
1794                         break;
1795
1796                 case 0x1b: /* Line In */
1797                         idx = 3;
1798                         break;
1799
1800                 case 0x1e: /* Front Mic */
1801                         idx = 4;
1802                         break;
1803
1804                 case 0x1f: /* CD */
1805                         idx = 1;
1806                         break;
1807                 }
1808                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1809                                            idx, 0x16);
1810                 if (err < 0)
1811                         return err;
1812                 imux->items[imux->num_items].label = labels[i];
1813                 imux->items[imux->num_items].index = idx;
1814                 imux->num_items++;
1815         }
1816         return 0;
1817 }
1818
1819 static int vt1708B_parse_auto_config(struct hda_codec *codec)
1820 {
1821         struct via_spec *spec = codec->spec;
1822         int err;
1823
1824         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1825         if (err < 0)
1826                 return err;
1827         err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
1828         if (err < 0)
1829                 return err;
1830         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1831                 return 0; /* can't find valid BIOS pin config */
1832
1833         err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
1834         if (err < 0)
1835                 return err;
1836         err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1837         if (err < 0)
1838                 return err;
1839         err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
1840         if (err < 0)
1841                 return err;
1842
1843         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1844
1845         if (spec->autocfg.dig_out_pin)
1846                 spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
1847         if (spec->autocfg.dig_in_pin)
1848                 spec->dig_in_nid = VT1708B_DIGIN_NID;
1849
1850         if (spec->kctl_alloc)
1851                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1852
1853         spec->input_mux = &spec->private_imux;
1854
1855         return 1;
1856 }
1857
1858 #ifdef CONFIG_SND_HDA_POWER_SAVE
1859 static struct hda_amp_list vt1708B_loopbacks[] = {
1860         { 0x16, HDA_INPUT, 1 },
1861         { 0x16, HDA_INPUT, 2 },
1862         { 0x16, HDA_INPUT, 3 },
1863         { 0x16, HDA_INPUT, 4 },
1864         { } /* end */
1865 };
1866 #endif
1867
1868 static int patch_vt1708B_8ch(struct hda_codec *codec)
1869 {
1870         struct via_spec *spec;
1871         int err;
1872
1873         /* create a codec specific record */
1874         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1875         if (spec == NULL)
1876                 return -ENOMEM;
1877
1878         codec->spec = spec;
1879
1880         /* automatic parse from the BIOS config */
1881         err = vt1708B_parse_auto_config(codec);
1882         if (err < 0) {
1883                 via_free(codec);
1884                 return err;
1885         } else if (!err) {
1886                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1887                        "from BIOS.  Using genenic mode...\n");
1888         }
1889
1890         spec->init_verbs = vt1708B_8ch_volume_init_verbs;
1891
1892         spec->stream_name_analog = "VT1708B Analog";
1893         spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
1894         spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1895
1896         spec->stream_name_digital = "VT1708B Digital";
1897         spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1898         spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1899
1900         if (!spec->adc_nids && spec->input_mux) {
1901                 spec->adc_nids = vt1708B_adc_nids;
1902                 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1903                 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1904                 spec->num_mixers++;
1905         }
1906
1907         codec->patch_ops = via_patch_ops;
1908
1909         codec->patch_ops.init = via_auto_init;
1910 #ifdef CONFIG_SND_HDA_POWER_SAVE
1911         spec->loopback.amplist = vt1708B_loopbacks;
1912 #endif
1913
1914         return 0;
1915 }
1916
1917 static int patch_vt1708B_4ch(struct hda_codec *codec)
1918 {
1919         struct via_spec *spec;
1920         int err;
1921
1922         /* create a codec specific record */
1923         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1924         if (spec == NULL)
1925                 return -ENOMEM;
1926
1927         codec->spec = spec;
1928
1929         /* automatic parse from the BIOS config */
1930         err = vt1708B_parse_auto_config(codec);
1931         if (err < 0) {
1932                 via_free(codec);
1933                 return err;
1934         } else if (!err) {
1935                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1936                        "from BIOS.  Using genenic mode...\n");
1937         }
1938
1939         spec->init_verbs = vt1708B_4ch_volume_init_verbs;
1940
1941         spec->stream_name_analog = "VT1708B Analog";
1942         spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
1943         spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1944
1945         spec->stream_name_digital = "VT1708B Digital";
1946         spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1947         spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1948
1949         if (!spec->adc_nids && spec->input_mux) {
1950                 spec->adc_nids = vt1708B_adc_nids;
1951                 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1952                 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1953                 spec->num_mixers++;
1954         }
1955
1956         codec->patch_ops = via_patch_ops;
1957
1958         codec->patch_ops.init = via_auto_init;
1959 #ifdef CONFIG_SND_HDA_POWER_SAVE
1960         spec->loopback.amplist = vt1708B_loopbacks;
1961 #endif
1962
1963         return 0;
1964 }
1965
1966 /*
1967  * patch entries
1968  */
1969 struct hda_codec_preset snd_hda_preset_via[] = {
1970         { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1971         { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1972         { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1973         { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
1974         { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
1975           .patch = patch_vt1709_10ch},
1976         { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
1977           .patch = patch_vt1709_10ch},
1978         { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
1979           .patch = patch_vt1709_10ch},
1980         { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
1981           .patch = patch_vt1709_10ch},
1982         { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
1983           .patch = patch_vt1709_6ch},
1984         { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
1985           .patch = patch_vt1709_6ch},
1986         { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
1987           .patch = patch_vt1709_6ch},
1988         { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
1989           .patch = patch_vt1709_6ch},
1990         { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
1991           .patch = patch_vt1708B_8ch},
1992         { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
1993           .patch = patch_vt1708B_8ch},
1994         { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
1995           .patch = patch_vt1708B_8ch},
1996         { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
1997           .patch = patch_vt1708B_8ch},
1998         { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
1999           .patch = patch_vt1708B_4ch},
2000         { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
2001           .patch = patch_vt1708B_4ch},
2002         { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
2003           .patch = patch_vt1708B_4ch},
2004         { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
2005           .patch = patch_vt1708B_4ch},
2006         {} /* terminator */
2007 };