2 * Universal Interface for Intel High Definition Audio Codec
4 * HD audio interface patch for VIA VT1702/VT1708/VT1709 codec
6 * Copyright (c) 2006-2008 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 */
32 /* 2007-11-14 Lydia Wang Add VT1708A codec HP and CD pin connect config */
33 /* 2008-02-03 Lydia Wang Fix Rear channels and Back channels inverse issue */
34 /* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */
35 /* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */
36 /* 2008-04-09 Lydia Wang Add Independent HP feature */
37 /* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */
39 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
42 #include <linux/init.h>
43 #include <linux/delay.h>
44 #include <linux/slab.h>
45 #include <sound/core.h>
46 #include <sound/asoundef.h>
47 #include "hda_codec.h"
48 #include "hda_local.h"
49 #include "hda_patch.h"
52 #define AMP_VAL_IDX_SHIFT 19
53 #define AMP_VAL_IDX_MASK (0x0f<<19)
55 #define NUM_CONTROL_ALLOC 32
56 #define NUM_VERB_ALLOC 32
59 #define VT1708_HP_NID 0x13
60 #define VT1708_DIGOUT_NID 0x14
61 #define VT1708_DIGIN_NID 0x16
62 #define VT1708_DIGIN_PIN 0x26
63 #define VT1708_HP_PIN_NID 0x20
64 #define VT1708_CD_PIN_NID 0x24
66 #define VT1709_HP_DAC_NID 0x28
67 #define VT1709_DIGOUT_NID 0x13
68 #define VT1709_DIGIN_NID 0x17
69 #define VT1709_DIGIN_PIN 0x25
71 #define VT1708B_HP_NID 0x25
72 #define VT1708B_DIGOUT_NID 0x12
73 #define VT1708B_DIGIN_NID 0x15
74 #define VT1708B_DIGIN_PIN 0x21
76 #define VT1708S_HP_NID 0x25
77 #define VT1708S_DIGOUT_NID 0x12
79 #define VT1702_HP_NID 0x17
80 #define VT1702_DIGOUT_NID 0x11
82 #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
83 #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
84 #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
85 #define IS_VT1708B_8CH_VENDORID(x) ((x) >= 0x1106e720 && (x) <= 0x1106e723)
86 #define IS_VT1708B_4CH_VENDORID(x) ((x) >= 0x1106e724 && (x) <= 0x1106e727)
87 #define IS_VT1708S_VENDORID(x) ((x) >= 0x11060397 && (x) <= 0x11067397)
88 #define IS_VT1702_VENDORID(x) ((x) >= 0x11060398 && (x) <= 0x11067398)
90 #define VIA_HP_EVENT 0x01
91 #define VIA_GPIO_EVENT 0x02
105 static struct snd_kcontrol_new vt1708_control_templates[] = {
106 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
107 HDA_CODEC_MUTE(NULL, 0, 0, 0),
112 /* codec parameterization */
113 struct snd_kcontrol_new *mixers[3];
114 unsigned int num_mixers;
116 struct hda_verb *init_verbs[5];
117 unsigned int num_iverbs;
119 char *stream_name_analog;
120 struct hda_pcm_stream *stream_analog_playback;
121 struct hda_pcm_stream *stream_analog_capture;
123 char *stream_name_digital;
124 struct hda_pcm_stream *stream_digital_playback;
125 struct hda_pcm_stream *stream_digital_capture;
126 struct hda_pcm_stream *stream_extra_digital_playback;
129 struct hda_multi_out multiout;
130 hda_nid_t extra_dig_out_nid;
133 unsigned int num_adc_nids;
135 hda_nid_t dig_in_nid;
138 const struct hda_input_mux *input_mux;
139 unsigned int cur_mux[3];
141 /* PCM information */
142 struct hda_pcm pcm_rec[3];
144 /* dynamic controls, init_verbs and input_mux */
145 struct auto_pin_cfg autocfg;
146 unsigned int num_kctl_alloc, num_kctl_used;
147 struct snd_kcontrol_new *kctl_alloc;
148 struct hda_input_mux private_imux[2];
149 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
152 const struct hda_input_mux *hp_mux;
153 unsigned int hp_independent_mode;
155 #ifdef CONFIG_SND_HDA_POWER_SAVE
156 struct hda_loopback_check loopback;
160 static hda_nid_t vt1708_adc_nids[2] = {
165 static hda_nid_t vt1709_adc_nids[3] = {
170 static hda_nid_t vt1708B_adc_nids[2] = {
175 static hda_nid_t vt1708S_adc_nids[2] = {
180 static hda_nid_t vt1702_adc_nids[3] = {
185 /* add dynamic controls */
186 static int via_add_control(struct via_spec *spec, int type, const char *name,
189 struct snd_kcontrol_new *knew;
191 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
192 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
194 /* array + terminator */
195 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
198 if (spec->kctl_alloc) {
199 memcpy(knew, spec->kctl_alloc,
200 sizeof(*knew) * spec->num_kctl_alloc);
201 kfree(spec->kctl_alloc);
203 spec->kctl_alloc = knew;
204 spec->num_kctl_alloc = num;
207 knew = &spec->kctl_alloc[spec->num_kctl_used];
208 *knew = vt1708_control_templates[type];
209 knew->name = kstrdup(name, GFP_KERNEL);
213 knew->private_value = val;
214 spec->num_kctl_used++;
218 /* create input playback/capture controls for the given pin */
219 static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
220 const char *ctlname, int idx, int mix_nid)
225 sprintf(name, "%s Playback Volume", ctlname);
226 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
227 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
230 sprintf(name, "%s Playback Switch", ctlname);
231 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
232 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
238 static void via_auto_set_output_and_unmute(struct hda_codec *codec,
239 hda_nid_t nid, int pin_type,
243 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
245 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
250 static void via_auto_init_multi_out(struct hda_codec *codec)
252 struct via_spec *spec = codec->spec;
255 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
256 hda_nid_t nid = spec->autocfg.line_out_pins[i];
258 via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
262 static void via_auto_init_hp_out(struct hda_codec *codec)
264 struct via_spec *spec = codec->spec;
267 pin = spec->autocfg.hp_pins[0];
268 if (pin) /* connect to front */
269 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
272 static void via_auto_init_analog_input(struct hda_codec *codec)
274 struct via_spec *spec = codec->spec;
277 for (i = 0; i < AUTO_PIN_LAST; i++) {
278 hda_nid_t nid = spec->autocfg.input_pins[i];
280 snd_hda_codec_write(codec, nid, 0,
281 AC_VERB_SET_PIN_WIDGET_CONTROL,
282 (i <= AUTO_PIN_FRONT_MIC ?
283 PIN_VREF50 : PIN_IN));
290 static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
291 struct snd_ctl_elem_info *uinfo)
293 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
294 struct via_spec *spec = codec->spec;
295 return snd_hda_input_mux_info(spec->input_mux, uinfo);
298 static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
299 struct snd_ctl_elem_value *ucontrol)
301 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
302 struct via_spec *spec = codec->spec;
303 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
305 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
309 static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
310 struct snd_ctl_elem_value *ucontrol)
312 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
313 struct via_spec *spec = codec->spec;
314 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
315 unsigned int vendor_id = codec->vendor_id;
317 /* AIW0 lydia 060801 add for correct sw0 input select */
318 if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
319 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
320 0x18, &spec->cur_mux[adc_idx]);
321 else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
322 IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0))
323 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
324 0x19, &spec->cur_mux[adc_idx]);
325 else if ((IS_VT1708B_8CH_VENDORID(vendor_id) ||
326 IS_VT1708B_4CH_VENDORID(vendor_id)) && (adc_idx == 0))
327 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
328 0x17, &spec->cur_mux[adc_idx]);
329 else if (IS_VT1702_VENDORID(vendor_id) && (adc_idx == 0))
330 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
331 0x13, &spec->cur_mux[adc_idx]);
333 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
334 spec->adc_nids[adc_idx],
335 &spec->cur_mux[adc_idx]);
338 static int via_independent_hp_info(struct snd_kcontrol *kcontrol,
339 struct snd_ctl_elem_info *uinfo)
341 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
342 struct via_spec *spec = codec->spec;
343 return snd_hda_input_mux_info(spec->hp_mux, uinfo);
346 static int via_independent_hp_get(struct snd_kcontrol *kcontrol,
347 struct snd_ctl_elem_value *ucontrol)
349 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
350 struct via_spec *spec = codec->spec;
351 hda_nid_t nid = spec->autocfg.hp_pins[0];
352 unsigned int pinsel = snd_hda_codec_read(codec, nid, 0,
353 AC_VERB_GET_CONNECT_SEL,
356 ucontrol->value.enumerated.item[0] = pinsel;
361 static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
362 struct snd_ctl_elem_value *ucontrol)
364 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
365 struct via_spec *spec = codec->spec;
366 hda_nid_t nid = spec->autocfg.hp_pins[0];
367 unsigned int pinsel = ucontrol->value.enumerated.item[0];
368 unsigned int con_nid = snd_hda_codec_read(codec, nid, 0,
369 AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
371 if (con_nid == spec->multiout.hp_nid) {
373 if (!spec->hp_independent_mode) {
374 if (spec->multiout.num_dacs > 1)
375 spec->multiout.num_dacs -= 1;
376 spec->hp_independent_mode = 1;
378 } else if (pinsel == 1) {
379 if (spec->hp_independent_mode) {
380 if (spec->multiout.num_dacs > 1)
381 spec->multiout.num_dacs += 1;
382 spec->hp_independent_mode = 0;
387 if (spec->hp_independent_mode) {
388 if (spec->multiout.num_dacs > 1)
389 spec->multiout.num_dacs += 1;
390 spec->hp_independent_mode = 0;
392 } else if (pinsel == 1) {
393 if (!spec->hp_independent_mode) {
394 if (spec->multiout.num_dacs > 1)
395 spec->multiout.num_dacs -= 1;
396 spec->hp_independent_mode = 1;
400 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
403 if (spec->multiout.hp_nid &&
404 spec->multiout.hp_nid != spec->multiout.dac_nids[HDA_FRONT])
405 snd_hda_codec_setup_stream(codec,
406 spec->multiout.hp_nid,
412 static struct snd_kcontrol_new via_hp_mixer[] = {
414 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
415 .name = "Independent HP",
417 .info = via_independent_hp_info,
418 .get = via_independent_hp_get,
419 .put = via_independent_hp_put,
424 /* capture mixer elements */
425 static struct snd_kcontrol_new vt1708_capture_mixer[] = {
426 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
427 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
428 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
429 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
431 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
432 /* The multiple "Capture Source" controls confuse alsamixer
433 * So call somewhat different..
435 /* .name = "Capture Source", */
436 .name = "Input Source",
438 .info = via_mux_enum_info,
439 .get = via_mux_enum_get,
440 .put = via_mux_enum_put,
445 * generic initialization of ADC, input mixers and output mixers
447 static struct hda_verb vt1708_volume_init_verbs[] = {
449 * Unmute ADC0-1 and set the default input to mic-in
451 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
452 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
455 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
458 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
459 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
460 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
461 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
462 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
463 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
466 * Set up output mixers (0x19 - 0x1b)
468 /* set vol=0 to output mixers */
469 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
470 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
471 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
473 /* Setup default input to PW4 */
474 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
475 /* PW9 Output enable */
476 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
480 static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
481 struct hda_codec *codec,
482 struct snd_pcm_substream *substream)
484 struct via_spec *spec = codec->spec;
485 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
489 static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
490 struct hda_codec *codec,
491 unsigned int stream_tag,
493 struct snd_pcm_substream *substream)
495 struct via_spec *spec = codec->spec;
496 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
497 stream_tag, format, substream);
500 static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
501 struct hda_codec *codec,
502 struct snd_pcm_substream *substream)
504 struct via_spec *spec = codec->spec;
505 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
509 static void playback_multi_pcm_prep_0(struct hda_codec *codec,
510 unsigned int stream_tag,
512 struct snd_pcm_substream *substream)
514 struct via_spec *spec = codec->spec;
515 struct hda_multi_out *mout = &spec->multiout;
516 hda_nid_t *nids = mout->dac_nids;
517 int chs = substream->runtime->channels;
520 mutex_lock(&codec->spdif_mutex);
521 if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
523 snd_hda_is_supported_format(codec, mout->dig_out_nid,
525 !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
526 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
527 /* turn off SPDIF once; otherwise the IEC958 bits won't
529 if (codec->spdif_ctls & AC_DIG1_ENABLE)
530 snd_hda_codec_write(codec, mout->dig_out_nid, 0,
531 AC_VERB_SET_DIGI_CONVERT_1,
533 ~AC_DIG1_ENABLE & 0xff);
534 snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
535 stream_tag, 0, format);
536 /* turn on again (if needed) */
537 if (codec->spdif_ctls & AC_DIG1_ENABLE)
538 snd_hda_codec_write(codec, mout->dig_out_nid, 0,
539 AC_VERB_SET_DIGI_CONVERT_1,
540 codec->spdif_ctls & 0xff);
542 mout->dig_out_used = 0;
543 snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
547 mutex_unlock(&codec->spdif_mutex);
550 snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
553 if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] &&
554 !spec->hp_independent_mode)
555 /* headphone out will just decode front left/right (stereo) */
556 snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
559 /* extra outputs copied from front */
560 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
561 if (mout->extra_out_nid[i])
562 snd_hda_codec_setup_stream(codec,
563 mout->extra_out_nid[i],
564 stream_tag, 0, format);
567 for (i = 1; i < mout->num_dacs; i++) {
568 if (chs >= (i + 1) * 2) /* independent out */
569 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
571 else /* copy front */
572 snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
577 static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo,
578 struct hda_codec *codec,
579 unsigned int stream_tag,
581 struct snd_pcm_substream *substream)
583 struct via_spec *spec = codec->spec;
584 struct hda_multi_out *mout = &spec->multiout;
585 hda_nid_t *nids = mout->dac_nids;
587 if (substream->number == 0)
588 playback_multi_pcm_prep_0(codec, stream_tag, format,
591 if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] &&
592 spec->hp_independent_mode)
593 snd_hda_codec_setup_stream(codec, mout->hp_nid,
594 stream_tag, 0, format);
600 static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo,
601 struct hda_codec *codec,
602 struct snd_pcm_substream *substream)
604 struct via_spec *spec = codec->spec;
605 struct hda_multi_out *mout = &spec->multiout;
606 hda_nid_t *nids = mout->dac_nids;
609 if (substream->number == 0) {
610 for (i = 0; i < mout->num_dacs; i++)
611 snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
613 if (mout->hp_nid && !spec->hp_independent_mode)
614 snd_hda_codec_setup_stream(codec, mout->hp_nid,
617 for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
618 if (mout->extra_out_nid[i])
619 snd_hda_codec_setup_stream(codec,
620 mout->extra_out_nid[i],
622 mutex_lock(&codec->spdif_mutex);
623 if (mout->dig_out_nid &&
624 mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
625 snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
627 mout->dig_out_used = 0;
629 mutex_unlock(&codec->spdif_mutex);
631 if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT] &&
632 spec->hp_independent_mode)
633 snd_hda_codec_setup_stream(codec, mout->hp_nid,
643 static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
644 struct hda_codec *codec,
645 struct snd_pcm_substream *substream)
647 struct via_spec *spec = codec->spec;
648 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
651 static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
652 struct hda_codec *codec,
653 struct snd_pcm_substream *substream)
655 struct via_spec *spec = codec->spec;
656 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
659 static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
660 struct hda_codec *codec,
661 unsigned int stream_tag,
663 struct snd_pcm_substream *substream)
665 struct via_spec *spec = codec->spec;
666 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
667 stream_tag, format, substream);
670 /* setup SPDIF output stream */
671 static void setup_dig_playback_stream(struct hda_codec *codec, hda_nid_t nid,
672 unsigned int stream_tag, unsigned int format)
674 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
675 if (codec->spdif_ctls & AC_DIG1_ENABLE)
676 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
677 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
678 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
679 /* turn on again (if needed) */
680 if (codec->spdif_ctls & AC_DIG1_ENABLE)
681 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
682 codec->spdif_ctls & 0xff);
685 static int via_extra_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
686 struct hda_codec *codec,
687 unsigned int stream_tag,
689 struct snd_pcm_substream *substream)
691 struct via_spec *spec = codec->spec;
693 mutex_lock(&codec->spdif_mutex);
694 setup_dig_playback_stream(codec, spec->extra_dig_out_nid, stream_tag,
696 mutex_unlock(&codec->spdif_mutex);
703 static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
704 struct hda_codec *codec,
705 unsigned int stream_tag,
707 struct snd_pcm_substream *substream)
709 struct via_spec *spec = codec->spec;
711 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
712 stream_tag, 0, format);
716 static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
717 struct hda_codec *codec,
718 struct snd_pcm_substream *substream)
720 struct via_spec *spec = codec->spec;
721 snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
725 static struct hda_pcm_stream vt1708_pcm_analog_playback = {
729 .nid = 0x10, /* NID to query formats and rates */
731 .open = via_playback_pcm_open,
732 .prepare = via_playback_multi_pcm_prepare,
733 .cleanup = via_playback_multi_pcm_cleanup
737 static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = {
741 .nid = 0x10, /* NID to query formats and rates */
742 /* We got noisy outputs on the right channel on VT1708 when
743 * 24bit samples are used. Until any workaround is found,
744 * disable the 24bit format, so far.
746 .formats = SNDRV_PCM_FMTBIT_S16_LE,
748 .open = via_playback_pcm_open,
749 .prepare = via_playback_pcm_prepare,
750 .cleanup = via_playback_pcm_cleanup
754 static struct hda_pcm_stream vt1708_pcm_analog_capture = {
758 .nid = 0x15, /* NID to query formats and rates */
760 .prepare = via_capture_pcm_prepare,
761 .cleanup = via_capture_pcm_cleanup
765 static struct hda_pcm_stream vt1708_pcm_digital_playback = {
769 /* NID is set in via_build_pcms */
771 .open = via_dig_playback_pcm_open,
772 .close = via_dig_playback_pcm_close,
773 .prepare = via_dig_playback_pcm_prepare
777 static struct hda_pcm_stream vt1708_pcm_digital_capture = {
783 static int via_build_controls(struct hda_codec *codec)
785 struct via_spec *spec = codec->spec;
789 for (i = 0; i < spec->num_mixers; i++) {
790 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
795 if (spec->multiout.dig_out_nid) {
796 err = snd_hda_create_spdif_out_ctls(codec,
797 spec->multiout.dig_out_nid);
800 err = snd_hda_create_spdif_share_sw(codec,
804 spec->multiout.share_spdif = 1;
806 if (spec->extra_dig_out_nid) {
807 err = snd_hda_create_spdif_out_ctls(codec,
808 spec->extra_dig_out_nid);
813 if (spec->dig_in_nid) {
814 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
821 static int via_build_pcms(struct hda_codec *codec)
823 struct via_spec *spec = codec->spec;
824 struct hda_pcm *info = spec->pcm_rec;
827 codec->pcm_info = info;
829 info->name = spec->stream_name_analog;
830 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
831 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
832 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
833 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
835 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
836 spec->multiout.max_channels;
838 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
841 info->name = spec->stream_name_digital;
842 info->pcm_type = HDA_PCM_TYPE_SPDIF;
843 if (spec->multiout.dig_out_nid) {
844 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
845 *(spec->stream_digital_playback);
846 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
847 spec->multiout.dig_out_nid;
849 if (spec->dig_in_nid) {
850 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
851 *(spec->stream_digital_capture);
852 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
857 if (spec->extra_dig_out_nid) {
860 info->name = spec->stream_name_digital;
861 info->pcm_type = HDA_PCM_TYPE_HDMI;
862 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
863 *(spec->stream_extra_digital_playback);
864 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
865 spec->extra_dig_out_nid;
871 static void via_free(struct hda_codec *codec)
873 struct via_spec *spec = codec->spec;
879 if (spec->kctl_alloc) {
880 for (i = 0; i < spec->num_kctl_used; i++)
881 kfree(spec->kctl_alloc[i].name);
882 kfree(spec->kctl_alloc);
888 /* mute internal speaker if HP is plugged */
889 static void via_hp_automute(struct hda_codec *codec)
891 unsigned int present;
892 struct via_spec *spec = codec->spec;
894 present = snd_hda_codec_read(codec, spec->autocfg.hp_pins[0], 0,
895 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
896 snd_hda_codec_amp_stereo(codec, spec->autocfg.line_out_pins[0],
897 HDA_OUTPUT, 0, HDA_AMP_MUTE,
898 present ? HDA_AMP_MUTE : 0);
901 static void via_gpio_control(struct hda_codec *codec)
903 unsigned int gpio_data;
904 unsigned int vol_counter;
906 unsigned int master_vol;
908 struct via_spec *spec = codec->spec;
910 gpio_data = snd_hda_codec_read(codec, codec->afg, 0,
911 AC_VERB_GET_GPIO_DATA, 0) & 0x03;
913 vol_counter = (snd_hda_codec_read(codec, codec->afg, 0,
914 0xF84, 0) & 0x3F0000) >> 16;
916 vol = vol_counter & 0x1F;
917 master_vol = snd_hda_codec_read(codec, 0x1A, 0,
918 AC_VERB_GET_AMP_GAIN_MUTE,
921 if (gpio_data == 0x02) {
922 /* unmute line out */
923 snd_hda_codec_amp_stereo(codec, spec->autocfg.line_out_pins[0],
924 HDA_OUTPUT, 0, HDA_AMP_MUTE, 0);
926 if (vol_counter & 0x20) {
927 /* decrease volume */
928 if (vol > master_vol)
930 snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT,
934 /* increase volume */
935 snd_hda_codec_amp_stereo(codec, 0x1A, HDA_INPUT, 0,
937 ((master_vol+vol) > 0x2A) ? 0x2A :
940 } else if (!(gpio_data & 0x02)) {
942 snd_hda_codec_amp_stereo(codec,
943 spec->autocfg.line_out_pins[0],
944 HDA_OUTPUT, 0, HDA_AMP_MUTE,
949 /* unsolicited event for jack sensing */
950 static void via_unsol_event(struct hda_codec *codec,
954 if (res == VIA_HP_EVENT)
955 via_hp_automute(codec);
956 else if (res == VIA_GPIO_EVENT)
957 via_gpio_control(codec);
960 static int via_init(struct hda_codec *codec)
962 struct via_spec *spec = codec->spec;
964 for (i = 0; i < spec->num_iverbs; i++)
965 snd_hda_sequence_write(codec, spec->init_verbs[i]);
967 /* Lydia Add for EAPD enable */
968 if (!spec->dig_in_nid) { /* No Digital In connection */
969 if (IS_VT1708_VENDORID(codec->vendor_id)) {
970 snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
971 AC_VERB_SET_PIN_WIDGET_CONTROL,
973 snd_hda_codec_write(codec, VT1708_DIGIN_PIN, 0,
974 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
975 } else if (IS_VT1709_10CH_VENDORID(codec->vendor_id) ||
976 IS_VT1709_6CH_VENDORID(codec->vendor_id)) {
977 snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
978 AC_VERB_SET_PIN_WIDGET_CONTROL,
980 snd_hda_codec_write(codec, VT1709_DIGIN_PIN, 0,
981 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
982 } else if (IS_VT1708B_8CH_VENDORID(codec->vendor_id) ||
983 IS_VT1708B_4CH_VENDORID(codec->vendor_id)) {
984 snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
985 AC_VERB_SET_PIN_WIDGET_CONTROL,
987 snd_hda_codec_write(codec, VT1708B_DIGIN_PIN, 0,
988 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
990 } else /* enable SPDIF-input pin */
991 snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0,
992 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
997 #ifdef CONFIG_SND_HDA_POWER_SAVE
998 static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
1000 struct via_spec *spec = codec->spec;
1001 return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
1007 static struct hda_codec_ops via_patch_ops = {
1008 .build_controls = via_build_controls,
1009 .build_pcms = via_build_pcms,
1012 #ifdef CONFIG_SND_HDA_POWER_SAVE
1013 .check_power_status = via_check_power_status,
1017 /* fill in the dac_nids table from the parsed pin configuration */
1018 static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
1019 const struct auto_pin_cfg *cfg)
1024 spec->multiout.num_dacs = cfg->line_outs;
1026 spec->multiout.dac_nids = spec->private_dac_nids;
1028 for(i = 0; i < 4; i++) {
1029 nid = cfg->line_out_pins[i];
1031 /* config dac list */
1033 case AUTO_SEQ_FRONT:
1034 spec->multiout.dac_nids[i] = 0x10;
1036 case AUTO_SEQ_CENLFE:
1037 spec->multiout.dac_nids[i] = 0x12;
1039 case AUTO_SEQ_SURROUND:
1040 spec->multiout.dac_nids[i] = 0x11;
1043 spec->multiout.dac_nids[i] = 0x13;
1052 /* add playback controls from the parsed DAC table */
1053 static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
1054 const struct auto_pin_cfg *cfg)
1057 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1058 hda_nid_t nid, nid_vol = 0;
1061 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1062 nid = cfg->line_out_pins[i];
1067 if (i != AUTO_SEQ_FRONT)
1070 if (i == AUTO_SEQ_CENLFE) {
1072 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1073 "Center Playback Volume",
1074 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1078 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1079 "LFE Playback Volume",
1080 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1084 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1085 "Center Playback Switch",
1086 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
1090 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1091 "LFE Playback Switch",
1092 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
1096 } else if (i == AUTO_SEQ_FRONT){
1097 /* add control to mixer index 0 */
1098 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1099 "Master Front Playback Volume",
1100 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
1104 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1105 "Master Front Playback Switch",
1106 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
1111 /* add control to PW3 */
1112 sprintf(name, "%s Playback Volume", chname[i]);
1113 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1114 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1118 sprintf(name, "%s Playback Switch", chname[i]);
1119 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1120 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1125 sprintf(name, "%s Playback Volume", chname[i]);
1126 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1127 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1131 sprintf(name, "%s Playback Switch", chname[i]);
1132 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1133 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
1143 static void create_hp_imux(struct via_spec *spec)
1146 struct hda_input_mux *imux = &spec->private_imux[1];
1147 static const char *texts[] = { "OFF", "ON", NULL};
1149 /* for hp mode select */
1151 while (texts[i] != NULL) {
1152 imux->items[imux->num_items].label = texts[i];
1153 imux->items[imux->num_items].index = i;
1158 spec->hp_mux = &spec->private_imux[1];
1161 static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1168 spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
1170 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1171 "Headphone Playback Volume",
1172 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1175 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1176 "Headphone Playback Switch",
1177 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1181 create_hp_imux(spec);
1186 /* create playback/capture controls for input pins */
1187 static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
1188 const struct auto_pin_cfg *cfg)
1190 static char *labels[] = {
1191 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1193 struct hda_input_mux *imux = &spec->private_imux[0];
1194 int i, err, idx = 0;
1196 /* for internal loopback recording select */
1197 imux->items[imux->num_items].label = "Stereo Mixer";
1198 imux->items[imux->num_items].index = idx;
1201 for (i = 0; i < AUTO_PIN_LAST; i++) {
1202 if (!cfg->input_pins[i])
1205 switch (cfg->input_pins[i]) {
1206 case 0x1d: /* Mic */
1210 case 0x1e: /* Line In */
1214 case 0x21: /* Front Mic */
1222 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1226 imux->items[imux->num_items].label = labels[i];
1227 imux->items[imux->num_items].index = idx;
1233 #ifdef CONFIG_SND_HDA_POWER_SAVE
1234 static struct hda_amp_list vt1708_loopbacks[] = {
1235 { 0x17, HDA_INPUT, 1 },
1236 { 0x17, HDA_INPUT, 2 },
1237 { 0x17, HDA_INPUT, 3 },
1238 { 0x17, HDA_INPUT, 4 },
1243 static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
1245 unsigned int def_conf;
1246 unsigned char seqassoc;
1248 def_conf = snd_hda_codec_read(codec, nid, 0,
1249 AC_VERB_GET_CONFIG_DEFAULT, 0);
1250 seqassoc = (unsigned char) get_defcfg_association(def_conf);
1251 seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
1252 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) {
1253 if (seqassoc == 0xff) {
1254 def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
1255 snd_hda_codec_write(codec, nid, 0,
1256 AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
1264 static int vt1708_parse_auto_config(struct hda_codec *codec)
1266 struct via_spec *spec = codec->spec;
1269 /* Add HP and CD pin config connect bit re-config action */
1270 vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
1271 vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
1273 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1276 err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
1279 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1280 return 0; /* can't find valid BIOS pin config */
1282 err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
1285 err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1288 err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
1292 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1294 if (spec->autocfg.dig_out_pin)
1295 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
1296 if (spec->autocfg.dig_in_pin)
1297 spec->dig_in_nid = VT1708_DIGIN_NID;
1299 if (spec->kctl_alloc)
1300 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1302 spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs;
1304 spec->input_mux = &spec->private_imux[0];
1306 spec->mixers[spec->num_mixers++] = via_hp_mixer;
1311 /* init callback for auto-configuration model -- overriding the default init */
1312 static int via_auto_init(struct hda_codec *codec)
1315 via_auto_init_multi_out(codec);
1316 via_auto_init_hp_out(codec);
1317 via_auto_init_analog_input(codec);
1321 static int patch_vt1708(struct hda_codec *codec)
1323 struct via_spec *spec;
1326 /* create a codec specific record */
1327 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1333 /* automatic parse from the BIOS config */
1334 err = vt1708_parse_auto_config(codec);
1339 printk(KERN_INFO "hda_codec: Cannot set up configuration "
1340 "from BIOS. Using genenic mode...\n");
1344 spec->stream_name_analog = "VT1708 Analog";
1345 spec->stream_analog_playback = &vt1708_pcm_analog_playback;
1346 /* disable 32bit format on VT1708 */
1347 if (codec->vendor_id == 0x11061708)
1348 spec->stream_analog_playback = &vt1708_pcm_analog_s16_playback;
1349 spec->stream_analog_capture = &vt1708_pcm_analog_capture;
1351 spec->stream_name_digital = "VT1708 Digital";
1352 spec->stream_digital_playback = &vt1708_pcm_digital_playback;
1353 spec->stream_digital_capture = &vt1708_pcm_digital_capture;
1356 if (!spec->adc_nids && spec->input_mux) {
1357 spec->adc_nids = vt1708_adc_nids;
1358 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
1359 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
1363 codec->patch_ops = via_patch_ops;
1365 codec->patch_ops.init = via_auto_init;
1366 #ifdef CONFIG_SND_HDA_POWER_SAVE
1367 spec->loopback.amplist = vt1708_loopbacks;
1373 /* capture mixer elements */
1374 static struct snd_kcontrol_new vt1709_capture_mixer[] = {
1375 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
1376 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
1377 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
1378 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
1379 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
1380 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
1382 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1383 /* The multiple "Capture Source" controls confuse alsamixer
1384 * So call somewhat different..
1386 /* .name = "Capture Source", */
1387 .name = "Input Source",
1389 .info = via_mux_enum_info,
1390 .get = via_mux_enum_get,
1391 .put = via_mux_enum_put,
1396 static struct hda_verb vt1709_uniwill_init_verbs[] = {
1397 {0x20, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
1402 * generic initialization of ADC, input mixers and output mixers
1404 static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
1406 * Unmute ADC0-2 and set the default input to mic-in
1408 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1409 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1410 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1413 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1416 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1417 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1418 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1419 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1420 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1421 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1424 * Set up output selector (0x1a, 0x1b, 0x29)
1426 /* set vol=0 to output mixers */
1427 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1428 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1429 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1432 * Unmute PW3 and PW4
1434 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1435 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1437 /* Set input of PW4 as AOW4 */
1438 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
1439 /* PW9 Output enable */
1440 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1444 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
1448 .nid = 0x10, /* NID to query formats and rates */
1450 .open = via_playback_pcm_open,
1451 .prepare = via_playback_pcm_prepare,
1452 .cleanup = via_playback_pcm_cleanup
1456 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
1460 .nid = 0x10, /* NID to query formats and rates */
1462 .open = via_playback_pcm_open,
1463 .prepare = via_playback_pcm_prepare,
1464 .cleanup = via_playback_pcm_cleanup
1468 static struct hda_pcm_stream vt1709_pcm_analog_capture = {
1472 .nid = 0x14, /* NID to query formats and rates */
1474 .prepare = via_capture_pcm_prepare,
1475 .cleanup = via_capture_pcm_cleanup
1479 static struct hda_pcm_stream vt1709_pcm_digital_playback = {
1483 /* NID is set in via_build_pcms */
1485 .open = via_dig_playback_pcm_open,
1486 .close = via_dig_playback_pcm_close
1490 static struct hda_pcm_stream vt1709_pcm_digital_capture = {
1496 static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
1497 const struct auto_pin_cfg *cfg)
1502 if (cfg->line_outs == 4) /* 10 channels */
1503 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
1504 else if (cfg->line_outs == 3) /* 6 channels */
1505 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
1507 spec->multiout.dac_nids = spec->private_dac_nids;
1509 if (cfg->line_outs == 4) { /* 10 channels */
1510 for (i = 0; i < cfg->line_outs; i++) {
1511 nid = cfg->line_out_pins[i];
1513 /* config dac list */
1515 case AUTO_SEQ_FRONT:
1517 spec->multiout.dac_nids[i] = 0x10;
1519 case AUTO_SEQ_CENLFE:
1521 spec->multiout.dac_nids[i] = 0x12;
1523 case AUTO_SEQ_SURROUND:
1525 spec->multiout.dac_nids[i] = 0x11;
1529 spec->multiout.dac_nids[i] = 0x27;
1536 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1538 } else if (cfg->line_outs == 3) { /* 6 channels */
1539 for(i = 0; i < cfg->line_outs; i++) {
1540 nid = cfg->line_out_pins[i];
1542 /* config dac list */
1544 case AUTO_SEQ_FRONT:
1546 spec->multiout.dac_nids[i] = 0x10;
1548 case AUTO_SEQ_CENLFE:
1550 spec->multiout.dac_nids[i] = 0x12;
1552 case AUTO_SEQ_SURROUND:
1554 spec->multiout.dac_nids[i] = 0x11;
1566 /* add playback controls from the parsed DAC table */
1567 static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1568 const struct auto_pin_cfg *cfg)
1571 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1575 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1576 nid = cfg->line_out_pins[i];
1581 if (i == AUTO_SEQ_CENLFE) {
1583 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1584 "Center Playback Volume",
1585 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1589 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1590 "LFE Playback Volume",
1591 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1595 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1596 "Center Playback Switch",
1597 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1601 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1602 "LFE Playback Switch",
1603 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1607 } else if (i == AUTO_SEQ_FRONT){
1608 /* add control to mixer index 0 */
1609 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1610 "Master Front Playback Volume",
1611 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1615 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1616 "Master Front Playback Switch",
1617 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1622 /* add control to PW3 */
1623 sprintf(name, "%s Playback Volume", chname[i]);
1624 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1625 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1629 sprintf(name, "%s Playback Switch", chname[i]);
1630 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1631 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
1635 } else if (i == AUTO_SEQ_SURROUND) {
1636 sprintf(name, "%s Playback Volume", chname[i]);
1637 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1638 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1642 sprintf(name, "%s Playback Switch", chname[i]);
1643 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1644 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1648 } else if (i == AUTO_SEQ_SIDE) {
1649 sprintf(name, "%s Playback Volume", chname[i]);
1650 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1651 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1655 sprintf(name, "%s Playback Switch", chname[i]);
1656 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1657 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1667 static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1674 if (spec->multiout.num_dacs == 5) /* 10 channels */
1675 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1676 else if (spec->multiout.num_dacs == 3) /* 6 channels */
1677 spec->multiout.hp_nid = 0;
1679 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1680 "Headphone Playback Volume",
1681 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1684 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1685 "Headphone Playback Switch",
1686 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1693 /* create playback/capture controls for input pins */
1694 static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1695 const struct auto_pin_cfg *cfg)
1697 static char *labels[] = {
1698 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1700 struct hda_input_mux *imux = &spec->private_imux[0];
1701 int i, err, idx = 0;
1703 /* for internal loopback recording select */
1704 imux->items[imux->num_items].label = "Stereo Mixer";
1705 imux->items[imux->num_items].index = idx;
1708 for (i = 0; i < AUTO_PIN_LAST; i++) {
1709 if (!cfg->input_pins[i])
1712 switch (cfg->input_pins[i]) {
1713 case 0x1d: /* Mic */
1717 case 0x1e: /* Line In */
1721 case 0x21: /* Front Mic */
1729 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1733 imux->items[imux->num_items].label = labels[i];
1734 imux->items[imux->num_items].index = idx;
1740 static int vt1709_parse_auto_config(struct hda_codec *codec)
1742 struct via_spec *spec = codec->spec;
1745 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1748 err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1751 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1752 return 0; /* can't find valid BIOS pin config */
1754 err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1757 err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1760 err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1764 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1766 if (spec->autocfg.dig_out_pin)
1767 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1768 if (spec->autocfg.dig_in_pin)
1769 spec->dig_in_nid = VT1709_DIGIN_NID;
1771 if (spec->kctl_alloc)
1772 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1774 spec->input_mux = &spec->private_imux[0];
1779 #ifdef CONFIG_SND_HDA_POWER_SAVE
1780 static struct hda_amp_list vt1709_loopbacks[] = {
1781 { 0x18, HDA_INPUT, 1 },
1782 { 0x18, HDA_INPUT, 2 },
1783 { 0x18, HDA_INPUT, 3 },
1784 { 0x18, HDA_INPUT, 4 },
1789 static int patch_vt1709_10ch(struct hda_codec *codec)
1791 struct via_spec *spec;
1794 /* create a codec specific record */
1795 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1801 err = vt1709_parse_auto_config(codec);
1806 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1807 "Using genenic mode...\n");
1810 spec->init_verbs[spec->num_iverbs++] = vt1709_10ch_volume_init_verbs;
1811 spec->init_verbs[spec->num_iverbs++] = vt1709_uniwill_init_verbs;
1813 spec->stream_name_analog = "VT1709 Analog";
1814 spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1815 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1817 spec->stream_name_digital = "VT1709 Digital";
1818 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1819 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1822 if (!spec->adc_nids && spec->input_mux) {
1823 spec->adc_nids = vt1709_adc_nids;
1824 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1825 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1829 codec->patch_ops = via_patch_ops;
1831 codec->patch_ops.init = via_auto_init;
1832 codec->patch_ops.unsol_event = via_unsol_event;
1833 #ifdef CONFIG_SND_HDA_POWER_SAVE
1834 spec->loopback.amplist = vt1709_loopbacks;
1840 * generic initialization of ADC, input mixers and output mixers
1842 static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1844 * Unmute ADC0-2 and set the default input to mic-in
1846 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1847 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1848 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1851 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1854 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1855 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1856 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1857 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1858 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1859 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1862 * Set up output selector (0x1a, 0x1b, 0x29)
1864 /* set vol=0 to output mixers */
1865 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1866 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1867 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1870 * Unmute PW3 and PW4
1872 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1873 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1875 /* Set input of PW4 as MW0 */
1876 {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1877 /* PW9 Output enable */
1878 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1882 static int patch_vt1709_6ch(struct hda_codec *codec)
1884 struct via_spec *spec;
1887 /* create a codec specific record */
1888 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1894 err = vt1709_parse_auto_config(codec);
1899 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1900 "Using genenic mode...\n");
1903 spec->init_verbs[spec->num_iverbs++] = vt1709_6ch_volume_init_verbs;
1904 spec->init_verbs[spec->num_iverbs++] = vt1709_uniwill_init_verbs;
1906 spec->stream_name_analog = "VT1709 Analog";
1907 spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1908 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1910 spec->stream_name_digital = "VT1709 Digital";
1911 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1912 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1915 if (!spec->adc_nids && spec->input_mux) {
1916 spec->adc_nids = vt1709_adc_nids;
1917 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1918 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1922 codec->patch_ops = via_patch_ops;
1924 codec->patch_ops.init = via_auto_init;
1925 codec->patch_ops.unsol_event = via_unsol_event;
1926 #ifdef CONFIG_SND_HDA_POWER_SAVE
1927 spec->loopback.amplist = vt1709_loopbacks;
1932 /* capture mixer elements */
1933 static struct snd_kcontrol_new vt1708B_capture_mixer[] = {
1934 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
1935 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
1936 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
1937 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
1939 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1940 /* The multiple "Capture Source" controls confuse alsamixer
1941 * So call somewhat different..
1943 /* .name = "Capture Source", */
1944 .name = "Input Source",
1946 .info = via_mux_enum_info,
1947 .get = via_mux_enum_get,
1948 .put = via_mux_enum_put,
1953 * generic initialization of ADC, input mixers and output mixers
1955 static struct hda_verb vt1708B_8ch_volume_init_verbs[] = {
1957 * Unmute ADC0-1 and set the default input to mic-in
1959 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1960 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1963 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1966 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1967 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1968 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1969 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1970 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1971 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1974 * Set up output mixers
1976 /* set vol=0 to output mixers */
1977 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1978 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1979 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1981 /* Setup default input to PW4 */
1982 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x1},
1983 /* PW9 Output enable */
1984 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1985 /* PW10 Input enable */
1986 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
1990 static struct hda_verb vt1708B_4ch_volume_init_verbs[] = {
1992 * Unmute ADC0-1 and set the default input to mic-in
1994 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1995 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1998 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
2001 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
2002 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2003 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2004 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2005 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
2006 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
2009 * Set up output mixers
2011 /* set vol=0 to output mixers */
2012 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2013 {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2014 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
2016 /* Setup default input of PW4 to MW0 */
2017 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
2018 /* PW9 Output enable */
2019 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2020 /* PW10 Input enable */
2021 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
2025 static struct hda_verb vt1708B_uniwill_init_verbs[] = {
2026 {0x1D, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
2030 static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback = {
2034 .nid = 0x10, /* NID to query formats and rates */
2036 .open = via_playback_pcm_open,
2037 .prepare = via_playback_multi_pcm_prepare,
2038 .cleanup = via_playback_multi_pcm_cleanup
2042 static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback = {
2046 .nid = 0x10, /* NID to query formats and rates */
2048 .open = via_playback_pcm_open,
2049 .prepare = via_playback_multi_pcm_prepare,
2050 .cleanup = via_playback_multi_pcm_cleanup
2054 static struct hda_pcm_stream vt1708B_pcm_analog_capture = {
2058 .nid = 0x13, /* NID to query formats and rates */
2060 .prepare = via_capture_pcm_prepare,
2061 .cleanup = via_capture_pcm_cleanup
2065 static struct hda_pcm_stream vt1708B_pcm_digital_playback = {
2069 /* NID is set in via_build_pcms */
2071 .open = via_dig_playback_pcm_open,
2072 .close = via_dig_playback_pcm_close,
2073 .prepare = via_dig_playback_pcm_prepare
2077 static struct hda_pcm_stream vt1708B_pcm_digital_capture = {
2083 /* fill in the dac_nids table from the parsed pin configuration */
2084 static int vt1708B_auto_fill_dac_nids(struct via_spec *spec,
2085 const struct auto_pin_cfg *cfg)
2090 spec->multiout.num_dacs = cfg->line_outs;
2092 spec->multiout.dac_nids = spec->private_dac_nids;
2094 for (i = 0; i < 4; i++) {
2095 nid = cfg->line_out_pins[i];
2097 /* config dac list */
2099 case AUTO_SEQ_FRONT:
2100 spec->multiout.dac_nids[i] = 0x10;
2102 case AUTO_SEQ_CENLFE:
2103 spec->multiout.dac_nids[i] = 0x24;
2105 case AUTO_SEQ_SURROUND:
2106 spec->multiout.dac_nids[i] = 0x11;
2109 spec->multiout.dac_nids[i] = 0x25;
2118 /* add playback controls from the parsed DAC table */
2119 static int vt1708B_auto_create_multi_out_ctls(struct via_spec *spec,
2120 const struct auto_pin_cfg *cfg)
2123 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
2124 hda_nid_t nid_vols[] = {0x16, 0x18, 0x26, 0x27};
2125 hda_nid_t nid, nid_vol = 0;
2128 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
2129 nid = cfg->line_out_pins[i];
2134 nid_vol = nid_vols[i];
2136 if (i == AUTO_SEQ_CENLFE) {
2138 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2139 "Center Playback Volume",
2140 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
2144 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2145 "LFE Playback Volume",
2146 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
2150 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2151 "Center Playback Switch",
2152 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
2156 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2157 "LFE Playback Switch",
2158 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
2162 } else if (i == AUTO_SEQ_FRONT) {
2163 /* add control to mixer index 0 */
2164 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2165 "Master Front Playback Volume",
2166 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
2170 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2171 "Master Front Playback Switch",
2172 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
2177 /* add control to PW3 */
2178 sprintf(name, "%s Playback Volume", chname[i]);
2179 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
2180 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
2184 sprintf(name, "%s Playback Switch", chname[i]);
2185 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
2186 HDA_COMPOSE_AMP_VAL(nid, 3, 0,
2191 sprintf(name, "%s Playback Volume", chname[i]);
2192 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
2193 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
2197 sprintf(name, "%s Playback Switch", chname[i]);
2198 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
2199 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
2209 static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
2216 spec->multiout.hp_nid = VT1708B_HP_NID; /* AOW3 */
2218 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2219 "Headphone Playback Volume",
2220 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
2223 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2224 "Headphone Playback Switch",
2225 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
2229 create_hp_imux(spec);
2234 /* create playback/capture controls for input pins */
2235 static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec,
2236 const struct auto_pin_cfg *cfg)
2238 static char *labels[] = {
2239 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
2241 struct hda_input_mux *imux = &spec->private_imux[0];
2242 int i, err, idx = 0;
2244 /* for internal loopback recording select */
2245 imux->items[imux->num_items].label = "Stereo Mixer";
2246 imux->items[imux->num_items].index = idx;
2249 for (i = 0; i < AUTO_PIN_LAST; i++) {
2250 if (!cfg->input_pins[i])
2253 switch (cfg->input_pins[i]) {
2254 case 0x1a: /* Mic */
2258 case 0x1b: /* Line In */
2262 case 0x1e: /* Front Mic */
2270 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
2274 imux->items[imux->num_items].label = labels[i];
2275 imux->items[imux->num_items].index = idx;
2281 static int vt1708B_parse_auto_config(struct hda_codec *codec)
2283 struct via_spec *spec = codec->spec;
2286 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
2289 err = vt1708B_auto_fill_dac_nids(spec, &spec->autocfg);
2292 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
2293 return 0; /* can't find valid BIOS pin config */
2295 err = vt1708B_auto_create_multi_out_ctls(spec, &spec->autocfg);
2298 err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
2301 err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg);
2305 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2307 if (spec->autocfg.dig_out_pin)
2308 spec->multiout.dig_out_nid = VT1708B_DIGOUT_NID;
2309 if (spec->autocfg.dig_in_pin)
2310 spec->dig_in_nid = VT1708B_DIGIN_NID;
2312 if (spec->kctl_alloc)
2313 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2315 spec->input_mux = &spec->private_imux[0];
2317 spec->mixers[spec->num_mixers++] = via_hp_mixer;
2322 #ifdef CONFIG_SND_HDA_POWER_SAVE
2323 static struct hda_amp_list vt1708B_loopbacks[] = {
2324 { 0x16, HDA_INPUT, 1 },
2325 { 0x16, HDA_INPUT, 2 },
2326 { 0x16, HDA_INPUT, 3 },
2327 { 0x16, HDA_INPUT, 4 },
2332 static int patch_vt1708B_8ch(struct hda_codec *codec)
2334 struct via_spec *spec;
2337 /* create a codec specific record */
2338 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2344 /* automatic parse from the BIOS config */
2345 err = vt1708B_parse_auto_config(codec);
2350 printk(KERN_INFO "hda_codec: Cannot set up configuration "
2351 "from BIOS. Using genenic mode...\n");
2354 spec->init_verbs[spec->num_iverbs++] = vt1708B_8ch_volume_init_verbs;
2355 spec->init_verbs[spec->num_iverbs++] = vt1708B_uniwill_init_verbs;
2357 spec->stream_name_analog = "VT1708B Analog";
2358 spec->stream_analog_playback = &vt1708B_8ch_pcm_analog_playback;
2359 spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
2361 spec->stream_name_digital = "VT1708B Digital";
2362 spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
2363 spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
2365 if (!spec->adc_nids && spec->input_mux) {
2366 spec->adc_nids = vt1708B_adc_nids;
2367 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
2368 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
2372 codec->patch_ops = via_patch_ops;
2374 codec->patch_ops.init = via_auto_init;
2375 codec->patch_ops.unsol_event = via_unsol_event;
2376 #ifdef CONFIG_SND_HDA_POWER_SAVE
2377 spec->loopback.amplist = vt1708B_loopbacks;
2383 static int patch_vt1708B_4ch(struct hda_codec *codec)
2385 struct via_spec *spec;
2388 /* create a codec specific record */
2389 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2395 /* automatic parse from the BIOS config */
2396 err = vt1708B_parse_auto_config(codec);
2401 printk(KERN_INFO "hda_codec: Cannot set up configuration "
2402 "from BIOS. Using genenic mode...\n");
2405 spec->init_verbs[spec->num_iverbs++] = vt1708B_4ch_volume_init_verbs;
2406 spec->init_verbs[spec->num_iverbs++] = vt1708B_uniwill_init_verbs;
2408 spec->stream_name_analog = "VT1708B Analog";
2409 spec->stream_analog_playback = &vt1708B_4ch_pcm_analog_playback;
2410 spec->stream_analog_capture = &vt1708B_pcm_analog_capture;
2412 spec->stream_name_digital = "VT1708B Digital";
2413 spec->stream_digital_playback = &vt1708B_pcm_digital_playback;
2414 spec->stream_digital_capture = &vt1708B_pcm_digital_capture;
2416 if (!spec->adc_nids && spec->input_mux) {
2417 spec->adc_nids = vt1708B_adc_nids;
2418 spec->num_adc_nids = ARRAY_SIZE(vt1708B_adc_nids);
2419 spec->mixers[spec->num_mixers] = vt1708B_capture_mixer;
2423 codec->patch_ops = via_patch_ops;
2425 codec->patch_ops.init = via_auto_init;
2426 codec->patch_ops.unsol_event = via_unsol_event;
2427 #ifdef CONFIG_SND_HDA_POWER_SAVE
2428 spec->loopback.amplist = vt1708B_loopbacks;
2434 /* Patch for VT1708S */
2436 /* capture mixer elements */
2437 static struct snd_kcontrol_new vt1708S_capture_mixer[] = {
2438 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT),
2439 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT),
2440 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT),
2441 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT),
2442 HDA_CODEC_VOLUME("Mic Boost", 0x1A, 0x0, HDA_INPUT),
2443 HDA_CODEC_VOLUME("Front Mic Boost", 0x1E, 0x0, HDA_INPUT),
2445 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2446 /* The multiple "Capture Source" controls confuse alsamixer
2447 * So call somewhat different..
2449 /* .name = "Capture Source", */
2450 .name = "Input Source",
2452 .info = via_mux_enum_info,
2453 .get = via_mux_enum_get,
2454 .put = via_mux_enum_put,
2459 static struct hda_verb vt1708S_volume_init_verbs[] = {
2460 /* Unmute ADC0-1 and set the default input to mic-in */
2461 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2462 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2464 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the
2465 * analog-loopback mixer widget */
2466 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
2467 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2468 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2469 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2470 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
2471 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
2473 /* Setup default input of PW4 to MW0 */
2474 {0x1d, AC_VERB_SET_CONNECT_SEL, 0x0},
2475 /* PW9 Output enable */
2476 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2480 static struct hda_verb vt1708S_uniwill_init_verbs[] = {
2481 {0x1D, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
2485 static struct hda_pcm_stream vt1708S_pcm_analog_playback = {
2489 .nid = 0x10, /* NID to query formats and rates */
2491 .open = via_playback_pcm_open,
2492 .prepare = via_playback_pcm_prepare,
2493 .cleanup = via_playback_pcm_cleanup
2497 static struct hda_pcm_stream vt1708S_pcm_analog_capture = {
2501 .nid = 0x13, /* NID to query formats and rates */
2503 .prepare = via_capture_pcm_prepare,
2504 .cleanup = via_capture_pcm_cleanup
2508 static struct hda_pcm_stream vt1708S_pcm_digital_playback = {
2512 /* NID is set in via_build_pcms */
2514 .open = via_dig_playback_pcm_open,
2515 .close = via_dig_playback_pcm_close,
2516 .prepare = via_dig_playback_pcm_prepare
2520 static struct hda_pcm_stream vt1708S_pcm_extra_digital_playback = {
2524 /* NID is set in via_build_pcms */
2526 .prepare = via_extra_dig_playback_pcm_prepare
2530 /* fill in the dac_nids table from the parsed pin configuration */
2531 static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
2532 const struct auto_pin_cfg *cfg)
2537 spec->multiout.num_dacs = cfg->line_outs;
2539 spec->multiout.dac_nids = spec->private_dac_nids;
2541 for (i = 0; i < 4; i++) {
2542 nid = cfg->line_out_pins[i];
2544 /* config dac list */
2546 case AUTO_SEQ_FRONT:
2547 spec->multiout.dac_nids[i] = 0x10;
2549 case AUTO_SEQ_CENLFE:
2550 spec->multiout.dac_nids[i] = 0x24;
2552 case AUTO_SEQ_SURROUND:
2553 spec->multiout.dac_nids[i] = 0x11;
2556 spec->multiout.dac_nids[i] = 0x25;
2565 /* add playback controls from the parsed DAC table */
2566 static int vt1708S_auto_create_multi_out_ctls(struct via_spec *spec,
2567 const struct auto_pin_cfg *cfg)
2570 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
2571 hda_nid_t nid_vols[] = {0x10, 0x11, 0x24, 0x25};
2572 hda_nid_t nid_mutes[] = {0x1C, 0x18, 0x26, 0x27};
2573 hda_nid_t nid, nid_vol, nid_mute;
2576 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
2577 nid = cfg->line_out_pins[i];
2582 nid_vol = nid_vols[i];
2583 nid_mute = nid_mutes[i];
2585 if (i == AUTO_SEQ_CENLFE) {
2587 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2588 "Center Playback Volume",
2589 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0,
2593 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2594 "LFE Playback Volume",
2595 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0,
2599 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2600 "Center Playback Switch",
2601 HDA_COMPOSE_AMP_VAL(nid_mute,
2606 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2607 "LFE Playback Switch",
2608 HDA_COMPOSE_AMP_VAL(nid_mute,
2613 } else if (i == AUTO_SEQ_FRONT) {
2614 /* add control to mixer index 0 */
2615 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2616 "Master Front Playback Volume",
2617 HDA_COMPOSE_AMP_VAL(0x16, 3, 0,
2621 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2622 "Master Front Playback Switch",
2623 HDA_COMPOSE_AMP_VAL(0x16, 3, 0,
2629 sprintf(name, "%s Playback Volume", chname[i]);
2630 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
2631 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
2635 sprintf(name, "%s Playback Switch", chname[i]);
2636 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
2637 HDA_COMPOSE_AMP_VAL(nid_mute,
2643 sprintf(name, "%s Playback Volume", chname[i]);
2644 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
2645 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0,
2649 sprintf(name, "%s Playback Switch", chname[i]);
2650 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
2651 HDA_COMPOSE_AMP_VAL(nid_mute,
2662 static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
2669 spec->multiout.hp_nid = VT1708S_HP_NID; /* AOW3 */
2671 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2672 "Headphone Playback Volume",
2673 HDA_COMPOSE_AMP_VAL(0x25, 3, 0, HDA_OUTPUT));
2677 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2678 "Headphone Playback Switch",
2679 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
2683 create_hp_imux(spec);
2688 /* create playback/capture controls for input pins */
2689 static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec,
2690 const struct auto_pin_cfg *cfg)
2692 static char *labels[] = {
2693 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
2695 struct hda_input_mux *imux = &spec->private_imux[0];
2696 int i, err, idx = 0;
2698 /* for internal loopback recording select */
2699 imux->items[imux->num_items].label = "Stereo Mixer";
2700 imux->items[imux->num_items].index = 5;
2703 for (i = 0; i < AUTO_PIN_LAST; i++) {
2704 if (!cfg->input_pins[i])
2707 switch (cfg->input_pins[i]) {
2708 case 0x1a: /* Mic */
2712 case 0x1b: /* Line In */
2716 case 0x1e: /* Front Mic */
2724 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
2728 imux->items[imux->num_items].label = labels[i];
2729 imux->items[imux->num_items].index = idx-1;
2735 static int vt1708S_parse_auto_config(struct hda_codec *codec)
2737 struct via_spec *spec = codec->spec;
2739 static hda_nid_t vt1708s_ignore[] = {0x21, 0};
2741 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
2745 err = vt1708S_auto_fill_dac_nids(spec, &spec->autocfg);
2748 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
2749 return 0; /* can't find valid BIOS pin config */
2751 err = vt1708S_auto_create_multi_out_ctls(spec, &spec->autocfg);
2754 err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
2757 err = vt1708S_auto_create_analog_input_ctls(spec, &spec->autocfg);
2761 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2763 if (spec->autocfg.dig_out_pin)
2764 spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID;
2766 spec->extra_dig_out_nid = 0x15;
2768 if (spec->kctl_alloc)
2769 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2771 spec->input_mux = &spec->private_imux[0];
2773 spec->mixers[spec->num_mixers++] = via_hp_mixer;
2778 #ifdef CONFIG_SND_HDA_POWER_SAVE
2779 static struct hda_amp_list vt1708S_loopbacks[] = {
2780 { 0x16, HDA_INPUT, 1 },
2781 { 0x16, HDA_INPUT, 2 },
2782 { 0x16, HDA_INPUT, 3 },
2783 { 0x16, HDA_INPUT, 4 },
2788 static int patch_vt1708S(struct hda_codec *codec)
2790 struct via_spec *spec;
2793 /* create a codec specific record */
2794 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2800 /* automatic parse from the BIOS config */
2801 err = vt1708S_parse_auto_config(codec);
2806 printk(KERN_INFO "hda_codec: Cannot set up configuration "
2807 "from BIOS. Using genenic mode...\n");
2810 spec->init_verbs[spec->num_iverbs++] = vt1708S_volume_init_verbs;
2811 spec->init_verbs[spec->num_iverbs++] = vt1708S_uniwill_init_verbs;
2813 spec->stream_name_analog = "VT1708S Analog";
2814 spec->stream_analog_playback = &vt1708S_pcm_analog_playback;
2815 spec->stream_analog_capture = &vt1708S_pcm_analog_capture;
2817 spec->stream_name_digital = "VT1708S Digital";
2818 spec->stream_digital_playback = &vt1708S_pcm_digital_playback;
2819 spec->stream_extra_digital_playback =
2820 &vt1708S_pcm_extra_digital_playback;
2822 if (!spec->adc_nids && spec->input_mux) {
2823 spec->adc_nids = vt1708S_adc_nids;
2824 spec->num_adc_nids = ARRAY_SIZE(vt1708S_adc_nids);
2825 spec->mixers[spec->num_mixers] = vt1708S_capture_mixer;
2829 codec->patch_ops = via_patch_ops;
2831 codec->patch_ops.init = via_auto_init;
2832 codec->patch_ops.unsol_event = via_unsol_event;
2833 #ifdef CONFIG_SND_HDA_POWER_SAVE
2834 spec->loopback.amplist = vt1708S_loopbacks;
2840 /* Patch for VT1702 */
2842 /* capture mixer elements */
2843 static struct snd_kcontrol_new vt1702_capture_mixer[] = {
2844 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_INPUT),
2845 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_INPUT),
2846 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x20, 0x0, HDA_INPUT),
2847 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x20, 0x0, HDA_INPUT),
2848 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x1F, 0x0, HDA_INPUT),
2849 HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x1F, 0x0, HDA_INPUT),
2850 HDA_CODEC_VOLUME("Digital Mic Boost Capture Volume", 0x1E, 0x0,
2853 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2854 /* The multiple "Capture Source" controls confuse alsamixer
2855 * So call somewhat different..
2857 /* .name = "Capture Source", */
2858 .name = "Input Source",
2860 .info = via_mux_enum_info,
2861 .get = via_mux_enum_get,
2862 .put = via_mux_enum_put,
2867 static struct hda_verb vt1702_volume_init_verbs[] = {
2869 * Unmute ADC0-1 and set the default input to mic-in
2871 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2872 {0x1F, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2873 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2876 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
2879 /* Amp Indices: Mic1 = 1, Line = 1, Mic2 = 3 */
2880 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2881 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
2882 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
2883 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
2884 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
2886 /* Setup default input of PW4 to MW0 */
2887 {0x17, AC_VERB_SET_CONNECT_SEL, 0x1},
2888 /* PW6 PW7 Output enable */
2889 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2890 {0x1C, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
2894 static struct hda_verb vt1702_uniwill_init_verbs[] = {
2895 {0x01, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_GPIO_EVENT},
2896 {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | VIA_HP_EVENT},
2900 static struct hda_pcm_stream vt1702_pcm_analog_playback = {
2904 .nid = 0x10, /* NID to query formats and rates */
2906 .open = via_playback_pcm_open,
2907 .prepare = via_playback_multi_pcm_prepare,
2908 .cleanup = via_playback_multi_pcm_cleanup
2912 static struct hda_pcm_stream vt1702_pcm_analog_capture = {
2916 .nid = 0x12, /* NID to query formats and rates */
2918 .prepare = via_capture_pcm_prepare,
2919 .cleanup = via_capture_pcm_cleanup
2923 static struct hda_pcm_stream vt1702_pcm_digital_playback = {
2927 /* NID is set in via_build_pcms */
2929 .open = via_dig_playback_pcm_open,
2930 .close = via_dig_playback_pcm_close,
2931 .prepare = via_dig_playback_pcm_prepare
2935 static struct hda_pcm_stream vt1702_pcm_extra_digital_playback = {
2939 /* NID is set in via_build_pcms */
2941 .prepare = via_extra_dig_playback_pcm_prepare
2945 /* fill in the dac_nids table from the parsed pin configuration */
2946 static int vt1702_auto_fill_dac_nids(struct via_spec *spec,
2947 const struct auto_pin_cfg *cfg)
2949 spec->multiout.num_dacs = 1;
2950 spec->multiout.dac_nids = spec->private_dac_nids;
2952 if (cfg->line_out_pins[0]) {
2953 /* config dac list */
2954 spec->multiout.dac_nids[0] = 0x10;
2960 /* add playback controls from the parsed DAC table */
2961 static int vt1702_auto_create_line_out_ctls(struct via_spec *spec,
2962 const struct auto_pin_cfg *cfg)
2966 if (!cfg->line_out_pins[0])
2969 /* add control to mixer index 0 */
2970 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2971 "Master Front Playback Volume",
2972 HDA_COMPOSE_AMP_VAL(0x1A, 3, 0, HDA_INPUT));
2975 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2976 "Master Front Playback Switch",
2977 HDA_COMPOSE_AMP_VAL(0x1A, 3, 0, HDA_INPUT));
2982 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
2983 "Front Playback Volume",
2984 HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT));
2987 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
2988 "Front Playback Switch",
2989 HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT));
2996 static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
3003 spec->multiout.hp_nid = 0x1D;
3005 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
3006 "Headphone Playback Volume",
3007 HDA_COMPOSE_AMP_VAL(0x1D, 3, 0, HDA_OUTPUT));
3011 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
3012 "Headphone Playback Switch",
3013 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
3017 create_hp_imux(spec);
3022 /* create playback/capture controls for input pins */
3023 static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec,
3024 const struct auto_pin_cfg *cfg)
3026 static char *labels[] = {
3027 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
3029 struct hda_input_mux *imux = &spec->private_imux[0];
3030 int i, err, idx = 0;
3032 /* for internal loopback recording select */
3033 imux->items[imux->num_items].label = "Stereo Mixer";
3034 imux->items[imux->num_items].index = 3;
3037 for (i = 0; i < AUTO_PIN_LAST; i++) {
3038 if (!cfg->input_pins[i])
3041 switch (cfg->input_pins[i]) {
3042 case 0x14: /* Mic */
3046 case 0x15: /* Line In */
3050 case 0x18: /* Front Mic */
3054 err = via_new_analog_input(spec, cfg->input_pins[i],
3055 labels[i], idx, 0x1A);
3058 imux->items[imux->num_items].label = labels[i];
3059 imux->items[imux->num_items].index = idx-1;
3065 static int vt1702_parse_auto_config(struct hda_codec *codec)
3067 struct via_spec *spec = codec->spec;
3069 static hda_nid_t vt1702_ignore[] = {0x1C, 0};
3071 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
3075 err = vt1702_auto_fill_dac_nids(spec, &spec->autocfg);
3078 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
3079 return 0; /* can't find valid BIOS pin config */
3081 err = vt1702_auto_create_line_out_ctls(spec, &spec->autocfg);
3084 err = vt1702_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
3087 err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg);
3091 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3093 if (spec->autocfg.dig_out_pin)
3094 spec->multiout.dig_out_nid = VT1702_DIGOUT_NID;
3096 spec->extra_dig_out_nid = 0x1B;
3098 if (spec->kctl_alloc)
3099 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
3101 spec->input_mux = &spec->private_imux[0];
3103 spec->mixers[spec->num_mixers++] = via_hp_mixer;
3108 #ifdef CONFIG_SND_HDA_POWER_SAVE
3109 static struct hda_amp_list vt1702_loopbacks[] = {
3110 { 0x1A, HDA_INPUT, 1 },
3111 { 0x1A, HDA_INPUT, 2 },
3112 { 0x1A, HDA_INPUT, 3 },
3113 { 0x1A, HDA_INPUT, 4 },
3118 static int patch_vt1702(struct hda_codec *codec)
3120 struct via_spec *spec;
3122 unsigned int response;
3123 unsigned char control;
3125 /* create a codec specific record */
3126 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3132 /* automatic parse from the BIOS config */
3133 err = vt1702_parse_auto_config(codec);
3138 printk(KERN_INFO "hda_codec: Cannot set up configuration "
3139 "from BIOS. Using genenic mode...\n");
3142 spec->init_verbs[spec->num_iverbs++] = vt1702_volume_init_verbs;
3143 spec->init_verbs[spec->num_iverbs++] = vt1702_uniwill_init_verbs;
3145 spec->stream_name_analog = "VT1702 Analog";
3146 spec->stream_analog_playback = &vt1702_pcm_analog_playback;
3147 spec->stream_analog_capture = &vt1702_pcm_analog_capture;
3149 spec->stream_name_digital = "VT1702 Digital";
3150 spec->stream_digital_playback = &vt1702_pcm_digital_playback;
3151 spec->stream_extra_digital_playback =
3152 &vt1702_pcm_extra_digital_playback;
3154 if (!spec->adc_nids && spec->input_mux) {
3155 spec->adc_nids = vt1702_adc_nids;
3156 spec->num_adc_nids = ARRAY_SIZE(vt1702_adc_nids);
3157 spec->mixers[spec->num_mixers] = vt1702_capture_mixer;
3161 codec->patch_ops = via_patch_ops;
3163 codec->patch_ops.init = via_auto_init;
3164 codec->patch_ops.unsol_event = via_unsol_event;
3165 #ifdef CONFIG_SND_HDA_POWER_SAVE
3166 spec->loopback.amplist = vt1702_loopbacks;
3170 response = snd_hda_codec_read(codec, codec->afg, 0, 0xF8C, 0);
3171 control = (unsigned char)(response & 0xff);
3173 snd_hda_codec_write(codec, codec->afg, 0, 0xF88, control);
3175 /* Enable GPIO 0&1 for volume&mute control */
3176 /* Enable GPIO 2 for DMIC-DATA */
3177 response = snd_hda_codec_read(codec, codec->afg, 0, 0xF84, 0);
3178 control = (unsigned char)((response >> 16) & 0x3f);
3179 snd_hda_codec_write(codec, codec->afg, 0, 0xF82, control);
3187 struct hda_codec_preset snd_hda_preset_via[] = {
3188 { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
3189 { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
3190 { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
3191 { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
3192 { .id = 0x1106E710, .name = "VIA VT1709 10-Ch",
3193 .patch = patch_vt1709_10ch},
3194 { .id = 0x1106E711, .name = "VIA VT1709 10-Ch",
3195 .patch = patch_vt1709_10ch},
3196 { .id = 0x1106E712, .name = "VIA VT1709 10-Ch",
3197 .patch = patch_vt1709_10ch},
3198 { .id = 0x1106E713, .name = "VIA VT1709 10-Ch",
3199 .patch = patch_vt1709_10ch},
3200 { .id = 0x1106E714, .name = "VIA VT1709 6-Ch",
3201 .patch = patch_vt1709_6ch},
3202 { .id = 0x1106E715, .name = "VIA VT1709 6-Ch",
3203 .patch = patch_vt1709_6ch},
3204 { .id = 0x1106E716, .name = "VIA VT1709 6-Ch",
3205 .patch = patch_vt1709_6ch},
3206 { .id = 0x1106E717, .name = "VIA VT1709 6-Ch",
3207 .patch = patch_vt1709_6ch},
3208 { .id = 0x1106E720, .name = "VIA VT1708B 8-Ch",
3209 .patch = patch_vt1708B_8ch},
3210 { .id = 0x1106E721, .name = "VIA VT1708B 8-Ch",
3211 .patch = patch_vt1708B_8ch},
3212 { .id = 0x1106E722, .name = "VIA VT1708B 8-Ch",
3213 .patch = patch_vt1708B_8ch},
3214 { .id = 0x1106E723, .name = "VIA VT1708B 8-Ch",
3215 .patch = patch_vt1708B_8ch},
3216 { .id = 0x1106E724, .name = "VIA VT1708B 4-Ch",
3217 .patch = patch_vt1708B_4ch},
3218 { .id = 0x1106E725, .name = "VIA VT1708B 4-Ch",
3219 .patch = patch_vt1708B_4ch},
3220 { .id = 0x1106E726, .name = "VIA VT1708B 4-Ch",
3221 .patch = patch_vt1708B_4ch},
3222 { .id = 0x1106E727, .name = "VIA VT1708B 4-Ch",
3223 .patch = patch_vt1708B_4ch},
3224 { .id = 0x11060397, .name = "VIA VT1708S",
3225 .patch = patch_vt1708S},
3226 { .id = 0x11061397, .name = "VIA VT1708S",
3227 .patch = patch_vt1708S},
3228 { .id = 0x11062397, .name = "VIA VT1708S",
3229 .patch = patch_vt1708S},
3230 { .id = 0x11063397, .name = "VIA VT1708S",
3231 .patch = patch_vt1708S},
3232 { .id = 0x11064397, .name = "VIA VT1708S",
3233 .patch = patch_vt1708S},
3234 { .id = 0x11065397, .name = "VIA VT1708S",
3235 .patch = patch_vt1708S},
3236 { .id = 0x11066397, .name = "VIA VT1708S",
3237 .patch = patch_vt1708S},
3238 { .id = 0x11067397, .name = "VIA VT1708S",
3239 .patch = patch_vt1708S},
3240 { .id = 0x11060398, .name = "VIA VT1702",
3241 .patch = patch_vt1702},
3242 { .id = 0x11061398, .name = "VIA VT1702",
3243 .patch = patch_vt1702},
3244 { .id = 0x11062398, .name = "VIA VT1702",
3245 .patch = patch_vt1702},
3246 { .id = 0x11063398, .name = "VIA VT1702",
3247 .patch = patch_vt1702},
3248 { .id = 0x11064398, .name = "VIA VT1702",
3249 .patch = patch_vt1702},
3250 { .id = 0x11065398, .name = "VIA VT1702",
3251 .patch = patch_vt1702},
3252 { .id = 0x11066398, .name = "VIA VT1702",
3253 .patch = patch_vt1702},
3254 { .id = 0x11067398, .name = "VIA VT1702",
3255 .patch = patch_vt1702},