2 * Universal Interface for Intel High Definition Audio Codec
4 * HD audio interface patch for VIA VT1708 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 */
34 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
37 #include <linux/init.h>
38 #include <linux/delay.h>
39 #include <linux/slab.h>
40 #include <sound/core.h>
41 #include "hda_codec.h"
42 #include "hda_local.h"
43 #include "hda_patch.h"
46 #define AMP_VAL_IDX_SHIFT 19
47 #define AMP_VAL_IDX_MASK (0x0f<<19)
49 #define NUM_CONTROL_ALLOC 32
50 #define NUM_VERB_ALLOC 32
53 #define VT1708_HP_NID 0x13
54 #define VT1708_DIGOUT_NID 0x14
55 #define VT1708_DIGIN_NID 0x16
56 #define VT1708_DIGIN_PIN 0x26
57 #define VT1708_HP_PIN_NID 0x20
58 #define VT1708_CD_PIN_NID 0x24
60 #define VT1709_HP_DAC_NID 0x28
61 #define VT1709_DIGOUT_NID 0x13
62 #define VT1709_DIGIN_NID 0x17
63 #define VT1709_DIGIN_PIN 0x25
65 #define VT1708B_HP_NID 0x25
66 #define VT1708B_DIGOUT_NID 0x12
67 #define VT1708B_DIGIN_NID 0x15
68 #define VT1708B_DIGIN_PIN 0x21
70 #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
71 #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
72 #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
73 #define IS_VT1708B_8CH_VENDORID(x) ((x) >= 0x1106e720 && (x) <= 0x1106e723)
74 #define IS_VT1708B_4CH_VENDORID(x) ((x) >= 0x1106e724 && (x) <= 0x1106e727)
89 static struct snd_kcontrol_new vt1708_control_templates
[] = {
90 HDA_CODEC_VOLUME(NULL
, 0, 0, 0),
91 HDA_CODEC_MUTE(NULL
, 0, 0, 0),
96 /* codec parameterization */
97 struct snd_kcontrol_new
*mixers
[3];
98 unsigned int num_mixers
;
100 struct hda_verb
*init_verbs
;
102 char *stream_name_analog
;
103 struct hda_pcm_stream
*stream_analog_playback
;
104 struct hda_pcm_stream
*stream_analog_capture
;
106 char *stream_name_digital
;
107 struct hda_pcm_stream
*stream_digital_playback
;
108 struct hda_pcm_stream
*stream_digital_capture
;
111 struct hda_multi_out multiout
;
114 unsigned int num_adc_nids
;
116 hda_nid_t dig_in_nid
;
119 const struct hda_input_mux
*input_mux
;
120 unsigned int cur_mux
[3];
122 /* PCM information */
123 struct hda_pcm pcm_rec
[2];
125 /* dynamic controls, init_verbs and input_mux */
126 struct auto_pin_cfg autocfg
;
127 unsigned int num_kctl_alloc
, num_kctl_used
;
128 struct snd_kcontrol_new
*kctl_alloc
;
129 struct hda_input_mux private_imux
;
130 hda_nid_t private_dac_nids
[AUTO_CFG_MAX_OUTS
];
132 #ifdef CONFIG_SND_HDA_POWER_SAVE
133 struct hda_loopback_check loopback
;
137 static hda_nid_t vt1708_adc_nids
[2] = {
142 static hda_nid_t vt1709_adc_nids
[3] = {
147 static hda_nid_t vt1708B_adc_nids
[2] = {
152 /* add dynamic controls */
153 static int via_add_control(struct via_spec
*spec
, int type
, const char *name
,
156 struct snd_kcontrol_new
*knew
;
158 if (spec
->num_kctl_used
>= spec
->num_kctl_alloc
) {
159 int num
= spec
->num_kctl_alloc
+ NUM_CONTROL_ALLOC
;
161 /* array + terminator */
162 knew
= kcalloc(num
+ 1, sizeof(*knew
), GFP_KERNEL
);
165 if (spec
->kctl_alloc
) {
166 memcpy(knew
, spec
->kctl_alloc
,
167 sizeof(*knew
) * spec
->num_kctl_alloc
);
168 kfree(spec
->kctl_alloc
);
170 spec
->kctl_alloc
= knew
;
171 spec
->num_kctl_alloc
= num
;
174 knew
= &spec
->kctl_alloc
[spec
->num_kctl_used
];
175 *knew
= vt1708_control_templates
[type
];
176 knew
->name
= kstrdup(name
, GFP_KERNEL
);
180 knew
->private_value
= val
;
181 spec
->num_kctl_used
++;
185 /* create input playback/capture controls for the given pin */
186 static int via_new_analog_input(struct via_spec
*spec
, hda_nid_t pin
,
187 const char *ctlname
, int idx
, int mix_nid
)
192 sprintf(name
, "%s Playback Volume", ctlname
);
193 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
194 HDA_COMPOSE_AMP_VAL(mix_nid
, 3, idx
, HDA_INPUT
));
197 sprintf(name
, "%s Playback Switch", ctlname
);
198 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
199 HDA_COMPOSE_AMP_VAL(mix_nid
, 3, idx
, HDA_INPUT
));
205 static void via_auto_set_output_and_unmute(struct hda_codec
*codec
,
206 hda_nid_t nid
, int pin_type
,
210 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
212 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
217 static void via_auto_init_multi_out(struct hda_codec
*codec
)
219 struct via_spec
*spec
= codec
->spec
;
222 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
223 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
225 via_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
229 static void via_auto_init_hp_out(struct hda_codec
*codec
)
231 struct via_spec
*spec
= codec
->spec
;
234 pin
= spec
->autocfg
.hp_pins
[0];
235 if (pin
) /* connect to front */
236 via_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0);
239 static void via_auto_init_analog_input(struct hda_codec
*codec
)
241 struct via_spec
*spec
= codec
->spec
;
244 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
245 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
247 snd_hda_codec_write(codec
, nid
, 0,
248 AC_VERB_SET_PIN_WIDGET_CONTROL
,
249 (i
<= AUTO_PIN_FRONT_MIC
?
250 PIN_VREF50
: PIN_IN
));
257 static int via_mux_enum_info(struct snd_kcontrol
*kcontrol
,
258 struct snd_ctl_elem_info
*uinfo
)
260 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
261 struct via_spec
*spec
= codec
->spec
;
262 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
265 static int via_mux_enum_get(struct snd_kcontrol
*kcontrol
,
266 struct snd_ctl_elem_value
*ucontrol
)
268 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
269 struct via_spec
*spec
= codec
->spec
;
270 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
272 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
276 static int via_mux_enum_put(struct snd_kcontrol
*kcontrol
,
277 struct snd_ctl_elem_value
*ucontrol
)
279 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
280 struct via_spec
*spec
= codec
->spec
;
281 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
282 unsigned int vendor_id
= codec
->vendor_id
;
284 /* AIW0 lydia 060801 add for correct sw0 input select */
285 if (IS_VT1708_VENDORID(vendor_id
) && (adc_idx
== 0))
286 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
287 0x18, &spec
->cur_mux
[adc_idx
]);
288 else if ((IS_VT1709_10CH_VENDORID(vendor_id
) ||
289 IS_VT1709_6CH_VENDORID(vendor_id
)) && (adc_idx
== 0))
290 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
291 0x19, &spec
->cur_mux
[adc_idx
]);
292 else if ((IS_VT1708B_8CH_VENDORID(vendor_id
) ||
293 IS_VT1708B_4CH_VENDORID(vendor_id
)) && (adc_idx
== 0))
294 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
295 0x17, &spec
->cur_mux
[adc_idx
]);
297 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
298 spec
->adc_nids
[adc_idx
],
299 &spec
->cur_mux
[adc_idx
]);
302 /* capture mixer elements */
303 static struct snd_kcontrol_new vt1708_capture_mixer
[] = {
304 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT
),
305 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT
),
306 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT
),
307 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT
),
309 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
310 /* The multiple "Capture Source" controls confuse alsamixer
311 * So call somewhat different..
313 /* .name = "Capture Source", */
314 .name
= "Input Source",
316 .info
= via_mux_enum_info
,
317 .get
= via_mux_enum_get
,
318 .put
= via_mux_enum_put
,
323 * generic initialization of ADC, input mixers and output mixers
325 static struct hda_verb vt1708_volume_init_verbs
[] = {
327 * Unmute ADC0-1 and set the default input to mic-in
329 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
330 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
333 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
336 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
337 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
338 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
339 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
340 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
341 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
344 * Set up output mixers (0x19 - 0x1b)
346 /* set vol=0 to output mixers */
347 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
348 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
349 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
351 /* Setup default input to PW4 */
352 {0x20, AC_VERB_SET_CONNECT_SEL
, 0x1},
353 /* PW9 Output enable */
354 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
358 static int via_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
359 struct hda_codec
*codec
,
360 struct snd_pcm_substream
*substream
)
362 struct via_spec
*spec
= codec
->spec
;
363 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
,
367 static int via_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
368 struct hda_codec
*codec
,
369 unsigned int stream_tag
,
371 struct snd_pcm_substream
*substream
)
373 struct via_spec
*spec
= codec
->spec
;
374 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
,
375 stream_tag
, format
, substream
);
378 static int via_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
379 struct hda_codec
*codec
,
380 struct snd_pcm_substream
*substream
)
382 struct via_spec
*spec
= codec
->spec
;
383 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
389 static int via_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
390 struct hda_codec
*codec
,
391 struct snd_pcm_substream
*substream
)
393 struct via_spec
*spec
= codec
->spec
;
394 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
397 static int via_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
398 struct hda_codec
*codec
,
399 struct snd_pcm_substream
*substream
)
401 struct via_spec
*spec
= codec
->spec
;
402 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
405 static int via_dig_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
406 struct hda_codec
*codec
,
407 unsigned int stream_tag
,
409 struct snd_pcm_substream
*substream
)
411 struct via_spec
*spec
= codec
->spec
;
412 return snd_hda_multi_out_dig_prepare(codec
, &spec
->multiout
,
413 stream_tag
, format
, substream
);
419 static int via_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
420 struct hda_codec
*codec
,
421 unsigned int stream_tag
,
423 struct snd_pcm_substream
*substream
)
425 struct via_spec
*spec
= codec
->spec
;
427 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
428 stream_tag
, 0, format
);
432 static int via_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
433 struct hda_codec
*codec
,
434 struct snd_pcm_substream
*substream
)
436 struct via_spec
*spec
= codec
->spec
;
437 snd_hda_codec_cleanup_stream(codec
, spec
->adc_nids
[substream
->number
]);
441 static struct hda_pcm_stream vt1708_pcm_analog_playback
= {
445 .nid
= 0x10, /* NID to query formats and rates */
447 .open
= via_playback_pcm_open
,
448 .prepare
= via_playback_pcm_prepare
,
449 .cleanup
= via_playback_pcm_cleanup
453 static struct hda_pcm_stream vt1708_pcm_analog_s16_playback
= {
457 .nid
= 0x10, /* NID to query formats and rates */
458 /* We got noisy outputs on the right channel on VT1708 when
459 * 24bit samples are used. Until any workaround is found,
460 * disable the 24bit format, so far.
462 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
464 .open
= via_playback_pcm_open
,
465 .prepare
= via_playback_pcm_prepare
,
466 .cleanup
= via_playback_pcm_cleanup
470 static struct hda_pcm_stream vt1708_pcm_analog_capture
= {
474 .nid
= 0x15, /* NID to query formats and rates */
476 .prepare
= via_capture_pcm_prepare
,
477 .cleanup
= via_capture_pcm_cleanup
481 static struct hda_pcm_stream vt1708_pcm_digital_playback
= {
485 /* NID is set in via_build_pcms */
487 .open
= via_dig_playback_pcm_open
,
488 .close
= via_dig_playback_pcm_close
,
489 .prepare
= via_dig_playback_pcm_prepare
493 static struct hda_pcm_stream vt1708_pcm_digital_capture
= {
499 static int via_build_controls(struct hda_codec
*codec
)
501 struct via_spec
*spec
= codec
->spec
;
505 for (i
= 0; i
< spec
->num_mixers
; i
++) {
506 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
511 if (spec
->multiout
.dig_out_nid
) {
512 err
= snd_hda_create_spdif_out_ctls(codec
,
513 spec
->multiout
.dig_out_nid
);
516 err
= snd_hda_create_spdif_share_sw(codec
,
520 spec
->multiout
.share_spdif
= 1;
522 if (spec
->dig_in_nid
) {
523 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
530 static int via_build_pcms(struct hda_codec
*codec
)
532 struct via_spec
*spec
= codec
->spec
;
533 struct hda_pcm
*info
= spec
->pcm_rec
;
536 codec
->pcm_info
= info
;
538 info
->name
= spec
->stream_name_analog
;
539 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_analog_playback
);
540 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
541 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_analog_capture
);
542 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
544 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
=
545 spec
->multiout
.max_channels
;
547 if (spec
->multiout
.dig_out_nid
|| spec
->dig_in_nid
) {
550 info
->name
= spec
->stream_name_digital
;
551 info
->pcm_type
= HDA_PCM_TYPE_SPDIF
;
552 if (spec
->multiout
.dig_out_nid
) {
553 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
554 *(spec
->stream_digital_playback
);
555 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
=
556 spec
->multiout
.dig_out_nid
;
558 if (spec
->dig_in_nid
) {
559 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] =
560 *(spec
->stream_digital_capture
);
561 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
=
569 static void via_free(struct hda_codec
*codec
)
571 struct via_spec
*spec
= codec
->spec
;
577 if (spec
->kctl_alloc
) {
578 for (i
= 0; i
< spec
->num_kctl_used
; i
++)
579 kfree(spec
->kctl_alloc
[i
].name
);
580 kfree(spec
->kctl_alloc
);
586 static int via_init(struct hda_codec
*codec
)
588 struct via_spec
*spec
= codec
->spec
;
589 snd_hda_sequence_write(codec
, spec
->init_verbs
);
590 /* Lydia Add for EAPD enable */
591 if (!spec
->dig_in_nid
) { /* No Digital In connection */
592 if (IS_VT1708_VENDORID(codec
->vendor_id
)) {
593 snd_hda_codec_write(codec
, VT1708_DIGIN_PIN
, 0,
594 AC_VERB_SET_PIN_WIDGET_CONTROL
,
596 snd_hda_codec_write(codec
, VT1708_DIGIN_PIN
, 0,
597 AC_VERB_SET_EAPD_BTLENABLE
, 0x02);
598 } else if (IS_VT1709_10CH_VENDORID(codec
->vendor_id
) ||
599 IS_VT1709_6CH_VENDORID(codec
->vendor_id
)) {
600 snd_hda_codec_write(codec
, VT1709_DIGIN_PIN
, 0,
601 AC_VERB_SET_PIN_WIDGET_CONTROL
,
603 snd_hda_codec_write(codec
, VT1709_DIGIN_PIN
, 0,
604 AC_VERB_SET_EAPD_BTLENABLE
, 0x02);
605 } else if (IS_VT1708B_8CH_VENDORID(codec
->vendor_id
) ||
606 IS_VT1708B_4CH_VENDORID(codec
->vendor_id
)) {
607 snd_hda_codec_write(codec
, VT1708B_DIGIN_PIN
, 0,
608 AC_VERB_SET_PIN_WIDGET_CONTROL
,
610 snd_hda_codec_write(codec
, VT1708B_DIGIN_PIN
, 0,
611 AC_VERB_SET_EAPD_BTLENABLE
, 0x02);
613 } else /* enable SPDIF-input pin */
614 snd_hda_codec_write(codec
, spec
->autocfg
.dig_in_pin
, 0,
615 AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
);
620 #ifdef CONFIG_SND_HDA_POWER_SAVE
621 static int via_check_power_status(struct hda_codec
*codec
, hda_nid_t nid
)
623 struct via_spec
*spec
= codec
->spec
;
624 return snd_hda_check_amp_list_power(codec
, &spec
->loopback
, nid
);
630 static struct hda_codec_ops via_patch_ops
= {
631 .build_controls
= via_build_controls
,
632 .build_pcms
= via_build_pcms
,
635 #ifdef CONFIG_SND_HDA_POWER_SAVE
636 .check_power_status
= via_check_power_status
,
640 /* fill in the dac_nids table from the parsed pin configuration */
641 static int vt1708_auto_fill_dac_nids(struct via_spec
*spec
,
642 const struct auto_pin_cfg
*cfg
)
647 spec
->multiout
.num_dacs
= cfg
->line_outs
;
649 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
651 for(i
= 0; i
< 4; i
++) {
652 nid
= cfg
->line_out_pins
[i
];
654 /* config dac list */
657 spec
->multiout
.dac_nids
[i
] = 0x10;
659 case AUTO_SEQ_CENLFE
:
660 spec
->multiout
.dac_nids
[i
] = 0x12;
662 case AUTO_SEQ_SURROUND
:
663 spec
->multiout
.dac_nids
[i
] = 0x13;
666 spec
->multiout
.dac_nids
[i
] = 0x11;
675 /* add playback controls from the parsed DAC table */
676 static int vt1708_auto_create_multi_out_ctls(struct via_spec
*spec
,
677 const struct auto_pin_cfg
*cfg
)
680 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
681 hda_nid_t nid
, nid_vol
= 0;
684 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
685 nid
= cfg
->line_out_pins
[i
];
690 if (i
!= AUTO_SEQ_FRONT
)
691 nid_vol
= 0x1b - i
+ 1;
693 if (i
== AUTO_SEQ_CENLFE
) {
695 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
696 "Center Playback Volume",
697 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
701 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
702 "LFE Playback Volume",
703 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
707 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
708 "Center Playback Switch",
709 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
713 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
714 "LFE Playback Switch",
715 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
719 } else if (i
== AUTO_SEQ_FRONT
){
720 /* add control to mixer index 0 */
721 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
722 "Master Front Playback Volume",
723 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
727 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
728 "Master Front Playback Switch",
729 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
734 /* add control to PW3 */
735 sprintf(name
, "%s Playback Volume", chname
[i
]);
736 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
737 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
741 sprintf(name
, "%s Playback Switch", chname
[i
]);
742 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
743 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
748 sprintf(name
, "%s Playback Volume", chname
[i
]);
749 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
750 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
754 sprintf(name
, "%s Playback Switch", chname
[i
]);
755 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
756 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
766 static int vt1708_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
773 spec
->multiout
.hp_nid
= VT1708_HP_NID
; /* AOW3 */
775 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
776 "Headphone Playback Volume",
777 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
780 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
781 "Headphone Playback Switch",
782 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
789 /* create playback/capture controls for input pins */
790 static int vt1708_auto_create_analog_input_ctls(struct via_spec
*spec
,
791 const struct auto_pin_cfg
*cfg
)
793 static char *labels
[] = {
794 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
796 struct hda_input_mux
*imux
= &spec
->private_imux
;
799 /* for internal loopback recording select */
800 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
801 imux
->items
[imux
->num_items
].index
= idx
;
804 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
805 if (!cfg
->input_pins
[i
])
808 switch (cfg
->input_pins
[i
]) {
813 case 0x1e: /* Line In */
817 case 0x21: /* Front Mic */
825 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
829 imux
->items
[imux
->num_items
].label
= labels
[i
];
830 imux
->items
[imux
->num_items
].index
= idx
;
836 #ifdef CONFIG_SND_HDA_POWER_SAVE
837 static struct hda_amp_list vt1708_loopbacks
[] = {
838 { 0x17, HDA_INPUT
, 1 },
839 { 0x17, HDA_INPUT
, 2 },
840 { 0x17, HDA_INPUT
, 3 },
841 { 0x17, HDA_INPUT
, 4 },
846 static void vt1708_set_pinconfig_connect(struct hda_codec
*codec
, hda_nid_t nid
)
848 unsigned int def_conf
;
849 unsigned char seqassoc
;
851 def_conf
= snd_hda_codec_read(codec
, nid
, 0,
852 AC_VERB_GET_CONFIG_DEFAULT
, 0);
853 seqassoc
= (unsigned char) get_defcfg_association(def_conf
);
854 seqassoc
= (seqassoc
<< 4) | get_defcfg_sequence(def_conf
);
855 if (get_defcfg_connect(def_conf
) == AC_JACK_PORT_NONE
) {
856 if (seqassoc
== 0xff) {
857 def_conf
= def_conf
& (~(AC_JACK_PORT_BOTH
<< 30));
858 snd_hda_codec_write(codec
, nid
, 0,
859 AC_VERB_SET_CONFIG_DEFAULT_BYTES_3
,
867 static int vt1708_parse_auto_config(struct hda_codec
*codec
)
869 struct via_spec
*spec
= codec
->spec
;
872 /* Add HP and CD pin config connect bit re-config action */
873 vt1708_set_pinconfig_connect(codec
, VT1708_HP_PIN_NID
);
874 vt1708_set_pinconfig_connect(codec
, VT1708_CD_PIN_NID
);
876 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
879 err
= vt1708_auto_fill_dac_nids(spec
, &spec
->autocfg
);
882 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
883 return 0; /* can't find valid BIOS pin config */
885 err
= vt1708_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
888 err
= vt1708_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
891 err
= vt1708_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
895 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
897 if (spec
->autocfg
.dig_out_pin
)
898 spec
->multiout
.dig_out_nid
= VT1708_DIGOUT_NID
;
899 if (spec
->autocfg
.dig_in_pin
)
900 spec
->dig_in_nid
= VT1708_DIGIN_NID
;
902 if (spec
->kctl_alloc
)
903 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
905 spec
->init_verbs
= vt1708_volume_init_verbs
;
907 spec
->input_mux
= &spec
->private_imux
;
912 /* init callback for auto-configuration model -- overriding the default init */
913 static int via_auto_init(struct hda_codec
*codec
)
916 via_auto_init_multi_out(codec
);
917 via_auto_init_hp_out(codec
);
918 via_auto_init_analog_input(codec
);
922 static int patch_vt1708(struct hda_codec
*codec
)
924 struct via_spec
*spec
;
927 /* create a codec specific record */
928 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
934 /* automatic parse from the BIOS config */
935 err
= vt1708_parse_auto_config(codec
);
940 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
941 "from BIOS. Using genenic mode...\n");
945 spec
->stream_name_analog
= "VT1708 Analog";
946 spec
->stream_analog_playback
= &vt1708_pcm_analog_playback
;
947 /* disable 32bit format on VT1708 */
948 if (codec
->vendor_id
== 0x11061708)
949 spec
->stream_analog_playback
= &vt1708_pcm_analog_s16_playback
;
950 spec
->stream_analog_capture
= &vt1708_pcm_analog_capture
;
952 spec
->stream_name_digital
= "VT1708 Digital";
953 spec
->stream_digital_playback
= &vt1708_pcm_digital_playback
;
954 spec
->stream_digital_capture
= &vt1708_pcm_digital_capture
;
957 if (!spec
->adc_nids
&& spec
->input_mux
) {
958 spec
->adc_nids
= vt1708_adc_nids
;
959 spec
->num_adc_nids
= ARRAY_SIZE(vt1708_adc_nids
);
960 spec
->mixers
[spec
->num_mixers
] = vt1708_capture_mixer
;
964 codec
->patch_ops
= via_patch_ops
;
966 codec
->patch_ops
.init
= via_auto_init
;
967 #ifdef CONFIG_SND_HDA_POWER_SAVE
968 spec
->loopback
.amplist
= vt1708_loopbacks
;
974 /* capture mixer elements */
975 static struct snd_kcontrol_new vt1709_capture_mixer
[] = {
976 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT
),
977 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT
),
978 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT
),
979 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT
),
980 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT
),
981 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT
),
983 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
984 /* The multiple "Capture Source" controls confuse alsamixer
985 * So call somewhat different..
987 /* .name = "Capture Source", */
988 .name
= "Input Source",
990 .info
= via_mux_enum_info
,
991 .get
= via_mux_enum_get
,
992 .put
= via_mux_enum_put
,
998 * generic initialization of ADC, input mixers and output mixers
1000 static struct hda_verb vt1709_10ch_volume_init_verbs
[] = {
1002 * Unmute ADC0-2 and set the default input to mic-in
1004 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1005 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1006 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1009 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1012 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1013 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1014 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1015 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1016 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1017 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1020 * Set up output selector (0x1a, 0x1b, 0x29)
1022 /* set vol=0 to output mixers */
1023 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1024 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1025 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1028 * Unmute PW3 and PW4
1030 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1031 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1033 /* Set input of PW4 as AOW4 */
1034 {0x20, AC_VERB_SET_CONNECT_SEL
, 0x1},
1035 /* PW9 Output enable */
1036 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1040 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback
= {
1044 .nid
= 0x10, /* NID to query formats and rates */
1046 .open
= via_playback_pcm_open
,
1047 .prepare
= via_playback_pcm_prepare
,
1048 .cleanup
= via_playback_pcm_cleanup
1052 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback
= {
1056 .nid
= 0x10, /* NID to query formats and rates */
1058 .open
= via_playback_pcm_open
,
1059 .prepare
= via_playback_pcm_prepare
,
1060 .cleanup
= via_playback_pcm_cleanup
1064 static struct hda_pcm_stream vt1709_pcm_analog_capture
= {
1068 .nid
= 0x14, /* NID to query formats and rates */
1070 .prepare
= via_capture_pcm_prepare
,
1071 .cleanup
= via_capture_pcm_cleanup
1075 static struct hda_pcm_stream vt1709_pcm_digital_playback
= {
1079 /* NID is set in via_build_pcms */
1081 .open
= via_dig_playback_pcm_open
,
1082 .close
= via_dig_playback_pcm_close
1086 static struct hda_pcm_stream vt1709_pcm_digital_capture
= {
1092 static int vt1709_auto_fill_dac_nids(struct via_spec
*spec
,
1093 const struct auto_pin_cfg
*cfg
)
1098 if (cfg
->line_outs
== 4) /* 10 channels */
1099 spec
->multiout
.num_dacs
= cfg
->line_outs
+1; /* AOW0~AOW4 */
1100 else if (cfg
->line_outs
== 3) /* 6 channels */
1101 spec
->multiout
.num_dacs
= cfg
->line_outs
; /* AOW0~AOW2 */
1103 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
1105 if (cfg
->line_outs
== 4) { /* 10 channels */
1106 for (i
= 0; i
< cfg
->line_outs
; i
++) {
1107 nid
= cfg
->line_out_pins
[i
];
1109 /* config dac list */
1111 case AUTO_SEQ_FRONT
:
1113 spec
->multiout
.dac_nids
[i
] = 0x10;
1115 case AUTO_SEQ_CENLFE
:
1117 spec
->multiout
.dac_nids
[i
] = 0x12;
1119 case AUTO_SEQ_SURROUND
:
1121 spec
->multiout
.dac_nids
[i
] = 0x27;
1125 spec
->multiout
.dac_nids
[i
] = 0x11;
1132 spec
->multiout
.dac_nids
[cfg
->line_outs
] = 0x28; /* AOW4 */
1134 } else if (cfg
->line_outs
== 3) { /* 6 channels */
1135 for(i
= 0; i
< cfg
->line_outs
; i
++) {
1136 nid
= cfg
->line_out_pins
[i
];
1138 /* config dac list */
1140 case AUTO_SEQ_FRONT
:
1142 spec
->multiout
.dac_nids
[i
] = 0x10;
1144 case AUTO_SEQ_CENLFE
:
1146 spec
->multiout
.dac_nids
[i
] = 0x12;
1148 case AUTO_SEQ_SURROUND
:
1150 spec
->multiout
.dac_nids
[i
] = 0x11;
1162 /* add playback controls from the parsed DAC table */
1163 static int vt1709_auto_create_multi_out_ctls(struct via_spec
*spec
,
1164 const struct auto_pin_cfg
*cfg
)
1167 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
1171 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
1172 nid
= cfg
->line_out_pins
[i
];
1177 if (i
== AUTO_SEQ_CENLFE
) {
1179 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1180 "Center Playback Volume",
1181 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1185 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1186 "LFE Playback Volume",
1187 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1191 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1192 "Center Playback Switch",
1193 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1197 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1198 "LFE Playback Switch",
1199 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1203 } else if (i
== AUTO_SEQ_FRONT
){
1204 /* add control to mixer index 0 */
1205 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1206 "Master Front Playback Volume",
1207 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1211 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1212 "Master Front Playback Switch",
1213 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1218 /* add control to PW3 */
1219 sprintf(name
, "%s Playback Volume", chname
[i
]);
1220 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1221 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
1225 sprintf(name
, "%s Playback Switch", chname
[i
]);
1226 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1227 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
1231 } else if (i
== AUTO_SEQ_SURROUND
) {
1232 sprintf(name
, "%s Playback Volume", chname
[i
]);
1233 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1234 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1238 sprintf(name
, "%s Playback Switch", chname
[i
]);
1239 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1240 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1244 } else if (i
== AUTO_SEQ_SIDE
) {
1245 sprintf(name
, "%s Playback Volume", chname
[i
]);
1246 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1247 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1251 sprintf(name
, "%s Playback Switch", chname
[i
]);
1252 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1253 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1263 static int vt1709_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
1270 if (spec
->multiout
.num_dacs
== 5) /* 10 channels */
1271 spec
->multiout
.hp_nid
= VT1709_HP_DAC_NID
;
1272 else if (spec
->multiout
.num_dacs
== 3) /* 6 channels */
1273 spec
->multiout
.hp_nid
= 0;
1275 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1276 "Headphone Playback Volume",
1277 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1280 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1281 "Headphone Playback Switch",
1282 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1289 /* create playback/capture controls for input pins */
1290 static int vt1709_auto_create_analog_input_ctls(struct via_spec
*spec
,
1291 const struct auto_pin_cfg
*cfg
)
1293 static char *labels
[] = {
1294 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1296 struct hda_input_mux
*imux
= &spec
->private_imux
;
1297 int i
, err
, idx
= 0;
1299 /* for internal loopback recording select */
1300 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
1301 imux
->items
[imux
->num_items
].index
= idx
;
1304 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
1305 if (!cfg
->input_pins
[i
])
1308 switch (cfg
->input_pins
[i
]) {
1309 case 0x1d: /* Mic */
1313 case 0x1e: /* Line In */
1317 case 0x21: /* Front Mic */
1325 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
1329 imux
->items
[imux
->num_items
].label
= labels
[i
];
1330 imux
->items
[imux
->num_items
].index
= idx
;
1336 static int vt1709_parse_auto_config(struct hda_codec
*codec
)
1338 struct via_spec
*spec
= codec
->spec
;
1341 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
1344 err
= vt1709_auto_fill_dac_nids(spec
, &spec
->autocfg
);
1347 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
1348 return 0; /* can't find valid BIOS pin config */
1350 err
= vt1709_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
1353 err
= vt1709_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
1356 err
= vt1709_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
1360 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
1362 if (spec
->autocfg
.dig_out_pin
)
1363 spec
->multiout
.dig_out_nid
= VT1709_DIGOUT_NID
;
1364 if (spec
->autocfg
.dig_in_pin
)
1365 spec
->dig_in_nid
= VT1709_DIGIN_NID
;
1367 if (spec
->kctl_alloc
)
1368 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
1370 spec
->input_mux
= &spec
->private_imux
;
1375 #ifdef CONFIG_SND_HDA_POWER_SAVE
1376 static struct hda_amp_list vt1709_loopbacks
[] = {
1377 { 0x18, HDA_INPUT
, 1 },
1378 { 0x18, HDA_INPUT
, 2 },
1379 { 0x18, HDA_INPUT
, 3 },
1380 { 0x18, HDA_INPUT
, 4 },
1385 static int patch_vt1709_10ch(struct hda_codec
*codec
)
1387 struct via_spec
*spec
;
1390 /* create a codec specific record */
1391 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1397 err
= vt1709_parse_auto_config(codec
);
1402 printk(KERN_INFO
"hda_codec: Cannot set up configuration. "
1403 "Using genenic mode...\n");
1406 spec
->init_verbs
= vt1709_10ch_volume_init_verbs
;
1408 spec
->stream_name_analog
= "VT1709 Analog";
1409 spec
->stream_analog_playback
= &vt1709_10ch_pcm_analog_playback
;
1410 spec
->stream_analog_capture
= &vt1709_pcm_analog_capture
;
1412 spec
->stream_name_digital
= "VT1709 Digital";
1413 spec
->stream_digital_playback
= &vt1709_pcm_digital_playback
;
1414 spec
->stream_digital_capture
= &vt1709_pcm_digital_capture
;
1417 if (!spec
->adc_nids
&& spec
->input_mux
) {
1418 spec
->adc_nids
= vt1709_adc_nids
;
1419 spec
->num_adc_nids
= ARRAY_SIZE(vt1709_adc_nids
);
1420 spec
->mixers
[spec
->num_mixers
] = vt1709_capture_mixer
;
1424 codec
->patch_ops
= via_patch_ops
;
1426 codec
->patch_ops
.init
= via_auto_init
;
1427 #ifdef CONFIG_SND_HDA_POWER_SAVE
1428 spec
->loopback
.amplist
= vt1709_loopbacks
;
1434 * generic initialization of ADC, input mixers and output mixers
1436 static struct hda_verb vt1709_6ch_volume_init_verbs
[] = {
1438 * Unmute ADC0-2 and set the default input to mic-in
1440 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1441 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1442 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1445 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1448 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1449 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1450 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1451 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1452 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1453 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1456 * Set up output selector (0x1a, 0x1b, 0x29)
1458 /* set vol=0 to output mixers */
1459 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1460 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1461 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1464 * Unmute PW3 and PW4
1466 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1467 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1469 /* Set input of PW4 as MW0 */
1470 {0x20, AC_VERB_SET_CONNECT_SEL
, 0},
1471 /* PW9 Output enable */
1472 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1476 static int patch_vt1709_6ch(struct hda_codec
*codec
)
1478 struct via_spec
*spec
;
1481 /* create a codec specific record */
1482 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1488 err
= vt1709_parse_auto_config(codec
);
1493 printk(KERN_INFO
"hda_codec: Cannot set up configuration. "
1494 "Using genenic mode...\n");
1497 spec
->init_verbs
= vt1709_6ch_volume_init_verbs
;
1499 spec
->stream_name_analog
= "VT1709 Analog";
1500 spec
->stream_analog_playback
= &vt1709_6ch_pcm_analog_playback
;
1501 spec
->stream_analog_capture
= &vt1709_pcm_analog_capture
;
1503 spec
->stream_name_digital
= "VT1709 Digital";
1504 spec
->stream_digital_playback
= &vt1709_pcm_digital_playback
;
1505 spec
->stream_digital_capture
= &vt1709_pcm_digital_capture
;
1508 if (!spec
->adc_nids
&& spec
->input_mux
) {
1509 spec
->adc_nids
= vt1709_adc_nids
;
1510 spec
->num_adc_nids
= ARRAY_SIZE(vt1709_adc_nids
);
1511 spec
->mixers
[spec
->num_mixers
] = vt1709_capture_mixer
;
1515 codec
->patch_ops
= via_patch_ops
;
1517 codec
->patch_ops
.init
= via_auto_init
;
1518 #ifdef CONFIG_SND_HDA_POWER_SAVE
1519 spec
->loopback
.amplist
= vt1709_loopbacks
;
1524 /* capture mixer elements */
1525 static struct snd_kcontrol_new vt1708B_capture_mixer
[] = {
1526 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT
),
1527 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT
),
1528 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT
),
1529 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT
),
1531 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1532 /* The multiple "Capture Source" controls confuse alsamixer
1533 * So call somewhat different..
1535 /* .name = "Capture Source", */
1536 .name
= "Input Source",
1538 .info
= via_mux_enum_info
,
1539 .get
= via_mux_enum_get
,
1540 .put
= via_mux_enum_put
,
1545 * generic initialization of ADC, input mixers and output mixers
1547 static struct hda_verb vt1708B_8ch_volume_init_verbs
[] = {
1549 * Unmute ADC0-1 and set the default input to mic-in
1551 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1552 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1555 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1558 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1559 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1560 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1561 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1562 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1563 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1566 * Set up output mixers
1568 /* set vol=0 to output mixers */
1569 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1570 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1571 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1573 /* Setup default input to PW4 */
1574 {0x1d, AC_VERB_SET_CONNECT_SEL
, 0x1},
1575 /* PW9 Output enable */
1576 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1577 /* PW10 Input enable */
1578 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
1582 static struct hda_verb vt1708B_4ch_volume_init_verbs
[] = {
1584 * Unmute ADC0-1 and set the default input to mic-in
1586 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1587 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1590 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1593 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1594 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1595 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1596 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1597 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1598 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1601 * Set up output mixers
1603 /* set vol=0 to output mixers */
1604 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1605 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1606 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1608 /* Setup default input of PW4 to MW0 */
1609 {0x1d, AC_VERB_SET_CONNECT_SEL
, 0x0},
1610 /* PW9 Output enable */
1611 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1612 /* PW10 Input enable */
1613 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
1617 static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback
= {
1621 .nid
= 0x10, /* NID to query formats and rates */
1623 .open
= via_playback_pcm_open
,
1624 .prepare
= via_playback_pcm_prepare
,
1625 .cleanup
= via_playback_pcm_cleanup
1629 static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback
= {
1633 .nid
= 0x10, /* NID to query formats and rates */
1635 .open
= via_playback_pcm_open
,
1636 .prepare
= via_playback_pcm_prepare
,
1637 .cleanup
= via_playback_pcm_cleanup
1641 static struct hda_pcm_stream vt1708B_pcm_analog_capture
= {
1645 .nid
= 0x13, /* NID to query formats and rates */
1647 .prepare
= via_capture_pcm_prepare
,
1648 .cleanup
= via_capture_pcm_cleanup
1652 static struct hda_pcm_stream vt1708B_pcm_digital_playback
= {
1656 /* NID is set in via_build_pcms */
1658 .open
= via_dig_playback_pcm_open
,
1659 .close
= via_dig_playback_pcm_close
,
1660 .prepare
= via_dig_playback_pcm_prepare
1664 static struct hda_pcm_stream vt1708B_pcm_digital_capture
= {
1670 /* fill in the dac_nids table from the parsed pin configuration */
1671 static int vt1708B_auto_fill_dac_nids(struct via_spec
*spec
,
1672 const struct auto_pin_cfg
*cfg
)
1677 spec
->multiout
.num_dacs
= cfg
->line_outs
;
1679 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
1681 for (i
= 0; i
< 4; i
++) {
1682 nid
= cfg
->line_out_pins
[i
];
1684 /* config dac list */
1686 case AUTO_SEQ_FRONT
:
1687 spec
->multiout
.dac_nids
[i
] = 0x10;
1689 case AUTO_SEQ_CENLFE
:
1690 spec
->multiout
.dac_nids
[i
] = 0x24;
1692 case AUTO_SEQ_SURROUND
:
1693 spec
->multiout
.dac_nids
[i
] = 0x25;
1696 spec
->multiout
.dac_nids
[i
] = 0x11;
1705 /* add playback controls from the parsed DAC table */
1706 static int vt1708B_auto_create_multi_out_ctls(struct via_spec
*spec
,
1707 const struct auto_pin_cfg
*cfg
)
1710 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
1711 hda_nid_t nid_vols
[] = {0x16, 0x27, 0x26, 0x18};
1712 hda_nid_t nid
, nid_vol
= 0;
1715 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
1716 nid
= cfg
->line_out_pins
[i
];
1721 nid_vol
= nid_vols
[i
];
1723 if (i
== AUTO_SEQ_CENLFE
) {
1725 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1726 "Center Playback Volume",
1727 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
1731 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1732 "LFE Playback Volume",
1733 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
1737 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1738 "Center Playback Switch",
1739 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
1743 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1744 "LFE Playback Switch",
1745 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
1749 } else if (i
== AUTO_SEQ_FRONT
) {
1750 /* add control to mixer index 0 */
1751 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1752 "Master Front Playback Volume",
1753 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1757 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1758 "Master Front Playback Switch",
1759 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1764 /* add control to PW3 */
1765 sprintf(name
, "%s Playback Volume", chname
[i
]);
1766 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1767 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
1771 sprintf(name
, "%s Playback Switch", chname
[i
]);
1772 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1773 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
1778 sprintf(name
, "%s Playback Volume", chname
[i
]);
1779 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1780 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1784 sprintf(name
, "%s Playback Switch", chname
[i
]);
1785 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1786 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1796 static int vt1708B_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
1803 spec
->multiout
.hp_nid
= VT1708B_HP_NID
; /* AOW3 */
1805 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1806 "Headphone Playback Volume",
1807 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1810 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1811 "Headphone Playback Switch",
1812 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1819 /* create playback/capture controls for input pins */
1820 static int vt1708B_auto_create_analog_input_ctls(struct via_spec
*spec
,
1821 const struct auto_pin_cfg
*cfg
)
1823 static char *labels
[] = {
1824 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1826 struct hda_input_mux
*imux
= &spec
->private_imux
;
1827 int i
, err
, idx
= 0;
1829 /* for internal loopback recording select */
1830 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
1831 imux
->items
[imux
->num_items
].index
= idx
;
1834 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
1835 if (!cfg
->input_pins
[i
])
1838 switch (cfg
->input_pins
[i
]) {
1839 case 0x1a: /* Mic */
1843 case 0x1b: /* Line In */
1847 case 0x1e: /* Front Mic */
1855 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
1859 imux
->items
[imux
->num_items
].label
= labels
[i
];
1860 imux
->items
[imux
->num_items
].index
= idx
;
1866 static int vt1708B_parse_auto_config(struct hda_codec
*codec
)
1868 struct via_spec
*spec
= codec
->spec
;
1871 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
1874 err
= vt1708B_auto_fill_dac_nids(spec
, &spec
->autocfg
);
1877 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
1878 return 0; /* can't find valid BIOS pin config */
1880 err
= vt1708B_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
1883 err
= vt1708B_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
1886 err
= vt1708B_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
1890 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
1892 if (spec
->autocfg
.dig_out_pin
)
1893 spec
->multiout
.dig_out_nid
= VT1708B_DIGOUT_NID
;
1894 if (spec
->autocfg
.dig_in_pin
)
1895 spec
->dig_in_nid
= VT1708B_DIGIN_NID
;
1897 if (spec
->kctl_alloc
)
1898 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
1900 spec
->input_mux
= &spec
->private_imux
;
1905 #ifdef CONFIG_SND_HDA_POWER_SAVE
1906 static struct hda_amp_list vt1708B_loopbacks
[] = {
1907 { 0x16, HDA_INPUT
, 1 },
1908 { 0x16, HDA_INPUT
, 2 },
1909 { 0x16, HDA_INPUT
, 3 },
1910 { 0x16, HDA_INPUT
, 4 },
1915 static int patch_vt1708B_8ch(struct hda_codec
*codec
)
1917 struct via_spec
*spec
;
1920 /* create a codec specific record */
1921 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1927 /* automatic parse from the BIOS config */
1928 err
= vt1708B_parse_auto_config(codec
);
1933 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
1934 "from BIOS. Using genenic mode...\n");
1937 spec
->init_verbs
= vt1708B_8ch_volume_init_verbs
;
1939 spec
->stream_name_analog
= "VT1708B Analog";
1940 spec
->stream_analog_playback
= &vt1708B_8ch_pcm_analog_playback
;
1941 spec
->stream_analog_capture
= &vt1708B_pcm_analog_capture
;
1943 spec
->stream_name_digital
= "VT1708B Digital";
1944 spec
->stream_digital_playback
= &vt1708B_pcm_digital_playback
;
1945 spec
->stream_digital_capture
= &vt1708B_pcm_digital_capture
;
1947 if (!spec
->adc_nids
&& spec
->input_mux
) {
1948 spec
->adc_nids
= vt1708B_adc_nids
;
1949 spec
->num_adc_nids
= ARRAY_SIZE(vt1708B_adc_nids
);
1950 spec
->mixers
[spec
->num_mixers
] = vt1708B_capture_mixer
;
1954 codec
->patch_ops
= via_patch_ops
;
1956 codec
->patch_ops
.init
= via_auto_init
;
1957 #ifdef CONFIG_SND_HDA_POWER_SAVE
1958 spec
->loopback
.amplist
= vt1708B_loopbacks
;
1964 static int patch_vt1708B_4ch(struct hda_codec
*codec
)
1966 struct via_spec
*spec
;
1969 /* create a codec specific record */
1970 spec
= kzalloc(sizeof(*spec
), GFP_KERNEL
);
1976 /* automatic parse from the BIOS config */
1977 err
= vt1708B_parse_auto_config(codec
);
1982 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
1983 "from BIOS. Using genenic mode...\n");
1986 spec
->init_verbs
= vt1708B_4ch_volume_init_verbs
;
1988 spec
->stream_name_analog
= "VT1708B Analog";
1989 spec
->stream_analog_playback
= &vt1708B_4ch_pcm_analog_playback
;
1990 spec
->stream_analog_capture
= &vt1708B_pcm_analog_capture
;
1992 spec
->stream_name_digital
= "VT1708B Digital";
1993 spec
->stream_digital_playback
= &vt1708B_pcm_digital_playback
;
1994 spec
->stream_digital_capture
= &vt1708B_pcm_digital_capture
;
1996 if (!spec
->adc_nids
&& spec
->input_mux
) {
1997 spec
->adc_nids
= vt1708B_adc_nids
;
1998 spec
->num_adc_nids
= ARRAY_SIZE(vt1708B_adc_nids
);
1999 spec
->mixers
[spec
->num_mixers
] = vt1708B_capture_mixer
;
2003 codec
->patch_ops
= via_patch_ops
;
2005 codec
->patch_ops
.init
= via_auto_init
;
2006 #ifdef CONFIG_SND_HDA_POWER_SAVE
2007 spec
->loopback
.amplist
= vt1708B_loopbacks
;
2016 struct hda_codec_preset snd_hda_preset_via
[] = {
2017 { .id
= 0x11061708, .name
= "VIA VT1708", .patch
= patch_vt1708
},
2018 { .id
= 0x11061709, .name
= "VIA VT1708", .patch
= patch_vt1708
},
2019 { .id
= 0x1106170A, .name
= "VIA VT1708", .patch
= patch_vt1708
},
2020 { .id
= 0x1106170B, .name
= "VIA VT1708", .patch
= patch_vt1708
},
2021 { .id
= 0x1106E710, .name
= "VIA VT1709 10-Ch",
2022 .patch
= patch_vt1709_10ch
},
2023 { .id
= 0x1106E711, .name
= "VIA VT1709 10-Ch",
2024 .patch
= patch_vt1709_10ch
},
2025 { .id
= 0x1106E712, .name
= "VIA VT1709 10-Ch",
2026 .patch
= patch_vt1709_10ch
},
2027 { .id
= 0x1106E713, .name
= "VIA VT1709 10-Ch",
2028 .patch
= patch_vt1709_10ch
},
2029 { .id
= 0x1106E714, .name
= "VIA VT1709 6-Ch",
2030 .patch
= patch_vt1709_6ch
},
2031 { .id
= 0x1106E715, .name
= "VIA VT1709 6-Ch",
2032 .patch
= patch_vt1709_6ch
},
2033 { .id
= 0x1106E716, .name
= "VIA VT1709 6-Ch",
2034 .patch
= patch_vt1709_6ch
},
2035 { .id
= 0x1106E717, .name
= "VIA VT1709 6-Ch",
2036 .patch
= patch_vt1709_6ch
},
2037 { .id
= 0x1106E720, .name
= "VIA VT1708B 8-Ch",
2038 .patch
= patch_vt1708B_8ch
},
2039 { .id
= 0x1106E721, .name
= "VIA VT1708B 8-Ch",
2040 .patch
= patch_vt1708B_8ch
},
2041 { .id
= 0x1106E722, .name
= "VIA VT1708B 8-Ch",
2042 .patch
= patch_vt1708B_8ch
},
2043 { .id
= 0x1106E723, .name
= "VIA VT1708B 8-Ch",
2044 .patch
= patch_vt1708B_8ch
},
2045 { .id
= 0x1106E724, .name
= "VIA VT1708B 4-Ch",
2046 .patch
= patch_vt1708B_4ch
},
2047 { .id
= 0x1106E725, .name
= "VIA VT1708B 4-Ch",
2048 .patch
= patch_vt1708B_4ch
},
2049 { .id
= 0x1106E726, .name
= "VIA VT1708B 4-Ch",
2050 .patch
= patch_vt1708B_4ch
},
2051 { .id
= 0x1106E727, .name
= "VIA VT1708B 4-Ch",
2052 .patch
= patch_vt1708B_4ch
},