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_capture
= {
454 .nid
= 0x15, /* NID to query formats and rates */
456 .prepare
= via_capture_pcm_prepare
,
457 .cleanup
= via_capture_pcm_cleanup
461 static struct hda_pcm_stream vt1708_pcm_digital_playback
= {
465 /* NID is set in via_build_pcms */
467 .open
= via_dig_playback_pcm_open
,
468 .close
= via_dig_playback_pcm_close
,
469 .prepare
= via_dig_playback_pcm_prepare
473 static struct hda_pcm_stream vt1708_pcm_digital_capture
= {
479 static int via_build_controls(struct hda_codec
*codec
)
481 struct via_spec
*spec
= codec
->spec
;
485 for (i
= 0; i
< spec
->num_mixers
; i
++) {
486 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
491 if (spec
->multiout
.dig_out_nid
) {
492 err
= snd_hda_create_spdif_out_ctls(codec
,
493 spec
->multiout
.dig_out_nid
);
496 err
= snd_hda_create_spdif_share_sw(codec
,
500 spec
->multiout
.share_spdif
= 1;
502 if (spec
->dig_in_nid
) {
503 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
510 static int via_build_pcms(struct hda_codec
*codec
)
512 struct via_spec
*spec
= codec
->spec
;
513 struct hda_pcm
*info
= spec
->pcm_rec
;
516 codec
->pcm_info
= info
;
518 info
->name
= spec
->stream_name_analog
;
519 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_analog_playback
);
520 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
521 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_analog_capture
);
522 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
524 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
=
525 spec
->multiout
.max_channels
;
527 if (spec
->multiout
.dig_out_nid
|| spec
->dig_in_nid
) {
530 info
->name
= spec
->stream_name_digital
;
531 info
->pcm_type
= HDA_PCM_TYPE_SPDIF
;
532 if (spec
->multiout
.dig_out_nid
) {
533 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
534 *(spec
->stream_digital_playback
);
535 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
=
536 spec
->multiout
.dig_out_nid
;
538 if (spec
->dig_in_nid
) {
539 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] =
540 *(spec
->stream_digital_capture
);
541 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
=
549 static void via_free(struct hda_codec
*codec
)
551 struct via_spec
*spec
= codec
->spec
;
557 if (spec
->kctl_alloc
) {
558 for (i
= 0; i
< spec
->num_kctl_used
; i
++)
559 kfree(spec
->kctl_alloc
[i
].name
);
560 kfree(spec
->kctl_alloc
);
566 static int via_init(struct hda_codec
*codec
)
568 struct via_spec
*spec
= codec
->spec
;
569 snd_hda_sequence_write(codec
, spec
->init_verbs
);
570 /* Lydia Add for EAPD enable */
571 if (!spec
->dig_in_nid
) { /* No Digital In connection */
572 if (IS_VT1708_VENDORID(codec
->vendor_id
)) {
573 snd_hda_codec_write(codec
, VT1708_DIGIN_PIN
, 0,
574 AC_VERB_SET_PIN_WIDGET_CONTROL
,
576 snd_hda_codec_write(codec
, VT1708_DIGIN_PIN
, 0,
577 AC_VERB_SET_EAPD_BTLENABLE
, 0x02);
578 } else if (IS_VT1709_10CH_VENDORID(codec
->vendor_id
) ||
579 IS_VT1709_6CH_VENDORID(codec
->vendor_id
)) {
580 snd_hda_codec_write(codec
, VT1709_DIGIN_PIN
, 0,
581 AC_VERB_SET_PIN_WIDGET_CONTROL
,
583 snd_hda_codec_write(codec
, VT1709_DIGIN_PIN
, 0,
584 AC_VERB_SET_EAPD_BTLENABLE
, 0x02);
585 } else if (IS_VT1708B_8CH_VENDORID(codec
->vendor_id
) ||
586 IS_VT1708B_4CH_VENDORID(codec
->vendor_id
)) {
587 snd_hda_codec_write(codec
, VT1708B_DIGIN_PIN
, 0,
588 AC_VERB_SET_PIN_WIDGET_CONTROL
,
590 snd_hda_codec_write(codec
, VT1708B_DIGIN_PIN
, 0,
591 AC_VERB_SET_EAPD_BTLENABLE
, 0x02);
593 } else /* enable SPDIF-input pin */
594 snd_hda_codec_write(codec
, spec
->autocfg
.dig_in_pin
, 0,
595 AC_VERB_SET_PIN_WIDGET_CONTROL
, PIN_IN
);
600 #ifdef CONFIG_SND_HDA_POWER_SAVE
601 static int via_check_power_status(struct hda_codec
*codec
, hda_nid_t nid
)
603 struct via_spec
*spec
= codec
->spec
;
604 return snd_hda_check_amp_list_power(codec
, &spec
->loopback
, nid
);
610 static struct hda_codec_ops via_patch_ops
= {
611 .build_controls
= via_build_controls
,
612 .build_pcms
= via_build_pcms
,
615 #ifdef CONFIG_SND_HDA_POWER_SAVE
616 .check_power_status
= via_check_power_status
,
620 /* fill in the dac_nids table from the parsed pin configuration */
621 static int vt1708_auto_fill_dac_nids(struct via_spec
*spec
,
622 const struct auto_pin_cfg
*cfg
)
627 spec
->multiout
.num_dacs
= cfg
->line_outs
;
629 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
631 for(i
= 0; i
< 4; i
++) {
632 nid
= cfg
->line_out_pins
[i
];
634 /* config dac list */
637 spec
->multiout
.dac_nids
[i
] = 0x10;
639 case AUTO_SEQ_CENLFE
:
640 spec
->multiout
.dac_nids
[i
] = 0x12;
642 case AUTO_SEQ_SURROUND
:
643 spec
->multiout
.dac_nids
[i
] = 0x13;
646 spec
->multiout
.dac_nids
[i
] = 0x11;
655 /* add playback controls from the parsed DAC table */
656 static int vt1708_auto_create_multi_out_ctls(struct via_spec
*spec
,
657 const struct auto_pin_cfg
*cfg
)
660 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
661 hda_nid_t nid
, nid_vol
= 0;
664 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
665 nid
= cfg
->line_out_pins
[i
];
670 if (i
!= AUTO_SEQ_FRONT
)
671 nid_vol
= 0x1b - i
+ 1;
673 if (i
== AUTO_SEQ_CENLFE
) {
675 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
676 "Center Playback Volume",
677 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
681 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
682 "LFE Playback Volume",
683 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
687 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
688 "Center Playback Switch",
689 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
693 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
694 "LFE Playback Switch",
695 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
699 } else if (i
== AUTO_SEQ_FRONT
){
700 /* add control to mixer index 0 */
701 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
702 "Master Front Playback Volume",
703 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
707 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
708 "Master Front Playback Switch",
709 HDA_COMPOSE_AMP_VAL(0x17, 3, 0,
714 /* add control to PW3 */
715 sprintf(name
, "%s Playback Volume", chname
[i
]);
716 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
717 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
721 sprintf(name
, "%s Playback Switch", chname
[i
]);
722 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
723 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
728 sprintf(name
, "%s Playback Volume", chname
[i
]);
729 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
730 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
734 sprintf(name
, "%s Playback Switch", chname
[i
]);
735 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
736 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
746 static int vt1708_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
753 spec
->multiout
.hp_nid
= VT1708_HP_NID
; /* AOW3 */
755 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
756 "Headphone Playback Volume",
757 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
760 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
761 "Headphone Playback Switch",
762 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
769 /* create playback/capture controls for input pins */
770 static int vt1708_auto_create_analog_input_ctls(struct via_spec
*spec
,
771 const struct auto_pin_cfg
*cfg
)
773 static char *labels
[] = {
774 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
776 struct hda_input_mux
*imux
= &spec
->private_imux
;
779 /* for internal loopback recording select */
780 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
781 imux
->items
[imux
->num_items
].index
= idx
;
784 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
785 if (!cfg
->input_pins
[i
])
788 switch (cfg
->input_pins
[i
]) {
793 case 0x1e: /* Line In */
797 case 0x21: /* Front Mic */
805 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
809 imux
->items
[imux
->num_items
].label
= labels
[i
];
810 imux
->items
[imux
->num_items
].index
= idx
;
816 #ifdef CONFIG_SND_HDA_POWER_SAVE
817 static struct hda_amp_list vt1708_loopbacks
[] = {
818 { 0x17, HDA_INPUT
, 1 },
819 { 0x17, HDA_INPUT
, 2 },
820 { 0x17, HDA_INPUT
, 3 },
821 { 0x17, HDA_INPUT
, 4 },
826 static int vt1708_parse_auto_config(struct hda_codec
*codec
)
828 struct via_spec
*spec
= codec
->spec
;
831 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
834 err
= vt1708_auto_fill_dac_nids(spec
, &spec
->autocfg
);
837 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
838 return 0; /* can't find valid BIOS pin config */
840 err
= vt1708_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
843 err
= vt1708_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
846 err
= vt1708_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
850 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
852 if (spec
->autocfg
.dig_out_pin
)
853 spec
->multiout
.dig_out_nid
= VT1708_DIGOUT_NID
;
854 if (spec
->autocfg
.dig_in_pin
)
855 spec
->dig_in_nid
= VT1708_DIGIN_NID
;
857 if (spec
->kctl_alloc
)
858 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
860 spec
->init_verbs
= vt1708_volume_init_verbs
;
862 spec
->input_mux
= &spec
->private_imux
;
867 /* init callback for auto-configuration model -- overriding the default init */
868 static int via_auto_init(struct hda_codec
*codec
)
871 via_auto_init_multi_out(codec
);
872 via_auto_init_hp_out(codec
);
873 via_auto_init_analog_input(codec
);
877 static int patch_vt1708(struct hda_codec
*codec
)
879 struct via_spec
*spec
;
882 /* create a codec specific record */
883 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
889 /* automatic parse from the BIOS config */
890 err
= vt1708_parse_auto_config(codec
);
895 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
896 "from BIOS. Using genenic mode...\n");
900 spec
->stream_name_analog
= "VT1708 Analog";
901 spec
->stream_analog_playback
= &vt1708_pcm_analog_playback
;
902 spec
->stream_analog_capture
= &vt1708_pcm_analog_capture
;
904 spec
->stream_name_digital
= "VT1708 Digital";
905 spec
->stream_digital_playback
= &vt1708_pcm_digital_playback
;
906 spec
->stream_digital_capture
= &vt1708_pcm_digital_capture
;
909 if (!spec
->adc_nids
&& spec
->input_mux
) {
910 spec
->adc_nids
= vt1708_adc_nids
;
911 spec
->num_adc_nids
= ARRAY_SIZE(vt1708_adc_nids
);
912 spec
->mixers
[spec
->num_mixers
] = vt1708_capture_mixer
;
916 codec
->patch_ops
= via_patch_ops
;
918 codec
->patch_ops
.init
= via_auto_init
;
919 #ifdef CONFIG_SND_HDA_POWER_SAVE
920 spec
->loopback
.amplist
= vt1708_loopbacks
;
926 /* capture mixer elements */
927 static struct snd_kcontrol_new vt1709_capture_mixer
[] = {
928 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT
),
929 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT
),
930 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT
),
931 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT
),
932 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT
),
933 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT
),
935 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
936 /* The multiple "Capture Source" controls confuse alsamixer
937 * So call somewhat different..
939 /* .name = "Capture Source", */
940 .name
= "Input Source",
942 .info
= via_mux_enum_info
,
943 .get
= via_mux_enum_get
,
944 .put
= via_mux_enum_put
,
950 * generic initialization of ADC, input mixers and output mixers
952 static struct hda_verb vt1709_10ch_volume_init_verbs
[] = {
954 * Unmute ADC0-2 and set the default input to mic-in
956 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
957 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
958 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
961 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
964 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
965 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
966 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
967 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
968 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
969 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
972 * Set up output selector (0x1a, 0x1b, 0x29)
974 /* set vol=0 to output mixers */
975 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
976 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
977 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
982 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
983 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
985 /* Set input of PW4 as AOW4 */
986 {0x20, AC_VERB_SET_CONNECT_SEL
, 0x1},
987 /* PW9 Output enable */
988 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
992 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback
= {
996 .nid
= 0x10, /* NID to query formats and rates */
998 .open
= via_playback_pcm_open
,
999 .prepare
= via_playback_pcm_prepare
,
1000 .cleanup
= via_playback_pcm_cleanup
1004 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback
= {
1008 .nid
= 0x10, /* NID to query formats and rates */
1010 .open
= via_playback_pcm_open
,
1011 .prepare
= via_playback_pcm_prepare
,
1012 .cleanup
= via_playback_pcm_cleanup
1016 static struct hda_pcm_stream vt1709_pcm_analog_capture
= {
1020 .nid
= 0x14, /* NID to query formats and rates */
1022 .prepare
= via_capture_pcm_prepare
,
1023 .cleanup
= via_capture_pcm_cleanup
1027 static struct hda_pcm_stream vt1709_pcm_digital_playback
= {
1031 /* NID is set in via_build_pcms */
1033 .open
= via_dig_playback_pcm_open
,
1034 .close
= via_dig_playback_pcm_close
1038 static struct hda_pcm_stream vt1709_pcm_digital_capture
= {
1044 static int vt1709_auto_fill_dac_nids(struct via_spec
*spec
,
1045 const struct auto_pin_cfg
*cfg
)
1050 if (cfg
->line_outs
== 4) /* 10 channels */
1051 spec
->multiout
.num_dacs
= cfg
->line_outs
+1; /* AOW0~AOW4 */
1052 else if (cfg
->line_outs
== 3) /* 6 channels */
1053 spec
->multiout
.num_dacs
= cfg
->line_outs
; /* AOW0~AOW2 */
1055 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
1057 if (cfg
->line_outs
== 4) { /* 10 channels */
1058 for (i
= 0; i
< cfg
->line_outs
; i
++) {
1059 nid
= cfg
->line_out_pins
[i
];
1061 /* config dac list */
1063 case AUTO_SEQ_FRONT
:
1065 spec
->multiout
.dac_nids
[i
] = 0x10;
1067 case AUTO_SEQ_CENLFE
:
1069 spec
->multiout
.dac_nids
[i
] = 0x12;
1071 case AUTO_SEQ_SURROUND
:
1073 spec
->multiout
.dac_nids
[i
] = 0x27;
1077 spec
->multiout
.dac_nids
[i
] = 0x11;
1084 spec
->multiout
.dac_nids
[cfg
->line_outs
] = 0x28; /* AOW4 */
1086 } else if (cfg
->line_outs
== 3) { /* 6 channels */
1087 for(i
= 0; i
< cfg
->line_outs
; i
++) {
1088 nid
= cfg
->line_out_pins
[i
];
1090 /* config dac list */
1092 case AUTO_SEQ_FRONT
:
1094 spec
->multiout
.dac_nids
[i
] = 0x10;
1096 case AUTO_SEQ_CENLFE
:
1098 spec
->multiout
.dac_nids
[i
] = 0x12;
1100 case AUTO_SEQ_SURROUND
:
1102 spec
->multiout
.dac_nids
[i
] = 0x11;
1114 /* add playback controls from the parsed DAC table */
1115 static int vt1709_auto_create_multi_out_ctls(struct via_spec
*spec
,
1116 const struct auto_pin_cfg
*cfg
)
1119 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
1123 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
1124 nid
= cfg
->line_out_pins
[i
];
1129 if (i
== AUTO_SEQ_CENLFE
) {
1131 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1132 "Center Playback Volume",
1133 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1137 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1138 "LFE Playback Volume",
1139 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1143 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1144 "Center Playback Switch",
1145 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0,
1149 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1150 "LFE Playback Switch",
1151 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0,
1155 } else if (i
== AUTO_SEQ_FRONT
){
1156 /* add control to mixer index 0 */
1157 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1158 "Master Front Playback Volume",
1159 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1163 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1164 "Master Front Playback Switch",
1165 HDA_COMPOSE_AMP_VAL(0x18, 3, 0,
1170 /* add control to PW3 */
1171 sprintf(name
, "%s Playback Volume", chname
[i
]);
1172 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1173 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
1177 sprintf(name
, "%s Playback Switch", chname
[i
]);
1178 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1179 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
1183 } else if (i
== AUTO_SEQ_SURROUND
) {
1184 sprintf(name
, "%s Playback Volume", chname
[i
]);
1185 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1186 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1190 sprintf(name
, "%s Playback Switch", chname
[i
]);
1191 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1192 HDA_COMPOSE_AMP_VAL(0x29, 3, 0,
1196 } else if (i
== AUTO_SEQ_SIDE
) {
1197 sprintf(name
, "%s Playback Volume", chname
[i
]);
1198 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1199 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1203 sprintf(name
, "%s Playback Switch", chname
[i
]);
1204 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1205 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0,
1215 static int vt1709_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
1222 if (spec
->multiout
.num_dacs
== 5) /* 10 channels */
1223 spec
->multiout
.hp_nid
= VT1709_HP_DAC_NID
;
1224 else if (spec
->multiout
.num_dacs
== 3) /* 6 channels */
1225 spec
->multiout
.hp_nid
= 0;
1227 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1228 "Headphone Playback Volume",
1229 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1232 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1233 "Headphone Playback Switch",
1234 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1241 /* create playback/capture controls for input pins */
1242 static int vt1709_auto_create_analog_input_ctls(struct via_spec
*spec
,
1243 const struct auto_pin_cfg
*cfg
)
1245 static char *labels
[] = {
1246 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1248 struct hda_input_mux
*imux
= &spec
->private_imux
;
1249 int i
, err
, idx
= 0;
1251 /* for internal loopback recording select */
1252 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
1253 imux
->items
[imux
->num_items
].index
= idx
;
1256 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
1257 if (!cfg
->input_pins
[i
])
1260 switch (cfg
->input_pins
[i
]) {
1261 case 0x1d: /* Mic */
1265 case 0x1e: /* Line In */
1269 case 0x21: /* Front Mic */
1277 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
1281 imux
->items
[imux
->num_items
].label
= labels
[i
];
1282 imux
->items
[imux
->num_items
].index
= idx
;
1288 static int vt1709_parse_auto_config(struct hda_codec
*codec
)
1290 struct via_spec
*spec
= codec
->spec
;
1293 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
1296 err
= vt1709_auto_fill_dac_nids(spec
, &spec
->autocfg
);
1299 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
1300 return 0; /* can't find valid BIOS pin config */
1302 err
= vt1709_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
1305 err
= vt1709_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
1308 err
= vt1709_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
1312 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
1314 if (spec
->autocfg
.dig_out_pin
)
1315 spec
->multiout
.dig_out_nid
= VT1709_DIGOUT_NID
;
1316 if (spec
->autocfg
.dig_in_pin
)
1317 spec
->dig_in_nid
= VT1709_DIGIN_NID
;
1319 if (spec
->kctl_alloc
)
1320 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
1322 spec
->input_mux
= &spec
->private_imux
;
1327 #ifdef CONFIG_SND_HDA_POWER_SAVE
1328 static struct hda_amp_list vt1709_loopbacks
[] = {
1329 { 0x18, HDA_INPUT
, 1 },
1330 { 0x18, HDA_INPUT
, 2 },
1331 { 0x18, HDA_INPUT
, 3 },
1332 { 0x18, HDA_INPUT
, 4 },
1337 static int patch_vt1709_10ch(struct hda_codec
*codec
)
1339 struct via_spec
*spec
;
1342 /* create a codec specific record */
1343 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1349 err
= vt1709_parse_auto_config(codec
);
1354 printk(KERN_INFO
"hda_codec: Cannot set up configuration. "
1355 "Using genenic mode...\n");
1358 spec
->init_verbs
= vt1709_10ch_volume_init_verbs
;
1360 spec
->stream_name_analog
= "VT1709 Analog";
1361 spec
->stream_analog_playback
= &vt1709_10ch_pcm_analog_playback
;
1362 spec
->stream_analog_capture
= &vt1709_pcm_analog_capture
;
1364 spec
->stream_name_digital
= "VT1709 Digital";
1365 spec
->stream_digital_playback
= &vt1709_pcm_digital_playback
;
1366 spec
->stream_digital_capture
= &vt1709_pcm_digital_capture
;
1369 if (!spec
->adc_nids
&& spec
->input_mux
) {
1370 spec
->adc_nids
= vt1709_adc_nids
;
1371 spec
->num_adc_nids
= ARRAY_SIZE(vt1709_adc_nids
);
1372 spec
->mixers
[spec
->num_mixers
] = vt1709_capture_mixer
;
1376 codec
->patch_ops
= via_patch_ops
;
1378 codec
->patch_ops
.init
= via_auto_init
;
1379 #ifdef CONFIG_SND_HDA_POWER_SAVE
1380 spec
->loopback
.amplist
= vt1709_loopbacks
;
1386 * generic initialization of ADC, input mixers and output mixers
1388 static struct hda_verb vt1709_6ch_volume_init_verbs
[] = {
1390 * Unmute ADC0-2 and set the default input to mic-in
1392 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1393 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1394 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1397 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1400 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1401 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1402 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1403 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1404 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1405 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1408 * Set up output selector (0x1a, 0x1b, 0x29)
1410 /* set vol=0 to output mixers */
1411 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1412 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1413 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1416 * Unmute PW3 and PW4
1418 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1419 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1421 /* Set input of PW4 as MW0 */
1422 {0x20, AC_VERB_SET_CONNECT_SEL
, 0},
1423 /* PW9 Output enable */
1424 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1428 static int patch_vt1709_6ch(struct hda_codec
*codec
)
1430 struct via_spec
*spec
;
1433 /* create a codec specific record */
1434 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1440 err
= vt1709_parse_auto_config(codec
);
1445 printk(KERN_INFO
"hda_codec: Cannot set up configuration. "
1446 "Using genenic mode...\n");
1449 spec
->init_verbs
= vt1709_6ch_volume_init_verbs
;
1451 spec
->stream_name_analog
= "VT1709 Analog";
1452 spec
->stream_analog_playback
= &vt1709_6ch_pcm_analog_playback
;
1453 spec
->stream_analog_capture
= &vt1709_pcm_analog_capture
;
1455 spec
->stream_name_digital
= "VT1709 Digital";
1456 spec
->stream_digital_playback
= &vt1709_pcm_digital_playback
;
1457 spec
->stream_digital_capture
= &vt1709_pcm_digital_capture
;
1460 if (!spec
->adc_nids
&& spec
->input_mux
) {
1461 spec
->adc_nids
= vt1709_adc_nids
;
1462 spec
->num_adc_nids
= ARRAY_SIZE(vt1709_adc_nids
);
1463 spec
->mixers
[spec
->num_mixers
] = vt1709_capture_mixer
;
1467 codec
->patch_ops
= via_patch_ops
;
1469 codec
->patch_ops
.init
= via_auto_init
;
1470 #ifdef CONFIG_SND_HDA_POWER_SAVE
1471 spec
->loopback
.amplist
= vt1709_loopbacks
;
1476 /* capture mixer elements */
1477 static struct snd_kcontrol_new vt1708B_capture_mixer
[] = {
1478 HDA_CODEC_VOLUME("Capture Volume", 0x13, 0x0, HDA_INPUT
),
1479 HDA_CODEC_MUTE("Capture Switch", 0x13, 0x0, HDA_INPUT
),
1480 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x14, 0x0, HDA_INPUT
),
1481 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x14, 0x0, HDA_INPUT
),
1483 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
1484 /* The multiple "Capture Source" controls confuse alsamixer
1485 * So call somewhat different..
1487 /* .name = "Capture Source", */
1488 .name
= "Input Source",
1490 .info
= via_mux_enum_info
,
1491 .get
= via_mux_enum_get
,
1492 .put
= via_mux_enum_put
,
1497 * generic initialization of ADC, input mixers and output mixers
1499 static struct hda_verb vt1708B_8ch_volume_init_verbs
[] = {
1501 * Unmute ADC0-1 and set the default input to mic-in
1503 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1504 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1507 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1510 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1511 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1512 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1513 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1514 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1515 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1518 * Set up output mixers
1520 /* set vol=0 to output mixers */
1521 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1522 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1523 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1525 /* Setup default input to PW4 */
1526 {0x1d, AC_VERB_SET_CONNECT_SEL
, 0x1},
1527 /* PW9 Output enable */
1528 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1529 /* PW10 Input enable */
1530 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
1534 static struct hda_verb vt1708B_4ch_volume_init_verbs
[] = {
1536 * Unmute ADC0-1 and set the default input to mic-in
1538 {0x13, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1539 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1542 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1545 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1546 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1547 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1548 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1549 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1550 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1553 * Set up output mixers
1555 /* set vol=0 to output mixers */
1556 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1557 {0x26, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1558 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1560 /* Setup default input of PW4 to MW0 */
1561 {0x1d, AC_VERB_SET_CONNECT_SEL
, 0x0},
1562 /* PW9 Output enable */
1563 {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1564 /* PW10 Input enable */
1565 {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x20},
1569 static struct hda_pcm_stream vt1708B_8ch_pcm_analog_playback
= {
1573 .nid
= 0x10, /* NID to query formats and rates */
1575 .open
= via_playback_pcm_open
,
1576 .prepare
= via_playback_pcm_prepare
,
1577 .cleanup
= via_playback_pcm_cleanup
1581 static struct hda_pcm_stream vt1708B_4ch_pcm_analog_playback
= {
1585 .nid
= 0x10, /* NID to query formats and rates */
1587 .open
= via_playback_pcm_open
,
1588 .prepare
= via_playback_pcm_prepare
,
1589 .cleanup
= via_playback_pcm_cleanup
1593 static struct hda_pcm_stream vt1708B_pcm_analog_capture
= {
1597 .nid
= 0x13, /* NID to query formats and rates */
1599 .prepare
= via_capture_pcm_prepare
,
1600 .cleanup
= via_capture_pcm_cleanup
1604 static struct hda_pcm_stream vt1708B_pcm_digital_playback
= {
1608 /* NID is set in via_build_pcms */
1610 .open
= via_dig_playback_pcm_open
,
1611 .close
= via_dig_playback_pcm_close
,
1612 .prepare
= via_dig_playback_pcm_prepare
1616 static struct hda_pcm_stream vt1708B_pcm_digital_capture
= {
1622 /* fill in the dac_nids table from the parsed pin configuration */
1623 static int vt1708B_auto_fill_dac_nids(struct via_spec
*spec
,
1624 const struct auto_pin_cfg
*cfg
)
1629 spec
->multiout
.num_dacs
= cfg
->line_outs
;
1631 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
1633 for (i
= 0; i
< 4; i
++) {
1634 nid
= cfg
->line_out_pins
[i
];
1636 /* config dac list */
1638 case AUTO_SEQ_FRONT
:
1639 spec
->multiout
.dac_nids
[i
] = 0x10;
1641 case AUTO_SEQ_CENLFE
:
1642 spec
->multiout
.dac_nids
[i
] = 0x24;
1644 case AUTO_SEQ_SURROUND
:
1645 spec
->multiout
.dac_nids
[i
] = 0x25;
1648 spec
->multiout
.dac_nids
[i
] = 0x11;
1657 /* add playback controls from the parsed DAC table */
1658 static int vt1708B_auto_create_multi_out_ctls(struct via_spec
*spec
,
1659 const struct auto_pin_cfg
*cfg
)
1662 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
1663 hda_nid_t nid_vols
[] = {0x16, 0x27, 0x26, 0x18};
1664 hda_nid_t nid
, nid_vol
= 0;
1667 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
1668 nid
= cfg
->line_out_pins
[i
];
1673 nid_vol
= nid_vols
[i
];
1675 if (i
== AUTO_SEQ_CENLFE
) {
1677 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1678 "Center Playback Volume",
1679 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
1683 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1684 "LFE Playback Volume",
1685 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
1689 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1690 "Center Playback Switch",
1691 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0,
1695 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1696 "LFE Playback Switch",
1697 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0,
1701 } else if (i
== AUTO_SEQ_FRONT
) {
1702 /* add control to mixer index 0 */
1703 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1704 "Master Front Playback Volume",
1705 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1709 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1710 "Master Front Playback Switch",
1711 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1716 /* add control to PW3 */
1717 sprintf(name
, "%s Playback Volume", chname
[i
]);
1718 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1719 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
1723 sprintf(name
, "%s Playback Switch", chname
[i
]);
1724 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1725 HDA_COMPOSE_AMP_VAL(nid
, 3, 0,
1730 sprintf(name
, "%s Playback Volume", chname
[i
]);
1731 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1732 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1736 sprintf(name
, "%s Playback Switch", chname
[i
]);
1737 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1738 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0,
1748 static int vt1708B_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
1755 spec
->multiout
.hp_nid
= VT1708B_HP_NID
; /* AOW3 */
1757 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1758 "Headphone Playback Volume",
1759 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1762 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1763 "Headphone Playback Switch",
1764 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1771 /* create playback/capture controls for input pins */
1772 static int vt1708B_auto_create_analog_input_ctls(struct via_spec
*spec
,
1773 const struct auto_pin_cfg
*cfg
)
1775 static char *labels
[] = {
1776 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1778 struct hda_input_mux
*imux
= &spec
->private_imux
;
1779 int i
, err
, idx
= 0;
1781 /* for internal loopback recording select */
1782 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
1783 imux
->items
[imux
->num_items
].index
= idx
;
1786 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
1787 if (!cfg
->input_pins
[i
])
1790 switch (cfg
->input_pins
[i
]) {
1791 case 0x1a: /* Mic */
1795 case 0x1b: /* Line In */
1799 case 0x1e: /* Front Mic */
1807 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
1811 imux
->items
[imux
->num_items
].label
= labels
[i
];
1812 imux
->items
[imux
->num_items
].index
= idx
;
1818 static int vt1708B_parse_auto_config(struct hda_codec
*codec
)
1820 struct via_spec
*spec
= codec
->spec
;
1823 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
1826 err
= vt1708B_auto_fill_dac_nids(spec
, &spec
->autocfg
);
1829 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
1830 return 0; /* can't find valid BIOS pin config */
1832 err
= vt1708B_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
1835 err
= vt1708B_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
1838 err
= vt1708B_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
1842 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
1844 if (spec
->autocfg
.dig_out_pin
)
1845 spec
->multiout
.dig_out_nid
= VT1708B_DIGOUT_NID
;
1846 if (spec
->autocfg
.dig_in_pin
)
1847 spec
->dig_in_nid
= VT1708B_DIGIN_NID
;
1849 if (spec
->kctl_alloc
)
1850 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
1852 spec
->input_mux
= &spec
->private_imux
;
1857 #ifdef CONFIG_SND_HDA_POWER_SAVE
1858 static struct hda_amp_list vt1708B_loopbacks
[] = {
1859 { 0x16, HDA_INPUT
, 1 },
1860 { 0x16, HDA_INPUT
, 2 },
1861 { 0x16, HDA_INPUT
, 3 },
1862 { 0x16, HDA_INPUT
, 4 },
1867 static int patch_vt1708B_8ch(struct hda_codec
*codec
)
1869 struct via_spec
*spec
;
1872 /* create a codec specific record */
1873 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1879 /* automatic parse from the BIOS config */
1880 err
= vt1708B_parse_auto_config(codec
);
1885 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
1886 "from BIOS. Using genenic mode...\n");
1889 spec
->init_verbs
= vt1708B_8ch_volume_init_verbs
;
1891 spec
->stream_name_analog
= "VT1708B Analog";
1892 spec
->stream_analog_playback
= &vt1708B_8ch_pcm_analog_playback
;
1893 spec
->stream_analog_capture
= &vt1708B_pcm_analog_capture
;
1895 spec
->stream_name_digital
= "VT1708B Digital";
1896 spec
->stream_digital_playback
= &vt1708B_pcm_digital_playback
;
1897 spec
->stream_digital_capture
= &vt1708B_pcm_digital_capture
;
1899 if (!spec
->adc_nids
&& spec
->input_mux
) {
1900 spec
->adc_nids
= vt1708B_adc_nids
;
1901 spec
->num_adc_nids
= ARRAY_SIZE(vt1708B_adc_nids
);
1902 spec
->mixers
[spec
->num_mixers
] = vt1708B_capture_mixer
;
1906 codec
->patch_ops
= via_patch_ops
;
1908 codec
->patch_ops
.init
= via_auto_init
;
1909 #ifdef CONFIG_SND_HDA_POWER_SAVE
1910 spec
->loopback
.amplist
= vt1708B_loopbacks
;
1916 static int patch_vt1708B_4ch(struct hda_codec
*codec
)
1918 struct via_spec
*spec
;
1921 /* create a codec specific record */
1922 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1928 /* automatic parse from the BIOS config */
1929 err
= vt1708B_parse_auto_config(codec
);
1934 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
1935 "from BIOS. Using genenic mode...\n");
1938 spec
->init_verbs
= vt1708B_4ch_volume_init_verbs
;
1940 spec
->stream_name_analog
= "VT1708B Analog";
1941 spec
->stream_analog_playback
= &vt1708B_4ch_pcm_analog_playback
;
1942 spec
->stream_analog_capture
= &vt1708B_pcm_analog_capture
;
1944 spec
->stream_name_digital
= "VT1708B Digital";
1945 spec
->stream_digital_playback
= &vt1708B_pcm_digital_playback
;
1946 spec
->stream_digital_capture
= &vt1708B_pcm_digital_capture
;
1948 if (!spec
->adc_nids
&& spec
->input_mux
) {
1949 spec
->adc_nids
= vt1708B_adc_nids
;
1950 spec
->num_adc_nids
= ARRAY_SIZE(vt1708B_adc_nids
);
1951 spec
->mixers
[spec
->num_mixers
] = vt1708B_capture_mixer
;
1955 codec
->patch_ops
= via_patch_ops
;
1957 codec
->patch_ops
.init
= via_auto_init
;
1958 #ifdef CONFIG_SND_HDA_POWER_SAVE
1959 spec
->loopback
.amplist
= vt1708B_loopbacks
;
1968 struct hda_codec_preset snd_hda_preset_via
[] = {
1969 { .id
= 0x11061708, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1970 { .id
= 0x11061709, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1971 { .id
= 0x1106170A, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1972 { .id
= 0x1106170B, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1973 { .id
= 0x1106E710, .name
= "VIA VT1709 10-Ch",
1974 .patch
= patch_vt1709_10ch
},
1975 { .id
= 0x1106E711, .name
= "VIA VT1709 10-Ch",
1976 .patch
= patch_vt1709_10ch
},
1977 { .id
= 0x1106E712, .name
= "VIA VT1709 10-Ch",
1978 .patch
= patch_vt1709_10ch
},
1979 { .id
= 0x1106E713, .name
= "VIA VT1709 10-Ch",
1980 .patch
= patch_vt1709_10ch
},
1981 { .id
= 0x1106E714, .name
= "VIA VT1709 6-Ch",
1982 .patch
= patch_vt1709_6ch
},
1983 { .id
= 0x1106E715, .name
= "VIA VT1709 6-Ch",
1984 .patch
= patch_vt1709_6ch
},
1985 { .id
= 0x1106E716, .name
= "VIA VT1709 6-Ch",
1986 .patch
= patch_vt1709_6ch
},
1987 { .id
= 0x1106E717, .name
= "VIA VT1709 6-Ch",
1988 .patch
= patch_vt1709_6ch
},
1989 { .id
= 0x1106E720, .name
= "VIA VT1708B 8-Ch",
1990 .patch
= patch_vt1708B_8ch
},
1991 { .id
= 0x1106E721, .name
= "VIA VT1708B 8-Ch",
1992 .patch
= patch_vt1708B_8ch
},
1993 { .id
= 0x1106E722, .name
= "VIA VT1708B 8-Ch",
1994 .patch
= patch_vt1708B_8ch
},
1995 { .id
= 0x1106E723, .name
= "VIA VT1708B 8-Ch",
1996 .patch
= patch_vt1708B_8ch
},
1997 { .id
= 0x1106E724, .name
= "VIA VT1708B 4-Ch",
1998 .patch
= patch_vt1708B_4ch
},
1999 { .id
= 0x1106E725, .name
= "VIA VT1708B 4-Ch",
2000 .patch
= patch_vt1708B_4ch
},
2001 { .id
= 0x1106E726, .name
= "VIA VT1708B 4-Ch",
2002 .patch
= patch_vt1708B_4ch
},
2003 { .id
= 0x1106E727, .name
= "VIA VT1708B 4-Ch",
2004 .patch
= patch_vt1708B_4ch
},