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