ALSA: HDA patch_via.c: Mute on headphone plug-in
[linux-2.6-block.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 VT1702/VT1708/VT1709 codec
5  *
6  * Copyright (c) 2006-2008 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 /* 2007-11-14  Lydia Wang  Add VT1708A codec HP and CD pin connect config    */
33 /* 2008-02-03  Lydia Wang  Fix Rear channels and Back channels inverse issue */
34 /* 2008-03-06  Lydia Wang  Add VT1702 codec and VT1708S codec support        */
35 /* 2008-04-09  Lydia Wang  Add mute front speaker when HP plugin             */
36 /*                                                                           */
37 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
38
39
40 #include <linux/init.h>
41 #include <linux/delay.h>
42 #include <linux/slab.h>
43 #include <sound/core.h>
44 #include "hda_codec.h"
45 #include "hda_local.h"
46 #include "hda_patch.h"
47
48 /* amp values */
49 #define AMP_VAL_IDX_SHIFT       19
50 #define AMP_VAL_IDX_MASK        (0x0f<<19)
51
52 #define NUM_CONTROL_ALLOC       32
53 #define NUM_VERB_ALLOC          32
54
55 /* Pin Widget NID */
56 #define VT1708_HP_NID           0x13
57 #define VT1708_DIGOUT_NID       0x14
58 #define VT1708_DIGIN_NID        0x16
59 #define VT1708_DIGIN_PIN        0x26
60 #define VT1708_HP_PIN_NID       0x20
61 #define VT1708_CD_PIN_NID       0x24
62
63 #define VT1709_HP_DAC_NID       0x28
64 #define VT1709_DIGOUT_NID       0x13
65 #define VT1709_DIGIN_NID        0x17
66 #define VT1709_DIGIN_PIN        0x25
67
68 #define VT1708B_HP_NID          0x25
69 #define VT1708B_DIGOUT_NID      0x12
70 #define VT1708B_DIGIN_NID       0x15
71 #define VT1708B_DIGIN_PIN       0x21
72
73 #define VT1708S_HP_NID          0x25
74 #define VT1708S_DIGOUT_NID      0x12
75
76 #define VT1702_HP_NID           0x17
77 #define VT1702_DIGOUT_NID       0x11
78
79 #define IS_VT1708_VENDORID(x)           ((x) >= 0x11061708 && (x) <= 0x1106170b)
80 #define IS_VT1709_10CH_VENDORID(x)      ((x) >= 0x1106e710 && (x) <= 0x1106e713)
81 #define IS_VT1709_6CH_VENDORID(x)       ((x) >= 0x1106e714 && (x) <= 0x1106e717)
82 #define IS_VT1708B_8CH_VENDORID(x)      ((x) >= 0x1106e720 && (x) <= 0x1106e723)
83 #define IS_VT1708B_4CH_VENDORID(x)      ((x) >= 0x1106e724 && (x) <= 0x1106e727)
84 #define IS_VT1708S_VENDORID(x)          ((x) >= 0x11060397 && (x) <= 0x11067397)
85 #define IS_VT1702_VENDORID(x)           ((x) >= 0x11060398 && (x) <= 0x11067398)
86
87 #define VIA_HP_EVENT            0x01
88 #define VIA_GPIO_EVENT          0x02
89
90 enum {
91         VIA_CTL_WIDGET_VOL,
92         VIA_CTL_WIDGET_MUTE,
93 };
94
95 enum {
96         AUTO_SEQ_FRONT = 0,
97         AUTO_SEQ_SURROUND,
98         AUTO_SEQ_CENLFE,
99         AUTO_SEQ_SIDE
100 };
101
102 static struct snd_kcontrol_new vt1708_control_templates[] = {
103         HDA_CODEC_VOLUME(NULL, 0, 0, 0),
104         HDA_CODEC_MUTE(NULL, 0, 0, 0),
105 };
106
107
108 struct via_spec {
109         /* codec parameterization */
110         struct snd_kcontrol_new *mixers[3];
111         unsigned int num_mixers;
112
113         struct hda_verb *init_verbs[5];
114         unsigned int num_iverbs;
115
116         char *stream_name_analog;
117         struct hda_pcm_stream *stream_analog_playback;
118         struct hda_pcm_stream *stream_analog_capture;
119
120         char *stream_name_digital;
121         struct hda_pcm_stream *stream_digital_playback;
122         struct hda_pcm_stream *stream_digital_capture;
123
124         /* playback */
125         struct hda_multi_out multiout;
126
127         /* capture */
128         unsigned int num_adc_nids;
129         hda_nid_t *adc_nids;
130         hda_nid_t dig_in_nid;
131
132         /* capture source */
133         const struct hda_input_mux *input_mux;
134         unsigned int cur_mux[3];
135
136         /* PCM information */
137         struct hda_pcm pcm_rec[2];
138
139         /* dynamic controls, init_verbs and input_mux */
140         struct auto_pin_cfg autocfg;
141         unsigned int num_kctl_alloc, num_kctl_used;
142         struct snd_kcontrol_new *kctl_alloc;
143         struct hda_input_mux private_imux;
144         hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
145
146 #ifdef CONFIG_SND_HDA_POWER_SAVE
147         struct hda_loopback_check loopback;
148 #endif
149 };
150
151 static hda_nid_t vt1708_adc_nids[2] = {
152         /* ADC1-2 */
153         0x15, 0x27
154 };
155
156 static hda_nid_t vt1709_adc_nids[3] = {
157         /* ADC1-2 */
158         0x14, 0x15, 0x16
159 };
160
161 static hda_nid_t vt1708B_adc_nids[2] = {
162         /* ADC1-2 */
163         0x13, 0x14
164 };
165
166 static hda_nid_t vt1708S_adc_nids[2] = {
167         /* ADC1-2 */
168         0x13, 0x14
169 };
170
171 static hda_nid_t vt1702_adc_nids[3] = {
172         /* ADC1-2 */
173         0x12, 0x20, 0x1F
174 };
175
176 /* add dynamic controls */
177 static int via_add_control(struct via_spec *spec, int type, const char *name,
178                            unsigned long val)
179 {
180         struct snd_kcontrol_new *knew;
181
182         if (spec->num_kctl_used >= spec->num_kctl_alloc) {
183                 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
184
185                 /* array + terminator */
186                 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
187                 if (!knew)
188                         return -ENOMEM;
189                 if (spec->kctl_alloc) {
190                         memcpy(knew, spec->kctl_alloc,
191                                sizeof(*knew) * spec->num_kctl_alloc);
192                         kfree(spec->kctl_alloc);
193                 }
194                 spec->kctl_alloc = knew;
195                 spec->num_kctl_alloc = num;
196         }
197
198         knew = &spec->kctl_alloc[spec->num_kctl_used];
199         *knew = vt1708_control_templates[type];
200         knew->name = kstrdup(name, GFP_KERNEL);
201
202         if (!knew->name)
203                 return -ENOMEM;
204         knew->private_value = val;
205         spec->num_kctl_used++;
206         return 0;
207 }
208
209 /* create input playback/capture controls for the given pin */
210 static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
211                                 const char *ctlname, int idx, int mix_nid)
212 {
213         char name[32];
214         int err;
215
216         sprintf(name, "%s Playback Volume", ctlname);
217         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
218                               HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
219         if (err < 0)
220                 return err;
221         sprintf(name, "%s Playback Switch", ctlname);
222         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
223                               HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
224         if (err < 0)
225                 return err;
226         return 0;
227 }
228
229 static void via_auto_set_output_and_unmute(struct hda_codec *codec,
230                                            hda_nid_t nid, int pin_type,
231                                            int dac_idx)
232 {
233         /* set as output */
234         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
235                             pin_type);
236         snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
237                             AMP_OUT_UNMUTE);
238 }
239
240
241 static void via_auto_init_multi_out(struct hda_codec *codec)
242 {
243         struct via_spec *spec = codec->spec;
244         int i;
245
246         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
247                 hda_nid_t nid = spec->autocfg.line_out_pins[i];
248                 if (nid)
249                         via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
250         }
251 }
252
253 static void via_auto_init_hp_out(struct hda_codec *codec)
254 {
255         struct via_spec *spec = codec->spec;
256         hda_nid_t pin;
257
258         pin = spec->autocfg.hp_pins[0];
259         if (pin) /* connect to front */
260                 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
261 }
262
263 static void via_auto_init_analog_input(struct hda_codec *codec)
264 {
265         struct via_spec *spec = codec->spec;
266         int i;
267
268         for (i = 0; i < AUTO_PIN_LAST; i++) {
269                 hda_nid_t nid = spec->autocfg.input_pins[i];
270
271                 snd_hda_codec_write(codec, nid, 0,
272                                     AC_VERB_SET_PIN_WIDGET_CONTROL,
273                                     (i <= AUTO_PIN_FRONT_MIC ?
274                                      PIN_VREF50 : PIN_IN));
275
276         }
277 }
278 /*
279  * input MUX handling
280  */
281 static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
282                              struct snd_ctl_elem_info *uinfo)
283 {
284         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
285         struct via_spec *spec = codec->spec;
286         return snd_hda_input_mux_info(spec->input_mux, uinfo);
287 }
288
289 static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
290                             struct snd_ctl_elem_value *ucontrol)
291 {
292         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
293         struct via_spec *spec = codec->spec;
294         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
295
296         ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
297         return 0;
298 }
299
300 static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
301                             struct snd_ctl_elem_value *ucontrol)
302 {
303         struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
304         struct via_spec *spec = codec->spec;
305         unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
306         unsigned int vendor_id = codec->vendor_id;
307
308         /* AIW0  lydia 060801 add for correct sw0 input select */
309         if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
310                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
311                                              0x18, &spec->cur_mux[adc_idx]);
312         else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
313                   IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0))
314                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
315                                              0x19, &spec->cur_mux[adc_idx]);
316         else if ((IS_VT1708B_8CH_VENDORID(vendor_id) ||
317                   IS_VT1708B_4CH_VENDORID(vendor_id)) && (adc_idx == 0))
318                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
319                                              0x17, &spec->cur_mux[adc_idx]);
320         else if (IS_VT1702_VENDORID(vendor_id) && (adc_idx == 0))
321                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
322                                              0x13, &spec->cur_mux[adc_idx]);
323         else
324                 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
325                                              spec->adc_nids[adc_idx],
326                                              &spec->cur_mux[adc_idx]);
327 }
328
329 /* capture mixer elements */
330 static struct snd_kcontrol_new vt1708_capture_mixer[] = {
331         HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
332         HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
333         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
334         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
335         {
336                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
337                 /* The multiple "Capture Source" controls confuse alsamixer
338                  * So call somewhat different..
339                  */
340                 /* .name = "Capture Source", */
341                 .name = "Input Source",
342                 .count = 1,
343                 .info = via_mux_enum_info,
344                 .get = via_mux_enum_get,
345                 .put = via_mux_enum_put,
346         },
347         { } /* end */
348 };
349 /*
350  * generic initialization of ADC, input mixers and output mixers
351  */
352 static struct hda_verb vt1708_volume_init_verbs[] = {
353         /*
354          * Unmute ADC0-1 and set the default input to mic-in
355          */
356         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
357         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
358
359
360         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
361          * mixer widget
362          */
363         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
364         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
365         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
366         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
367         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
368         {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
369
370         /*
371          * Set up output mixers (0x19 - 0x1b)
372          */
373         /* set vol=0 to output mixers */
374         {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
375         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
376         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
377         
378         /* Setup default input to PW4 */
379         {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
380         /* PW9 Output enable */
381         {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
382         { }
383 };
384
385 static int via_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_analog_open(codec, &spec->multiout, substream,
391                                              hinfo);
392 }
393
394 static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
395                                     struct hda_codec *codec,
396                                     unsigned int stream_tag,
397                                     unsigned int format,
398                                     struct snd_pcm_substream *substream)
399 {
400         struct via_spec *spec = codec->spec;
401         return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
402                                                 stream_tag, format, substream);
403 }
404
405 static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
406                                     struct hda_codec *codec,
407                                     struct snd_pcm_substream *substream)
408 {
409         struct via_spec *spec = codec->spec;
410         return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
411 }
412
413 /*
414  * Digital out
415  */
416 static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
417                                      struct hda_codec *codec,
418                                      struct snd_pcm_substream *substream)
419 {
420         struct via_spec *spec = codec->spec;
421         return snd_hda_multi_out_dig_open(codec, &spec->multiout);
422 }
423
424 static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
425                                       struct hda_codec *codec,
426                                       struct snd_pcm_substream *substream)
427 {
428         struct via_spec *spec = codec->spec;
429         return snd_hda_multi_out_dig_close(codec, &spec->multiout);
430 }
431
432 static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
433                                         struct hda_codec *codec,
434                                         unsigned int stream_tag,
435                                         unsigned int format,
436                                         struct snd_pcm_substream *substream)
437 {
438         struct via_spec *spec = codec->spec;
439         return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
440                                              stream_tag, format, substream);
441 }
442
443 /*
444  * Analog capture
445  */
446 static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
447                                    struct hda_codec *codec,
448                                    unsigned int stream_tag,
449                                    unsigned int format,
450                                    struct snd_pcm_substream *substream)
451 {
452         struct via_spec *spec = codec->spec;
453
454         snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
455                                    stream_tag, 0, format);
456         return 0;
457 }
458
459 static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
460                                    struct hda_codec *codec,
461                                    struct snd_pcm_substream *substream)
462 {
463         struct via_spec *spec = codec->spec;
464         snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
465         return 0;
466 }
467
468 static struct hda_pcm_stream vt1708_pcm_analog_playback = {
469         .substreams = 1,
470         .channels_min = 2,
471         .channels_max = 8,
472         .nid = 0x10, /* NID to query formats and rates */
473         .ops = {
474                 .open = via_playback_pcm_open,
475                 .prepare = via_playback_pcm_prepare,
476                 .cleanup = via_playback_pcm_cleanup
477         },
478 };
479
480 static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
481         .substreams = 1,
482         .channels_min = 2,
483         .channels_max = 8,
484         .nid = 0x10, /* NID to query formats and rates */
485         /* We got noisy outputs on the right channel on VT1708 when
486          * 24bit samples are used.  Until any workaround is found,
487          * disable the 24bit format, so far.
488          */
489         .formats = SNDRV_PCM_FMTBIT_S16_LE,
490         .ops = {
491                 .open = via_playback_pcm_open,
492                 .prepare = via_playback_pcm_prepare,
493                 .cleanup = via_playback_pcm_cleanup
494         },
495 };
496
497 static struct hda_pcm_stream vt1708_pcm_analog_capture = {
498         .substreams = 2,
499         .channels_min = 2,
500         .channels_max = 2,
501         .nid = 0x15, /* NID to query formats and rates */
502         .ops = {
503                 .prepare = via_capture_pcm_prepare,
504                 .cleanup = via_capture_pcm_cleanup
505         },
506 };
507
508 static struct hda_pcm_stream vt1708_pcm_digital_playback = {
509         .substreams = 1,
510         .channels_min = 2,
511         .channels_max = 2,
512         /* NID is set in via_build_pcms */
513         .ops = {
514                 .open = via_dig_playback_pcm_open,
515                 .close = via_dig_playback_pcm_close,
516                 .prepare = via_dig_playback_pcm_prepare
517         },
518 };
519
520 static struct hda_pcm_stream vt1708_pcm_digital_capture = {
521         .substreams = 1,
522         .channels_min = 2,
523         .channels_max = 2,
524 };
525
526 static int via_build_controls(struct hda_codec *codec)
527 {
528         struct via_spec *spec = codec->spec;
529         int err;
530         int i;
531
532         for (i = 0; i < spec->num_mixers; i++) {
533                 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
534                 if (err < 0)
535                         return err;
536         }
537
538         if (spec->multiout.dig_out_nid) {
539                 err = snd_hda_create_spdif_out_ctls(codec,
540                                                     spec->multiout.dig_out_nid);
541                 if (err < 0)
542                         return err;
543                 err = snd_hda_create_spdif_share_sw(codec,
544                                                     &spec->multiout);
545                 if (err < 0)
546                         return err;
547                 spec->multiout.share_spdif = 1;
548         }
549         if (spec->dig_in_nid) {
550                 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
551                 if (err < 0)
552                         return err;
553         }
554         return 0;
555 }
556
557 static int via_build_pcms(struct hda_codec *codec)
558 {
559         struct via_spec *spec = codec->spec;
560         struct hda_pcm *info = spec->pcm_rec;
561
562         codec->num_pcms = 1;
563         codec->pcm_info = info;
564
565         info->name = spec->stream_name_analog;
566         info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
567         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
568         info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
569         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
570
571         info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
572                 spec->multiout.max_channels;
573
574         if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
575                 codec->num_pcms++;
576                 info++;
577                 info->name = spec->stream_name_digital;
578                 info->pcm_type = HDA_PCM_TYPE_SPDIF;
579                 if (spec->multiout.dig_out_nid) {
580                         info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
581                                 *(spec->stream_digital_playback);
582                         info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
583                                 spec->multiout.dig_out_nid;
584                 }
585                 if (spec->dig_in_nid) {
586                         info->stream[SNDRV_PCM_STREAM_CAPTURE] =
587                                 *(spec->stream_digital_capture);
588                         info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
589                                 spec->dig_in_nid;
590                 }
591         }
592
593         return 0;
594 }
595
596 static void via_free(struct hda_codec *codec)
597 {
598         struct via_spec *spec = codec->spec;
599         unsigned int i;
600
601         if (!spec)
602                 return;
603
604         if (spec->kctl_alloc) {
605                 for (i = 0; i < spec->num_kctl_used; i++)
606                         kfree(spec->kctl_alloc[i].name);
607                 kfree(spec->kctl_alloc);
608         }
609
610         kfree(codec->spec);
611 }
612
613 /* mute internal speaker if HP is plugged */
614 static void via_hp_automute(struct hda_codec *codec)
615 {
616         unsigned int present;
617         struct via_spec *spec = codec->spec;
618
619         present = snd_hda_codec_read(codec, spec->autocfg.hp_pins[0], 0,
620                                      AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
621         snd_hda_codec_amp_stereo(codec, spec->autocfg.line_out_pins[0],
622                                  HDA_OUTPUT, 0, HDA_AMP_MUTE,
623                                  present ? HDA_AMP_MUTE : 0);
624 }
625
626 static void via_gpio_control(struct hda_codec *codec)
627 {
628         unsigned int gpio_data;
629         unsigned int vol_counter;
630         unsigned int vol;
631         unsigned int master_vol;
632
633         struct via_spec *spec = codec->spec;
634
635         gpio_data = snd_hda_codec_read(codec, codec->afg, 0,
636                                        AC_VERB_GET_GPIO_DATA, 0) & 0x03;
637
638         vol_counter = (snd_hda_codec_read(codec, codec->afg, 0,
639                                           0xF84, 0) & 0x3F0000) >> 16;
640
641         vol = vol_counter & 0x1F;
642         master_vol = snd_hda_codec_read(codec, 0x1A, 0,
643                                         AC_VERB_GET_AMP_GAIN_MUTE,
644                                         AC_AMP_GET_INPUT);
645
646         if (gpio_data == 0x02) {
647                 /* unmute line out */
648                 snd_hda_codec_amp_stereo(codec, spec->autocfg.line_out_pins[0],
649                                          HDA_OUTPUT, 0, HDA_AMP_MUTE, 0);
650
651                 if (vol_counter & 0x20) {
652                         /* decrease volume */
653                         if (vol > master_vol)
654                                 vol = master_vol;
655                         snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT,
656                                                  0, HDA_AMP_VOLMASK,
657                                                  master_vol-vol);
658                 } else {
659                         /* increase volume */
660                         snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, 0,
661                                          HDA_AMP_VOLMASK,
662                                          ((master_vol+vol) > 0x2A) ? 0x2A :
663                                           (master_vol+vol));
664                 }
665         } else if (!(gpio_data & 0x02)) {
666                 /* mute line out */
667                 snd_hda_codec_amp_stereo(codec,
668                                          spec->autocfg.line_out_pins[0],
669                                          HDA_OUTPUT, 0, HDA_AMP_MUTE,
670                                          HDA_AMP_MUTE);
671         }
672 }
673
674 /* unsolicited event for jack sensing */
675 static void via_unsol_event(struct hda_codec *codec,
676                                   unsigned int res)
677 {
678         res >>= 26;
679         if (res == VIA_HP_EVENT)
680                 via_hp_automute(codec);
681         else if (res == VIA_GPIO_EVENT)
682                 via_gpio_control(codec);
683 }
684
685 static int via_init(struct hda_codec *codec)
686 {
687         struct via_spec *spec = codec->spec;
688         int i;
689         for (i = 0; i < spec->num_iverbs; i++)
690                 snd_hda_sequence_write(codec, spec->init_verbs[i]);
691
692         /* Lydia Add for EAPD enable */
693         if (!spec->dig_in_nid) { /* No Digital In connection */
694                 if (IS_VT1708_VENDORID(codec->vendor_id)) {
695                         snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
696                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
697                                             PIN_OUT);
698                         snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
699                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
700                 } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
701                            IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
702                         snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
703                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
704                                             PIN_OUT);
705                         snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
706                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
707                 } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
708                            IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
709                         snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
710                                             AC_VERB_SET_PIN_WIDGET_CONTROL,
711                                             PIN_OUT);
712                         snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
713                                             AC_VERB_SET_EAPD_BTLENABLE, 0x02);
714                 }
715         } else /* enable SPDIF-input pin */
716                 snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
717                                     AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
718
719         return 0;
720 }
721
722 #ifdef CONFIG_SND_HDA_POWER_SAVE
723 static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
724 {
725         struct via_spec *spec = codec->spec;
726         return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
727 }
728 #endif
729
730 /*
731  */
732 static struct hda_codec_ops via_patch_ops = {
733         .build_controls = via_build_controls,
734         .build_pcms = via_build_pcms,
735         .init = via_init,
736         .free = via_free,
737 #ifdef CONFIG_SND_HDA_POWER_SAVE
738         .check_power_status = via_check_power_status,
739 #endif
740 };
741
742 /* fill in the dac_nids table from the parsed pin configuration */
743 static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
744                                      const struct auto_pin_cfg *cfg)
745 {
746         int i;
747         hda_nid_t nid;
748
749         spec->multiout.num_dacs = cfg->line_outs;
750
751         spec->multiout.dac_nids = spec->private_dac_nids;
752         
753         for(i = 0; i < 4; i++) {
754                 nid = cfg->line_out_pins[i];
755                 if (nid) {
756                         /* config dac list */
757                         switch (i) {
758                         case AUTO_SEQ_FRONT:
759                                 spec->multiout.dac_nids[i] = 0x10;
760                                 break;
761                         case AUTO_SEQ_CENLFE:
762                                 spec->multiout.dac_nids[i] = 0x12;
763                                 break;
764                         case AUTO_SEQ_SURROUND:
765                                 spec->multiout.dac_nids[i] = 0x11;
766                                 break;
767                         case AUTO_SEQ_SIDE:
768                                 spec->multiout.dac_nids[i] = 0x13;
769                                 break;
770                         }
771                 }
772         }
773
774         return 0;
775 }
776
777 /* add playback controls from the parsed DAC table */
778 static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
779                                              const struct auto_pin_cfg *cfg)
780 {
781         char name[32];
782         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
783         hda_nid_t nid, nid_vol = 0;
784         int i, err;
785
786         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
787                 nid = cfg->line_out_pins[i];
788
789                 if (!nid)
790                         continue;
791                 
792                 if (i != AUTO_SEQ_FRONT)
793                         nid_vol = 0x18 + i;
794
795                 if (i == AUTO_SEQ_CENLFE) {
796                         /* Center/LFE */
797                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
798                                         "Center Playback Volume",
799                                         HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
800                                                             HDA_OUTPUT));
801                         if (err < 0)
802                                 return err;
803                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
804                                               "LFE Playback Volume",
805                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
806                                                                   HDA_OUTPUT));
807                         if (err < 0)
808                                 return err;
809                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
810                                               "Center Playback Switch",
811                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
812                                                                   HDA_OUTPUT));
813                         if (err < 0)
814                                 return err;
815                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
816                                               "LFE Playback Switch",
817                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
818                                                                   HDA_OUTPUT));
819                         if (err < 0)
820                                 return err;
821                 } else if (i == AUTO_SEQ_FRONT){
822                         /* add control to mixer index 0 */
823                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
824                                               "Master Front Playback Volume",
825                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
826                                                                   HDA_INPUT));
827                         if (err < 0)
828                                 return err;
829                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
830                                               "Master Front Playback Switch",
831                                               HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
832                                                                   HDA_INPUT));
833                         if (err < 0)
834                                 return err;
835                         
836                         /* add control to PW3 */
837                         sprintf(name, "%s Playback Volume", chname[i]);
838                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
839                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
840                                                                   HDA_OUTPUT));
841                         if (err < 0)
842                                 return err;
843                         sprintf(name, "%s Playback Switch", chname[i]);
844                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
845                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
846                                                                   HDA_OUTPUT));
847                         if (err < 0)
848                                 return err;
849                 } else {
850                         sprintf(name, "%s Playback Volume", chname[i]);
851                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
852                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
853                                                                   HDA_OUTPUT));
854                         if (err < 0)
855                                 return err;
856                         sprintf(name, "%s Playback Switch", chname[i]);
857                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
858                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
859                                                                   HDA_OUTPUT));
860                         if (err < 0)
861                                 return err;
862                 }
863         }
864
865         return 0;
866 }
867
868 static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
869 {
870         int err;
871
872         if (!pin)
873                 return 0;
874
875         spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
876
877         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
878                               "Headphone Playback Volume",
879                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
880         if (err < 0)
881                 return err;
882         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
883                               "Headphone Playback Switch",
884                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
885         if (err < 0)
886                 return err;
887
888         return 0;
889 }
890
891 /* create playback/capture controls for input pins */
892 static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
893                                                 const struct auto_pin_cfg *cfg)
894 {
895         static char *labels[] = {
896                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
897         };
898         struct hda_input_mux *imux = &spec->private_imux;
899         int i, err, idx = 0;
900
901         /* for internal loopback recording select */
902         imux->items[imux->num_items].label = "Stereo Mixer";
903         imux->items[imux->num_items].index = idx;
904         imux->num_items++;
905
906         for (i = 0; i < AUTO_PIN_LAST; i++) {
907                 if (!cfg->input_pins[i])
908                         continue;
909
910                 switch (cfg->input_pins[i]) {
911                 case 0x1d: /* Mic */
912                         idx = 2;
913                         break;
914                                 
915                 case 0x1e: /* Line In */
916                         idx = 3;
917                         break;
918
919                 case 0x21: /* Front Mic */
920                         idx = 4;
921                         break;
922
923                 case 0x24: /* CD */
924                         idx = 1;
925                         break;
926                 }
927                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
928                                            idx, 0x17);
929                 if (err < 0)
930                         return err;
931                 imux->items[imux->num_items].label = labels[i];
932                 imux->items[imux->num_items].index = idx;
933                 imux->num_items++;
934         }
935         return 0;
936 }
937
938 #ifdef CONFIG_SND_HDA_POWER_SAVE
939 static struct hda_amp_list vt1708_loopbacks[] = {
940         { 0x17, HDA_INPUT, 1 },
941         { 0x17, HDA_INPUT, 2 },
942         { 0x17, HDA_INPUT, 3 },
943         { 0x17, HDA_INPUT, 4 },
944         { } /* end */
945 };
946 #endif
947
948 static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
949 {
950         unsigned int def_conf;
951         unsigned char seqassoc;
952
953         def_conf = snd_hda_codec_read(codec, nid, 0,
954                                       AC_VERB_GET_CONFIG_DEFAULT, 0);
955         seqassoc = (unsigned char) get_defcfg_association(def_conf);
956         seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
957         if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) {
958                 if (seqassoc == 0xff) {
959                         def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
960                         snd_hda_codec_write(codec, nid, 0,
961                                             AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
962                                             def_conf >> 24);
963                 }
964         }
965
966         return;
967 }
968
969 static int vt1708_parse_auto_config(struct hda_codec *codec)
970 {
971         struct via_spec *spec = codec->spec;
972         int err;
973
974         /* Add HP and CD pin config connect bit re-config action */
975         vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
976         vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
977
978         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
979         if (err < 0)
980                 return err;
981         err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
982         if (err < 0)
983                 return err;
984         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
985                 return 0; /* can't find valid BIOS pin config */
986
987         err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
988         if (err < 0)
989                 return err;
990         err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
991         if (err < 0)
992                 return err;
993         err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
994         if (err < 0)
995                 return err;
996
997         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
998
999         if (spec->autocfg.dig_out_pin)
1000                 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
1001         if (spec->autocfg.dig_in_pin)
1002                 spec->dig_in_nid = VT1708_DIGIN_NID;
1003
1004         if (spec->kctl_alloc)
1005                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1006
1007         spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs;
1008
1009         spec->input_mux = &spec->private_imux;
1010
1011         return 1;
1012 }
1013
1014 /* init callback for auto-configuration model -- overriding the default init */
1015 static int via_auto_init(struct hda_codec *codec)
1016 {
1017         via_init(codec);
1018         via_auto_init_multi_out(codec);
1019         via_auto_init_hp_out(codec);
1020         via_auto_init_analog_input(codec);
1021         return 0;
1022 }
1023
1024 static int patch_vt1708(struct hda_codec *codec)
1025 {
1026         struct via_spec *spec;
1027         int err;
1028
1029         /* create a codec specific record */
1030         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1031         if (spec == NULL)
1032                 return -ENOMEM;
1033
1034         codec->spec = spec;
1035
1036         /* automatic parse from the BIOS config */
1037         err = vt1708_parse_auto_config(codec);
1038         if (err < 0) {
1039                 via_free(codec);
1040                 return err;
1041         } else if (!err) {
1042                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1043                        "from BIOS.  Using genenic mode...\n");
1044         }
1045
1046         
1047         spec->stream_name_analog = "VT1708 Analog";
1048         spec->stream_analog_playback = &vt1708_pcm_analog_playback;
1049         /* disable 32bit format on VT1708 */
1050         if (codec->vendor_id == 0x11061708)
1051                 spec->stream_analog_playback = &vt1708_pcm_analog_s16_playback;
1052         spec->stream_analog_capture = &vt1708_pcm_analog_capture;
1053
1054         spec->stream_name_digital = "VT1708 Digital";
1055         spec->stream_digital_playback = &vt1708_pcm_digital_playback;
1056         spec->stream_digital_capture = &vt1708_pcm_digital_capture;
1057
1058         
1059         if (!spec->adc_nids && spec->input_mux) {
1060                 spec->adc_nids = vt1708_adc_nids;
1061                 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
1062                 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
1063                 spec->num_mixers++;
1064         }
1065
1066         codec->patch_ops = via_patch_ops;
1067
1068         codec->patch_ops.init = via_auto_init;
1069 #ifdef CONFIG_SND_HDA_POWER_SAVE
1070         spec->loopback.amplist = vt1708_loopbacks;
1071 #endif
1072
1073         return 0;
1074 }
1075
1076 /* capture mixer elements */
1077 static struct snd_kcontrol_new vt1709_capture_mixer[] = {
1078         HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
1079         HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
1080         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
1081         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
1082         HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
1083         HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
1084         {
1085                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1086                 /* The multiple "Capture Source" controls confuse alsamixer
1087                  * So call somewhat different..
1088                  */
1089                 /* .name = "Capture Source", */
1090                 .name = "Input Source",
1091                 .count = 1,
1092                 .info = via_mux_enum_info,
1093                 .get = via_mux_enum_get,
1094                 .put = via_mux_enum_put,
1095         },
1096         { } /* end */
1097 };
1098
1099 static struct hda_verb vt1709_uniwill_init_verbs[] = {
1100         {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
1101         { }
1102 };
1103
1104 /*
1105  * generic initialization of ADC, input mixers and output mixers
1106  */
1107 static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
1108         /*
1109          * Unmute ADC0-2 and set the default input to mic-in
1110          */
1111         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1112         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1113         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1114
1115
1116         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1117          * mixer widget
1118          */
1119         /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1120         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1121         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1122         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1123         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1124         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1125
1126         /*
1127          * Set up output selector (0x1a, 0x1b, 0x29)
1128          */
1129         /* set vol=0 to output mixers */
1130         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1131         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1132         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1133
1134         /*
1135          *  Unmute PW3 and PW4
1136          */
1137         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1138         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1139
1140         /* Set input of PW4 as AOW4 */
1141         {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
1142         /* PW9 Output enable */
1143         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1144         { }
1145 };
1146
1147 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
1148         .substreams = 1,
1149         .channels_min = 2,
1150         .channels_max = 10,
1151         .nid = 0x10, /* NID to query formats and rates */
1152         .ops = {
1153                 .open = via_playback_pcm_open,
1154                 .prepare = via_playback_pcm_prepare,
1155                 .cleanup = via_playback_pcm_cleanup
1156         },
1157 };
1158
1159 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
1160         .substreams = 1,
1161         .channels_min = 2,
1162         .channels_max = 6,
1163         .nid = 0x10, /* NID to query formats and rates */
1164         .ops = {
1165                 .open = via_playback_pcm_open,
1166                 .prepare = via_playback_pcm_prepare,
1167                 .cleanup = via_playback_pcm_cleanup
1168         },
1169 };
1170
1171 static struct hda_pcm_stream vt1709_pcm_analog_capture = {
1172         .substreams = 2,
1173         .channels_min = 2,
1174         .channels_max = 2,
1175         .nid = 0x14, /* NID to query formats and rates */
1176         .ops = {
1177                 .prepare = via_capture_pcm_prepare,
1178                 .cleanup = via_capture_pcm_cleanup
1179         },
1180 };
1181
1182 static struct hda_pcm_stream vt1709_pcm_digital_playback = {
1183         .substreams = 1,
1184         .channels_min = 2,
1185         .channels_max = 2,
1186         /* NID is set in via_build_pcms */
1187         .ops = {
1188                 .open = via_dig_playback_pcm_open,
1189                 .close = via_dig_playback_pcm_close
1190         },
1191 };
1192
1193 static struct hda_pcm_stream vt1709_pcm_digital_capture = {
1194         .substreams = 1,
1195         .channels_min = 2,
1196         .channels_max = 2,
1197 };
1198
1199 static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
1200                                      const struct auto_pin_cfg *cfg)
1201 {
1202         int i;
1203         hda_nid_t nid;
1204
1205         if (cfg->line_outs == 4)  /* 10 channels */
1206                 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
1207         else if (cfg->line_outs == 3) /* 6 channels */
1208                 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
1209
1210         spec->multiout.dac_nids = spec->private_dac_nids;
1211
1212         if (cfg->line_outs == 4) { /* 10 channels */
1213                 for (i = 0; i < cfg->line_outs; i++) {
1214                         nid = cfg->line_out_pins[i];
1215                         if (nid) {
1216                                 /* config dac list */
1217                                 switch (i) {
1218                                 case AUTO_SEQ_FRONT:
1219                                         /* AOW0 */
1220                                         spec->multiout.dac_nids[i] = 0x10;
1221                                         break;
1222                                 case AUTO_SEQ_CENLFE:
1223                                         /* AOW2 */
1224                                         spec->multiout.dac_nids[i] = 0x12;
1225                                         break;
1226                                 case AUTO_SEQ_SURROUND:
1227                                         /* AOW3 */
1228                                         spec->multiout.dac_nids[i] = 0x11;
1229                                         break;
1230                                 case AUTO_SEQ_SIDE:
1231                                         /* AOW1 */
1232                                         spec->multiout.dac_nids[i] = 0x27;
1233                                         break;
1234                                 default:
1235                                         break;
1236                                 }
1237                         }
1238                 }
1239                 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1240
1241         } else if (cfg->line_outs == 3) { /* 6 channels */
1242                 for(i = 0; i < cfg->line_outs; i++) {
1243                         nid = cfg->line_out_pins[i];
1244                         if (nid) {
1245                                 /* config dac list */
1246                                 switch(i) {
1247                                 case AUTO_SEQ_FRONT:
1248                                         /* AOW0 */
1249                                         spec->multiout.dac_nids[i] = 0x10;
1250                                         break;
1251                                 case AUTO_SEQ_CENLFE:
1252                                         /* AOW2 */
1253                                         spec->multiout.dac_nids[i] = 0x12;
1254                                         break;
1255                                 case AUTO_SEQ_SURROUND:
1256                                         /* AOW1 */
1257                                         spec->multiout.dac_nids[i] = 0x11;
1258                                         break;
1259                                 default:
1260                                         break;
1261                                 }
1262                         }
1263                 }
1264         }
1265
1266         return 0;
1267 }
1268
1269 /* add playback controls from the parsed DAC table */
1270 static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1271                                              const struct auto_pin_cfg *cfg)
1272 {
1273         char name[32];
1274         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1275         hda_nid_t nid = 0;
1276         int i, err;
1277
1278         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1279                 nid = cfg->line_out_pins[i];
1280
1281                 if (!nid)       
1282                         continue;
1283
1284                 if (i == AUTO_SEQ_CENLFE) {
1285                         /* Center/LFE */
1286                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1287                                               "Center Playback Volume",
1288                                               HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1289                                                                   HDA_OUTPUT));
1290                         if (err < 0)
1291                                 return err;
1292                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1293                                               "LFE Playback Volume",
1294                                               HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1295                                                                   HDA_OUTPUT));
1296                         if (err < 0)
1297                                 return err;
1298                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1299                                               "Center Playback Switch",
1300                                               HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1301                                                                   HDA_OUTPUT));
1302                         if (err < 0)
1303                                 return err;
1304                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1305                                               "LFE Playback Switch",
1306                                               HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1307                                                                   HDA_OUTPUT));
1308                         if (err < 0)
1309                                 return err;
1310                 } else if (i == AUTO_SEQ_FRONT){
1311                         /* add control to mixer index 0 */
1312                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1313                                               "Master Front Playback Volume",
1314                                               HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1315                                                                   HDA_INPUT));
1316                         if (err < 0)
1317                                 return err;
1318                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1319                                               "Master Front Playback Switch",
1320                                               HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1321                                                                   HDA_INPUT));
1322                         if (err < 0)
1323                                 return err;
1324                         
1325                         /* add control to PW3 */
1326                         sprintf(name, "%s Playback Volume", chname[i]);
1327                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1328                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1329                                                                   HDA_OUTPUT));
1330                         if (err < 0)
1331                                 return err;
1332                         sprintf(name, "%s Playback Switch", chname[i]);
1333                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1334                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1335                                                                   HDA_OUTPUT));
1336                         if (err < 0)
1337                                 return err;
1338                 } else if (i == AUTO_SEQ_SURROUND) {
1339                         sprintf(name, "%s Playback Volume", chname[i]);
1340                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1341                                               HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1342                                                                   HDA_OUTPUT));
1343                         if (err < 0)
1344                                 return err;
1345                         sprintf(name, "%s Playback Switch", chname[i]);
1346                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1347                                               HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1348                                                                   HDA_OUTPUT));
1349                         if (err < 0)
1350                                 return err;
1351                 } else if (i == AUTO_SEQ_SIDE) {
1352                         sprintf(name, "%s Playback Volume", chname[i]);
1353                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1354                                               HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1355                                                                   HDA_OUTPUT));
1356                         if (err < 0)
1357                                 return err;
1358                         sprintf(name, "%s Playback Switch", chname[i]);
1359                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1360                                               HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1361                                                                   HDA_OUTPUT));
1362                         if (err < 0)
1363                                 return err;
1364                 }
1365         }
1366
1367         return 0;
1368 }
1369
1370 static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1371 {
1372         int err;
1373
1374         if (!pin)
1375                 return 0;
1376
1377         if (spec->multiout.num_dacs == 5) /* 10 channels */
1378                 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1379         else if (spec->multiout.num_dacs == 3) /* 6 channels */
1380                 spec->multiout.hp_nid = 0;
1381
1382         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1383                               "Headphone Playback Volume",
1384                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1385         if (err < 0)
1386                 return err;
1387         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1388                               "Headphone Playback Switch",
1389                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1390         if (err < 0)
1391                 return err;
1392
1393         return 0;
1394 }
1395
1396 /* create playback/capture controls for input pins */
1397 static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1398                                                 const struct auto_pin_cfg *cfg)
1399 {
1400         static char *labels[] = {
1401                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1402         };
1403         struct hda_input_mux *imux = &spec->private_imux;
1404         int i, err, idx = 0;
1405
1406         /* for internal loopback recording select */
1407         imux->items[imux->num_items].label = "Stereo Mixer";
1408         imux->items[imux->num_items].index = idx;
1409         imux->num_items++;
1410
1411         for (i = 0; i < AUTO_PIN_LAST; i++) {
1412                 if (!cfg->input_pins[i])
1413                         continue;
1414
1415                 switch (cfg->input_pins[i]) {
1416                 case 0x1d: /* Mic */
1417                         idx = 2;
1418                         break;
1419                                 
1420                 case 0x1e: /* Line In */
1421                         idx = 3;
1422                         break;
1423
1424                 case 0x21: /* Front Mic */
1425                         idx = 4;
1426                         break;
1427
1428                 case 0x23: /* CD */
1429                         idx = 1;
1430                         break;
1431                 }
1432                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1433                                            idx, 0x18);
1434                 if (err < 0)
1435                         return err;
1436                 imux->items[imux->num_items].label = labels[i];
1437                 imux->items[imux->num_items].index = idx;
1438                 imux->num_items++;
1439         }
1440         return 0;
1441 }
1442
1443 static int vt1709_parse_auto_config(struct hda_codec *codec)
1444 {
1445         struct via_spec *spec = codec->spec;
1446         int err;
1447
1448         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1449         if (err < 0)
1450                 return err;
1451         err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1452         if (err < 0)
1453                 return err;
1454         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1455                 return 0; /* can't find valid BIOS pin config */
1456
1457         err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1458         if (err < 0)
1459                 return err;
1460         err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1461         if (err < 0)
1462                 return err;
1463         err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1464         if (err < 0)
1465                 return err;
1466
1467         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1468
1469         if (spec->autocfg.dig_out_pin)
1470                 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1471         if (spec->autocfg.dig_in_pin)
1472                 spec->dig_in_nid = VT1709_DIGIN_NID;
1473
1474         if (spec->kctl_alloc)
1475                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1476
1477         spec->input_mux = &spec->private_imux;
1478
1479         return 1;
1480 }
1481
1482 #ifdef CONFIG_SND_HDA_POWER_SAVE
1483 static struct hda_amp_list vt1709_loopbacks[] = {
1484         { 0x18, HDA_INPUT, 1 },
1485         { 0x18, HDA_INPUT, 2 },
1486         { 0x18, HDA_INPUT, 3 },
1487         { 0x18, HDA_INPUT, 4 },
1488         { } /* end */
1489 };
1490 #endif
1491
1492 static int patch_vt1709_10ch(struct hda_codec *codec)
1493 {
1494         struct via_spec *spec;
1495         int err;
1496
1497         /* create a codec specific record */
1498         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1499         if (spec == NULL)
1500                 return -ENOMEM;
1501
1502         codec->spec = spec;
1503
1504         err = vt1709_parse_auto_config(codec);
1505         if (err < 0) {
1506                 via_free(codec);
1507                 return err;
1508         } else if (!err) {
1509                 printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1510                        "Using genenic mode...\n");
1511         }
1512
1513         spec->init_verbs[spec->num_iverbs++] = vt1709_10ch_volume_init_verbs;
1514         spec->init_verbs[spec->num_iverbs++] = vt1709_uniwill_init_verbs;
1515
1516         spec->stream_name_analog = "VT1709 Analog";
1517         spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1518         spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1519
1520         spec->stream_name_digital = "VT1709 Digital";
1521         spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1522         spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1523
1524         
1525         if (!spec->adc_nids && spec->input_mux) {
1526                 spec->adc_nids = vt1709_adc_nids;
1527                 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1528                 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1529                 spec->num_mixers++;
1530         }
1531
1532         codec->patch_ops = via_patch_ops;
1533
1534         codec->patch_ops.init = via_auto_init;
1535         codec->patch_ops.unsol_event = via_unsol_event;
1536 #ifdef CONFIG_SND_HDA_POWER_SAVE
1537         spec->loopback.amplist = vt1709_loopbacks;
1538 #endif
1539
1540         return 0;
1541 }
1542 /*
1543  * generic initialization of ADC, input mixers and output mixers
1544  */
1545 static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1546         /*
1547          * Unmute ADC0-2 and set the default input to mic-in
1548          */
1549         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1550         {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1551         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1552
1553
1554         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1555          * mixer widget
1556          */
1557         /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1558         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1559         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1560         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1561         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1562         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1563
1564         /*
1565          * Set up output selector (0x1a, 0x1b, 0x29)
1566          */
1567         /* set vol=0 to output mixers */
1568         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1569         {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1570         {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1571
1572         /*
1573          *  Unmute PW3 and PW4
1574          */
1575         {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1576         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1577
1578         /* Set input of PW4 as MW0 */
1579         {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1580         /* PW9 Output enable */
1581         {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1582         { }
1583 };
1584
1585 static int patch_vt1709_6ch(struct hda_codec *codec)
1586 {
1587         struct via_spec *spec;
1588         int err;
1589
1590         /* create a codec specific record */
1591         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1592         if (spec == NULL)
1593                 return -ENOMEM;
1594
1595         codec->spec = spec;
1596
1597         err = vt1709_parse_auto_config(codec);
1598         if (err < 0) {
1599                 via_free(codec);
1600                 return err;
1601         } else if (!err) {
1602                 printk(KERN_INFO "hda_codec: Cannot set up configuration.  "
1603                        "Using genenic mode...\n");
1604         }
1605
1606         spec->init_verbs[spec->num_iverbs++] = vt1709_6ch_volume_init_verbs;
1607         spec->init_verbs[spec->num_iverbs++] = vt1709_uniwill_init_verbs;
1608
1609         spec->stream_name_analog = "VT1709 Analog";
1610         spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1611         spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1612
1613         spec->stream_name_digital = "VT1709 Digital";
1614         spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1615         spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1616
1617         
1618         if (!spec->adc_nids && spec->input_mux) {
1619                 spec->adc_nids = vt1709_adc_nids;
1620                 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1621                 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1622                 spec->num_mixers++;
1623         }
1624
1625         codec->patch_ops = via_patch_ops;
1626
1627         codec->patch_ops.init = via_auto_init;
1628         codec->patch_ops.unsol_event = via_unsol_event;
1629 #ifdef CONFIG_SND_HDA_POWER_SAVE
1630         spec->loopback.amplist = vt1709_loopbacks;
1631 #endif
1632         return 0;
1633 }
1634
1635 /* capture mixer elements */
1636 static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
1637         HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
1638         HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
1639         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
1640         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
1641         {
1642                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1643                 /* The multiple "Capture Source" controls confuse alsamixer
1644                  * So call somewhat different..
1645                  */
1646                 /* .name = "Capture Source", */
1647                 .name = "Input Source",
1648                 .count = 1,
1649                 .info = via_mux_enum_info,
1650                 .get = via_mux_enum_get,
1651                 .put = via_mux_enum_put,
1652         },
1653         { } /* end */
1654 };
1655 /*
1656  * generic initialization of ADC, input mixers and output mixers
1657  */
1658 static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
1659         /*
1660          * Unmute ADC0-1 and set the default input to mic-in
1661          */
1662         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1663         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1664
1665
1666         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1667          * mixer widget
1668          */
1669         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1670         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1671         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1672         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1673         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1674         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1675
1676         /*
1677          * Set up output mixers
1678          */
1679         /* set vol=0 to output mixers */
1680         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1681         {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1682         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1683
1684         /* Setup default input to PW4 */
1685         {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1},
1686         /* PW9 Output enable */
1687         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1688         /* PW10 Input enable */
1689         {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1690         { }
1691 };
1692
1693 static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
1694         /*
1695          * Unmute ADC0-1 and set the default input to mic-in
1696          */
1697         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1698         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1699
1700
1701         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1702          * mixer widget
1703          */
1704         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1705         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1706         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1707         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1708         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1709         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1710
1711         /*
1712          * Set up output mixers
1713          */
1714         /* set vol=0 to output mixers */
1715         {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1716         {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1717         {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1718
1719         /* Setup default input of PW4 to MW0 */
1720         {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
1721         /* PW9 Output enable */
1722         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1723         /* PW10 Input enable */
1724         {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1725         { }
1726 };
1727
1728 static struct hda_verb vt1708B_uniwill_init_verbs[] = {
1729         {0x1D, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
1730         { }
1731 };
1732
1733 static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
1734         .substreams = 1,
1735         .channels_min = 2,
1736         .channels_max = 8,
1737         .nid = 0x10, /* NID to query formats and rates */
1738         .ops = {
1739                 .open = via_playback_pcm_open,
1740                 .prepare = via_playback_pcm_prepare,
1741                 .cleanup = via_playback_pcm_cleanup
1742         },
1743 };
1744
1745 static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
1746         .substreams = 1,
1747         .channels_min = 2,
1748         .channels_max = 4,
1749         .nid = 0x10, /* NID to query formats and rates */
1750         .ops = {
1751                 .open = via_playback_pcm_open,
1752                 .prepare = via_playback_pcm_prepare,
1753                 .cleanup = via_playback_pcm_cleanup
1754         },
1755 };
1756
1757 static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
1758         .substreams = 2,
1759         .channels_min = 2,
1760         .channels_max = 2,
1761         .nid = 0x13, /* NID to query formats and rates */
1762         .ops = {
1763                 .prepare = via_capture_pcm_prepare,
1764                 .cleanup = via_capture_pcm_cleanup
1765         },
1766 };
1767
1768 static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
1769         .substreams = 1,
1770         .channels_min = 2,
1771         .channels_max = 2,
1772         /* NID is set in via_build_pcms */
1773         .ops = {
1774                 .open = via_dig_playback_pcm_open,
1775                 .close = via_dig_playback_pcm_close,
1776                 .prepare = via_dig_playback_pcm_prepare
1777         },
1778 };
1779
1780 static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
1781         .substreams = 1,
1782         .channels_min = 2,
1783         .channels_max = 2,
1784 };
1785
1786 /* fill in the dac_nids table from the parsed pin configuration */
1787 static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
1788                                      const struct auto_pin_cfg *cfg)
1789 {
1790         int i;
1791         hda_nid_t nid;
1792
1793         spec->multiout.num_dacs = cfg->line_outs;
1794
1795         spec->multiout.dac_nids = spec->private_dac_nids;
1796
1797         for (i = 0; i < 4; i++) {
1798                 nid = cfg->line_out_pins[i];
1799                 if (nid) {
1800                         /* config dac list */
1801                         switch (i) {
1802                         case AUTO_SEQ_FRONT:
1803                                 spec->multiout.dac_nids[i] = 0x10;
1804                                 break;
1805                         case AUTO_SEQ_CENLFE:
1806                                 spec->multiout.dac_nids[i] = 0x24;
1807                                 break;
1808                         case AUTO_SEQ_SURROUND:
1809                                 spec->multiout.dac_nids[i] = 0x11;
1810                                 break;
1811                         case AUTO_SEQ_SIDE:
1812                                 spec->multiout.dac_nids[i] = 0x25;
1813                                 break;
1814                         }
1815                 }
1816         }
1817
1818         return 0;
1819 }
1820
1821 /* add playback controls from the parsed DAC table */
1822 static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
1823                                              const struct auto_pin_cfg *cfg)
1824 {
1825         char name[32];
1826         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1827         hda_nid_t nid_vols[] = {0x16, 0x18, 0x26, 0x27};
1828         hda_nid_t nid, nid_vol = 0;
1829         int i, err;
1830
1831         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1832                 nid = cfg->line_out_pins[i];
1833
1834                 if (!nid)
1835                         continue;
1836
1837                 nid_vol = nid_vols[i];
1838
1839                 if (i == AUTO_SEQ_CENLFE) {
1840                         /* Center/LFE */
1841                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1842                                               "Center Playback Volume",
1843                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1844                                                                   HDA_OUTPUT));
1845                         if (err < 0)
1846                                 return err;
1847                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1848                                               "LFE Playback Volume",
1849                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1850                                                                   HDA_OUTPUT));
1851                         if (err < 0)
1852                                 return err;
1853                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1854                                               "Center Playback Switch",
1855                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1856                                                                   HDA_OUTPUT));
1857                         if (err < 0)
1858                                 return err;
1859                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1860                                               "LFE Playback Switch",
1861                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1862                                                                   HDA_OUTPUT));
1863                         if (err < 0)
1864                                 return err;
1865                 } else if (i == AUTO_SEQ_FRONT) {
1866                         /* add control to mixer index 0 */
1867                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1868                                               "Master Front Playback Volume",
1869                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1870                                                                   HDA_INPUT));
1871                         if (err < 0)
1872                                 return err;
1873                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1874                                               "Master Front Playback Switch",
1875                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1876                                                                   HDA_INPUT));
1877                         if (err < 0)
1878                                 return err;
1879
1880                         /* add control to PW3 */
1881                         sprintf(name, "%s Playback Volume", chname[i]);
1882                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1883                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1884                                                                   HDA_OUTPUT));
1885                         if (err < 0)
1886                                 return err;
1887                         sprintf(name, "%s Playback Switch", chname[i]);
1888                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1889                                               HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1890                                                                   HDA_OUTPUT));
1891                         if (err < 0)
1892                                 return err;
1893                 } else {
1894                         sprintf(name, "%s Playback Volume", chname[i]);
1895                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1896                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1897                                                                   HDA_OUTPUT));
1898                         if (err < 0)
1899                                 return err;
1900                         sprintf(name, "%s Playback Switch", chname[i]);
1901                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1902                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1903                                                                   HDA_OUTPUT));
1904                         if (err < 0)
1905                                 return err;
1906                 }
1907         }
1908
1909         return 0;
1910 }
1911
1912 static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1913 {
1914         int err;
1915
1916         if (!pin)
1917                 return 0;
1918
1919         spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
1920
1921         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1922                               "Headphone Playback Volume",
1923                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1924         if (err < 0)
1925                 return err;
1926         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1927                               "Headphone Playback Switch",
1928                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1929         if (err < 0)
1930                 return err;
1931
1932         return 0;
1933 }
1934
1935 /* create playback/capture controls for input pins */
1936 static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
1937                                                 const struct auto_pin_cfg *cfg)
1938 {
1939         static char *labels[] = {
1940                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1941         };
1942         struct hda_input_mux *imux = &spec->private_imux;
1943         int i, err, idx = 0;
1944
1945         /* for internal loopback recording select */
1946         imux->items[imux->num_items].label = "Stereo Mixer";
1947         imux->items[imux->num_items].index = idx;
1948         imux->num_items++;
1949
1950         for (i = 0; i < AUTO_PIN_LAST; i++) {
1951                 if (!cfg->input_pins[i])
1952                         continue;
1953
1954                 switch (cfg->input_pins[i]) {
1955                 case 0x1a: /* Mic */
1956                         idx = 2;
1957                         break;
1958
1959                 case 0x1b: /* Line In */
1960                         idx = 3;
1961                         break;
1962
1963                 case 0x1e: /* Front Mic */
1964                         idx = 4;
1965                         break;
1966
1967                 case 0x1f: /* CD */
1968                         idx = 1;
1969                         break;
1970                 }
1971                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1972                                            idx, 0x16);
1973                 if (err < 0)
1974                         return err;
1975                 imux->items[imux->num_items].label = labels[i];
1976                 imux->items[imux->num_items].index = idx;
1977                 imux->num_items++;
1978         }
1979         return 0;
1980 }
1981
1982 static int vt1708B_parse_auto_config(struct hda_codec *codec)
1983 {
1984         struct via_spec *spec = codec->spec;
1985         int err;
1986
1987         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1988         if (err < 0)
1989                 return err;
1990         err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
1991         if (err < 0)
1992                 return err;
1993         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1994                 return 0; /* can't find valid BIOS pin config */
1995
1996         err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
1997         if (err < 0)
1998                 return err;
1999         err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
2000         if (err < 0)
2001                 return err;
2002         err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
2003         if (err < 0)
2004                 return err;
2005
2006         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2007
2008         if (spec->autocfg.dig_out_pin)
2009                 spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
2010         if (spec->autocfg.dig_in_pin)
2011                 spec->dig_in_nid = VT1708B_DIGIN_NID;
2012
2013         if (spec->kctl_alloc)
2014                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2015
2016         spec->input_mux = &spec->private_imux;
2017
2018         return 1;
2019 }
2020
2021 #ifdef CONFIG_SND_HDA_POWER_SAVE
2022 static struct hda_amp_list vt1708B_loopbacks[] = {
2023         { 0x16, HDA_INPUT, 1 },
2024         { 0x16, HDA_INPUT, 2 },
2025         { 0x16, HDA_INPUT, 3 },
2026         { 0x16, HDA_INPUT, 4 },
2027         { } /* end */
2028 };
2029 #endif
2030
2031 static int patch_vt1708B_8ch(struct hda_codec *codec)
2032 {
2033         struct via_spec *spec;
2034         int err;
2035
2036         /* create a codec specific record */
2037         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2038         if (spec == NULL)
2039                 return -ENOMEM;
2040
2041         codec->spec = spec;
2042
2043         /* automatic parse from the BIOS config */
2044         err = vt1708B_parse_auto_config(codec);
2045         if (err < 0) {
2046                 via_free(codec);
2047                 return err;
2048         } else if (!err) {
2049                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
2050                        "from BIOS.  Using genenic mode...\n");
2051         }
2052
2053         spec->init_verbs[spec->num_iverbs++] = vt1708B_8ch_volume_init_verbs;
2054         spec->init_verbs[spec->num_iverbs++] = vt1708B_uniwill_init_verbs;
2055
2056         spec->stream_name_analog = "VT1708B Analog";
2057         spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
2058         spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
2059
2060         spec->stream_name_digital = "VT1708B Digital";
2061         spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
2062         spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
2063
2064         if (!spec->adc_nids && spec->input_mux) {
2065                 spec->adc_nids = vt1708B_adc_nids;
2066                 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
2067                 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
2068                 spec->num_mixers++;
2069         }
2070
2071         codec->patch_ops = via_patch_ops;
2072
2073         codec->patch_ops.init = via_auto_init;
2074         codec->patch_ops.unsol_event = via_unsol_event;
2075 #ifdef CONFIG_SND_HDA_POWER_SAVE
2076         spec->loopback.amplist = vt1708B_loopbacks;
2077 #endif
2078
2079         return 0;
2080 }
2081
2082 static int patch_vt1708B_4ch(struct hda_codec *codec)
2083 {
2084         struct via_spec *spec;
2085         int err;
2086
2087         /* create a codec specific record */
2088         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2089         if (spec == NULL)
2090                 return -ENOMEM;
2091
2092         codec->spec = spec;
2093
2094         /* automatic parse from the BIOS config */
2095         err = vt1708B_parse_auto_config(codec);
2096         if (err < 0) {
2097                 via_free(codec);
2098                 return err;
2099         } else if (!err) {
2100                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
2101                        "from BIOS.  Using genenic mode...\n");
2102         }
2103
2104         spec->init_verbs[spec->num_iverbs++] = vt1708B_4ch_volume_init_verbs;
2105         spec->init_verbs[spec->num_iverbs++] = vt1708B_uniwill_init_verbs;
2106
2107         spec->stream_name_analog = "VT1708B Analog";
2108         spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
2109         spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
2110
2111         spec->stream_name_digital = "VT1708B Digital";
2112         spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
2113         spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
2114
2115         if (!spec->adc_nids && spec->input_mux) {
2116                 spec->adc_nids = vt1708B_adc_nids;
2117                 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
2118                 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
2119                 spec->num_mixers++;
2120         }
2121
2122         codec->patch_ops = via_patch_ops;
2123
2124         codec->patch_ops.init = via_auto_init;
2125         codec->patch_ops.unsol_event = via_unsol_event;
2126 #ifdef CONFIG_SND_HDA_POWER_SAVE
2127         spec->loopback.amplist = vt1708B_loopbacks;
2128 #endif
2129
2130         return 0;
2131 }
2132
2133 /* Patch for VT1708S */
2134
2135 /* capture mixer elements */
2136 static struct snd_kcontrol_new vt1708S_capture_mixer[] = {
2137         HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
2138         HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
2139         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
2140         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
2141         HDA_CODEC_VOLUME("Mic Boost", 0x1A, 0x0, HDA_INPUT),
2142         HDA_CODEC_VOLUME("Front Mic Boost", 0x1E, 0x0, HDA_INPUT),
2143         {
2144                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2145                 /* The multiple "Capture Source" controls confuse alsamixer
2146                  * So call somewhat different..
2147                  */
2148                 /* .name = "Capture Source", */
2149                 .name = "Input Source",
2150                 .count = 1,
2151                 .info = via_mux_enum_info,
2152                 .get = via_mux_enum_get,
2153                 .put = via_mux_enum_put,
2154         },
2155         { } /* end */
2156 };
2157
2158 static struct hda_verb vt1708S_volume_init_verbs[] = {
2159         /* Unmute ADC0-1 and set the default input to mic-in */
2160         {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2161         {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2162
2163         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the
2164          * analog-loopback mixer widget */
2165         /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
2166         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2167         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2168         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2169         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
2170         {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
2171
2172         /* Setup default input of PW4 to MW0 */
2173         {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
2174         /* PW9 Output enable */
2175         {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2176         { }
2177 };
2178
2179 static struct hda_verb vt1708S_uniwill_init_verbs[] = {
2180         {0x1D, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
2181         { }
2182 };
2183
2184 static struct hda_pcm_stream vt1708S_pcm_analog_playback = {
2185         .substreams = 2,
2186         .channels_min = 2,
2187         .channels_max = 8,
2188         .nid = 0x10, /* NID to query formats and rates */
2189         .ops = {
2190                 .open = via_playback_pcm_open,
2191                 .prepare = via_playback_pcm_prepare,
2192                 .cleanup = via_playback_pcm_cleanup
2193         },
2194 };
2195
2196 static struct hda_pcm_stream vt1708S_pcm_analog_capture = {
2197         .substreams = 2,
2198         .channels_min = 2,
2199         .channels_max = 2,
2200         .nid = 0x13, /* NID to query formats and rates */
2201         .ops = {
2202                 .prepare = via_capture_pcm_prepare,
2203                 .cleanup = via_capture_pcm_cleanup
2204         },
2205 };
2206
2207 static struct hda_pcm_stream vt1708S_pcm_digital_playback = {
2208         .substreams = 1,
2209         .channels_min = 2,
2210         .channels_max = 2,
2211         /* NID is set in via_build_pcms */
2212         .ops = {
2213                 .open = via_dig_playback_pcm_open,
2214                 .close = via_dig_playback_pcm_close,
2215                 .prepare = via_dig_playback_pcm_prepare
2216         },
2217 };
2218
2219 /* fill in the dac_nids table from the parsed pin configuration */
2220 static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
2221                                      const struct auto_pin_cfg *cfg)
2222 {
2223         int i;
2224         hda_nid_t nid;
2225
2226         spec->multiout.num_dacs = cfg->line_outs;
2227
2228         spec->multiout.dac_nids = spec->private_dac_nids;
2229
2230         for (i = 0; i < 4; i++) {
2231                 nid = cfg->line_out_pins[i];
2232                 if (nid) {
2233                         /* config dac list */
2234                         switch (i) {
2235                         case AUTO_SEQ_FRONT:
2236                                 spec->multiout.dac_nids[i] = 0x10;
2237                                 break;
2238                         case AUTO_SEQ_CENLFE:
2239                                 spec->multiout.dac_nids[i] = 0x24;
2240                                 break;
2241                         case AUTO_SEQ_SURROUND:
2242                                 spec->multiout.dac_nids[i] = 0x11;
2243                                 break;
2244                         case AUTO_SEQ_SIDE:
2245                                 spec->multiout.dac_nids[i] = 0x25;
2246                                 break;
2247                         }
2248                 }
2249         }
2250
2251         return 0;
2252 }
2253
2254 /* add playback controls from the parsed DAC table */
2255 static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec,
2256                                              const struct auto_pin_cfg *cfg)
2257 {
2258         char name[32];
2259         static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
2260         hda_nid_t nid_vols[] = {0x10, 0x11, 0x24, 0x25};
2261         hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x26, 0x27};
2262         hda_nid_t nid, nid_vol, nid_mute;
2263         int i, err;
2264
2265         for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
2266                 nid = cfg->line_out_pins[i];
2267
2268                 if (!nid)
2269                         continue;
2270
2271                 nid_vol = nid_vols[i];
2272                 nid_mute = nid_mutes[i];
2273
2274                 if (i == AUTO_SEQ_CENLFE) {
2275                         /* Center/LFE */
2276                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2277                                               "Center Playback Volume",
2278                                               HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
2279                                                                   HDA_OUTPUT));
2280                         if (err < 0)
2281                                 return err;
2282                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2283                                               "LFE Playback Volume",
2284                                               HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
2285                                                                   HDA_OUTPUT));
2286                         if (err < 0)
2287                                 return err;
2288                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2289                                               "Center Playback Switch",
2290                                               HDA_COMPOSE_AMP_VAL(nid_mute,
2291                                                                   1, 0,
2292                                                                   HDA_OUTPUT));
2293                         if (err < 0)
2294                                 return err;
2295                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2296                                               "LFE Playback Switch",
2297                                               HDA_COMPOSE_AMP_VAL(nid_mute,
2298                                                                   2, 0,
2299                                                                   HDA_OUTPUT));
2300                         if (err < 0)
2301                                 return err;
2302                 } else if (i == AUTO_SEQ_FRONT) {
2303                         /* add control to mixer index 0 */
2304                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2305                                               "Master Front Playback Volume",
2306                                               HDA_COMPOSE_AMP_VAL(0x16, 3, 0,
2307                                                                   HDA_INPUT));
2308                         if (err < 0)
2309                                 return err;
2310                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2311                                               "Master Front Playback Switch",
2312                                               HDA_COMPOSE_AMP_VAL(0x16, 3, 0,
2313                                                                   HDA_INPUT));
2314                         if (err < 0)
2315                                 return err;
2316
2317                         /* Front */
2318                         sprintf(name, "%s Playback Volume", chname[i]);
2319                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
2320                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
2321                                                                   HDA_OUTPUT));
2322                         if (err < 0)
2323                                 return err;
2324                         sprintf(name, "%s Playback Switch", chname[i]);
2325                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
2326                                               HDA_COMPOSE_AMP_VAL(nid_mute,
2327                                                                   3, 0,
2328                                                                   HDA_OUTPUT));
2329                         if (err < 0)
2330                                 return err;
2331                 } else {
2332                         sprintf(name, "%s Playback Volume", chname[i]);
2333                         err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
2334                                               HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
2335                                                                   HDA_OUTPUT));
2336                         if (err < 0)
2337                                 return err;
2338                         sprintf(name, "%s Playback Switch", chname[i]);
2339                         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
2340                                               HDA_COMPOSE_AMP_VAL(nid_mute,
2341                                                                   3, 0,
2342                                                                   HDA_OUTPUT));
2343                         if (err < 0)
2344                                 return err;
2345                 }
2346         }
2347
2348         return 0;
2349 }
2350
2351 static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
2352 {
2353         int err;
2354
2355         if (!pin)
2356                 return 0;
2357
2358         spec->multiout.hp_nid = VT1708S_HP_NID; /* AOW3 */
2359
2360         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2361                               "Headphone Playback Volume",
2362                               HDA_COMPOSE_AMP_VAL(0x25, 3, 0, HDA_OUTPUT));
2363         if (err < 0)
2364                 return err;
2365
2366         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2367                               "Headphone Playback Switch",
2368                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
2369         if (err < 0)
2370                 return err;
2371
2372         return 0;
2373 }
2374
2375 /* create playback/capture controls for input pins */
2376 static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec,
2377                                                 const struct auto_pin_cfg *cfg)
2378 {
2379         static char *labels[] = {
2380                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
2381         };
2382         struct hda_input_mux *imux = &spec->private_imux;
2383         int i, err, idx = 0;
2384
2385         /* for internal loopback recording select */
2386         imux->items[imux->num_items].label = "Stereo Mixer";
2387         imux->items[imux->num_items].index = 5;
2388         imux->num_items++;
2389
2390         for (i = 0; i < AUTO_PIN_LAST; i++) {
2391                 if (!cfg->input_pins[i])
2392                         continue;
2393
2394                 switch (cfg->input_pins[i]) {
2395                 case 0x1a: /* Mic */
2396                         idx = 2;
2397                         break;
2398
2399                 case 0x1b: /* Line In */
2400                         idx = 3;
2401                         break;
2402
2403                 case 0x1e: /* Front Mic */
2404                         idx = 4;
2405                         break;
2406
2407                 case 0x1f: /* CD */
2408                         idx = 1;
2409                         break;
2410                 }
2411                 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
2412                                            idx, 0x16);
2413                 if (err < 0)
2414                         return err;
2415                 imux->items[imux->num_items].label = labels[i];
2416                 imux->items[imux->num_items].index = idx-1;
2417                 imux->num_items++;
2418         }
2419         return 0;
2420 }
2421
2422 static int vt1708S_parse_auto_config(struct hda_codec *codec)
2423 {
2424         struct via_spec *spec = codec->spec;
2425         int err;
2426         static hda_nid_t vt1708s_ignore[] = {0x21, 0};
2427
2428         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
2429                                            vt1708s_ignore);
2430         if (err < 0)
2431                 return err;
2432         err = vt1708S_auto_fill_dac_nids(spec, &spec->autocfg);
2433         if (err < 0)
2434                 return err;
2435         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
2436                 return 0; /* can't find valid BIOS pin config */
2437
2438         err = vt1708S_auto_create_multi_out_ctls(spec, &spec->autocfg);
2439         if (err < 0)
2440                 return err;
2441         err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
2442         if (err < 0)
2443                 return err;
2444         err = vt1708S_auto_create_analog_input_ctls(spec, &spec->autocfg);
2445         if (err < 0)
2446                 return err;
2447
2448         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2449
2450         if (spec->autocfg.dig_out_pin)
2451                 spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID;
2452
2453         if (spec->kctl_alloc)
2454                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2455
2456         spec->input_mux = &spec->private_imux;
2457
2458         return 1;
2459 }
2460
2461 #ifdef CONFIG_SND_HDA_POWER_SAVE
2462 static struct hda_amp_list vt1708S_loopbacks[] = {
2463         { 0x16, HDA_INPUT, 1 },
2464         { 0x16, HDA_INPUT, 2 },
2465         { 0x16, HDA_INPUT, 3 },
2466         { 0x16, HDA_INPUT, 4 },
2467         { } /* end */
2468 };
2469 #endif
2470
2471 static int patch_vt1708S(struct hda_codec *codec)
2472 {
2473         struct via_spec *spec;
2474         int err;
2475
2476         /* create a codec specific record */
2477         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2478         if (spec == NULL)
2479                 return -ENOMEM;
2480
2481         codec->spec = spec;
2482
2483         /* automatic parse from the BIOS config */
2484         err = vt1708S_parse_auto_config(codec);
2485         if (err < 0) {
2486                 via_free(codec);
2487                 return err;
2488         } else if (!err) {
2489                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
2490                        "from BIOS.  Using genenic mode...\n");
2491         }
2492
2493         spec->init_verbs[spec->num_iverbs++] = vt1708S_volume_init_verbs;
2494         spec->init_verbs[spec->num_iverbs++] = vt1708S_uniwill_init_verbs;
2495
2496         spec->stream_name_analog = "VT1708S Analog";
2497         spec->stream_analog_playback = &vt1708S_pcm_analog_playback;
2498         spec->stream_analog_capture = &vt1708S_pcm_analog_capture;
2499
2500         spec->stream_name_digital = "VT1708S Digital";
2501         spec->stream_digital_playback = &vt1708S_pcm_digital_playback;
2502
2503         if (!spec->adc_nids && spec->input_mux) {
2504                 spec->adc_nids = vt1708S_adc_nids;
2505                 spec->num_adc_nids = ARRAY_SIZE(vt1708S_adc_nids);
2506                 spec->mixers[spec->num_mixers] = vt1708S_capture_mixer;
2507                 spec->num_mixers++;
2508         }
2509
2510         codec->patch_ops = via_patch_ops;
2511
2512         codec->patch_ops.init = via_auto_init;
2513         codec->patch_ops.unsol_event = via_unsol_event;
2514 #ifdef CONFIG_SND_HDA_POWER_SAVE
2515         spec->loopback.amplist = vt1708S_loopbacks;
2516 #endif
2517
2518         return 0;
2519 }
2520
2521 /* Patch for VT1702 */
2522
2523 /* capture mixer elements */
2524 static struct snd_kcontrol_new vt1702_capture_mixer[] = {
2525         HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_INPUT),
2526         HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_INPUT),
2527         HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x20, 0x0, HDA_INPUT),
2528         HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x20, 0x0, HDA_INPUT),
2529         HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x1F, 0x0, HDA_INPUT),
2530         HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x1F, 0x0, HDA_INPUT),
2531         HDA_CODEC_VOLUME("Digital Mic Boost Capture Volume", 0x1E, 0x0,
2532                          HDA_INPUT),
2533         {
2534                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2535                 /* The multiple "Capture Source" controls confuse alsamixer
2536                  * So call somewhat different..
2537                  */
2538                 /* .name = "Capture Source", */
2539                 .name = "Input Source",
2540                 .count = 1,
2541                 .info = via_mux_enum_info,
2542                 .get = via_mux_enum_get,
2543                 .put = via_mux_enum_put,
2544         },
2545         { } /* end */
2546 };
2547
2548 static struct hda_verb vt1702_volume_init_verbs[] = {
2549         /*
2550          * Unmute ADC0-1 and set the default input to mic-in
2551          */
2552         {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2553         {0x1F, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2554         {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2555
2556
2557         /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
2558          * mixer widget
2559          */
2560         /* Amp Indices: Mic1 = 1, Line = 1, Mic2 = 3 */
2561         {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2562         {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2563         {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2564         {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
2565         {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2566
2567         /* Setup default input of PW4 to MW0 */
2568         {0x17, AC_VERB_SET_CONNECT_SEL, 0x1},
2569         /* PW6 PW7 Output enable */
2570         {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2571         {0x1C, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2572         { }
2573 };
2574
2575 static struct hda_verb vt1702_uniwill_init_verbs[] = {
2576         {0x01, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_GPIO_EVENT},
2577         {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
2578         { }
2579 };
2580
2581 static struct hda_pcm_stream vt1702_pcm_analog_playback = {
2582         .substreams = 1,
2583         .channels_min = 2,
2584         .channels_max = 2,
2585         .nid = 0x10, /* NID to query formats and rates */
2586         .ops = {
2587                 .open = via_playback_pcm_open,
2588                 .prepare = via_playback_pcm_prepare,
2589                 .cleanup = via_playback_pcm_cleanup
2590         },
2591 };
2592
2593 static struct hda_pcm_stream vt1702_pcm_analog_capture = {
2594         .substreams = 3,
2595         .channels_min = 2,
2596         .channels_max = 2,
2597         .nid = 0x12, /* NID to query formats and rates */
2598         .ops = {
2599                 .prepare = via_capture_pcm_prepare,
2600                 .cleanup = via_capture_pcm_cleanup
2601         },
2602 };
2603
2604 static struct hda_pcm_stream vt1702_pcm_digital_playback = {
2605         .substreams = 1,
2606         .channels_min = 2,
2607         .channels_max = 2,
2608         /* NID is set in via_build_pcms */
2609         .ops = {
2610                 .open = via_dig_playback_pcm_open,
2611                 .close = via_dig_playback_pcm_close,
2612                 .prepare = via_dig_playback_pcm_prepare
2613         },
2614 };
2615
2616 /* fill in the dac_nids table from the parsed pin configuration */
2617 static int vt1702_auto_fill_dac_nids(struct via_spec *spec,
2618                                      const struct auto_pin_cfg *cfg)
2619 {
2620         spec->multiout.num_dacs = 1;
2621         spec->multiout.dac_nids = spec->private_dac_nids;
2622
2623         if (cfg->line_out_pins[0]) {
2624                 /* config dac list */
2625                 spec->multiout.dac_nids[0] = 0x10;
2626         }
2627
2628         return 0;
2629 }
2630
2631 /* add playback controls from the parsed DAC table */
2632 static int vt1702_auto_create_line_out_ctls(struct via_spec *spec,
2633                                              const struct auto_pin_cfg *cfg)
2634 {
2635         int err;
2636
2637         if (!cfg->line_out_pins[0])
2638                 return -1;
2639
2640         /* add control to mixer index 0 */
2641         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2642                               "Master Front Playback Volume",
2643                               HDA_COMPOSE_AMP_VAL(0x1A, 3, 0, HDA_INPUT));
2644         if (err < 0)
2645                 return err;
2646         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2647                               "Master Front Playback Switch",
2648                               HDA_COMPOSE_AMP_VAL(0x1A, 3, 0, HDA_INPUT));
2649         if (err < 0)
2650                 return err;
2651
2652         /* Front */
2653         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2654                               "Front Playback Volume",
2655                               HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT));
2656         if (err < 0)
2657                 return err;
2658         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2659                               "Front Playback Switch",
2660                               HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT));
2661         if (err < 0)
2662                 return err;
2663
2664         return 0;
2665 }
2666
2667 static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
2668 {
2669         int err;
2670
2671         if (!pin)
2672                 return 0;
2673
2674         spec->multiout.hp_nid = 0x1D;
2675
2676         err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2677                               "Headphone Playback Volume",
2678                               HDA_COMPOSE_AMP_VAL(0x1D, 3, 0, HDA_OUTPUT));
2679         if (err < 0)
2680                 return err;
2681
2682         err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2683                               "Headphone Playback Switch",
2684                               HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
2685         if (err < 0)
2686                 return err;
2687
2688         return 0;
2689 }
2690
2691 /* create playback/capture controls for input pins */
2692 static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec,
2693                                                 const struct auto_pin_cfg *cfg)
2694 {
2695         static char *labels[] = {
2696                 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
2697         };
2698         struct hda_input_mux *imux = &spec->private_imux;
2699         int i, err, idx = 0;
2700
2701         /* for internal loopback recording select */
2702         imux->items[imux->num_items].label = "Stereo Mixer";
2703         imux->items[imux->num_items].index = 3;
2704         imux->num_items++;
2705
2706         for (i = 0; i < AUTO_PIN_LAST; i++) {
2707                 if (!cfg->input_pins[i])
2708                         continue;
2709
2710                 switch (cfg->input_pins[i]) {
2711                 case 0x14: /* Mic */
2712                         idx = 1;
2713                         break;
2714
2715                 case 0x15: /* Line In */
2716                         idx = 2;
2717                         break;
2718
2719                 case 0x18: /* Front Mic */
2720                         idx = 3;
2721                         break;
2722                 }
2723                 err = via_new_analog_input(spec, cfg->input_pins[i],
2724                                            labels[i], idx, 0x1A);
2725                 if (err < 0)
2726                         return err;
2727                 imux->items[imux->num_items].label = labels[i];
2728                 imux->items[imux->num_items].index = idx-1;
2729                 imux->num_items++;
2730         }
2731         return 0;
2732 }
2733
2734 static int vt1702_parse_auto_config(struct hda_codec *codec)
2735 {
2736         struct via_spec *spec = codec->spec;
2737         int err;
2738         static hda_nid_t vt1702_ignore[] = {0x1C, 0};
2739
2740         err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
2741                                            vt1702_ignore);
2742         if (err < 0)
2743                 return err;
2744         err = vt1702_auto_fill_dac_nids(spec, &spec->autocfg);
2745         if (err < 0)
2746                 return err;
2747         if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
2748                 return 0; /* can't find valid BIOS pin config */
2749
2750         err = vt1702_auto_create_line_out_ctls(spec, &spec->autocfg);
2751         if (err < 0)
2752                 return err;
2753         err = vt1702_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
2754         if (err < 0)
2755                 return err;
2756         err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg);
2757         if (err < 0)
2758                 return err;
2759
2760         spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2761
2762         if (spec->autocfg.dig_out_pin)
2763                 spec->multiout.dig_out_nid = VT1702_DIGOUT_NID;
2764
2765         if (spec->kctl_alloc)
2766                 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2767
2768         spec->input_mux = &spec->private_imux;
2769
2770         return 1;
2771 }
2772
2773 #ifdef CONFIG_SND_HDA_POWER_SAVE
2774 static struct hda_amp_list vt1702_loopbacks[] = {
2775         { 0x1A, HDA_INPUT, 1 },
2776         { 0x1A, HDA_INPUT, 2 },
2777         { 0x1A, HDA_INPUT, 3 },
2778         { 0x1A, HDA_INPUT, 4 },
2779         { } /* end */
2780 };
2781 #endif
2782
2783 static int patch_vt1702(struct hda_codec *codec)
2784 {
2785         struct via_spec *spec;
2786         int err;
2787         unsigned int response;
2788         unsigned char control;
2789
2790         /* create a codec specific record */
2791         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2792         if (spec == NULL)
2793                 return -ENOMEM;
2794
2795         codec->spec = spec;
2796
2797         /* automatic parse from the BIOS config */
2798         err = vt1702_parse_auto_config(codec);
2799         if (err < 0) {
2800                 via_free(codec);
2801                 return err;
2802         } else if (!err) {
2803                 printk(KERN_INFO "hda_codec: Cannot set up configuration "
2804                        "from BIOS.  Using genenic mode...\n");
2805         }
2806
2807         spec->init_verbs[spec->num_iverbs++] = vt1702_volume_init_verbs;
2808         spec->init_verbs[spec->num_iverbs++] = vt1702_uniwill_init_verbs;
2809
2810         spec->stream_name_analog = "VT1702 Analog";
2811         spec->stream_analog_playback = &vt1702_pcm_analog_playback;
2812         spec->stream_analog_capture = &vt1702_pcm_analog_capture;
2813
2814         spec->stream_name_digital = "VT1702 Digital";
2815         spec->stream_digital_playback = &vt1702_pcm_digital_playback;
2816
2817         if (!spec->adc_nids && spec->input_mux) {
2818                 spec->adc_nids = vt1702_adc_nids;
2819                 spec->num_adc_nids = ARRAY_SIZE(vt1702_adc_nids);
2820                 spec->mixers[spec->num_mixers] = vt1702_capture_mixer;
2821                 spec->num_mixers++;
2822         }
2823
2824         codec->patch_ops = via_patch_ops;
2825
2826         codec->patch_ops.init = via_auto_init;
2827         codec->patch_ops.unsol_event = via_unsol_event;
2828 #ifdef CONFIG_SND_HDA_POWER_SAVE
2829         spec->loopback.amplist = vt1702_loopbacks;
2830 #endif
2831
2832         /* Open backdoor */
2833         response = snd_hda_codec_read(codec, codec->afg, 0, 0xF8C, 0);
2834         control = (unsigned char)(response & 0xff);
2835         control |= 0x3;
2836         snd_hda_codec_write(codec,  codec->afg, 0, 0xF88, control);
2837
2838         /* Enable GPIO 0&1 for volume&mute control */
2839         /* Enable GPIO 2 for DMIC-DATA */
2840         response = snd_hda_codec_read(codec, codec->afg, 0, 0xF84, 0);
2841         control = (unsigned char)((response >> 16) & 0x3f);
2842         snd_hda_codec_write(codec,  codec->afg, 0, 0xF82, control);
2843
2844         return 0;
2845 }
2846
2847 /*
2848  * patch entries
2849  */
2850 struct hda_codec_preset snd_hda_preset_via[] = {
2851         { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
2852         { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
2853         { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
2854         { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
2855         { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
2856           .patch = patch_vt1709_10ch},
2857         { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
2858           .patch = patch_vt1709_10ch},
2859         { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
2860           .patch = patch_vt1709_10ch},
2861         { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
2862           .patch = patch_vt1709_10ch},
2863         { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
2864           .patch = patch_vt1709_6ch},
2865         { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
2866           .patch = patch_vt1709_6ch},
2867         { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
2868           .patch = patch_vt1709_6ch},
2869         { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
2870           .patch = patch_vt1709_6ch},
2871         { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
2872           .patch = patch_vt1708B_8ch},
2873         { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
2874           .patch = patch_vt1708B_8ch},
2875         { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
2876           .patch = patch_vt1708B_8ch},
2877         { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
2878           .patch = patch_vt1708B_8ch},
2879         { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
2880           .patch = patch_vt1708B_4ch},
2881         { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
2882           .patch = patch_vt1708B_4ch},
2883         { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
2884           .patch = patch_vt1708B_4ch},
2885         { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
2886           .patch = patch_vt1708B_4ch},
2887         { .id = 0x11060397, .name = "VIA VT1708S",
2888           .patch = patch_vt1708S},
2889         { .id = 0x11061397, .name = "VIA VT1708S",
2890           .patch = patch_vt1708S},
2891         { .id = 0x11062397, .name = "VIA VT1708S",
2892           .patch = patch_vt1708S},
2893         { .id = 0x11063397, .name = "VIA VT1708S",
2894           .patch = patch_vt1708S},
2895         { .id = 0x11064397, .name = "VIA VT1708S",
2896           .patch = patch_vt1708S},
2897         { .id = 0x11065397, .name = "VIA VT1708S",
2898           .patch = patch_vt1708S},
2899         { .id = 0x11066397, .name = "VIA VT1708S",
2900           .patch = patch_vt1708S},
2901         { .id = 0x11067397, .name = "VIA VT1708S",
2902           .patch = patch_vt1708S},
2903         { .id = 0x11060398, .name = "VIA VT1702",
2904           .patch = patch_vt1702},
2905         { .id = 0x11061398, .name = "VIA VT1702",
2906           .patch = patch_vt1702},
2907         { .id = 0x11062398, .name = "VIA VT1702",
2908           .patch = patch_vt1702},
2909         { .id = 0x11063398, .name = "VIA VT1702",
2910           .patch = patch_vt1702},
2911         { .id = 0x11064398, .name = "VIA VT1702",
2912           .patch = patch_vt1702},
2913         { .id = 0x11065398, .name = "VIA VT1702",
2914           .patch = patch_vt1702},
2915         { .id = 0x11066398, .name = "VIA VT1702",
2916           .patch = patch_vt1702},
2917         { .id = 0x11067398, .name = "VIA VT1702",
2918           .patch = patch_vt1702},
2919         {} /* terminator */
2920 };