RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / sound / pci / hda / patch_via.c
blobba32d1e52cb84d52b4f3a0b9087ab2ae2588a55d
1 /*
2 * Universal Interface for Intel High Definition Audio Codec
4 * HD audio interface patch for VIA VT1708 codec
6 * Copyright (c) 2006 Lydia Wang <lydiawang@viatech.com>
7 * Takashi Iwai <tiwai@suse.de>
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.
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.
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
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 /* */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
34 #include <sound/driver.h>
35 #include <linux/init.h>
36 #include <linux/delay.h>
37 #include <linux/slab.h>
38 #include <sound/core.h>
39 #include "hda_codec.h"
40 #include "hda_local.h"
43 /* amp values */
44 #define AMP_VAL_IDX_SHIFT 19
45 #define AMP_VAL_IDX_MASK (0x0f<<19)
47 #define NUM_CONTROL_ALLOC 32
48 #define NUM_VERB_ALLOC 32
50 /* Pin Widget NID */
51 #define VT1708_HP_NID 0x13
52 #define VT1708_DIGOUT_NID 0x14
53 #define VT1708_DIGIN_NID 0x16
55 #define VT1709_HP_DAC_NID 0x28
56 #define VT1709_DIGOUT_NID 0x13
57 #define VT1709_DIGIN_NID 0x17
59 #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
60 #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
61 #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
64 enum {
65 VIA_CTL_WIDGET_VOL,
66 VIA_CTL_WIDGET_MUTE,
69 enum {
70 AUTO_SEQ_FRONT,
71 AUTO_SEQ_SURROUND,
72 AUTO_SEQ_CENLFE,
73 AUTO_SEQ_SIDE
76 static struct snd_kcontrol_new vt1708_control_templates[] = {
77 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
78 HDA_CODEC_MUTE(NULL, 0, 0, 0),
82 struct via_spec {
83 /* codec parameterization */
84 struct snd_kcontrol_new *mixers[3];
85 unsigned int num_mixers;
87 struct hda_verb *init_verbs;
89 char *stream_name_analog;
90 struct hda_pcm_stream *stream_analog_playback;
91 struct hda_pcm_stream *stream_analog_capture;
93 char *stream_name_digital;
94 struct hda_pcm_stream *stream_digital_playback;
95 struct hda_pcm_stream *stream_digital_capture;
97 /* playback */
98 struct hda_multi_out multiout;
100 /* capture */
101 unsigned int num_adc_nids;
102 hda_nid_t *adc_nids;
103 hda_nid_t dig_in_nid;
105 /* capture source */
106 const struct hda_input_mux *input_mux;
107 unsigned int cur_mux[3];
109 /* PCM information */
110 struct hda_pcm pcm_rec[2];
112 /* dynamic controls, init_verbs and input_mux */
113 struct auto_pin_cfg autocfg;
114 unsigned int num_kctl_alloc, num_kctl_used;
115 struct snd_kcontrol_new *kctl_alloc;
116 struct hda_input_mux private_imux;
117 hda_nid_t private_dac_nids[4];
120 static hda_nid_t vt1708_adc_nids[2] = {
121 /* ADC1-2 */
122 0x15, 0x27
125 static hda_nid_t vt1709_adc_nids[3] = {
126 /* ADC1-2 */
127 0x14, 0x15, 0x16
130 /* add dynamic controls */
131 static int via_add_control(struct via_spec *spec, int type, const char *name,
132 unsigned long val)
134 struct snd_kcontrol_new *knew;
136 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
137 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
139 /* array + terminator */
140 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
141 if (!knew)
142 return -ENOMEM;
143 if (spec->kctl_alloc) {
144 memcpy(knew, spec->kctl_alloc,
145 sizeof(*knew) * spec->num_kctl_alloc);
146 kfree(spec->kctl_alloc);
148 spec->kctl_alloc = knew;
149 spec->num_kctl_alloc = num;
152 knew = &spec->kctl_alloc[spec->num_kctl_used];
153 *knew = vt1708_control_templates[type];
154 knew->name = kstrdup(name, GFP_KERNEL);
156 if (!knew->name)
157 return -ENOMEM;
158 knew->private_value = val;
159 spec->num_kctl_used++;
160 return 0;
163 /* create input playback/capture controls for the given pin */
164 static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
165 const char *ctlname, int idx, int mix_nid)
167 char name[32];
168 int err;
170 sprintf(name, "%s Playback Volume", ctlname);
171 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
172 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
173 if (err < 0)
174 return err;
175 sprintf(name, "%s Playback Switch", ctlname);
176 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
177 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
178 if (err < 0)
179 return err;
180 return 0;
183 static void via_auto_set_output_and_unmute(struct hda_codec *codec,
184 hda_nid_t nid, int pin_type,
185 int dac_idx)
187 /* set as output */
188 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
189 pin_type);
190 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
191 AMP_OUT_UNMUTE);
195 static void via_auto_init_multi_out(struct hda_codec *codec)
197 struct via_spec *spec = codec->spec;
198 int i;
200 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
201 hda_nid_t nid = spec->autocfg.line_out_pins[i];
202 if (nid)
203 via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
207 static void via_auto_init_hp_out(struct hda_codec *codec)
209 struct via_spec *spec = codec->spec;
210 hda_nid_t pin;
212 pin = spec->autocfg.hp_pins[0];
213 if (pin) /* connect to front */
214 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
217 static void via_auto_init_analog_input(struct hda_codec *codec)
219 struct via_spec *spec = codec->spec;
220 int i;
222 for (i = 0; i < AUTO_PIN_LAST; i++) {
223 hda_nid_t nid = spec->autocfg.input_pins[i];
225 snd_hda_codec_write(codec, nid, 0,
226 AC_VERB_SET_PIN_WIDGET_CONTROL,
227 (i <= AUTO_PIN_FRONT_MIC ?
228 PIN_VREF50 : PIN_IN));
233 * input MUX handling
235 static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
236 struct snd_ctl_elem_info *uinfo)
238 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
239 struct via_spec *spec = codec->spec;
240 return snd_hda_input_mux_info(spec->input_mux, uinfo);
243 static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
244 struct snd_ctl_elem_value *ucontrol)
246 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
247 struct via_spec *spec = codec->spec;
248 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
250 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
251 return 0;
254 static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
255 struct snd_ctl_elem_value *ucontrol)
257 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
258 struct via_spec *spec = codec->spec;
259 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
260 unsigned int vendor_id = codec->vendor_id;
262 /* AIW0 lydia 060801 add for correct sw0 input select */
263 if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
264 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
265 0x18, &spec->cur_mux[adc_idx]);
266 else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
267 IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0) )
268 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
269 0x19, &spec->cur_mux[adc_idx]);
270 else
271 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
272 spec->adc_nids[adc_idx],
273 &spec->cur_mux[adc_idx]);
276 /* capture mixer elements */
277 static struct snd_kcontrol_new vt1708_capture_mixer[] = {
278 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
279 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
280 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
281 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
283 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
284 /* The multiple "Capture Source" controls confuse alsamixer
285 * So call somewhat different..
286 * FIXME: the controls appear in the "playback" view!
288 /* .name = "Capture Source", */
289 .name = "Input Source",
290 .count = 1,
291 .info = via_mux_enum_info,
292 .get = via_mux_enum_get,
293 .put = via_mux_enum_put,
295 { } /* end */
298 * generic initialization of ADC, input mixers and output mixers
300 static struct hda_verb vt1708_volume_init_verbs[] = {
302 * Unmute ADC0-1 and set the default input to mic-in
304 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
305 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
308 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
309 * mixer widget
311 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
312 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
313 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
314 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
315 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
316 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
319 * Set up output mixers (0x19 - 0x1b)
321 /* set vol=0 to output mixers */
322 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
323 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
324 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
326 /* Setup default input to PW4 */
327 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
328 /* Set mic as default input of sw0 */
329 {0x18, AC_VERB_SET_CONNECT_SEL, 0x2},
330 /* PW9 Output enable */
331 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
334 static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
335 struct hda_codec *codec,
336 struct snd_pcm_substream *substream)
338 struct via_spec *spec = codec->spec;
339 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
342 static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
343 struct hda_codec *codec,
344 unsigned int stream_tag,
345 unsigned int format,
346 struct snd_pcm_substream *substream)
348 struct via_spec *spec = codec->spec;
349 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
350 stream_tag, format, substream);
353 static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
354 struct hda_codec *codec,
355 struct snd_pcm_substream *substream)
357 struct via_spec *spec = codec->spec;
358 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
362 * Digital out
364 static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
365 struct hda_codec *codec,
366 struct snd_pcm_substream *substream)
368 struct via_spec *spec = codec->spec;
369 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
372 static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
373 struct hda_codec *codec,
374 struct snd_pcm_substream *substream)
376 struct via_spec *spec = codec->spec;
377 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
380 static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
381 struct hda_codec *codec,
382 unsigned int stream_tag,
383 unsigned int format,
384 struct snd_pcm_substream *substream)
386 struct via_spec *spec = codec->spec;
387 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
388 stream_tag, format, substream);
392 * Analog capture
394 static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
395 struct hda_codec *codec,
396 unsigned int stream_tag,
397 unsigned int format,
398 struct snd_pcm_substream *substream)
400 struct via_spec *spec = codec->spec;
402 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
403 stream_tag, 0, format);
404 return 0;
407 static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
408 struct hda_codec *codec,
409 struct snd_pcm_substream *substream)
411 struct via_spec *spec = codec->spec;
412 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
413 0, 0, 0);
414 return 0;
417 static struct hda_pcm_stream vt1708_pcm_analog_playback = {
418 .substreams = 1,
419 .channels_min = 2,
420 .channels_max = 8,
421 .nid = 0x10, /* NID to query formats and rates */
422 .ops = {
423 .open = via_playback_pcm_open,
424 .prepare = via_playback_pcm_prepare,
425 .cleanup = via_playback_pcm_cleanup
429 static struct hda_pcm_stream vt1708_pcm_analog_capture = {
430 .substreams = 2,
431 .channels_min = 2,
432 .channels_max = 2,
433 .nid = 0x15, /* NID to query formats and rates */
434 .ops = {
435 .prepare = via_capture_pcm_prepare,
436 .cleanup = via_capture_pcm_cleanup
440 static struct hda_pcm_stream vt1708_pcm_digital_playback = {
441 .substreams = 1,
442 .channels_min = 2,
443 .channels_max = 2,
444 /* NID is set in via_build_pcms */
445 .ops = {
446 .open = via_dig_playback_pcm_open,
447 .close = via_dig_playback_pcm_close,
448 .prepare = via_dig_playback_pcm_prepare
452 static struct hda_pcm_stream vt1708_pcm_digital_capture = {
453 .substreams = 1,
454 .channels_min = 2,
455 .channels_max = 2,
458 static int via_build_controls(struct hda_codec *codec)
460 struct via_spec *spec = codec->spec;
461 int err;
462 int i;
464 for (i = 0; i < spec->num_mixers; i++) {
465 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
466 if (err < 0)
467 return err;
470 if (spec->multiout.dig_out_nid) {
471 err = snd_hda_create_spdif_out_ctls(codec,
472 spec->multiout.dig_out_nid);
473 if (err < 0)
474 return err;
476 if (spec->dig_in_nid) {
477 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
478 if (err < 0)
479 return err;
481 return 0;
484 static int via_build_pcms(struct hda_codec *codec)
486 struct via_spec *spec = codec->spec;
487 struct hda_pcm *info = spec->pcm_rec;
489 codec->num_pcms = 1;
490 codec->pcm_info = info;
492 info->name = spec->stream_name_analog;
493 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
494 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
495 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
496 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
498 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
499 spec->multiout.max_channels;
501 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
502 codec->num_pcms++;
503 info++;
504 info->name = spec->stream_name_digital;
505 if (spec->multiout.dig_out_nid) {
506 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
507 *(spec->stream_digital_playback);
508 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
509 spec->multiout.dig_out_nid;
511 if (spec->dig_in_nid) {
512 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
513 *(spec->stream_digital_capture);
514 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
515 spec->dig_in_nid;
519 return 0;
522 static void via_free(struct hda_codec *codec)
524 struct via_spec *spec = codec->spec;
525 unsigned int i;
527 if (!spec)
528 return;
530 if (spec->kctl_alloc) {
531 for (i = 0; i < spec->num_kctl_used; i++)
532 kfree(spec->kctl_alloc[i].name);
533 kfree(spec->kctl_alloc);
536 kfree(codec->spec);
539 static int via_init(struct hda_codec *codec)
541 struct via_spec *spec = codec->spec;
542 snd_hda_sequence_write(codec, spec->init_verbs);
543 return 0;
546 #ifdef CONFIG_PM
548 * resume
550 static int via_resume(struct hda_codec *codec)
552 struct via_spec *spec = codec->spec;
553 int i;
555 via_init(codec);
556 for (i = 0; i < spec->num_mixers; i++)
557 snd_hda_resume_ctls(codec, spec->mixers[i]);
558 if (spec->multiout.dig_out_nid)
559 snd_hda_resume_spdif_out(codec);
560 if (spec->dig_in_nid)
561 snd_hda_resume_spdif_in(codec);
563 return 0;
565 #endif
569 static struct hda_codec_ops via_patch_ops = {
570 .build_controls = via_build_controls,
571 .build_pcms = via_build_pcms,
572 .init = via_init,
573 .free = via_free,
574 #ifdef CONFIG_PM
575 .resume = via_resume,
576 #endif
579 /* fill in the dac_nids table from the parsed pin configuration */
580 static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
581 const struct auto_pin_cfg *cfg)
583 int i;
584 hda_nid_t nid;
586 spec->multiout.num_dacs = cfg->line_outs;
588 spec->multiout.dac_nids = spec->private_dac_nids;
590 for(i = 0; i < 4; i++) {
591 nid = cfg->line_out_pins[i];
592 if (nid) {
593 /* config dac list */
594 switch (i) {
595 case AUTO_SEQ_FRONT:
596 spec->multiout.dac_nids[i] = 0x10;
597 break;
598 case AUTO_SEQ_CENLFE:
599 spec->multiout.dac_nids[i] = 0x12;
600 break;
601 case AUTO_SEQ_SURROUND:
602 spec->multiout.dac_nids[i] = 0x13;
603 break;
604 case AUTO_SEQ_SIDE:
605 spec->multiout.dac_nids[i] = 0x11;
606 break;
611 return 0;
614 /* add playback controls from the parsed DAC table */
615 static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
616 const struct auto_pin_cfg *cfg)
618 char name[32];
619 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
620 hda_nid_t nid, nid_vol = 0;
621 int i, err;
623 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
624 nid = cfg->line_out_pins[i];
626 if (!nid)
627 continue;
629 if (i != AUTO_SEQ_FRONT)
630 nid_vol = 0x1b - i + 1;
632 if (i == AUTO_SEQ_CENLFE) {
633 /* Center/LFE */
634 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
635 "Center Playback Volume",
636 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
637 if (err < 0)
638 return err;
639 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
640 "LFE Playback Volume",
641 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
642 if (err < 0)
643 return err;
644 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
645 "Center Playback Switch",
646 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
647 if (err < 0)
648 return err;
649 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
650 "LFE Playback Switch",
651 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
652 if (err < 0)
653 return err;
654 } else if (i == AUTO_SEQ_FRONT){
655 /* add control to mixer index 0 */
656 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
657 "Master Front Playback Volume",
658 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
659 if (err < 0)
660 return err;
661 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
662 "Master Front Playback Switch",
663 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
664 if (err < 0)
665 return err;
667 /* add control to PW3 */
668 sprintf(name, "%s Playback Volume", chname[i]);
669 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
670 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
671 if (err < 0)
672 return err;
673 sprintf(name, "%s Playback Switch", chname[i]);
674 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
675 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
676 if (err < 0)
677 return err;
678 } else {
679 sprintf(name, "%s Playback Volume", chname[i]);
680 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
681 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
682 if (err < 0)
683 return err;
684 sprintf(name, "%s Playback Switch", chname[i]);
685 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
686 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
687 if (err < 0)
688 return err;
692 return 0;
695 static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
697 int err;
699 if (!pin)
700 return 0;
702 spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
704 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
705 "Headphone Playback Volume",
706 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
707 if (err < 0)
708 return err;
709 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
710 "Headphone Playback Switch",
711 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
712 if (err < 0)
713 return err;
715 return 0;
718 /* create playback/capture controls for input pins */
719 static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
720 const struct auto_pin_cfg *cfg)
722 static char *labels[] = {
723 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
725 struct hda_input_mux *imux = &spec->private_imux;
726 int i, err, idx = 0;
728 /* for internal loopback recording select */
729 imux->items[imux->num_items].label = "Stereo Mixer";
730 imux->items[imux->num_items].index = idx;
731 imux->num_items++;
733 for (i = 0; i < AUTO_PIN_LAST; i++) {
734 if (!cfg->input_pins[i])
735 continue;
737 switch (cfg->input_pins[i]) {
738 case 0x1d: /* Mic */
739 idx = 2;
740 break;
742 case 0x1e: /* Line In */
743 idx = 3;
744 break;
746 case 0x21: /* Front Mic */
747 idx = 4;
748 break;
750 case 0x24: /* CD */
751 idx = 1;
752 break;
754 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
755 idx, 0x17);
756 if (err < 0)
757 return err;
758 imux->items[imux->num_items].label = labels[i];
759 imux->items[imux->num_items].index = idx;
760 imux->num_items++;
762 return 0;
765 static int vt1708_parse_auto_config(struct hda_codec *codec)
767 struct via_spec *spec = codec->spec;
768 int err;
770 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
771 if (err < 0)
772 return err;
773 err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
774 if (err < 0)
775 return err;
776 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
777 return 0; /* can't find valid BIOS pin config */
779 err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
780 if (err < 0)
781 return err;
782 err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
783 if (err < 0)
784 return err;
785 err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
786 if (err < 0)
787 return err;
789 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
791 if (spec->autocfg.dig_out_pin)
792 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
793 if (spec->autocfg.dig_in_pin)
794 spec->dig_in_nid = VT1708_DIGIN_NID;
796 if (spec->kctl_alloc)
797 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
799 spec->init_verbs = vt1708_volume_init_verbs;
801 spec->input_mux = &spec->private_imux;
803 return 1;
806 /* init callback for auto-configuration model -- overriding the default init */
807 static int via_auto_init(struct hda_codec *codec)
809 via_init(codec);
810 via_auto_init_multi_out(codec);
811 via_auto_init_hp_out(codec);
812 via_auto_init_analog_input(codec);
813 return 0;
816 static int patch_vt1708(struct hda_codec *codec)
818 struct via_spec *spec;
819 int err;
821 /* create a codec specific record */
822 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
823 if (spec == NULL)
824 return -ENOMEM;
826 codec->spec = spec;
828 /* automatic parse from the BIOS config */
829 err = vt1708_parse_auto_config(codec);
830 if (err < 0) {
831 via_free(codec);
832 return err;
833 } else if (!err) {
834 printk(KERN_INFO "hda_codec: Cannot set up configuration "
835 "from BIOS. Using genenic mode...\n");
839 spec->stream_name_analog = "VT1708 Analog";
840 spec->stream_analog_playback = &vt1708_pcm_analog_playback;
841 spec->stream_analog_capture = &vt1708_pcm_analog_capture;
843 spec->stream_name_digital = "VT1708 Digital";
844 spec->stream_digital_playback = &vt1708_pcm_digital_playback;
845 spec->stream_digital_capture = &vt1708_pcm_digital_capture;
848 if (!spec->adc_nids && spec->input_mux) {
849 spec->adc_nids = vt1708_adc_nids;
850 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
851 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
852 spec->num_mixers++;
855 codec->patch_ops = via_patch_ops;
857 codec->patch_ops.init = via_auto_init;
859 return 0;
862 /* capture mixer elements */
863 static struct snd_kcontrol_new vt1709_capture_mixer[] = {
864 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
865 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
866 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
867 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
868 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
869 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
871 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
872 /* The multiple "Capture Source" controls confuse alsamixer
873 * So call somewhat different..
874 * FIXME: the controls appear in the "playback" view!
876 /* .name = "Capture Source", */
877 .name = "Input Source",
878 .count = 1,
879 .info = via_mux_enum_info,
880 .get = via_mux_enum_get,
881 .put = via_mux_enum_put,
883 { } /* end */
887 * generic initialization of ADC, input mixers and output mixers
889 static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
891 * Unmute ADC0-2 and set the default input to mic-in
893 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
894 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
895 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
898 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
899 * mixer widget
901 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
902 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
903 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
904 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
905 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
906 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
909 * Set up output selector (0x1a, 0x1b, 0x29)
911 /* set vol=0 to output mixers */
912 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
913 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
914 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
917 * Unmute PW3 and PW4
919 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
920 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
922 /* Set input of PW4 as AOW4 */
923 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
924 /* Set mic as default input of sw0 */
925 {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
926 /* PW9 Output enable */
927 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
931 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
932 .substreams = 1,
933 .channels_min = 2,
934 .channels_max = 10,
935 .nid = 0x10, /* NID to query formats and rates */
936 .ops = {
937 .open = via_playback_pcm_open,
938 .prepare = via_playback_pcm_prepare,
939 .cleanup = via_playback_pcm_cleanup
943 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
944 .substreams = 1,
945 .channels_min = 2,
946 .channels_max = 6,
947 .nid = 0x10, /* NID to query formats and rates */
948 .ops = {
949 .open = via_playback_pcm_open,
950 .prepare = via_playback_pcm_prepare,
951 .cleanup = via_playback_pcm_cleanup
955 static struct hda_pcm_stream vt1709_pcm_analog_capture = {
956 .substreams = 2,
957 .channels_min = 2,
958 .channels_max = 2,
959 .nid = 0x14, /* NID to query formats and rates */
960 .ops = {
961 .prepare = via_capture_pcm_prepare,
962 .cleanup = via_capture_pcm_cleanup
966 static struct hda_pcm_stream vt1709_pcm_digital_playback = {
967 .substreams = 1,
968 .channels_min = 2,
969 .channels_max = 2,
970 /* NID is set in via_build_pcms */
971 .ops = {
972 .open = via_dig_playback_pcm_open,
973 .close = via_dig_playback_pcm_close
977 static struct hda_pcm_stream vt1709_pcm_digital_capture = {
978 .substreams = 1,
979 .channels_min = 2,
980 .channels_max = 2,
983 static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
984 const struct auto_pin_cfg *cfg)
986 int i;
987 hda_nid_t nid;
989 if (cfg->line_outs == 4) /* 10 channels */
990 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
991 else if (cfg->line_outs == 3) /* 6 channels */
992 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
994 spec->multiout.dac_nids = spec->private_dac_nids;
996 if (cfg->line_outs == 4) { /* 10 channels */
997 for (i = 0; i < cfg->line_outs; i++) {
998 nid = cfg->line_out_pins[i];
999 if (nid) {
1000 /* config dac list */
1001 switch (i) {
1002 case AUTO_SEQ_FRONT:
1003 /* AOW0 */
1004 spec->multiout.dac_nids[i] = 0x10;
1005 break;
1006 case AUTO_SEQ_CENLFE:
1007 /* AOW2 */
1008 spec->multiout.dac_nids[i] = 0x12;
1009 break;
1010 case AUTO_SEQ_SURROUND:
1011 /* AOW3 */
1012 spec->multiout.dac_nids[i] = 0x27;
1013 break;
1014 case AUTO_SEQ_SIDE:
1015 /* AOW1 */
1016 spec->multiout.dac_nids[i] = 0x11;
1017 break;
1018 default:
1019 break;
1023 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1025 } else if (cfg->line_outs == 3) { /* 6 channels */
1026 for(i = 0; i < cfg->line_outs; i++) {
1027 nid = cfg->line_out_pins[i];
1028 if (nid) {
1029 /* config dac list */
1030 switch(i) {
1031 case AUTO_SEQ_FRONT:
1032 /* AOW0 */
1033 spec->multiout.dac_nids[i] = 0x10;
1034 break;
1035 case AUTO_SEQ_CENLFE:
1036 /* AOW2 */
1037 spec->multiout.dac_nids[i] = 0x12;
1038 break;
1039 case AUTO_SEQ_SURROUND:
1040 /* AOW1 */
1041 spec->multiout.dac_nids[i] = 0x11;
1042 break;
1043 default:
1044 break;
1050 return 0;
1053 /* add playback controls from the parsed DAC table */
1054 static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1055 const struct auto_pin_cfg *cfg)
1057 char name[32];
1058 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1059 hda_nid_t nid = 0;
1060 int i, err;
1062 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1063 nid = cfg->line_out_pins[i];
1065 if (!nid)
1066 continue;
1068 if (i == AUTO_SEQ_CENLFE) {
1069 /* Center/LFE */
1070 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1071 "Center Playback Volume",
1072 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
1073 if (err < 0)
1074 return err;
1075 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1076 "LFE Playback Volume",
1077 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
1078 if (err < 0)
1079 return err;
1080 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1081 "Center Playback Switch",
1082 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
1083 if (err < 0)
1084 return err;
1085 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1086 "LFE Playback Switch",
1087 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
1088 if (err < 0)
1089 return err;
1090 } else if (i == AUTO_SEQ_FRONT){
1091 /* add control to mixer index 0 */
1092 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1093 "Master Front Playback Volume",
1094 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
1095 if (err < 0)
1096 return err;
1097 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1098 "Master Front Playback Switch",
1099 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
1100 if (err < 0)
1101 return err;
1103 /* add control to PW3 */
1104 sprintf(name, "%s Playback Volume", chname[i]);
1105 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1106 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
1107 if (err < 0)
1108 return err;
1109 sprintf(name, "%s Playback Switch", chname[i]);
1110 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1111 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
1112 if (err < 0)
1113 return err;
1114 } else if (i == AUTO_SEQ_SURROUND) {
1115 sprintf(name, "%s Playback Volume", chname[i]);
1116 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1117 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
1118 if (err < 0)
1119 return err;
1120 sprintf(name, "%s Playback Switch", chname[i]);
1121 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1122 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
1123 if (err < 0)
1124 return err;
1125 } else if (i == AUTO_SEQ_SIDE) {
1126 sprintf(name, "%s Playback Volume", chname[i]);
1127 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1128 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
1129 if (err < 0)
1130 return err;
1131 sprintf(name, "%s Playback Switch", chname[i]);
1132 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1133 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
1134 if (err < 0)
1135 return err;
1139 return 0;
1142 static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1144 int err;
1146 if (!pin)
1147 return 0;
1149 if (spec->multiout.num_dacs == 5) /* 10 channels */
1150 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1151 else if (spec->multiout.num_dacs == 3) /* 6 channels */
1152 spec->multiout.hp_nid = 0;
1154 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1155 "Headphone Playback Volume",
1156 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1157 if (err < 0)
1158 return err;
1159 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1160 "Headphone Playback Switch",
1161 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1162 if (err < 0)
1163 return err;
1165 return 0;
1168 /* create playback/capture controls for input pins */
1169 static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1170 const struct auto_pin_cfg *cfg)
1172 static char *labels[] = {
1173 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1175 struct hda_input_mux *imux = &spec->private_imux;
1176 int i, err, idx = 0;
1178 /* for internal loopback recording select */
1179 imux->items[imux->num_items].label = "Stereo Mixer";
1180 imux->items[imux->num_items].index = idx;
1181 imux->num_items++;
1183 for (i = 0; i < AUTO_PIN_LAST; i++) {
1184 if (!cfg->input_pins[i])
1185 continue;
1187 switch (cfg->input_pins[i]) {
1188 case 0x1d: /* Mic */
1189 idx = 2;
1190 break;
1192 case 0x1e: /* Line In */
1193 idx = 3;
1194 break;
1196 case 0x21: /* Front Mic */
1197 idx = 4;
1198 break;
1200 case 0x23: /* CD */
1201 idx = 1;
1202 break;
1204 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1205 idx, 0x18);
1206 if (err < 0)
1207 return err;
1208 imux->items[imux->num_items].label = labels[i];
1209 imux->items[imux->num_items].index = idx;
1210 imux->num_items++;
1212 return 0;
1215 static int vt1709_parse_auto_config(struct hda_codec *codec)
1217 struct via_spec *spec = codec->spec;
1218 int err;
1220 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1221 if (err < 0)
1222 return err;
1223 err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1224 if (err < 0)
1225 return err;
1226 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1227 return 0; /* can't find valid BIOS pin config */
1229 err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1230 if (err < 0)
1231 return err;
1232 err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1233 if (err < 0)
1234 return err;
1235 err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1236 if (err < 0)
1237 return err;
1239 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1241 if (spec->autocfg.dig_out_pin)
1242 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1243 if (spec->autocfg.dig_in_pin)
1244 spec->dig_in_nid = VT1709_DIGIN_NID;
1246 if (spec->kctl_alloc)
1247 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1249 spec->input_mux = &spec->private_imux;
1251 return 1;
1254 static int patch_vt1709_10ch(struct hda_codec *codec)
1256 struct via_spec *spec;
1257 int err;
1259 /* create a codec specific record */
1260 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1261 if (spec == NULL)
1262 return -ENOMEM;
1264 codec->spec = spec;
1266 err = vt1709_parse_auto_config(codec);
1267 if (err < 0) {
1268 via_free(codec);
1269 return err;
1270 } else if (!err) {
1271 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1272 "Using genenic mode...\n");
1275 spec->init_verbs = vt1709_10ch_volume_init_verbs;
1277 spec->stream_name_analog = "VT1709 Analog";
1278 spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1279 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1281 spec->stream_name_digital = "VT1709 Digital";
1282 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1283 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1286 if (!spec->adc_nids && spec->input_mux) {
1287 spec->adc_nids = vt1709_adc_nids;
1288 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1289 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1290 spec->num_mixers++;
1293 codec->patch_ops = via_patch_ops;
1295 codec->patch_ops.init = via_auto_init;
1297 return 0;
1300 * generic initialization of ADC, input mixers and output mixers
1302 static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1304 * Unmute ADC0-2 and set the default input to mic-in
1306 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1307 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1308 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1311 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1312 * mixer widget
1314 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1315 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1316 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1317 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1318 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1319 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1322 * Set up output selector (0x1a, 0x1b, 0x29)
1324 /* set vol=0 to output mixers */
1325 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1326 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1327 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1330 * Unmute PW3 and PW4
1332 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1333 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1335 /* Set input of PW4 as MW0 */
1336 {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1337 /* Set mic as default input of sw0 */
1338 {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
1339 /* PW9 Output enable */
1340 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1344 static int patch_vt1709_6ch(struct hda_codec *codec)
1346 struct via_spec *spec;
1347 int err;
1349 /* create a codec specific record */
1350 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1351 if (spec == NULL)
1352 return -ENOMEM;
1354 codec->spec = spec;
1356 err = vt1709_parse_auto_config(codec);
1357 if (err < 0) {
1358 via_free(codec);
1359 return err;
1360 } else if (!err) {
1361 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1362 "Using genenic mode...\n");
1365 spec->init_verbs = vt1709_6ch_volume_init_verbs;
1367 spec->stream_name_analog = "VT1709 Analog";
1368 spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1369 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1371 spec->stream_name_digital = "VT1709 Digital";
1372 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1373 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1376 if (!spec->adc_nids && spec->input_mux) {
1377 spec->adc_nids = vt1709_adc_nids;
1378 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1379 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1380 spec->num_mixers++;
1383 codec->patch_ops = via_patch_ops;
1385 codec->patch_ops.init = via_auto_init;
1387 return 0;
1391 * patch entries
1393 struct hda_codec_preset snd_hda_preset_via[] = {
1394 { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1395 { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1396 { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1397 { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
1398 { .id = 0x1106E710, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1399 { .id = 0x1106E711, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1400 { .id = 0x1106E712, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1401 { .id = 0x1106E713, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1402 { .id = 0x1106E714, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1403 { .id = 0x1106E715, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1404 { .id = 0x1106E716, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1405 { .id = 0x1106E717, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1406 {} /* terminator */