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