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