cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

patch_via.c (32492B)


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