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