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