Merge branch 'xarray' of git://git.infradead.org/users/willy/linux-dax
[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>
be57bfff 55#include <sound/hda_codec.h>
c577b8a1 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 /* HP mode source */
f3db423d 94 unsigned int dmic_enabled;
1f2e99fe
LW
95 enum VIA_HDA_CODEC codec_type;
96
e9d010c2
TI
97 /* analog low-power control */
98 bool alc_mode;
99
1f2e99fe 100 /* work to check hp jack state */
187d333e 101 int hp_work_active;
e06e5a29 102 int vt1708_jack_detect;
1f2e99fe
LW
103};
104
0341ccd7 105static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
b3f6008f
TI
106static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
107 struct hda_codec *codec,
108 struct snd_pcm_substream *substream,
109 int action);
b3f6008f 110
225068ab
TI
111static const struct hda_codec_ops via_patch_ops; /* defined below */
112
b3f6008f 113static struct via_spec *via_new_spec(struct hda_codec *codec)
5b0cb1d8
JK
114{
115 struct via_spec *spec;
116
117 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
118 if (spec == NULL)
119 return NULL;
120
121 codec->spec = spec;
b3f6008f 122 snd_hda_gen_spec_init(&spec->gen);
0341ccd7
LW
123 spec->codec_type = get_codec_type(codec);
124 /* VT1708BCE & VT1708S are almost same */
125 if (spec->codec_type == VT1708BCE)
126 spec->codec_type = VT1708S;
13961170 127 spec->gen.indep_hp = 1;
05909d5c 128 spec->gen.keep_eapd_on = 1;
b3f6008f 129 spec->gen.pcm_playback_hook = via_playback_pcm_hook;
74f14b36 130 spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO;
967b1307 131 codec->power_save_node = 1;
688b12cc 132 spec->gen.power_down_unused = 1;
225068ab 133 codec->patch_ops = via_patch_ops;
5b0cb1d8
JK
134 return spec;
135}
136
744ff5f4 137static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
d7426329 138{
7639a06c 139 u32 vendor_id = codec->core.vendor_id;
d7426329
HW
140 u16 ven_id = vendor_id >> 16;
141 u16 dev_id = vendor_id & 0xffff;
142 enum VIA_HDA_CODEC codec_type;
143
144 /* get codec type */
145 if (ven_id != 0x1106)
146 codec_type = UNKNOWN;
147 else if (dev_id >= 0x1708 && dev_id <= 0x170b)
148 codec_type = VT1708;
149 else if (dev_id >= 0xe710 && dev_id <= 0xe713)
150 codec_type = VT1709_10CH;
151 else if (dev_id >= 0xe714 && dev_id <= 0xe717)
152 codec_type = VT1709_6CH;
518bf3ba 153 else if (dev_id >= 0xe720 && dev_id <= 0xe723) {
d7426329 154 codec_type = VT1708B_8CH;
518bf3ba
LW
155 if (snd_hda_param_read(codec, 0x16, AC_PAR_CONNLIST_LEN) == 0x7)
156 codec_type = VT1708BCE;
157 } else if (dev_id >= 0xe724 && dev_id <= 0xe727)
d7426329
HW
158 codec_type = VT1708B_4CH;
159 else if ((dev_id & 0xfff) == 0x397
160 && (dev_id >> 12) < 8)
161 codec_type = VT1708S;
162 else if ((dev_id & 0xfff) == 0x398
163 && (dev_id >> 12) < 8)
164 codec_type = VT1702;
eb7188ca
LW
165 else if ((dev_id & 0xfff) == 0x428
166 && (dev_id >> 12) < 8)
167 codec_type = VT1718S;
f3db423d
LW
168 else if (dev_id == 0x0433 || dev_id == 0xa721)
169 codec_type = VT1716S;
bb3c6bfc
LW
170 else if (dev_id == 0x0441 || dev_id == 0x4441)
171 codec_type = VT1718S;
25eaba2f
LW
172 else if (dev_id == 0x0438 || dev_id == 0x4438)
173 codec_type = VT2002P;
ab6734e7
LW
174 else if (dev_id == 0x0448)
175 codec_type = VT1812;
36dd5c4a
LW
176 else if (dev_id == 0x0440)
177 codec_type = VT1708S;
11890956
LW
178 else if ((dev_id & 0xfff) == 0x446)
179 codec_type = VT1802;
43737e0a
LW
180 else if (dev_id == 0x4760)
181 codec_type = VT1705CF;
6121b84a
LW
182 else if (dev_id == 0x4761 || dev_id == 0x4762)
183 codec_type = VT1808;
d7426329
HW
184 else
185 codec_type = UNKNOWN;
186 return codec_type;
187};
188
ada509ec
TI
189static void analog_low_current_mode(struct hda_codec *codec);
190static bool is_aa_path_mute(struct hda_codec *codec);
1f2e99fe 191
187d333e
TI
192#define hp_detect_with_aa(codec) \
193 (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
194 !is_aa_path_mute(codec))
195
b3f6008f 196static void vt1708_stop_hp_work(struct hda_codec *codec)
1f2e99fe 197{
b3f6008f
TI
198 struct via_spec *spec = codec->spec;
199 if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
1f2e99fe 200 return;
187d333e 201 if (spec->hp_work_active) {
b3f6008f 202 snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
7eaa9161 203 codec->jackpoll_interval = 0;
b3f6008f
TI
204 cancel_delayed_work_sync(&codec->jackpoll_work);
205 spec->hp_work_active = false;
187d333e 206 }
1f2e99fe
LW
207}
208
b3f6008f 209static void vt1708_update_hp_work(struct hda_codec *codec)
1f2e99fe 210{
b3f6008f
TI
211 struct via_spec *spec = codec->spec;
212 if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
1f2e99fe 213 return;
05dc0fc9 214 if (spec->vt1708_jack_detect) {
187d333e 215 if (!spec->hp_work_active) {
b3f6008f
TI
216 codec->jackpoll_interval = msecs_to_jiffies(100);
217 snd_hda_codec_write(codec, 0x1, 0, 0xf81, 0);
2f35c630 218 schedule_delayed_work(&codec->jackpoll_work, 0);
b3f6008f 219 spec->hp_work_active = true;
187d333e 220 }
b3f6008f
TI
221 } else if (!hp_detect_with_aa(codec))
222 vt1708_stop_hp_work(codec);
1f2e99fe 223}
f5271101 224
24088a58
TI
225static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
226 struct snd_ctl_elem_info *uinfo)
227{
dda415d4 228 return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
24088a58
TI
229}
230
231static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
232 struct snd_ctl_elem_value *ucontrol)
233{
234 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
735c75cf
TI
235 struct via_spec *spec = codec->spec;
236
237 ucontrol->value.enumerated.item[0] = spec->gen.power_down_unused;
24088a58
TI
238 return 0;
239}
240
241static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
243{
244 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
245 struct via_spec *spec = codec->spec;
688b12cc 246 bool val = !!ucontrol->value.enumerated.item[0];
24088a58 247
735c75cf 248 if (val == spec->gen.power_down_unused)
24088a58 249 return 0;
735c75cf 250 /* codec->power_save_node = val; */ /* widget PM seems yet broken */
688b12cc 251 spec->gen.power_down_unused = val;
e9d010c2 252 analog_low_current_mode(codec);
24088a58
TI
253 return 1;
254}
255
0e8f9862 256static const struct snd_kcontrol_new via_pin_power_ctl_enum = {
24088a58
TI
257 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
258 .name = "Dynamic Power-Control",
259 .info = via_pin_power_ctl_info,
260 .get = via_pin_power_ctl_get,
261 .put = via_pin_power_ctl_put,
262};
263
4738465c 264#ifdef CONFIG_SND_HDA_INPUT_BEEP
4738465c 265/* additional beep mixers; the actual parameters are overwritten at build */
0e8f9862 266static const struct snd_kcontrol_new via_beep_mixer[] = {
4738465c
TK
267 HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
268 HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
4738465c
TK
269};
270
0e8f9862
TI
271static int set_beep_amp(struct via_spec *spec, hda_nid_t nid,
272 int idx, int dir)
4738465c 273{
0e8f9862
TI
274 struct snd_kcontrol_new *knew;
275 unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
276 int i;
4738465c 277
0e8f9862
TI
278 spec->gen.beep_nid = nid;
279 for (i = 0; i < ARRAY_SIZE(via_beep_mixer); i++) {
280 knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
281 &via_beep_mixer[i]);
282 if (!knew)
283 return -ENOMEM;
284 knew->private_value = beep_amp;
4738465c
TK
285 }
286 return 0;
287}
288
0e8f9862 289static int auto_parse_beep(struct hda_codec *codec)
4738465c
TK
290{
291 struct via_spec *spec = codec->spec;
292 hda_nid_t nid;
293
294 for_each_hda_codec_node(nid, codec)
0e8f9862
TI
295 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP)
296 return set_beep_amp(spec, nid, 0, HDA_OUTPUT);
297 return 0;
4738465c
TK
298}
299#else
0e8f9862 300#define auto_parse_beep(codec) 0
4738465c 301#endif
24088a58 302
b3f6008f
TI
303/* check AA path's mute status */
304static bool is_aa_path_mute(struct hda_codec *codec)
0aa62aef 305{
cdc1784d 306 struct via_spec *spec = codec->spec;
b3f6008f 307 const struct hda_amp_list *p;
0186f4f4 308 int ch, v;
cdc1784d 309
0186f4f4
TI
310 p = spec->gen.loopback.amplist;
311 if (!p)
312 return true;
313 for (; p->nid; p++) {
b3f6008f
TI
314 for (ch = 0; ch < 2; ch++) {
315 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
316 p->idx);
317 if (!(v & HDA_AMP_MUTE) && v > 0)
318 return false;
319 }
3b607e3d 320 }
b3f6008f 321 return true;
3b607e3d
TI
322}
323
b3f6008f
TI
324/* enter/exit analog low-current mode */
325static void __analog_low_current_mode(struct hda_codec *codec, bool force)
3b607e3d
TI
326{
327 struct via_spec *spec = codec->spec;
b3f6008f
TI
328 bool enable;
329 unsigned int verb, parm;
3b607e3d 330
967b1307 331 if (!codec->power_save_node)
b3f6008f
TI
332 enable = false;
333 else
334 enable = is_aa_path_mute(codec) && !spec->gen.active_streams;
335 if (enable == spec->alc_mode && !force)
3b607e3d 336 return;
b3f6008f 337 spec->alc_mode = enable;
3b607e3d 338
b3f6008f
TI
339 /* decide low current mode's verb & parameter */
340 switch (spec->codec_type) {
341 case VT1708B_8CH:
342 case VT1708B_4CH:
343 verb = 0xf70;
344 parm = enable ? 0x02 : 0x00; /* 0x02: 2/3x, 0x00: 1x */
345 break;
346 case VT1708S:
347 case VT1718S:
348 case VT1716S:
349 verb = 0xf73;
350 parm = enable ? 0x51 : 0xe1; /* 0x51: 4/28x, 0xe1: 1x */
351 break;
352 case VT1702:
353 verb = 0xf73;
354 parm = enable ? 0x01 : 0x1d; /* 0x01: 4/40x, 0x1d: 1x */
355 break;
356 case VT2002P:
357 case VT1812:
358 case VT1802:
359 verb = 0xf93;
360 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
361 break;
362 case VT1705CF:
363 case VT1808:
364 verb = 0xf82;
365 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
366 break;
367 default:
368 return; /* other codecs are not supported */
f5271101
LW
369 }
370 /* send verb */
7639a06c 371 snd_hda_codec_write(codec, codec->core.afg, 0, verb, parm);
a86a88ea
TI
372}
373
b3f6008f
TI
374static void analog_low_current_mode(struct hda_codec *codec)
375{
376 return __analog_low_current_mode(codec, false);
377}
a86a88ea 378
b3f6008f
TI
379static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
380 struct hda_codec *codec,
381 struct snd_pcm_substream *substream,
382 int action)
a86a88ea 383{
b3f6008f
TI
384 analog_low_current_mode(codec);
385 vt1708_update_hp_work(codec);
a86a88ea
TI
386}
387
b3f6008f 388static void via_free(struct hda_codec *codec)
a86a88ea 389{
b3f6008f 390 vt1708_stop_hp_work(codec);
a8dca460 391 snd_hda_gen_free(codec);
a86a88ea
TI
392}
393
b3f6008f
TI
394#ifdef CONFIG_PM
395static int via_suspend(struct hda_codec *codec)
a86a88ea
TI
396{
397 struct via_spec *spec = codec->spec;
b3f6008f 398 vt1708_stop_hp_work(codec);
d7a99cce 399
2c38d990
TI
400 /* Fix pop noise on headphones */
401 if (spec->codec_type == VT1802)
402 snd_hda_shutup_pins(codec);
d7a99cce 403
a86a88ea
TI
404 return 0;
405}
6b6d0007
TI
406
407static int via_resume(struct hda_codec *codec)
408{
409 /* some delay here to make jack detection working (bko#98921) */
410 msleep(10);
411 codec->patch_ops.init(codec);
412 regcache_sync(codec->core.regmap);
413 return 0;
414}
b3f6008f 415#endif
a86a88ea 416
b3f6008f
TI
417#ifdef CONFIG_PM
418static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
a86a88ea
TI
419{
420 struct via_spec *spec = codec->spec;
b3f6008f
TI
421 analog_low_current_mode(codec);
422 vt1708_update_hp_work(codec);
423 return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid);
424}
425#endif
a86a88ea 426
b3f6008f
TI
427/*
428 */
a86a88ea 429
b3f6008f 430static int via_init(struct hda_codec *codec);
a86a88ea 431
b3f6008f 432static const struct hda_codec_ops via_patch_ops = {
0e8f9862 433 .build_controls = snd_hda_gen_build_controls,
b3f6008f
TI
434 .build_pcms = snd_hda_gen_build_pcms,
435 .init = via_init,
436 .free = via_free,
437 .unsol_event = snd_hda_jack_unsol_event,
438#ifdef CONFIG_PM
439 .suspend = via_suspend,
6b6d0007 440 .resume = via_resume,
b3f6008f
TI
441 .check_power_status = via_check_power_status,
442#endif
443};
a86a88ea 444
c577b8a1 445
b3f6008f
TI
446static const struct hda_verb vt1708_init_verbs[] = {
447 /* power down jack detect function */
448 {0x1, 0xf81, 0x1},
449 { }
450};
76d9b0dd
HW
451static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
452{
453 unsigned int def_conf;
454 unsigned char seqassoc;
455
2f334f92 456 def_conf = snd_hda_codec_get_pincfg(codec, nid);
76d9b0dd
HW
457 seqassoc = (unsigned char) get_defcfg_association(def_conf);
458 seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
82ef9e45
LW
459 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
460 && (seqassoc == 0xf0 || seqassoc == 0xff)) {
461 def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
462 snd_hda_codec_set_pincfg(codec, nid, def_conf);
76d9b0dd
HW
463 }
464
465 return;
466}
467
e06e5a29 468static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
1f2e99fe
LW
469 struct snd_ctl_elem_value *ucontrol)
470{
471 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
472 struct via_spec *spec = codec->spec;
473
474 if (spec->codec_type != VT1708)
475 return 0;
e06e5a29 476 ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
1f2e99fe
LW
477 return 0;
478}
479
e06e5a29 480static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
1f2e99fe
LW
481 struct snd_ctl_elem_value *ucontrol)
482{
483 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
484 struct via_spec *spec = codec->spec;
187d333e 485 int val;
1f2e99fe
LW
486
487 if (spec->codec_type != VT1708)
488 return 0;
187d333e
TI
489 val = !!ucontrol->value.integer.value[0];
490 if (spec->vt1708_jack_detect == val)
491 return 0;
492 spec->vt1708_jack_detect = val;
b3f6008f 493 vt1708_update_hp_work(codec);
187d333e 494 return 1;
1f2e99fe
LW
495}
496
0e8f9862 497static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
e06e5a29
TI
498 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
499 .name = "Jack Detect",
500 .count = 1,
501 .info = snd_ctl_boolean_mono_info,
502 .get = vt1708_jack_detect_get,
503 .put = vt1708_jack_detect_put,
1f2e99fe
LW
504};
505
4abdbd1c
TI
506static const struct badness_table via_main_out_badness = {
507 .no_primary_dac = 0x10000,
508 .no_dac = 0x4000,
509 .shared_primary = 0x10000,
510 .shared_surr = 0x20,
511 .shared_clfe = 0x20,
512 .shared_surr_main = 0x20,
513};
514static const struct badness_table via_extra_out_badness = {
515 .no_primary_dac = 0x4000,
516 .no_dac = 0x4000,
517 .shared_primary = 0x12,
518 .shared_surr = 0x20,
519 .shared_clfe = 0x20,
520 .shared_surr_main = 0x10,
521};
522
b3f6008f
TI
523static int via_parse_auto_config(struct hda_codec *codec)
524{
525 struct via_spec *spec = codec->spec;
526 int err;
527
4abdbd1c
TI
528 spec->gen.main_out_badness = &via_main_out_badness;
529 spec->gen.extra_out_badness = &via_extra_out_badness;
530
b3f6008f
TI
531 err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
532 if (err < 0)
533 return err;
534
535 err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
536 if (err < 0)
537 return err;
538
0e8f9862
TI
539 err = auto_parse_beep(codec);
540 if (err < 0)
541 return err;
542
543 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &via_pin_power_ctl_enum))
544 return -ENOMEM;
545
688b12cc 546 /* disable widget PM at start for compatibility */
967b1307 547 codec->power_save_node = 0;
688b12cc 548 spec->gen.power_down_unused = 0;
b3f6008f
TI
549 return 0;
550}
551
5d41762a
TI
552static int via_init(struct hda_codec *codec)
553{
e9d010c2 554 /* init power states */
e9d010c2
TI
555 __analog_low_current_mode(codec, true);
556
b3f6008f 557 snd_hda_gen_init(codec);
4a918ffe 558
b3f6008f 559 vt1708_update_hp_work(codec);
25eaba2f 560
c577b8a1
JC
561 return 0;
562}
563
f672f65a
DH
564static int vt1708_build_controls(struct hda_codec *codec)
565{
566 /* In order not to create "Phantom Jack" controls,
567 temporary enable jackpoll */
568 int err;
569 int old_interval = codec->jackpoll_interval;
570 codec->jackpoll_interval = msecs_to_jiffies(100);
0e8f9862 571 err = snd_hda_gen_build_controls(codec);
f672f65a
DH
572 codec->jackpoll_interval = old_interval;
573 return err;
574}
575
b3f6008f 576static int vt1708_build_pcms(struct hda_codec *codec)
337b9d02
TI
577{
578 struct via_spec *spec = codec->spec;
b3f6008f
TI
579 int i, err;
580
581 err = snd_hda_gen_build_pcms(codec);
7639a06c 582 if (err < 0 || codec->core.vendor_id != 0x11061708)
b3f6008f
TI
583 return err;
584
585 /* We got noisy outputs on the right channel on VT1708 when
586 * 24bit samples are used. Until any workaround is found,
587 * disable the 24bit format, so far.
588 */
bbbc7e85
TI
589 for (i = 0; i < ARRAY_SIZE(spec->gen.pcm_rec); i++) {
590 struct hda_pcm *info = spec->gen.pcm_rec[i];
591 if (!info)
592 continue;
b3f6008f
TI
593 if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
594 info->pcm_type != HDA_PCM_TYPE_AUDIO)
595 continue;
596 info->stream[SNDRV_PCM_STREAM_PLAYBACK].formats =
597 SNDRV_PCM_FMTBIT_S16_LE;
337b9d02 598 }
b3f6008f 599
1c55d521 600 return 0;
337b9d02
TI
601}
602
c577b8a1
JC
603static int patch_vt1708(struct hda_codec *codec)
604{
605 struct via_spec *spec;
606 int err;
607
608 /* create a codec specific record */
5b0cb1d8 609 spec = via_new_spec(codec);
c577b8a1
JC
610 if (spec == NULL)
611 return -ENOMEM;
612
225068ab
TI
613 /* override some patch_ops */
614 codec->patch_ops.build_controls = vt1708_build_controls;
615 codec->patch_ops.build_pcms = vt1708_build_pcms;
b3f6008f
TI
616 spec->gen.mixer_nid = 0x17;
617
618 /* set jackpoll_interval while parsing the codec */
619 codec->jackpoll_interval = msecs_to_jiffies(100);
620 spec->vt1708_jack_detect = 1;
621
622 /* don't support the input jack switching due to lack of unsol event */
623 /* (it may work with polling, though, but it needs testing) */
624 spec->gen.suppress_auto_mic = 1;
eb33ccf7
TI
625 /* Some machines show the broken speaker mute */
626 spec->gen.auto_mute_via_amp = 1;
620e2b28 627
12daef65
TI
628 /* Add HP and CD pin config connect bit re-config action */
629 vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
630 vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
631
f8bfc628
TI
632 err = snd_hda_add_verbs(codec, vt1708_init_verbs);
633 if (err < 0)
634 goto error;
635
c577b8a1 636 /* automatic parse from the BIOS config */
12daef65 637 err = via_parse_auto_config(codec);
fcbdcc1a
TI
638 if (err < 0)
639 goto error;
c577b8a1 640
12daef65 641 /* add jack detect on/off control */
0e8f9862
TI
642 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1708_jack_detect_ctl)) {
643 err = -ENOMEM;
644 goto error;
645 }
c577b8a1 646
b3f6008f
TI
647 /* clear jackpoll_interval again; it's set dynamically */
648 codec->jackpoll_interval = 0;
c577b8a1 649
c577b8a1 650 return 0;
fcbdcc1a
TI
651
652 error:
653 via_free(codec);
654 return err;
c577b8a1
JC
655}
656
ddd304d8 657static int patch_vt1709(struct hda_codec *codec)
c577b8a1
JC
658{
659 struct via_spec *spec;
660 int err;
661
662 /* create a codec specific record */
5b0cb1d8 663 spec = via_new_spec(codec);
c577b8a1
JC
664 if (spec == NULL)
665 return -ENOMEM;
666
b3f6008f 667 spec->gen.mixer_nid = 0x18;
620e2b28 668
12daef65 669 err = via_parse_auto_config(codec);
fcbdcc1a
TI
670 if (err < 0)
671 goto error;
c577b8a1 672
f7278fd0 673 return 0;
fcbdcc1a
TI
674
675 error:
676 via_free(codec);
677 return err;
f7278fd0
JC
678}
679
518bf3ba 680static int patch_vt1708S(struct hda_codec *codec);
ddd304d8 681static int patch_vt1708B(struct hda_codec *codec)
f7278fd0
JC
682{
683 struct via_spec *spec;
684 int err;
685
518bf3ba
LW
686 if (get_codec_type(codec) == VT1708BCE)
687 return patch_vt1708S(codec);
ddd304d8 688
f7278fd0 689 /* create a codec specific record */
5b0cb1d8 690 spec = via_new_spec(codec);
f7278fd0
JC
691 if (spec == NULL)
692 return -ENOMEM;
693
b3f6008f 694 spec->gen.mixer_nid = 0x16;
620e2b28 695
f7278fd0 696 /* automatic parse from the BIOS config */
12daef65 697 err = via_parse_auto_config(codec);
fcbdcc1a
TI
698 if (err < 0)
699 goto error;
f7278fd0 700
f7278fd0 701 return 0;
fcbdcc1a
TI
702
703 error:
704 via_free(codec);
705 return err;
f7278fd0
JC
706}
707
d949cac1 708/* Patch for VT1708S */
096a8854 709static const struct hda_verb vt1708S_init_verbs[] = {
d7426329
HW
710 /* Enable Mic Boost Volume backdoor */
711 {0x1, 0xf98, 0x1},
bc7e7e5c
LW
712 /* don't bybass mixer */
713 {0x1, 0xf88, 0xc0},
d949cac1
HW
714 { }
715};
716
6369bcfc
LW
717static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
718 int offset, int num_steps, int step_size)
719{
d045c5dc
TI
720 snd_hda_override_wcaps(codec, pin,
721 get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
6369bcfc
LW
722 snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
723 (offset << AC_AMPCAP_OFFSET_SHIFT) |
724 (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
725 (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
726 (0 << AC_AMPCAP_MUTE_SHIFT));
727}
728
d949cac1
HW
729static int patch_vt1708S(struct hda_codec *codec)
730{
731 struct via_spec *spec;
732 int err;
733
734 /* create a codec specific record */
5b0cb1d8 735 spec = via_new_spec(codec);
d949cac1
HW
736 if (spec == NULL)
737 return -ENOMEM;
738
b3f6008f 739 spec->gen.mixer_nid = 0x16;
d7a99cce
TI
740 override_mic_boost(codec, 0x1a, 0, 3, 40);
741 override_mic_boost(codec, 0x1e, 0, 3, 40);
620e2b28 742
518bf3ba 743 /* correct names for VT1708BCE */
ded255be
TI
744 if (get_codec_type(codec) == VT1708BCE)
745 snd_hda_codec_set_name(codec, "VT1708BCE");
bc92df7f 746 /* correct names for VT1705 */
ded255be
TI
747 if (codec->core.vendor_id == 0x11064397)
748 snd_hda_codec_set_name(codec, "VT1705");
b3f6008f 749
f8bfc628
TI
750 err = snd_hda_add_verbs(codec, vt1708S_init_verbs);
751 if (err < 0)
752 goto error;
753
b3f6008f
TI
754 /* automatic parse from the BIOS config */
755 err = via_parse_auto_config(codec);
fcbdcc1a
TI
756 if (err < 0)
757 goto error;
b3f6008f 758
d949cac1 759 return 0;
fcbdcc1a
TI
760
761 error:
762 via_free(codec);
763 return err;
d949cac1
HW
764}
765
766/* Patch for VT1702 */
767
096a8854 768static const struct hda_verb vt1702_init_verbs[] = {
bc7e7e5c
LW
769 /* mixer enable */
770 {0x1, 0xF88, 0x3},
771 /* GPIO 0~2 */
772 {0x1, 0xF82, 0x3F},
d949cac1
HW
773 { }
774};
775
d949cac1
HW
776static int patch_vt1702(struct hda_codec *codec)
777{
778 struct via_spec *spec;
779 int err;
d949cac1
HW
780
781 /* create a codec specific record */
5b0cb1d8 782 spec = via_new_spec(codec);
d949cac1
HW
783 if (spec == NULL)
784 return -ENOMEM;
785
b3f6008f 786 spec->gen.mixer_nid = 0x1a;
620e2b28 787
12daef65
TI
788 /* limit AA path volume to 0 dB */
789 snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
790 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
791 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
792 (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
793 (1 << AC_AMPCAP_MUTE_SHIFT));
794
f8bfc628
TI
795 err = snd_hda_add_verbs(codec, vt1702_init_verbs);
796 if (err < 0)
797 goto error;
798
d949cac1 799 /* automatic parse from the BIOS config */
12daef65 800 err = via_parse_auto_config(codec);
fcbdcc1a
TI
801 if (err < 0)
802 goto error;
d949cac1 803
d949cac1 804 return 0;
fcbdcc1a
TI
805
806 error:
807 via_free(codec);
808 return err;
d949cac1
HW
809}
810
eb7188ca
LW
811/* Patch for VT1718S */
812
096a8854 813static const struct hda_verb vt1718S_init_verbs[] = {
4ab2d53a
LW
814 /* Enable MW0 adjust Gain 5 */
815 {0x1, 0xfb2, 0x10},
eb7188ca
LW
816 /* Enable Boost Volume backdoor */
817 {0x1, 0xf88, 0x8},
5d41762a 818
eb7188ca
LW
819 { }
820};
821
30b45033
TI
822/* Add a connection to the primary DAC from AA-mixer for some codecs
823 * This isn't listed from the raw info, but the chip has a secret connection.
824 */
825static int add_secret_dac_path(struct hda_codec *codec)
826{
827 struct via_spec *spec = codec->spec;
828 int i, nums;
829 hda_nid_t conn[8];
830 hda_nid_t nid;
831
b3f6008f 832 if (!spec->gen.mixer_nid)
30b45033 833 return 0;
b3f6008f 834 nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
30b45033
TI
835 ARRAY_SIZE(conn) - 1);
836 for (i = 0; i < nums; i++) {
837 if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
838 return 0;
839 }
840
841 /* find the primary DAC and add to the connection list */
7639a06c 842 for_each_hda_codec_node(nid, codec) {
30b45033
TI
843 unsigned int caps = get_wcaps(codec, nid);
844 if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
845 !(caps & AC_WCAP_DIGITAL)) {
846 conn[nums++] = nid;
847 return snd_hda_override_conn_list(codec,
b3f6008f 848 spec->gen.mixer_nid,
30b45033
TI
849 nums, conn);
850 }
851 }
852 return 0;
853}
854
855
eb7188ca
LW
856static int patch_vt1718S(struct hda_codec *codec)
857{
858 struct via_spec *spec;
859 int err;
860
861 /* create a codec specific record */
5b0cb1d8 862 spec = via_new_spec(codec);
eb7188ca
LW
863 if (spec == NULL)
864 return -ENOMEM;
865
b3f6008f 866 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
867 override_mic_boost(codec, 0x2b, 0, 3, 40);
868 override_mic_boost(codec, 0x29, 0, 3, 40);
30b45033 869 add_secret_dac_path(codec);
620e2b28 870
f8bfc628
TI
871 err = snd_hda_add_verbs(codec, vt1718S_init_verbs);
872 if (err < 0)
873 goto error;
874
eb7188ca 875 /* automatic parse from the BIOS config */
12daef65 876 err = via_parse_auto_config(codec);
fcbdcc1a
TI
877 if (err < 0)
878 goto error;
eb7188ca 879
eb7188ca 880 return 0;
fcbdcc1a
TI
881
882 error:
883 via_free(codec);
884 return err;
eb7188ca 885}
f3db423d
LW
886
887/* Patch for VT1716S */
888
889static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
890 struct snd_ctl_elem_info *uinfo)
891{
892 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
893 uinfo->count = 1;
894 uinfo->value.integer.min = 0;
895 uinfo->value.integer.max = 1;
896 return 0;
897}
898
899static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
900 struct snd_ctl_elem_value *ucontrol)
901{
902 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
903 int index = 0;
904
905 index = snd_hda_codec_read(codec, 0x26, 0,
906 AC_VERB_GET_CONNECT_SEL, 0);
907 if (index != -1)
908 *ucontrol->value.integer.value = index;
909
910 return 0;
911}
912
913static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
914 struct snd_ctl_elem_value *ucontrol)
915{
916 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
917 struct via_spec *spec = codec->spec;
918 int index = *ucontrol->value.integer.value;
919
920 snd_hda_codec_write(codec, 0x26, 0,
921 AC_VERB_SET_CONNECT_SEL, index);
922 spec->dmic_enabled = index;
f3db423d
LW
923 return 1;
924}
925
0e8f9862
TI
926static const struct snd_kcontrol_new vt1716s_dmic_mixer_vol =
927 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT);
928static const struct snd_kcontrol_new vt1716s_dmic_mixer_sw = {
f3db423d
LW
929 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
930 .name = "Digital Mic Capture Switch",
5b0cb1d8 931 .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
f3db423d
LW
932 .count = 1,
933 .info = vt1716s_dmic_info,
934 .get = vt1716s_dmic_get,
935 .put = vt1716s_dmic_put,
f3db423d
LW
936};
937
938
939/* mono-out mixer elements */
0e8f9862
TI
940static const struct snd_kcontrol_new vt1716S_mono_out_mixer =
941 HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT);
f3db423d 942
096a8854 943static const struct hda_verb vt1716S_init_verbs[] = {
f3db423d
LW
944 /* Enable Boost Volume backdoor */
945 {0x1, 0xf8a, 0x80},
946 /* don't bybass mixer */
947 {0x1, 0xf88, 0xc0},
948 /* Enable mono output */
949 {0x1, 0xf90, 0x08},
950 { }
951};
952
f3db423d
LW
953static int patch_vt1716S(struct hda_codec *codec)
954{
955 struct via_spec *spec;
956 int err;
957
958 /* create a codec specific record */
5b0cb1d8 959 spec = via_new_spec(codec);
f3db423d
LW
960 if (spec == NULL)
961 return -ENOMEM;
962
b3f6008f 963 spec->gen.mixer_nid = 0x16;
d7a99cce
TI
964 override_mic_boost(codec, 0x1a, 0, 3, 40);
965 override_mic_boost(codec, 0x1e, 0, 3, 40);
620e2b28 966
f8bfc628
TI
967 err = snd_hda_add_verbs(codec, vt1716S_init_verbs);
968 if (err < 0)
969 goto error;
970
f3db423d 971 /* automatic parse from the BIOS config */
12daef65 972 err = via_parse_auto_config(codec);
fcbdcc1a
TI
973 if (err < 0)
974 goto error;
f3db423d 975
0e8f9862
TI
976 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_vol) ||
977 !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_sw) ||
978 !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716S_mono_out_mixer)) {
979 err = -ENOMEM;
980 goto error;
981 }
f3db423d 982
f3db423d 983 return 0;
fcbdcc1a
TI
984
985 error:
986 via_free(codec);
987 return err;
f3db423d 988}
25eaba2f
LW
989
990/* for vt2002P */
991
096a8854 992static const struct hda_verb vt2002P_init_verbs[] = {
eadb9a80
LW
993 /* Class-D speaker related verbs */
994 {0x1, 0xfe0, 0x4},
995 {0x1, 0xfe9, 0x80},
996 {0x1, 0xfe2, 0x22},
25eaba2f
LW
997 /* Enable Boost Volume backdoor */
998 {0x1, 0xfb9, 0x24},
25eaba2f
LW
999 /* Enable AOW0 to MW9 */
1000 {0x1, 0xfb8, 0x88},
1001 { }
1002};
4a918ffe 1003
096a8854 1004static const struct hda_verb vt1802_init_verbs[] = {
11890956
LW
1005 /* Enable Boost Volume backdoor */
1006 {0x1, 0xfb9, 0x24},
11890956
LW
1007 /* Enable AOW0 to MW9 */
1008 {0x1, 0xfb8, 0x88},
1009 { }
1010};
25eaba2f 1011
4b527b65
DH
1012/*
1013 * pin fix-up
1014 */
1015enum {
1016 VIA_FIXUP_INTMIC_BOOST,
d5266125 1017 VIA_FIXUP_ASUS_G75,
4b527b65
DH
1018};
1019
1020static void via_fixup_intmic_boost(struct hda_codec *codec,
1021 const struct hda_fixup *fix, int action)
1022{
1023 if (action == HDA_FIXUP_ACT_PRE_PROBE)
1024 override_mic_boost(codec, 0x30, 0, 2, 40);
1025}
1026
1027static const struct hda_fixup via_fixups[] = {
1028 [VIA_FIXUP_INTMIC_BOOST] = {
1029 .type = HDA_FIXUP_FUNC,
1030 .v.func = via_fixup_intmic_boost,
1031 },
d5266125
TI
1032 [VIA_FIXUP_ASUS_G75] = {
1033 .type = HDA_FIXUP_PINS,
1034 .v.pins = (const struct hda_pintbl[]) {
1035 /* set 0x24 and 0x33 as speakers */
1036 { 0x24, 0x991301f0 },
1037 { 0x33, 0x991301f1 }, /* subwoofer */
1038 { }
1039 }
1040 },
4b527b65
DH
1041};
1042
1043static const struct snd_pci_quirk vt2002p_fixups[] = {
d5266125 1044 SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
4b527b65
DH
1045 SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
1046 {}
1047};
1048
ef4da458
TI
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 hda_nid_t conn_24[] = { 0x14, 0x1c };
1055 static 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
25eaba2f
LW
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 */
5b0cb1d8 1068 spec = via_new_spec(codec);
25eaba2f
LW
1069 if (spec == NULL)
1070 return -ENOMEM;
1071
b3f6008f 1072 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1073 override_mic_boost(codec, 0x2b, 0, 3, 40);
1074 override_mic_boost(codec, 0x29, 0, 3, 40);
ef4da458
TI
1075 if (spec->codec_type == VT1802)
1076 fix_vt1802_connections(codec);
30b45033 1077 add_secret_dac_path(codec);
620e2b28 1078
4b527b65
DH
1079 snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
1080 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1081
f8bfc628
TI
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
25eaba2f 1089 /* automatic parse from the BIOS config */
12daef65 1090 err = via_parse_auto_config(codec);
fcbdcc1a
TI
1091 if (err < 0)
1092 goto error;
25eaba2f 1093
25eaba2f 1094 return 0;
fcbdcc1a
TI
1095
1096 error:
1097 via_free(codec);
1098 return err;
25eaba2f 1099}
ab6734e7
LW
1100
1101/* for vt1812 */
1102
096a8854 1103static const struct hda_verb vt1812_init_verbs[] = {
ab6734e7
LW
1104 /* Enable Boost Volume backdoor */
1105 {0x1, 0xfb9, 0x24},
ab6734e7
LW
1106 /* Enable AOW0 to MW9 */
1107 {0x1, 0xfb8, 0xa8},
1108 { }
1109};
1110
ab6734e7
LW
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 */
5b0cb1d8 1118 spec = via_new_spec(codec);
ab6734e7
LW
1119 if (spec == NULL)
1120 return -ENOMEM;
1121
b3f6008f 1122 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1123 override_mic_boost(codec, 0x2b, 0, 3, 40);
1124 override_mic_boost(codec, 0x29, 0, 3, 40);
30b45033 1125 add_secret_dac_path(codec);
620e2b28 1126
f8bfc628
TI
1127 err = snd_hda_add_verbs(codec, vt1812_init_verbs);
1128 if (err < 0)
1129 goto error;
1130
ab6734e7 1131 /* automatic parse from the BIOS config */
12daef65 1132 err = via_parse_auto_config(codec);
fcbdcc1a
TI
1133 if (err < 0)
1134 goto error;
ab6734e7 1135
ab6734e7 1136 return 0;
fcbdcc1a
TI
1137
1138 error:
1139 via_free(codec);
1140 return err;
ab6734e7
LW
1141}
1142
43737e0a
LW
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
43737e0a
LW
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
b3f6008f 1165 spec->gen.mixer_nid = 0x3f;
43737e0a
LW
1166 add_secret_dac_path(codec);
1167
f8bfc628
TI
1168 err = snd_hda_add_verbs(codec, vt3476_init_verbs);
1169 if (err < 0)
1170 goto error;
1171
43737e0a
LW
1172 /* automatic parse from the BIOS config */
1173 err = via_parse_auto_config(codec);
fcbdcc1a
TI
1174 if (err < 0)
1175 goto error;
43737e0a 1176
43737e0a 1177 return 0;
fcbdcc1a
TI
1178
1179 error:
1180 via_free(codec);
1181 return err;
43737e0a
LW
1182}
1183
c577b8a1
JC
1184/*
1185 * patch entries
1186 */
b9a94a9c
TI
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),
c577b8a1
JC
1239 {} /* terminator */
1240};
b9a94a9c 1241MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_via);
1289e9e8 1242
d8a766a1 1243static struct hda_codec_driver via_driver = {
b9a94a9c 1244 .id = snd_hda_id_via,
1289e9e8
TI
1245};
1246
1247MODULE_LICENSE("GPL");
1248MODULE_DESCRIPTION("VIA HD-audio codec");
1249
d8a766a1 1250module_hda_codec_driver(via_driver);