~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/sound/pci/hda/patch_via.c

Version: ~ [ 2.4.21-47.EL ] ~ [ 2.6.9-67.EL ] ~ [ 2.6.18-128.el5 ] ~ [ 2.6.18-164.el5 ] ~
Architecture: ~ [ i386 ] ~ [ x86_64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.