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 */
31 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
34 #include <sound/driver.h>
35 #include <linux/init.h>
36 #include <linux/delay.h>
37 #include <linux/slab.h>
38 #include <linux/pci.h>
39 #include <sound/core.h>
40 #include "hda_codec.h"
41 #include "hda_local.h"
45 #define AMP_VAL_IDX_SHIFT 19
46 #define AMP_VAL_IDX_MASK (0x0f<<19)
48 #define NUM_CONTROL_ALLOC 32
49 #define NUM_VERB_ALLOC 32
52 #define VT1708_HP_NID 0x13
53 #define VT1708_DIGOUT_NID 0x14
54 #define VT1708_DIGIN_NID 0x16
56 #define VT1709_HP_DAC_NID 0x28
57 #define VT1709_DIGOUT_NID 0x13
58 #define VT1709_DIGIN_NID 0x17
60 #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
61 #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
62 #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
77 static struct snd_kcontrol_new vt1708_control_templates
[] = {
78 HDA_CODEC_VOLUME(NULL
, 0, 0, 0),
79 HDA_CODEC_MUTE(NULL
, 0, 0, 0),
84 /* codec parameterization */
85 struct snd_kcontrol_new
*mixers
[3];
86 unsigned int num_mixers
;
88 struct hda_verb
*init_verbs
;
90 char *stream_name_analog
;
91 struct hda_pcm_stream
*stream_analog_playback
;
92 struct hda_pcm_stream
*stream_analog_capture
;
94 char *stream_name_digital
;
95 struct hda_pcm_stream
*stream_digital_playback
;
96 struct hda_pcm_stream
*stream_digital_capture
;
99 struct hda_multi_out multiout
;
102 unsigned int num_adc_nids
;
104 hda_nid_t dig_in_nid
;
107 const struct hda_input_mux
*input_mux
;
108 unsigned int cur_mux
[3];
110 /* PCM information */
111 struct hda_pcm pcm_rec
[2];
113 /* dynamic controls, init_verbs and input_mux */
114 struct auto_pin_cfg autocfg
;
115 unsigned int num_kctl_alloc
, num_kctl_used
;
116 struct snd_kcontrol_new
*kctl_alloc
;
117 struct hda_input_mux private_imux
;
118 hda_nid_t private_dac_nids
[4];
121 static hda_nid_t vt1708_adc_nids
[2] = {
126 static hda_nid_t vt1709_adc_nids
[3] = {
131 /* add dynamic controls */
132 static int via_add_control(struct via_spec
*spec
, int type
, const char *name
,
135 struct snd_kcontrol_new
*knew
;
137 if (spec
->num_kctl_used
>= spec
->num_kctl_alloc
) {
138 int num
= spec
->num_kctl_alloc
+ NUM_CONTROL_ALLOC
;
140 /* array + terminator */
141 knew
= kcalloc(num
+ 1, sizeof(*knew
), GFP_KERNEL
);
144 if (spec
->kctl_alloc
) {
145 memcpy(knew
, spec
->kctl_alloc
,
146 sizeof(*knew
) * spec
->num_kctl_alloc
);
147 kfree(spec
->kctl_alloc
);
149 spec
->kctl_alloc
= knew
;
150 spec
->num_kctl_alloc
= num
;
153 knew
= &spec
->kctl_alloc
[spec
->num_kctl_used
];
154 *knew
= vt1708_control_templates
[type
];
155 knew
->name
= kstrdup(name
, GFP_KERNEL
);
159 knew
->private_value
= val
;
160 spec
->num_kctl_used
++;
164 /* create input playback/capture controls for the given pin */
165 static int via_new_analog_input(struct via_spec
*spec
, hda_nid_t pin
,
166 const char *ctlname
, int idx
, int mix_nid
)
171 sprintf(name
, "%s Playback Volume", ctlname
);
172 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
173 HDA_COMPOSE_AMP_VAL(mix_nid
, 3, idx
, HDA_INPUT
));
176 sprintf(name
, "%s Playback Switch", ctlname
);
177 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
178 HDA_COMPOSE_AMP_VAL(mix_nid
, 3, idx
, HDA_INPUT
));
184 static void via_auto_set_output_and_unmute(struct hda_codec
*codec
,
185 hda_nid_t nid
, int pin_type
,
189 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
191 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
196 static void via_auto_init_multi_out(struct hda_codec
*codec
)
198 struct via_spec
*spec
= codec
->spec
;
201 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
202 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
204 via_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
208 static void via_auto_init_hp_out(struct hda_codec
*codec
)
210 struct via_spec
*spec
= codec
->spec
;
213 pin
= spec
->autocfg
.hp_pins
[0];
214 if (pin
) /* connect to front */
215 via_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0);
218 static void via_auto_init_analog_input(struct hda_codec
*codec
)
220 struct via_spec
*spec
= codec
->spec
;
223 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
224 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
226 snd_hda_codec_write(codec
, nid
, 0,
227 AC_VERB_SET_PIN_WIDGET_CONTROL
,
228 (i
<= AUTO_PIN_FRONT_MIC
?
229 PIN_VREF50
: PIN_IN
));
236 static int via_mux_enum_info(struct snd_kcontrol
*kcontrol
,
237 struct snd_ctl_elem_info
*uinfo
)
239 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
240 struct via_spec
*spec
= codec
->spec
;
241 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
244 static int via_mux_enum_get(struct snd_kcontrol
*kcontrol
,
245 struct snd_ctl_elem_value
*ucontrol
)
247 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
248 struct via_spec
*spec
= codec
->spec
;
249 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
251 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
255 static int via_mux_enum_put(struct snd_kcontrol
*kcontrol
,
256 struct snd_ctl_elem_value
*ucontrol
)
258 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
259 struct via_spec
*spec
= codec
->spec
;
260 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
261 unsigned int vendor_id
= codec
->vendor_id
;
263 /* AIW0 lydia 060801 add for correct sw0 input select */
264 if (IS_VT1708_VENDORID(vendor_id
) && (adc_idx
== 0))
265 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
266 0x18, &spec
->cur_mux
[adc_idx
]);
267 else if ((IS_VT1709_10CH_VENDORID(vendor_id
) ||
268 IS_VT1709_6CH_VENDORID(vendor_id
)) && (adc_idx
== 0) )
269 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
270 0x19, &spec
->cur_mux
[adc_idx
]);
272 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
273 spec
->adc_nids
[adc_idx
],
274 &spec
->cur_mux
[adc_idx
]);
277 /* capture mixer elements */
278 static struct snd_kcontrol_new vt1708_capture_mixer
[] = {
279 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT
),
280 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT
),
281 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT
),
282 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT
),
284 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
285 /* The multiple "Capture Source" controls confuse alsamixer
286 * So call somewhat different..
287 * FIXME: the controls appear in the "playback" view!
289 /* .name = "Capture Source", */
290 .name
= "Input Source",
292 .info
= via_mux_enum_info
,
293 .get
= via_mux_enum_get
,
294 .put
= via_mux_enum_put
,
299 * generic initialization of ADC, input mixers and output mixers
301 static struct hda_verb vt1708_volume_init_verbs
[] = {
303 * Unmute ADC0-1 and set the default input to mic-in
305 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
306 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
309 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
312 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
313 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
314 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
315 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
316 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
317 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
320 * Set up output mixers (0x19 - 0x1b)
322 /* set vol=0 to output mixers */
323 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
324 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
325 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
327 /* Setup default input to PW4 */
328 {0x20, AC_VERB_SET_CONNECT_SEL
, 0x1},
329 /* Set mic as default input of sw0 */
330 {0x18, AC_VERB_SET_CONNECT_SEL
, 0x2},
331 /* PW9 Output enable */
332 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
335 static int via_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
336 struct hda_codec
*codec
,
337 struct snd_pcm_substream
*substream
)
339 struct via_spec
*spec
= codec
->spec
;
340 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
);
343 static int via_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
344 struct hda_codec
*codec
,
345 unsigned int stream_tag
,
347 struct snd_pcm_substream
*substream
)
349 struct via_spec
*spec
= codec
->spec
;
350 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
,
351 stream_tag
, format
, substream
);
354 static int via_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
355 struct hda_codec
*codec
,
356 struct snd_pcm_substream
*substream
)
358 struct via_spec
*spec
= codec
->spec
;
359 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
365 static int via_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
366 struct hda_codec
*codec
,
367 struct snd_pcm_substream
*substream
)
369 struct via_spec
*spec
= codec
->spec
;
370 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
373 static int via_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
374 struct hda_codec
*codec
,
375 struct snd_pcm_substream
*substream
)
377 struct via_spec
*spec
= codec
->spec
;
378 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
384 static int via_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
385 struct hda_codec
*codec
,
386 unsigned int stream_tag
,
388 struct snd_pcm_substream
*substream
)
390 struct via_spec
*spec
= codec
->spec
;
392 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
393 stream_tag
, 0, format
);
397 static int via_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
398 struct hda_codec
*codec
,
399 struct snd_pcm_substream
*substream
)
401 struct via_spec
*spec
= codec
->spec
;
402 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
407 static struct hda_pcm_stream vt1708_pcm_analog_playback
= {
411 .nid
= 0x10, /* NID to query formats and rates */
413 .open
= via_playback_pcm_open
,
414 .prepare
= via_playback_pcm_prepare
,
415 .cleanup
= via_playback_pcm_cleanup
419 static struct hda_pcm_stream vt1708_pcm_analog_capture
= {
423 .nid
= 0x15, /* NID to query formats and rates */
425 .prepare
= via_capture_pcm_prepare
,
426 .cleanup
= via_capture_pcm_cleanup
430 static struct hda_pcm_stream vt1708_pcm_digital_playback
= {
434 /* NID is set in via_build_pcms */
436 .open
= via_dig_playback_pcm_open
,
437 .close
= via_dig_playback_pcm_close
441 static struct hda_pcm_stream vt1708_pcm_digital_capture
= {
447 static int via_build_controls(struct hda_codec
*codec
)
449 struct via_spec
*spec
= codec
->spec
;
453 for (i
= 0; i
< spec
->num_mixers
; i
++) {
454 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
459 if (spec
->multiout
.dig_out_nid
) {
460 err
= snd_hda_create_spdif_out_ctls(codec
,
461 spec
->multiout
.dig_out_nid
);
465 if (spec
->dig_in_nid
) {
466 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
473 static int via_build_pcms(struct hda_codec
*codec
)
475 struct via_spec
*spec
= codec
->spec
;
476 struct hda_pcm
*info
= spec
->pcm_rec
;
479 codec
->pcm_info
= info
;
481 info
->name
= spec
->stream_name_analog
;
482 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_analog_playback
);
483 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
484 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_analog_capture
);
485 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
487 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
=
488 spec
->multiout
.max_channels
;
490 if (spec
->multiout
.dig_out_nid
|| spec
->dig_in_nid
) {
493 info
->name
= spec
->stream_name_digital
;
494 if (spec
->multiout
.dig_out_nid
) {
495 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
496 *(spec
->stream_digital_playback
);
497 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
=
498 spec
->multiout
.dig_out_nid
;
500 if (spec
->dig_in_nid
) {
501 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] =
502 *(spec
->stream_digital_capture
);
503 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
=
511 static void via_free(struct hda_codec
*codec
)
513 struct via_spec
*spec
= codec
->spec
;
519 if (spec
->kctl_alloc
) {
520 for (i
= 0; i
< spec
->num_kctl_used
; i
++)
521 kfree(spec
->kctl_alloc
[i
].name
);
522 kfree(spec
->kctl_alloc
);
528 static int via_init(struct hda_codec
*codec
)
530 struct via_spec
*spec
= codec
->spec
;
531 snd_hda_sequence_write(codec
, spec
->init_verbs
);
539 static int via_resume(struct hda_codec
*codec
)
541 struct via_spec
*spec
= codec
->spec
;
545 for (i
= 0; i
< spec
->num_mixers
; i
++)
546 snd_hda_resume_ctls(codec
, spec
->mixers
[i
]);
547 if (spec
->multiout
.dig_out_nid
)
548 snd_hda_resume_spdif_out(codec
);
549 if (spec
->dig_in_nid
)
550 snd_hda_resume_spdif_in(codec
);
558 static struct hda_codec_ops via_patch_ops
= {
559 .build_controls
= via_build_controls
,
560 .build_pcms
= via_build_pcms
,
564 .resume
= via_resume
,
568 /* fill in the dac_nids table from the parsed pin configuration */
569 static int vt1708_auto_fill_dac_nids(struct via_spec
*spec
,
570 const struct auto_pin_cfg
*cfg
)
575 spec
->multiout
.num_dacs
= cfg
->line_outs
;
577 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
579 for(i
= 0; i
< 4; i
++) {
580 nid
= cfg
->line_out_pins
[i
];
582 /* config dac list */
585 spec
->multiout
.dac_nids
[i
] = 0x10;
587 case AUTO_SEQ_CENLFE
:
588 spec
->multiout
.dac_nids
[i
] = 0x12;
590 case AUTO_SEQ_SURROUND
:
591 spec
->multiout
.dac_nids
[i
] = 0x13;
594 spec
->multiout
.dac_nids
[i
] = 0x11;
603 /* add playback controls from the parsed DAC table */
604 static int vt1708_auto_create_multi_out_ctls(struct via_spec
*spec
,
605 const struct auto_pin_cfg
*cfg
)
608 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
609 hda_nid_t nid
, nid_vol
= 0;
612 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
613 nid
= cfg
->line_out_pins
[i
];
618 if (i
!= AUTO_SEQ_FRONT
)
619 nid_vol
= 0x1b - i
+ 1;
621 if (i
== AUTO_SEQ_CENLFE
) {
623 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
624 "Center Playback Volume",
625 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0, HDA_OUTPUT
));
628 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
629 "LFE Playback Volume",
630 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0, HDA_OUTPUT
));
633 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
634 "Center Playback Switch",
635 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0, HDA_OUTPUT
));
638 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
639 "LFE Playback Switch",
640 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0, HDA_OUTPUT
));
643 } else if (i
== AUTO_SEQ_FRONT
){
644 /* add control to mixer index 0 */
645 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
646 "Master Front Playback Volume",
647 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT
));
650 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
651 "Master Front Playback Switch",
652 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT
));
656 /* add control to PW3 */
657 sprintf(name
, "%s Playback Volume", chname
[i
]);
658 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
659 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
662 sprintf(name
, "%s Playback Switch", chname
[i
]);
663 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
664 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
668 sprintf(name
, "%s Playback Volume", chname
[i
]);
669 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
670 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0, HDA_OUTPUT
));
673 sprintf(name
, "%s Playback Switch", chname
[i
]);
674 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
675 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0, HDA_OUTPUT
));
684 static int vt1708_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
691 spec
->multiout
.hp_nid
= VT1708_HP_NID
; /* AOW3 */
693 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
694 "Headphone Playback Volume",
695 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
698 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
699 "Headphone Playback Switch",
700 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
707 /* create playback/capture controls for input pins */
708 static int vt1708_auto_create_analog_input_ctls(struct via_spec
*spec
,
709 const struct auto_pin_cfg
*cfg
)
711 static char *labels
[] = {
712 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
714 struct hda_input_mux
*imux
= &spec
->private_imux
;
717 /* for internal loopback recording select */
718 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
719 imux
->items
[imux
->num_items
].index
= idx
;
722 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
723 if (!cfg
->input_pins
[i
])
726 switch (cfg
->input_pins
[i
]) {
731 case 0x1e: /* Line In */
735 case 0x21: /* Front Mic */
743 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
747 imux
->items
[imux
->num_items
].label
= labels
[i
];
748 imux
->items
[imux
->num_items
].index
= idx
;
754 static int vt1708_parse_auto_config(struct hda_codec
*codec
)
756 struct via_spec
*spec
= codec
->spec
;
759 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
762 err
= vt1708_auto_fill_dac_nids(spec
, &spec
->autocfg
);
765 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
766 return 0; /* can't find valid BIOS pin config */
768 err
= vt1708_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
771 err
= vt1708_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
774 err
= vt1708_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
778 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
780 if (spec
->autocfg
.dig_out_pin
)
781 spec
->multiout
.dig_out_nid
= VT1708_DIGOUT_NID
;
782 if (spec
->autocfg
.dig_in_pin
)
783 spec
->dig_in_nid
= VT1708_DIGIN_NID
;
785 if (spec
->kctl_alloc
)
786 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
788 spec
->init_verbs
= vt1708_volume_init_verbs
;
790 spec
->input_mux
= &spec
->private_imux
;
795 /* init callback for auto-configuration model -- overriding the default init */
796 static int via_auto_init(struct hda_codec
*codec
)
799 via_auto_init_multi_out(codec
);
800 via_auto_init_hp_out(codec
);
801 via_auto_init_analog_input(codec
);
805 static int patch_vt1708(struct hda_codec
*codec
)
807 struct via_spec
*spec
;
810 /* create a codec specific record */
811 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
817 /* automatic parse from the BIOS config */
818 err
= vt1708_parse_auto_config(codec
);
823 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
824 "from BIOS. Using genenic mode...\n");
828 spec
->stream_name_analog
= "VT1708 Analog";
829 spec
->stream_analog_playback
= &vt1708_pcm_analog_playback
;
830 spec
->stream_analog_capture
= &vt1708_pcm_analog_capture
;
832 spec
->stream_name_digital
= "VT1708 Digital";
833 spec
->stream_digital_playback
= &vt1708_pcm_digital_playback
;
834 spec
->stream_digital_capture
= &vt1708_pcm_digital_capture
;
837 if (!spec
->adc_nids
&& spec
->input_mux
) {
838 spec
->adc_nids
= vt1708_adc_nids
;
839 spec
->num_adc_nids
= ARRAY_SIZE(vt1708_adc_nids
);
840 spec
->mixers
[spec
->num_mixers
] = vt1708_capture_mixer
;
844 codec
->patch_ops
= via_patch_ops
;
846 codec
->patch_ops
.init
= via_auto_init
;
851 /* capture mixer elements */
852 static struct snd_kcontrol_new vt1709_capture_mixer
[] = {
853 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT
),
854 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT
),
855 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT
),
856 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT
),
857 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT
),
858 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT
),
860 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
861 /* The multiple "Capture Source" controls confuse alsamixer
862 * So call somewhat different..
863 * FIXME: the controls appear in the "playback" view!
865 /* .name = "Capture Source", */
866 .name
= "Input Source",
868 .info
= via_mux_enum_info
,
869 .get
= via_mux_enum_get
,
870 .put
= via_mux_enum_put
,
876 * generic initialization of ADC, input mixers and output mixers
878 static struct hda_verb vt1709_10ch_volume_init_verbs
[] = {
880 * Unmute ADC0-2 and set the default input to mic-in
882 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
883 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
884 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
887 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
890 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
891 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
892 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
893 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
894 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
895 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
898 * Set up output selector (0x1a, 0x1b, 0x29)
900 /* set vol=0 to output mixers */
901 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
902 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
903 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
908 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
909 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
911 /* Set input of PW4 as AOW4 */
912 {0x20, AC_VERB_SET_CONNECT_SEL
, 0x1},
913 /* Set mic as default input of sw0 */
914 {0x19, AC_VERB_SET_CONNECT_SEL
, 0x2},
915 /* PW9 Output enable */
916 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
920 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback
= {
924 .nid
= 0x10, /* NID to query formats and rates */
926 .open
= via_playback_pcm_open
,
927 .prepare
= via_playback_pcm_prepare
,
928 .cleanup
= via_playback_pcm_cleanup
932 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback
= {
936 .nid
= 0x10, /* NID to query formats and rates */
938 .open
= via_playback_pcm_open
,
939 .prepare
= via_playback_pcm_prepare
,
940 .cleanup
= via_playback_pcm_cleanup
944 static struct hda_pcm_stream vt1709_pcm_analog_capture
= {
948 .nid
= 0x14, /* NID to query formats and rates */
950 .prepare
= via_capture_pcm_prepare
,
951 .cleanup
= via_capture_pcm_cleanup
955 static struct hda_pcm_stream vt1709_pcm_digital_playback
= {
959 /* NID is set in via_build_pcms */
961 .open
= via_dig_playback_pcm_open
,
962 .close
= via_dig_playback_pcm_close
966 static struct hda_pcm_stream vt1709_pcm_digital_capture
= {
972 static int vt1709_auto_fill_dac_nids(struct via_spec
*spec
,
973 const struct auto_pin_cfg
*cfg
)
978 if (cfg
->line_outs
== 4) /* 10 channels */
979 spec
->multiout
.num_dacs
= cfg
->line_outs
+1; /* AOW0~AOW4 */
980 else if (cfg
->line_outs
== 3) /* 6 channels */
981 spec
->multiout
.num_dacs
= cfg
->line_outs
; /* AOW0~AOW2 */
983 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
985 if (cfg
->line_outs
== 4) { /* 10 channels */
986 for (i
= 0; i
< cfg
->line_outs
; i
++) {
987 nid
= cfg
->line_out_pins
[i
];
989 /* config dac list */
993 spec
->multiout
.dac_nids
[i
] = 0x10;
995 case AUTO_SEQ_CENLFE
:
997 spec
->multiout
.dac_nids
[i
] = 0x12;
999 case AUTO_SEQ_SURROUND
:
1001 spec
->multiout
.dac_nids
[i
] = 0x27;
1005 spec
->multiout
.dac_nids
[i
] = 0x11;
1012 spec
->multiout
.dac_nids
[cfg
->line_outs
] = 0x28; /* AOW4 */
1014 } else if (cfg
->line_outs
== 3) { /* 6 channels */
1015 for(i
= 0; i
< cfg
->line_outs
; i
++) {
1016 nid
= cfg
->line_out_pins
[i
];
1018 /* config dac list */
1020 case AUTO_SEQ_FRONT
:
1022 spec
->multiout
.dac_nids
[i
] = 0x10;
1024 case AUTO_SEQ_CENLFE
:
1026 spec
->multiout
.dac_nids
[i
] = 0x12;
1028 case AUTO_SEQ_SURROUND
:
1030 spec
->multiout
.dac_nids
[i
] = 0x11;
1042 /* add playback controls from the parsed DAC table */
1043 static int vt1709_auto_create_multi_out_ctls(struct via_spec
*spec
,
1044 const struct auto_pin_cfg
*cfg
)
1047 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
1051 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
1052 nid
= cfg
->line_out_pins
[i
];
1057 if (i
== AUTO_SEQ_CENLFE
) {
1059 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1060 "Center Playback Volume",
1061 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT
));
1064 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1065 "LFE Playback Volume",
1066 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT
));
1069 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1070 "Center Playback Switch",
1071 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT
));
1074 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1075 "LFE Playback Switch",
1076 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT
));
1079 } else if (i
== AUTO_SEQ_FRONT
){
1080 /* add control to mixer index 0 */
1081 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1082 "Master Front Playback Volume",
1083 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT
));
1086 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1087 "Master Front Playback Switch",
1088 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT
));
1092 /* add control to PW3 */
1093 sprintf(name
, "%s Playback Volume", chname
[i
]);
1094 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1095 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
1098 sprintf(name
, "%s Playback Switch", chname
[i
]);
1099 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1100 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
1103 } else if (i
== AUTO_SEQ_SURROUND
) {
1104 sprintf(name
, "%s Playback Volume", chname
[i
]);
1105 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1106 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT
));
1109 sprintf(name
, "%s Playback Switch", chname
[i
]);
1110 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1111 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT
));
1114 } else if (i
== AUTO_SEQ_SIDE
) {
1115 sprintf(name
, "%s Playback Volume", chname
[i
]);
1116 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1117 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
));
1120 sprintf(name
, "%s Playback Switch", chname
[i
]);
1121 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1122 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
));
1131 static int vt1709_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
1138 if (spec
->multiout
.num_dacs
== 5) /* 10 channels */
1139 spec
->multiout
.hp_nid
= VT1709_HP_DAC_NID
;
1140 else if (spec
->multiout
.num_dacs
== 3) /* 6 channels */
1141 spec
->multiout
.hp_nid
= 0;
1143 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1144 "Headphone Playback Volume",
1145 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1148 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1149 "Headphone Playback Switch",
1150 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1157 /* create playback/capture controls for input pins */
1158 static int vt1709_auto_create_analog_input_ctls(struct via_spec
*spec
,
1159 const struct auto_pin_cfg
*cfg
)
1161 static char *labels
[] = {
1162 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1164 struct hda_input_mux
*imux
= &spec
->private_imux
;
1165 int i
, err
, idx
= 0;
1167 /* for internal loopback recording select */
1168 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
1169 imux
->items
[imux
->num_items
].index
= idx
;
1172 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
1173 if (!cfg
->input_pins
[i
])
1176 switch (cfg
->input_pins
[i
]) {
1177 case 0x1d: /* Mic */
1181 case 0x1e: /* Line In */
1185 case 0x21: /* Front Mic */
1193 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
1197 imux
->items
[imux
->num_items
].label
= labels
[i
];
1198 imux
->items
[imux
->num_items
].index
= idx
;
1204 static int vt1709_parse_auto_config(struct hda_codec
*codec
)
1206 struct via_spec
*spec
= codec
->spec
;
1209 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
1212 err
= vt1709_auto_fill_dac_nids(spec
, &spec
->autocfg
);
1215 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
1216 return 0; /* can't find valid BIOS pin config */
1218 err
= vt1709_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
1221 err
= vt1709_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
1224 err
= vt1709_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
1228 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
1230 if (spec
->autocfg
.dig_out_pin
)
1231 spec
->multiout
.dig_out_nid
= VT1709_DIGOUT_NID
;
1232 if (spec
->autocfg
.dig_in_pin
)
1233 spec
->dig_in_nid
= VT1709_DIGIN_NID
;
1235 if (spec
->kctl_alloc
)
1236 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
1238 spec
->input_mux
= &spec
->private_imux
;
1243 static int patch_vt1709_10ch(struct hda_codec
*codec
)
1245 struct via_spec
*spec
;
1248 /* create a codec specific record */
1249 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1255 err
= vt1709_parse_auto_config(codec
);
1260 printk(KERN_INFO
"hda_codec: Cannot set up configuration. "
1261 "Using genenic mode...\n");
1264 spec
->init_verbs
= vt1709_10ch_volume_init_verbs
;
1266 spec
->stream_name_analog
= "VT1709 Analog";
1267 spec
->stream_analog_playback
= &vt1709_10ch_pcm_analog_playback
;
1268 spec
->stream_analog_capture
= &vt1709_pcm_analog_capture
;
1270 spec
->stream_name_digital
= "VT1709 Digital";
1271 spec
->stream_digital_playback
= &vt1709_pcm_digital_playback
;
1272 spec
->stream_digital_capture
= &vt1709_pcm_digital_capture
;
1275 if (!spec
->adc_nids
&& spec
->input_mux
) {
1276 spec
->adc_nids
= vt1709_adc_nids
;
1277 spec
->num_adc_nids
= ARRAY_SIZE(vt1709_adc_nids
);
1278 spec
->mixers
[spec
->num_mixers
] = vt1709_capture_mixer
;
1282 codec
->patch_ops
= via_patch_ops
;
1284 codec
->patch_ops
.init
= via_auto_init
;
1289 * generic initialization of ADC, input mixers and output mixers
1291 static struct hda_verb vt1709_6ch_volume_init_verbs
[] = {
1293 * Unmute ADC0-2 and set the default input to mic-in
1295 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1296 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1297 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1300 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1303 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1304 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1305 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1306 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1307 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1308 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1311 * Set up output selector (0x1a, 0x1b, 0x29)
1313 /* set vol=0 to output mixers */
1314 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1315 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1316 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1319 * Unmute PW3 and PW4
1321 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1322 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1324 /* Set input of PW4 as MW0 */
1325 {0x20, AC_VERB_SET_CONNECT_SEL
, 0},
1326 /* Set mic as default input of sw0 */
1327 {0x19, AC_VERB_SET_CONNECT_SEL
, 0x2},
1328 /* PW9 Output enable */
1329 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1333 static int patch_vt1709_6ch(struct hda_codec
*codec
)
1335 struct via_spec
*spec
;
1338 /* create a codec specific record */
1339 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1345 err
= vt1709_parse_auto_config(codec
);
1350 printk(KERN_INFO
"hda_codec: Cannot set up configuration. "
1351 "Using genenic mode...\n");
1354 spec
->init_verbs
= vt1709_6ch_volume_init_verbs
;
1356 spec
->stream_name_analog
= "VT1709 Analog";
1357 spec
->stream_analog_playback
= &vt1709_6ch_pcm_analog_playback
;
1358 spec
->stream_analog_capture
= &vt1709_pcm_analog_capture
;
1360 spec
->stream_name_digital
= "VT1709 Digital";
1361 spec
->stream_digital_playback
= &vt1709_pcm_digital_playback
;
1362 spec
->stream_digital_capture
= &vt1709_pcm_digital_capture
;
1365 if (!spec
->adc_nids
&& spec
->input_mux
) {
1366 spec
->adc_nids
= vt1709_adc_nids
;
1367 spec
->num_adc_nids
= ARRAY_SIZE(vt1709_adc_nids
);
1368 spec
->mixers
[spec
->num_mixers
] = vt1709_capture_mixer
;
1372 codec
->patch_ops
= via_patch_ops
;
1374 codec
->patch_ops
.init
= via_auto_init
;
1382 struct hda_codec_preset snd_hda_preset_via
[] = {
1383 { .id
= 0x11061708, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1384 { .id
= 0x11061709, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1385 { .id
= 0x1106170A, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1386 { .id
= 0x1106170B, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1387 { .id
= 0x1106E710, .name
= "VIA VT1709 10-Ch", .patch
= patch_vt1709_10ch
},
1388 { .id
= 0x1106E711, .name
= "VIA VT1709 10-Ch", .patch
= patch_vt1709_10ch
},
1389 { .id
= 0x1106E712, .name
= "VIA VT1709 10-Ch", .patch
= patch_vt1709_10ch
},
1390 { .id
= 0x1106E713, .name
= "VIA VT1709 10-Ch", .patch
= patch_vt1709_10ch
},
1391 { .id
= 0x1106E714, .name
= "VIA VT1709 6-Ch", .patch
= patch_vt1709_6ch
},
1392 { .id
= 0x1106E715, .name
= "VIA VT1709 6-Ch", .patch
= patch_vt1709_6ch
},
1393 { .id
= 0x1106E716, .name
= "VIA VT1709 6-Ch", .patch
= patch_vt1709_6ch
},
1394 { .id
= 0x1106E717, .name
= "VIA VT1709 6-Ch", .patch
= patch_vt1709_6ch
},