xref: /openbmc/linux/sound/pci/hda/patch_via.c (revision 034f90b3)
1 /*
2  * Universal Interface for Intel High Definition Audio Codec
3  *
4  * HD audio interface patch for VIA VT17xx/VT18xx/VT20xx codec
5  *
6  *  (C) 2006-2009 VIA Technology, Inc.
7  *  (C) 2006-2008 Takashi Iwai <tiwai@suse.de>
8  *
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.
13  *
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.
18  *
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
22  */
23 
24 /* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
25 /*									     */
26 /* 2006-03-03  Lydia Wang  Create the basic patch to support VT1708 codec    */
27 /* 2006-03-14  Lydia Wang  Modify hard code for some pin widget nid	     */
28 /* 2006-08-02  Lydia Wang  Add support to VT1709 codec			     */
29 /* 2006-09-08  Lydia Wang  Fix internal loopback recording source select bug */
30 /* 2007-09-12  Lydia Wang  Add EAPD enable during driver initialization	     */
31 /* 2007-09-17  Lydia Wang  Add VT1708B codec support			    */
32 /* 2007-11-14  Lydia Wang  Add VT1708A codec HP and CD pin connect config    */
33 /* 2008-02-03  Lydia Wang  Fix Rear channels and Back channels inverse issue */
34 /* 2008-03-06  Lydia Wang  Add VT1702 codec and VT1708S codec support	     */
35 /* 2008-04-09  Lydia Wang  Add mute front speaker when HP plugin	     */
36 /* 2008-04-09  Lydia Wang  Add Independent HP feature			     */
37 /* 2008-05-28  Lydia Wang  Add second S/PDIF Out support for VT1702	     */
38 /* 2008-09-15  Logan Li	   Add VT1708S Mic Boost workaround/backdoor	     */
39 /* 2009-02-16  Logan Li	   Add support for VT1718S			     */
40 /* 2009-03-13  Logan Li	   Add support for VT1716S			     */
41 /* 2009-04-14  Lydai Wang  Add support for VT1828S and VT2020		     */
42 /* 2009-07-08  Lydia Wang  Add support for VT2002P			     */
43 /* 2009-07-21  Lydia Wang  Add support for VT1812			     */
44 /* 2009-09-19  Lydia Wang  Add support for VT1818S			     */
45 /*									     */
46 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47 
48 
49 #include <linux/init.h>
50 #include <linux/delay.h>
51 #include <linux/slab.h>
52 #include <linux/module.h>
53 #include <sound/core.h>
54 #include <sound/asoundef.h>
55 #include "hda_codec.h"
56 #include "hda_local.h"
57 #include "hda_auto_parser.h"
58 #include "hda_jack.h"
59 #include "hda_generic.h"
60 
61 /* Pin Widget NID */
62 #define VT1708_HP_PIN_NID	0x20
63 #define VT1708_CD_PIN_NID	0x24
64 
65 enum VIA_HDA_CODEC {
66 	UNKNOWN = -1,
67 	VT1708,
68 	VT1709_10CH,
69 	VT1709_6CH,
70 	VT1708B_8CH,
71 	VT1708B_4CH,
72 	VT1708S,
73 	VT1708BCE,
74 	VT1702,
75 	VT1718S,
76 	VT1716S,
77 	VT2002P,
78 	VT1812,
79 	VT1802,
80 	VT1705CF,
81 	VT1808,
82 	CODEC_TYPES,
83 };
84 
85 #define VT2002P_COMPATIBLE(spec) \
86 	((spec)->codec_type == VT2002P ||\
87 	 (spec)->codec_type == VT1812 ||\
88 	 (spec)->codec_type == VT1802)
89 
90 struct via_spec {
91 	struct hda_gen_spec gen;
92 
93 	/* codec parameterization */
94 	const struct snd_kcontrol_new *mixers[6];
95 	unsigned int num_mixers;
96 
97 	const struct hda_verb *init_verbs[5];
98 	unsigned int num_iverbs;
99 
100 	/* HP mode source */
101 	unsigned int dmic_enabled;
102 	enum VIA_HDA_CODEC codec_type;
103 
104 	/* analog low-power control */
105 	bool alc_mode;
106 
107 	/* work to check hp jack state */
108 	int hp_work_active;
109 	int vt1708_jack_detect;
110 };
111 
112 static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
113 static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
114 				  struct hda_codec *codec,
115 				  struct snd_pcm_substream *substream,
116 				  int action);
117 
118 static struct via_spec *via_new_spec(struct hda_codec *codec)
119 {
120 	struct via_spec *spec;
121 
122 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
123 	if (spec == NULL)
124 		return NULL;
125 
126 	codec->spec = spec;
127 	snd_hda_gen_spec_init(&spec->gen);
128 	spec->codec_type = get_codec_type(codec);
129 	/* VT1708BCE & VT1708S are almost same */
130 	if (spec->codec_type == VT1708BCE)
131 		spec->codec_type = VT1708S;
132 	spec->gen.indep_hp = 1;
133 	spec->gen.keep_eapd_on = 1;
134 	spec->gen.pcm_playback_hook = via_playback_pcm_hook;
135 	spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
136 	codec->power_save_node = 1;
137 	spec->gen.power_down_unused = 1;
138 	return spec;
139 }
140 
141 static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
142 {
143 	u32 vendor_id = codec->core.vendor_id;
144 	u16 ven_id = vendor_id >> 16;
145 	u16 dev_id = vendor_id & 0xffff;
146 	enum VIA_HDA_CODEC codec_type;
147 
148 	/* get codec type */
149 	if (ven_id != 0x1106)
150 		codec_type = UNKNOWN;
151 	else if (dev_id >= 0x1708 && dev_id <= 0x170b)
152 		codec_type = VT1708;
153 	else if (dev_id >= 0xe710 && dev_id <= 0xe713)
154 		codec_type = VT1709_10CH;
155 	else if (dev_id >= 0xe714 && dev_id <= 0xe717)
156 		codec_type = VT1709_6CH;
157 	else if (dev_id >= 0xe720 && dev_id <= 0xe723) {
158 		codec_type = VT1708B_8CH;
159 		if (snd_hda_param_read(codec, 0x16, AC_PAR_CONNLIST_LEN) == 0x7)
160 			codec_type = VT1708BCE;
161 	} else if (dev_id >= 0xe724 && dev_id <= 0xe727)
162 		codec_type = VT1708B_4CH;
163 	else if ((dev_id & 0xfff) == 0x397
164 		 && (dev_id >> 12) < 8)
165 		codec_type = VT1708S;
166 	else if ((dev_id & 0xfff) == 0x398
167 		 && (dev_id >> 12) < 8)
168 		codec_type = VT1702;
169 	else if ((dev_id & 0xfff) == 0x428
170 		 && (dev_id >> 12) < 8)
171 		codec_type = VT1718S;
172 	else if (dev_id == 0x0433 || dev_id == 0xa721)
173 		codec_type = VT1716S;
174 	else if (dev_id == 0x0441 || dev_id == 0x4441)
175 		codec_type = VT1718S;
176 	else if (dev_id == 0x0438 || dev_id == 0x4438)
177 		codec_type = VT2002P;
178 	else if (dev_id == 0x0448)
179 		codec_type = VT1812;
180 	else if (dev_id == 0x0440)
181 		codec_type = VT1708S;
182 	else if ((dev_id & 0xfff) == 0x446)
183 		codec_type = VT1802;
184 	else if (dev_id == 0x4760)
185 		codec_type = VT1705CF;
186 	else if (dev_id == 0x4761 || dev_id == 0x4762)
187 		codec_type = VT1808;
188 	else
189 		codec_type = UNKNOWN;
190 	return codec_type;
191 };
192 
193 static void analog_low_current_mode(struct hda_codec *codec);
194 static bool is_aa_path_mute(struct hda_codec *codec);
195 
196 #define hp_detect_with_aa(codec) \
197 	(snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
198 	 !is_aa_path_mute(codec))
199 
200 static void vt1708_stop_hp_work(struct hda_codec *codec)
201 {
202 	struct via_spec *spec = codec->spec;
203 	if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
204 		return;
205 	if (spec->hp_work_active) {
206 		snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
207 		codec->jackpoll_interval = 0;
208 		cancel_delayed_work_sync(&codec->jackpoll_work);
209 		spec->hp_work_active = false;
210 	}
211 }
212 
213 static void vt1708_update_hp_work(struct hda_codec *codec)
214 {
215 	struct via_spec *spec = codec->spec;
216 	if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
217 		return;
218 	if (spec->vt1708_jack_detect) {
219 		if (!spec->hp_work_active) {
220 			codec->jackpoll_interval = msecs_to_jiffies(100);
221 			snd_hda_codec_write(codec, 0x1, 0, 0xf81, 0);
222 			schedule_delayed_work(&codec->jackpoll_work, 0);
223 			spec->hp_work_active = true;
224 		}
225 	} else if (!hp_detect_with_aa(codec))
226 		vt1708_stop_hp_work(codec);
227 }
228 
229 static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
230 				  struct snd_ctl_elem_info *uinfo)
231 {
232 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
233 }
234 
235 static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
236 				 struct snd_ctl_elem_value *ucontrol)
237 {
238 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
239 	ucontrol->value.enumerated.item[0] = codec->power_save_node;
240 	return 0;
241 }
242 
243 static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
244 				 struct snd_ctl_elem_value *ucontrol)
245 {
246 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
247 	struct via_spec *spec = codec->spec;
248 	bool val = !!ucontrol->value.enumerated.item[0];
249 
250 	if (val == codec->power_save_node)
251 		return 0;
252 	codec->power_save_node = val;
253 	spec->gen.power_down_unused = val;
254 	analog_low_current_mode(codec);
255 	return 1;
256 }
257 
258 static const struct snd_kcontrol_new via_pin_power_ctl_enum[] = {
259 	{
260 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
261 	.name = "Dynamic Power-Control",
262 	.info = via_pin_power_ctl_info,
263 	.get = via_pin_power_ctl_get,
264 	.put = via_pin_power_ctl_put,
265 	},
266 	{} /* terminator */
267 };
268 
269 
270 /* check AA path's mute status */
271 static bool is_aa_path_mute(struct hda_codec *codec)
272 {
273 	struct via_spec *spec = codec->spec;
274 	const struct hda_amp_list *p;
275 	int ch, v;
276 
277 	p = spec->gen.loopback.amplist;
278 	if (!p)
279 		return true;
280 	for (; p->nid; p++) {
281 		for (ch = 0; ch < 2; ch++) {
282 			v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
283 						   p->idx);
284 			if (!(v & HDA_AMP_MUTE) && v > 0)
285 				return false;
286 		}
287 	}
288 	return true;
289 }
290 
291 /* enter/exit analog low-current mode */
292 static void __analog_low_current_mode(struct hda_codec *codec, bool force)
293 {
294 	struct via_spec *spec = codec->spec;
295 	bool enable;
296 	unsigned int verb, parm;
297 
298 	if (!codec->power_save_node)
299 		enable = false;
300 	else
301 		enable = is_aa_path_mute(codec) && !spec->gen.active_streams;
302 	if (enable == spec->alc_mode && !force)
303 		return;
304 	spec->alc_mode = enable;
305 
306 	/* decide low current mode's verb & parameter */
307 	switch (spec->codec_type) {
308 	case VT1708B_8CH:
309 	case VT1708B_4CH:
310 		verb = 0xf70;
311 		parm = enable ? 0x02 : 0x00; /* 0x02: 2/3x, 0x00: 1x */
312 		break;
313 	case VT1708S:
314 	case VT1718S:
315 	case VT1716S:
316 		verb = 0xf73;
317 		parm = enable ? 0x51 : 0xe1; /* 0x51: 4/28x, 0xe1: 1x */
318 		break;
319 	case VT1702:
320 		verb = 0xf73;
321 		parm = enable ? 0x01 : 0x1d; /* 0x01: 4/40x, 0x1d: 1x */
322 		break;
323 	case VT2002P:
324 	case VT1812:
325 	case VT1802:
326 		verb = 0xf93;
327 		parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
328 		break;
329 	case VT1705CF:
330 	case VT1808:
331 		verb = 0xf82;
332 		parm = enable ? 0x00 : 0xe0;  /* 0x00: 4/40x, 0xe0: 1x */
333 		break;
334 	default:
335 		return;		/* other codecs are not supported */
336 	}
337 	/* send verb */
338 	snd_hda_codec_write(codec, codec->core.afg, 0, verb, parm);
339 }
340 
341 static void analog_low_current_mode(struct hda_codec *codec)
342 {
343 	return __analog_low_current_mode(codec, false);
344 }
345 
346 static int via_build_controls(struct hda_codec *codec)
347 {
348 	struct via_spec *spec = codec->spec;
349 	int err, i;
350 
351 	err = snd_hda_gen_build_controls(codec);
352 	if (err < 0)
353 		return err;
354 
355 	spec->mixers[spec->num_mixers++] = via_pin_power_ctl_enum;
356 
357 	for (i = 0; i < spec->num_mixers; i++) {
358 		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
359 		if (err < 0)
360 			return err;
361 	}
362 
363 	return 0;
364 }
365 
366 static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
367 				  struct hda_codec *codec,
368 				  struct snd_pcm_substream *substream,
369 				  int action)
370 {
371 	analog_low_current_mode(codec);
372 	vt1708_update_hp_work(codec);
373 }
374 
375 static void via_free(struct hda_codec *codec)
376 {
377 	vt1708_stop_hp_work(codec);
378 	snd_hda_gen_free(codec);
379 }
380 
381 #ifdef CONFIG_PM
382 static int via_suspend(struct hda_codec *codec)
383 {
384 	struct via_spec *spec = codec->spec;
385 	vt1708_stop_hp_work(codec);
386 
387 	/* Fix pop noise on headphones */
388 	if (spec->codec_type == VT1802)
389 		snd_hda_shutup_pins(codec);
390 
391 	return 0;
392 }
393 #endif
394 
395 #ifdef CONFIG_PM
396 static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
397 {
398 	struct via_spec *spec = codec->spec;
399 	analog_low_current_mode(codec);
400 	vt1708_update_hp_work(codec);
401 	return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid);
402 }
403 #endif
404 
405 /*
406  */
407 
408 static int via_init(struct hda_codec *codec);
409 
410 static const struct hda_codec_ops via_patch_ops = {
411 	.build_controls = via_build_controls,
412 	.build_pcms = snd_hda_gen_build_pcms,
413 	.init = via_init,
414 	.free = via_free,
415 	.unsol_event = snd_hda_jack_unsol_event,
416 #ifdef CONFIG_PM
417 	.suspend = via_suspend,
418 	.check_power_status = via_check_power_status,
419 #endif
420 };
421 
422 
423 static const struct hda_verb vt1708_init_verbs[] = {
424 	/* power down jack detect function */
425 	{0x1, 0xf81, 0x1},
426 	{ }
427 };
428 static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
429 {
430 	unsigned int def_conf;
431 	unsigned char seqassoc;
432 
433 	def_conf = snd_hda_codec_get_pincfg(codec, nid);
434 	seqassoc = (unsigned char) get_defcfg_association(def_conf);
435 	seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
436 	if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
437 	    && (seqassoc == 0xf0 || seqassoc == 0xff)) {
438 		def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
439 		snd_hda_codec_set_pincfg(codec, nid, def_conf);
440 	}
441 
442 	return;
443 }
444 
445 static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
446 				     struct snd_ctl_elem_value *ucontrol)
447 {
448 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
449 	struct via_spec *spec = codec->spec;
450 
451 	if (spec->codec_type != VT1708)
452 		return 0;
453 	ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
454 	return 0;
455 }
456 
457 static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
458 				     struct snd_ctl_elem_value *ucontrol)
459 {
460 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
461 	struct via_spec *spec = codec->spec;
462 	int val;
463 
464 	if (spec->codec_type != VT1708)
465 		return 0;
466 	val = !!ucontrol->value.integer.value[0];
467 	if (spec->vt1708_jack_detect == val)
468 		return 0;
469 	spec->vt1708_jack_detect = val;
470 	vt1708_update_hp_work(codec);
471 	return 1;
472 }
473 
474 static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = {
475 	{
476 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
477 	.name = "Jack Detect",
478 	.count = 1,
479 	.info = snd_ctl_boolean_mono_info,
480 	.get = vt1708_jack_detect_get,
481 	.put = vt1708_jack_detect_put,
482 	},
483 	{} /* terminator */
484 };
485 
486 static const struct badness_table via_main_out_badness = {
487 	.no_primary_dac = 0x10000,
488 	.no_dac = 0x4000,
489 	.shared_primary = 0x10000,
490 	.shared_surr = 0x20,
491 	.shared_clfe = 0x20,
492 	.shared_surr_main = 0x20,
493 };
494 static const struct badness_table via_extra_out_badness = {
495 	.no_primary_dac = 0x4000,
496 	.no_dac = 0x4000,
497 	.shared_primary = 0x12,
498 	.shared_surr = 0x20,
499 	.shared_clfe = 0x20,
500 	.shared_surr_main = 0x10,
501 };
502 
503 static int via_parse_auto_config(struct hda_codec *codec)
504 {
505 	struct via_spec *spec = codec->spec;
506 	int err;
507 
508 	spec->gen.main_out_badness = &via_main_out_badness;
509 	spec->gen.extra_out_badness = &via_extra_out_badness;
510 
511 	err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
512 	if (err < 0)
513 		return err;
514 
515 	err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
516 	if (err < 0)
517 		return err;
518 
519 	/* disable widget PM at start for compatibility */
520 	codec->power_save_node = 0;
521 	spec->gen.power_down_unused = 0;
522 	return 0;
523 }
524 
525 static int via_init(struct hda_codec *codec)
526 {
527 	struct via_spec *spec = codec->spec;
528 	int i;
529 
530 	for (i = 0; i < spec->num_iverbs; i++)
531 		snd_hda_sequence_write(codec, spec->init_verbs[i]);
532 
533 	/* init power states */
534 	__analog_low_current_mode(codec, true);
535 
536 	snd_hda_gen_init(codec);
537 
538 	vt1708_update_hp_work(codec);
539 
540 	return 0;
541 }
542 
543 static int vt1708_build_controls(struct hda_codec *codec)
544 {
545 	/* In order not to create "Phantom Jack" controls,
546 	   temporary enable jackpoll */
547 	int err;
548 	int old_interval = codec->jackpoll_interval;
549 	codec->jackpoll_interval = msecs_to_jiffies(100);
550 	err = via_build_controls(codec);
551 	codec->jackpoll_interval = old_interval;
552 	return err;
553 }
554 
555 static int vt1708_build_pcms(struct hda_codec *codec)
556 {
557 	struct via_spec *spec = codec->spec;
558 	int i, err;
559 
560 	err = snd_hda_gen_build_pcms(codec);
561 	if (err < 0 || codec->core.vendor_id != 0x11061708)
562 		return err;
563 
564 	/* We got noisy outputs on the right channel on VT1708 when
565 	 * 24bit samples are used.  Until any workaround is found,
566 	 * disable the 24bit format, so far.
567 	 */
568 	for (i = 0; i < ARRAY_SIZE(spec->gen.pcm_rec); i++) {
569 		struct hda_pcm *info = spec->gen.pcm_rec[i];
570 		if (!info)
571 			continue;
572 		if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
573 		    info->pcm_type != HDA_PCM_TYPE_AUDIO)
574 			continue;
575 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].formats =
576 			SNDRV_PCM_FMTBIT_S16_LE;
577 	}
578 
579 	return 0;
580 }
581 
582 static int patch_vt1708(struct hda_codec *codec)
583 {
584 	struct via_spec *spec;
585 	int err;
586 
587 	/* create a codec specific record */
588 	spec = via_new_spec(codec);
589 	if (spec == NULL)
590 		return -ENOMEM;
591 
592 	spec->gen.mixer_nid = 0x17;
593 
594 	/* set jackpoll_interval while parsing the codec */
595 	codec->jackpoll_interval = msecs_to_jiffies(100);
596 	spec->vt1708_jack_detect = 1;
597 
598 	/* don't support the input jack switching due to lack of unsol event */
599 	/* (it may work with polling, though, but it needs testing) */
600 	spec->gen.suppress_auto_mic = 1;
601 	/* Some machines show the broken speaker mute */
602 	spec->gen.auto_mute_via_amp = 1;
603 
604 	/* Add HP and CD pin config connect bit re-config action */
605 	vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
606 	vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
607 
608 	/* automatic parse from the BIOS config */
609 	err = via_parse_auto_config(codec);
610 	if (err < 0) {
611 		via_free(codec);
612 		return err;
613 	}
614 
615 	/* add jack detect on/off control */
616 	spec->mixers[spec->num_mixers++] = vt1708_jack_detect_ctl;
617 
618 	spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs;
619 
620 	codec->patch_ops = via_patch_ops;
621 	codec->patch_ops.build_controls = vt1708_build_controls;
622 	codec->patch_ops.build_pcms = vt1708_build_pcms;
623 
624 	/* clear jackpoll_interval again; it's set dynamically */
625 	codec->jackpoll_interval = 0;
626 
627 	return 0;
628 }
629 
630 static int patch_vt1709(struct hda_codec *codec)
631 {
632 	struct via_spec *spec;
633 	int err;
634 
635 	/* create a codec specific record */
636 	spec = via_new_spec(codec);
637 	if (spec == NULL)
638 		return -ENOMEM;
639 
640 	spec->gen.mixer_nid = 0x18;
641 
642 	err = via_parse_auto_config(codec);
643 	if (err < 0) {
644 		via_free(codec);
645 		return err;
646 	}
647 
648 	codec->patch_ops = via_patch_ops;
649 
650 	return 0;
651 }
652 
653 static int patch_vt1708S(struct hda_codec *codec);
654 static int patch_vt1708B(struct hda_codec *codec)
655 {
656 	struct via_spec *spec;
657 	int err;
658 
659 	if (get_codec_type(codec) == VT1708BCE)
660 		return patch_vt1708S(codec);
661 
662 	/* create a codec specific record */
663 	spec = via_new_spec(codec);
664 	if (spec == NULL)
665 		return -ENOMEM;
666 
667 	spec->gen.mixer_nid = 0x16;
668 
669 	/* automatic parse from the BIOS config */
670 	err = via_parse_auto_config(codec);
671 	if (err < 0) {
672 		via_free(codec);
673 		return err;
674 	}
675 
676 	codec->patch_ops = via_patch_ops;
677 	return 0;
678 }
679 
680 /* Patch for VT1708S */
681 static const struct hda_verb vt1708S_init_verbs[] = {
682 	/* Enable Mic Boost Volume backdoor */
683 	{0x1, 0xf98, 0x1},
684 	/* don't bybass mixer */
685 	{0x1, 0xf88, 0xc0},
686 	{ }
687 };
688 
689 static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
690 			       int offset, int num_steps, int step_size)
691 {
692 	snd_hda_override_wcaps(codec, pin,
693 			       get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
694 	snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
695 				  (offset << AC_AMPCAP_OFFSET_SHIFT) |
696 				  (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
697 				  (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
698 				  (0 << AC_AMPCAP_MUTE_SHIFT));
699 }
700 
701 static int patch_vt1708S(struct hda_codec *codec)
702 {
703 	struct via_spec *spec;
704 	int err;
705 
706 	/* create a codec specific record */
707 	spec = via_new_spec(codec);
708 	if (spec == NULL)
709 		return -ENOMEM;
710 
711 	spec->gen.mixer_nid = 0x16;
712 	override_mic_boost(codec, 0x1a, 0, 3, 40);
713 	override_mic_boost(codec, 0x1e, 0, 3, 40);
714 
715 	/* correct names for VT1708BCE */
716 	if (get_codec_type(codec) == VT1708BCE)	{
717 		kfree(codec->core.chip_name);
718 		codec->core.chip_name = kstrdup("VT1708BCE", GFP_KERNEL);
719 		snprintf(codec->card->mixername,
720 			 sizeof(codec->card->mixername),
721 			 "%s %s", codec->core.vendor_name, codec->core.chip_name);
722 	}
723 	/* correct names for VT1705 */
724 	if (codec->core.vendor_id == 0x11064397) {
725 		kfree(codec->core.chip_name);
726 		codec->core.chip_name = kstrdup("VT1705", GFP_KERNEL);
727 		snprintf(codec->card->mixername,
728 			 sizeof(codec->card->mixername),
729 			 "%s %s", codec->core.vendor_name, codec->core.chip_name);
730 	}
731 
732 	/* automatic parse from the BIOS config */
733 	err = via_parse_auto_config(codec);
734 	if (err < 0) {
735 		via_free(codec);
736 		return err;
737 	}
738 
739 	spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs;
740 
741 	codec->patch_ops = via_patch_ops;
742 	return 0;
743 }
744 
745 /* Patch for VT1702 */
746 
747 static const struct hda_verb vt1702_init_verbs[] = {
748 	/* mixer enable */
749 	{0x1, 0xF88, 0x3},
750 	/* GPIO 0~2 */
751 	{0x1, 0xF82, 0x3F},
752 	{ }
753 };
754 
755 static int patch_vt1702(struct hda_codec *codec)
756 {
757 	struct via_spec *spec;
758 	int err;
759 
760 	/* create a codec specific record */
761 	spec = via_new_spec(codec);
762 	if (spec == NULL)
763 		return -ENOMEM;
764 
765 	spec->gen.mixer_nid = 0x1a;
766 
767 	/* limit AA path volume to 0 dB */
768 	snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
769 				  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
770 				  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
771 				  (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
772 				  (1 << AC_AMPCAP_MUTE_SHIFT));
773 
774 	/* automatic parse from the BIOS config */
775 	err = via_parse_auto_config(codec);
776 	if (err < 0) {
777 		via_free(codec);
778 		return err;
779 	}
780 
781 	spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs;
782 
783 	codec->patch_ops = via_patch_ops;
784 	return 0;
785 }
786 
787 /* Patch for VT1718S */
788 
789 static const struct hda_verb vt1718S_init_verbs[] = {
790 	/* Enable MW0 adjust Gain 5 */
791 	{0x1, 0xfb2, 0x10},
792 	/* Enable Boost Volume backdoor */
793 	{0x1, 0xf88, 0x8},
794 
795 	{ }
796 };
797 
798 /* Add a connection to the primary DAC from AA-mixer for some codecs
799  * This isn't listed from the raw info, but the chip has a secret connection.
800  */
801 static int add_secret_dac_path(struct hda_codec *codec)
802 {
803 	struct via_spec *spec = codec->spec;
804 	int i, nums;
805 	hda_nid_t conn[8];
806 	hda_nid_t nid;
807 
808 	if (!spec->gen.mixer_nid)
809 		return 0;
810 	nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
811 				       ARRAY_SIZE(conn) - 1);
812 	for (i = 0; i < nums; i++) {
813 		if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
814 			return 0;
815 	}
816 
817 	/* find the primary DAC and add to the connection list */
818 	for_each_hda_codec_node(nid, codec) {
819 		unsigned int caps = get_wcaps(codec, nid);
820 		if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
821 		    !(caps & AC_WCAP_DIGITAL)) {
822 			conn[nums++] = nid;
823 			return snd_hda_override_conn_list(codec,
824 							  spec->gen.mixer_nid,
825 							  nums, conn);
826 		}
827 	}
828 	return 0;
829 }
830 
831 
832 static int patch_vt1718S(struct hda_codec *codec)
833 {
834 	struct via_spec *spec;
835 	int err;
836 
837 	/* create a codec specific record */
838 	spec = via_new_spec(codec);
839 	if (spec == NULL)
840 		return -ENOMEM;
841 
842 	spec->gen.mixer_nid = 0x21;
843 	override_mic_boost(codec, 0x2b, 0, 3, 40);
844 	override_mic_boost(codec, 0x29, 0, 3, 40);
845 	add_secret_dac_path(codec);
846 
847 	/* automatic parse from the BIOS config */
848 	err = via_parse_auto_config(codec);
849 	if (err < 0) {
850 		via_free(codec);
851 		return err;
852 	}
853 
854 	spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs;
855 
856 	codec->patch_ops = via_patch_ops;
857 	return 0;
858 }
859 
860 /* Patch for VT1716S */
861 
862 static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
863 			    struct snd_ctl_elem_info *uinfo)
864 {
865 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
866 	uinfo->count = 1;
867 	uinfo->value.integer.min = 0;
868 	uinfo->value.integer.max = 1;
869 	return 0;
870 }
871 
872 static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
873 			   struct snd_ctl_elem_value *ucontrol)
874 {
875 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
876 	int index = 0;
877 
878 	index = snd_hda_codec_read(codec, 0x26, 0,
879 					       AC_VERB_GET_CONNECT_SEL, 0);
880 	if (index != -1)
881 		*ucontrol->value.integer.value = index;
882 
883 	return 0;
884 }
885 
886 static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
887 			   struct snd_ctl_elem_value *ucontrol)
888 {
889 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
890 	struct via_spec *spec = codec->spec;
891 	int index = *ucontrol->value.integer.value;
892 
893 	snd_hda_codec_write(codec, 0x26, 0,
894 					       AC_VERB_SET_CONNECT_SEL, index);
895 	spec->dmic_enabled = index;
896 	return 1;
897 }
898 
899 static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
900 	HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT),
901 	{
902 	 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
903 	 .name = "Digital Mic Capture Switch",
904 	 .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
905 	 .count = 1,
906 	 .info = vt1716s_dmic_info,
907 	 .get = vt1716s_dmic_get,
908 	 .put = vt1716s_dmic_put,
909 	 },
910 	{}			/* end */
911 };
912 
913 
914 /* mono-out mixer elements */
915 static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
916 	HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT),
917 	{ } /* end */
918 };
919 
920 static const struct hda_verb vt1716S_init_verbs[] = {
921 	/* Enable Boost Volume backdoor */
922 	{0x1, 0xf8a, 0x80},
923 	/* don't bybass mixer */
924 	{0x1, 0xf88, 0xc0},
925 	/* Enable mono output */
926 	{0x1, 0xf90, 0x08},
927 	{ }
928 };
929 
930 static int patch_vt1716S(struct hda_codec *codec)
931 {
932 	struct via_spec *spec;
933 	int err;
934 
935 	/* create a codec specific record */
936 	spec = via_new_spec(codec);
937 	if (spec == NULL)
938 		return -ENOMEM;
939 
940 	spec->gen.mixer_nid = 0x16;
941 	override_mic_boost(codec, 0x1a, 0, 3, 40);
942 	override_mic_boost(codec, 0x1e, 0, 3, 40);
943 
944 	/* automatic parse from the BIOS config */
945 	err = via_parse_auto_config(codec);
946 	if (err < 0) {
947 		via_free(codec);
948 		return err;
949 	}
950 
951 	spec->init_verbs[spec->num_iverbs++]  = vt1716S_init_verbs;
952 
953 	spec->mixers[spec->num_mixers++] = vt1716s_dmic_mixer;
954 	spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer;
955 
956 	codec->patch_ops = via_patch_ops;
957 	return 0;
958 }
959 
960 /* for vt2002P */
961 
962 static const struct hda_verb vt2002P_init_verbs[] = {
963 	/* Class-D speaker related verbs */
964 	{0x1, 0xfe0, 0x4},
965 	{0x1, 0xfe9, 0x80},
966 	{0x1, 0xfe2, 0x22},
967 	/* Enable Boost Volume backdoor */
968 	{0x1, 0xfb9, 0x24},
969 	/* Enable AOW0 to MW9 */
970 	{0x1, 0xfb8, 0x88},
971 	{ }
972 };
973 
974 static const struct hda_verb vt1802_init_verbs[] = {
975 	/* Enable Boost Volume backdoor */
976 	{0x1, 0xfb9, 0x24},
977 	/* Enable AOW0 to MW9 */
978 	{0x1, 0xfb8, 0x88},
979 	{ }
980 };
981 
982 /*
983  * pin fix-up
984  */
985 enum {
986 	VIA_FIXUP_INTMIC_BOOST,
987 	VIA_FIXUP_ASUS_G75,
988 };
989 
990 static void via_fixup_intmic_boost(struct hda_codec *codec,
991 				  const struct hda_fixup *fix, int action)
992 {
993 	if (action == HDA_FIXUP_ACT_PRE_PROBE)
994 		override_mic_boost(codec, 0x30, 0, 2, 40);
995 }
996 
997 static const struct hda_fixup via_fixups[] = {
998 	[VIA_FIXUP_INTMIC_BOOST] = {
999 		.type = HDA_FIXUP_FUNC,
1000 		.v.func = via_fixup_intmic_boost,
1001 	},
1002 	[VIA_FIXUP_ASUS_G75] = {
1003 		.type = HDA_FIXUP_PINS,
1004 		.v.pins = (const struct hda_pintbl[]) {
1005 			/* set 0x24 and 0x33 as speakers */
1006 			{ 0x24, 0x991301f0 },
1007 			{ 0x33, 0x991301f1 }, /* subwoofer */
1008 			{ }
1009 		}
1010 	},
1011 };
1012 
1013 static const struct snd_pci_quirk vt2002p_fixups[] = {
1014 	SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
1015 	SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
1016 	{}
1017 };
1018 
1019 /* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
1020  * Replace this with mixer NID 0x1c
1021  */
1022 static void fix_vt1802_connections(struct hda_codec *codec)
1023 {
1024 	static hda_nid_t conn_24[] = { 0x14, 0x1c };
1025 	static hda_nid_t conn_33[] = { 0x1c };
1026 
1027 	snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
1028 	snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
1029 }
1030 
1031 /* patch for vt2002P */
1032 static int patch_vt2002P(struct hda_codec *codec)
1033 {
1034 	struct via_spec *spec;
1035 	int err;
1036 
1037 	/* create a codec specific record */
1038 	spec = via_new_spec(codec);
1039 	if (spec == NULL)
1040 		return -ENOMEM;
1041 
1042 	spec->gen.mixer_nid = 0x21;
1043 	override_mic_boost(codec, 0x2b, 0, 3, 40);
1044 	override_mic_boost(codec, 0x29, 0, 3, 40);
1045 	if (spec->codec_type == VT1802)
1046 		fix_vt1802_connections(codec);
1047 	add_secret_dac_path(codec);
1048 
1049 	snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
1050 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1051 
1052 	/* automatic parse from the BIOS config */
1053 	err = via_parse_auto_config(codec);
1054 	if (err < 0) {
1055 		via_free(codec);
1056 		return err;
1057 	}
1058 
1059 	if (spec->codec_type == VT1802)
1060 		spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs;
1061 	else
1062 		spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs;
1063 
1064 	codec->patch_ops = via_patch_ops;
1065 	return 0;
1066 }
1067 
1068 /* for vt1812 */
1069 
1070 static const struct hda_verb vt1812_init_verbs[] = {
1071 	/* Enable Boost Volume backdoor */
1072 	{0x1, 0xfb9, 0x24},
1073 	/* Enable AOW0 to MW9 */
1074 	{0x1, 0xfb8, 0xa8},
1075 	{ }
1076 };
1077 
1078 /* patch for vt1812 */
1079 static int patch_vt1812(struct hda_codec *codec)
1080 {
1081 	struct via_spec *spec;
1082 	int err;
1083 
1084 	/* create a codec specific record */
1085 	spec = via_new_spec(codec);
1086 	if (spec == NULL)
1087 		return -ENOMEM;
1088 
1089 	spec->gen.mixer_nid = 0x21;
1090 	override_mic_boost(codec, 0x2b, 0, 3, 40);
1091 	override_mic_boost(codec, 0x29, 0, 3, 40);
1092 	add_secret_dac_path(codec);
1093 
1094 	/* automatic parse from the BIOS config */
1095 	err = via_parse_auto_config(codec);
1096 	if (err < 0) {
1097 		via_free(codec);
1098 		return err;
1099 	}
1100 
1101 	spec->init_verbs[spec->num_iverbs++]  = vt1812_init_verbs;
1102 
1103 	codec->patch_ops = via_patch_ops;
1104 	return 0;
1105 }
1106 
1107 /* patch for vt3476 */
1108 
1109 static const struct hda_verb vt3476_init_verbs[] = {
1110 	/* Enable DMic 8/16/32K */
1111 	{0x1, 0xF7B, 0x30},
1112 	/* Enable Boost Volume backdoor */
1113 	{0x1, 0xFB9, 0x20},
1114 	/* Enable AOW-MW9 path */
1115 	{0x1, 0xFB8, 0x10},
1116 	{ }
1117 };
1118 
1119 static int patch_vt3476(struct hda_codec *codec)
1120 {
1121 	struct via_spec *spec;
1122 	int err;
1123 
1124 	/* create a codec specific record */
1125 	spec = via_new_spec(codec);
1126 	if (spec == NULL)
1127 		return -ENOMEM;
1128 
1129 	spec->gen.mixer_nid = 0x3f;
1130 	add_secret_dac_path(codec);
1131 
1132 	/* automatic parse from the BIOS config */
1133 	err = via_parse_auto_config(codec);
1134 	if (err < 0) {
1135 		via_free(codec);
1136 		return err;
1137 	}
1138 
1139 	spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs;
1140 
1141 	codec->patch_ops = via_patch_ops;
1142 	return 0;
1143 }
1144 
1145 /*
1146  * patch entries
1147  */
1148 static const struct hda_codec_preset snd_hda_preset_via[] = {
1149 	{ .id = 0x11061708, .name = "VT1708", .patch = patch_vt1708},
1150 	{ .id = 0x11061709, .name = "VT1708", .patch = patch_vt1708},
1151 	{ .id = 0x1106170a, .name = "VT1708", .patch = patch_vt1708},
1152 	{ .id = 0x1106170b, .name = "VT1708", .patch = patch_vt1708},
1153 	{ .id = 0x1106e710, .name = "VT1709 10-Ch",
1154 	  .patch = patch_vt1709},
1155 	{ .id = 0x1106e711, .name = "VT1709 10-Ch",
1156 	  .patch = patch_vt1709},
1157 	{ .id = 0x1106e712, .name = "VT1709 10-Ch",
1158 	  .patch = patch_vt1709},
1159 	{ .id = 0x1106e713, .name = "VT1709 10-Ch",
1160 	  .patch = patch_vt1709},
1161 	{ .id = 0x1106e714, .name = "VT1709 6-Ch",
1162 	  .patch = patch_vt1709},
1163 	{ .id = 0x1106e715, .name = "VT1709 6-Ch",
1164 	  .patch = patch_vt1709},
1165 	{ .id = 0x1106e716, .name = "VT1709 6-Ch",
1166 	  .patch = patch_vt1709},
1167 	{ .id = 0x1106e717, .name = "VT1709 6-Ch",
1168 	  .patch = patch_vt1709},
1169 	{ .id = 0x1106e720, .name = "VT1708B 8-Ch",
1170 	  .patch = patch_vt1708B},
1171 	{ .id = 0x1106e721, .name = "VT1708B 8-Ch",
1172 	  .patch = patch_vt1708B},
1173 	{ .id = 0x1106e722, .name = "VT1708B 8-Ch",
1174 	  .patch = patch_vt1708B},
1175 	{ .id = 0x1106e723, .name = "VT1708B 8-Ch",
1176 	  .patch = patch_vt1708B},
1177 	{ .id = 0x1106e724, .name = "VT1708B 4-Ch",
1178 	  .patch = patch_vt1708B},
1179 	{ .id = 0x1106e725, .name = "VT1708B 4-Ch",
1180 	  .patch = patch_vt1708B},
1181 	{ .id = 0x1106e726, .name = "VT1708B 4-Ch",
1182 	  .patch = patch_vt1708B},
1183 	{ .id = 0x1106e727, .name = "VT1708B 4-Ch",
1184 	  .patch = patch_vt1708B},
1185 	{ .id = 0x11060397, .name = "VT1708S",
1186 	  .patch = patch_vt1708S},
1187 	{ .id = 0x11061397, .name = "VT1708S",
1188 	  .patch = patch_vt1708S},
1189 	{ .id = 0x11062397, .name = "VT1708S",
1190 	  .patch = patch_vt1708S},
1191 	{ .id = 0x11063397, .name = "VT1708S",
1192 	  .patch = patch_vt1708S},
1193 	{ .id = 0x11064397, .name = "VT1705",
1194 	  .patch = patch_vt1708S},
1195 	{ .id = 0x11065397, .name = "VT1708S",
1196 	  .patch = patch_vt1708S},
1197 	{ .id = 0x11066397, .name = "VT1708S",
1198 	  .patch = patch_vt1708S},
1199 	{ .id = 0x11067397, .name = "VT1708S",
1200 	  .patch = patch_vt1708S},
1201 	{ .id = 0x11060398, .name = "VT1702",
1202 	  .patch = patch_vt1702},
1203 	{ .id = 0x11061398, .name = "VT1702",
1204 	  .patch = patch_vt1702},
1205 	{ .id = 0x11062398, .name = "VT1702",
1206 	  .patch = patch_vt1702},
1207 	{ .id = 0x11063398, .name = "VT1702",
1208 	  .patch = patch_vt1702},
1209 	{ .id = 0x11064398, .name = "VT1702",
1210 	  .patch = patch_vt1702},
1211 	{ .id = 0x11065398, .name = "VT1702",
1212 	  .patch = patch_vt1702},
1213 	{ .id = 0x11066398, .name = "VT1702",
1214 	  .patch = patch_vt1702},
1215 	{ .id = 0x11067398, .name = "VT1702",
1216 	  .patch = patch_vt1702},
1217 	{ .id = 0x11060428, .name = "VT1718S",
1218 	  .patch = patch_vt1718S},
1219 	{ .id = 0x11064428, .name = "VT1718S",
1220 	  .patch = patch_vt1718S},
1221 	{ .id = 0x11060441, .name = "VT2020",
1222 	  .patch = patch_vt1718S},
1223 	{ .id = 0x11064441, .name = "VT1828S",
1224 	  .patch = patch_vt1718S},
1225 	{ .id = 0x11060433, .name = "VT1716S",
1226 	  .patch = patch_vt1716S},
1227 	{ .id = 0x1106a721, .name = "VT1716S",
1228 	  .patch = patch_vt1716S},
1229 	{ .id = 0x11060438, .name = "VT2002P", .patch = patch_vt2002P},
1230 	{ .id = 0x11064438, .name = "VT2002P", .patch = patch_vt2002P},
1231 	{ .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812},
1232 	{ .id = 0x11060440, .name = "VT1818S",
1233 	  .patch = patch_vt1708S},
1234 	{ .id = 0x11060446, .name = "VT1802",
1235 		.patch = patch_vt2002P},
1236 	{ .id = 0x11068446, .name = "VT1802",
1237 		.patch = patch_vt2002P},
1238 	{ .id = 0x11064760, .name = "VT1705CF",
1239 		.patch = patch_vt3476},
1240 	{ .id = 0x11064761, .name = "VT1708SCE",
1241 		.patch = patch_vt3476},
1242 	{ .id = 0x11064762, .name = "VT1808",
1243 		.patch = patch_vt3476},
1244 	{} /* terminator */
1245 };
1246 
1247 MODULE_ALIAS("snd-hda-codec-id:1106*");
1248 
1249 static struct hda_codec_driver via_driver = {
1250 	.preset = snd_hda_preset_via,
1251 };
1252 
1253 MODULE_LICENSE("GPL");
1254 MODULE_DESCRIPTION("VIA HD-audio codec");
1255 
1256 module_hda_codec_driver(via_driver);
1257