Merge branch 'master' of git://git.infradead.org/users/pcmoore/lblnet-2.6_next into...
[sfrench/cifs-2.6.git] / sound / pci / hda / patch_via.c
1 /*
2  * Universal Interface for Intel High Definition Audio Codec
3  *
4  * HD audio interface patch for VIA VT1708 codec
5  *
6  * Copyright (c) 2006 Lydia Wang <lydiawang@viatech.com>
7  *                    Takashi Iwai <tiwai@suse.de>
8  *
9  *  This driver is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This driver is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22  */
23
24 /* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
25 /*                                                                           */
26 /* 2006-03-03  Lydia Wang  Create the basic patch to support VT1708 codec    */
27 /* 2006-03-14  Lydia Wang  Modify hard code for some pin widget nid          */
28 /* 2006-08-02  Lydia Wang  Add support to VT1709 codec                       */
29 /* 2006-09-08  Lydia Wang  Fix internal loopback recording source select bug */
30 /* 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_cleanup_stream(codec, spec->adc_nids[substream->number]);
435         return 0;
436 }
437
438 static struct hda_pcm_stream vt1708_pcm_analog_playback = {
439         .substreams = 1,
440         .channels_min = 2,
441         .channels_max = 8,
442         .nid = 0x10, /* NID to query formats and rates */
443         .ops = {
444                 .open = via_playback_pcm_open,
445                 .prepare = via_playback_pcm_prepare,
446                 .cleanup = via_playback_pcm_cleanup
447         },
448 };
449
450 static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
451         .substreams = 1,
452         .channels_min = 2,
453         .channels_max = 8,
454         .nid = 0x10, /* NID to query formats and rates */
455         /* We got noisy outputs on the right channel on VT1708 when
456          * 24bit samples are used.  Until any workaround is found,
457          * disable the 24bit format, so far.
458          */
459         .formats = SNDRV_PCM_FMTBIT_S16_LE,
460         .ops = {
461                 .open = via_playback_pcm_open,
462                 .prepare = via_playback_pcm_prepare,
463                 .cleanup = via_playback_pcm_cleanup
464         },
465 };
466
467 static struct hda_pcm_stream vt1708_pcm_analog_capture = {
468         .substreams = 2,
469         .channels_min = 2,
470         .channels_max = 2,
471         .nid = 0x15, /* NID to query formats and rates */
472         .ops = {
473                 .prepare = via_capture_pcm_prepare,
474                 .cleanup = via_capture_pcm_cleanup
475         },
476 };
477
478 static struct hda_pcm_stream vt1708_pcm_digital_playback = {
479         .substreams = 1,
480         .channels_min = 2,
481         .channels_max = 2,
482         /* NID is set in via_build_pcms */
483         .ops = {
484                 .open = via_dig_playback_pcm_open,
485                 .close = via_dig_playback_pcm_close,
486                 .prepare = via_dig_playback_pcm_prepare
487         },
488 };
489
490 static struct hda_pcm_stream vt1708_pcm_digital_capture = {
491         .substreams = 1,
492         .channels_min = 2,
493         .channels_max = 2,
494 };
495
496 static int via_build_controls(struct hda_codec *codec)
497 {
498         struct via_spec *spec = codec->spec;
499         int err;
500         int i;
501
502         for (i = 0; i < spec->num_mixers; i++) {
503                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
504                 if (err < 0)
505                         return err;
506         }
507
508         if (spec->multiout.dig_out_nid) {
509                 err = snd_hda_create_spdif_out_ctls(codec,
510                                                     spec->multiout.dig_out_nid);
511                 if (err < 0)
512                         return err;
513                 err = snd_hda_create_spdif_share_sw(codec,
514                                                     &spec->multiout);
515                 if (err < 0)
516                         return err;
517                 spec->multiout.share_spdif = 1;
518         }
519         if (spec->dig_in_nid) {
520                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
521                 if (err < 0)
522                         return err;
523         }
524         return 0;
525 }
526
527 static int via_build_pcms(struct hda_codec *codec)
528 {
529         struct via_spec *spec = codec->spec;
530         struct hda_pcm *info = spec->pcm_rec;
531
532         codec->num_pcms = 1;
533         codec->pcm_info = info;
534
535         info->name = spec->stream_name_analog;
536         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
537         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
538         info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
539         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
540
541         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
542                 spec->multiout.max_channels;
543
544         if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
545                 codec->num_pcms++;
546                 info++;
547                 info->name = spec->stream_name_digital;
548                 info->pcm_type = HDA_PCM_TYPE_SPDIF;
549                 if (spec->multiout.dig_out_nid) {
550                         info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
551                                 *(spec->stream_digital_playback);
552                         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
553                                 spec->multiout.dig_out_nid;
554                 }
555                 if (spec->dig_in_nid) {
556                         info->stream[SNDRV_PCM_STREAM_CAPTURE] =
557                                 *(spec->stream_digital_capture);
558                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
559                                 spec->dig_in_nid;
560                 }
561         }
562
563         return 0;
564 }
565
566 static void via_free(struct hda_codec *codec)
567 {
568         struct via_spec *spec = codec->spec;
569         unsigned int i;
570
571         if (!spec)
572                 return;
573
574         if (spec->kctl_alloc) {
575                 for (i = 0; i < spec->num_kctl_used; i++)
576                         kfree(spec->kctl_alloc[i].name);
577                 kfree(spec->kctl_alloc);
578         }
579
580         kfree(codec->spec);
581 }
582
583 static int via_init(struct hda_codec *codec)
584 {
585         struct via_spec *spec = codec->spec;
586         snd_hda_sequence_write(codec, spec->init_verbs);
587         /* Lydia Add for EAPD enable */
588         if (!spec->dig_in_nid) { /* No Digital In connection */
589                 if (IS_VT1708_VENDORID(codec->vendor_id)) {
590                         snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
591                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
592                                             PIN_OUT);
593                         snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
594                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
595                 } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
596                            IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
597                         snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
598                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
599                                             PIN_OUT);
600                         snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
601                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
602                 } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
603                            IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
604                         snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
605                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
606                                             PIN_OUT);
607                         snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
608                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
609                 }
610         } else /* enable SPDIF-input pin */
611                 snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
612                                     AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
613
614         return 0;
615 }
616
617 #ifdef CONFIG_SND_HDA_POWER_SAVE
618 static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
619 {
620         struct via_spec *spec = codec->spec;
621         return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
622 }
623 #endif
624
625 /*
626  */
627 static struct hda_codec_ops via_patch_ops = {
628         .build_controls = via_build_controls,
629         .build_pcms = via_build_pcms,
630         .init = via_init,
631         .free = via_free,
632 #ifdef CONFIG_SND_HDA_POWER_SAVE
633         .check_power_status = via_check_power_status,
634 #endif
635 };
636
637 /* fill in the dac_nids table from the parsed pin configuration */
638 static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
639                                      const struct auto_pin_cfg *cfg)
640 {
641         int i;
642         hda_nid_t nid;
643
644         spec->multiout.num_dacs = cfg->line_outs;
645
646         spec->multiout.dac_nids = spec->private_dac_nids;
647         
648         for(i = 0; i < 4; i++) {
649                 nid = cfg->line_out_pins[i];
650                 if (nid) {
651                         /* config dac list */
652                         switch (i) {
653                         case AUTO_SEQ_FRONT:
654                                 spec->multiout.dac_nids[i] = 0x10;
655                                 break;
656                         case AUTO_SEQ_CENLFE:
657                                 spec->multiout.dac_nids[i] = 0x12;
658                                 break;
659                         case AUTO_SEQ_SURROUND:
660                                 spec->multiout.dac_nids[i] = 0x13;
661                                 break;
662                         case AUTO_SEQ_SIDE:
663                                 spec->multiout.dac_nids[i] = 0x11;
664                                 break;
665                         }
666                 }
667         }
668
669         return 0;
670 }
671
672 /* add playback controls from the parsed DAC table */
673 static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
674                                              const struct auto_pin_cfg *cfg)
675 {
676         char name[32];
677         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
678         hda_nid_t nid, nid_vol = 0;
679         int i, err;
680
681         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
682                 nid = cfg->line_out_pins[i];
683
684                 if (!nid)
685                         continue;
686                 
687                 if (i != AUTO_SEQ_FRONT)
688                         nid_vol = 0x1b - i + 1;
689
690                 if (i == AUTO_SEQ_CENLFE) {
691                         /* Center/LFE */
692                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
693                                         "Center Playback Volume",
694                                         HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
695                                                             HDA_OUTPUT));
696                         if (err < 0)
697                                 return err;
698                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
699                                               "LFE Playback Volume",
700                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
701                                                                   HDA_OUTPUT));
702                         if (err < 0)
703                                 return err;
704                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
705                                               "Center Playback Switch",
706                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
707                                                                   HDA_OUTPUT));
708                         if (err < 0)
709                                 return err;
710                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
711                                               "LFE Playback Switch",
712                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
713                                                                   HDA_OUTPUT));
714                         if (err < 0)
715                                 return err;
716                 } else if (i == AUTO_SEQ_FRONT){
717                         /* add control to mixer index 0 */
718                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
719                                               "Master Front Playback Volume",
720                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
721                                                                   HDA_INPUT));
722                         if (err < 0)
723                                 return err;
724                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
725                                               "Master Front Playback Switch",
726                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
727                                                                   HDA_INPUT));
728                         if (err < 0)
729                                 return err;
730                         
731                         /* add control to PW3 */
732                         sprintf(name, "%s Playback Volume", chname[i]);
733                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
734                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
735                                                                   HDA_OUTPUT));
736                         if (err < 0)
737                                 return err;
738                         sprintf(name, "%s Playback Switch", chname[i]);
739                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
740                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
741                                                                   HDA_OUTPUT));
742                         if (err < 0)
743                                 return err;
744                 } else {
745                         sprintf(name, "%s Playback Volume", chname[i]);
746                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
747                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
748                                                                   HDA_OUTPUT));
749                         if (err < 0)
750                                 return err;
751                         sprintf(name, "%s Playback Switch", chname[i]);
752                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
753                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
754                                                                   HDA_OUTPUT));
755                         if (err < 0)
756                                 return err;
757                 }
758         }
759
760         return 0;
761 }
762
763 static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
764 {
765         int err;
766
767         if (!pin)
768                 return 0;
769
770         spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
771
772         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
773                               "Headphone Playback Volume",
774                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
775         if (err < 0)
776                 return err;
777         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
778                               "Headphone Playback Switch",
779                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
780         if (err < 0)
781                 return err;
782
783         return 0;
784 }
785
786 /* create playback/capture controls for input pins */
787 static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
788                                                 const struct auto_pin_cfg *cfg)
789 {
790         static char *labels[] = {
791                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
792         };
793         struct hda_input_mux *imux = &spec->private_imux;
794         int i, err, idx = 0;
795
796         /* for internal loopback recording select */
797         imux->items[imux->num_items].label = "Stereo Mixer";
798         imux->items[imux->num_items].index = idx;
799         imux->num_items++;
800
801         for (i = 0; i < AUTO_PIN_LAST; i++) {
802                 if (!cfg->input_pins[i])
803                         continue;
804
805                 switch (cfg->input_pins[i]) {
806                 case 0x1d: /* Mic */
807                         idx = 2;
808                         break;
809                                 
810                 case 0x1e: /* Line In */
811                         idx = 3;
812                         break;
813
814                 case 0x21: /* Front Mic */
815                         idx = 4;
816                         break;
817
818                 case 0x24: /* CD */
819                         idx = 1;
820                         break;
821                 }
822                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
823                                            idx, 0x17);
824                 if (err < 0)
825                         return err;
826                 imux->items[imux->num_items].label = labels[i];
827                 imux->items[imux->num_items].index = idx;
828                 imux->num_items++;
829         }
830         return 0;
831 }
832
833 #ifdef CONFIG_SND_HDA_POWER_SAVE
834 static struct hda_amp_list vt1708_loopbacks[] = {
835         { 0x17, HDA_INPUT, 1 },
836         { 0x17, HDA_INPUT, 2 },
837         { 0x17, HDA_INPUT, 3 },
838         { 0x17, HDA_INPUT, 4 },
839         { } /* end */
840 };
841 #endif
842
843 static int vt1708_parse_auto_config(struct hda_codec *codec)
844 {
845         struct via_spec *spec = codec->spec;
846         int err;
847
848         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
849         if (err < 0)
850                 return err;
851         err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
852         if (err < 0)
853                 return err;
854         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
855                 return 0; /* can't find valid BIOS pin config */
856
857         err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
858         if (err < 0)
859                 return err;
860         err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
861         if (err < 0)
862                 return err;
863         err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
864         if (err < 0)
865                 return err;
866
867         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
868
869         if (spec->autocfg.dig_out_pin)
870                 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
871         if (spec->autocfg.dig_in_pin)
872                 spec->dig_in_nid = VT1708_DIGIN_NID;
873
874         if (spec->kctl_alloc)
875                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
876
877         spec->init_verbs = vt1708_volume_init_verbs;    
878
879         spec->input_mux = &spec->private_imux;
880
881         return 1;
882 }
883
884 /* init callback for auto-configuration model -- overriding the default init */
885 static int via_auto_init(struct hda_codec *codec)
886 {
887         via_init(codec);
888         via_auto_init_multi_out(codec);
889         via_auto_init_hp_out(codec);
890         via_auto_init_analog_input(codec);
891         return 0;
892 }
893
894 static int patch_vt1708(struct hda_codec *codec)
895 {
896         struct via_spec *spec;
897         int err;
898
899         /* create a codec specific record */
900         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
901         if (spec == NULL)
902                 return -ENOMEM;
903
904         codec->spec = spec;
905
906         /* automatic parse from the BIOS config */
907         err = vt1708_parse_auto_config(codec);
908         if (err < 0) {
909                 via_free(codec);
910                 return err;
911         } else if (!err) {
912                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
913                        "from BIOS.  Using genenic mode...\n");
914         }
915
916         
917         spec->stream_name_analog = "VT1708 Analog";
918         spec->stream_analog_playback = &vt1708_pcm_analog_playback;
919         /* disable 32bit format on VT1708 */
920         if (codec->vendor_id == 0x11061708)
921                 spec->stream_analog_playback = &vt1708_pcm_analog_s16_playback;
922         spec->stream_analog_capture = &vt1708_pcm_analog_capture;
923
924         spec->stream_name_digital = "VT1708 Digital";
925         spec->stream_digital_playback = &vt1708_pcm_digital_playback;
926         spec->stream_digital_capture = &vt1708_pcm_digital_capture;
927
928         
929         if (!spec->adc_nids && spec->input_mux) {
930                 spec->adc_nids = vt1708_adc_nids;
931                 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
932                 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
933                 spec->num_mixers++;
934         }
935
936         codec->patch_ops = via_patch_ops;
937
938         codec->patch_ops.init = via_auto_init;
939 #ifdef CONFIG_SND_HDA_POWER_SAVE
940         spec->loopback.amplist = vt1708_loopbacks;
941 #endif
942
943         return 0;
944 }
945
946 /* capture mixer elements */
947 static struct snd_kcontrol_new vt1709_capture_mixer[] = {
948         HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
949         HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
950         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
951         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
952         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
953         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
954         {
955                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
956                 /* The multiple "Capture Source" controls confuse alsamixer
957                  * So call somewhat different..
958                  */
959                 /* .name = "Capture Source", */
960                 .name = "Input Source",
961                 .count = 1,
962                 .info = via_mux_enum_info,
963                 .get = via_mux_enum_get,
964                 .put = via_mux_enum_put,
965         },
966         { } /* end */
967 };
968
969 /*
970  * generic initialization of ADC, input mixers and output mixers
971  */
972 static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
973         /*
974          * Unmute ADC0-2 and set the default input to mic-in
975          */
976         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
977         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
978         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
979
980
981         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
982          * mixer widget
983          */
984         /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
985         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
986         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
987         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
988         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
989         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
990
991         /*
992          * Set up output selector (0x1a, 0x1b, 0x29)
993          */
994         /* set vol=0 to output mixers */
995         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
996         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
997         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
998
999         /*
1000          *  Unmute PW3 and PW4
1001          */
1002         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1003         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1004
1005         /* Set input of PW4 as AOW4 */
1006         {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
1007         /* PW9 Output enable */
1008         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1009         { }
1010 };
1011
1012 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
1013         .substreams = 1,
1014         .channels_min = 2,
1015         .channels_max = 10,
1016         .nid = 0x10, /* NID to query formats and rates */
1017         .ops = {
1018                 .open = via_playback_pcm_open,
1019                 .prepare = via_playback_pcm_prepare,
1020                 .cleanup = via_playback_pcm_cleanup
1021         },
1022 };
1023
1024 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
1025         .substreams = 1,
1026         .channels_min = 2,
1027         .channels_max = 6,
1028         .nid = 0x10, /* NID to query formats and rates */
1029         .ops = {
1030                 .open = via_playback_pcm_open,
1031                 .prepare = via_playback_pcm_prepare,
1032                 .cleanup = via_playback_pcm_cleanup
1033         },
1034 };
1035
1036 static struct hda_pcm_stream vt1709_pcm_analog_capture = {
1037         .substreams = 2,
1038         .channels_min = 2,
1039         .channels_max = 2,
1040         .nid = 0x14, /* NID to query formats and rates */
1041         .ops = {
1042                 .prepare = via_capture_pcm_prepare,
1043                 .cleanup = via_capture_pcm_cleanup
1044         },
1045 };
1046
1047 static struct hda_pcm_stream vt1709_pcm_digital_playback = {
1048         .substreams = 1,
1049         .channels_min = 2,
1050         .channels_max = 2,
1051         /* NID is set in via_build_pcms */
1052         .ops = {
1053                 .open = via_dig_playback_pcm_open,
1054                 .close = via_dig_playback_pcm_close
1055         },
1056 };
1057
1058 static struct hda_pcm_stream vt1709_pcm_digital_capture = {
1059         .substreams = 1,
1060         .channels_min = 2,
1061         .channels_max = 2,
1062 };
1063
1064 static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
1065                                      const struct auto_pin_cfg *cfg)
1066 {
1067         int i;
1068         hda_nid_t nid;
1069
1070         if (cfg->line_outs == 4)  /* 10 channels */
1071                 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
1072         else if (cfg->line_outs == 3) /* 6 channels */
1073                 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
1074
1075         spec->multiout.dac_nids = spec->private_dac_nids;
1076
1077         if (cfg->line_outs == 4) { /* 10 channels */
1078                 for (i = 0; i < cfg->line_outs; i++) {
1079                         nid = cfg->line_out_pins[i];
1080                         if (nid) {
1081                                 /* config dac list */
1082                                 switch (i) {
1083                                 case AUTO_SEQ_FRONT:
1084                                         /* AOW0 */
1085                                         spec->multiout.dac_nids[i] = 0x10;
1086                                         break;
1087                                 case AUTO_SEQ_CENLFE:
1088                                         /* AOW2 */
1089                                         spec->multiout.dac_nids[i] = 0x12;
1090                                         break;
1091                                 case AUTO_SEQ_SURROUND:
1092                                         /* AOW3 */
1093                                         spec->multiout.dac_nids[i] = 0x27;
1094                                         break;
1095                                 case AUTO_SEQ_SIDE:
1096                                         /* AOW1 */
1097                                         spec->multiout.dac_nids[i] = 0x11;
1098                                         break;
1099                                 default:
1100                                         break;
1101                                 }
1102                         }
1103                 }
1104                 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1105
1106         } else if (cfg->line_outs == 3) { /* 6 channels */
1107                 for(i = 0; i < cfg->line_outs; i++) {
1108                         nid = cfg->line_out_pins[i];
1109                         if (nid) {
1110                                 /* config dac list */
1111                                 switch(i) {
1112                                 case AUTO_SEQ_FRONT:
1113                                         /* AOW0 */
1114                                         spec->multiout.dac_nids[i] = 0x10;
1115                                         break;
1116                                 case AUTO_SEQ_CENLFE:
1117                                         /* AOW2 */
1118                                         spec->multiout.dac_nids[i] = 0x12;
1119                                         break;
1120                                 case AUTO_SEQ_SURROUND:
1121                                         /* AOW1 */
1122                                         spec->multiout.dac_nids[i] = 0x11;
1123                                         break;
1124                                 default:
1125                                         break;
1126                                 }
1127                         }
1128                 }
1129         }
1130
1131         return 0;
1132 }
1133
1134 /* add playback controls from the parsed DAC table */
1135 static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1136                                              const struct auto_pin_cfg *cfg)
1137 {
1138         char name[32];
1139         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1140         hda_nid_t nid = 0;
1141         int i, err;
1142
1143         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1144                 nid = cfg->line_out_pins[i];
1145
1146                 if (!nid)       
1147                         continue;
1148
1149                 if (i == AUTO_SEQ_CENLFE) {
1150                         /* Center/LFE */
1151                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1152                                               "Center Playback Volume",
1153                                               HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1154                                                                   HDA_OUTPUT));
1155                         if (err < 0)
1156                                 return err;
1157                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1158                                               "LFE Playback Volume",
1159                                               HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1160                                                                   HDA_OUTPUT));
1161                         if (err < 0)
1162                                 return err;
1163                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1164                                               "Center Playback Switch",
1165                                               HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1166                                                                   HDA_OUTPUT));
1167                         if (err < 0)
1168                                 return err;
1169                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1170                                               "LFE Playback Switch",
1171                                               HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1172                                                                   HDA_OUTPUT));
1173                         if (err < 0)
1174                                 return err;
1175                 } else if (i == AUTO_SEQ_FRONT){
1176                         /* add control to mixer index 0 */
1177                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1178                                               "Master Front Playback Volume",
1179                                               HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1180                                                                   HDA_INPUT));
1181                         if (err < 0)
1182                                 return err;
1183                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1184                                               "Master Front Playback Switch",
1185                                               HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1186                                                                   HDA_INPUT));
1187                         if (err < 0)
1188                                 return err;
1189                         
1190                         /* add control to PW3 */
1191                         sprintf(name, "%s Playback Volume", chname[i]);
1192                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1193                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1194                                                                   HDA_OUTPUT));
1195                         if (err < 0)
1196                                 return err;
1197                         sprintf(name, "%s Playback Switch", chname[i]);
1198                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1199                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1200                                                                   HDA_OUTPUT));
1201                         if (err < 0)
1202                                 return err;
1203                 } else if (i == AUTO_SEQ_SURROUND) {
1204                         sprintf(name, "%s Playback Volume", chname[i]);
1205                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1206                                               HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1207                                                                   HDA_OUTPUT));
1208                         if (err < 0)
1209                                 return err;
1210                         sprintf(name, "%s Playback Switch", chname[i]);
1211                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1212                                               HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1213                                                                   HDA_OUTPUT));
1214                         if (err < 0)
1215                                 return err;
1216                 } else if (i == AUTO_SEQ_SIDE) {
1217                         sprintf(name, "%s Playback Volume", chname[i]);
1218                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1219                                               HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1220                                                                   HDA_OUTPUT));
1221                         if (err < 0)
1222                                 return err;
1223                         sprintf(name, "%s Playback Switch", chname[i]);
1224                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1225                                               HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1226                                                                   HDA_OUTPUT));
1227                         if (err < 0)
1228                                 return err;
1229                 }
1230         }
1231
1232         return 0;
1233 }
1234
1235 static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1236 {
1237         int err;
1238
1239         if (!pin)
1240                 return 0;
1241
1242         if (spec->multiout.num_dacs == 5) /* 10 channels */
1243                 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1244         else if (spec->multiout.num_dacs == 3) /* 6 channels */
1245                 spec->multiout.hp_nid = 0;
1246
1247         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1248                               "Headphone Playback Volume",
1249                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1250         if (err < 0)
1251                 return err;
1252         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1253                               "Headphone Playback Switch",
1254                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1255         if (err < 0)
1256                 return err;
1257
1258         return 0;
1259 }
1260
1261 /* create playback/capture controls for input pins */
1262 static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1263                                                 const struct auto_pin_cfg *cfg)
1264 {
1265         static char *labels[] = {
1266                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1267         };
1268         struct hda_input_mux *imux = &spec->private_imux;
1269         int i, err, idx = 0;
1270
1271         /* for internal loopback recording select */
1272         imux->items[imux->num_items].label = "Stereo Mixer";
1273         imux->items[imux->num_items].index = idx;
1274         imux->num_items++;
1275
1276         for (i = 0; i < AUTO_PIN_LAST; i++) {
1277                 if (!cfg->input_pins[i])
1278                         continue;
1279
1280                 switch (cfg->input_pins[i]) {
1281                 case 0x1d: /* Mic */
1282                         idx = 2;
1283                         break;
1284                                 
1285                 case 0x1e: /* Line In */
1286                         idx = 3;
1287                         break;
1288
1289                 case 0x21: /* Front Mic */
1290                         idx = 4;
1291                         break;
1292
1293                 case 0x23: /* CD */
1294                         idx = 1;
1295                         break;
1296                 }
1297                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1298                                            idx, 0x18);
1299                 if (err < 0)
1300                         return err;
1301                 imux->items[imux->num_items].label = labels[i];
1302                 imux->items[imux->num_items].index = idx;
1303                 imux->num_items++;
1304         }
1305         return 0;
1306 }
1307
1308 static int vt1709_parse_auto_config(struct hda_codec *codec)
1309 {
1310         struct via_spec *spec = codec->spec;
1311         int err;
1312
1313         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1314         if (err < 0)
1315                 return err;
1316         err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1317         if (err < 0)
1318                 return err;
1319         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1320                 return 0; /* can't find valid BIOS pin config */
1321
1322         err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1323         if (err < 0)
1324                 return err;
1325         err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1326         if (err < 0)
1327                 return err;
1328         err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1329         if (err < 0)
1330                 return err;
1331
1332         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1333
1334         if (spec->autocfg.dig_out_pin)
1335                 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1336         if (spec->autocfg.dig_in_pin)
1337                 spec->dig_in_nid = VT1709_DIGIN_NID;
1338
1339         if (spec->kctl_alloc)
1340                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1341
1342         spec->input_mux = &spec->private_imux;
1343
1344         return 1;
1345 }
1346
1347 #ifdef CONFIG_SND_HDA_POWER_SAVE
1348 static struct hda_amp_list vt1709_loopbacks[] = {
1349         { 0x18, HDA_INPUT, 1 },
1350         { 0x18, HDA_INPUT, 2 },
1351         { 0x18, HDA_INPUT, 3 },
1352         { 0x18, HDA_INPUT, 4 },
1353         { } /* end */
1354 };
1355 #endif
1356
1357 static int patch_vt1709_10ch(struct hda_codec *codec)
1358 {
1359         struct via_spec *spec;
1360         int err;
1361
1362         /* create a codec specific record */
1363         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1364         if (spec == NULL)
1365                 return -ENOMEM;
1366
1367         codec->spec = spec;
1368
1369         err = vt1709_parse_auto_config(codec);
1370         if (err < 0) {
1371                 via_free(codec);
1372                 return err;
1373         } else if (!err) {
1374                 printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1375                        "Using genenic mode...\n");
1376         }
1377
1378         spec->init_verbs = vt1709_10ch_volume_init_verbs;       
1379
1380         spec->stream_name_analog = "VT1709 Analog";
1381         spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1382         spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1383
1384         spec->stream_name_digital = "VT1709 Digital";
1385         spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1386         spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1387
1388         
1389         if (!spec->adc_nids && spec->input_mux) {
1390                 spec->adc_nids = vt1709_adc_nids;
1391                 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1392                 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1393                 spec->num_mixers++;
1394         }
1395
1396         codec->patch_ops = via_patch_ops;
1397
1398         codec->patch_ops.init = via_auto_init;
1399 #ifdef CONFIG_SND_HDA_POWER_SAVE
1400         spec->loopback.amplist = vt1709_loopbacks;
1401 #endif
1402
1403         return 0;
1404 }
1405 /*
1406  * generic initialization of ADC, input mixers and output mixers
1407  */
1408 static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1409         /*
1410          * Unmute ADC0-2 and set the default input to mic-in
1411          */
1412         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1413         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1414         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1415
1416
1417         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1418          * mixer widget
1419          */
1420         /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1421         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1422         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1423         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1424         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1425         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1426
1427         /*
1428          * Set up output selector (0x1a, 0x1b, 0x29)
1429          */
1430         /* set vol=0 to output mixers */
1431         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1432         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1433         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1434
1435         /*
1436          *  Unmute PW3 and PW4
1437          */
1438         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1439         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1440
1441         /* Set input of PW4 as MW0 */
1442         {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1443         /* PW9 Output enable */
1444         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1445         { }
1446 };
1447
1448 static int patch_vt1709_6ch(struct hda_codec *codec)
1449 {
1450         struct via_spec *spec;
1451         int err;
1452
1453         /* create a codec specific record */
1454         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1455         if (spec == NULL)
1456                 return -ENOMEM;
1457
1458         codec->spec = spec;
1459
1460         err = vt1709_parse_auto_config(codec);
1461         if (err < 0) {
1462                 via_free(codec);
1463                 return err;
1464         } else if (!err) {
1465                 printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1466                        "Using genenic mode...\n");
1467         }
1468
1469         spec->init_verbs = vt1709_6ch_volume_init_verbs;        
1470
1471         spec->stream_name_analog = "VT1709 Analog";
1472         spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1473         spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1474
1475         spec->stream_name_digital = "VT1709 Digital";
1476         spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1477         spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1478
1479         
1480         if (!spec->adc_nids && spec->input_mux) {
1481                 spec->adc_nids = vt1709_adc_nids;
1482                 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1483                 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1484                 spec->num_mixers++;
1485         }
1486
1487         codec->patch_ops = via_patch_ops;
1488
1489         codec->patch_ops.init = via_auto_init;
1490 #ifdef CONFIG_SND_HDA_POWER_SAVE
1491         spec->loopback.amplist = vt1709_loopbacks;
1492 #endif
1493         return 0;
1494 }
1495
1496 /* capture mixer elements */
1497 static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
1498         HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
1499         HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
1500         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
1501         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
1502         {
1503                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1504                 /* The multiple "Capture Source" controls confuse alsamixer
1505                  * So call somewhat different..
1506                  */
1507                 /* .name = "Capture Source", */
1508                 .name = "Input Source",
1509                 .count = 1,
1510                 .info = via_mux_enum_info,
1511                 .get = via_mux_enum_get,
1512                 .put = via_mux_enum_put,
1513         },
1514         { } /* end */
1515 };
1516 /*
1517  * generic initialization of ADC, input mixers and output mixers
1518  */
1519 static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
1520         /*
1521          * Unmute ADC0-1 and set the default input to mic-in
1522          */
1523         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1524         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1525
1526
1527         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1528          * mixer widget
1529          */
1530         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1531         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1532         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1533         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1534         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1535         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1536
1537         /*
1538          * Set up output mixers
1539          */
1540         /* set vol=0 to output mixers */
1541         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1542         {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1543         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1544
1545         /* Setup default input to PW4 */
1546         {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1},
1547         /* PW9 Output enable */
1548         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1549         /* PW10 Input enable */
1550         {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1551         { }
1552 };
1553
1554 static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
1555         /*
1556          * Unmute ADC0-1 and set the default input to mic-in
1557          */
1558         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1559         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1560
1561
1562         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1563          * mixer widget
1564          */
1565         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1566         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1567         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1568         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1569         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1570         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1571
1572         /*
1573          * Set up output mixers
1574          */
1575         /* set vol=0 to output mixers */
1576         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1577         {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1578         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1579
1580         /* Setup default input of PW4 to MW0 */
1581         {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
1582         /* PW9 Output enable */
1583         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1584         /* PW10 Input enable */
1585         {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1586         { }
1587 };
1588
1589 static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
1590         .substreams = 1,
1591         .channels_min = 2,
1592         .channels_max = 8,
1593         .nid = 0x10, /* NID to query formats and rates */
1594         .ops = {
1595                 .open = via_playback_pcm_open,
1596                 .prepare = via_playback_pcm_prepare,
1597                 .cleanup = via_playback_pcm_cleanup
1598         },
1599 };
1600
1601 static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
1602         .substreams = 1,
1603         .channels_min = 2,
1604         .channels_max = 4,
1605         .nid = 0x10, /* NID to query formats and rates */
1606         .ops = {
1607                 .open = via_playback_pcm_open,
1608                 .prepare = via_playback_pcm_prepare,
1609                 .cleanup = via_playback_pcm_cleanup
1610         },
1611 };
1612
1613 static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
1614         .substreams = 2,
1615         .channels_min = 2,
1616         .channels_max = 2,
1617         .nid = 0x13, /* NID to query formats and rates */
1618         .ops = {
1619                 .prepare = via_capture_pcm_prepare,
1620                 .cleanup = via_capture_pcm_cleanup
1621         },
1622 };
1623
1624 static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
1625         .substreams = 1,
1626         .channels_min = 2,
1627         .channels_max = 2,
1628         /* NID is set in via_build_pcms */
1629         .ops = {
1630                 .open = via_dig_playback_pcm_open,
1631                 .close = via_dig_playback_pcm_close,
1632                 .prepare = via_dig_playback_pcm_prepare
1633         },
1634 };
1635
1636 static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
1637         .substreams = 1,
1638         .channels_min = 2,
1639         .channels_max = 2,
1640 };
1641
1642 /* fill in the dac_nids table from the parsed pin configuration */
1643 static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
1644                                      const struct auto_pin_cfg *cfg)
1645 {
1646         int i;
1647         hda_nid_t nid;
1648
1649         spec->multiout.num_dacs = cfg->line_outs;
1650
1651         spec->multiout.dac_nids = spec->private_dac_nids;
1652
1653         for (i = 0; i < 4; i++) {
1654                 nid = cfg->line_out_pins[i];
1655                 if (nid) {
1656                         /* config dac list */
1657                         switch (i) {
1658                         case AUTO_SEQ_FRONT:
1659                                 spec->multiout.dac_nids[i] = 0x10;
1660                                 break;
1661                         case AUTO_SEQ_CENLFE:
1662                                 spec->multiout.dac_nids[i] = 0x24;
1663                                 break;
1664                         case AUTO_SEQ_SURROUND:
1665                                 spec->multiout.dac_nids[i] = 0x25;
1666                                 break;
1667                         case AUTO_SEQ_SIDE:
1668                                 spec->multiout.dac_nids[i] = 0x11;
1669                                 break;
1670                         }
1671                 }
1672         }
1673
1674         return 0;
1675 }
1676
1677 /* add playback controls from the parsed DAC table */
1678 static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
1679                                              const struct auto_pin_cfg *cfg)
1680 {
1681         char name[32];
1682         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1683         hda_nid_t nid_vols[] = {0x16, 0x27, 0x26, 0x18};
1684         hda_nid_t nid, nid_vol = 0;
1685         int i, err;
1686
1687         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1688                 nid = cfg->line_out_pins[i];
1689
1690                 if (!nid)
1691                         continue;
1692
1693                 nid_vol = nid_vols[i];
1694
1695                 if (i == AUTO_SEQ_CENLFE) {
1696                         /* Center/LFE */
1697                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1698                                               "Center Playback Volume",
1699                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1700                                                                   HDA_OUTPUT));
1701                         if (err < 0)
1702                                 return err;
1703                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1704                                               "LFE Playback Volume",
1705                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1706                                                                   HDA_OUTPUT));
1707                         if (err < 0)
1708                                 return err;
1709                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1710                                               "Center Playback Switch",
1711                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1712                                                                   HDA_OUTPUT));
1713                         if (err < 0)
1714                                 return err;
1715                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1716                                               "LFE Playback Switch",
1717                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1718                                                                   HDA_OUTPUT));
1719                         if (err < 0)
1720                                 return err;
1721                 } else if (i == AUTO_SEQ_FRONT) {
1722                         /* add control to mixer index 0 */
1723                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1724                                               "Master Front Playback Volume",
1725                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1726                                                                   HDA_INPUT));
1727                         if (err < 0)
1728                                 return err;
1729                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1730                                               "Master Front Playback Switch",
1731                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1732                                                                   HDA_INPUT));
1733                         if (err < 0)
1734                                 return err;
1735
1736                         /* add control to PW3 */
1737                         sprintf(name, "%s Playback Volume", chname[i]);
1738                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1739                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1740                                                                   HDA_OUTPUT));
1741                         if (err < 0)
1742                                 return err;
1743                         sprintf(name, "%s Playback Switch", chname[i]);
1744                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1745                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1746                                                                   HDA_OUTPUT));
1747                         if (err < 0)
1748                                 return err;
1749                 } else {
1750                         sprintf(name, "%s Playback Volume", chname[i]);
1751                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1752                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1753                                                                   HDA_OUTPUT));
1754                         if (err < 0)
1755                                 return err;
1756                         sprintf(name, "%s Playback Switch", chname[i]);
1757                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1758                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1759                                                                   HDA_OUTPUT));
1760                         if (err < 0)
1761                                 return err;
1762                 }
1763         }
1764
1765         return 0;
1766 }
1767
1768 static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1769 {
1770         int err;
1771
1772         if (!pin)
1773                 return 0;
1774
1775         spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
1776
1777         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1778                               "Headphone Playback Volume",
1779                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1780         if (err < 0)
1781                 return err;
1782         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1783                               "Headphone Playback Switch",
1784                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1785         if (err < 0)
1786                 return err;
1787
1788         return 0;
1789 }
1790
1791 /* create playback/capture controls for input pins */
1792 static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
1793                                                 const struct auto_pin_cfg *cfg)
1794 {
1795         static char *labels[] = {
1796                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1797         };
1798         struct hda_input_mux *imux = &spec->private_imux;
1799         int i, err, idx = 0;
1800
1801         /* for internal loopback recording select */
1802         imux->items[imux->num_items].label = "Stereo Mixer";
1803         imux->items[imux->num_items].index = idx;
1804         imux->num_items++;
1805
1806         for (i = 0; i < AUTO_PIN_LAST; i++) {
1807                 if (!cfg->input_pins[i])
1808                         continue;
1809
1810                 switch (cfg->input_pins[i]) {
1811                 case 0x1a: /* Mic */
1812                         idx = 2;
1813                         break;
1814
1815                 case 0x1b: /* Line In */
1816                         idx = 3;
1817                         break;
1818
1819                 case 0x1e: /* Front Mic */
1820                         idx = 4;
1821                         break;
1822
1823                 case 0x1f: /* CD */
1824                         idx = 1;
1825                         break;
1826                 }
1827                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1828                                            idx, 0x16);
1829                 if (err < 0)
1830                         return err;
1831                 imux->items[imux->num_items].label = labels[i];
1832                 imux->items[imux->num_items].index = idx;
1833                 imux->num_items++;
1834         }
1835         return 0;
1836 }
1837
1838 static int vt1708B_parse_auto_config(struct hda_codec *codec)
1839 {
1840         struct via_spec *spec = codec->spec;
1841         int err;
1842
1843         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1844         if (err < 0)
1845                 return err;
1846         err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
1847         if (err < 0)
1848                 return err;
1849         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1850                 return 0; /* can't find valid BIOS pin config */
1851
1852         err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
1853         if (err < 0)
1854                 return err;
1855         err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1856         if (err < 0)
1857                 return err;
1858         err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
1859         if (err < 0)
1860                 return err;
1861
1862         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1863
1864         if (spec->autocfg.dig_out_pin)
1865                 spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
1866         if (spec->autocfg.dig_in_pin)
1867                 spec->dig_in_nid = VT1708B_DIGIN_NID;
1868
1869         if (spec->kctl_alloc)
1870                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1871
1872         spec->input_mux = &spec->private_imux;
1873
1874         return 1;
1875 }
1876
1877 #ifdef CONFIG_SND_HDA_POWER_SAVE
1878 static struct hda_amp_list vt1708B_loopbacks[] = {
1879         { 0x16, HDA_INPUT, 1 },
1880         { 0x16, HDA_INPUT, 2 },
1881         { 0x16, HDA_INPUT, 3 },
1882         { 0x16, HDA_INPUT, 4 },
1883         { } /* end */
1884 };
1885 #endif
1886
1887 static int patch_vt1708B_8ch(struct hda_codec *codec)
1888 {
1889         struct via_spec *spec;
1890         int err;
1891
1892         /* create a codec specific record */
1893         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1894         if (spec == NULL)
1895                 return -ENOMEM;
1896
1897         codec->spec = spec;
1898
1899         /* automatic parse from the BIOS config */
1900         err = vt1708B_parse_auto_config(codec);
1901         if (err < 0) {
1902                 via_free(codec);
1903                 return err;
1904         } else if (!err) {
1905                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1906                        "from BIOS.  Using genenic mode...\n");
1907         }
1908
1909         spec->init_verbs = vt1708B_8ch_volume_init_verbs;
1910
1911         spec->stream_name_analog = "VT1708B Analog";
1912         spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
1913         spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1914
1915         spec->stream_name_digital = "VT1708B Digital";
1916         spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1917         spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1918
1919         if (!spec->adc_nids && spec->input_mux) {
1920                 spec->adc_nids = vt1708B_adc_nids;
1921                 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1922                 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1923                 spec->num_mixers++;
1924         }
1925
1926         codec->patch_ops = via_patch_ops;
1927
1928         codec->patch_ops.init = via_auto_init;
1929 #ifdef CONFIG_SND_HDA_POWER_SAVE
1930         spec->loopback.amplist = vt1708B_loopbacks;
1931 #endif
1932
1933         return 0;
1934 }
1935
1936 static int patch_vt1708B_4ch(struct hda_codec *codec)
1937 {
1938         struct via_spec *spec;
1939         int err;
1940
1941         /* create a codec specific record */
1942         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1943         if (spec == NULL)
1944                 return -ENOMEM;
1945
1946         codec->spec = spec;
1947
1948         /* automatic parse from the BIOS config */
1949         err = vt1708B_parse_auto_config(codec);
1950         if (err < 0) {
1951                 via_free(codec);
1952                 return err;
1953         } else if (!err) {
1954                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1955                        "from BIOS.  Using genenic mode...\n");
1956         }
1957
1958         spec->init_verbs = vt1708B_4ch_volume_init_verbs;
1959
1960         spec->stream_name_analog = "VT1708B Analog";
1961         spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
1962         spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1963
1964         spec->stream_name_digital = "VT1708B Digital";
1965         spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1966         spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1967
1968         if (!spec->adc_nids && spec->input_mux) {
1969                 spec->adc_nids = vt1708B_adc_nids;
1970                 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1971                 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1972                 spec->num_mixers++;
1973         }
1974
1975         codec->patch_ops = via_patch_ops;
1976
1977         codec->patch_ops.init = via_auto_init;
1978 #ifdef CONFIG_SND_HDA_POWER_SAVE
1979         spec->loopback.amplist = vt1708B_loopbacks;
1980 #endif
1981
1982         return 0;
1983 }
1984
1985 /*
1986  * patch entries
1987  */
1988 struct hda_codec_preset snd_hda_preset_via[] = {
1989         { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1990         { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1991         { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1992         { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
1993         { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
1994           .patch = patch_vt1709_10ch},
1995         { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
1996           .patch = patch_vt1709_10ch},
1997         { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
1998           .patch = patch_vt1709_10ch},
1999         { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
2000           .patch = patch_vt1709_10ch},
2001         { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
2002           .patch = patch_vt1709_6ch},
2003         { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
2004           .patch = patch_vt1709_6ch},
2005         { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
2006           .patch = patch_vt1709_6ch},
2007         { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
2008           .patch = patch_vt1709_6ch},
2009         { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
2010           .patch = patch_vt1708B_8ch},
2011         { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
2012           .patch = patch_vt1708B_8ch},
2013         { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
2014           .patch = patch_vt1708B_8ch},
2015         { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
2016           .patch = patch_vt1708B_8ch},
2017         { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
2018           .patch = patch_vt1708B_4ch},
2019         { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
2020           .patch = patch_vt1708B_4ch},
2021         { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
2022           .patch = patch_vt1708B_4ch},
2023         { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
2024           .patch = patch_vt1708B_4ch},
2025         {} /* terminator */
2026 };