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"
42 #include "hda_patch.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..
310 /* .name = "Capture Source", */
311 .name
= "Input Source",
313 .info
= via_mux_enum_info
,
314 .get
= via_mux_enum_get
,
315 .put
= via_mux_enum_put
,
320 * generic initialization of ADC, input mixers and output mixers
322 static struct hda_verb vt1708_volume_init_verbs
[] = {
324 * Unmute ADC0-1 and set the default input to mic-in
326 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
327 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
330 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
333 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
334 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
335 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
336 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
337 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
338 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
341 * Set up output mixers (0x19 - 0x1b)
343 /* set vol=0 to output mixers */
344 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
345 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
346 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
348 /* Setup default input to PW4 */
349 {0x20, AC_VERB_SET_CONNECT_SEL
, 0x1},
350 /* PW9 Output enable */
351 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
355 static int via_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
356 struct hda_codec
*codec
,
357 struct snd_pcm_substream
*substream
)
359 struct via_spec
*spec
= codec
->spec
;
360 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_cleanup_stream(codec
, spec
->adc_nids
[substream
->number
]);
438 static struct hda_pcm_stream vt1708_pcm_analog_playback
= {
442 .nid
= 0x10, /* NID to query formats and rates */
444 .open
= via_playback_pcm_open
,
445 .prepare
= via_playback_pcm_prepare
,
446 .cleanup
= via_playback_pcm_cleanup
450 static struct hda_pcm_stream vt1708_pcm_analog_s16_playback
= {
454 .nid
= 0x10, /* NID to query formats and rates */
455 /* We got noisy outputs on the right channel on VT1708 when
456 * 24bit samples are used. Until any workaround is found,
457 * disable the 24bit format, so far.
459 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
461 .open
= via_playback_pcm_open
,
462 .prepare
= via_playback_pcm_prepare
,
463 .cleanup
= via_playback_pcm_cleanup
467 static struct hda_pcm_stream vt1708_pcm_analog_capture
= {
471 .nid
= 0x15, /* NID to query formats and rates */
473 .prepare
= via_capture_pcm_prepare
,
474 .cleanup
= via_capture_pcm_cleanup
478 static struct hda_pcm_stream vt1708_pcm_digital_playback
= {
482 /* NID is set in via_build_pcms */
484 .open
= via_dig_playback_pcm_open
,
485 .close
= via_dig_playback_pcm_close
,
486 .prepare
= via_dig_playback_pcm_prepare
490 static struct hda_pcm_stream vt1708_pcm_digital_capture
= {
496 static int via_build_controls(struct hda_codec
*codec
)
498 struct via_spec
*spec
= codec
->spec
;
502 for (i
= 0; i
< spec
->num_mixers
; i
++) {
503 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
508 if (spec
->multiout
.dig_out_nid
) {
509 err
= snd_hda_create_spdif_out_ctls(codec
,
510 spec
->multiout
.dig_out_nid
);
513 err
= snd_hda_create_spdif_share_sw(codec
,
517 spec
->multiout
.share_spdif
= 1;
519 if (spec
->dig_in_nid
) {
520 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
527 static int via_build_pcms(struct hda_codec
*codec
)
529 struct via_spec
*spec
= codec
->spec
;
530 struct hda_pcm
*info
= spec
->pcm_rec
;
533 codec
->pcm_info
= info
;
535 info
->name
= spec
->stream_name_analog
;
536 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_analog_playback
);
537 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
538 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_analog_capture
);
539 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
541 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
=
542 spec
->multiout
.max_channels
;
544 if (spec
->multiout
.dig_out_nid
|| spec
->dig_in_nid
) {
547 info
->name
= spec
->stream_name_digital
;
548 info
->pcm_type
= HDA_PCM_TYPE_SPDIF
;
549 if (spec
->multiout
.dig_out_nid
) {
550 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
551 *(spec
->stream_digital_playback
);
552 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
=
553 spec
->multiout
.dig_out_nid
;
555 if (spec
->dig_in_nid
) {
556 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] =
557 *(spec
->stream_digital_capture
);
558 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
=
566 static void via_free(struct hda_codec
*codec
)
568 struct via_spec
*spec
= codec
->spec
;
574 if (spec
->kctl_alloc
) {
575 for (i
= 0; i
< spec
->num_kctl_used
; i
++)
576 kfree(spec
->kctl_alloc
[i
].name
);
577 kfree(spec
->kctl_alloc
);
583 static int via_init(struct hda_codec
*codec
)
585 struct via_spec
*spec
= codec
->spec
;
586 snd_hda_sequence_write(codec
, spec
->init_verbs
);
587 /* Lydia Add for EAPD enable */
588 if (!spec
->dig_in_nid
) { /* No Digital In connection */
589 if (IS_VT1708_VENDORID(codec
->vendor_id
)) {
590 snd_hda_codec_write(codec
, VT1708_DIGIN_PIN
, 0,
591 AC_VERB_SET_PIN_WIDGET_CONTROL
,
593 snd_hda_codec_write(codec
, VT1708_DIGIN_PIN
, 0,
594 AC_VERB_SET_EAPD_BTLENABLE
, 0x02);
595 } else if (IS_VT1709_10CH_VENDORID(codec
->vendor_id
) ||
596 IS_VT1709_6CH_VENDORID(codec
->vendor_id
)) {
597 snd_hda_codec_write(codec
, VT1709_DIGIN_PIN
, 0,
598 AC_VERB_SET_PIN_WIDGET_CONTROL
,
600 snd_hda_codec_write(codec
, VT1709_DIGIN_PIN
, 0,
601 AC_VERB_SET_EAPD_BTLENABLE
, 0x02);
602 } else if (IS_VT1708B_8CH_VENDORID(codec
->vendor_id
) ||
603 IS_VT1708B_4CH_VENDORID(codec
->vendor_id
)) {
604 snd_hda_codec_write(codec
, VT1708B_DIGIN_PIN
, 0,
605 AC_VERB_SET_PIN_WIDGET_CONTROL
,
607 snd_hda_codec_write(codec
, VT1708B_DIGIN_PIN
, 0,
608 AC_VERB_SET_EAPD_BTLENABLE
, 0x02);
610 } else /* enable SPDIF-input pin */
611 snd_hda_codec_write(codec
, spec
->autocfg
.dig_in_pin
, 0,
612 AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
);
617 #ifdef CONFIG_SND_HDA_POWER_SAVE
618 static int via_check_power_status(struct hda_codec
*codec
, hda_nid_t nid
)
620 struct via_spec
*spec
= codec
->spec
;
621 return snd_hda_check_amp_list_power(codec
, &spec
->loopback
, nid
);
627 static struct hda_codec_ops via_patch_ops
= {
628 .build_controls
= via_build_controls
,
629 .build_pcms
= via_build_pcms
,
632 #ifdef CONFIG_SND_HDA_POWER_SAVE
633 .check_power_status
= via_check_power_status
,
637 /* fill in the dac_nids table from the parsed pin configuration */
638 static int vt1708_auto_fill_dac_nids(struct via_spec
*spec
,
639 const struct auto_pin_cfg
*cfg
)
644 spec
->multiout
.num_dacs
= cfg
->line_outs
;
646 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
648 for(i
= 0; i
< 4; i
++) {
649 nid
= cfg
->line_out_pins
[i
];
651 /* config dac list */
654 spec
->multiout
.dac_nids
[i
] = 0x10;
656 case AUTO_SEQ_CENLFE
:
657 spec
->multiout
.dac_nids
[i
] = 0x12;
659 case AUTO_SEQ_SURROUND
:
660 spec
->multiout
.dac_nids
[i
] = 0x13;
663 spec
->multiout
.dac_nids
[i
] = 0x11;
672 /* add playback controls from the parsed DAC table */
673 static int vt1708_auto_create_multi_out_ctls(struct via_spec
*spec
,
674 const struct auto_pin_cfg
*cfg
)
677 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
678 hda_nid_t nid
, nid_vol
= 0;
681 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
682 nid
= cfg
->line_out_pins
[i
];
687 if (i
!= AUTO_SEQ_FRONT
)
688 nid_vol
= 0x1b - i
+ 1;
690 if (i
== AUTO_SEQ_CENLFE
) {
692 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
693 "Center Playback Volume",
694 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
698 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
699 "LFE Playback Volume",
700 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
704 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
705 "Center Playback Switch",
706 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
710 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
711 "LFE Playback Switch",
712 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
716 } else if (i
== AUTO_SEQ_FRONT
){
717 /* add control to mixer index 0 */
718 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
719 "Master Front Playback Volume",
720 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
724 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
725 "Master Front Playback Switch",
726 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
731 /* add control to PW3 */
732 sprintf(name
, "%s Playback Volume", chname
[i
]);
733 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
734 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
738 sprintf(name
, "%s Playback Switch", chname
[i
]);
739 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
740 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
745 sprintf(name
, "%s Playback Volume", chname
[i
]);
746 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
747 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
751 sprintf(name
, "%s Playback Switch", chname
[i
]);
752 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
753 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
763 static int vt1708_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
770 spec
->multiout
.hp_nid
= VT1708_HP_NID
; /* AOW3 */
772 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
773 "Headphone Playback Volume",
774 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
777 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
778 "Headphone Playback Switch",
779 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
786 /* create playback/capture controls for input pins */
787 static int vt1708_auto_create_analog_input_ctls(struct via_spec
*spec
,
788 const struct auto_pin_cfg
*cfg
)
790 static char *labels
[] = {
791 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
793 struct hda_input_mux
*imux
= &spec
->private_imux
;
796 /* for internal loopback recording select */
797 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
798 imux
->items
[imux
->num_items
].index
= idx
;
801 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
802 if (!cfg
->input_pins
[i
])
805 switch (cfg
->input_pins
[i
]) {
810 case 0x1e: /* Line In */
814 case 0x21: /* Front Mic */
822 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
826 imux
->items
[imux
->num_items
].label
= labels
[i
];
827 imux
->items
[imux
->num_items
].index
= idx
;
833 #ifdef CONFIG_SND_HDA_POWER_SAVE
834 static struct hda_amp_list vt1708_loopbacks
[] = {
835 { 0x17, HDA_INPUT
, 1 },
836 { 0x17, HDA_INPUT
, 2 },
837 { 0x17, HDA_INPUT
, 3 },
838 { 0x17, HDA_INPUT
, 4 },
843 static int vt1708_parse_auto_config(struct hda_codec
*codec
)
845 struct via_spec
*spec
= codec
->spec
;
848 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
851 err
= vt1708_auto_fill_dac_nids(spec
, &spec
->autocfg
);
854 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
855 return 0; /* can't find valid BIOS pin config */
857 err
= vt1708_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
860 err
= vt1708_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
863 err
= vt1708_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
867 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
869 if (spec
->autocfg
.dig_out_pin
)
870 spec
->multiout
.dig_out_nid
= VT1708_DIGOUT_NID
;
871 if (spec
->autocfg
.dig_in_pin
)
872 spec
->dig_in_nid
= VT1708_DIGIN_NID
;
874 if (spec
->kctl_alloc
)
875 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
877 spec
->init_verbs
= vt1708_volume_init_verbs
;
879 spec
->input_mux
= &spec
->private_imux
;
884 /* init callback for auto-configuration model -- overriding the default init */
885 static int via_auto_init(struct hda_codec
*codec
)
888 via_auto_init_multi_out(codec
);
889 via_auto_init_hp_out(codec
);
890 via_auto_init_analog_input(codec
);
894 static int patch_vt1708(struct hda_codec
*codec
)
896 struct via_spec
*spec
;
899 /* create a codec specific record */
900 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
906 /* automatic parse from the BIOS config */
907 err
= vt1708_parse_auto_config(codec
);
912 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
913 "from BIOS. Using genenic mode...\n");
917 spec
->stream_name_analog
= "VT1708 Analog";
918 spec
->stream_analog_playback
= &vt1708_pcm_analog_playback
;
919 /* disable 32bit format on VT1708 */
920 if (codec
->vendor_id
== 0x11061708)
921 spec
->stream_analog_playback
= &vt1708_pcm_analog_s16_playback
;
922 spec
->stream_analog_capture
= &vt1708_pcm_analog_capture
;
924 spec
->stream_name_digital
= "VT1708 Digital";
925 spec
->stream_digital_playback
= &vt1708_pcm_digital_playback
;
926 spec
->stream_digital_capture
= &vt1708_pcm_digital_capture
;
929 if (!spec
->adc_nids
&& spec
->input_mux
) {
930 spec
->adc_nids
= vt1708_adc_nids
;
931 spec
->num_adc_nids
= ARRAY_SIZE(vt1708_adc_nids
);
932 spec
->mixers
[spec
->num_mixers
] = vt1708_capture_mixer
;
936 codec
->patch_ops
= via_patch_ops
;
938 codec
->patch_ops
.init
= via_auto_init
;
939 #ifdef CONFIG_SND_HDA_POWER_SAVE
940 spec
->loopback
.amplist
= vt1708_loopbacks
;
946 /* capture mixer elements */
947 static struct snd_kcontrol_new vt1709_capture_mixer
[] = {
948 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT
),
949 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT
),
950 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT
),
951 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT
),
952 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT
),
953 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT
),
955 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
956 /* The multiple "Capture Source" controls confuse alsamixer
957 * So call somewhat different..
959 /* .name = "Capture Source", */
960 .name
= "Input Source",
962 .info
= via_mux_enum_info
,
963 .get
= via_mux_enum_get
,
964 .put
= via_mux_enum_put
,
970 * generic initialization of ADC, input mixers and output mixers
972 static struct hda_verb vt1709_10ch_volume_init_verbs
[] = {
974 * Unmute ADC0-2 and set the default input to mic-in
976 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
977 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
978 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
981 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
984 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
985 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
986 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
987 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
988 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
989 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
992 * Set up output selector (0x1a, 0x1b, 0x29)
994 /* set vol=0 to output mixers */
995 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
996 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
997 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1000 * Unmute PW3 and PW4
1002 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1003 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1005 /* Set input of PW4 as AOW4 */
1006 {0x20, AC_VERB_SET_CONNECT_SEL
, 0x1},
1007 /* PW9 Output enable */
1008 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1012 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback
= {
1016 .nid
= 0x10, /* NID to query formats and rates */
1018 .open
= via_playback_pcm_open
,
1019 .prepare
= via_playback_pcm_prepare
,
1020 .cleanup
= via_playback_pcm_cleanup
1024 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback
= {
1028 .nid
= 0x10, /* NID to query formats and rates */
1030 .open
= via_playback_pcm_open
,
1031 .prepare
= via_playback_pcm_prepare
,
1032 .cleanup
= via_playback_pcm_cleanup
1036 static struct hda_pcm_stream vt1709_pcm_analog_capture
= {
1040 .nid
= 0x14, /* NID to query formats and rates */
1042 .prepare
= via_capture_pcm_prepare
,
1043 .cleanup
= via_capture_pcm_cleanup
1047 static struct hda_pcm_stream vt1709_pcm_digital_playback
= {
1051 /* NID is set in via_build_pcms */
1053 .open
= via_dig_playback_pcm_open
,
1054 .close
= via_dig_playback_pcm_close
1058 static struct hda_pcm_stream vt1709_pcm_digital_capture
= {
1064 static int vt1709_auto_fill_dac_nids(struct via_spec
*spec
,
1065 const struct auto_pin_cfg
*cfg
)
1070 if (cfg
->line_outs
== 4) /* 10 channels */
1071 spec
->multiout
.num_dacs
= cfg
->line_outs
+1; /* AOW0~AOW4 */
1072 else if (cfg
->line_outs
== 3) /* 6 channels */
1073 spec
->multiout
.num_dacs
= cfg
->line_outs
; /* AOW0~AOW2 */
1075 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
1077 if (cfg
->line_outs
== 4) { /* 10 channels */
1078 for (i
= 0; i
< cfg
->line_outs
; i
++) {
1079 nid
= cfg
->line_out_pins
[i
];
1081 /* config dac list */
1083 case AUTO_SEQ_FRONT
:
1085 spec
->multiout
.dac_nids
[i
] = 0x10;
1087 case AUTO_SEQ_CENLFE
:
1089 spec
->multiout
.dac_nids
[i
] = 0x12;
1091 case AUTO_SEQ_SURROUND
:
1093 spec
->multiout
.dac_nids
[i
] = 0x27;
1097 spec
->multiout
.dac_nids
[i
] = 0x11;
1104 spec
->multiout
.dac_nids
[cfg
->line_outs
] = 0x28; /* AOW4 */
1106 } else if (cfg
->line_outs
== 3) { /* 6 channels */
1107 for(i
= 0; i
< cfg
->line_outs
; i
++) {
1108 nid
= cfg
->line_out_pins
[i
];
1110 /* config dac list */
1112 case AUTO_SEQ_FRONT
:
1114 spec
->multiout
.dac_nids
[i
] = 0x10;
1116 case AUTO_SEQ_CENLFE
:
1118 spec
->multiout
.dac_nids
[i
] = 0x12;
1120 case AUTO_SEQ_SURROUND
:
1122 spec
->multiout
.dac_nids
[i
] = 0x11;
1134 /* add playback controls from the parsed DAC table */
1135 static int vt1709_auto_create_multi_out_ctls(struct via_spec
*spec
,
1136 const struct auto_pin_cfg
*cfg
)
1139 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
1143 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
1144 nid
= cfg
->line_out_pins
[i
];
1149 if (i
== AUTO_SEQ_CENLFE
) {
1151 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1152 "Center Playback Volume",
1153 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1157 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1158 "LFE Playback Volume",
1159 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1163 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1164 "Center Playback Switch",
1165 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1169 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1170 "LFE Playback Switch",
1171 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1175 } else if (i
== AUTO_SEQ_FRONT
){
1176 /* add control to mixer index 0 */
1177 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1178 "Master Front Playback Volume",
1179 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1183 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1184 "Master Front Playback Switch",
1185 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1190 /* add control to PW3 */
1191 sprintf(name
, "%s Playback Volume", chname
[i
]);
1192 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1193 HDA_COMPOSE_AMP_VAL(nid
, 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(nid
, 3, 0,
1203 } else if (i
== AUTO_SEQ_SURROUND
) {
1204 sprintf(name
, "%s Playback Volume", chname
[i
]);
1205 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1206 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1210 sprintf(name
, "%s Playback Switch", chname
[i
]);
1211 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1212 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1216 } else if (i
== AUTO_SEQ_SIDE
) {
1217 sprintf(name
, "%s Playback Volume", chname
[i
]);
1218 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1219 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1223 sprintf(name
, "%s Playback Switch", chname
[i
]);
1224 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1225 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1235 static int vt1709_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
1242 if (spec
->multiout
.num_dacs
== 5) /* 10 channels */
1243 spec
->multiout
.hp_nid
= VT1709_HP_DAC_NID
;
1244 else if (spec
->multiout
.num_dacs
== 3) /* 6 channels */
1245 spec
->multiout
.hp_nid
= 0;
1247 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1248 "Headphone Playback Volume",
1249 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1252 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1253 "Headphone Playback Switch",
1254 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1261 /* create playback/capture controls for input pins */
1262 static int vt1709_auto_create_analog_input_ctls(struct via_spec
*spec
,
1263 const struct auto_pin_cfg
*cfg
)
1265 static char *labels
[] = {
1266 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1268 struct hda_input_mux
*imux
= &spec
->private_imux
;
1269 int i
, err
, idx
= 0;
1271 /* for internal loopback recording select */
1272 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
1273 imux
->items
[imux
->num_items
].index
= idx
;
1276 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
1277 if (!cfg
->input_pins
[i
])
1280 switch (cfg
->input_pins
[i
]) {
1281 case 0x1d: /* Mic */
1285 case 0x1e: /* Line In */
1289 case 0x21: /* Front Mic */
1297 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
1301 imux
->items
[imux
->num_items
].label
= labels
[i
];
1302 imux
->items
[imux
->num_items
].index
= idx
;
1308 static int vt1709_parse_auto_config(struct hda_codec
*codec
)
1310 struct via_spec
*spec
= codec
->spec
;
1313 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
1316 err
= vt1709_auto_fill_dac_nids(spec
, &spec
->autocfg
);
1319 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
1320 return 0; /* can't find valid BIOS pin config */
1322 err
= vt1709_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
1325 err
= vt1709_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
1328 err
= vt1709_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
1332 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
1334 if (spec
->autocfg
.dig_out_pin
)
1335 spec
->multiout
.dig_out_nid
= VT1709_DIGOUT_NID
;
1336 if (spec
->autocfg
.dig_in_pin
)
1337 spec
->dig_in_nid
= VT1709_DIGIN_NID
;
1339 if (spec
->kctl_alloc
)
1340 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
1342 spec
->input_mux
= &spec
->private_imux
;
1347 #ifdef CONFIG_SND_HDA_POWER_SAVE
1348 static struct hda_amp_list vt1709_loopbacks
[] = {
1349 { 0x18, HDA_INPUT
, 1 },
1350 { 0x18, HDA_INPUT
, 2 },
1351 { 0x18, HDA_INPUT
, 3 },
1352 { 0x18, HDA_INPUT
, 4 },
1357 static int patch_vt1709_10ch(struct hda_codec
*codec
)
1359 struct via_spec
*spec
;
1362 /* create a codec specific record */
1363 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1369 err
= vt1709_parse_auto_config(codec
);
1374 printk(KERN_INFO
"hda_codec: Cannot set up configuration. "
1375 "Using genenic mode...\n");
1378 spec
->init_verbs
= vt1709_10ch_volume_init_verbs
;
1380 spec
->stream_name_analog
= "VT1709 Analog";
1381 spec
->stream_analog_playback
= &vt1709_10ch_pcm_analog_playback
;
1382 spec
->stream_analog_capture
= &vt1709_pcm_analog_capture
;
1384 spec
->stream_name_digital
= "VT1709 Digital";
1385 spec
->stream_digital_playback
= &vt1709_pcm_digital_playback
;
1386 spec
->stream_digital_capture
= &vt1709_pcm_digital_capture
;
1389 if (!spec
->adc_nids
&& spec
->input_mux
) {
1390 spec
->adc_nids
= vt1709_adc_nids
;
1391 spec
->num_adc_nids
= ARRAY_SIZE(vt1709_adc_nids
);
1392 spec
->mixers
[spec
->num_mixers
] = vt1709_capture_mixer
;
1396 codec
->patch_ops
= via_patch_ops
;
1398 codec
->patch_ops
.init
= via_auto_init
;
1399 #ifdef CONFIG_SND_HDA_POWER_SAVE
1400 spec
->loopback
.amplist
= vt1709_loopbacks
;
1406 * generic initialization of ADC, input mixers and output mixers
1408 static struct hda_verb vt1709_6ch_volume_init_verbs
[] = {
1410 * Unmute ADC0-2 and set the default input to mic-in
1412 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1413 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1414 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1417 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1420 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1421 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1422 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1423 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1424 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1425 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1428 * Set up output selector (0x1a, 0x1b, 0x29)
1430 /* set vol=0 to output mixers */
1431 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1432 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1433 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1436 * Unmute PW3 and PW4
1438 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1439 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1441 /* Set input of PW4 as MW0 */
1442 {0x20, AC_VERB_SET_CONNECT_SEL
, 0},
1443 /* PW9 Output enable */
1444 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1448 static int patch_vt1709_6ch(struct hda_codec
*codec
)
1450 struct via_spec
*spec
;
1453 /* create a codec specific record */
1454 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1460 err
= vt1709_parse_auto_config(codec
);
1465 printk(KERN_INFO
"hda_codec: Cannot set up configuration. "
1466 "Using genenic mode...\n");
1469 spec
->init_verbs
= vt1709_6ch_volume_init_verbs
;
1471 spec
->stream_name_analog
= "VT1709 Analog";
1472 spec
->stream_analog_playback
= &vt1709_6ch_pcm_analog_playback
;
1473 spec
->stream_analog_capture
= &vt1709_pcm_analog_capture
;
1475 spec
->stream_name_digital
= "VT1709 Digital";
1476 spec
->stream_digital_playback
= &vt1709_pcm_digital_playback
;
1477 spec
->stream_digital_capture
= &vt1709_pcm_digital_capture
;
1480 if (!spec
->adc_nids
&& spec
->input_mux
) {
1481 spec
->adc_nids
= vt1709_adc_nids
;
1482 spec
->num_adc_nids
= ARRAY_SIZE(vt1709_adc_nids
);
1483 spec
->mixers
[spec
->num_mixers
] = vt1709_capture_mixer
;
1487 codec
->patch_ops
= via_patch_ops
;
1489 codec
->patch_ops
.init
= via_auto_init
;
1490 #ifdef CONFIG_SND_HDA_POWER_SAVE
1491 spec
->loopback
.amplist
= vt1709_loopbacks
;
1496 /* capture mixer elements */
1497 static struct snd_kcontrol_new vt1708B_capture_mixer
[] = {
1498 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT
),
1499 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT
),
1500 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT
),
1501 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT
),
1503 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1504 /* The multiple "Capture Source" controls confuse alsamixer
1505 * So call somewhat different..
1507 /* .name = "Capture Source", */
1508 .name
= "Input Source",
1510 .info
= via_mux_enum_info
,
1511 .get
= via_mux_enum_get
,
1512 .put
= via_mux_enum_put
,
1517 * generic initialization of ADC, input mixers and output mixers
1519 static struct hda_verb vt1708B_8ch_volume_init_verbs
[] = {
1521 * Unmute ADC0-1 and set the default input to mic-in
1523 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1524 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1527 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1530 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1531 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1532 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1533 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1534 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1535 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1538 * Set up output mixers
1540 /* set vol=0 to output mixers */
1541 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1542 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1543 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1545 /* Setup default input to PW4 */
1546 {0x1d, AC_VERB_SET_CONNECT_SEL
, 0x1},
1547 /* PW9 Output enable */
1548 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1549 /* PW10 Input enable */
1550 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
1554 static struct hda_verb vt1708B_4ch_volume_init_verbs
[] = {
1556 * Unmute ADC0-1 and set the default input to mic-in
1558 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1559 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1562 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1565 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1566 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1567 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1568 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1569 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1570 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1573 * Set up output mixers
1575 /* set vol=0 to output mixers */
1576 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1577 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1578 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1580 /* Setup default input of PW4 to MW0 */
1581 {0x1d, AC_VERB_SET_CONNECT_SEL
, 0x0},
1582 /* PW9 Output enable */
1583 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1584 /* PW10 Input enable */
1585 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
1589 static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback
= {
1593 .nid
= 0x10, /* NID to query formats and rates */
1595 .open
= via_playback_pcm_open
,
1596 .prepare
= via_playback_pcm_prepare
,
1597 .cleanup
= via_playback_pcm_cleanup
1601 static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback
= {
1605 .nid
= 0x10, /* NID to query formats and rates */
1607 .open
= via_playback_pcm_open
,
1608 .prepare
= via_playback_pcm_prepare
,
1609 .cleanup
= via_playback_pcm_cleanup
1613 static struct hda_pcm_stream vt1708B_pcm_analog_capture
= {
1617 .nid
= 0x13, /* NID to query formats and rates */
1619 .prepare
= via_capture_pcm_prepare
,
1620 .cleanup
= via_capture_pcm_cleanup
1624 static struct hda_pcm_stream vt1708B_pcm_digital_playback
= {
1628 /* NID is set in via_build_pcms */
1630 .open
= via_dig_playback_pcm_open
,
1631 .close
= via_dig_playback_pcm_close
,
1632 .prepare
= via_dig_playback_pcm_prepare
1636 static struct hda_pcm_stream vt1708B_pcm_digital_capture
= {
1642 /* fill in the dac_nids table from the parsed pin configuration */
1643 static int vt1708B_auto_fill_dac_nids(struct via_spec
*spec
,
1644 const struct auto_pin_cfg
*cfg
)
1649 spec
->multiout
.num_dacs
= cfg
->line_outs
;
1651 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
1653 for (i
= 0; i
< 4; i
++) {
1654 nid
= cfg
->line_out_pins
[i
];
1656 /* config dac list */
1658 case AUTO_SEQ_FRONT
:
1659 spec
->multiout
.dac_nids
[i
] = 0x10;
1661 case AUTO_SEQ_CENLFE
:
1662 spec
->multiout
.dac_nids
[i
] = 0x24;
1664 case AUTO_SEQ_SURROUND
:
1665 spec
->multiout
.dac_nids
[i
] = 0x25;
1668 spec
->multiout
.dac_nids
[i
] = 0x11;
1677 /* add playback controls from the parsed DAC table */
1678 static int vt1708B_auto_create_multi_out_ctls(struct via_spec
*spec
,
1679 const struct auto_pin_cfg
*cfg
)
1682 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
1683 hda_nid_t nid_vols
[] = {0x16, 0x27, 0x26, 0x18};
1684 hda_nid_t nid
, nid_vol
= 0;
1687 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
1688 nid
= cfg
->line_out_pins
[i
];
1693 nid_vol
= nid_vols
[i
];
1695 if (i
== AUTO_SEQ_CENLFE
) {
1697 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1698 "Center Playback Volume",
1699 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
1703 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1704 "LFE Playback Volume",
1705 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
1709 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1710 "Center Playback Switch",
1711 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
1715 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1716 "LFE Playback Switch",
1717 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
1721 } else if (i
== AUTO_SEQ_FRONT
) {
1722 /* add control to mixer index 0 */
1723 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1724 "Master Front Playback Volume",
1725 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1729 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1730 "Master Front Playback Switch",
1731 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1736 /* add control to PW3 */
1737 sprintf(name
, "%s Playback Volume", chname
[i
]);
1738 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1739 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
1743 sprintf(name
, "%s Playback Switch", chname
[i
]);
1744 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1745 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
1750 sprintf(name
, "%s Playback Volume", chname
[i
]);
1751 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1752 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1756 sprintf(name
, "%s Playback Switch", chname
[i
]);
1757 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1758 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1768 static int vt1708B_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
1775 spec
->multiout
.hp_nid
= VT1708B_HP_NID
; /* AOW3 */
1777 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1778 "Headphone Playback Volume",
1779 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1782 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1783 "Headphone Playback Switch",
1784 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1791 /* create playback/capture controls for input pins */
1792 static int vt1708B_auto_create_analog_input_ctls(struct via_spec
*spec
,
1793 const struct auto_pin_cfg
*cfg
)
1795 static char *labels
[] = {
1796 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1798 struct hda_input_mux
*imux
= &spec
->private_imux
;
1799 int i
, err
, idx
= 0;
1801 /* for internal loopback recording select */
1802 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
1803 imux
->items
[imux
->num_items
].index
= idx
;
1806 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
1807 if (!cfg
->input_pins
[i
])
1810 switch (cfg
->input_pins
[i
]) {
1811 case 0x1a: /* Mic */
1815 case 0x1b: /* Line In */
1819 case 0x1e: /* Front Mic */
1827 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
1831 imux
->items
[imux
->num_items
].label
= labels
[i
];
1832 imux
->items
[imux
->num_items
].index
= idx
;
1838 static int vt1708B_parse_auto_config(struct hda_codec
*codec
)
1840 struct via_spec
*spec
= codec
->spec
;
1843 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
1846 err
= vt1708B_auto_fill_dac_nids(spec
, &spec
->autocfg
);
1849 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
1850 return 0; /* can't find valid BIOS pin config */
1852 err
= vt1708B_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
1855 err
= vt1708B_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
1858 err
= vt1708B_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
1862 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
1864 if (spec
->autocfg
.dig_out_pin
)
1865 spec
->multiout
.dig_out_nid
= VT1708B_DIGOUT_NID
;
1866 if (spec
->autocfg
.dig_in_pin
)
1867 spec
->dig_in_nid
= VT1708B_DIGIN_NID
;
1869 if (spec
->kctl_alloc
)
1870 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
1872 spec
->input_mux
= &spec
->private_imux
;
1877 #ifdef CONFIG_SND_HDA_POWER_SAVE
1878 static struct hda_amp_list vt1708B_loopbacks
[] = {
1879 { 0x16, HDA_INPUT
, 1 },
1880 { 0x16, HDA_INPUT
, 2 },
1881 { 0x16, HDA_INPUT
, 3 },
1882 { 0x16, HDA_INPUT
, 4 },
1887 static int patch_vt1708B_8ch(struct hda_codec
*codec
)
1889 struct via_spec
*spec
;
1892 /* create a codec specific record */
1893 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1899 /* automatic parse from the BIOS config */
1900 err
= vt1708B_parse_auto_config(codec
);
1905 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
1906 "from BIOS. Using genenic mode...\n");
1909 spec
->init_verbs
= vt1708B_8ch_volume_init_verbs
;
1911 spec
->stream_name_analog
= "VT1708B Analog";
1912 spec
->stream_analog_playback
= &vt1708B_8ch_pcm_analog_playback
;
1913 spec
->stream_analog_capture
= &vt1708B_pcm_analog_capture
;
1915 spec
->stream_name_digital
= "VT1708B Digital";
1916 spec
->stream_digital_playback
= &vt1708B_pcm_digital_playback
;
1917 spec
->stream_digital_capture
= &vt1708B_pcm_digital_capture
;
1919 if (!spec
->adc_nids
&& spec
->input_mux
) {
1920 spec
->adc_nids
= vt1708B_adc_nids
;
1921 spec
->num_adc_nids
= ARRAY_SIZE(vt1708B_adc_nids
);
1922 spec
->mixers
[spec
->num_mixers
] = vt1708B_capture_mixer
;
1926 codec
->patch_ops
= via_patch_ops
;
1928 codec
->patch_ops
.init
= via_auto_init
;
1929 #ifdef CONFIG_SND_HDA_POWER_SAVE
1930 spec
->loopback
.amplist
= vt1708B_loopbacks
;
1936 static int patch_vt1708B_4ch(struct hda_codec
*codec
)
1938 struct via_spec
*spec
;
1941 /* create a codec specific record */
1942 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1948 /* automatic parse from the BIOS config */
1949 err
= vt1708B_parse_auto_config(codec
);
1954 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
1955 "from BIOS. Using genenic mode...\n");
1958 spec
->init_verbs
= vt1708B_4ch_volume_init_verbs
;
1960 spec
->stream_name_analog
= "VT1708B Analog";
1961 spec
->stream_analog_playback
= &vt1708B_4ch_pcm_analog_playback
;
1962 spec
->stream_analog_capture
= &vt1708B_pcm_analog_capture
;
1964 spec
->stream_name_digital
= "VT1708B Digital";
1965 spec
->stream_digital_playback
= &vt1708B_pcm_digital_playback
;
1966 spec
->stream_digital_capture
= &vt1708B_pcm_digital_capture
;
1968 if (!spec
->adc_nids
&& spec
->input_mux
) {
1969 spec
->adc_nids
= vt1708B_adc_nids
;
1970 spec
->num_adc_nids
= ARRAY_SIZE(vt1708B_adc_nids
);
1971 spec
->mixers
[spec
->num_mixers
] = vt1708B_capture_mixer
;
1975 codec
->patch_ops
= via_patch_ops
;
1977 codec
->patch_ops
.init
= via_auto_init
;
1978 #ifdef CONFIG_SND_HDA_POWER_SAVE
1979 spec
->loopback
.amplist
= vt1708B_loopbacks
;
1988 struct hda_codec_preset snd_hda_preset_via
[] = {
1989 { .id
= 0x11061708, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1990 { .id
= 0x11061709, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1991 { .id
= 0x1106170A, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1992 { .id
= 0x1106170B, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1993 { .id
= 0x1106E710, .name
= "VIA VT1709 10-Ch",
1994 .patch
= patch_vt1709_10ch
},
1995 { .id
= 0x1106E711, .name
= "VIA VT1709 10-Ch",
1996 .patch
= patch_vt1709_10ch
},
1997 { .id
= 0x1106E712, .name
= "VIA VT1709 10-Ch",
1998 .patch
= patch_vt1709_10ch
},
1999 { .id
= 0x1106E713, .name
= "VIA VT1709 10-Ch",
2000 .patch
= patch_vt1709_10ch
},
2001 { .id
= 0x1106E714, .name
= "VIA VT1709 6-Ch",
2002 .patch
= patch_vt1709_6ch
},
2003 { .id
= 0x1106E715, .name
= "VIA VT1709 6-Ch",
2004 .patch
= patch_vt1709_6ch
},
2005 { .id
= 0x1106E716, .name
= "VIA VT1709 6-Ch",
2006 .patch
= patch_vt1709_6ch
},
2007 { .id
= 0x1106E717, .name
= "VIA VT1709 6-Ch",
2008 .patch
= patch_vt1709_6ch
},
2009 { .id
= 0x1106E720, .name
= "VIA VT1708B 8-Ch",
2010 .patch
= patch_vt1708B_8ch
},
2011 { .id
= 0x1106E721, .name
= "VIA VT1708B 8-Ch",
2012 .patch
= patch_vt1708B_8ch
},
2013 { .id
= 0x1106E722, .name
= "VIA VT1708B 8-Ch",
2014 .patch
= patch_vt1708B_8ch
},
2015 { .id
= 0x1106E723, .name
= "VIA VT1708B 8-Ch",
2016 .patch
= patch_vt1708B_8ch
},
2017 { .id
= 0x1106E724, .name
= "VIA VT1708B 4-Ch",
2018 .patch
= patch_vt1708B_4ch
},
2019 { .id
= 0x1106E725, .name
= "VIA VT1708B 4-Ch",
2020 .patch
= patch_vt1708B_4ch
},
2021 { .id
= 0x1106E726, .name
= "VIA VT1708B 4-Ch",
2022 .patch
= patch_vt1708B_4ch
},
2023 { .id
= 0x1106E727, .name
= "VIA VT1708B 4-Ch",
2024 .patch
= patch_vt1708B_4ch
},