ALSA: hda - Move a part of hda_codec stuff into hdac_device
[linux-2.6-block.git] / sound / pci / hda / patch_via.c
CommitLineData
c577b8a1
JC
1/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
8e86597f 4 * HD audio interface patch for VIA VT17xx/VT18xx/VT20xx codec
c577b8a1 5 *
8e86597f
LW
6 * (C) 2006-2009 VIA Technology, Inc.
7 * (C) 2006-2008 Takashi Iwai <tiwai@suse.de>
c577b8a1
JC
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 * * * * * * * * * * * * * * * * */
377ff31a 25/* */
c577b8a1 26/* 2006-03-03 Lydia Wang Create the basic patch to support VT1708 codec */
377ff31a
LW
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 */
c577b8a1 29/* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */
377ff31a
LW
30/* 2007-09-12 Lydia Wang Add EAPD enable during driver initialization */
31/* 2007-09-17 Lydia Wang Add VT1708B codec support */
76d9b0dd 32/* 2007-11-14 Lydia Wang Add VT1708A codec HP and CD pin connect config */
fb4cb772 33/* 2008-02-03 Lydia Wang Fix Rear channels and Back channels inverse issue */
377ff31a
LW
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 */
98aa34c0 37/* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */
377ff31a 38/* 2008-09-15 Logan Li Add VT1708S Mic Boost workaround/backdoor */
8e86597f
LW
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 */
36dd5c4a 44/* 2009-09-19 Lydia Wang Add support for VT1818S */
377ff31a 45/* */
c577b8a1
JC
46/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47
48
c577b8a1
JC
49#include <linux/init.h>
50#include <linux/delay.h>
51#include <linux/slab.h>
da155d5b 52#include <linux/module.h>
c577b8a1 53#include <sound/core.h>
0aa62aef 54#include <sound/asoundef.h>
c577b8a1
JC
55#include "hda_codec.h"
56#include "hda_local.h"
128bc4ba 57#include "hda_auto_parser.h"
1835a0f9 58#include "hda_jack.h"
b3f6008f 59#include "hda_generic.h"
c577b8a1 60
c577b8a1 61/* Pin Widget NID */
d949cac1
HW
62#define VT1708_HP_PIN_NID 0x20
63#define VT1708_CD_PIN_NID 0x24
c577b8a1 64
d7426329
HW
65enum VIA_HDA_CODEC {
66 UNKNOWN = -1,
67 VT1708,
68 VT1709_10CH,
69 VT1709_6CH,
70 VT1708B_8CH,
71 VT1708B_4CH,
72 VT1708S,
518bf3ba 73 VT1708BCE,
d7426329 74 VT1702,
eb7188ca 75 VT1718S,
f3db423d 76 VT1716S,
25eaba2f 77 VT2002P,
ab6734e7 78 VT1812,
11890956 79 VT1802,
43737e0a 80 VT1705CF,
6121b84a 81 VT1808,
d7426329
HW
82 CODEC_TYPES,
83};
84
11890956
LW
85#define VT2002P_COMPATIBLE(spec) \
86 ((spec)->codec_type == VT2002P ||\
87 (spec)->codec_type == VT1812 ||\
88 (spec)->codec_type == VT1802)
89
1f2e99fe 90struct via_spec {
b3f6008f
TI
91 struct hda_gen_spec gen;
92
1f2e99fe 93 /* codec parameterization */
90dd48a1 94 const struct snd_kcontrol_new *mixers[6];
1f2e99fe
LW
95 unsigned int num_mixers;
96
90dd48a1 97 const struct hda_verb *init_verbs[5];
1f2e99fe
LW
98 unsigned int num_iverbs;
99
1f2e99fe 100 /* HP mode source */
f3db423d 101 unsigned int dmic_enabled;
1f2e99fe
LW
102 enum VIA_HDA_CODEC codec_type;
103
e9d010c2
TI
104 /* analog low-power control */
105 bool alc_mode;
106
1f2e99fe 107 /* work to check hp jack state */
187d333e 108 int hp_work_active;
e06e5a29 109 int vt1708_jack_detect;
1f2e99fe
LW
110};
111
0341ccd7 112static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
b3f6008f
TI
113static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
114 struct hda_codec *codec,
115 struct snd_pcm_substream *substream,
116 int action);
b3f6008f
TI
117
118static struct via_spec *via_new_spec(struct hda_codec *codec)
5b0cb1d8
JK
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;
b3f6008f 127 snd_hda_gen_spec_init(&spec->gen);
0341ccd7
LW
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;
13961170 132 spec->gen.indep_hp = 1;
05909d5c 133 spec->gen.keep_eapd_on = 1;
b3f6008f 134 spec->gen.pcm_playback_hook = via_playback_pcm_hook;
74f14b36 135 spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
967b1307 136 codec->power_save_node = 1;
688b12cc 137 spec->gen.power_down_unused = 1;
5b0cb1d8
JK
138 return spec;
139}
140
744ff5f4 141static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
d7426329 142{
7639a06c 143 u32 vendor_id = codec->core.vendor_id;
d7426329
HW
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;
518bf3ba 157 else if (dev_id >= 0xe720 && dev_id <= 0xe723) {
d7426329 158 codec_type = VT1708B_8CH;
518bf3ba
LW
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)
d7426329
HW
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;
eb7188ca
LW
169 else if ((dev_id & 0xfff) == 0x428
170 && (dev_id >> 12) < 8)
171 codec_type = VT1718S;
f3db423d
LW
172 else if (dev_id == 0x0433 || dev_id == 0xa721)
173 codec_type = VT1716S;
bb3c6bfc
LW
174 else if (dev_id == 0x0441 || dev_id == 0x4441)
175 codec_type = VT1718S;
25eaba2f
LW
176 else if (dev_id == 0x0438 || dev_id == 0x4438)
177 codec_type = VT2002P;
ab6734e7
LW
178 else if (dev_id == 0x0448)
179 codec_type = VT1812;
36dd5c4a
LW
180 else if (dev_id == 0x0440)
181 codec_type = VT1708S;
11890956
LW
182 else if ((dev_id & 0xfff) == 0x446)
183 codec_type = VT1802;
43737e0a
LW
184 else if (dev_id == 0x4760)
185 codec_type = VT1705CF;
6121b84a
LW
186 else if (dev_id == 0x4761 || dev_id == 0x4762)
187 codec_type = VT1808;
d7426329
HW
188 else
189 codec_type = UNKNOWN;
190 return codec_type;
191};
192
ada509ec
TI
193static void analog_low_current_mode(struct hda_codec *codec);
194static bool is_aa_path_mute(struct hda_codec *codec);
1f2e99fe 195
187d333e
TI
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
b3f6008f 200static void vt1708_stop_hp_work(struct hda_codec *codec)
1f2e99fe 201{
b3f6008f
TI
202 struct via_spec *spec = codec->spec;
203 if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
1f2e99fe 204 return;
187d333e 205 if (spec->hp_work_active) {
b3f6008f 206 snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
7eaa9161 207 codec->jackpoll_interval = 0;
b3f6008f
TI
208 cancel_delayed_work_sync(&codec->jackpoll_work);
209 spec->hp_work_active = false;
187d333e 210 }
1f2e99fe
LW
211}
212
b3f6008f 213static void vt1708_update_hp_work(struct hda_codec *codec)
1f2e99fe 214{
b3f6008f
TI
215 struct via_spec *spec = codec->spec;
216 if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
1f2e99fe 217 return;
05dc0fc9 218 if (spec->vt1708_jack_detect) {
187d333e 219 if (!spec->hp_work_active) {
b3f6008f
TI
220 codec->jackpoll_interval = msecs_to_jiffies(100);
221 snd_hda_codec_write(codec, 0x1, 0, 0xf81, 0);
2f35c630 222 schedule_delayed_work(&codec->jackpoll_work, 0);
b3f6008f 223 spec->hp_work_active = true;
187d333e 224 }
b3f6008f
TI
225 } else if (!hp_detect_with_aa(codec))
226 vt1708_stop_hp_work(codec);
1f2e99fe 227}
f5271101 228
24088a58
TI
229static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
230 struct snd_ctl_elem_info *uinfo)
231{
dda415d4 232 return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
24088a58
TI
233}
234
235static 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);
967b1307 239 ucontrol->value.enumerated.item[0] = codec->power_save_node;
24088a58
TI
240 return 0;
241}
242
243static 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;
688b12cc 248 bool val = !!ucontrol->value.enumerated.item[0];
24088a58 249
967b1307 250 if (val == codec->power_save_node)
24088a58 251 return 0;
967b1307 252 codec->power_save_node = val;
688b12cc 253 spec->gen.power_down_unused = val;
e9d010c2 254 analog_low_current_mode(codec);
24088a58
TI
255 return 1;
256}
257
b3f6008f
TI
258static const struct snd_kcontrol_new via_pin_power_ctl_enum[] = {
259 {
24088a58
TI
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,
b3f6008f
TI
265 },
266 {} /* terminator */
24088a58
TI
267};
268
269
b3f6008f
TI
270/* check AA path's mute status */
271static bool is_aa_path_mute(struct hda_codec *codec)
0aa62aef 272{
cdc1784d 273 struct via_spec *spec = codec->spec;
b3f6008f 274 const struct hda_amp_list *p;
0186f4f4 275 int ch, v;
cdc1784d 276
0186f4f4
TI
277 p = spec->gen.loopback.amplist;
278 if (!p)
279 return true;
280 for (; p->nid; p++) {
b3f6008f
TI
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 }
3b607e3d 287 }
b3f6008f 288 return true;
3b607e3d
TI
289}
290
b3f6008f
TI
291/* enter/exit analog low-current mode */
292static void __analog_low_current_mode(struct hda_codec *codec, bool force)
3b607e3d
TI
293{
294 struct via_spec *spec = codec->spec;
b3f6008f
TI
295 bool enable;
296 unsigned int verb, parm;
3b607e3d 297
967b1307 298 if (!codec->power_save_node)
b3f6008f
TI
299 enable = false;
300 else
301 enable = is_aa_path_mute(codec) && !spec->gen.active_streams;
302 if (enable == spec->alc_mode && !force)
3b607e3d 303 return;
b3f6008f 304 spec->alc_mode = enable;
3b607e3d 305
b3f6008f
TI
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 */
f5271101
LW
336 }
337 /* send verb */
7639a06c 338 snd_hda_codec_write(codec, codec->core.afg, 0, verb, parm);
a86a88ea
TI
339}
340
b3f6008f
TI
341static void analog_low_current_mode(struct hda_codec *codec)
342{
343 return __analog_low_current_mode(codec, false);
344}
a86a88ea 345
b3f6008f 346static int via_build_controls(struct hda_codec *codec)
a86a88ea
TI
347{
348 struct via_spec *spec = codec->spec;
b3f6008f 349 int err, i;
a766d0d7 350
b3f6008f 351 err = snd_hda_gen_build_controls(codec);
a766d0d7
TI
352 if (err < 0)
353 return err;
c577b8a1 354
688b12cc 355 spec->mixers[spec->num_mixers++] = via_pin_power_ctl_enum;
c577b8a1 356
b3f6008f
TI
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 }
a86a88ea
TI
362
363 return 0;
364}
365
b3f6008f
TI
366static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
367 struct hda_codec *codec,
368 struct snd_pcm_substream *substream,
369 int action)
a86a88ea 370{
b3f6008f
TI
371 analog_low_current_mode(codec);
372 vt1708_update_hp_work(codec);
a86a88ea
TI
373}
374
b3f6008f 375static void via_free(struct hda_codec *codec)
a86a88ea 376{
b3f6008f 377 vt1708_stop_hp_work(codec);
a8dca460 378 snd_hda_gen_free(codec);
a86a88ea
TI
379}
380
b3f6008f
TI
381#ifdef CONFIG_PM
382static int via_suspend(struct hda_codec *codec)
a86a88ea
TI
383{
384 struct via_spec *spec = codec->spec;
b3f6008f 385 vt1708_stop_hp_work(codec);
d7a99cce 386
2c38d990
TI
387 /* Fix pop noise on headphones */
388 if (spec->codec_type == VT1802)
389 snd_hda_shutup_pins(codec);
d7a99cce 390
a86a88ea
TI
391 return 0;
392}
b3f6008f 393#endif
a86a88ea 394
b3f6008f
TI
395#ifdef CONFIG_PM
396static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
a86a88ea
TI
397{
398 struct via_spec *spec = codec->spec;
b3f6008f
TI
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
a86a88ea 404
b3f6008f
TI
405/*
406 */
a86a88ea 407
b3f6008f 408static int via_init(struct hda_codec *codec);
a86a88ea 409
b3f6008f
TI
410static 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};
a86a88ea 421
c577b8a1 422
b3f6008f
TI
423static const struct hda_verb vt1708_init_verbs[] = {
424 /* power down jack detect function */
425 {0x1, 0xf81, 0x1},
426 { }
427};
76d9b0dd
HW
428static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
429{
430 unsigned int def_conf;
431 unsigned char seqassoc;
432
2f334f92 433 def_conf = snd_hda_codec_get_pincfg(codec, nid);
76d9b0dd
HW
434 seqassoc = (unsigned char) get_defcfg_association(def_conf);
435 seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
82ef9e45
LW
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);
76d9b0dd
HW
440 }
441
442 return;
443}
444
e06e5a29 445static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
1f2e99fe
LW
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;
e06e5a29 453 ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
1f2e99fe
LW
454 return 0;
455}
456
e06e5a29 457static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
1f2e99fe
LW
458 struct snd_ctl_elem_value *ucontrol)
459{
460 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
461 struct via_spec *spec = codec->spec;
187d333e 462 int val;
1f2e99fe
LW
463
464 if (spec->codec_type != VT1708)
465 return 0;
187d333e
TI
466 val = !!ucontrol->value.integer.value[0];
467 if (spec->vt1708_jack_detect == val)
468 return 0;
469 spec->vt1708_jack_detect = val;
b3f6008f 470 vt1708_update_hp_work(codec);
187d333e 471 return 1;
1f2e99fe
LW
472}
473
b3f6008f
TI
474static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = {
475 {
e06e5a29
TI
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,
b3f6008f
TI
482 },
483 {} /* terminator */
1f2e99fe
LW
484};
485
4abdbd1c
TI
486static 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};
494static 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
b3f6008f
TI
503static int via_parse_auto_config(struct hda_codec *codec)
504{
505 struct via_spec *spec = codec->spec;
506 int err;
507
4abdbd1c
TI
508 spec->gen.main_out_badness = &via_main_out_badness;
509 spec->gen.extra_out_badness = &via_extra_out_badness;
510
b3f6008f
TI
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
688b12cc 519 /* disable widget PM at start for compatibility */
967b1307 520 codec->power_save_node = 0;
688b12cc 521 spec->gen.power_down_unused = 0;
b3f6008f
TI
522 return 0;
523}
524
5d41762a
TI
525static 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]);
25eaba2f 532
e9d010c2 533 /* init power states */
e9d010c2
TI
534 __analog_low_current_mode(codec, true);
535
b3f6008f 536 snd_hda_gen_init(codec);
4a918ffe 537
b3f6008f 538 vt1708_update_hp_work(codec);
25eaba2f 539
c577b8a1
JC
540 return 0;
541}
542
f672f65a
DH
543static 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
b3f6008f 555static int vt1708_build_pcms(struct hda_codec *codec)
337b9d02
TI
556{
557 struct via_spec *spec = codec->spec;
b3f6008f
TI
558 int i, err;
559
560 err = snd_hda_gen_build_pcms(codec);
7639a06c 561 if (err < 0 || codec->core.vendor_id != 0x11061708)
b3f6008f
TI
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 */
bbbc7e85
TI
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;
b3f6008f
TI
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;
337b9d02 577 }
b3f6008f 578
1c55d521 579 return 0;
337b9d02
TI
580}
581
c577b8a1
JC
582static int patch_vt1708(struct hda_codec *codec)
583{
584 struct via_spec *spec;
585 int err;
586
587 /* create a codec specific record */
5b0cb1d8 588 spec = via_new_spec(codec);
c577b8a1
JC
589 if (spec == NULL)
590 return -ENOMEM;
591
b3f6008f
TI
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;
eb33ccf7
TI
601 /* Some machines show the broken speaker mute */
602 spec->gen.auto_mute_via_amp = 1;
620e2b28 603
12daef65
TI
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
c577b8a1 608 /* automatic parse from the BIOS config */
12daef65 609 err = via_parse_auto_config(codec);
c577b8a1
JC
610 if (err < 0) {
611 via_free(codec);
612 return err;
c577b8a1
JC
613 }
614
12daef65 615 /* add jack detect on/off control */
b3f6008f 616 spec->mixers[spec->num_mixers++] = vt1708_jack_detect_ctl;
c577b8a1 617
e322a36d
LW
618 spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs;
619
c577b8a1 620 codec->patch_ops = via_patch_ops;
f672f65a 621 codec->patch_ops.build_controls = vt1708_build_controls;
b3f6008f
TI
622 codec->patch_ops.build_pcms = vt1708_build_pcms;
623
624 /* clear jackpoll_interval again; it's set dynamically */
625 codec->jackpoll_interval = 0;
c577b8a1 626
c577b8a1
JC
627 return 0;
628}
629
ddd304d8 630static int patch_vt1709(struct hda_codec *codec)
c577b8a1
JC
631{
632 struct via_spec *spec;
633 int err;
634
635 /* create a codec specific record */
5b0cb1d8 636 spec = via_new_spec(codec);
c577b8a1
JC
637 if (spec == NULL)
638 return -ENOMEM;
639
b3f6008f 640 spec->gen.mixer_nid = 0x18;
620e2b28 641
12daef65 642 err = via_parse_auto_config(codec);
c577b8a1
JC
643 if (err < 0) {
644 via_free(codec);
645 return err;
c577b8a1
JC
646 }
647
c577b8a1
JC
648 codec->patch_ops = via_patch_ops;
649
f7278fd0
JC
650 return 0;
651}
652
518bf3ba 653static int patch_vt1708S(struct hda_codec *codec);
ddd304d8 654static int patch_vt1708B(struct hda_codec *codec)
f7278fd0
JC
655{
656 struct via_spec *spec;
657 int err;
658
518bf3ba
LW
659 if (get_codec_type(codec) == VT1708BCE)
660 return patch_vt1708S(codec);
ddd304d8 661
f7278fd0 662 /* create a codec specific record */
5b0cb1d8 663 spec = via_new_spec(codec);
f7278fd0
JC
664 if (spec == NULL)
665 return -ENOMEM;
666
b3f6008f 667 spec->gen.mixer_nid = 0x16;
620e2b28 668
f7278fd0 669 /* automatic parse from the BIOS config */
12daef65 670 err = via_parse_auto_config(codec);
f7278fd0
JC
671 if (err < 0) {
672 via_free(codec);
673 return err;
f7278fd0
JC
674 }
675
f7278fd0 676 codec->patch_ops = via_patch_ops;
f7278fd0
JC
677 return 0;
678}
679
d949cac1 680/* Patch for VT1708S */
096a8854 681static const struct hda_verb vt1708S_init_verbs[] = {
d7426329
HW
682 /* Enable Mic Boost Volume backdoor */
683 {0x1, 0xf98, 0x1},
bc7e7e5c
LW
684 /* don't bybass mixer */
685 {0x1, 0xf88, 0xc0},
d949cac1
HW
686 { }
687};
688
6369bcfc
LW
689static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
690 int offset, int num_steps, int step_size)
691{
d045c5dc
TI
692 snd_hda_override_wcaps(codec, pin,
693 get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
6369bcfc
LW
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
d949cac1
HW
701static int patch_vt1708S(struct hda_codec *codec)
702{
703 struct via_spec *spec;
704 int err;
705
706 /* create a codec specific record */
5b0cb1d8 707 spec = via_new_spec(codec);
d949cac1
HW
708 if (spec == NULL)
709 return -ENOMEM;
710
b3f6008f 711 spec->gen.mixer_nid = 0x16;
d7a99cce
TI
712 override_mic_boost(codec, 0x1a, 0, 3, 40);
713 override_mic_boost(codec, 0x1e, 0, 3, 40);
620e2b28 714
518bf3ba
LW
715 /* correct names for VT1708BCE */
716 if (get_codec_type(codec) == VT1708BCE) {
7639a06c
TI
717 kfree(codec->core.chip_name);
718 codec->core.chip_name = kstrdup("VT1708BCE", GFP_KERNEL);
6efdd851
TI
719 snprintf(codec->card->mixername,
720 sizeof(codec->card->mixername),
7639a06c 721 "%s %s", codec->core.vendor_name, codec->core.chip_name);
970f630f 722 }
bc92df7f 723 /* correct names for VT1705 */
7639a06c
TI
724 if (codec->core.vendor_id == 0x11064397) {
725 kfree(codec->core.chip_name);
726 codec->core.chip_name = kstrdup("VT1705", GFP_KERNEL);
6efdd851
TI
727 snprintf(codec->card->mixername,
728 sizeof(codec->card->mixername),
7639a06c 729 "%s %s", codec->core.vendor_name, codec->core.chip_name);
bc92df7f 730 }
b3f6008f
TI
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;
d949cac1
HW
742 return 0;
743}
744
745/* Patch for VT1702 */
746
096a8854 747static const struct hda_verb vt1702_init_verbs[] = {
bc7e7e5c
LW
748 /* mixer enable */
749 {0x1, 0xF88, 0x3},
750 /* GPIO 0~2 */
751 {0x1, 0xF82, 0x3F},
d949cac1
HW
752 { }
753};
754
d949cac1
HW
755static int patch_vt1702(struct hda_codec *codec)
756{
757 struct via_spec *spec;
758 int err;
d949cac1
HW
759
760 /* create a codec specific record */
5b0cb1d8 761 spec = via_new_spec(codec);
d949cac1
HW
762 if (spec == NULL)
763 return -ENOMEM;
764
b3f6008f 765 spec->gen.mixer_nid = 0x1a;
620e2b28 766
12daef65
TI
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
d949cac1 774 /* automatic parse from the BIOS config */
12daef65 775 err = via_parse_auto_config(codec);
d949cac1
HW
776 if (err < 0) {
777 via_free(codec);
778 return err;
d949cac1
HW
779 }
780
096a8854 781 spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs;
d949cac1 782
d949cac1 783 codec->patch_ops = via_patch_ops;
d949cac1
HW
784 return 0;
785}
786
eb7188ca
LW
787/* Patch for VT1718S */
788
096a8854 789static const struct hda_verb vt1718S_init_verbs[] = {
4ab2d53a
LW
790 /* Enable MW0 adjust Gain 5 */
791 {0x1, 0xfb2, 0x10},
eb7188ca
LW
792 /* Enable Boost Volume backdoor */
793 {0x1, 0xf88, 0x8},
5d41762a 794
eb7188ca
LW
795 { }
796};
797
30b45033
TI
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 */
801static 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
b3f6008f 808 if (!spec->gen.mixer_nid)
30b45033 809 return 0;
b3f6008f 810 nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
30b45033
TI
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 */
7639a06c 818 for_each_hda_codec_node(nid, codec) {
30b45033
TI
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,
b3f6008f 824 spec->gen.mixer_nid,
30b45033
TI
825 nums, conn);
826 }
827 }
828 return 0;
829}
830
831
eb7188ca
LW
832static int patch_vt1718S(struct hda_codec *codec)
833{
834 struct via_spec *spec;
835 int err;
836
837 /* create a codec specific record */
5b0cb1d8 838 spec = via_new_spec(codec);
eb7188ca
LW
839 if (spec == NULL)
840 return -ENOMEM;
841
b3f6008f 842 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
843 override_mic_boost(codec, 0x2b, 0, 3, 40);
844 override_mic_boost(codec, 0x29, 0, 3, 40);
30b45033 845 add_secret_dac_path(codec);
620e2b28 846
eb7188ca 847 /* automatic parse from the BIOS config */
12daef65 848 err = via_parse_auto_config(codec);
eb7188ca
LW
849 if (err < 0) {
850 via_free(codec);
851 return err;
eb7188ca
LW
852 }
853
096a8854 854 spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs;
eb7188ca 855
eb7188ca 856 codec->patch_ops = via_patch_ops;
eb7188ca
LW
857 return 0;
858}
f3db423d
LW
859
860/* Patch for VT1716S */
861
862static 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
872static 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
886static 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;
f3db423d
LW
896 return 1;
897}
898
90dd48a1 899static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
f3db423d
LW
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",
5b0cb1d8 904 .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
f3db423d
LW
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 */
90dd48a1 915static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
f3db423d
LW
916 HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT),
917 { } /* end */
918};
919
096a8854 920static const struct hda_verb vt1716S_init_verbs[] = {
f3db423d
LW
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
f3db423d
LW
930static int patch_vt1716S(struct hda_codec *codec)
931{
932 struct via_spec *spec;
933 int err;
934
935 /* create a codec specific record */
5b0cb1d8 936 spec = via_new_spec(codec);
f3db423d
LW
937 if (spec == NULL)
938 return -ENOMEM;
939
b3f6008f 940 spec->gen.mixer_nid = 0x16;
d7a99cce
TI
941 override_mic_boost(codec, 0x1a, 0, 3, 40);
942 override_mic_boost(codec, 0x1e, 0, 3, 40);
620e2b28 943
f3db423d 944 /* automatic parse from the BIOS config */
12daef65 945 err = via_parse_auto_config(codec);
f3db423d
LW
946 if (err < 0) {
947 via_free(codec);
948 return err;
f3db423d
LW
949 }
950
096a8854 951 spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs;
f3db423d 952
b3f6008f 953 spec->mixers[spec->num_mixers++] = vt1716s_dmic_mixer;
f3db423d
LW
954 spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer;
955
956 codec->patch_ops = via_patch_ops;
f3db423d
LW
957 return 0;
958}
25eaba2f
LW
959
960/* for vt2002P */
961
096a8854 962static const struct hda_verb vt2002P_init_verbs[] = {
eadb9a80
LW
963 /* Class-D speaker related verbs */
964 {0x1, 0xfe0, 0x4},
965 {0x1, 0xfe9, 0x80},
966 {0x1, 0xfe2, 0x22},
25eaba2f
LW
967 /* Enable Boost Volume backdoor */
968 {0x1, 0xfb9, 0x24},
25eaba2f
LW
969 /* Enable AOW0 to MW9 */
970 {0x1, 0xfb8, 0x88},
971 { }
972};
4a918ffe 973
096a8854 974static const struct hda_verb vt1802_init_verbs[] = {
11890956
LW
975 /* Enable Boost Volume backdoor */
976 {0x1, 0xfb9, 0x24},
11890956
LW
977 /* Enable AOW0 to MW9 */
978 {0x1, 0xfb8, 0x88},
979 { }
980};
25eaba2f 981
4b527b65
DH
982/*
983 * pin fix-up
984 */
985enum {
986 VIA_FIXUP_INTMIC_BOOST,
d5266125 987 VIA_FIXUP_ASUS_G75,
4b527b65
DH
988};
989
990static 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
997static const struct hda_fixup via_fixups[] = {
998 [VIA_FIXUP_INTMIC_BOOST] = {
999 .type = HDA_FIXUP_FUNC,
1000 .v.func = via_fixup_intmic_boost,
1001 },
d5266125
TI
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 },
4b527b65
DH
1011};
1012
1013static const struct snd_pci_quirk vt2002p_fixups[] = {
d5266125 1014 SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
4b527b65
DH
1015 SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
1016 {}
1017};
1018
ef4da458
TI
1019/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
1020 * Replace this with mixer NID 0x1c
1021 */
1022static 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
25eaba2f
LW
1031/* patch for vt2002P */
1032static int patch_vt2002P(struct hda_codec *codec)
1033{
1034 struct via_spec *spec;
1035 int err;
1036
1037 /* create a codec specific record */
5b0cb1d8 1038 spec = via_new_spec(codec);
25eaba2f
LW
1039 if (spec == NULL)
1040 return -ENOMEM;
1041
b3f6008f 1042 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1043 override_mic_boost(codec, 0x2b, 0, 3, 40);
1044 override_mic_boost(codec, 0x29, 0, 3, 40);
ef4da458
TI
1045 if (spec->codec_type == VT1802)
1046 fix_vt1802_connections(codec);
30b45033 1047 add_secret_dac_path(codec);
620e2b28 1048
4b527b65
DH
1049 snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
1050 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1051
25eaba2f 1052 /* automatic parse from the BIOS config */
12daef65 1053 err = via_parse_auto_config(codec);
25eaba2f
LW
1054 if (err < 0) {
1055 via_free(codec);
1056 return err;
25eaba2f
LW
1057 }
1058
11890956 1059 if (spec->codec_type == VT1802)
4a918ffe 1060 spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs;
11890956 1061 else
4a918ffe 1062 spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs;
11890956 1063
25eaba2f 1064 codec->patch_ops = via_patch_ops;
25eaba2f
LW
1065 return 0;
1066}
ab6734e7
LW
1067
1068/* for vt1812 */
1069
096a8854 1070static const struct hda_verb vt1812_init_verbs[] = {
ab6734e7
LW
1071 /* Enable Boost Volume backdoor */
1072 {0x1, 0xfb9, 0x24},
ab6734e7
LW
1073 /* Enable AOW0 to MW9 */
1074 {0x1, 0xfb8, 0xa8},
1075 { }
1076};
1077
ab6734e7
LW
1078/* patch for vt1812 */
1079static int patch_vt1812(struct hda_codec *codec)
1080{
1081 struct via_spec *spec;
1082 int err;
1083
1084 /* create a codec specific record */
5b0cb1d8 1085 spec = via_new_spec(codec);
ab6734e7
LW
1086 if (spec == NULL)
1087 return -ENOMEM;
1088
b3f6008f 1089 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1090 override_mic_boost(codec, 0x2b, 0, 3, 40);
1091 override_mic_boost(codec, 0x29, 0, 3, 40);
30b45033 1092 add_secret_dac_path(codec);
620e2b28 1093
ab6734e7 1094 /* automatic parse from the BIOS config */
12daef65 1095 err = via_parse_auto_config(codec);
ab6734e7
LW
1096 if (err < 0) {
1097 via_free(codec);
1098 return err;
ab6734e7
LW
1099 }
1100
096a8854 1101 spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs;
ab6734e7 1102
ab6734e7 1103 codec->patch_ops = via_patch_ops;
ab6734e7
LW
1104 return 0;
1105}
1106
43737e0a
LW
1107/* patch for vt3476 */
1108
1109static 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
43737e0a
LW
1119static 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
b3f6008f 1129 spec->gen.mixer_nid = 0x3f;
43737e0a
LW
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;
43737e0a
LW
1142 return 0;
1143}
1144
c577b8a1
JC
1145/*
1146 * patch entries
1147 */
90dd48a1 1148static const struct hda_codec_preset snd_hda_preset_via[] = {
3218c178
TI
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",
ddd304d8 1154 .patch = patch_vt1709},
3218c178 1155 { .id = 0x1106e711, .name = "VT1709 10-Ch",
ddd304d8 1156 .patch = patch_vt1709},
3218c178 1157 { .id = 0x1106e712, .name = "VT1709 10-Ch",
ddd304d8 1158 .patch = patch_vt1709},
3218c178 1159 { .id = 0x1106e713, .name = "VT1709 10-Ch",
ddd304d8 1160 .patch = patch_vt1709},
3218c178 1161 { .id = 0x1106e714, .name = "VT1709 6-Ch",
ddd304d8 1162 .patch = patch_vt1709},
3218c178 1163 { .id = 0x1106e715, .name = "VT1709 6-Ch",
ddd304d8 1164 .patch = patch_vt1709},
3218c178 1165 { .id = 0x1106e716, .name = "VT1709 6-Ch",
ddd304d8 1166 .patch = patch_vt1709},
3218c178 1167 { .id = 0x1106e717, .name = "VT1709 6-Ch",
ddd304d8 1168 .patch = patch_vt1709},
3218c178 1169 { .id = 0x1106e720, .name = "VT1708B 8-Ch",
ddd304d8 1170 .patch = patch_vt1708B},
3218c178 1171 { .id = 0x1106e721, .name = "VT1708B 8-Ch",
ddd304d8 1172 .patch = patch_vt1708B},
3218c178 1173 { .id = 0x1106e722, .name = "VT1708B 8-Ch",
ddd304d8 1174 .patch = patch_vt1708B},
3218c178 1175 { .id = 0x1106e723, .name = "VT1708B 8-Ch",
ddd304d8 1176 .patch = patch_vt1708B},
3218c178 1177 { .id = 0x1106e724, .name = "VT1708B 4-Ch",
ddd304d8 1178 .patch = patch_vt1708B},
3218c178 1179 { .id = 0x1106e725, .name = "VT1708B 4-Ch",
ddd304d8 1180 .patch = patch_vt1708B},
3218c178 1181 { .id = 0x1106e726, .name = "VT1708B 4-Ch",
ddd304d8 1182 .patch = patch_vt1708B},
3218c178 1183 { .id = 0x1106e727, .name = "VT1708B 4-Ch",
ddd304d8 1184 .patch = patch_vt1708B},
3218c178 1185 { .id = 0x11060397, .name = "VT1708S",
d949cac1 1186 .patch = patch_vt1708S},
3218c178 1187 { .id = 0x11061397, .name = "VT1708S",
d949cac1 1188 .patch = patch_vt1708S},
3218c178 1189 { .id = 0x11062397, .name = "VT1708S",
d949cac1 1190 .patch = patch_vt1708S},
3218c178 1191 { .id = 0x11063397, .name = "VT1708S",
d949cac1 1192 .patch = patch_vt1708S},
bc92df7f 1193 { .id = 0x11064397, .name = "VT1705",
d949cac1 1194 .patch = patch_vt1708S},
3218c178 1195 { .id = 0x11065397, .name = "VT1708S",
d949cac1 1196 .patch = patch_vt1708S},
3218c178 1197 { .id = 0x11066397, .name = "VT1708S",
d949cac1 1198 .patch = patch_vt1708S},
3218c178 1199 { .id = 0x11067397, .name = "VT1708S",
d949cac1 1200 .patch = patch_vt1708S},
3218c178 1201 { .id = 0x11060398, .name = "VT1702",
d949cac1 1202 .patch = patch_vt1702},
3218c178 1203 { .id = 0x11061398, .name = "VT1702",
d949cac1 1204 .patch = patch_vt1702},
3218c178 1205 { .id = 0x11062398, .name = "VT1702",
d949cac1 1206 .patch = patch_vt1702},
3218c178 1207 { .id = 0x11063398, .name = "VT1702",
d949cac1 1208 .patch = patch_vt1702},
3218c178 1209 { .id = 0x11064398, .name = "VT1702",
d949cac1 1210 .patch = patch_vt1702},
3218c178 1211 { .id = 0x11065398, .name = "VT1702",
d949cac1 1212 .patch = patch_vt1702},
3218c178 1213 { .id = 0x11066398, .name = "VT1702",
d949cac1 1214 .patch = patch_vt1702},
3218c178 1215 { .id = 0x11067398, .name = "VT1702",
d949cac1 1216 .patch = patch_vt1702},
eb7188ca
LW
1217 { .id = 0x11060428, .name = "VT1718S",
1218 .patch = patch_vt1718S},
1219 { .id = 0x11064428, .name = "VT1718S",
1220 .patch = patch_vt1718S},
bb3c6bfc
LW
1221 { .id = 0x11060441, .name = "VT2020",
1222 .patch = patch_vt1718S},
1223 { .id = 0x11064441, .name = "VT1828S",
1224 .patch = patch_vt1718S},
f3db423d
LW
1225 { .id = 0x11060433, .name = "VT1716S",
1226 .patch = patch_vt1716S},
1227 { .id = 0x1106a721, .name = "VT1716S",
1228 .patch = patch_vt1716S},
25eaba2f
LW
1229 { .id = 0x11060438, .name = "VT2002P", .patch = patch_vt2002P},
1230 { .id = 0x11064438, .name = "VT2002P", .patch = patch_vt2002P},
ab6734e7 1231 { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812},
36dd5c4a
LW
1232 { .id = 0x11060440, .name = "VT1818S",
1233 .patch = patch_vt1708S},
11890956
LW
1234 { .id = 0x11060446, .name = "VT1802",
1235 .patch = patch_vt2002P},
1236 { .id = 0x11068446, .name = "VT1802",
1237 .patch = patch_vt2002P},
43737e0a
LW
1238 { .id = 0x11064760, .name = "VT1705CF",
1239 .patch = patch_vt3476},
6121b84a
LW
1240 { .id = 0x11064761, .name = "VT1708SCE",
1241 .patch = patch_vt3476},
1242 { .id = 0x11064762, .name = "VT1808",
1243 .patch = patch_vt3476},
c577b8a1
JC
1244 {} /* terminator */
1245};
1289e9e8
TI
1246
1247MODULE_ALIAS("snd-hda-codec-id:1106*");
1248
d8a766a1 1249static struct hda_codec_driver via_driver = {
1289e9e8 1250 .preset = snd_hda_preset_via,
1289e9e8
TI
1251};
1252
1253MODULE_LICENSE("GPL");
1254MODULE_DESCRIPTION("VIA HD-audio codec");
1255
d8a766a1 1256module_hda_codec_driver(via_driver);