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 * * * * * * * * * * * * * * * * */
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 */
33 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
36 #include <linux/init.h>
37 #include <linux/delay.h>
38 #include <linux/slab.h>
39 #include <sound/core.h>
40 #include "hda_codec.h"
41 #include "hda_local.h"
45 #define AMP_VAL_IDX_SHIFT 19
46 #define AMP_VAL_IDX_MASK (0x0f<<19)
48 #define NUM_CONTROL_ALLOC 32
49 #define NUM_VERB_ALLOC 32
52 #define VT1708_HP_NID 0x13
53 #define VT1708_DIGOUT_NID 0x14
54 #define VT1708_DIGIN_NID 0x16
55 #define VT1708_DIGIN_PIN 0x26
57 #define VT1709_HP_DAC_NID 0x28
58 #define VT1709_DIGOUT_NID 0x13
59 #define VT1709_DIGIN_NID 0x17
60 #define VT1709_DIGIN_PIN 0x25
62 #define VT1708B_HP_NID 0x25
63 #define VT1708B_DIGOUT_NID 0x12
64 #define VT1708B_DIGIN_NID 0x15
65 #define VT1708B_DIGIN_PIN 0x21
67 #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
68 #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
69 #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
70 #define IS_VT1708B_8CH_VENDORID(x) ((x) >= 0x1106e720 && (x) <= 0x1106e723)
71 #define IS_VT1708B_4CH_VENDORID(x) ((x) >= 0x1106e724 && (x) <= 0x1106e727)
86 static struct snd_kcontrol_new vt1708_control_templates[] = {
87 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
88 HDA_CODEC_MUTE(NULL, 0, 0, 0),
93 /* codec parameterization */
94 struct snd_kcontrol_new *mixers[3];
95 unsigned int num_mixers;
97 struct hda_verb *init_verbs;
99 char *stream_name_analog;
100 struct hda_pcm_stream *stream_analog_playback;
101 struct hda_pcm_stream *stream_analog_capture;
103 char *stream_name_digital;
104 struct hda_pcm_stream *stream_digital_playback;
105 struct hda_pcm_stream *stream_digital_capture;
108 struct hda_multi_out multiout;
111 unsigned int num_adc_nids;
113 hda_nid_t dig_in_nid;
116 const struct hda_input_mux *input_mux;
117 unsigned int cur_mux[3];
119 /* PCM information */
120 struct hda_pcm pcm_rec[2];
122 /* dynamic controls, init_verbs and input_mux */
123 struct auto_pin_cfg autocfg;
124 unsigned int num_kctl_alloc, num_kctl_used;
125 struct snd_kcontrol_new *kctl_alloc;
126 struct hda_input_mux private_imux;
127 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
129 #ifdef CONFIG_SND_HDA_POWER_SAVE
130 struct hda_loopback_check loopback;
134 static hda_nid_t vt1708_adc_nids[2] = {
139 static hda_nid_t vt1709_adc_nids[3] = {
144 static hda_nid_t vt1708B_adc_nids[2] = {
149 /* add dynamic controls */
150 static int via_add_control(struct via_spec *spec, int type, const char *name,
153 struct snd_kcontrol_new *knew;
155 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
156 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
158 /* array + terminator */
159 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
162 if (spec->kctl_alloc) {
163 memcpy(knew, spec->kctl_alloc,
164 sizeof(*knew) * spec->num_kctl_alloc);
165 kfree(spec->kctl_alloc);
167 spec->kctl_alloc = knew;
168 spec->num_kctl_alloc = num;
171 knew = &spec->kctl_alloc[spec->num_kctl_used];
172 *knew = vt1708_control_templates[type];
173 knew->name = kstrdup(name, GFP_KERNEL);
177 knew->private_value = val;
178 spec->num_kctl_used++;
182 /* create input playback/capture controls for the given pin */
183 static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
184 const char *ctlname, int idx, int mix_nid)
189 sprintf(name, "%s Playback Volume", ctlname);
190 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
191 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
194 sprintf(name, "%s Playback Switch", ctlname);
195 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
196 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
202 static void via_auto_set_output_and_unmute(struct hda_codec *codec,
203 hda_nid_t nid, int pin_type,
207 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
209 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
214 static void via_auto_init_multi_out(struct hda_codec *codec)
216 struct via_spec *spec = codec->spec;
219 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
220 hda_nid_t nid = spec->autocfg.line_out_pins[i];
222 via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
226 static void via_auto_init_hp_out(struct hda_codec *codec)
228 struct via_spec *spec = codec->spec;
231 pin = spec->autocfg.hp_pins[0];
232 if (pin) /* connect to front */
233 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
236 static void via_auto_init_analog_input(struct hda_codec *codec)
238 struct via_spec *spec = codec->spec;
241 for (i = 0; i < AUTO_PIN_LAST; i++) {
242 hda_nid_t nid = spec->autocfg.input_pins[i];
244 snd_hda_codec_write(codec, nid, 0,
245 AC_VERB_SET_PIN_WIDGET_CONTROL,
246 (i <= AUTO_PIN_FRONT_MIC ?
247 PIN_VREF50 : PIN_IN));
254 static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
255 struct snd_ctl_elem_info *uinfo)
257 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
258 struct via_spec *spec = codec->spec;
259 return snd_hda_input_mux_info(spec->input_mux, uinfo);
262 static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
263 struct snd_ctl_elem_value *ucontrol)
265 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
266 struct via_spec *spec = codec->spec;
267 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
269 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
273 static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
274 struct snd_ctl_elem_value *ucontrol)
276 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
277 struct via_spec *spec = codec->spec;
278 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
279 unsigned int vendor_id = codec->vendor_id;
281 /* AIW0 lydia 060801 add for correct sw0 input select */
282 if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
283 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
284 0x18, &spec->cur_mux[adc_idx]);
285 else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
286 IS_VT1709_6CH_VENDORID(vendor_id)) && adc_idx == 0)
287 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
288 0x19, &spec->cur_mux[adc_idx]);
289 else if ((IS_VT1708B_8CH_VENDORID(vendor_id) ||
290 IS_VT1708B_4CH_VENDORID(vendor_id)) && adc_idx == 0)
291 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
292 0x17, &spec->cur_mux[adc_idx]);
294 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
295 spec->adc_nids[adc_idx],
296 &spec->cur_mux[adc_idx]);
299 /* capture mixer elements */
300 static struct snd_kcontrol_new vt1708_capture_mixer[] = {
301 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
302 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
303 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
304 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
306 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
307 /* The multiple "Capture Source" controls confuse alsamixer
308 * So call somewhat different..
309 * FIXME: the controls appear in the "playback" view!
311 /* .name = "Capture Source", */
312 .name = "Input Source",
314 .info = via_mux_enum_info,
315 .get = via_mux_enum_get,
316 .put = via_mux_enum_put,
321 * generic initialization of ADC, input mixers and output mixers
323 static struct hda_verb vt1708_volume_init_verbs[] = {
325 * Unmute ADC0-1 and set the default input to mic-in
327 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
328 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
331 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
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)},
342 * Set up output mixers (0x19 - 0x1b)
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},
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},
356 static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
357 struct hda_codec *codec,
358 struct snd_pcm_substream *substream)
360 struct via_spec *spec = codec->spec;
361 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
364 static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
365 struct hda_codec *codec,
366 unsigned int stream_tag,
368 struct snd_pcm_substream *substream)
370 struct via_spec *spec = codec->spec;
371 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
372 stream_tag, format, substream);
375 static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
376 struct hda_codec *codec,
377 struct snd_pcm_substream *substream)
379 struct via_spec *spec = codec->spec;
380 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
386 static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
387 struct hda_codec *codec,
388 struct snd_pcm_substream *substream)
390 struct via_spec *spec = codec->spec;
391 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
394 static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
395 struct hda_codec *codec,
396 struct snd_pcm_substream *substream)
398 struct via_spec *spec = codec->spec;
399 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
402 static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
403 struct hda_codec *codec,
404 unsigned int stream_tag,
406 struct snd_pcm_substream *substream)
408 struct via_spec *spec = codec->spec;
409 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
410 stream_tag, format, substream);
416 static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
417 struct hda_codec *codec,
418 unsigned int stream_tag,
420 struct snd_pcm_substream *substream)
422 struct via_spec *spec = codec->spec;
424 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
425 stream_tag, 0, format);
429 static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
430 struct hda_codec *codec,
431 struct snd_pcm_substream *substream)
433 struct via_spec *spec = codec->spec;
434 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
439 static struct hda_pcm_stream vt1708_pcm_analog_playback = {
443 .nid = 0x10, /* NID to query formats and rates */
445 .open = via_playback_pcm_open,
446 .prepare = via_playback_pcm_prepare,
447 .cleanup = via_playback_pcm_cleanup
451 static struct hda_pcm_stream vt1708_pcm_analog_capture = {
455 .nid = 0x15, /* NID to query formats and rates */
457 .prepare = via_capture_pcm_prepare,
458 .cleanup = via_capture_pcm_cleanup
462 static struct hda_pcm_stream vt1708_pcm_digital_playback = {
466 /* NID is set in via_build_pcms */
468 .open = via_dig_playback_pcm_open,
469 .close = via_dig_playback_pcm_close,
470 .prepare = via_dig_playback_pcm_prepare
474 static struct hda_pcm_stream vt1708_pcm_digital_capture = {
480 static int via_build_controls(struct hda_codec *codec)
482 struct via_spec *spec = codec->spec;
486 for (i = 0; i < spec->num_mixers; i++) {
487 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
492 if (spec->multiout.dig_out_nid) {
493 err = snd_hda_create_spdif_out_ctls(codec,
494 spec->multiout.dig_out_nid);
498 if (spec->dig_in_nid) {
499 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
506 static int via_build_pcms(struct hda_codec *codec)
508 struct via_spec *spec = codec->spec;
509 struct hda_pcm *info = spec->pcm_rec;
512 codec->pcm_info = info;
514 info->name = spec->stream_name_analog;
515 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
516 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
517 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
518 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
520 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
521 spec->multiout.max_channels;
523 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
526 info->name = spec->stream_name_digital;
527 if (spec->multiout.dig_out_nid) {
528 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
529 *(spec->stream_digital_playback);
530 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
531 spec->multiout.dig_out_nid;
533 if (spec->dig_in_nid) {
534 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
535 *(spec->stream_digital_capture);
536 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
544 static void via_free(struct hda_codec *codec)
546 struct via_spec *spec = codec->spec;
552 if (spec->kctl_alloc) {
553 for (i = 0; i < spec->num_kctl_used; i++)
554 kfree(spec->kctl_alloc[i].name);
555 kfree(spec->kctl_alloc);
561 static int via_init(struct hda_codec *codec)
563 struct via_spec *spec = codec->spec;
564 snd_hda_sequence_write(codec, spec->init_verbs);
565 /* Lydia Add for EAPD enable */
566 if (!spec->dig_in_nid) { /* No Digital In connection */
567 if (IS_VT1708_VENDORID(codec->vendor_id)) {
568 snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
569 AC_VERB_SET_PIN_WIDGET_CONTROL,
571 snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
572 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
573 } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
574 IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
575 snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
576 AC_VERB_SET_PIN_WIDGET_CONTROL,
578 snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
579 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
580 } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
581 IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
582 snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
583 AC_VERB_SET_PIN_WIDGET_CONTROL,
585 snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
586 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
593 #ifdef CONFIG_SND_HDA_POWER_SAVE
594 static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
596 struct via_spec *spec = codec->spec;
597 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
603 static struct hda_codec_ops via_patch_ops = {
604 .build_controls = via_build_controls,
605 .build_pcms = via_build_pcms,
608 #ifdef CONFIG_SND_HDA_POWER_SAVE
609 .check_power_status = via_check_power_status,
613 /* fill in the dac_nids table from the parsed pin configuration */
614 static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
615 const struct auto_pin_cfg *cfg)
620 spec->multiout.num_dacs = cfg->line_outs;
622 spec->multiout.dac_nids = spec->private_dac_nids;
624 for(i = 0; i < 4; i++) {
625 nid = cfg->line_out_pins[i];
627 /* config dac list */
630 spec->multiout.dac_nids[i] = 0x10;
632 case AUTO_SEQ_CENLFE:
633 spec->multiout.dac_nids[i] = 0x12;
635 case AUTO_SEQ_SURROUND:
636 spec->multiout.dac_nids[i] = 0x13;
639 spec->multiout.dac_nids[i] = 0x11;
648 /* add playback controls from the parsed DAC table */
649 static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
650 const struct auto_pin_cfg *cfg)
653 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
654 hda_nid_t nid, nid_vol = 0;
657 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
658 nid = cfg->line_out_pins[i];
663 if (i != AUTO_SEQ_FRONT)
664 nid_vol = 0x1b - i + 1;
666 if (i == AUTO_SEQ_CENLFE) {
668 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
669 "Center Playback Volume",
670 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
674 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
675 "LFE Playback Volume",
676 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
680 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
681 "Center Playback Switch",
682 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
686 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
687 "LFE Playback Switch",
688 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
692 } else if (i == AUTO_SEQ_FRONT){
693 /* add control to mixer index 0 */
694 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
695 "Master Front Playback Volume",
696 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
700 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
701 "Master Front Playback Switch",
702 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
707 /* add control to PW3 */
708 sprintf(name, "%s Playback Volume", chname[i]);
709 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
710 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
714 sprintf(name, "%s Playback Switch", chname[i]);
715 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
716 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
721 sprintf(name, "%s Playback Volume", chname[i]);
722 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
723 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
727 sprintf(name, "%s Playback Switch", chname[i]);
728 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
729 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
739 static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
746 spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
748 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
749 "Headphone Playback Volume",
750 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
753 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
754 "Headphone Playback Switch",
755 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
762 /* create playback/capture controls for input pins */
763 static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
764 const struct auto_pin_cfg *cfg)
766 static char *labels[] = {
767 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
769 struct hda_input_mux *imux = &spec->private_imux;
772 /* for internal loopback recording select */
773 imux->items[imux->num_items].label = "Stereo Mixer";
774 imux->items[imux->num_items].index = idx;
777 for (i = 0; i < AUTO_PIN_LAST; i++) {
778 if (!cfg->input_pins[i])
781 switch (cfg->input_pins[i]) {
786 case 0x1e: /* Line In */
790 case 0x21: /* Front Mic */
798 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
802 imux->items[imux->num_items].label = labels[i];
803 imux->items[imux->num_items].index = idx;
809 #ifdef CONFIG_SND_HDA_POWER_SAVE
810 static struct hda_amp_list vt1708_loopbacks[] = {
811 { 0x17, HDA_INPUT, 1 },
812 { 0x17, HDA_INPUT, 2 },
813 { 0x17, HDA_INPUT, 3 },
814 { 0x17, HDA_INPUT, 4 },
819 static int vt1708_parse_auto_config(struct hda_codec *codec)
821 struct via_spec *spec = codec->spec;
824 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
827 err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
830 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
831 return 0; /* can't find valid BIOS pin config */
833 err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
836 err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
839 err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
843 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
845 if (spec->autocfg.dig_out_pin)
846 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
847 if (spec->autocfg.dig_in_pin)
848 spec->dig_in_nid = VT1708_DIGIN_NID;
850 if (spec->kctl_alloc)
851 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
853 spec->init_verbs = vt1708_volume_init_verbs;
855 spec->input_mux = &spec->private_imux;
860 /* init callback for auto-configuration model -- overriding the default init */
861 static int via_auto_init(struct hda_codec *codec)
864 via_auto_init_multi_out(codec);
865 via_auto_init_hp_out(codec);
866 via_auto_init_analog_input(codec);
870 static int patch_vt1708(struct hda_codec *codec)
872 struct via_spec *spec;
875 /* create a codec specific record */
876 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
882 /* automatic parse from the BIOS config */
883 err = vt1708_parse_auto_config(codec);
888 printk(KERN_INFO "hda_codec: Cannot set up configuration "
889 "from BIOS. Using genenic mode...\n");
893 spec->stream_name_analog = "VT1708 Analog";
894 spec->stream_analog_playback = &vt1708_pcm_analog_playback;
895 spec->stream_analog_capture = &vt1708_pcm_analog_capture;
897 spec->stream_name_digital = "VT1708 Digital";
898 spec->stream_digital_playback = &vt1708_pcm_digital_playback;
899 spec->stream_digital_capture = &vt1708_pcm_digital_capture;
902 if (!spec->adc_nids && spec->input_mux) {
903 spec->adc_nids = vt1708_adc_nids;
904 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
905 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
909 codec->patch_ops = via_patch_ops;
911 codec->patch_ops.init = via_auto_init;
912 #ifdef CONFIG_SND_HDA_POWER_SAVE
913 spec->loopback.amplist = vt1708_loopbacks;
919 /* capture mixer elements */
920 static struct snd_kcontrol_new vt1709_capture_mixer[] = {
921 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
922 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
923 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
924 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
925 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
926 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
928 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
929 /* The multiple "Capture Source" controls confuse alsamixer
930 * So call somewhat different..
931 * FIXME: the controls appear in the "playback" view!
933 /* .name = "Capture Source", */
934 .name = "Input Source",
936 .info = via_mux_enum_info,
937 .get = via_mux_enum_get,
938 .put = via_mux_enum_put,
944 * generic initialization of ADC, input mixers and output mixers
946 static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
948 * Unmute ADC0-2 and set the default input to mic-in
950 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
951 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
952 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
955 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
958 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
959 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
960 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
961 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
962 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
963 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
966 * Set up output selector (0x1a, 0x1b, 0x29)
968 /* set vol=0 to output mixers */
969 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
970 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
971 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
976 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
977 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
979 /* Set input of PW4 as AOW4 */
980 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
981 /* PW9 Output enable */
982 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
986 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
990 .nid = 0x10, /* NID to query formats and rates */
992 .open = via_playback_pcm_open,
993 .prepare = via_playback_pcm_prepare,
994 .cleanup = via_playback_pcm_cleanup
998 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
1002 .nid = 0x10, /* NID to query formats and rates */
1004 .open = via_playback_pcm_open,
1005 .prepare = via_playback_pcm_prepare,
1006 .cleanup = via_playback_pcm_cleanup
1010 static struct hda_pcm_stream vt1709_pcm_analog_capture = {
1014 .nid = 0x14, /* NID to query formats and rates */
1016 .prepare = via_capture_pcm_prepare,
1017 .cleanup = via_capture_pcm_cleanup
1021 static struct hda_pcm_stream vt1709_pcm_digital_playback = {
1025 /* NID is set in via_build_pcms */
1027 .open = via_dig_playback_pcm_open,
1028 .close = via_dig_playback_pcm_close
1032 static struct hda_pcm_stream vt1709_pcm_digital_capture = {
1038 static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
1039 const struct auto_pin_cfg *cfg)
1044 if (cfg->line_outs == 4) /* 10 channels */
1045 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
1046 else if (cfg->line_outs == 3) /* 6 channels */
1047 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
1049 spec->multiout.dac_nids = spec->private_dac_nids;
1051 if (cfg->line_outs == 4) { /* 10 channels */
1052 for (i = 0; i < cfg->line_outs; i++) {
1053 nid = cfg->line_out_pins[i];
1055 /* config dac list */
1057 case AUTO_SEQ_FRONT:
1059 spec->multiout.dac_nids[i] = 0x10;
1061 case AUTO_SEQ_CENLFE:
1063 spec->multiout.dac_nids[i] = 0x12;
1065 case AUTO_SEQ_SURROUND:
1067 spec->multiout.dac_nids[i] = 0x27;
1071 spec->multiout.dac_nids[i] = 0x11;
1078 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1080 } else if (cfg->line_outs == 3) { /* 6 channels */
1081 for(i = 0; i < cfg->line_outs; i++) {
1082 nid = cfg->line_out_pins[i];
1084 /* config dac list */
1086 case AUTO_SEQ_FRONT:
1088 spec->multiout.dac_nids[i] = 0x10;
1090 case AUTO_SEQ_CENLFE:
1092 spec->multiout.dac_nids[i] = 0x12;
1094 case AUTO_SEQ_SURROUND:
1096 spec->multiout.dac_nids[i] = 0x11;
1108 /* add playback controls from the parsed DAC table */
1109 static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1110 const struct auto_pin_cfg *cfg)
1113 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1117 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1118 nid = cfg->line_out_pins[i];
1123 if (i == AUTO_SEQ_CENLFE) {
1125 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1126 "Center Playback Volume",
1127 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1131 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1132 "LFE Playback Volume",
1133 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1137 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1138 "Center Playback Switch",
1139 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1143 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1144 "LFE Playback Switch",
1145 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1149 } else if (i == AUTO_SEQ_FRONT){
1150 /* add control to mixer index 0 */
1151 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1152 "Master Front Playback Volume",
1153 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1157 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1158 "Master Front Playback Switch",
1159 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1164 /* add control to PW3 */
1165 sprintf(name, "%s Playback Volume", chname[i]);
1166 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1167 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1171 sprintf(name, "%s Playback Switch", chname[i]);
1172 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1173 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1177 } else if (i == AUTO_SEQ_SURROUND) {
1178 sprintf(name, "%s Playback Volume", chname[i]);
1179 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1180 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1184 sprintf(name, "%s Playback Switch", chname[i]);
1185 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1186 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1190 } else if (i == AUTO_SEQ_SIDE) {
1191 sprintf(name, "%s Playback Volume", chname[i]);
1192 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1193 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1197 sprintf(name, "%s Playback Switch", chname[i]);
1198 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1199 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1209 static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1216 if (spec->multiout.num_dacs == 5) /* 10 channels */
1217 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1218 else if (spec->multiout.num_dacs == 3) /* 6 channels */
1219 spec->multiout.hp_nid = 0;
1221 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1222 "Headphone Playback Volume",
1223 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1226 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1227 "Headphone Playback Switch",
1228 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1235 /* create playback/capture controls for input pins */
1236 static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1237 const struct auto_pin_cfg *cfg)
1239 static char *labels[] = {
1240 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1242 struct hda_input_mux *imux = &spec->private_imux;
1243 int i, err, idx = 0;
1245 /* for internal loopback recording select */
1246 imux->items[imux->num_items].label = "Stereo Mixer";
1247 imux->items[imux->num_items].index = idx;
1250 for (i = 0; i < AUTO_PIN_LAST; i++) {
1251 if (!cfg->input_pins[i])
1254 switch (cfg->input_pins[i]) {
1255 case 0x1d: /* Mic */
1259 case 0x1e: /* Line In */
1263 case 0x21: /* Front Mic */
1271 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1275 imux->items[imux->num_items].label = labels[i];
1276 imux->items[imux->num_items].index = idx;
1282 static int vt1709_parse_auto_config(struct hda_codec *codec)
1284 struct via_spec *spec = codec->spec;
1287 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1290 err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1293 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1294 return 0; /* can't find valid BIOS pin config */
1296 err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1299 err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1302 err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1306 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1308 if (spec->autocfg.dig_out_pin)
1309 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1310 if (spec->autocfg.dig_in_pin)
1311 spec->dig_in_nid = VT1709_DIGIN_NID;
1313 if (spec->kctl_alloc)
1314 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1316 spec->input_mux = &spec->private_imux;
1321 #ifdef CONFIG_SND_HDA_POWER_SAVE
1322 static struct hda_amp_list vt1709_loopbacks[] = {
1323 { 0x18, HDA_INPUT, 1 },
1324 { 0x18, HDA_INPUT, 2 },
1325 { 0x18, HDA_INPUT, 3 },
1326 { 0x18, HDA_INPUT, 4 },
1331 static int patch_vt1709_10ch(struct hda_codec *codec)
1333 struct via_spec *spec;
1336 /* create a codec specific record */
1337 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1343 err = vt1709_parse_auto_config(codec);
1348 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1349 "Using genenic mode...\n");
1352 spec->init_verbs = vt1709_10ch_volume_init_verbs;
1354 spec->stream_name_analog = "VT1709 Analog";
1355 spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1356 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1358 spec->stream_name_digital = "VT1709 Digital";
1359 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1360 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1363 if (!spec->adc_nids && spec->input_mux) {
1364 spec->adc_nids = vt1709_adc_nids;
1365 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1366 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1370 codec->patch_ops = via_patch_ops;
1372 codec->patch_ops.init = via_auto_init;
1373 #ifdef CONFIG_SND_HDA_POWER_SAVE
1374 spec->loopback.amplist = vt1709_loopbacks;
1380 * generic initialization of ADC, input mixers and output mixers
1382 static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1384 * Unmute ADC0-2 and set the default input to mic-in
1386 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1387 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1388 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1391 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1394 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1395 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1396 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1397 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1398 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1399 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1402 * Set up output selector (0x1a, 0x1b, 0x29)
1404 /* set vol=0 to output mixers */
1405 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1406 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1407 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1410 * Unmute PW3 and PW4
1412 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1413 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1415 /* Set input of PW4 as MW0 */
1416 {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1417 /* PW9 Output enable */
1418 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1422 static int patch_vt1709_6ch(struct hda_codec *codec)
1424 struct via_spec *spec;
1427 /* create a codec specific record */
1428 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1434 err = vt1709_parse_auto_config(codec);
1439 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1440 "Using genenic mode...\n");
1443 spec->init_verbs = vt1709_6ch_volume_init_verbs;
1445 spec->stream_name_analog = "VT1709 Analog";
1446 spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1447 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1449 spec->stream_name_digital = "VT1709 Digital";
1450 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1451 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1454 if (!spec->adc_nids && spec->input_mux) {
1455 spec->adc_nids = vt1709_adc_nids;
1456 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1457 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1461 codec->patch_ops = via_patch_ops;
1463 codec->patch_ops.init = via_auto_init;
1464 #ifdef CONFIG_SND_HDA_POWER_SAVE
1465 spec->loopback.amplist = vt1709_loopbacks;
1470 /* capture mixer elements */
1471 static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
1472 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
1473 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
1474 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
1475 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
1477 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1478 /* The multiple "Capture Source" controls confuse alsamixer
1479 * So call somewhat different..
1480 * FIXME: the controls appear in the "playback" view!
1482 /* .name = "Capture Source", */
1483 .name = "Input Source",
1485 .info = via_mux_enum_info,
1486 .get = via_mux_enum_get,
1487 .put = via_mux_enum_put,
1492 * generic initialization of ADC, input mixers and output mixers
1494 static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
1496 * Unmute ADC0-1 and set the default input to mic-in
1498 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1499 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1502 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1505 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1506 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1507 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1508 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1509 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1510 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1513 * Set up output mixers
1515 /* set vol=0 to output mixers */
1516 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1517 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1518 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1520 /* Setup default input to PW4 */
1521 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1},
1522 /* PW9 Output enable */
1523 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1524 /* PW10 Input enable */
1525 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1529 static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
1531 * Unmute ADC0-1 and set the default input to mic-in
1533 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1534 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1537 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1540 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1541 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1542 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1543 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1544 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1545 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1548 * Set up output mixers
1550 /* set vol=0 to output mixers */
1551 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1552 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1553 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1555 /* Setup default input of PW4 to MW0 */
1556 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
1557 /* PW9 Output enable */
1558 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1559 /* PW10 Input enable */
1560 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1564 static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
1568 .nid = 0x10, /* NID to query formats and rates */
1570 .open = via_playback_pcm_open,
1571 .prepare = via_playback_pcm_prepare,
1572 .cleanup = via_playback_pcm_cleanup
1576 static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
1580 .nid = 0x10, /* NID to query formats and rates */
1582 .open = via_playback_pcm_open,
1583 .prepare = via_playback_pcm_prepare,
1584 .cleanup = via_playback_pcm_cleanup
1588 static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
1592 .nid = 0x13, /* NID to query formats and rates */
1594 .prepare = via_capture_pcm_prepare,
1595 .cleanup = via_capture_pcm_cleanup
1599 static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
1603 /* NID is set in via_build_pcms */
1605 .open = via_dig_playback_pcm_open,
1606 .close = via_dig_playback_pcm_close,
1607 .prepare = via_dig_playback_pcm_prepare
1611 static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
1617 /* fill in the dac_nids table from the parsed pin configuration */
1618 static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
1619 const struct auto_pin_cfg *cfg)
1624 spec->multiout.num_dacs = cfg->line_outs;
1626 spec->multiout.dac_nids = spec->private_dac_nids;
1628 for (i = 0; i < 4; i++) {
1629 nid = cfg->line_out_pins[i];
1631 /* config dac list */
1633 case AUTO_SEQ_FRONT:
1634 spec->multiout.dac_nids[i] = 0x10;
1636 case AUTO_SEQ_CENLFE:
1637 spec->multiout.dac_nids[i] = 0x24;
1639 case AUTO_SEQ_SURROUND:
1640 spec->multiout.dac_nids[i] = 0x25;
1643 spec->multiout.dac_nids[i] = 0x11;
1652 /* add playback controls from the parsed DAC table */
1653 static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
1654 const struct auto_pin_cfg *cfg)
1657 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1658 hda_nid_t nid_vols[] = {0x16, 0x27, 0x26, 0x18};
1659 hda_nid_t nid, nid_vol = 0;
1662 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1663 nid = cfg->line_out_pins[i];
1668 nid_vol = nid_vols[i];
1670 if (i == AUTO_SEQ_CENLFE) {
1672 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1673 "Center Playback Volume",
1674 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1678 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1679 "LFE Playback Volume",
1680 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1684 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1685 "Center Playback Switch",
1686 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1690 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1691 "LFE Playback Switch",
1692 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1696 } else if (i == AUTO_SEQ_FRONT) {
1697 /* add control to mixer index 0 */
1698 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1699 "Master Front Playback Volume",
1700 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1704 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1705 "Master Front Playback Switch",
1706 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1711 /* add control to PW3 */
1712 sprintf(name, "%s Playback Volume", chname[i]);
1713 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1714 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1718 sprintf(name, "%s Playback Switch", chname[i]);
1719 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1720 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1725 sprintf(name, "%s Playback Volume", chname[i]);
1726 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1727 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1731 sprintf(name, "%s Playback Switch", chname[i]);
1732 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1733 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1743 static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1750 spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
1752 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1753 "Headphone Playback Volume",
1754 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1757 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1758 "Headphone Playback Switch",
1759 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1766 /* create playback/capture controls for input pins */
1767 static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
1768 const struct auto_pin_cfg *cfg)
1770 static char *labels[] = {
1771 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1773 struct hda_input_mux *imux = &spec->private_imux;
1774 int i, err, idx = 0;
1776 /* for internal loopback recording select */
1777 imux->items[imux->num_items].label = "Stereo Mixer";
1778 imux->items[imux->num_items].index = idx;
1781 for (i = 0; i < AUTO_PIN_LAST; i++) {
1782 if (!cfg->input_pins[i])
1785 switch (cfg->input_pins[i]) {
1786 case 0x1a: /* Mic */
1790 case 0x1b: /* Line In */
1794 case 0x1e: /* Front Mic */
1802 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1806 imux->items[imux->num_items].label = labels[i];
1807 imux->items[imux->num_items].index = idx;
1813 static int vt1708B_parse_auto_config(struct hda_codec *codec)
1815 struct via_spec *spec = codec->spec;
1818 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1821 err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
1824 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1825 return 0; /* can't find valid BIOS pin config */
1827 err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
1830 err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1833 err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
1837 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1839 if (spec->autocfg.dig_out_pin)
1840 spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
1841 if (spec->autocfg.dig_in_pin)
1842 spec->dig_in_nid = VT1708B_DIGIN_NID;
1844 if (spec->kctl_alloc)
1845 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1847 spec->input_mux = &spec->private_imux;
1852 #ifdef CONFIG_SND_HDA_POWER_SAVE
1853 static struct hda_amp_list vt1708B_loopbacks[] = {
1854 { 0x16, HDA_INPUT, 1 },
1855 { 0x16, HDA_INPUT, 2 },
1856 { 0x16, HDA_INPUT, 3 },
1857 { 0x16, HDA_INPUT, 4 },
1862 static int patch_vt1708B_8ch(struct hda_codec *codec)
1864 struct via_spec *spec;
1867 /* create a codec specific record */
1868 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1874 /* automatic parse from the BIOS config */
1875 err = vt1708B_parse_auto_config(codec);
1880 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1881 "from BIOS. Using genenic mode...\n");
1884 spec->init_verbs = vt1708B_8ch_volume_init_verbs;
1886 spec->stream_name_analog = "VT1708B Analog";
1887 spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
1888 spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1890 spec->stream_name_digital = "VT1708B Digital";
1891 spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1892 spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1894 if (!spec->adc_nids && spec->input_mux) {
1895 spec->adc_nids = vt1708B_adc_nids;
1896 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1897 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1901 codec->patch_ops = via_patch_ops;
1903 codec->patch_ops.init = via_auto_init;
1904 #ifdef CONFIG_SND_HDA_POWER_SAVE
1905 spec->loopback.amplist = vt1708B_loopbacks;
1911 static int patch_vt1708B_4ch(struct hda_codec *codec)
1913 struct via_spec *spec;
1916 /* create a codec specific record */
1917 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1923 /* automatic parse from the BIOS config */
1924 err = vt1708B_parse_auto_config(codec);
1929 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1930 "from BIOS. Using genenic mode...\n");
1933 spec->init_verbs = vt1708B_4ch_volume_init_verbs;
1935 spec->stream_name_analog = "VT1708B Analog";
1936 spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
1937 spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
1939 spec->stream_name_digital = "VT1708B Digital";
1940 spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
1941 spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
1943 if (!spec->adc_nids && spec->input_mux) {
1944 spec->adc_nids = vt1708B_adc_nids;
1945 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
1946 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
1950 codec->patch_ops = via_patch_ops;
1952 codec->patch_ops.init = via_auto_init;
1953 #ifdef CONFIG_SND_HDA_POWER_SAVE
1954 spec->loopback.amplist = vt1708B_loopbacks;
1963 struct hda_codec_preset snd_hda_preset_via[] = {
1964 { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1965 { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1966 { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1967 { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
1968 { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
1969 .patch = patch_vt1709_10ch},
1970 { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
1971 .patch = patch_vt1709_10ch},
1972 { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
1973 .patch = patch_vt1709_10ch},
1974 { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
1975 .patch = patch_vt1709_10ch},
1976 { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
1977 .patch = patch_vt1709_6ch},
1978 { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
1979 .patch = patch_vt1709_6ch},
1980 { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
1981 .patch = patch_vt1709_6ch},
1982 { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
1983 .patch = patch_vt1709_6ch},
1984 { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
1985 .patch = patch_vt1708B_8ch},
1986 { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
1987 .patch = patch_vt1708B_8ch},
1988 { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
1989 .patch = patch_vt1708B_8ch},
1990 { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
1991 .patch = patch_vt1708B_8ch},
1992 { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
1993 .patch = patch_vt1708B_4ch},
1994 { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
1995 .patch = patch_vt1708B_4ch},
1996 { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
1997 .patch = patch_vt1708B_4ch},
1998 { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
1999 .patch = patch_vt1708B_4ch},