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