[ALSA] hda-intel - Fix PCM device number assignment
[linux-2.6] / sound / pci / hda / patch_via.c
1 /*
2  * Universal Interface for Intel High Definition Audio Codec
3  *
4  * HD audio interface patch for VIA VT1708 codec
5  *
6  * Copyright (c) 2006 Lydia Wang <lydiawang@viatech.com>
7  *                    Takashi Iwai <tiwai@suse.de>
8  *
9  *  This driver is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This driver is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22  */
23
24 /* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
25 /*                                                                           */
26 /* 2006-03-03  Lydia Wang  Create the basic patch to support VT1708 codec    */
27 /* 2006-03-14  Lydia Wang  Modify hard code for some pin widget nid          */
28 /* 2006-08-02  Lydia Wang  Add support to VT1709 codec                       */
29 /* 2006-09-08  Lydia Wang  Fix internal loopback recording source select bug */
30 /* 2007-09-12  Lydia Wang  Add EAPD enable during driver initialization      */
31 /* 2007-09-17  Lydia Wang  Add VT1708B codec support                        */
32 /*                                                                           */
33 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
34
35
36 #include <linux/init.h>
37 #include <linux/delay.h>
38 #include <linux/slab.h>
39 #include <sound/core.h>
40 #include "hda_codec.h"
41 #include "hda_local.h"
42
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 }
362
363 static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
364                                     struct hda_codec *codec,
365                                     unsigned int stream_tag,
366                                     unsigned int format,
367                                     struct snd_pcm_substream *substream)
368 {
369         struct via_spec *spec = codec->spec;
370         return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
371                                                 stream_tag, format, substream);
372 }
373
374 static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
375                                     struct hda_codec *codec,
376                                     struct snd_pcm_substream *substream)
377 {
378         struct via_spec *spec = codec->spec;
379         return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
380 }
381
382 /*
383  * Digital out
384  */
385 static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
386                                      struct hda_codec *codec,
387                                      struct snd_pcm_substream *substream)
388 {
389         struct via_spec *spec = codec->spec;
390         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
391 }
392
393 static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
394                                       struct hda_codec *codec,
395                                       struct snd_pcm_substream *substream)
396 {
397         struct via_spec *spec = codec->spec;
398         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
399 }
400
401 static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
402                                         struct hda_codec *codec,
403                                         unsigned int stream_tag,
404                                         unsigned int format,
405                                         struct snd_pcm_substream *substream)
406 {
407         struct via_spec *spec = codec->spec;
408         return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
409                                              stream_tag, format, substream);
410 }
411
412 /*
413  * Analog capture
414  */
415 static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
416                                    struct hda_codec *codec,
417                                    unsigned int stream_tag,
418                                    unsigned int format,
419                                    struct snd_pcm_substream *substream)
420 {
421         struct via_spec *spec = codec->spec;
422
423         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
424                                    stream_tag, 0, format);
425         return 0;
426 }
427
428 static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
429                                    struct hda_codec *codec,
430                                    struct snd_pcm_substream *substream)
431 {
432         struct via_spec *spec = codec->spec;
433         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
434                                    0, 0, 0);
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_capture = {
451         .substreams = 2,
452         .channels_min = 2,
453         .channels_max = 2,
454         .nid = 0x15, /* NID to query formats and rates */
455         .ops = {
456                 .prepare = via_capture_pcm_prepare,
457                 .cleanup = via_capture_pcm_cleanup
458         },
459 };
460
461 static struct hda_pcm_stream vt1708_pcm_digital_playback = {
462         .substreams = 1,
463         .channels_min = 2,
464         .channels_max = 2,
465         /* NID is set in via_build_pcms */
466         .ops = {
467                 .open = via_dig_playback_pcm_open,
468                 .close = via_dig_playback_pcm_close,
469                 .prepare = via_dig_playback_pcm_prepare
470         },
471 };
472
473 static struct hda_pcm_stream vt1708_pcm_digital_capture = {
474         .substreams = 1,
475         .channels_min = 2,
476         .channels_max = 2,
477 };
478
479 static int via_build_controls(struct hda_codec *codec)
480 {
481         struct via_spec *spec = codec->spec;
482         int err;
483         int i;
484
485         for (i = 0; i < spec->num_mixers; i++) {
486                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
487                 if (err < 0)
488                         return err;
489         }
490
491         if (spec->multiout.dig_out_nid) {
492                 err = snd_hda_create_spdif_out_ctls(codec,
493                                                     spec->multiout.dig_out_nid);
494                 if (err < 0)
495                         return err;
496         }
497         if (spec->dig_in_nid) {
498                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
499                 if (err < 0)
500                         return err;
501         }
502         return 0;
503 }
504
505 static int via_build_pcms(struct hda_codec *codec)
506 {
507         struct via_spec *spec = codec->spec;
508         struct hda_pcm *info = spec->pcm_rec;
509
510         codec->num_pcms = 1;
511         codec->pcm_info = info;
512
513         info->name = spec->stream_name_analog;
514         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
515         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
516         info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
517         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
518
519         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
520                 spec->multiout.max_channels;
521
522         if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
523                 codec->num_pcms++;
524                 info++;
525                 info->name = spec->stream_name_digital;
526                 info->pcm_type = HDA_PCM_TYPE_SPDIF;
527                 if (spec->multiout.dig_out_nid) {
528                         info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
529                                 *(spec->stream_digital_playback);
530                         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
531                                 spec->multiout.dig_out_nid;
532                 }
533                 if (spec->dig_in_nid) {
534                         info->stream[SNDRV_PCM_STREAM_CAPTURE] =
535                                 *(spec->stream_digital_capture);
536                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
537                                 spec->dig_in_nid;
538                 }
539         }
540
541         return 0;
542 }
543
544 static void via_free(struct hda_codec *codec)
545 {
546         struct via_spec *spec = codec->spec;
547         unsigned int i;
548
549         if (!spec)
550                 return;
551
552         if (spec->kctl_alloc) {
553                 for (i = 0; i < spec->num_kctl_used; i++)
554                         kfree(spec->kctl_alloc[i].name);
555                 kfree(spec->kctl_alloc);
556         }
557
558         kfree(codec->spec);
559 }
560
561 static int via_init(struct hda_codec *codec)
562 {
563         struct via_spec *spec = codec->spec;
564         snd_hda_sequence_write(codec, spec->init_verbs);
565         /* Lydia Add for EAPD enable */
566         if (!spec->dig_in_nid) { /* No Digital In connection */
567                 if (IS_VT1708_VENDORID(codec->vendor_id)) {
568                         snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
569                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
570                                             PIN_OUT);
571                         snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
572                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
573                 } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
574                            IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
575                         snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
576                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
577                                             PIN_OUT);
578                         snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
579                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
580                 } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
581                            IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
582                         snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
583                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
584                                             PIN_OUT);
585                         snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
586                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
587                 }
588         } else /* enable SPDIF-input pin */
589                 snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
590                                     AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
591
592         return 0;
593 }
594
595 #ifdef CONFIG_SND_HDA_POWER_SAVE
596 static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
597 {
598         struct via_spec *spec = codec->spec;
599         return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
600 }
601 #endif
602
603 /*
604  */
605 static struct hda_codec_ops via_patch_ops = {
606         .build_controls = via_build_controls,
607         .build_pcms = via_build_pcms,
608         .init = via_init,
609         .free = via_free,
610 #ifdef CONFIG_SND_HDA_POWER_SAVE
611         .check_power_status = via_check_power_status,
612 #endif
613 };
614
615 /* fill in the dac_nids table from the parsed pin configuration */
616 static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
617                                      const struct auto_pin_cfg *cfg)
618 {
619         int i;
620         hda_nid_t nid;
621
622         spec->multiout.num_dacs = cfg->line_outs;
623
624         spec->multiout.dac_nids = spec->private_dac_nids;
625         
626         for(i = 0; i < 4; i++) {
627                 nid = cfg->line_out_pins[i];
628                 if (nid) {
629                         /* config dac list */
630                         switch (i) {
631                         case AUTO_SEQ_FRONT:
632                                 spec->multiout.dac_nids[i] = 0x10;
633                                 break;
634                         case AUTO_SEQ_CENLFE:
635                                 spec->multiout.dac_nids[i] = 0x12;
636                                 break;
637                         case AUTO_SEQ_SURROUND:
638                                 spec->multiout.dac_nids[i] = 0x13;
639                                 break;
640                         case AUTO_SEQ_SIDE:
641                                 spec->multiout.dac_nids[i] = 0x11;
642                                 break;
643                         }
644                 }
645         }
646
647         return 0;
648 }
649
650 /* add playback controls from the parsed DAC table */
651 static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
652                                              const struct auto_pin_cfg *cfg)
653 {
654         char name[32];
655         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
656         hda_nid_t nid, nid_vol = 0;
657         int i, err;
658
659         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
660                 nid = cfg->line_out_pins[i];
661
662                 if (!nid)
663                         continue;
664                 
665                 if (i != AUTO_SEQ_FRONT)
666                         nid_vol = 0x1b - i + 1;
667
668                 if (i == AUTO_SEQ_CENLFE) {
669                         /* Center/LFE */
670                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
671                                         "Center Playback Volume",
672                                         HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
673                                                             HDA_OUTPUT));
674                         if (err < 0)
675                                 return err;
676                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
677                                               "LFE Playback Volume",
678                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
679                                                                   HDA_OUTPUT));
680                         if (err < 0)
681                                 return err;
682                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
683                                               "Center Playback Switch",
684                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
685                                                                   HDA_OUTPUT));
686                         if (err < 0)
687                                 return err;
688                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
689                                               "LFE Playback Switch",
690                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
691                                                                   HDA_OUTPUT));
692                         if (err < 0)
693                                 return err;
694                 } else if (i == AUTO_SEQ_FRONT){
695                         /* add control to mixer index 0 */
696                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
697                                               "Master Front Playback Volume",
698                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
699                                                                   HDA_INPUT));
700                         if (err < 0)
701                                 return err;
702                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
703                                               "Master Front Playback Switch",
704                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
705                                                                   HDA_INPUT));
706                         if (err < 0)
707                                 return err;
708                         
709                         /* add control to PW3 */
710                         sprintf(name, "%s Playback Volume", chname[i]);
711                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
712                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
713                                                                   HDA_OUTPUT));
714                         if (err < 0)
715                                 return err;
716                         sprintf(name, "%s Playback Switch", chname[i]);
717                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
718                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
719                                                                   HDA_OUTPUT));
720                         if (err < 0)
721                                 return err;
722                 } else {
723                         sprintf(name, "%s Playback Volume", chname[i]);
724                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
725                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
726                                                                   HDA_OUTPUT));
727                         if (err < 0)
728                                 return err;
729                         sprintf(name, "%s Playback Switch", chname[i]);
730                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
731                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
732                                                                   HDA_OUTPUT));
733                         if (err < 0)
734                                 return err;
735                 }
736         }
737
738         return 0;
739 }
740
741 static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
742 {
743         int err;
744
745         if (!pin)
746                 return 0;
747
748         spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
749
750         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
751                               "Headphone Playback Volume",
752                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
753         if (err < 0)
754                 return err;
755         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
756                               "Headphone Playback Switch",
757                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
758         if (err < 0)
759                 return err;
760
761         return 0;
762 }
763
764 /* create playback/capture controls for input pins */
765 static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
766                                                 const struct auto_pin_cfg *cfg)
767 {
768         static char *labels[] = {
769                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
770         };
771         struct hda_input_mux *imux = &spec->private_imux;
772         int i, err, idx = 0;
773
774         /* for internal loopback recording select */
775         imux->items[imux->num_items].label = "Stereo Mixer";
776         imux->items[imux->num_items].index = idx;
777         imux->num_items++;
778
779         for (i = 0; i < AUTO_PIN_LAST; i++) {
780                 if (!cfg->input_pins[i])
781                         continue;
782
783                 switch (cfg->input_pins[i]) {
784                 case 0x1d: /* Mic */
785                         idx = 2;
786                         break;
787                                 
788                 case 0x1e: /* Line In */
789                         idx = 3;
790                         break;
791
792                 case 0x21: /* Front Mic */
793                         idx = 4;
794                         break;
795
796                 case 0x24: /* CD */
797                         idx = 1;
798                         break;
799                 }
800                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
801                                            idx, 0x17);
802                 if (err < 0)
803                         return err;
804                 imux->items[imux->num_items].label = labels[i];
805                 imux->items[imux->num_items].index = idx;
806                 imux->num_items++;
807         }
808         return 0;
809 }
810
811 #ifdef CONFIG_SND_HDA_POWER_SAVE
812 static struct hda_amp_list vt1708_loopbacks[] = {
813         { 0x17, HDA_INPUT, 1 },
814         { 0x17, HDA_INPUT, 2 },
815         { 0x17, HDA_INPUT, 3 },
816         { 0x17, HDA_INPUT, 4 },
817         { } /* end */
818 };
819 #endif
820
821 static int vt1708_parse_auto_config(struct hda_codec *codec)
822 {
823         struct via_spec *spec = codec->spec;
824         int err;
825
826         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
827         if (err < 0)
828                 return err;
829         err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
830         if (err < 0)
831                 return err;
832         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
833                 return 0; /* can't find valid BIOS pin config */
834
835         err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
836         if (err < 0)
837                 return err;
838         err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
839         if (err < 0)
840                 return err;
841         err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
842         if (err < 0)
843                 return err;
844
845         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
846
847         if (spec->autocfg.dig_out_pin)
848                 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
849         if (spec->autocfg.dig_in_pin)
850                 spec->dig_in_nid = VT1708_DIGIN_NID;
851
852         if (spec->kctl_alloc)
853                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
854
855         spec->init_verbs = vt1708_volume_init_verbs;    
856
857         spec->input_mux = &spec->private_imux;
858
859         return 1;
860 }
861
862 /* init callback for auto-configuration model -- overriding the default init */
863 static int via_auto_init(struct hda_codec *codec)
864 {
865         via_init(codec);
866         via_auto_init_multi_out(codec);
867         via_auto_init_hp_out(codec);
868         via_auto_init_analog_input(codec);
869         return 0;
870 }
871
872 static int patch_vt1708(struct hda_codec *codec)
873 {
874         struct via_spec *spec;
875         int err;
876
877         /* create a codec specific record */
878         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
879         if (spec == NULL)
880                 return -ENOMEM;
881
882         codec->spec = spec;
883
884         /* automatic parse from the BIOS config */
885         err = vt1708_parse_auto_config(codec);
886         if (err < 0) {
887                 via_free(codec);
888                 return err;
889         } else if (!err) {
890                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
891                        "from BIOS.  Using genenic mode...\n");
892         }
893
894         
895         spec->stream_name_analog = "VT1708 Analog";
896         spec->stream_analog_playback = &vt1708_pcm_analog_playback;
897         spec->stream_analog_capture = &vt1708_pcm_analog_capture;
898
899         spec->stream_name_digital = "VT1708 Digital";
900         spec->stream_digital_playback = &vt1708_pcm_digital_playback;
901         spec->stream_digital_capture = &vt1708_pcm_digital_capture;
902
903         
904         if (!spec->adc_nids && spec->input_mux) {
905                 spec->adc_nids = vt1708_adc_nids;
906                 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
907                 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
908                 spec->num_mixers++;
909         }
910
911         codec->patch_ops = via_patch_ops;
912
913         codec->patch_ops.init = via_auto_init;
914 #ifdef CONFIG_SND_HDA_POWER_SAVE
915         spec->loopback.amplist = vt1708_loopbacks;
916 #endif
917
918         return 0;
919 }
920
921 /* capture mixer elements */
922 static struct snd_kcontrol_new vt1709_capture_mixer[] = {
923         HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
924         HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
925         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
926         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
927         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
928         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
929         {
930                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
931                 /* The multiple "Capture Source" controls confuse alsamixer
932                  * So call somewhat different..
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                  */
1482                 /* .name = "Capture Source", */
1483                 .name = "Input Source",
1484                 .count = 1,
1485                 .info = via_mux_enum_info,
1486                 .get = via_mux_enum_get,
1487                 .put = via_mux_enum_put,
1488         },
1489         { } /* end */
1490 };
1491 /*
1492  * generic initialization of ADC, input mixers and output mixers
1493  */
1494 static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
1495         /*
1496          * Unmute ADC0-1 and set the default input to mic-in
1497          */
1498         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1499         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1500
1501
1502         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1503          * mixer widget
1504          */
1505         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1506         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1507         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1508         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1509         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1510         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1511
1512         /*
1513          * Set up output mixers
1514          */
1515         /* set vol=0 to output mixers */
1516         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1517         {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1518         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1519
1520         /* Setup default input to PW4 */
1521         {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1},
1522         /* PW9 Output enable */
1523         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1524         /* PW10 Input enable */
1525         {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1526         { }
1527 };
1528
1529 static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
1530         /*
1531          * Unmute ADC0-1 and set the default input to mic-in
1532          */
1533         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1534         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1535
1536
1537         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1538          * mixer widget
1539          */
1540         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1541         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1542         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1543         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1544         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1545         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1546
1547         /*
1548          * Set up output mixers
1549          */
1550         /* set vol=0 to output mixers */
1551         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1552         {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1553         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1554
1555         /* Setup default input of PW4 to MW0 */
1556         {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
1557         /* PW9 Output enable */
1558         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1559         /* PW10 Input enable */
1560         {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1561         { }
1562 };
1563
1564 static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
1565         .substreams = 1,
1566         .channels_min = 2,
1567         .channels_max = 8,
1568         .nid = 0x10, /* NID to query formats and rates */
1569         .ops = {
1570                 .open = via_playback_pcm_open,
1571                 .prepare = via_playback_pcm_prepare,
1572                 .cleanup = via_playback_pcm_cleanup
1573         },
1574 };
1575
1576 static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
1577         .substreams = 1,
1578         .channels_min = 2,
1579         .channels_max = 4,
1580         .nid = 0x10, /* NID to query formats and rates */
1581         .ops = {
1582                 .open = via_playback_pcm_open,
1583                 .prepare = via_playback_pcm_prepare,
1584                 .cleanup = via_playback_pcm_cleanup
1585         },
1586 };
1587
1588 static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
1589         .substreams = 2,
1590         .channels_min = 2,
1591         .channels_max = 2,
1592         .nid = 0x13, /* NID to query formats and rates */
1593         .ops = {
1594                 .prepare = via_capture_pcm_prepare,
1595                 .cleanup = via_capture_pcm_cleanup
1596         },
1597 };
1598
1599 static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
1600         .substreams = 1,
1601         .channels_min = 2,
1602         .channels_max = 2,
1603         /* NID is set in via_build_pcms */
1604         .ops = {
1605                 .open = via_dig_playback_pcm_open,
1606                 .close = via_dig_playback_pcm_close,
1607                 .prepare = via_dig_playback_pcm_prepare
1608         },
1609 };
1610
1611 static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
1612         .substreams = 1,
1613         .channels_min = 2,
1614         .channels_max = 2,
1615 };
1616
1617 /* fill in the dac_nids table from the parsed pin configuration */
1618 static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
1619                                      const struct auto_pin_cfg *cfg)
1620 {
1621         int i;
1622         hda_nid_t nid;
1623
1624         spec->multiout.num_dacs = cfg->line_outs;
1625
1626         spec->multiout.dac_nids = spec->private_dac_nids;
1627
1628         for (i = 0; i < 4; i++) {
1629                 nid = cfg->line_out_pins[i];
1630                 if (nid) {
1631                         /* config dac list */
1632                         switch (i) {
1633                         case AUTO_SEQ_FRONT:
1634                                 spec->multiout.dac_nids[i] = 0x10;
1635                                 break;
1636                         case AUTO_SEQ_CENLFE:
1637                                 spec->multiout.dac_nids[i] = 0x24;
1638                                 break;
1639                         case AUTO_SEQ_SURROUND:
1640                                 spec->multiout.dac_nids[i] = 0x25;
1641                                 break;
1642                         case AUTO_SEQ_SIDE:
1643                                 spec->multiout.dac_nids[i] = 0x11;
1644                                 break;
1645                         }
1646                 }
1647         }
1648
1649         return 0;
1650 }
1651
1652 /* add playback controls from the parsed DAC table */
1653 static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
1654                                              const struct auto_pin_cfg *cfg)
1655 {
1656         char name[32];
1657         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1658         hda_nid_t nid_vols[] = {0x16, 0x27, 0x26, 0x18};
1659         hda_nid_t nid, nid_vol = 0;
1660         int i, err;
1661
1662         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1663                 nid = cfg->line_out_pins[i];
1664
1665                 if (!nid)
1666                         continue;
1667
1668                 nid_vol = nid_vols[i];
1669
1670                 if (i == AUTO_SEQ_CENLFE) {
1671                         /* Center/LFE */
1672                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1673                                               "Center Playback Volume",
1674                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1675                                                                   HDA_OUTPUT));
1676                         if (err < 0)
1677                                 return err;
1678                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1679                                               "LFE Playback Volume",
1680                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1681                                                                   HDA_OUTPUT));
1682                         if (err < 0)
1683                                 return err;
1684                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1685                                               "Center Playback Switch",
1686                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1687                                                                   HDA_OUTPUT));
1688                         if (err < 0)
1689                                 return err;
1690                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1691                                               "LFE Playback Switch",
1692                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1693                                                                   HDA_OUTPUT));
1694                         if (err < 0)
1695                                 return err;
1696                 } else if (i == AUTO_SEQ_FRONT) {
1697                         /* add control to mixer index 0 */
1698                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1699                                               "Master Front Playback Volume",
1700                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1701                                                                   HDA_INPUT));
1702                         if (err < 0)
1703                                 return err;
1704                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1705                                               "Master Front Playback Switch",
1706                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1707                                                                   HDA_INPUT));
1708                         if (err < 0)
1709                                 return err;
1710
1711                         /* add control to PW3 */
1712                         sprintf(name, "%s Playback Volume", chname[i]);
1713                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1714                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1715                                                                   HDA_OUTPUT));
1716                         if (err < 0)
1717                                 return err;
1718                         sprintf(name, "%s Playback Switch", chname[i]);
1719                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1720                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1721                                                                   HDA_OUTPUT));
1722                         if (err < 0)
1723                                 return err;
1724                 } else {
1725                         sprintf(name, "%s Playback Volume", chname[i]);
1726                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1727                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1728                                                                   HDA_OUTPUT));
1729                         if (err < 0)
1730                                 return err;
1731                         sprintf(name, "%s Playback Switch", chname[i]);
1732                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1733                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1734                                                                   HDA_OUTPUT));
1735                         if (err < 0)
1736                                 return err;
1737                 }
1738         }
1739
1740         return 0;
1741 }
1742
1743 static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1744 {
1745         int err;
1746
1747         if (!pin)
1748                 return 0;
1749
1750         spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
1751
1752         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1753                               "Headphone Playback Volume",
1754                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1755         if (err < 0)
1756                 return err;
1757         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1758                               "Headphone Playback Switch",
1759                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1760         if (err < 0)
1761                 return err;
1762
1763         return 0;
1764 }
1765
1766 /* create playback/capture controls for input pins */
1767 static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
1768                                                 const struct auto_pin_cfg *cfg)
1769 {
1770         static char *labels[] = {
1771                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1772         };
1773         struct hda_input_mux *imux = &spec->private_imux;
1774         int i, err, idx = 0;
1775
1776         /* for internal loopback recording select */
1777         imux->items[imux->num_items].label = "Stereo Mixer";
1778         imux->items[imux->num_items].index = idx;
1779         imux->num_items++;
1780
1781         for (i = 0; i < AUTO_PIN_LAST; i++) {
1782                 if (!cfg->input_pins[i])
1783                         continue;
1784
1785                 switch (cfg->input_pins[i]) {
1786                 case 0x1a: /* Mic */
1787                         idx = 2;
1788                         break;
1789
1790                 case 0x1b: /* Line In */
1791                         idx = 3;
1792                         break;
1793
1794                 case 0x1e: /* Front Mic */
1795                         idx = 4;
1796                         break;
1797
1798                 case 0x1f: /* CD */
1799                         idx = 1;
1800                         break;
1801                 }
1802                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1803                                            idx, 0x16);
1804                 if (err < 0)
1805                         return err;
1806                 imux->items[imux->num_items].label = labels[i];
1807                 imux->items[imux->num_items].index = idx;
1808                 imux->num_items++;
1809         }
1810         return 0;
1811 }
1812
1813 static int vt1708B_parse_auto_config(struct hda_codec *codec)
1814 {
1815         struct via_spec *spec = codec->spec;
1816         int err;
1817
1818         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1819         if (err < 0)
1820                 return err;
1821         err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
1822         if (err < 0)
1823                 return err;
1824         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1825                 return 0; /* can't find valid BIOS pin config */
1826
1827         err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
1828         if (err < 0)
1829                 return err;
1830         err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1831         if (err < 0)
1832                 return err;
1833         err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
1834         if (err < 0)
1835                 return err;
1836
1837         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1838
1839         if (spec->autocfg.dig_out_pin)
1840                 spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
1841         if (spec->autocfg.dig_in_pin)
1842                 spec->dig_in_nid = VT1708B_DIGIN_NID;
1843
1844         if (spec->kctl_alloc)
1845                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1846
1847         spec->input_mux = &spec->private_imux;
1848
1849         return 1;
1850 }
1851
1852 #ifdef CONFIG_SND_HDA_POWER_SAVE
1853 static struct hda_amp_list vt1708B_loopbacks[] = {
1854         { 0x16, HDA_INPUT, 1 },
1855         { 0x16, HDA_INPUT, 2 },
1856         { 0x16, HDA_INPUT, 3 },
1857         { 0x16, HDA_INPUT, 4 },
1858         { } /* end */
1859 };
1860 #endif
1861
1862 static int patch_vt1708B_8ch(struct hda_codec *codec)
1863 {
1864         struct via_spec *spec;
1865         int err;
1866
1867         /* create a codec specific record */
1868         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1869         if (spec == NULL)
1870                 return -ENOMEM;
1871
1872         codec->spec = spec;
1873
1874         /* automatic parse from the BIOS config */
1875         err = vt1708B_parse_auto_config(codec);
1876         if (err < 0) {
1877                 via_free(codec);
1878                 return err;
1879         } else if (!err) {
1880                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1881                        "from BIOS.  Using genenic mode...\n");
1882         }
1883
1884         spec->init_verbs = vt1708B_8ch_volume_init_verbs;
1885
1886         spec->stream_name_analog = "VT1708B Analog";
1887         spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
1888         spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1889
1890         spec->stream_name_digital = "VT1708B Digital";
1891         spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1892         spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1893
1894         if (!spec->adc_nids && spec->input_mux) {
1895                 spec->adc_nids = vt1708B_adc_nids;
1896                 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1897                 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1898                 spec->num_mixers++;
1899         }
1900
1901         codec->patch_ops = via_patch_ops;
1902
1903         codec->patch_ops.init = via_auto_init;
1904 #ifdef CONFIG_SND_HDA_POWER_SAVE
1905         spec->loopback.amplist = vt1708B_loopbacks;
1906 #endif
1907
1908         return 0;
1909 }
1910
1911 static int patch_vt1708B_4ch(struct hda_codec *codec)
1912 {
1913         struct via_spec *spec;
1914         int err;
1915
1916         /* create a codec specific record */
1917         spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1918         if (spec == NULL)
1919                 return -ENOMEM;
1920
1921         codec->spec = spec;
1922
1923         /* automatic parse from the BIOS config */
1924         err = vt1708B_parse_auto_config(codec);
1925         if (err < 0) {
1926                 via_free(codec);
1927                 return err;
1928         } else if (!err) {
1929                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1930                        "from BIOS.  Using genenic mode...\n");
1931         }
1932
1933         spec->init_verbs = vt1708B_4ch_volume_init_verbs;
1934
1935         spec->stream_name_analog = "VT1708B Analog";
1936         spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
1937         spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1938
1939         spec->stream_name_digital = "VT1708B Digital";
1940         spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1941         spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1942
1943         if (!spec->adc_nids && spec->input_mux) {
1944                 spec->adc_nids = vt1708B_adc_nids;
1945                 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1946                 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1947                 spec->num_mixers++;
1948         }
1949
1950         codec->patch_ops = via_patch_ops;
1951
1952         codec->patch_ops.init = via_auto_init;
1953 #ifdef CONFIG_SND_HDA_POWER_SAVE
1954         spec->loopback.amplist = vt1708B_loopbacks;
1955 #endif
1956
1957         return 0;
1958 }
1959
1960 /*
1961  * patch entries
1962  */
1963 struct hda_codec_preset snd_hda_preset_via[] = {
1964         { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1965         { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1966         { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1967         { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
1968         { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
1969           .patch = patch_vt1709_10ch},
1970         { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
1971           .patch = patch_vt1709_10ch},
1972         { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
1973           .patch = patch_vt1709_10ch},
1974         { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
1975           .patch = patch_vt1709_10ch},
1976         { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
1977           .patch = patch_vt1709_6ch},
1978         { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
1979           .patch = patch_vt1709_6ch},
1980         { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
1981           .patch = patch_vt1709_6ch},
1982         { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
1983           .patch = patch_vt1709_6ch},
1984         { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
1985           .patch = patch_vt1708B_8ch},
1986         { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
1987           .patch = patch_vt1708B_8ch},
1988         { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
1989           .patch = patch_vt1708B_8ch},
1990         { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
1991           .patch = patch_vt1708B_8ch},
1992         { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
1993           .patch = patch_vt1708B_4ch},
1994         { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
1995           .patch = patch_vt1708B_4ch},
1996         { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
1997           .patch = patch_vt1708B_4ch},
1998         { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
1999           .patch = patch_vt1708B_4ch},
2000         {} /* terminator */
2001 };