drivers: power: report battery voltage in AOSP compatible format
[GitHub/mt8127/android_kernel_alcatel_ttab.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;
24088a58 102 unsigned int no_pin_power_ctl;
1f2e99fe
LW
103 enum VIA_HDA_CODEC codec_type;
104
e9d010c2
TI
105 /* analog low-power control */
106 bool alc_mode;
107
1f2e99fe 108 /* work to check hp jack state */
187d333e 109 int hp_work_active;
e06e5a29 110 int vt1708_jack_detect;
3e95b9ab
LW
111
112 void (*set_widgets_power_state)(struct hda_codec *codec);
43737e0a 113 unsigned int dac_stream_tag[4];
1f2e99fe
LW
114};
115
0341ccd7 116static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
b3f6008f
TI
117static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
118 struct hda_codec *codec,
119 struct snd_pcm_substream *substream,
120 int action);
121static void via_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl);
122
123static struct via_spec *via_new_spec(struct hda_codec *codec)
5b0cb1d8
JK
124{
125 struct via_spec *spec;
126
127 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
128 if (spec == NULL)
129 return NULL;
130
131 codec->spec = spec;
b3f6008f 132 snd_hda_gen_spec_init(&spec->gen);
0341ccd7
LW
133 spec->codec_type = get_codec_type(codec);
134 /* VT1708BCE & VT1708S are almost same */
135 if (spec->codec_type == VT1708BCE)
136 spec->codec_type = VT1708S;
b3f6008f 137 spec->no_pin_power_ctl = 1;
13961170 138 spec->gen.indep_hp = 1;
05909d5c 139 spec->gen.keep_eapd_on = 1;
b3f6008f 140 spec->gen.pcm_playback_hook = via_playback_pcm_hook;
5b0cb1d8
JK
141 return spec;
142}
143
744ff5f4 144static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec)
d7426329 145{
744ff5f4 146 u32 vendor_id = codec->vendor_id;
d7426329
HW
147 u16 ven_id = vendor_id >> 16;
148 u16 dev_id = vendor_id & 0xffff;
149 enum VIA_HDA_CODEC codec_type;
150
151 /* get codec type */
152 if (ven_id != 0x1106)
153 codec_type = UNKNOWN;
154 else if (dev_id >= 0x1708 && dev_id <= 0x170b)
155 codec_type = VT1708;
156 else if (dev_id >= 0xe710 && dev_id <= 0xe713)
157 codec_type = VT1709_10CH;
158 else if (dev_id >= 0xe714 && dev_id <= 0xe717)
159 codec_type = VT1709_6CH;
518bf3ba 160 else if (dev_id >= 0xe720 && dev_id <= 0xe723) {
d7426329 161 codec_type = VT1708B_8CH;
518bf3ba
LW
162 if (snd_hda_param_read(codec, 0x16, AC_PAR_CONNLIST_LEN) == 0x7)
163 codec_type = VT1708BCE;
164 } else if (dev_id >= 0xe724 && dev_id <= 0xe727)
d7426329
HW
165 codec_type = VT1708B_4CH;
166 else if ((dev_id & 0xfff) == 0x397
167 && (dev_id >> 12) < 8)
168 codec_type = VT1708S;
169 else if ((dev_id & 0xfff) == 0x398
170 && (dev_id >> 12) < 8)
171 codec_type = VT1702;
eb7188ca
LW
172 else if ((dev_id & 0xfff) == 0x428
173 && (dev_id >> 12) < 8)
174 codec_type = VT1718S;
f3db423d
LW
175 else if (dev_id == 0x0433 || dev_id == 0xa721)
176 codec_type = VT1716S;
bb3c6bfc
LW
177 else if (dev_id == 0x0441 || dev_id == 0x4441)
178 codec_type = VT1718S;
25eaba2f
LW
179 else if (dev_id == 0x0438 || dev_id == 0x4438)
180 codec_type = VT2002P;
ab6734e7
LW
181 else if (dev_id == 0x0448)
182 codec_type = VT1812;
36dd5c4a
LW
183 else if (dev_id == 0x0440)
184 codec_type = VT1708S;
11890956
LW
185 else if ((dev_id & 0xfff) == 0x446)
186 codec_type = VT1802;
43737e0a
LW
187 else if (dev_id == 0x4760)
188 codec_type = VT1705CF;
6121b84a
LW
189 else if (dev_id == 0x4761 || dev_id == 0x4762)
190 codec_type = VT1808;
d7426329
HW
191 else
192 codec_type = UNKNOWN;
193 return codec_type;
194};
195
ada509ec
TI
196static void analog_low_current_mode(struct hda_codec *codec);
197static bool is_aa_path_mute(struct hda_codec *codec);
1f2e99fe 198
187d333e
TI
199#define hp_detect_with_aa(codec) \
200 (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
201 !is_aa_path_mute(codec))
202
b3f6008f 203static void vt1708_stop_hp_work(struct hda_codec *codec)
1f2e99fe 204{
b3f6008f
TI
205 struct via_spec *spec = codec->spec;
206 if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
1f2e99fe 207 return;
187d333e 208 if (spec->hp_work_active) {
b3f6008f
TI
209 snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
210 cancel_delayed_work_sync(&codec->jackpoll_work);
211 spec->hp_work_active = false;
212 codec->jackpoll_interval = 0;
187d333e 213 }
1f2e99fe
LW
214}
215
b3f6008f 216static void vt1708_update_hp_work(struct hda_codec *codec)
1f2e99fe 217{
b3f6008f
TI
218 struct via_spec *spec = codec->spec;
219 if (spec->codec_type != VT1708 || !spec->gen.autocfg.hp_outs)
1f2e99fe 220 return;
05dc0fc9 221 if (spec->vt1708_jack_detect) {
187d333e 222 if (!spec->hp_work_active) {
b3f6008f
TI
223 codec->jackpoll_interval = msecs_to_jiffies(100);
224 snd_hda_codec_write(codec, 0x1, 0, 0xf81, 0);
225 queue_delayed_work(codec->bus->workq,
226 &codec->jackpoll_work, 0);
227 spec->hp_work_active = true;
187d333e 228 }
b3f6008f
TI
229 } else if (!hp_detect_with_aa(codec))
230 vt1708_stop_hp_work(codec);
1f2e99fe 231}
f5271101 232
3e95b9ab
LW
233static void set_widgets_power_state(struct hda_codec *codec)
234{
087c2e3b
TI
235#if 0 /* FIXME: the assumed connections don't match always with the
236 * actual routes by the generic parser, so better to disable
237 * the control for safety.
238 */
3e95b9ab
LW
239 struct via_spec *spec = codec->spec;
240 if (spec->set_widgets_power_state)
241 spec->set_widgets_power_state(codec);
087c2e3b 242#endif
3e95b9ab 243}
25eaba2f 244
054d867e
TI
245static void update_power_state(struct hda_codec *codec, hda_nid_t nid,
246 unsigned int parm)
247{
9040d102 248 if (snd_hda_check_power_state(codec, nid, parm))
054d867e
TI
249 return;
250 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
251}
252
43737e0a
LW
253static void update_conv_power_state(struct hda_codec *codec, hda_nid_t nid,
254 unsigned int parm, unsigned int index)
255{
256 struct via_spec *spec = codec->spec;
257 unsigned int format;
9040d102
TI
258
259 if (snd_hda_check_power_state(codec, nid, parm))
43737e0a
LW
260 return;
261 format = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
262 if (format && (spec->dac_stream_tag[index] != format))
263 spec->dac_stream_tag[index] = format;
264
265 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
266 if (parm == AC_PWRST_D0) {
267 format = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0);
268 if (!format && (spec->dac_stream_tag[index] != format))
269 snd_hda_codec_write(codec, nid, 0,
270 AC_VERB_SET_CHANNEL_STREAMID,
271 spec->dac_stream_tag[index]);
272 }
273}
274
b3f6008f
TI
275static bool smart51_enabled(struct hda_codec *codec)
276{
277 struct via_spec *spec = codec->spec;
278 return spec->gen.ext_channel_count > 2;
279}
280
281static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin)
282{
283 struct via_spec *spec = codec->spec;
284 int i;
285
286 for (i = 0; i < spec->gen.multi_ios; i++)
287 if (spec->gen.multi_io[i].pin == pin)
288 return true;
289 return false;
290}
291
f5271101
LW
292static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
293 unsigned int *affected_parm)
294{
295 unsigned parm;
296 unsigned def_conf = snd_hda_codec_get_pincfg(codec, nid);
297 unsigned no_presence = (def_conf & AC_DEFCFG_MISC)
298 >> AC_DEFCFG_MISC_SHIFT
299 & AC_DEFCFG_MISC_NO_PRESENCE; /* do not support pin sense */
1564b287 300 struct via_spec *spec = codec->spec;
24088a58
TI
301 unsigned present = 0;
302
303 no_presence |= spec->no_pin_power_ctl;
304 if (!no_presence)
305 present = snd_hda_jack_detect(codec, nid);
b3f6008f 306 if ((smart51_enabled(codec) && is_smart51_pins(codec, nid))
1564b287
LW
307 || ((no_presence || present)
308 && get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)) {
f5271101
LW
309 *affected_parm = AC_PWRST_D0; /* if it's connected */
310 parm = AC_PWRST_D0;
311 } else
312 parm = AC_PWRST_D3;
313
054d867e 314 update_power_state(codec, nid, parm);
f5271101
LW
315}
316
24088a58
TI
317static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
318 struct snd_ctl_elem_info *uinfo)
319{
dda415d4 320 return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
24088a58
TI
321}
322
323static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol,
324 struct snd_ctl_elem_value *ucontrol)
325{
326 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
327 struct via_spec *spec = codec->spec;
328 ucontrol->value.enumerated.item[0] = !spec->no_pin_power_ctl;
329 return 0;
330}
331
332static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
333 struct snd_ctl_elem_value *ucontrol)
334{
335 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
336 struct via_spec *spec = codec->spec;
337 unsigned int val = !ucontrol->value.enumerated.item[0];
338
339 if (val == spec->no_pin_power_ctl)
340 return 0;
341 spec->no_pin_power_ctl = val;
342 set_widgets_power_state(codec);
e9d010c2 343 analog_low_current_mode(codec);
24088a58
TI
344 return 1;
345}
346
b3f6008f
TI
347static const struct snd_kcontrol_new via_pin_power_ctl_enum[] = {
348 {
24088a58
TI
349 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
350 .name = "Dynamic Power-Control",
351 .info = via_pin_power_ctl_info,
352 .get = via_pin_power_ctl_get,
353 .put = via_pin_power_ctl_put,
b3f6008f
TI
354 },
355 {} /* terminator */
24088a58
TI
356};
357
358
b3f6008f
TI
359/* check AA path's mute status */
360static bool is_aa_path_mute(struct hda_codec *codec)
0aa62aef 361{
cdc1784d 362 struct via_spec *spec = codec->spec;
b3f6008f 363 const struct hda_amp_list *p;
0186f4f4 364 int ch, v;
cdc1784d 365
0186f4f4
TI
366 p = spec->gen.loopback.amplist;
367 if (!p)
368 return true;
369 for (; p->nid; p++) {
b3f6008f
TI
370 for (ch = 0; ch < 2; ch++) {
371 v = snd_hda_codec_amp_read(codec, p->nid, ch, p->dir,
372 p->idx);
373 if (!(v & HDA_AMP_MUTE) && v > 0)
374 return false;
375 }
3b607e3d 376 }
b3f6008f 377 return true;
3b607e3d
TI
378}
379
b3f6008f
TI
380/* enter/exit analog low-current mode */
381static void __analog_low_current_mode(struct hda_codec *codec, bool force)
3b607e3d
TI
382{
383 struct via_spec *spec = codec->spec;
b3f6008f
TI
384 bool enable;
385 unsigned int verb, parm;
3b607e3d 386
b3f6008f
TI
387 if (spec->no_pin_power_ctl)
388 enable = false;
389 else
390 enable = is_aa_path_mute(codec) && !spec->gen.active_streams;
391 if (enable == spec->alc_mode && !force)
3b607e3d 392 return;
b3f6008f 393 spec->alc_mode = enable;
3b607e3d 394
b3f6008f
TI
395 /* decide low current mode's verb & parameter */
396 switch (spec->codec_type) {
397 case VT1708B_8CH:
398 case VT1708B_4CH:
399 verb = 0xf70;
400 parm = enable ? 0x02 : 0x00; /* 0x02: 2/3x, 0x00: 1x */
401 break;
402 case VT1708S:
403 case VT1718S:
404 case VT1716S:
405 verb = 0xf73;
406 parm = enable ? 0x51 : 0xe1; /* 0x51: 4/28x, 0xe1: 1x */
407 break;
408 case VT1702:
409 verb = 0xf73;
410 parm = enable ? 0x01 : 0x1d; /* 0x01: 4/40x, 0x1d: 1x */
411 break;
412 case VT2002P:
413 case VT1812:
414 case VT1802:
415 verb = 0xf93;
416 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
417 break;
418 case VT1705CF:
419 case VT1808:
420 verb = 0xf82;
421 parm = enable ? 0x00 : 0xe0; /* 0x00: 4/40x, 0xe0: 1x */
422 break;
423 default:
424 return; /* other codecs are not supported */
f5271101
LW
425 }
426 /* send verb */
b3f6008f 427 snd_hda_codec_write(codec, codec->afg, 0, verb, parm);
a86a88ea
TI
428}
429
b3f6008f
TI
430static void analog_low_current_mode(struct hda_codec *codec)
431{
432 return __analog_low_current_mode(codec, false);
433}
a86a88ea 434
b3f6008f 435static int via_build_controls(struct hda_codec *codec)
a86a88ea
TI
436{
437 struct via_spec *spec = codec->spec;
b3f6008f 438 int err, i;
a766d0d7 439
b3f6008f 440 err = snd_hda_gen_build_controls(codec);
a766d0d7
TI
441 if (err < 0)
442 return err;
c577b8a1 443
b3f6008f
TI
444 if (spec->set_widgets_power_state)
445 spec->mixers[spec->num_mixers++] = via_pin_power_ctl_enum;
c577b8a1 446
b3f6008f
TI
447 for (i = 0; i < spec->num_mixers; i++) {
448 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
449 if (err < 0)
450 return err;
451 }
a86a88ea
TI
452
453 return 0;
454}
455
b3f6008f
TI
456static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo,
457 struct hda_codec *codec,
458 struct snd_pcm_substream *substream,
459 int action)
a86a88ea 460{
b3f6008f
TI
461 analog_low_current_mode(codec);
462 vt1708_update_hp_work(codec);
a86a88ea
TI
463}
464
b3f6008f 465static void via_free(struct hda_codec *codec)
a86a88ea
TI
466{
467 struct via_spec *spec = codec->spec;
a86a88ea 468
b3f6008f
TI
469 if (!spec)
470 return;
a86a88ea 471
b3f6008f
TI
472 vt1708_stop_hp_work(codec);
473 snd_hda_gen_spec_free(&spec->gen);
474 kfree(spec);
a86a88ea
TI
475}
476
b3f6008f
TI
477#ifdef CONFIG_PM
478static int via_suspend(struct hda_codec *codec)
a86a88ea
TI
479{
480 struct via_spec *spec = codec->spec;
b3f6008f 481 vt1708_stop_hp_work(codec);
d7a99cce 482
b3f6008f
TI
483 if (spec->codec_type == VT1802) {
484 /* Fix pop noise on headphones */
485 int i;
486 for (i = 0; i < spec->gen.autocfg.hp_outs; i++)
5a6f294e
TI
487 snd_hda_codec_write(codec, spec->gen.autocfg.hp_pins[i],
488 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
489 0x00);
d7a99cce
TI
490 }
491
a86a88ea
TI
492 return 0;
493}
b3f6008f 494#endif
a86a88ea 495
b3f6008f
TI
496#ifdef CONFIG_PM
497static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
a86a88ea
TI
498{
499 struct via_spec *spec = codec->spec;
b3f6008f
TI
500 set_widgets_power_state(codec);
501 analog_low_current_mode(codec);
502 vt1708_update_hp_work(codec);
503 return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid);
504}
505#endif
a86a88ea 506
b3f6008f
TI
507/*
508 */
a86a88ea 509
b3f6008f 510static int via_init(struct hda_codec *codec);
a86a88ea 511
b3f6008f
TI
512static const struct hda_codec_ops via_patch_ops = {
513 .build_controls = via_build_controls,
514 .build_pcms = snd_hda_gen_build_pcms,
515 .init = via_init,
516 .free = via_free,
517 .unsol_event = snd_hda_jack_unsol_event,
518#ifdef CONFIG_PM
519 .suspend = via_suspend,
520 .check_power_status = via_check_power_status,
521#endif
522};
a86a88ea 523
c577b8a1 524
b3f6008f
TI
525static const struct hda_verb vt1708_init_verbs[] = {
526 /* power down jack detect function */
527 {0x1, 0xf81, 0x1},
528 { }
529};
76d9b0dd
HW
530static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
531{
532 unsigned int def_conf;
533 unsigned char seqassoc;
534
2f334f92 535 def_conf = snd_hda_codec_get_pincfg(codec, nid);
76d9b0dd
HW
536 seqassoc = (unsigned char) get_defcfg_association(def_conf);
537 seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
82ef9e45
LW
538 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
539 && (seqassoc == 0xf0 || seqassoc == 0xff)) {
540 def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
541 snd_hda_codec_set_pincfg(codec, nid, def_conf);
76d9b0dd
HW
542 }
543
544 return;
545}
546
e06e5a29 547static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
1f2e99fe
LW
548 struct snd_ctl_elem_value *ucontrol)
549{
550 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
551 struct via_spec *spec = codec->spec;
552
553 if (spec->codec_type != VT1708)
554 return 0;
e06e5a29 555 ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
1f2e99fe
LW
556 return 0;
557}
558
e06e5a29 559static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
1f2e99fe
LW
560 struct snd_ctl_elem_value *ucontrol)
561{
562 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
563 struct via_spec *spec = codec->spec;
187d333e 564 int val;
1f2e99fe
LW
565
566 if (spec->codec_type != VT1708)
567 return 0;
187d333e
TI
568 val = !!ucontrol->value.integer.value[0];
569 if (spec->vt1708_jack_detect == val)
570 return 0;
571 spec->vt1708_jack_detect = val;
b3f6008f 572 vt1708_update_hp_work(codec);
187d333e 573 return 1;
1f2e99fe
LW
574}
575
b3f6008f
TI
576static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = {
577 {
e06e5a29
TI
578 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
579 .name = "Jack Detect",
580 .count = 1,
581 .info = snd_ctl_boolean_mono_info,
582 .get = vt1708_jack_detect_get,
583 .put = vt1708_jack_detect_put,
b3f6008f
TI
584 },
585 {} /* terminator */
1f2e99fe
LW
586};
587
b3f6008f 588static void via_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl)
c577b8a1 589{
b3f6008f
TI
590 set_widgets_power_state(codec);
591 snd_hda_gen_hp_automute(codec, tbl);
5d41762a
TI
592}
593
b3f6008f 594static void via_line_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl)
4e2d16d3
DH
595{
596 set_widgets_power_state(codec);
b3f6008f 597 snd_hda_gen_line_automute(codec, tbl);
4e2d16d3
DH
598}
599
600static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
601{
602 set_widgets_power_state(codec);
603}
604
b3f6008f
TI
605#define VIA_JACK_EVENT (HDA_GEN_LAST_EVENT + 1)
606
607static void via_set_jack_unsol_events(struct hda_codec *codec)
4a918ffe
TI
608{
609 struct via_spec *spec = codec->spec;
b3f6008f
TI
610 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
611 hda_nid_t pin;
4a918ffe 612 int i;
4a918ffe 613
b3f6008f 614 spec->gen.hp_automute_hook = via_hp_automute;
4a918ffe 615 if (cfg->speaker_pins[0])
b3f6008f 616 spec->gen.line_automute_hook = via_line_automute;
4e2d16d3 617
4a918ffe 618 for (i = 0; i < cfg->line_outs; i++) {
b3f6008f
TI
619 pin = cfg->line_out_pins[i];
620 if (pin && !snd_hda_jack_tbl_get(codec, pin) &&
621 is_jack_detectable(codec, pin))
622 snd_hda_jack_detect_enable_callback(codec, pin,
623 VIA_JACK_EVENT,
624 via_jack_powerstate_event);
4a918ffe
TI
625 }
626
627 for (i = 0; i < cfg->num_inputs; i++) {
b3f6008f
TI
628 pin = cfg->line_out_pins[i];
629 if (pin && !snd_hda_jack_tbl_get(codec, pin) &&
630 is_jack_detectable(codec, pin))
631 snd_hda_jack_detect_enable_callback(codec, pin,
4e2d16d3
DH
632 VIA_JACK_EVENT,
633 via_jack_powerstate_event);
4a918ffe
TI
634 }
635}
636
4abdbd1c
TI
637static const struct badness_table via_main_out_badness = {
638 .no_primary_dac = 0x10000,
639 .no_dac = 0x4000,
640 .shared_primary = 0x10000,
641 .shared_surr = 0x20,
642 .shared_clfe = 0x20,
643 .shared_surr_main = 0x20,
644};
645static const struct badness_table via_extra_out_badness = {
646 .no_primary_dac = 0x4000,
647 .no_dac = 0x4000,
648 .shared_primary = 0x12,
649 .shared_surr = 0x20,
650 .shared_clfe = 0x20,
651 .shared_surr_main = 0x10,
652};
653
b3f6008f
TI
654static int via_parse_auto_config(struct hda_codec *codec)
655{
656 struct via_spec *spec = codec->spec;
657 int err;
658
4abdbd1c
TI
659 spec->gen.main_out_badness = &via_main_out_badness;
660 spec->gen.extra_out_badness = &via_extra_out_badness;
661
b3f6008f
TI
662 err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
663 if (err < 0)
664 return err;
665
666 err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
667 if (err < 0)
668 return err;
669
670 via_set_jack_unsol_events(codec);
671 return 0;
672}
673
5d41762a
TI
674static int via_init(struct hda_codec *codec)
675{
676 struct via_spec *spec = codec->spec;
677 int i;
678
679 for (i = 0; i < spec->num_iverbs; i++)
680 snd_hda_sequence_write(codec, spec->init_verbs[i]);
25eaba2f 681
e9d010c2
TI
682 /* init power states */
683 set_widgets_power_state(codec);
684 __analog_low_current_mode(codec, true);
685
b3f6008f 686 snd_hda_gen_init(codec);
4a918ffe 687
b3f6008f 688 vt1708_update_hp_work(codec);
25eaba2f 689
c577b8a1
JC
690 return 0;
691}
692
f672f65a
DH
693static int vt1708_build_controls(struct hda_codec *codec)
694{
695 /* In order not to create "Phantom Jack" controls,
696 temporary enable jackpoll */
697 int err;
698 int old_interval = codec->jackpoll_interval;
699 codec->jackpoll_interval = msecs_to_jiffies(100);
700 err = via_build_controls(codec);
701 codec->jackpoll_interval = old_interval;
702 return err;
703}
704
b3f6008f 705static int vt1708_build_pcms(struct hda_codec *codec)
337b9d02
TI
706{
707 struct via_spec *spec = codec->spec;
b3f6008f
TI
708 int i, err;
709
710 err = snd_hda_gen_build_pcms(codec);
711 if (err < 0 || codec->vendor_id != 0x11061708)
712 return err;
713
714 /* We got noisy outputs on the right channel on VT1708 when
715 * 24bit samples are used. Until any workaround is found,
716 * disable the 24bit format, so far.
717 */
718 for (i = 0; i < codec->num_pcms; i++) {
719 struct hda_pcm *info = &spec->gen.pcm_rec[i];
720 if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
721 info->pcm_type != HDA_PCM_TYPE_AUDIO)
722 continue;
723 info->stream[SNDRV_PCM_STREAM_PLAYBACK].formats =
724 SNDRV_PCM_FMTBIT_S16_LE;
337b9d02 725 }
b3f6008f 726
1c55d521 727 return 0;
337b9d02
TI
728}
729
c577b8a1
JC
730static int patch_vt1708(struct hda_codec *codec)
731{
732 struct via_spec *spec;
733 int err;
734
735 /* create a codec specific record */
5b0cb1d8 736 spec = via_new_spec(codec);
c577b8a1
JC
737 if (spec == NULL)
738 return -ENOMEM;
739
b3f6008f
TI
740 spec->gen.mixer_nid = 0x17;
741
742 /* set jackpoll_interval while parsing the codec */
743 codec->jackpoll_interval = msecs_to_jiffies(100);
744 spec->vt1708_jack_detect = 1;
745
746 /* don't support the input jack switching due to lack of unsol event */
747 /* (it may work with polling, though, but it needs testing) */
748 spec->gen.suppress_auto_mic = 1;
620e2b28 749
12daef65
TI
750 /* Add HP and CD pin config connect bit re-config action */
751 vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
752 vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
753
c577b8a1 754 /* automatic parse from the BIOS config */
12daef65 755 err = via_parse_auto_config(codec);
c577b8a1
JC
756 if (err < 0) {
757 via_free(codec);
758 return err;
c577b8a1
JC
759 }
760
12daef65 761 /* add jack detect on/off control */
b3f6008f 762 spec->mixers[spec->num_mixers++] = vt1708_jack_detect_ctl;
c577b8a1 763
e322a36d
LW
764 spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs;
765
c577b8a1 766 codec->patch_ops = via_patch_ops;
f672f65a 767 codec->patch_ops.build_controls = vt1708_build_controls;
b3f6008f
TI
768 codec->patch_ops.build_pcms = vt1708_build_pcms;
769
770 /* clear jackpoll_interval again; it's set dynamically */
771 codec->jackpoll_interval = 0;
c577b8a1 772
c577b8a1
JC
773 return 0;
774}
775
ddd304d8 776static int patch_vt1709(struct hda_codec *codec)
c577b8a1
JC
777{
778 struct via_spec *spec;
779 int err;
780
781 /* create a codec specific record */
5b0cb1d8 782 spec = via_new_spec(codec);
c577b8a1
JC
783 if (spec == NULL)
784 return -ENOMEM;
785
b3f6008f 786 spec->gen.mixer_nid = 0x18;
620e2b28 787
12daef65 788 err = via_parse_auto_config(codec);
c577b8a1
JC
789 if (err < 0) {
790 via_free(codec);
791 return err;
c577b8a1
JC
792 }
793
c577b8a1
JC
794 codec->patch_ops = via_patch_ops;
795
f7278fd0
JC
796 return 0;
797}
798
3e95b9ab
LW
799static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
800{
801 struct via_spec *spec = codec->spec;
802 int imux_is_smixer;
803 unsigned int parm;
804 int is_8ch = 0;
bc92df7f
LW
805 if ((spec->codec_type != VT1708B_4CH) &&
806 (codec->vendor_id != 0x11064397))
3e95b9ab
LW
807 is_8ch = 1;
808
809 /* SW0 (17h) = stereo mixer */
810 imux_is_smixer =
811 (snd_hda_codec_read(codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
812 == ((spec->codec_type == VT1708S) ? 5 : 0));
813 /* inputs */
814 /* PW 1/2/5 (1ah/1bh/1eh) */
815 parm = AC_PWRST_D3;
816 set_pin_power_state(codec, 0x1a, &parm);
817 set_pin_power_state(codec, 0x1b, &parm);
818 set_pin_power_state(codec, 0x1e, &parm);
819 if (imux_is_smixer)
820 parm = AC_PWRST_D0;
821 /* SW0 (17h), AIW 0/1 (13h/14h) */
054d867e
TI
822 update_power_state(codec, 0x17, parm);
823 update_power_state(codec, 0x13, parm);
824 update_power_state(codec, 0x14, parm);
3e95b9ab
LW
825
826 /* outputs */
827 /* PW0 (19h), SW1 (18h), AOW1 (11h) */
828 parm = AC_PWRST_D3;
829 set_pin_power_state(codec, 0x19, &parm);
b3f6008f 830 if (smart51_enabled(codec))
3e95b9ab 831 set_pin_power_state(codec, 0x1b, &parm);
054d867e
TI
832 update_power_state(codec, 0x18, parm);
833 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
834
835 /* PW6 (22h), SW2 (26h), AOW2 (24h) */
836 if (is_8ch) {
837 parm = AC_PWRST_D3;
838 set_pin_power_state(codec, 0x22, &parm);
b3f6008f 839 if (smart51_enabled(codec))
3e95b9ab 840 set_pin_power_state(codec, 0x1a, &parm);
054d867e
TI
841 update_power_state(codec, 0x26, parm);
842 update_power_state(codec, 0x24, parm);
bc92df7f
LW
843 } else if (codec->vendor_id == 0x11064397) {
844 /* PW7(23h), SW2(27h), AOW2(25h) */
845 parm = AC_PWRST_D3;
846 set_pin_power_state(codec, 0x23, &parm);
b3f6008f 847 if (smart51_enabled(codec))
bc92df7f 848 set_pin_power_state(codec, 0x1a, &parm);
054d867e
TI
849 update_power_state(codec, 0x27, parm);
850 update_power_state(codec, 0x25, parm);
3e95b9ab
LW
851 }
852
853 /* PW 3/4/7 (1ch/1dh/23h) */
854 parm = AC_PWRST_D3;
855 /* force to D0 for internal Speaker */
856 set_pin_power_state(codec, 0x1c, &parm);
857 set_pin_power_state(codec, 0x1d, &parm);
858 if (is_8ch)
859 set_pin_power_state(codec, 0x23, &parm);
860
861 /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
054d867e
TI
862 update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
863 update_power_state(codec, 0x10, parm);
3e95b9ab 864 if (is_8ch) {
054d867e
TI
865 update_power_state(codec, 0x25, parm);
866 update_power_state(codec, 0x27, parm);
b3f6008f 867 } else if (codec->vendor_id == 0x11064397 && spec->gen.indep_hp_enabled)
054d867e 868 update_power_state(codec, 0x25, parm);
3e95b9ab
LW
869}
870
518bf3ba 871static int patch_vt1708S(struct hda_codec *codec);
ddd304d8 872static int patch_vt1708B(struct hda_codec *codec)
f7278fd0
JC
873{
874 struct via_spec *spec;
875 int err;
876
518bf3ba
LW
877 if (get_codec_type(codec) == VT1708BCE)
878 return patch_vt1708S(codec);
ddd304d8 879
f7278fd0 880 /* create a codec specific record */
5b0cb1d8 881 spec = via_new_spec(codec);
f7278fd0
JC
882 if (spec == NULL)
883 return -ENOMEM;
884
b3f6008f 885 spec->gen.mixer_nid = 0x16;
620e2b28 886
f7278fd0 887 /* automatic parse from the BIOS config */
12daef65 888 err = via_parse_auto_config(codec);
f7278fd0
JC
889 if (err < 0) {
890 via_free(codec);
891 return err;
f7278fd0
JC
892 }
893
f7278fd0
JC
894 codec->patch_ops = via_patch_ops;
895
3e95b9ab
LW
896 spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
897
f7278fd0
JC
898 return 0;
899}
900
d949cac1 901/* Patch for VT1708S */
096a8854 902static const struct hda_verb vt1708S_init_verbs[] = {
d7426329
HW
903 /* Enable Mic Boost Volume backdoor */
904 {0x1, 0xf98, 0x1},
bc7e7e5c
LW
905 /* don't bybass mixer */
906 {0x1, 0xf88, 0xc0},
d949cac1
HW
907 { }
908};
909
6369bcfc
LW
910static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
911 int offset, int num_steps, int step_size)
912{
1f563ec4
TI
913 snd_hda_override_wcaps(codec, pin,
914 get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
6369bcfc
LW
915 snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
916 (offset << AC_AMPCAP_OFFSET_SHIFT) |
917 (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
918 (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
919 (0 << AC_AMPCAP_MUTE_SHIFT));
920}
921
d949cac1
HW
922static int patch_vt1708S(struct hda_codec *codec)
923{
924 struct via_spec *spec;
925 int err;
926
927 /* create a codec specific record */
5b0cb1d8 928 spec = via_new_spec(codec);
d949cac1
HW
929 if (spec == NULL)
930 return -ENOMEM;
931
b3f6008f 932 spec->gen.mixer_nid = 0x16;
d7a99cce
TI
933 override_mic_boost(codec, 0x1a, 0, 3, 40);
934 override_mic_boost(codec, 0x1e, 0, 3, 40);
620e2b28 935
518bf3ba
LW
936 /* correct names for VT1708BCE */
937 if (get_codec_type(codec) == VT1708BCE) {
938 kfree(codec->chip_name);
939 codec->chip_name = kstrdup("VT1708BCE", GFP_KERNEL);
940 snprintf(codec->bus->card->mixername,
941 sizeof(codec->bus->card->mixername),
942 "%s %s", codec->vendor_name, codec->chip_name);
970f630f 943 }
bc92df7f
LW
944 /* correct names for VT1705 */
945 if (codec->vendor_id == 0x11064397) {
946 kfree(codec->chip_name);
947 codec->chip_name = kstrdup("VT1705", GFP_KERNEL);
948 snprintf(codec->bus->card->mixername,
949 sizeof(codec->bus->card->mixername),
950 "%s %s", codec->vendor_name, codec->chip_name);
951 }
b3f6008f
TI
952
953 /* automatic parse from the BIOS config */
954 err = via_parse_auto_config(codec);
955 if (err < 0) {
956 via_free(codec);
957 return err;
958 }
959
960 spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs;
961
962 codec->patch_ops = via_patch_ops;
963
3e95b9ab 964 spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
d949cac1
HW
965 return 0;
966}
967
968/* Patch for VT1702 */
969
096a8854 970static const struct hda_verb vt1702_init_verbs[] = {
bc7e7e5c
LW
971 /* mixer enable */
972 {0x1, 0xF88, 0x3},
973 /* GPIO 0~2 */
974 {0x1, 0xF82, 0x3F},
d949cac1
HW
975 { }
976};
977
3e95b9ab
LW
978static void set_widgets_power_state_vt1702(struct hda_codec *codec)
979{
980 int imux_is_smixer =
981 snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
982 unsigned int parm;
983 /* inputs */
984 /* PW 1/2/5 (14h/15h/18h) */
985 parm = AC_PWRST_D3;
986 set_pin_power_state(codec, 0x14, &parm);
987 set_pin_power_state(codec, 0x15, &parm);
988 set_pin_power_state(codec, 0x18, &parm);
989 if (imux_is_smixer)
990 parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
991 /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
054d867e
TI
992 update_power_state(codec, 0x13, parm);
993 update_power_state(codec, 0x12, parm);
994 update_power_state(codec, 0x1f, parm);
995 update_power_state(codec, 0x20, parm);
3e95b9ab
LW
996
997 /* outputs */
998 /* PW 3/4 (16h/17h) */
999 parm = AC_PWRST_D3;
1000 set_pin_power_state(codec, 0x17, &parm);
1001 set_pin_power_state(codec, 0x16, &parm);
1002 /* MW0 (1ah), AOW 0/1 (10h/1dh) */
054d867e
TI
1003 update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm);
1004 update_power_state(codec, 0x10, parm);
1005 update_power_state(codec, 0x1d, parm);
3e95b9ab
LW
1006}
1007
d949cac1
HW
1008static int patch_vt1702(struct hda_codec *codec)
1009{
1010 struct via_spec *spec;
1011 int err;
d949cac1
HW
1012
1013 /* create a codec specific record */
5b0cb1d8 1014 spec = via_new_spec(codec);
d949cac1
HW
1015 if (spec == NULL)
1016 return -ENOMEM;
1017
b3f6008f 1018 spec->gen.mixer_nid = 0x1a;
620e2b28 1019
12daef65
TI
1020 /* limit AA path volume to 0 dB */
1021 snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
1022 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1023 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1024 (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1025 (1 << AC_AMPCAP_MUTE_SHIFT));
1026
d949cac1 1027 /* automatic parse from the BIOS config */
12daef65 1028 err = via_parse_auto_config(codec);
d949cac1
HW
1029 if (err < 0) {
1030 via_free(codec);
1031 return err;
d949cac1
HW
1032 }
1033
096a8854 1034 spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs;
d949cac1 1035
d949cac1
HW
1036 codec->patch_ops = via_patch_ops;
1037
3e95b9ab 1038 spec->set_widgets_power_state = set_widgets_power_state_vt1702;
d949cac1
HW
1039 return 0;
1040}
1041
eb7188ca
LW
1042/* Patch for VT1718S */
1043
096a8854 1044static const struct hda_verb vt1718S_init_verbs[] = {
4ab2d53a
LW
1045 /* Enable MW0 adjust Gain 5 */
1046 {0x1, 0xfb2, 0x10},
eb7188ca
LW
1047 /* Enable Boost Volume backdoor */
1048 {0x1, 0xf88, 0x8},
5d41762a 1049
eb7188ca
LW
1050 { }
1051};
1052
3e95b9ab
LW
1053static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
1054{
1055 struct via_spec *spec = codec->spec;
1056 int imux_is_smixer;
6162552b 1057 unsigned int parm, parm2;
3e95b9ab
LW
1058 /* MUX6 (1eh) = stereo mixer */
1059 imux_is_smixer =
1060 snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
1061 /* inputs */
1062 /* PW 5/6/7 (29h/2ah/2bh) */
1063 parm = AC_PWRST_D3;
1064 set_pin_power_state(codec, 0x29, &parm);
1065 set_pin_power_state(codec, 0x2a, &parm);
1066 set_pin_power_state(codec, 0x2b, &parm);
1067 if (imux_is_smixer)
1068 parm = AC_PWRST_D0;
1069 /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
054d867e
TI
1070 update_power_state(codec, 0x1e, parm);
1071 update_power_state(codec, 0x1f, parm);
1072 update_power_state(codec, 0x10, parm);
1073 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1074
1075 /* outputs */
1076 /* PW3 (27h), MW2 (1ah), AOW3 (bh) */
1077 parm = AC_PWRST_D3;
1078 set_pin_power_state(codec, 0x27, &parm);
054d867e 1079 update_power_state(codec, 0x1a, parm);
6162552b 1080 parm2 = parm; /* for pin 0x0b */
3e95b9ab
LW
1081
1082 /* PW2 (26h), AOW2 (ah) */
1083 parm = AC_PWRST_D3;
1084 set_pin_power_state(codec, 0x26, &parm);
b3f6008f 1085 if (smart51_enabled(codec))
3e95b9ab 1086 set_pin_power_state(codec, 0x2b, &parm);
054d867e 1087 update_power_state(codec, 0xa, parm);
3e95b9ab
LW
1088
1089 /* PW0 (24h), AOW0 (8h) */
1090 parm = AC_PWRST_D3;
1091 set_pin_power_state(codec, 0x24, &parm);
b3f6008f 1092 if (!spec->gen.indep_hp_enabled) /* check for redirected HP */
3e95b9ab 1093 set_pin_power_state(codec, 0x28, &parm);
054d867e 1094 update_power_state(codec, 0x8, parm);
b3f6008f 1095 if (!spec->gen.indep_hp_enabled && parm2 != AC_PWRST_D3)
6162552b
TI
1096 parm = parm2;
1097 update_power_state(codec, 0xb, parm);
3e95b9ab 1098 /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
054d867e 1099 update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm);
3e95b9ab
LW
1100
1101 /* PW1 (25h), AOW1 (9h) */
1102 parm = AC_PWRST_D3;
1103 set_pin_power_state(codec, 0x25, &parm);
b3f6008f 1104 if (smart51_enabled(codec))
3e95b9ab 1105 set_pin_power_state(codec, 0x2a, &parm);
054d867e 1106 update_power_state(codec, 0x9, parm);
3e95b9ab 1107
b3f6008f 1108 if (spec->gen.indep_hp_enabled) {
3e95b9ab
LW
1109 /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
1110 parm = AC_PWRST_D3;
1111 set_pin_power_state(codec, 0x28, &parm);
054d867e
TI
1112 update_power_state(codec, 0x1b, parm);
1113 update_power_state(codec, 0x34, parm);
1114 update_power_state(codec, 0xc, parm);
3e95b9ab
LW
1115 }
1116}
1117
30b45033
TI
1118/* Add a connection to the primary DAC from AA-mixer for some codecs
1119 * This isn't listed from the raw info, but the chip has a secret connection.
1120 */
1121static int add_secret_dac_path(struct hda_codec *codec)
1122{
1123 struct via_spec *spec = codec->spec;
1124 int i, nums;
1125 hda_nid_t conn[8];
1126 hda_nid_t nid;
1127
b3f6008f 1128 if (!spec->gen.mixer_nid)
30b45033 1129 return 0;
b3f6008f 1130 nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
30b45033
TI
1131 ARRAY_SIZE(conn) - 1);
1132 for (i = 0; i < nums; i++) {
1133 if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
1134 return 0;
1135 }
1136
1137 /* find the primary DAC and add to the connection list */
1138 nid = codec->start_nid;
1139 for (i = 0; i < codec->num_nodes; i++, nid++) {
1140 unsigned int caps = get_wcaps(codec, nid);
1141 if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
1142 !(caps & AC_WCAP_DIGITAL)) {
1143 conn[nums++] = nid;
1144 return snd_hda_override_conn_list(codec,
b3f6008f 1145 spec->gen.mixer_nid,
30b45033
TI
1146 nums, conn);
1147 }
1148 }
1149 return 0;
1150}
1151
1152
eb7188ca
LW
1153static int patch_vt1718S(struct hda_codec *codec)
1154{
1155 struct via_spec *spec;
1156 int err;
1157
1158 /* create a codec specific record */
5b0cb1d8 1159 spec = via_new_spec(codec);
eb7188ca
LW
1160 if (spec == NULL)
1161 return -ENOMEM;
1162
b3f6008f 1163 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1164 override_mic_boost(codec, 0x2b, 0, 3, 40);
1165 override_mic_boost(codec, 0x29, 0, 3, 40);
30b45033 1166 add_secret_dac_path(codec);
620e2b28 1167
eb7188ca 1168 /* automatic parse from the BIOS config */
12daef65 1169 err = via_parse_auto_config(codec);
eb7188ca
LW
1170 if (err < 0) {
1171 via_free(codec);
1172 return err;
eb7188ca
LW
1173 }
1174
096a8854 1175 spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs;
eb7188ca 1176
eb7188ca
LW
1177 codec->patch_ops = via_patch_ops;
1178
3e95b9ab
LW
1179 spec->set_widgets_power_state = set_widgets_power_state_vt1718S;
1180
eb7188ca
LW
1181 return 0;
1182}
f3db423d
LW
1183
1184/* Patch for VT1716S */
1185
1186static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
1187 struct snd_ctl_elem_info *uinfo)
1188{
1189 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1190 uinfo->count = 1;
1191 uinfo->value.integer.min = 0;
1192 uinfo->value.integer.max = 1;
1193 return 0;
1194}
1195
1196static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
1197 struct snd_ctl_elem_value *ucontrol)
1198{
1199 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1200 int index = 0;
1201
1202 index = snd_hda_codec_read(codec, 0x26, 0,
1203 AC_VERB_GET_CONNECT_SEL, 0);
1204 if (index != -1)
1205 *ucontrol->value.integer.value = index;
1206
1207 return 0;
1208}
1209
1210static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
1211 struct snd_ctl_elem_value *ucontrol)
1212{
1213 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1214 struct via_spec *spec = codec->spec;
1215 int index = *ucontrol->value.integer.value;
1216
1217 snd_hda_codec_write(codec, 0x26, 0,
1218 AC_VERB_SET_CONNECT_SEL, index);
1219 spec->dmic_enabled = index;
3e95b9ab 1220 set_widgets_power_state(codec);
f3db423d
LW
1221 return 1;
1222}
1223
90dd48a1 1224static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
f3db423d
LW
1225 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT),
1226 {
1227 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1228 .name = "Digital Mic Capture Switch",
5b0cb1d8 1229 .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
f3db423d
LW
1230 .count = 1,
1231 .info = vt1716s_dmic_info,
1232 .get = vt1716s_dmic_get,
1233 .put = vt1716s_dmic_put,
1234 },
1235 {} /* end */
1236};
1237
1238
1239/* mono-out mixer elements */
90dd48a1 1240static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
f3db423d
LW
1241 HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT),
1242 { } /* end */
1243};
1244
096a8854 1245static const struct hda_verb vt1716S_init_verbs[] = {
f3db423d
LW
1246 /* Enable Boost Volume backdoor */
1247 {0x1, 0xf8a, 0x80},
1248 /* don't bybass mixer */
1249 {0x1, 0xf88, 0xc0},
1250 /* Enable mono output */
1251 {0x1, 0xf90, 0x08},
1252 { }
1253};
1254
3e95b9ab
LW
1255static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
1256{
1257 struct via_spec *spec = codec->spec;
1258 int imux_is_smixer;
1259 unsigned int parm;
1260 unsigned int mono_out, present;
1261 /* SW0 (17h) = stereo mixer */
1262 imux_is_smixer =
1263 (snd_hda_codec_read(codec, 0x17, 0,
1264 AC_VERB_GET_CONNECT_SEL, 0x00) == 5);
1265 /* inputs */
1266 /* PW 1/2/5 (1ah/1bh/1eh) */
1267 parm = AC_PWRST_D3;
1268 set_pin_power_state(codec, 0x1a, &parm);
1269 set_pin_power_state(codec, 0x1b, &parm);
1270 set_pin_power_state(codec, 0x1e, &parm);
1271 if (imux_is_smixer)
1272 parm = AC_PWRST_D0;
1273 /* SW0 (17h), AIW0(13h) */
054d867e
TI
1274 update_power_state(codec, 0x17, parm);
1275 update_power_state(codec, 0x13, parm);
3e95b9ab
LW
1276
1277 parm = AC_PWRST_D3;
1278 set_pin_power_state(codec, 0x1e, &parm);
1279 /* PW11 (22h) */
1280 if (spec->dmic_enabled)
1281 set_pin_power_state(codec, 0x22, &parm);
1282 else
054d867e 1283 update_power_state(codec, 0x22, AC_PWRST_D3);
3e95b9ab
LW
1284
1285 /* SW2(26h), AIW1(14h) */
054d867e
TI
1286 update_power_state(codec, 0x26, parm);
1287 update_power_state(codec, 0x14, parm);
3e95b9ab
LW
1288
1289 /* outputs */
1290 /* PW0 (19h), SW1 (18h), AOW1 (11h) */
1291 parm = AC_PWRST_D3;
1292 set_pin_power_state(codec, 0x19, &parm);
1293 /* Smart 5.1 PW2(1bh) */
b3f6008f 1294 if (smart51_enabled(codec))
3e95b9ab 1295 set_pin_power_state(codec, 0x1b, &parm);
054d867e
TI
1296 update_power_state(codec, 0x18, parm);
1297 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1298
1299 /* PW7 (23h), SW3 (27h), AOW3 (25h) */
1300 parm = AC_PWRST_D3;
1301 set_pin_power_state(codec, 0x23, &parm);
1302 /* Smart 5.1 PW1(1ah) */
b3f6008f 1303 if (smart51_enabled(codec))
3e95b9ab 1304 set_pin_power_state(codec, 0x1a, &parm);
054d867e 1305 update_power_state(codec, 0x27, parm);
3e95b9ab
LW
1306
1307 /* Smart 5.1 PW5(1eh) */
b3f6008f 1308 if (smart51_enabled(codec))
3e95b9ab 1309 set_pin_power_state(codec, 0x1e, &parm);
054d867e 1310 update_power_state(codec, 0x25, parm);
3e95b9ab
LW
1311
1312 /* Mono out */
1313 /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
1314 present = snd_hda_jack_detect(codec, 0x1c);
1315
1316 if (present)
1317 mono_out = 0;
1318 else {
1319 present = snd_hda_jack_detect(codec, 0x1d);
b3f6008f 1320 if (!spec->gen.indep_hp_enabled && present)
3e95b9ab
LW
1321 mono_out = 0;
1322 else
1323 mono_out = 1;
1324 }
1325 parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
054d867e
TI
1326 update_power_state(codec, 0x28, parm);
1327 update_power_state(codec, 0x29, parm);
1328 update_power_state(codec, 0x2a, parm);
3e95b9ab
LW
1329
1330 /* PW 3/4 (1ch/1dh) */
1331 parm = AC_PWRST_D3;
1332 set_pin_power_state(codec, 0x1c, &parm);
1333 set_pin_power_state(codec, 0x1d, &parm);
1334 /* HP Independent Mode, power on AOW3 */
b3f6008f 1335 if (spec->gen.indep_hp_enabled)
054d867e 1336 update_power_state(codec, 0x25, parm);
3e95b9ab
LW
1337
1338 /* force to D0 for internal Speaker */
1339 /* MW0 (16h), AOW0 (10h) */
054d867e
TI
1340 update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
1341 update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm);
3e95b9ab
LW
1342}
1343
f3db423d
LW
1344static int patch_vt1716S(struct hda_codec *codec)
1345{
1346 struct via_spec *spec;
1347 int err;
1348
1349 /* create a codec specific record */
5b0cb1d8 1350 spec = via_new_spec(codec);
f3db423d
LW
1351 if (spec == NULL)
1352 return -ENOMEM;
1353
b3f6008f 1354 spec->gen.mixer_nid = 0x16;
d7a99cce
TI
1355 override_mic_boost(codec, 0x1a, 0, 3, 40);
1356 override_mic_boost(codec, 0x1e, 0, 3, 40);
620e2b28 1357
f3db423d 1358 /* automatic parse from the BIOS config */
12daef65 1359 err = via_parse_auto_config(codec);
f3db423d
LW
1360 if (err < 0) {
1361 via_free(codec);
1362 return err;
f3db423d
LW
1363 }
1364
096a8854 1365 spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs;
f3db423d 1366
b3f6008f 1367 spec->mixers[spec->num_mixers++] = vt1716s_dmic_mixer;
f3db423d
LW
1368 spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer;
1369
1370 codec->patch_ops = via_patch_ops;
1371
3e95b9ab 1372 spec->set_widgets_power_state = set_widgets_power_state_vt1716S;
f3db423d
LW
1373 return 0;
1374}
25eaba2f
LW
1375
1376/* for vt2002P */
1377
096a8854 1378static const struct hda_verb vt2002P_init_verbs[] = {
eadb9a80
LW
1379 /* Class-D speaker related verbs */
1380 {0x1, 0xfe0, 0x4},
1381 {0x1, 0xfe9, 0x80},
1382 {0x1, 0xfe2, 0x22},
25eaba2f
LW
1383 /* Enable Boost Volume backdoor */
1384 {0x1, 0xfb9, 0x24},
25eaba2f
LW
1385 /* Enable AOW0 to MW9 */
1386 {0x1, 0xfb8, 0x88},
1387 { }
1388};
4a918ffe 1389
096a8854 1390static const struct hda_verb vt1802_init_verbs[] = {
11890956
LW
1391 /* Enable Boost Volume backdoor */
1392 {0x1, 0xfb9, 0x24},
11890956
LW
1393 /* Enable AOW0 to MW9 */
1394 {0x1, 0xfb8, 0x88},
1395 { }
1396};
25eaba2f 1397
3e95b9ab
LW
1398static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
1399{
1400 struct via_spec *spec = codec->spec;
1401 int imux_is_smixer;
1402 unsigned int parm;
1403 unsigned int present;
1404 /* MUX9 (1eh) = stereo mixer */
1405 imux_is_smixer =
1406 snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
1407 /* inputs */
1408 /* PW 5/6/7 (29h/2ah/2bh) */
1409 parm = AC_PWRST_D3;
1410 set_pin_power_state(codec, 0x29, &parm);
1411 set_pin_power_state(codec, 0x2a, &parm);
1412 set_pin_power_state(codec, 0x2b, &parm);
1413 parm = AC_PWRST_D0;
1414 /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
054d867e
TI
1415 update_power_state(codec, 0x1e, parm);
1416 update_power_state(codec, 0x1f, parm);
1417 update_power_state(codec, 0x10, parm);
1418 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1419
1420 /* outputs */
1421 /* AOW0 (8h)*/
054d867e 1422 update_power_state(codec, 0x8, parm);
3e95b9ab 1423
11890956
LW
1424 if (spec->codec_type == VT1802) {
1425 /* PW4 (28h), MW4 (18h), MUX4(38h) */
1426 parm = AC_PWRST_D3;
1427 set_pin_power_state(codec, 0x28, &parm);
054d867e
TI
1428 update_power_state(codec, 0x18, parm);
1429 update_power_state(codec, 0x38, parm);
11890956
LW
1430 } else {
1431 /* PW4 (26h), MW4 (1ch), MUX4(37h) */
1432 parm = AC_PWRST_D3;
1433 set_pin_power_state(codec, 0x26, &parm);
054d867e
TI
1434 update_power_state(codec, 0x1c, parm);
1435 update_power_state(codec, 0x37, parm);
11890956 1436 }
3e95b9ab 1437
11890956
LW
1438 if (spec->codec_type == VT1802) {
1439 /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
1440 parm = AC_PWRST_D3;
1441 set_pin_power_state(codec, 0x25, &parm);
054d867e
TI
1442 update_power_state(codec, 0x15, parm);
1443 update_power_state(codec, 0x35, parm);
11890956
LW
1444 } else {
1445 /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
1446 parm = AC_PWRST_D3;
1447 set_pin_power_state(codec, 0x25, &parm);
054d867e
TI
1448 update_power_state(codec, 0x19, parm);
1449 update_power_state(codec, 0x35, parm);
11890956 1450 }
3e95b9ab 1451
b3f6008f 1452 if (spec->gen.indep_hp_enabled)
054d867e 1453 update_power_state(codec, 0x9, AC_PWRST_D0);
3e95b9ab
LW
1454
1455 /* Class-D */
1456 /* PW0 (24h), MW0(18h/14h), MUX0(34h) */
1457 present = snd_hda_jack_detect(codec, 0x25);
1458
1459 parm = AC_PWRST_D3;
1460 set_pin_power_state(codec, 0x24, &parm);
1461 parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
11890956 1462 if (spec->codec_type == VT1802)
054d867e 1463 update_power_state(codec, 0x14, parm);
11890956 1464 else
054d867e
TI
1465 update_power_state(codec, 0x18, parm);
1466 update_power_state(codec, 0x34, parm);
3e95b9ab
LW
1467
1468 /* Mono Out */
1469 present = snd_hda_jack_detect(codec, 0x26);
1470
1471 parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
11890956
LW
1472 if (spec->codec_type == VT1802) {
1473 /* PW15 (33h), MW8(1ch), MUX8(3ch) */
054d867e
TI
1474 update_power_state(codec, 0x33, parm);
1475 update_power_state(codec, 0x1c, parm);
1476 update_power_state(codec, 0x3c, parm);
11890956
LW
1477 } else {
1478 /* PW15 (31h), MW8(17h), MUX8(3bh) */
054d867e
TI
1479 update_power_state(codec, 0x31, parm);
1480 update_power_state(codec, 0x17, parm);
1481 update_power_state(codec, 0x3b, parm);
11890956 1482 }
3e95b9ab
LW
1483 /* MW9 (21h) */
1484 if (imux_is_smixer || !is_aa_path_mute(codec))
054d867e 1485 update_power_state(codec, 0x21, AC_PWRST_D0);
3e95b9ab 1486 else
054d867e 1487 update_power_state(codec, 0x21, AC_PWRST_D3);
3e95b9ab 1488}
25eaba2f 1489
4b527b65
DH
1490/*
1491 * pin fix-up
1492 */
1493enum {
1494 VIA_FIXUP_INTMIC_BOOST,
d5266125 1495 VIA_FIXUP_ASUS_G75,
4b527b65
DH
1496};
1497
1498static void via_fixup_intmic_boost(struct hda_codec *codec,
1499 const struct hda_fixup *fix, int action)
1500{
1501 if (action == HDA_FIXUP_ACT_PRE_PROBE)
1502 override_mic_boost(codec, 0x30, 0, 2, 40);
1503}
1504
1505static const struct hda_fixup via_fixups[] = {
1506 [VIA_FIXUP_INTMIC_BOOST] = {
1507 .type = HDA_FIXUP_FUNC,
1508 .v.func = via_fixup_intmic_boost,
1509 },
d5266125
TI
1510 [VIA_FIXUP_ASUS_G75] = {
1511 .type = HDA_FIXUP_PINS,
1512 .v.pins = (const struct hda_pintbl[]) {
1513 /* set 0x24 and 0x33 as speakers */
1514 { 0x24, 0x991301f0 },
1515 { 0x33, 0x991301f1 }, /* subwoofer */
1516 { }
1517 }
1518 },
4b527b65
DH
1519};
1520
1521static const struct snd_pci_quirk vt2002p_fixups[] = {
d5266125 1522 SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
4b527b65
DH
1523 SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
1524 {}
1525};
1526
ef4da458
TI
1527/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
1528 * Replace this with mixer NID 0x1c
1529 */
1530static void fix_vt1802_connections(struct hda_codec *codec)
1531{
1532 static hda_nid_t conn_24[] = { 0x14, 0x1c };
1533 static hda_nid_t conn_33[] = { 0x1c };
1534
1535 snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
1536 snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
1537}
1538
25eaba2f
LW
1539/* patch for vt2002P */
1540static int patch_vt2002P(struct hda_codec *codec)
1541{
1542 struct via_spec *spec;
1543 int err;
1544
1545 /* create a codec specific record */
5b0cb1d8 1546 spec = via_new_spec(codec);
25eaba2f
LW
1547 if (spec == NULL)
1548 return -ENOMEM;
1549
b3f6008f 1550 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1551 override_mic_boost(codec, 0x2b, 0, 3, 40);
1552 override_mic_boost(codec, 0x29, 0, 3, 40);
ef4da458
TI
1553 if (spec->codec_type == VT1802)
1554 fix_vt1802_connections(codec);
30b45033 1555 add_secret_dac_path(codec);
620e2b28 1556
4b527b65
DH
1557 snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
1558 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1559
25eaba2f 1560 /* automatic parse from the BIOS config */
12daef65 1561 err = via_parse_auto_config(codec);
25eaba2f
LW
1562 if (err < 0) {
1563 via_free(codec);
1564 return err;
25eaba2f
LW
1565 }
1566
11890956 1567 if (spec->codec_type == VT1802)
4a918ffe 1568 spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs;
11890956 1569 else
4a918ffe 1570 spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs;
11890956 1571
25eaba2f
LW
1572 codec->patch_ops = via_patch_ops;
1573
3e95b9ab 1574 spec->set_widgets_power_state = set_widgets_power_state_vt2002P;
25eaba2f
LW
1575 return 0;
1576}
ab6734e7
LW
1577
1578/* for vt1812 */
1579
096a8854 1580static const struct hda_verb vt1812_init_verbs[] = {
ab6734e7
LW
1581 /* Enable Boost Volume backdoor */
1582 {0x1, 0xfb9, 0x24},
ab6734e7
LW
1583 /* Enable AOW0 to MW9 */
1584 {0x1, 0xfb8, 0xa8},
1585 { }
1586};
1587
3e95b9ab
LW
1588static void set_widgets_power_state_vt1812(struct hda_codec *codec)
1589{
1590 struct via_spec *spec = codec->spec;
3e95b9ab
LW
1591 unsigned int parm;
1592 unsigned int present;
3e95b9ab
LW
1593 /* inputs */
1594 /* PW 5/6/7 (29h/2ah/2bh) */
1595 parm = AC_PWRST_D3;
1596 set_pin_power_state(codec, 0x29, &parm);
1597 set_pin_power_state(codec, 0x2a, &parm);
1598 set_pin_power_state(codec, 0x2b, &parm);
1599 parm = AC_PWRST_D0;
1600 /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
054d867e
TI
1601 update_power_state(codec, 0x1e, parm);
1602 update_power_state(codec, 0x1f, parm);
1603 update_power_state(codec, 0x10, parm);
1604 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1605
1606 /* outputs */
1607 /* AOW0 (8h)*/
054d867e 1608 update_power_state(codec, 0x8, AC_PWRST_D0);
3e95b9ab
LW
1609
1610 /* PW4 (28h), MW4 (18h), MUX4(38h) */
1611 parm = AC_PWRST_D3;
1612 set_pin_power_state(codec, 0x28, &parm);
054d867e
TI
1613 update_power_state(codec, 0x18, parm);
1614 update_power_state(codec, 0x38, parm);
3e95b9ab
LW
1615
1616 /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
1617 parm = AC_PWRST_D3;
1618 set_pin_power_state(codec, 0x25, &parm);
054d867e
TI
1619 update_power_state(codec, 0x15, parm);
1620 update_power_state(codec, 0x35, parm);
b3f6008f 1621 if (spec->gen.indep_hp_enabled)
054d867e 1622 update_power_state(codec, 0x9, AC_PWRST_D0);
3e95b9ab
LW
1623
1624 /* Internal Speaker */
1625 /* PW0 (24h), MW0(14h), MUX0(34h) */
1626 present = snd_hda_jack_detect(codec, 0x25);
1627
1628 parm = AC_PWRST_D3;
1629 set_pin_power_state(codec, 0x24, &parm);
1630 if (present) {
054d867e
TI
1631 update_power_state(codec, 0x14, AC_PWRST_D3);
1632 update_power_state(codec, 0x34, AC_PWRST_D3);
3e95b9ab 1633 } else {
054d867e
TI
1634 update_power_state(codec, 0x14, AC_PWRST_D0);
1635 update_power_state(codec, 0x34, AC_PWRST_D0);
3e95b9ab
LW
1636 }
1637
1638
1639 /* Mono Out */
1640 /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
1641 present = snd_hda_jack_detect(codec, 0x28);
1642
1643 parm = AC_PWRST_D3;
1644 set_pin_power_state(codec, 0x31, &parm);
1645 if (present) {
054d867e
TI
1646 update_power_state(codec, 0x1c, AC_PWRST_D3);
1647 update_power_state(codec, 0x3c, AC_PWRST_D3);
1648 update_power_state(codec, 0x3e, AC_PWRST_D3);
3e95b9ab 1649 } else {
054d867e
TI
1650 update_power_state(codec, 0x1c, AC_PWRST_D0);
1651 update_power_state(codec, 0x3c, AC_PWRST_D0);
1652 update_power_state(codec, 0x3e, AC_PWRST_D0);
3e95b9ab
LW
1653 }
1654
1655 /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
1656 parm = AC_PWRST_D3;
1657 set_pin_power_state(codec, 0x33, &parm);
054d867e
TI
1658 update_power_state(codec, 0x1d, parm);
1659 update_power_state(codec, 0x3d, parm);
3e95b9ab
LW
1660
1661}
ab6734e7
LW
1662
1663/* patch for vt1812 */
1664static int patch_vt1812(struct hda_codec *codec)
1665{
1666 struct via_spec *spec;
1667 int err;
1668
1669 /* create a codec specific record */
5b0cb1d8 1670 spec = via_new_spec(codec);
ab6734e7
LW
1671 if (spec == NULL)
1672 return -ENOMEM;
1673
b3f6008f 1674 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1675 override_mic_boost(codec, 0x2b, 0, 3, 40);
1676 override_mic_boost(codec, 0x29, 0, 3, 40);
30b45033 1677 add_secret_dac_path(codec);
620e2b28 1678
ab6734e7 1679 /* automatic parse from the BIOS config */
12daef65 1680 err = via_parse_auto_config(codec);
ab6734e7
LW
1681 if (err < 0) {
1682 via_free(codec);
1683 return err;
ab6734e7
LW
1684 }
1685
096a8854 1686 spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs;
ab6734e7 1687
ab6734e7
LW
1688 codec->patch_ops = via_patch_ops;
1689
3e95b9ab 1690 spec->set_widgets_power_state = set_widgets_power_state_vt1812;
ab6734e7
LW
1691 return 0;
1692}
1693
43737e0a
LW
1694/* patch for vt3476 */
1695
1696static const struct hda_verb vt3476_init_verbs[] = {
1697 /* Enable DMic 8/16/32K */
1698 {0x1, 0xF7B, 0x30},
1699 /* Enable Boost Volume backdoor */
1700 {0x1, 0xFB9, 0x20},
1701 /* Enable AOW-MW9 path */
1702 {0x1, 0xFB8, 0x10},
1703 { }
1704};
1705
1706static void set_widgets_power_state_vt3476(struct hda_codec *codec)
1707{
1708 struct via_spec *spec = codec->spec;
1709 int imux_is_smixer;
1710 unsigned int parm, parm2;
1711 /* MUX10 (1eh) = stereo mixer */
1712 imux_is_smixer =
1713 snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 4;
1714 /* inputs */
1715 /* PW 5/6/7 (29h/2ah/2bh) */
1716 parm = AC_PWRST_D3;
1717 set_pin_power_state(codec, 0x29, &parm);
1718 set_pin_power_state(codec, 0x2a, &parm);
1719 set_pin_power_state(codec, 0x2b, &parm);
1720 if (imux_is_smixer)
1721 parm = AC_PWRST_D0;
1722 /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
1723 update_power_state(codec, 0x1e, parm);
1724 update_power_state(codec, 0x1f, parm);
1725 update_power_state(codec, 0x10, parm);
1726 update_power_state(codec, 0x11, parm);
1727
1728 /* outputs */
1729 /* PW3 (27h), MW3(37h), AOW3 (bh) */
1730 if (spec->codec_type == VT1705CF) {
1731 parm = AC_PWRST_D3;
1732 update_power_state(codec, 0x27, parm);
1733 update_power_state(codec, 0x37, parm);
1734 } else {
1735 parm = AC_PWRST_D3;
1736 set_pin_power_state(codec, 0x27, &parm);
1737 update_power_state(codec, 0x37, parm);
1738 }
1739
1740 /* PW2 (26h), MW2(36h), AOW2 (ah) */
1741 parm = AC_PWRST_D3;
1742 set_pin_power_state(codec, 0x26, &parm);
1743 update_power_state(codec, 0x36, parm);
b3f6008f 1744 if (smart51_enabled(codec)) {
43737e0a
LW
1745 /* PW7(2bh), MW7(3bh), MUX7(1Bh) */
1746 set_pin_power_state(codec, 0x2b, &parm);
1747 update_power_state(codec, 0x3b, parm);
1748 update_power_state(codec, 0x1b, parm);
1749 }
1750 update_conv_power_state(codec, 0xa, parm, 2);
1751
1752 /* PW1 (25h), MW1(35h), AOW1 (9h) */
1753 parm = AC_PWRST_D3;
1754 set_pin_power_state(codec, 0x25, &parm);
1755 update_power_state(codec, 0x35, parm);
b3f6008f 1756 if (smart51_enabled(codec)) {
43737e0a
LW
1757 /* PW6(2ah), MW6(3ah), MUX6(1ah) */
1758 set_pin_power_state(codec, 0x2a, &parm);
1759 update_power_state(codec, 0x3a, parm);
1760 update_power_state(codec, 0x1a, parm);
1761 }
1762 update_conv_power_state(codec, 0x9, parm, 1);
1763
1764 /* PW4 (28h), MW4 (38h), MUX4(18h), AOW3(bh)/AOW0(8h) */
1765 parm = AC_PWRST_D3;
1766 set_pin_power_state(codec, 0x28, &parm);
1767 update_power_state(codec, 0x38, parm);
1768 update_power_state(codec, 0x18, parm);
b3f6008f 1769 if (spec->gen.indep_hp_enabled)
43737e0a
LW
1770 update_conv_power_state(codec, 0xb, parm, 3);
1771 parm2 = parm; /* for pin 0x0b */
1772
1773 /* PW0 (24h), MW0(34h), MW9(3fh), AOW0 (8h) */
1774 parm = AC_PWRST_D3;
1775 set_pin_power_state(codec, 0x24, &parm);
1776 update_power_state(codec, 0x34, parm);
b3f6008f 1777 if (!spec->gen.indep_hp_enabled && parm2 != AC_PWRST_D3)
43737e0a
LW
1778 parm = parm2;
1779 update_conv_power_state(codec, 0x8, parm, 0);
1780 /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
1781 update_power_state(codec, 0x3f, imux_is_smixer ? AC_PWRST_D0 : parm);
1782}
1783
1784static int patch_vt3476(struct hda_codec *codec)
1785{
1786 struct via_spec *spec;
1787 int err;
1788
1789 /* create a codec specific record */
1790 spec = via_new_spec(codec);
1791 if (spec == NULL)
1792 return -ENOMEM;
1793
b3f6008f 1794 spec->gen.mixer_nid = 0x3f;
43737e0a
LW
1795 add_secret_dac_path(codec);
1796
1797 /* automatic parse from the BIOS config */
1798 err = via_parse_auto_config(codec);
1799 if (err < 0) {
1800 via_free(codec);
1801 return err;
1802 }
1803
1804 spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs;
1805
1806 codec->patch_ops = via_patch_ops;
1807
1808 spec->set_widgets_power_state = set_widgets_power_state_vt3476;
1809
1810 return 0;
1811}
1812
c577b8a1
JC
1813/*
1814 * patch entries
1815 */
90dd48a1 1816static const struct hda_codec_preset snd_hda_preset_via[] = {
3218c178
TI
1817 { .id = 0x11061708, .name = "VT1708", .patch = patch_vt1708},
1818 { .id = 0x11061709, .name = "VT1708", .patch = patch_vt1708},
1819 { .id = 0x1106170a, .name = "VT1708", .patch = patch_vt1708},
1820 { .id = 0x1106170b, .name = "VT1708", .patch = patch_vt1708},
1821 { .id = 0x1106e710, .name = "VT1709 10-Ch",
ddd304d8 1822 .patch = patch_vt1709},
3218c178 1823 { .id = 0x1106e711, .name = "VT1709 10-Ch",
ddd304d8 1824 .patch = patch_vt1709},
3218c178 1825 { .id = 0x1106e712, .name = "VT1709 10-Ch",
ddd304d8 1826 .patch = patch_vt1709},
3218c178 1827 { .id = 0x1106e713, .name = "VT1709 10-Ch",
ddd304d8 1828 .patch = patch_vt1709},
3218c178 1829 { .id = 0x1106e714, .name = "VT1709 6-Ch",
ddd304d8 1830 .patch = patch_vt1709},
3218c178 1831 { .id = 0x1106e715, .name = "VT1709 6-Ch",
ddd304d8 1832 .patch = patch_vt1709},
3218c178 1833 { .id = 0x1106e716, .name = "VT1709 6-Ch",
ddd304d8 1834 .patch = patch_vt1709},
3218c178 1835 { .id = 0x1106e717, .name = "VT1709 6-Ch",
ddd304d8 1836 .patch = patch_vt1709},
3218c178 1837 { .id = 0x1106e720, .name = "VT1708B 8-Ch",
ddd304d8 1838 .patch = patch_vt1708B},
3218c178 1839 { .id = 0x1106e721, .name = "VT1708B 8-Ch",
ddd304d8 1840 .patch = patch_vt1708B},
3218c178 1841 { .id = 0x1106e722, .name = "VT1708B 8-Ch",
ddd304d8 1842 .patch = patch_vt1708B},
3218c178 1843 { .id = 0x1106e723, .name = "VT1708B 8-Ch",
ddd304d8 1844 .patch = patch_vt1708B},
3218c178 1845 { .id = 0x1106e724, .name = "VT1708B 4-Ch",
ddd304d8 1846 .patch = patch_vt1708B},
3218c178 1847 { .id = 0x1106e725, .name = "VT1708B 4-Ch",
ddd304d8 1848 .patch = patch_vt1708B},
3218c178 1849 { .id = 0x1106e726, .name = "VT1708B 4-Ch",
ddd304d8 1850 .patch = patch_vt1708B},
3218c178 1851 { .id = 0x1106e727, .name = "VT1708B 4-Ch",
ddd304d8 1852 .patch = patch_vt1708B},
3218c178 1853 { .id = 0x11060397, .name = "VT1708S",
d949cac1 1854 .patch = patch_vt1708S},
3218c178 1855 { .id = 0x11061397, .name = "VT1708S",
d949cac1 1856 .patch = patch_vt1708S},
3218c178 1857 { .id = 0x11062397, .name = "VT1708S",
d949cac1 1858 .patch = patch_vt1708S},
3218c178 1859 { .id = 0x11063397, .name = "VT1708S",
d949cac1 1860 .patch = patch_vt1708S},
bc92df7f 1861 { .id = 0x11064397, .name = "VT1705",
d949cac1 1862 .patch = patch_vt1708S},
3218c178 1863 { .id = 0x11065397, .name = "VT1708S",
d949cac1 1864 .patch = patch_vt1708S},
3218c178 1865 { .id = 0x11066397, .name = "VT1708S",
d949cac1 1866 .patch = patch_vt1708S},
3218c178 1867 { .id = 0x11067397, .name = "VT1708S",
d949cac1 1868 .patch = patch_vt1708S},
3218c178 1869 { .id = 0x11060398, .name = "VT1702",
d949cac1 1870 .patch = patch_vt1702},
3218c178 1871 { .id = 0x11061398, .name = "VT1702",
d949cac1 1872 .patch = patch_vt1702},
3218c178 1873 { .id = 0x11062398, .name = "VT1702",
d949cac1 1874 .patch = patch_vt1702},
3218c178 1875 { .id = 0x11063398, .name = "VT1702",
d949cac1 1876 .patch = patch_vt1702},
3218c178 1877 { .id = 0x11064398, .name = "VT1702",
d949cac1 1878 .patch = patch_vt1702},
3218c178 1879 { .id = 0x11065398, .name = "VT1702",
d949cac1 1880 .patch = patch_vt1702},
3218c178 1881 { .id = 0x11066398, .name = "VT1702",
d949cac1 1882 .patch = patch_vt1702},
3218c178 1883 { .id = 0x11067398, .name = "VT1702",
d949cac1 1884 .patch = patch_vt1702},
eb7188ca
LW
1885 { .id = 0x11060428, .name = "VT1718S",
1886 .patch = patch_vt1718S},
1887 { .id = 0x11064428, .name = "VT1718S",
1888 .patch = patch_vt1718S},
bb3c6bfc
LW
1889 { .id = 0x11060441, .name = "VT2020",
1890 .patch = patch_vt1718S},
1891 { .id = 0x11064441, .name = "VT1828S",
1892 .patch = patch_vt1718S},
f3db423d
LW
1893 { .id = 0x11060433, .name = "VT1716S",
1894 .patch = patch_vt1716S},
1895 { .id = 0x1106a721, .name = "VT1716S",
1896 .patch = patch_vt1716S},
25eaba2f
LW
1897 { .id = 0x11060438, .name = "VT2002P", .patch = patch_vt2002P},
1898 { .id = 0x11064438, .name = "VT2002P", .patch = patch_vt2002P},
ab6734e7 1899 { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812},
36dd5c4a
LW
1900 { .id = 0x11060440, .name = "VT1818S",
1901 .patch = patch_vt1708S},
11890956
LW
1902 { .id = 0x11060446, .name = "VT1802",
1903 .patch = patch_vt2002P},
1904 { .id = 0x11068446, .name = "VT1802",
1905 .patch = patch_vt2002P},
43737e0a
LW
1906 { .id = 0x11064760, .name = "VT1705CF",
1907 .patch = patch_vt3476},
6121b84a
LW
1908 { .id = 0x11064761, .name = "VT1708SCE",
1909 .patch = patch_vt3476},
1910 { .id = 0x11064762, .name = "VT1808",
1911 .patch = patch_vt3476},
c577b8a1
JC
1912 {} /* terminator */
1913};
1289e9e8
TI
1914
1915MODULE_ALIAS("snd-hda-codec-id:1106*");
1916
1917static struct hda_codec_preset_list via_list = {
1918 .preset = snd_hda_preset_via,
1919 .owner = THIS_MODULE,
1920};
1921
1922MODULE_LICENSE("GPL");
1923MODULE_DESCRIPTION("VIA HD-audio codec");
1924
1925static int __init patch_via_init(void)
1926{
1927 return snd_hda_add_codec_preset(&via_list);
1928}
1929
1930static void __exit patch_via_exit(void)
1931{
1932 snd_hda_delete_codec_preset(&via_list);
1933}
1934
1935module_init(patch_via_init)
1936module_exit(patch_via_exit)