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 <sound/core.h>
39 #include "hda_codec.h"
40 #include "hda_local.h"
44 #define AMP_VAL_IDX_SHIFT 19
45 #define AMP_VAL_IDX_MASK (0x0f<<19)
47 #define NUM_CONTROL_ALLOC 32
48 #define NUM_VERB_ALLOC 32
51 #define VT1708_HP_NID 0x13
52 #define VT1708_DIGOUT_NID 0x14
53 #define VT1708_DIGIN_NID 0x16
55 #define VT1709_HP_DAC_NID 0x28
56 #define VT1709_DIGOUT_NID 0x13
57 #define VT1709_DIGIN_NID 0x17
59 #define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
60 #define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
61 #define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
76 static struct snd_kcontrol_new vt1708_control_templates
[] = {
77 HDA_CODEC_VOLUME(NULL
, 0, 0, 0),
78 HDA_CODEC_MUTE(NULL
, 0, 0, 0),
83 /* codec parameterization */
84 struct snd_kcontrol_new
*mixers
[3];
85 unsigned int num_mixers
;
87 struct hda_verb
*init_verbs
;
89 char *stream_name_analog
;
90 struct hda_pcm_stream
*stream_analog_playback
;
91 struct hda_pcm_stream
*stream_analog_capture
;
93 char *stream_name_digital
;
94 struct hda_pcm_stream
*stream_digital_playback
;
95 struct hda_pcm_stream
*stream_digital_capture
;
98 struct hda_multi_out multiout
;
101 unsigned int num_adc_nids
;
103 hda_nid_t dig_in_nid
;
106 const struct hda_input_mux
*input_mux
;
107 unsigned int cur_mux
[3];
109 /* PCM information */
110 struct hda_pcm pcm_rec
[2];
112 /* dynamic controls, init_verbs and input_mux */
113 struct auto_pin_cfg autocfg
;
114 unsigned int num_kctl_alloc
, num_kctl_used
;
115 struct snd_kcontrol_new
*kctl_alloc
;
116 struct hda_input_mux private_imux
;
117 hda_nid_t private_dac_nids
[AUTO_CFG_MAX_OUTS
];
119 #ifdef CONFIG_SND_HDA_POWER_SAVE
120 struct hda_loopback_check loopback
;
124 static hda_nid_t vt1708_adc_nids
[2] = {
129 static hda_nid_t vt1709_adc_nids
[3] = {
134 /* add dynamic controls */
135 static int via_add_control(struct via_spec
*spec
, int type
, const char *name
,
138 struct snd_kcontrol_new
*knew
;
140 if (spec
->num_kctl_used
>= spec
->num_kctl_alloc
) {
141 int num
= spec
->num_kctl_alloc
+ NUM_CONTROL_ALLOC
;
143 /* array + terminator */
144 knew
= kcalloc(num
+ 1, sizeof(*knew
), GFP_KERNEL
);
147 if (spec
->kctl_alloc
) {
148 memcpy(knew
, spec
->kctl_alloc
,
149 sizeof(*knew
) * spec
->num_kctl_alloc
);
150 kfree(spec
->kctl_alloc
);
152 spec
->kctl_alloc
= knew
;
153 spec
->num_kctl_alloc
= num
;
156 knew
= &spec
->kctl_alloc
[spec
->num_kctl_used
];
157 *knew
= vt1708_control_templates
[type
];
158 knew
->name
= kstrdup(name
, GFP_KERNEL
);
162 knew
->private_value
= val
;
163 spec
->num_kctl_used
++;
167 /* create input playback/capture controls for the given pin */
168 static int via_new_analog_input(struct via_spec
*spec
, hda_nid_t pin
,
169 const char *ctlname
, int idx
, int mix_nid
)
174 sprintf(name
, "%s Playback Volume", ctlname
);
175 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
176 HDA_COMPOSE_AMP_VAL(mix_nid
, 3, idx
, HDA_INPUT
));
179 sprintf(name
, "%s Playback Switch", ctlname
);
180 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
181 HDA_COMPOSE_AMP_VAL(mix_nid
, 3, idx
, HDA_INPUT
));
187 static void via_auto_set_output_and_unmute(struct hda_codec
*codec
,
188 hda_nid_t nid
, int pin_type
,
192 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_PIN_WIDGET_CONTROL
,
194 snd_hda_codec_write(codec
, nid
, 0, AC_VERB_SET_AMP_GAIN_MUTE
,
199 static void via_auto_init_multi_out(struct hda_codec
*codec
)
201 struct via_spec
*spec
= codec
->spec
;
204 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
205 hda_nid_t nid
= spec
->autocfg
.line_out_pins
[i
];
207 via_auto_set_output_and_unmute(codec
, nid
, PIN_OUT
, i
);
211 static void via_auto_init_hp_out(struct hda_codec
*codec
)
213 struct via_spec
*spec
= codec
->spec
;
216 pin
= spec
->autocfg
.hp_pins
[0];
217 if (pin
) /* connect to front */
218 via_auto_set_output_and_unmute(codec
, pin
, PIN_HP
, 0);
221 static void via_auto_init_analog_input(struct hda_codec
*codec
)
223 struct via_spec
*spec
= codec
->spec
;
226 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
227 hda_nid_t nid
= spec
->autocfg
.input_pins
[i
];
229 snd_hda_codec_write(codec
, nid
, 0,
230 AC_VERB_SET_PIN_WIDGET_CONTROL
,
231 (i
<= AUTO_PIN_FRONT_MIC
?
232 PIN_VREF50
: PIN_IN
));
239 static int via_mux_enum_info(struct snd_kcontrol
*kcontrol
,
240 struct snd_ctl_elem_info
*uinfo
)
242 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
243 struct via_spec
*spec
= codec
->spec
;
244 return snd_hda_input_mux_info(spec
->input_mux
, uinfo
);
247 static int via_mux_enum_get(struct snd_kcontrol
*kcontrol
,
248 struct snd_ctl_elem_value
*ucontrol
)
250 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
251 struct via_spec
*spec
= codec
->spec
;
252 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
254 ucontrol
->value
.enumerated
.item
[0] = spec
->cur_mux
[adc_idx
];
258 static int via_mux_enum_put(struct snd_kcontrol
*kcontrol
,
259 struct snd_ctl_elem_value
*ucontrol
)
261 struct hda_codec
*codec
= snd_kcontrol_chip(kcontrol
);
262 struct via_spec
*spec
= codec
->spec
;
263 unsigned int adc_idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
264 unsigned int vendor_id
= codec
->vendor_id
;
266 /* AIW0 lydia 060801 add for correct sw0 input select */
267 if (IS_VT1708_VENDORID(vendor_id
) && (adc_idx
== 0))
268 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
269 0x18, &spec
->cur_mux
[adc_idx
]);
270 else if ((IS_VT1709_10CH_VENDORID(vendor_id
) ||
271 IS_VT1709_6CH_VENDORID(vendor_id
)) && (adc_idx
== 0) )
272 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
273 0x19, &spec
->cur_mux
[adc_idx
]);
275 return snd_hda_input_mux_put(codec
, spec
->input_mux
, ucontrol
,
276 spec
->adc_nids
[adc_idx
],
277 &spec
->cur_mux
[adc_idx
]);
280 /* capture mixer elements */
281 static struct snd_kcontrol_new vt1708_capture_mixer
[] = {
282 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT
),
283 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT
),
284 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT
),
285 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT
),
287 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
288 /* The multiple "Capture Source" controls confuse alsamixer
289 * So call somewhat different..
290 * FIXME: the controls appear in the "playback" view!
292 /* .name = "Capture Source", */
293 .name
= "Input Source",
295 .info
= via_mux_enum_info
,
296 .get
= via_mux_enum_get
,
297 .put
= via_mux_enum_put
,
302 * generic initialization of ADC, input mixers and output mixers
304 static struct hda_verb vt1708_volume_init_verbs
[] = {
306 * Unmute ADC0-1 and set the default input to mic-in
308 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
309 {0x27, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
312 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
315 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
316 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)}, /* master */
317 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
318 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
319 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
320 {0x17, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
323 * Set up output mixers (0x19 - 0x1b)
325 /* set vol=0 to output mixers */
326 {0x19, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
327 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
328 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
330 /* Setup default input to PW4 */
331 {0x20, AC_VERB_SET_CONNECT_SEL
, 0x1},
332 /* Set mic as default input of sw0 */
333 {0x18, AC_VERB_SET_CONNECT_SEL
, 0x2},
334 /* PW9 Output enable */
335 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
338 static int via_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
339 struct hda_codec
*codec
,
340 struct snd_pcm_substream
*substream
)
342 struct via_spec
*spec
= codec
->spec
;
343 return snd_hda_multi_out_analog_open(codec
, &spec
->multiout
, substream
);
346 static int via_playback_pcm_prepare(struct hda_pcm_stream
*hinfo
,
347 struct hda_codec
*codec
,
348 unsigned int stream_tag
,
350 struct snd_pcm_substream
*substream
)
352 struct via_spec
*spec
= codec
->spec
;
353 return snd_hda_multi_out_analog_prepare(codec
, &spec
->multiout
,
354 stream_tag
, format
, substream
);
357 static int via_playback_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
358 struct hda_codec
*codec
,
359 struct snd_pcm_substream
*substream
)
361 struct via_spec
*spec
= codec
->spec
;
362 return snd_hda_multi_out_analog_cleanup(codec
, &spec
->multiout
);
368 static int via_dig_playback_pcm_open(struct hda_pcm_stream
*hinfo
,
369 struct hda_codec
*codec
,
370 struct snd_pcm_substream
*substream
)
372 struct via_spec
*spec
= codec
->spec
;
373 return snd_hda_multi_out_dig_open(codec
, &spec
->multiout
);
376 static int via_dig_playback_pcm_close(struct hda_pcm_stream
*hinfo
,
377 struct hda_codec
*codec
,
378 struct snd_pcm_substream
*substream
)
380 struct via_spec
*spec
= codec
->spec
;
381 return snd_hda_multi_out_dig_close(codec
, &spec
->multiout
);
384 static int via_dig_playback_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
;
391 return snd_hda_multi_out_dig_prepare(codec
, &spec
->multiout
,
392 stream_tag
, format
, substream
);
398 static int via_capture_pcm_prepare(struct hda_pcm_stream
*hinfo
,
399 struct hda_codec
*codec
,
400 unsigned int stream_tag
,
402 struct snd_pcm_substream
*substream
)
404 struct via_spec
*spec
= codec
->spec
;
406 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
407 stream_tag
, 0, format
);
411 static int via_capture_pcm_cleanup(struct hda_pcm_stream
*hinfo
,
412 struct hda_codec
*codec
,
413 struct snd_pcm_substream
*substream
)
415 struct via_spec
*spec
= codec
->spec
;
416 snd_hda_codec_setup_stream(codec
, spec
->adc_nids
[substream
->number
],
421 static struct hda_pcm_stream vt1708_pcm_analog_playback
= {
425 .nid
= 0x10, /* NID to query formats and rates */
427 .open
= via_playback_pcm_open
,
428 .prepare
= via_playback_pcm_prepare
,
429 .cleanup
= via_playback_pcm_cleanup
433 static struct hda_pcm_stream vt1708_pcm_analog_capture
= {
437 .nid
= 0x15, /* NID to query formats and rates */
439 .prepare
= via_capture_pcm_prepare
,
440 .cleanup
= via_capture_pcm_cleanup
444 static struct hda_pcm_stream vt1708_pcm_digital_playback
= {
448 /* NID is set in via_build_pcms */
450 .open
= via_dig_playback_pcm_open
,
451 .close
= via_dig_playback_pcm_close
,
452 .prepare
= via_dig_playback_pcm_prepare
456 static struct hda_pcm_stream vt1708_pcm_digital_capture
= {
462 static int via_build_controls(struct hda_codec
*codec
)
464 struct via_spec
*spec
= codec
->spec
;
468 for (i
= 0; i
< spec
->num_mixers
; i
++) {
469 err
= snd_hda_add_new_ctls(codec
, spec
->mixers
[i
]);
474 if (spec
->multiout
.dig_out_nid
) {
475 err
= snd_hda_create_spdif_out_ctls(codec
,
476 spec
->multiout
.dig_out_nid
);
480 if (spec
->dig_in_nid
) {
481 err
= snd_hda_create_spdif_in_ctls(codec
, spec
->dig_in_nid
);
488 static int via_build_pcms(struct hda_codec
*codec
)
490 struct via_spec
*spec
= codec
->spec
;
491 struct hda_pcm
*info
= spec
->pcm_rec
;
494 codec
->pcm_info
= info
;
496 info
->name
= spec
->stream_name_analog
;
497 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] = *(spec
->stream_analog_playback
);
498 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
= spec
->multiout
.dac_nids
[0];
499 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] = *(spec
->stream_analog_capture
);
500 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
= spec
->adc_nids
[0];
502 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].channels_max
=
503 spec
->multiout
.max_channels
;
505 if (spec
->multiout
.dig_out_nid
|| spec
->dig_in_nid
) {
508 info
->name
= spec
->stream_name_digital
;
509 if (spec
->multiout
.dig_out_nid
) {
510 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
] =
511 *(spec
->stream_digital_playback
);
512 info
->stream
[SNDRV_PCM_STREAM_PLAYBACK
].nid
=
513 spec
->multiout
.dig_out_nid
;
515 if (spec
->dig_in_nid
) {
516 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
] =
517 *(spec
->stream_digital_capture
);
518 info
->stream
[SNDRV_PCM_STREAM_CAPTURE
].nid
=
526 static void via_free(struct hda_codec
*codec
)
528 struct via_spec
*spec
= codec
->spec
;
534 if (spec
->kctl_alloc
) {
535 for (i
= 0; i
< spec
->num_kctl_used
; i
++)
536 kfree(spec
->kctl_alloc
[i
].name
);
537 kfree(spec
->kctl_alloc
);
543 static int via_init(struct hda_codec
*codec
)
545 struct via_spec
*spec
= codec
->spec
;
546 snd_hda_sequence_write(codec
, spec
->init_verbs
);
550 #ifdef CONFIG_SND_HDA_POWER_SAVE
551 static int via_check_power_status(struct hda_codec
*codec
, hda_nid_t nid
)
553 struct via_spec
*spec
= codec
->spec
;
554 return snd_hda_check_amp_list_power(codec
, &spec
->loopback
, nid
);
560 static struct hda_codec_ops via_patch_ops
= {
561 .build_controls
= via_build_controls
,
562 .build_pcms
= via_build_pcms
,
565 #ifdef CONFIG_SND_HDA_POWER_SAVE
566 .check_power_status
= via_check_power_status
,
570 /* fill in the dac_nids table from the parsed pin configuration */
571 static int vt1708_auto_fill_dac_nids(struct via_spec
*spec
,
572 const struct auto_pin_cfg
*cfg
)
577 spec
->multiout
.num_dacs
= cfg
->line_outs
;
579 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
581 for(i
= 0; i
< 4; i
++) {
582 nid
= cfg
->line_out_pins
[i
];
584 /* config dac list */
587 spec
->multiout
.dac_nids
[i
] = 0x10;
589 case AUTO_SEQ_CENLFE
:
590 spec
->multiout
.dac_nids
[i
] = 0x12;
592 case AUTO_SEQ_SURROUND
:
593 spec
->multiout
.dac_nids
[i
] = 0x13;
596 spec
->multiout
.dac_nids
[i
] = 0x11;
605 /* add playback controls from the parsed DAC table */
606 static int vt1708_auto_create_multi_out_ctls(struct via_spec
*spec
,
607 const struct auto_pin_cfg
*cfg
)
610 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
611 hda_nid_t nid
, nid_vol
= 0;
614 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
615 nid
= cfg
->line_out_pins
[i
];
620 if (i
!= AUTO_SEQ_FRONT
)
621 nid_vol
= 0x1b - i
+ 1;
623 if (i
== AUTO_SEQ_CENLFE
) {
625 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
626 "Center Playback Volume",
627 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0, HDA_OUTPUT
));
630 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
631 "LFE Playback Volume",
632 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0, HDA_OUTPUT
));
635 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
636 "Center Playback Switch",
637 HDA_COMPOSE_AMP_VAL(nid_vol
, 1, 0, HDA_OUTPUT
));
640 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
641 "LFE Playback Switch",
642 HDA_COMPOSE_AMP_VAL(nid_vol
, 2, 0, HDA_OUTPUT
));
645 } else if (i
== AUTO_SEQ_FRONT
){
646 /* add control to mixer index 0 */
647 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
648 "Master Front Playback Volume",
649 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT
));
652 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
653 "Master Front Playback Switch",
654 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT
));
658 /* add control to PW3 */
659 sprintf(name
, "%s Playback Volume", chname
[i
]);
660 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
661 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
664 sprintf(name
, "%s Playback Switch", chname
[i
]);
665 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
666 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
670 sprintf(name
, "%s Playback Volume", chname
[i
]);
671 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
672 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0, HDA_OUTPUT
));
675 sprintf(name
, "%s Playback Switch", chname
[i
]);
676 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
677 HDA_COMPOSE_AMP_VAL(nid_vol
, 3, 0, HDA_OUTPUT
));
686 static int vt1708_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
693 spec
->multiout
.hp_nid
= VT1708_HP_NID
; /* AOW3 */
695 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
696 "Headphone Playback Volume",
697 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
700 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
701 "Headphone Playback Switch",
702 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
709 /* create playback/capture controls for input pins */
710 static int vt1708_auto_create_analog_input_ctls(struct via_spec
*spec
,
711 const struct auto_pin_cfg
*cfg
)
713 static char *labels
[] = {
714 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
716 struct hda_input_mux
*imux
= &spec
->private_imux
;
719 /* for internal loopback recording select */
720 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
721 imux
->items
[imux
->num_items
].index
= idx
;
724 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
725 if (!cfg
->input_pins
[i
])
728 switch (cfg
->input_pins
[i
]) {
733 case 0x1e: /* Line In */
737 case 0x21: /* Front Mic */
745 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
749 imux
->items
[imux
->num_items
].label
= labels
[i
];
750 imux
->items
[imux
->num_items
].index
= idx
;
756 #ifdef CONFIG_SND_HDA_POWER_SAVE
757 static struct hda_amp_list vt1708_loopbacks
[] = {
758 { 0x17, HDA_INPUT
, 1 },
759 { 0x17, HDA_INPUT
, 2 },
760 { 0x17, HDA_INPUT
, 3 },
761 { 0x17, HDA_INPUT
, 4 },
766 static int vt1708_parse_auto_config(struct hda_codec
*codec
)
768 struct via_spec
*spec
= codec
->spec
;
771 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
774 err
= vt1708_auto_fill_dac_nids(spec
, &spec
->autocfg
);
777 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
778 return 0; /* can't find valid BIOS pin config */
780 err
= vt1708_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
783 err
= vt1708_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
786 err
= vt1708_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
790 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
792 if (spec
->autocfg
.dig_out_pin
)
793 spec
->multiout
.dig_out_nid
= VT1708_DIGOUT_NID
;
794 if (spec
->autocfg
.dig_in_pin
)
795 spec
->dig_in_nid
= VT1708_DIGIN_NID
;
797 if (spec
->kctl_alloc
)
798 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
800 spec
->init_verbs
= vt1708_volume_init_verbs
;
802 spec
->input_mux
= &spec
->private_imux
;
807 /* init callback for auto-configuration model -- overriding the default init */
808 static int via_auto_init(struct hda_codec
*codec
)
811 via_auto_init_multi_out(codec
);
812 via_auto_init_hp_out(codec
);
813 via_auto_init_analog_input(codec
);
817 static int patch_vt1708(struct hda_codec
*codec
)
819 struct via_spec
*spec
;
822 /* create a codec specific record */
823 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
829 /* automatic parse from the BIOS config */
830 err
= vt1708_parse_auto_config(codec
);
835 printk(KERN_INFO
"hda_codec: Cannot set up configuration "
836 "from BIOS. Using genenic mode...\n");
840 spec
->stream_name_analog
= "VT1708 Analog";
841 spec
->stream_analog_playback
= &vt1708_pcm_analog_playback
;
842 spec
->stream_analog_capture
= &vt1708_pcm_analog_capture
;
844 spec
->stream_name_digital
= "VT1708 Digital";
845 spec
->stream_digital_playback
= &vt1708_pcm_digital_playback
;
846 spec
->stream_digital_capture
= &vt1708_pcm_digital_capture
;
849 if (!spec
->adc_nids
&& spec
->input_mux
) {
850 spec
->adc_nids
= vt1708_adc_nids
;
851 spec
->num_adc_nids
= ARRAY_SIZE(vt1708_adc_nids
);
852 spec
->mixers
[spec
->num_mixers
] = vt1708_capture_mixer
;
856 codec
->patch_ops
= via_patch_ops
;
858 codec
->patch_ops
.init
= via_auto_init
;
859 #ifdef CONFIG_SND_HDA_POWER_SAVE
860 spec
->loopback
.amplist
= vt1708_loopbacks
;
866 /* capture mixer elements */
867 static struct snd_kcontrol_new vt1709_capture_mixer
[] = {
868 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT
),
869 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT
),
870 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT
),
871 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT
),
872 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT
),
873 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT
),
875 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
876 /* The multiple "Capture Source" controls confuse alsamixer
877 * So call somewhat different..
878 * FIXME: the controls appear in the "playback" view!
880 /* .name = "Capture Source", */
881 .name
= "Input Source",
883 .info
= via_mux_enum_info
,
884 .get
= via_mux_enum_get
,
885 .put
= via_mux_enum_put
,
891 * generic initialization of ADC, input mixers and output mixers
893 static struct hda_verb vt1709_10ch_volume_init_verbs
[] = {
895 * Unmute ADC0-2 and set the default input to mic-in
897 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
898 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
899 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
902 /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
905 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
906 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)}, /* unmute master */
907 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(1)},
908 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(2)},
909 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(3)},
910 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_MUTE(4)},
913 * Set up output selector (0x1a, 0x1b, 0x29)
915 /* set vol=0 to output mixers */
916 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
917 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
918 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
923 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
924 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
926 /* Set input of PW4 as AOW4 */
927 {0x20, AC_VERB_SET_CONNECT_SEL
, 0x1},
928 /* Set mic as default input of sw0 */
929 {0x19, AC_VERB_SET_CONNECT_SEL
, 0x2},
930 /* PW9 Output enable */
931 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
935 static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback
= {
939 .nid
= 0x10, /* NID to query formats and rates */
941 .open
= via_playback_pcm_open
,
942 .prepare
= via_playback_pcm_prepare
,
943 .cleanup
= via_playback_pcm_cleanup
947 static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback
= {
951 .nid
= 0x10, /* NID to query formats and rates */
953 .open
= via_playback_pcm_open
,
954 .prepare
= via_playback_pcm_prepare
,
955 .cleanup
= via_playback_pcm_cleanup
959 static struct hda_pcm_stream vt1709_pcm_analog_capture
= {
963 .nid
= 0x14, /* NID to query formats and rates */
965 .prepare
= via_capture_pcm_prepare
,
966 .cleanup
= via_capture_pcm_cleanup
970 static struct hda_pcm_stream vt1709_pcm_digital_playback
= {
974 /* NID is set in via_build_pcms */
976 .open
= via_dig_playback_pcm_open
,
977 .close
= via_dig_playback_pcm_close
981 static struct hda_pcm_stream vt1709_pcm_digital_capture
= {
987 static int vt1709_auto_fill_dac_nids(struct via_spec
*spec
,
988 const struct auto_pin_cfg
*cfg
)
993 if (cfg
->line_outs
== 4) /* 10 channels */
994 spec
->multiout
.num_dacs
= cfg
->line_outs
+1; /* AOW0~AOW4 */
995 else if (cfg
->line_outs
== 3) /* 6 channels */
996 spec
->multiout
.num_dacs
= cfg
->line_outs
; /* AOW0~AOW2 */
998 spec
->multiout
.dac_nids
= spec
->private_dac_nids
;
1000 if (cfg
->line_outs
== 4) { /* 10 channels */
1001 for (i
= 0; i
< cfg
->line_outs
; i
++) {
1002 nid
= cfg
->line_out_pins
[i
];
1004 /* config dac list */
1006 case AUTO_SEQ_FRONT
:
1008 spec
->multiout
.dac_nids
[i
] = 0x10;
1010 case AUTO_SEQ_CENLFE
:
1012 spec
->multiout
.dac_nids
[i
] = 0x12;
1014 case AUTO_SEQ_SURROUND
:
1016 spec
->multiout
.dac_nids
[i
] = 0x27;
1020 spec
->multiout
.dac_nids
[i
] = 0x11;
1027 spec
->multiout
.dac_nids
[cfg
->line_outs
] = 0x28; /* AOW4 */
1029 } else if (cfg
->line_outs
== 3) { /* 6 channels */
1030 for(i
= 0; i
< cfg
->line_outs
; i
++) {
1031 nid
= cfg
->line_out_pins
[i
];
1033 /* config dac list */
1035 case AUTO_SEQ_FRONT
:
1037 spec
->multiout
.dac_nids
[i
] = 0x10;
1039 case AUTO_SEQ_CENLFE
:
1041 spec
->multiout
.dac_nids
[i
] = 0x12;
1043 case AUTO_SEQ_SURROUND
:
1045 spec
->multiout
.dac_nids
[i
] = 0x11;
1057 /* add playback controls from the parsed DAC table */
1058 static int vt1709_auto_create_multi_out_ctls(struct via_spec
*spec
,
1059 const struct auto_pin_cfg
*cfg
)
1062 static const char *chname
[4] = { "Front", "Surround", "C/LFE", "Side" };
1066 for (i
= 0; i
<= AUTO_SEQ_SIDE
; i
++) {
1067 nid
= cfg
->line_out_pins
[i
];
1072 if (i
== AUTO_SEQ_CENLFE
) {
1074 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1075 "Center Playback Volume",
1076 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT
));
1079 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1080 "LFE Playback Volume",
1081 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT
));
1084 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1085 "Center Playback Switch",
1086 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT
));
1089 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1090 "LFE Playback Switch",
1091 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT
));
1094 } else if (i
== AUTO_SEQ_FRONT
){
1095 /* add control to mixer index 0 */
1096 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1097 "Master Front Playback Volume",
1098 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT
));
1101 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1102 "Master Front Playback Switch",
1103 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT
));
1107 /* add control to PW3 */
1108 sprintf(name
, "%s Playback Volume", chname
[i
]);
1109 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1110 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
1113 sprintf(name
, "%s Playback Switch", chname
[i
]);
1114 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1115 HDA_COMPOSE_AMP_VAL(nid
, 3, 0, HDA_OUTPUT
));
1118 } else if (i
== AUTO_SEQ_SURROUND
) {
1119 sprintf(name
, "%s Playback Volume", chname
[i
]);
1120 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1121 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT
));
1124 sprintf(name
, "%s Playback Switch", chname
[i
]);
1125 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1126 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT
));
1129 } else if (i
== AUTO_SEQ_SIDE
) {
1130 sprintf(name
, "%s Playback Volume", chname
[i
]);
1131 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
, name
,
1132 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
));
1135 sprintf(name
, "%s Playback Switch", chname
[i
]);
1136 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
, name
,
1137 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT
));
1146 static int vt1709_auto_create_hp_ctls(struct via_spec
*spec
, hda_nid_t pin
)
1153 if (spec
->multiout
.num_dacs
== 5) /* 10 channels */
1154 spec
->multiout
.hp_nid
= VT1709_HP_DAC_NID
;
1155 else if (spec
->multiout
.num_dacs
== 3) /* 6 channels */
1156 spec
->multiout
.hp_nid
= 0;
1158 err
= via_add_control(spec
, VIA_CTL_WIDGET_VOL
,
1159 "Headphone Playback Volume",
1160 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1163 err
= via_add_control(spec
, VIA_CTL_WIDGET_MUTE
,
1164 "Headphone Playback Switch",
1165 HDA_COMPOSE_AMP_VAL(pin
, 3, 0, HDA_OUTPUT
));
1172 /* create playback/capture controls for input pins */
1173 static int vt1709_auto_create_analog_input_ctls(struct via_spec
*spec
,
1174 const struct auto_pin_cfg
*cfg
)
1176 static char *labels
[] = {
1177 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1179 struct hda_input_mux
*imux
= &spec
->private_imux
;
1180 int i
, err
, idx
= 0;
1182 /* for internal loopback recording select */
1183 imux
->items
[imux
->num_items
].label
= "Stereo Mixer";
1184 imux
->items
[imux
->num_items
].index
= idx
;
1187 for (i
= 0; i
< AUTO_PIN_LAST
; i
++) {
1188 if (!cfg
->input_pins
[i
])
1191 switch (cfg
->input_pins
[i
]) {
1192 case 0x1d: /* Mic */
1196 case 0x1e: /* Line In */
1200 case 0x21: /* Front Mic */
1208 err
= via_new_analog_input(spec
, cfg
->input_pins
[i
], labels
[i
],
1212 imux
->items
[imux
->num_items
].label
= labels
[i
];
1213 imux
->items
[imux
->num_items
].index
= idx
;
1219 static int vt1709_parse_auto_config(struct hda_codec
*codec
)
1221 struct via_spec
*spec
= codec
->spec
;
1224 err
= snd_hda_parse_pin_def_config(codec
, &spec
->autocfg
, NULL
);
1227 err
= vt1709_auto_fill_dac_nids(spec
, &spec
->autocfg
);
1230 if (!spec
->autocfg
.line_outs
&& !spec
->autocfg
.hp_pins
[0])
1231 return 0; /* can't find valid BIOS pin config */
1233 err
= vt1709_auto_create_multi_out_ctls(spec
, &spec
->autocfg
);
1236 err
= vt1709_auto_create_hp_ctls(spec
, spec
->autocfg
.hp_pins
[0]);
1239 err
= vt1709_auto_create_analog_input_ctls(spec
, &spec
->autocfg
);
1243 spec
->multiout
.max_channels
= spec
->multiout
.num_dacs
* 2;
1245 if (spec
->autocfg
.dig_out_pin
)
1246 spec
->multiout
.dig_out_nid
= VT1709_DIGOUT_NID
;
1247 if (spec
->autocfg
.dig_in_pin
)
1248 spec
->dig_in_nid
= VT1709_DIGIN_NID
;
1250 if (spec
->kctl_alloc
)
1251 spec
->mixers
[spec
->num_mixers
++] = spec
->kctl_alloc
;
1253 spec
->input_mux
= &spec
->private_imux
;
1258 #ifdef CONFIG_SND_HDA_POWER_SAVE
1259 static struct hda_amp_list vt1709_loopbacks
[] = {
1260 { 0x18, HDA_INPUT
, 1 },
1261 { 0x18, HDA_INPUT
, 2 },
1262 { 0x18, HDA_INPUT
, 3 },
1263 { 0x18, HDA_INPUT
, 4 },
1268 static int patch_vt1709_10ch(struct hda_codec
*codec
)
1270 struct via_spec
*spec
;
1273 /* create a codec specific record */
1274 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1280 err
= vt1709_parse_auto_config(codec
);
1285 printk(KERN_INFO
"hda_codec: Cannot set up configuration. "
1286 "Using genenic mode...\n");
1289 spec
->init_verbs
= vt1709_10ch_volume_init_verbs
;
1291 spec
->stream_name_analog
= "VT1709 Analog";
1292 spec
->stream_analog_playback
= &vt1709_10ch_pcm_analog_playback
;
1293 spec
->stream_analog_capture
= &vt1709_pcm_analog_capture
;
1295 spec
->stream_name_digital
= "VT1709 Digital";
1296 spec
->stream_digital_playback
= &vt1709_pcm_digital_playback
;
1297 spec
->stream_digital_capture
= &vt1709_pcm_digital_capture
;
1300 if (!spec
->adc_nids
&& spec
->input_mux
) {
1301 spec
->adc_nids
= vt1709_adc_nids
;
1302 spec
->num_adc_nids
= ARRAY_SIZE(vt1709_adc_nids
);
1303 spec
->mixers
[spec
->num_mixers
] = vt1709_capture_mixer
;
1307 codec
->patch_ops
= via_patch_ops
;
1309 codec
->patch_ops
.init
= via_auto_init
;
1310 #ifdef CONFIG_SND_HDA_POWER_SAVE
1311 spec
->loopback
.amplist
= vt1709_loopbacks
;
1317 * generic initialization of ADC, input mixers and output mixers
1319 static struct hda_verb vt1709_6ch_volume_init_verbs
[] = {
1321 * Unmute ADC0-2 and set the default input to mic-in
1323 {0x14, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1324 {0x15, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1325 {0x16, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1328 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1331 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1332 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(0)},
1333 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(1)},
1334 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(2)},
1335 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(3)},
1336 {0x18, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_IN_UNMUTE(4)},
1339 * Set up output selector (0x1a, 0x1b, 0x29)
1341 /* set vol=0 to output mixers */
1342 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1343 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1344 {0x29, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1347 * Unmute PW3 and PW4
1349 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1350 {0x20, AC_VERB_SET_AMP_GAIN_MUTE
, AMP_OUT_ZERO
},
1352 /* Set input of PW4 as MW0 */
1353 {0x20, AC_VERB_SET_CONNECT_SEL
, 0},
1354 /* Set mic as default input of sw0 */
1355 {0x19, AC_VERB_SET_CONNECT_SEL
, 0x2},
1356 /* PW9 Output enable */
1357 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL
, 0x40},
1361 static int patch_vt1709_6ch(struct hda_codec
*codec
)
1363 struct via_spec
*spec
;
1366 /* create a codec specific record */
1367 spec
= kcalloc(1, sizeof(*spec
), GFP_KERNEL
);
1373 err
= vt1709_parse_auto_config(codec
);
1378 printk(KERN_INFO
"hda_codec: Cannot set up configuration. "
1379 "Using genenic mode...\n");
1382 spec
->init_verbs
= vt1709_6ch_volume_init_verbs
;
1384 spec
->stream_name_analog
= "VT1709 Analog";
1385 spec
->stream_analog_playback
= &vt1709_6ch_pcm_analog_playback
;
1386 spec
->stream_analog_capture
= &vt1709_pcm_analog_capture
;
1388 spec
->stream_name_digital
= "VT1709 Digital";
1389 spec
->stream_digital_playback
= &vt1709_pcm_digital_playback
;
1390 spec
->stream_digital_capture
= &vt1709_pcm_digital_capture
;
1393 if (!spec
->adc_nids
&& spec
->input_mux
) {
1394 spec
->adc_nids
= vt1709_adc_nids
;
1395 spec
->num_adc_nids
= ARRAY_SIZE(vt1709_adc_nids
);
1396 spec
->mixers
[spec
->num_mixers
] = vt1709_capture_mixer
;
1400 codec
->patch_ops
= via_patch_ops
;
1402 codec
->patch_ops
.init
= via_auto_init
;
1403 #ifdef CONFIG_SND_HDA_POWER_SAVE
1404 spec
->loopback
.amplist
= vt1709_loopbacks
;
1413 struct hda_codec_preset snd_hda_preset_via
[] = {
1414 { .id
= 0x11061708, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1415 { .id
= 0x11061709, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1416 { .id
= 0x1106170A, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1417 { .id
= 0x1106170B, .name
= "VIA VT1708", .patch
= patch_vt1708
},
1418 { .id
= 0x1106E710, .name
= "VIA VT1709 10-Ch", .patch
= patch_vt1709_10ch
},
1419 { .id
= 0x1106E711, .name
= "VIA VT1709 10-Ch", .patch
= patch_vt1709_10ch
},
1420 { .id
= 0x1106E712, .name
= "VIA VT1709 10-Ch", .patch
= patch_vt1709_10ch
},
1421 { .id
= 0x1106E713, .name
= "VIA VT1709 10-Ch", .patch
= patch_vt1709_10ch
},
1422 { .id
= 0x1106E714, .name
= "VIA VT1709 6-Ch", .patch
= patch_vt1709_6ch
},
1423 { .id
= 0x1106E715, .name
= "VIA VT1709 6-Ch", .patch
= patch_vt1709_6ch
},
1424 { .id
= 0x1106E716, .name
= "VIA VT1709 6-Ch", .patch
= patch_vt1709_6ch
},
1425 { .id
= 0x1106E717, .name
= "VIA VT1709 6-Ch", .patch
= patch_vt1709_6ch
},