Merge branch 'for-linus' into for-next
[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 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{
913 snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
914 (offset << AC_AMPCAP_OFFSET_SHIFT) |
915 (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
916 (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
917 (0 << AC_AMPCAP_MUTE_SHIFT));
918}
919
d949cac1
HW
920static int patch_vt1708S(struct hda_codec *codec)
921{
922 struct via_spec *spec;
923 int err;
924
925 /* create a codec specific record */
5b0cb1d8 926 spec = via_new_spec(codec);
d949cac1
HW
927 if (spec == NULL)
928 return -ENOMEM;
929
b3f6008f 930 spec->gen.mixer_nid = 0x16;
d7a99cce
TI
931 override_mic_boost(codec, 0x1a, 0, 3, 40);
932 override_mic_boost(codec, 0x1e, 0, 3, 40);
620e2b28 933
518bf3ba
LW
934 /* correct names for VT1708BCE */
935 if (get_codec_type(codec) == VT1708BCE) {
936 kfree(codec->chip_name);
937 codec->chip_name = kstrdup("VT1708BCE", GFP_KERNEL);
938 snprintf(codec->bus->card->mixername,
939 sizeof(codec->bus->card->mixername),
940 "%s %s", codec->vendor_name, codec->chip_name);
970f630f 941 }
bc92df7f
LW
942 /* correct names for VT1705 */
943 if (codec->vendor_id == 0x11064397) {
944 kfree(codec->chip_name);
945 codec->chip_name = kstrdup("VT1705", GFP_KERNEL);
946 snprintf(codec->bus->card->mixername,
947 sizeof(codec->bus->card->mixername),
948 "%s %s", codec->vendor_name, codec->chip_name);
949 }
b3f6008f
TI
950
951 /* automatic parse from the BIOS config */
952 err = via_parse_auto_config(codec);
953 if (err < 0) {
954 via_free(codec);
955 return err;
956 }
957
958 spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs;
959
960 codec->patch_ops = via_patch_ops;
961
3e95b9ab 962 spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
d949cac1
HW
963 return 0;
964}
965
966/* Patch for VT1702 */
967
096a8854 968static const struct hda_verb vt1702_init_verbs[] = {
bc7e7e5c
LW
969 /* mixer enable */
970 {0x1, 0xF88, 0x3},
971 /* GPIO 0~2 */
972 {0x1, 0xF82, 0x3F},
d949cac1
HW
973 { }
974};
975
3e95b9ab
LW
976static void set_widgets_power_state_vt1702(struct hda_codec *codec)
977{
978 int imux_is_smixer =
979 snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
980 unsigned int parm;
981 /* inputs */
982 /* PW 1/2/5 (14h/15h/18h) */
983 parm = AC_PWRST_D3;
984 set_pin_power_state(codec, 0x14, &parm);
985 set_pin_power_state(codec, 0x15, &parm);
986 set_pin_power_state(codec, 0x18, &parm);
987 if (imux_is_smixer)
988 parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
989 /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
054d867e
TI
990 update_power_state(codec, 0x13, parm);
991 update_power_state(codec, 0x12, parm);
992 update_power_state(codec, 0x1f, parm);
993 update_power_state(codec, 0x20, parm);
3e95b9ab
LW
994
995 /* outputs */
996 /* PW 3/4 (16h/17h) */
997 parm = AC_PWRST_D3;
998 set_pin_power_state(codec, 0x17, &parm);
999 set_pin_power_state(codec, 0x16, &parm);
1000 /* MW0 (1ah), AOW 0/1 (10h/1dh) */
054d867e
TI
1001 update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm);
1002 update_power_state(codec, 0x10, parm);
1003 update_power_state(codec, 0x1d, parm);
3e95b9ab
LW
1004}
1005
d949cac1
HW
1006static int patch_vt1702(struct hda_codec *codec)
1007{
1008 struct via_spec *spec;
1009 int err;
d949cac1
HW
1010
1011 /* create a codec specific record */
5b0cb1d8 1012 spec = via_new_spec(codec);
d949cac1
HW
1013 if (spec == NULL)
1014 return -ENOMEM;
1015
b3f6008f 1016 spec->gen.mixer_nid = 0x1a;
620e2b28 1017
12daef65
TI
1018 /* limit AA path volume to 0 dB */
1019 snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
1020 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
1021 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
1022 (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
1023 (1 << AC_AMPCAP_MUTE_SHIFT));
1024
d949cac1 1025 /* automatic parse from the BIOS config */
12daef65 1026 err = via_parse_auto_config(codec);
d949cac1
HW
1027 if (err < 0) {
1028 via_free(codec);
1029 return err;
d949cac1
HW
1030 }
1031
096a8854 1032 spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs;
d949cac1 1033
d949cac1
HW
1034 codec->patch_ops = via_patch_ops;
1035
3e95b9ab 1036 spec->set_widgets_power_state = set_widgets_power_state_vt1702;
d949cac1
HW
1037 return 0;
1038}
1039
eb7188ca
LW
1040/* Patch for VT1718S */
1041
096a8854 1042static const struct hda_verb vt1718S_init_verbs[] = {
4ab2d53a
LW
1043 /* Enable MW0 adjust Gain 5 */
1044 {0x1, 0xfb2, 0x10},
eb7188ca
LW
1045 /* Enable Boost Volume backdoor */
1046 {0x1, 0xf88, 0x8},
5d41762a 1047
eb7188ca
LW
1048 { }
1049};
1050
3e95b9ab
LW
1051static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
1052{
1053 struct via_spec *spec = codec->spec;
1054 int imux_is_smixer;
6162552b 1055 unsigned int parm, parm2;
3e95b9ab
LW
1056 /* MUX6 (1eh) = stereo mixer */
1057 imux_is_smixer =
1058 snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
1059 /* inputs */
1060 /* PW 5/6/7 (29h/2ah/2bh) */
1061 parm = AC_PWRST_D3;
1062 set_pin_power_state(codec, 0x29, &parm);
1063 set_pin_power_state(codec, 0x2a, &parm);
1064 set_pin_power_state(codec, 0x2b, &parm);
1065 if (imux_is_smixer)
1066 parm = AC_PWRST_D0;
1067 /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
054d867e
TI
1068 update_power_state(codec, 0x1e, parm);
1069 update_power_state(codec, 0x1f, parm);
1070 update_power_state(codec, 0x10, parm);
1071 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1072
1073 /* outputs */
1074 /* PW3 (27h), MW2 (1ah), AOW3 (bh) */
1075 parm = AC_PWRST_D3;
1076 set_pin_power_state(codec, 0x27, &parm);
054d867e 1077 update_power_state(codec, 0x1a, parm);
6162552b 1078 parm2 = parm; /* for pin 0x0b */
3e95b9ab
LW
1079
1080 /* PW2 (26h), AOW2 (ah) */
1081 parm = AC_PWRST_D3;
1082 set_pin_power_state(codec, 0x26, &parm);
b3f6008f 1083 if (smart51_enabled(codec))
3e95b9ab 1084 set_pin_power_state(codec, 0x2b, &parm);
054d867e 1085 update_power_state(codec, 0xa, parm);
3e95b9ab
LW
1086
1087 /* PW0 (24h), AOW0 (8h) */
1088 parm = AC_PWRST_D3;
1089 set_pin_power_state(codec, 0x24, &parm);
b3f6008f 1090 if (!spec->gen.indep_hp_enabled) /* check for redirected HP */
3e95b9ab 1091 set_pin_power_state(codec, 0x28, &parm);
054d867e 1092 update_power_state(codec, 0x8, parm);
b3f6008f 1093 if (!spec->gen.indep_hp_enabled && parm2 != AC_PWRST_D3)
6162552b
TI
1094 parm = parm2;
1095 update_power_state(codec, 0xb, parm);
3e95b9ab 1096 /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
054d867e 1097 update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm);
3e95b9ab
LW
1098
1099 /* PW1 (25h), AOW1 (9h) */
1100 parm = AC_PWRST_D3;
1101 set_pin_power_state(codec, 0x25, &parm);
b3f6008f 1102 if (smart51_enabled(codec))
3e95b9ab 1103 set_pin_power_state(codec, 0x2a, &parm);
054d867e 1104 update_power_state(codec, 0x9, parm);
3e95b9ab 1105
b3f6008f 1106 if (spec->gen.indep_hp_enabled) {
3e95b9ab
LW
1107 /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
1108 parm = AC_PWRST_D3;
1109 set_pin_power_state(codec, 0x28, &parm);
054d867e
TI
1110 update_power_state(codec, 0x1b, parm);
1111 update_power_state(codec, 0x34, parm);
1112 update_power_state(codec, 0xc, parm);
3e95b9ab
LW
1113 }
1114}
1115
30b45033
TI
1116/* Add a connection to the primary DAC from AA-mixer for some codecs
1117 * This isn't listed from the raw info, but the chip has a secret connection.
1118 */
1119static int add_secret_dac_path(struct hda_codec *codec)
1120{
1121 struct via_spec *spec = codec->spec;
1122 int i, nums;
1123 hda_nid_t conn[8];
1124 hda_nid_t nid;
1125
b3f6008f 1126 if (!spec->gen.mixer_nid)
30b45033 1127 return 0;
b3f6008f 1128 nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
30b45033
TI
1129 ARRAY_SIZE(conn) - 1);
1130 for (i = 0; i < nums; i++) {
1131 if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
1132 return 0;
1133 }
1134
1135 /* find the primary DAC and add to the connection list */
1136 nid = codec->start_nid;
1137 for (i = 0; i < codec->num_nodes; i++, nid++) {
1138 unsigned int caps = get_wcaps(codec, nid);
1139 if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
1140 !(caps & AC_WCAP_DIGITAL)) {
1141 conn[nums++] = nid;
1142 return snd_hda_override_conn_list(codec,
b3f6008f 1143 spec->gen.mixer_nid,
30b45033
TI
1144 nums, conn);
1145 }
1146 }
1147 return 0;
1148}
1149
1150
eb7188ca
LW
1151static int patch_vt1718S(struct hda_codec *codec)
1152{
1153 struct via_spec *spec;
1154 int err;
1155
1156 /* create a codec specific record */
5b0cb1d8 1157 spec = via_new_spec(codec);
eb7188ca
LW
1158 if (spec == NULL)
1159 return -ENOMEM;
1160
b3f6008f 1161 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1162 override_mic_boost(codec, 0x2b, 0, 3, 40);
1163 override_mic_boost(codec, 0x29, 0, 3, 40);
30b45033 1164 add_secret_dac_path(codec);
620e2b28 1165
eb7188ca 1166 /* automatic parse from the BIOS config */
12daef65 1167 err = via_parse_auto_config(codec);
eb7188ca
LW
1168 if (err < 0) {
1169 via_free(codec);
1170 return err;
eb7188ca
LW
1171 }
1172
096a8854 1173 spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs;
eb7188ca 1174
eb7188ca
LW
1175 codec->patch_ops = via_patch_ops;
1176
3e95b9ab
LW
1177 spec->set_widgets_power_state = set_widgets_power_state_vt1718S;
1178
eb7188ca
LW
1179 return 0;
1180}
f3db423d
LW
1181
1182/* Patch for VT1716S */
1183
1184static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
1185 struct snd_ctl_elem_info *uinfo)
1186{
1187 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1188 uinfo->count = 1;
1189 uinfo->value.integer.min = 0;
1190 uinfo->value.integer.max = 1;
1191 return 0;
1192}
1193
1194static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
1195 struct snd_ctl_elem_value *ucontrol)
1196{
1197 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1198 int index = 0;
1199
1200 index = snd_hda_codec_read(codec, 0x26, 0,
1201 AC_VERB_GET_CONNECT_SEL, 0);
1202 if (index != -1)
1203 *ucontrol->value.integer.value = index;
1204
1205 return 0;
1206}
1207
1208static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
1209 struct snd_ctl_elem_value *ucontrol)
1210{
1211 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1212 struct via_spec *spec = codec->spec;
1213 int index = *ucontrol->value.integer.value;
1214
1215 snd_hda_codec_write(codec, 0x26, 0,
1216 AC_VERB_SET_CONNECT_SEL, index);
1217 spec->dmic_enabled = index;
3e95b9ab 1218 set_widgets_power_state(codec);
f3db423d
LW
1219 return 1;
1220}
1221
90dd48a1 1222static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
f3db423d
LW
1223 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT),
1224 {
1225 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1226 .name = "Digital Mic Capture Switch",
5b0cb1d8 1227 .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
f3db423d
LW
1228 .count = 1,
1229 .info = vt1716s_dmic_info,
1230 .get = vt1716s_dmic_get,
1231 .put = vt1716s_dmic_put,
1232 },
1233 {} /* end */
1234};
1235
1236
1237/* mono-out mixer elements */
90dd48a1 1238static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
f3db423d
LW
1239 HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT),
1240 { } /* end */
1241};
1242
096a8854 1243static const struct hda_verb vt1716S_init_verbs[] = {
f3db423d
LW
1244 /* Enable Boost Volume backdoor */
1245 {0x1, 0xf8a, 0x80},
1246 /* don't bybass mixer */
1247 {0x1, 0xf88, 0xc0},
1248 /* Enable mono output */
1249 {0x1, 0xf90, 0x08},
1250 { }
1251};
1252
3e95b9ab
LW
1253static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
1254{
1255 struct via_spec *spec = codec->spec;
1256 int imux_is_smixer;
1257 unsigned int parm;
1258 unsigned int mono_out, present;
1259 /* SW0 (17h) = stereo mixer */
1260 imux_is_smixer =
1261 (snd_hda_codec_read(codec, 0x17, 0,
1262 AC_VERB_GET_CONNECT_SEL, 0x00) == 5);
1263 /* inputs */
1264 /* PW 1/2/5 (1ah/1bh/1eh) */
1265 parm = AC_PWRST_D3;
1266 set_pin_power_state(codec, 0x1a, &parm);
1267 set_pin_power_state(codec, 0x1b, &parm);
1268 set_pin_power_state(codec, 0x1e, &parm);
1269 if (imux_is_smixer)
1270 parm = AC_PWRST_D0;
1271 /* SW0 (17h), AIW0(13h) */
054d867e
TI
1272 update_power_state(codec, 0x17, parm);
1273 update_power_state(codec, 0x13, parm);
3e95b9ab
LW
1274
1275 parm = AC_PWRST_D3;
1276 set_pin_power_state(codec, 0x1e, &parm);
1277 /* PW11 (22h) */
1278 if (spec->dmic_enabled)
1279 set_pin_power_state(codec, 0x22, &parm);
1280 else
054d867e 1281 update_power_state(codec, 0x22, AC_PWRST_D3);
3e95b9ab
LW
1282
1283 /* SW2(26h), AIW1(14h) */
054d867e
TI
1284 update_power_state(codec, 0x26, parm);
1285 update_power_state(codec, 0x14, parm);
3e95b9ab
LW
1286
1287 /* outputs */
1288 /* PW0 (19h), SW1 (18h), AOW1 (11h) */
1289 parm = AC_PWRST_D3;
1290 set_pin_power_state(codec, 0x19, &parm);
1291 /* Smart 5.1 PW2(1bh) */
b3f6008f 1292 if (smart51_enabled(codec))
3e95b9ab 1293 set_pin_power_state(codec, 0x1b, &parm);
054d867e
TI
1294 update_power_state(codec, 0x18, parm);
1295 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1296
1297 /* PW7 (23h), SW3 (27h), AOW3 (25h) */
1298 parm = AC_PWRST_D3;
1299 set_pin_power_state(codec, 0x23, &parm);
1300 /* Smart 5.1 PW1(1ah) */
b3f6008f 1301 if (smart51_enabled(codec))
3e95b9ab 1302 set_pin_power_state(codec, 0x1a, &parm);
054d867e 1303 update_power_state(codec, 0x27, parm);
3e95b9ab
LW
1304
1305 /* Smart 5.1 PW5(1eh) */
b3f6008f 1306 if (smart51_enabled(codec))
3e95b9ab 1307 set_pin_power_state(codec, 0x1e, &parm);
054d867e 1308 update_power_state(codec, 0x25, parm);
3e95b9ab
LW
1309
1310 /* Mono out */
1311 /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
1312 present = snd_hda_jack_detect(codec, 0x1c);
1313
1314 if (present)
1315 mono_out = 0;
1316 else {
1317 present = snd_hda_jack_detect(codec, 0x1d);
b3f6008f 1318 if (!spec->gen.indep_hp_enabled && present)
3e95b9ab
LW
1319 mono_out = 0;
1320 else
1321 mono_out = 1;
1322 }
1323 parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
054d867e
TI
1324 update_power_state(codec, 0x28, parm);
1325 update_power_state(codec, 0x29, parm);
1326 update_power_state(codec, 0x2a, parm);
3e95b9ab
LW
1327
1328 /* PW 3/4 (1ch/1dh) */
1329 parm = AC_PWRST_D3;
1330 set_pin_power_state(codec, 0x1c, &parm);
1331 set_pin_power_state(codec, 0x1d, &parm);
1332 /* HP Independent Mode, power on AOW3 */
b3f6008f 1333 if (spec->gen.indep_hp_enabled)
054d867e 1334 update_power_state(codec, 0x25, parm);
3e95b9ab
LW
1335
1336 /* force to D0 for internal Speaker */
1337 /* MW0 (16h), AOW0 (10h) */
054d867e
TI
1338 update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
1339 update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm);
3e95b9ab
LW
1340}
1341
f3db423d
LW
1342static int patch_vt1716S(struct hda_codec *codec)
1343{
1344 struct via_spec *spec;
1345 int err;
1346
1347 /* create a codec specific record */
5b0cb1d8 1348 spec = via_new_spec(codec);
f3db423d
LW
1349 if (spec == NULL)
1350 return -ENOMEM;
1351
b3f6008f 1352 spec->gen.mixer_nid = 0x16;
d7a99cce
TI
1353 override_mic_boost(codec, 0x1a, 0, 3, 40);
1354 override_mic_boost(codec, 0x1e, 0, 3, 40);
620e2b28 1355
f3db423d 1356 /* automatic parse from the BIOS config */
12daef65 1357 err = via_parse_auto_config(codec);
f3db423d
LW
1358 if (err < 0) {
1359 via_free(codec);
1360 return err;
f3db423d
LW
1361 }
1362
096a8854 1363 spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs;
f3db423d 1364
b3f6008f 1365 spec->mixers[spec->num_mixers++] = vt1716s_dmic_mixer;
f3db423d
LW
1366 spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer;
1367
1368 codec->patch_ops = via_patch_ops;
1369
3e95b9ab 1370 spec->set_widgets_power_state = set_widgets_power_state_vt1716S;
f3db423d
LW
1371 return 0;
1372}
25eaba2f
LW
1373
1374/* for vt2002P */
1375
096a8854 1376static const struct hda_verb vt2002P_init_verbs[] = {
eadb9a80
LW
1377 /* Class-D speaker related verbs */
1378 {0x1, 0xfe0, 0x4},
1379 {0x1, 0xfe9, 0x80},
1380 {0x1, 0xfe2, 0x22},
25eaba2f
LW
1381 /* Enable Boost Volume backdoor */
1382 {0x1, 0xfb9, 0x24},
25eaba2f
LW
1383 /* Enable AOW0 to MW9 */
1384 {0x1, 0xfb8, 0x88},
1385 { }
1386};
4a918ffe 1387
096a8854 1388static const struct hda_verb vt1802_init_verbs[] = {
11890956
LW
1389 /* Enable Boost Volume backdoor */
1390 {0x1, 0xfb9, 0x24},
11890956
LW
1391 /* Enable AOW0 to MW9 */
1392 {0x1, 0xfb8, 0x88},
1393 { }
1394};
25eaba2f 1395
3e95b9ab
LW
1396static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
1397{
1398 struct via_spec *spec = codec->spec;
1399 int imux_is_smixer;
1400 unsigned int parm;
1401 unsigned int present;
1402 /* MUX9 (1eh) = stereo mixer */
1403 imux_is_smixer =
1404 snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
1405 /* inputs */
1406 /* PW 5/6/7 (29h/2ah/2bh) */
1407 parm = AC_PWRST_D3;
1408 set_pin_power_state(codec, 0x29, &parm);
1409 set_pin_power_state(codec, 0x2a, &parm);
1410 set_pin_power_state(codec, 0x2b, &parm);
1411 parm = AC_PWRST_D0;
1412 /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
054d867e
TI
1413 update_power_state(codec, 0x1e, parm);
1414 update_power_state(codec, 0x1f, parm);
1415 update_power_state(codec, 0x10, parm);
1416 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1417
1418 /* outputs */
1419 /* AOW0 (8h)*/
054d867e 1420 update_power_state(codec, 0x8, parm);
3e95b9ab 1421
11890956
LW
1422 if (spec->codec_type == VT1802) {
1423 /* PW4 (28h), MW4 (18h), MUX4(38h) */
1424 parm = AC_PWRST_D3;
1425 set_pin_power_state(codec, 0x28, &parm);
054d867e
TI
1426 update_power_state(codec, 0x18, parm);
1427 update_power_state(codec, 0x38, parm);
11890956
LW
1428 } else {
1429 /* PW4 (26h), MW4 (1ch), MUX4(37h) */
1430 parm = AC_PWRST_D3;
1431 set_pin_power_state(codec, 0x26, &parm);
054d867e
TI
1432 update_power_state(codec, 0x1c, parm);
1433 update_power_state(codec, 0x37, parm);
11890956 1434 }
3e95b9ab 1435
11890956
LW
1436 if (spec->codec_type == VT1802) {
1437 /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
1438 parm = AC_PWRST_D3;
1439 set_pin_power_state(codec, 0x25, &parm);
054d867e
TI
1440 update_power_state(codec, 0x15, parm);
1441 update_power_state(codec, 0x35, parm);
11890956
LW
1442 } else {
1443 /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
1444 parm = AC_PWRST_D3;
1445 set_pin_power_state(codec, 0x25, &parm);
054d867e
TI
1446 update_power_state(codec, 0x19, parm);
1447 update_power_state(codec, 0x35, parm);
11890956 1448 }
3e95b9ab 1449
b3f6008f 1450 if (spec->gen.indep_hp_enabled)
054d867e 1451 update_power_state(codec, 0x9, AC_PWRST_D0);
3e95b9ab
LW
1452
1453 /* Class-D */
1454 /* PW0 (24h), MW0(18h/14h), MUX0(34h) */
1455 present = snd_hda_jack_detect(codec, 0x25);
1456
1457 parm = AC_PWRST_D3;
1458 set_pin_power_state(codec, 0x24, &parm);
1459 parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
11890956 1460 if (spec->codec_type == VT1802)
054d867e 1461 update_power_state(codec, 0x14, parm);
11890956 1462 else
054d867e
TI
1463 update_power_state(codec, 0x18, parm);
1464 update_power_state(codec, 0x34, parm);
3e95b9ab
LW
1465
1466 /* Mono Out */
1467 present = snd_hda_jack_detect(codec, 0x26);
1468
1469 parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
11890956
LW
1470 if (spec->codec_type == VT1802) {
1471 /* PW15 (33h), MW8(1ch), MUX8(3ch) */
054d867e
TI
1472 update_power_state(codec, 0x33, parm);
1473 update_power_state(codec, 0x1c, parm);
1474 update_power_state(codec, 0x3c, parm);
11890956
LW
1475 } else {
1476 /* PW15 (31h), MW8(17h), MUX8(3bh) */
054d867e
TI
1477 update_power_state(codec, 0x31, parm);
1478 update_power_state(codec, 0x17, parm);
1479 update_power_state(codec, 0x3b, parm);
11890956 1480 }
3e95b9ab
LW
1481 /* MW9 (21h) */
1482 if (imux_is_smixer || !is_aa_path_mute(codec))
054d867e 1483 update_power_state(codec, 0x21, AC_PWRST_D0);
3e95b9ab 1484 else
054d867e 1485 update_power_state(codec, 0x21, AC_PWRST_D3);
3e95b9ab 1486}
25eaba2f 1487
4b527b65
DH
1488/*
1489 * pin fix-up
1490 */
1491enum {
1492 VIA_FIXUP_INTMIC_BOOST,
d5266125 1493 VIA_FIXUP_ASUS_G75,
4b527b65
DH
1494};
1495
1496static void via_fixup_intmic_boost(struct hda_codec *codec,
1497 const struct hda_fixup *fix, int action)
1498{
1499 if (action == HDA_FIXUP_ACT_PRE_PROBE)
1500 override_mic_boost(codec, 0x30, 0, 2, 40);
1501}
1502
1503static const struct hda_fixup via_fixups[] = {
1504 [VIA_FIXUP_INTMIC_BOOST] = {
1505 .type = HDA_FIXUP_FUNC,
1506 .v.func = via_fixup_intmic_boost,
1507 },
d5266125
TI
1508 [VIA_FIXUP_ASUS_G75] = {
1509 .type = HDA_FIXUP_PINS,
1510 .v.pins = (const struct hda_pintbl[]) {
1511 /* set 0x24 and 0x33 as speakers */
1512 { 0x24, 0x991301f0 },
1513 { 0x33, 0x991301f1 }, /* subwoofer */
1514 { }
1515 }
1516 },
4b527b65
DH
1517};
1518
1519static const struct snd_pci_quirk vt2002p_fixups[] = {
d5266125 1520 SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
4b527b65
DH
1521 SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
1522 {}
1523};
1524
ef4da458
TI
1525/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
1526 * Replace this with mixer NID 0x1c
1527 */
1528static void fix_vt1802_connections(struct hda_codec *codec)
1529{
1530 static hda_nid_t conn_24[] = { 0x14, 0x1c };
1531 static hda_nid_t conn_33[] = { 0x1c };
1532
1533 snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
1534 snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
1535}
1536
25eaba2f
LW
1537/* patch for vt2002P */
1538static int patch_vt2002P(struct hda_codec *codec)
1539{
1540 struct via_spec *spec;
1541 int err;
1542
1543 /* create a codec specific record */
5b0cb1d8 1544 spec = via_new_spec(codec);
25eaba2f
LW
1545 if (spec == NULL)
1546 return -ENOMEM;
1547
b3f6008f 1548 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1549 override_mic_boost(codec, 0x2b, 0, 3, 40);
1550 override_mic_boost(codec, 0x29, 0, 3, 40);
ef4da458
TI
1551 if (spec->codec_type == VT1802)
1552 fix_vt1802_connections(codec);
30b45033 1553 add_secret_dac_path(codec);
620e2b28 1554
4b527b65
DH
1555 snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
1556 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1557
25eaba2f 1558 /* automatic parse from the BIOS config */
12daef65 1559 err = via_parse_auto_config(codec);
25eaba2f
LW
1560 if (err < 0) {
1561 via_free(codec);
1562 return err;
25eaba2f
LW
1563 }
1564
11890956 1565 if (spec->codec_type == VT1802)
4a918ffe 1566 spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs;
11890956 1567 else
4a918ffe 1568 spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs;
11890956 1569
25eaba2f
LW
1570 codec->patch_ops = via_patch_ops;
1571
3e95b9ab 1572 spec->set_widgets_power_state = set_widgets_power_state_vt2002P;
25eaba2f
LW
1573 return 0;
1574}
ab6734e7
LW
1575
1576/* for vt1812 */
1577
096a8854 1578static const struct hda_verb vt1812_init_verbs[] = {
ab6734e7
LW
1579 /* Enable Boost Volume backdoor */
1580 {0x1, 0xfb9, 0x24},
ab6734e7
LW
1581 /* Enable AOW0 to MW9 */
1582 {0x1, 0xfb8, 0xa8},
1583 { }
1584};
1585
3e95b9ab
LW
1586static void set_widgets_power_state_vt1812(struct hda_codec *codec)
1587{
1588 struct via_spec *spec = codec->spec;
3e95b9ab
LW
1589 unsigned int parm;
1590 unsigned int present;
3e95b9ab
LW
1591 /* inputs */
1592 /* PW 5/6/7 (29h/2ah/2bh) */
1593 parm = AC_PWRST_D3;
1594 set_pin_power_state(codec, 0x29, &parm);
1595 set_pin_power_state(codec, 0x2a, &parm);
1596 set_pin_power_state(codec, 0x2b, &parm);
1597 parm = AC_PWRST_D0;
1598 /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
054d867e
TI
1599 update_power_state(codec, 0x1e, parm);
1600 update_power_state(codec, 0x1f, parm);
1601 update_power_state(codec, 0x10, parm);
1602 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1603
1604 /* outputs */
1605 /* AOW0 (8h)*/
054d867e 1606 update_power_state(codec, 0x8, AC_PWRST_D0);
3e95b9ab
LW
1607
1608 /* PW4 (28h), MW4 (18h), MUX4(38h) */
1609 parm = AC_PWRST_D3;
1610 set_pin_power_state(codec, 0x28, &parm);
054d867e
TI
1611 update_power_state(codec, 0x18, parm);
1612 update_power_state(codec, 0x38, parm);
3e95b9ab
LW
1613
1614 /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
1615 parm = AC_PWRST_D3;
1616 set_pin_power_state(codec, 0x25, &parm);
054d867e
TI
1617 update_power_state(codec, 0x15, parm);
1618 update_power_state(codec, 0x35, parm);
b3f6008f 1619 if (spec->gen.indep_hp_enabled)
054d867e 1620 update_power_state(codec, 0x9, AC_PWRST_D0);
3e95b9ab
LW
1621
1622 /* Internal Speaker */
1623 /* PW0 (24h), MW0(14h), MUX0(34h) */
1624 present = snd_hda_jack_detect(codec, 0x25);
1625
1626 parm = AC_PWRST_D3;
1627 set_pin_power_state(codec, 0x24, &parm);
1628 if (present) {
054d867e
TI
1629 update_power_state(codec, 0x14, AC_PWRST_D3);
1630 update_power_state(codec, 0x34, AC_PWRST_D3);
3e95b9ab 1631 } else {
054d867e
TI
1632 update_power_state(codec, 0x14, AC_PWRST_D0);
1633 update_power_state(codec, 0x34, AC_PWRST_D0);
3e95b9ab
LW
1634 }
1635
1636
1637 /* Mono Out */
1638 /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
1639 present = snd_hda_jack_detect(codec, 0x28);
1640
1641 parm = AC_PWRST_D3;
1642 set_pin_power_state(codec, 0x31, &parm);
1643 if (present) {
054d867e
TI
1644 update_power_state(codec, 0x1c, AC_PWRST_D3);
1645 update_power_state(codec, 0x3c, AC_PWRST_D3);
1646 update_power_state(codec, 0x3e, AC_PWRST_D3);
3e95b9ab 1647 } else {
054d867e
TI
1648 update_power_state(codec, 0x1c, AC_PWRST_D0);
1649 update_power_state(codec, 0x3c, AC_PWRST_D0);
1650 update_power_state(codec, 0x3e, AC_PWRST_D0);
3e95b9ab
LW
1651 }
1652
1653 /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
1654 parm = AC_PWRST_D3;
1655 set_pin_power_state(codec, 0x33, &parm);
054d867e
TI
1656 update_power_state(codec, 0x1d, parm);
1657 update_power_state(codec, 0x3d, parm);
3e95b9ab
LW
1658
1659}
ab6734e7
LW
1660
1661/* patch for vt1812 */
1662static int patch_vt1812(struct hda_codec *codec)
1663{
1664 struct via_spec *spec;
1665 int err;
1666
1667 /* create a codec specific record */
5b0cb1d8 1668 spec = via_new_spec(codec);
ab6734e7
LW
1669 if (spec == NULL)
1670 return -ENOMEM;
1671
b3f6008f 1672 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1673 override_mic_boost(codec, 0x2b, 0, 3, 40);
1674 override_mic_boost(codec, 0x29, 0, 3, 40);
30b45033 1675 add_secret_dac_path(codec);
620e2b28 1676
ab6734e7 1677 /* automatic parse from the BIOS config */
12daef65 1678 err = via_parse_auto_config(codec);
ab6734e7
LW
1679 if (err < 0) {
1680 via_free(codec);
1681 return err;
ab6734e7
LW
1682 }
1683
096a8854 1684 spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs;
ab6734e7 1685
ab6734e7
LW
1686 codec->patch_ops = via_patch_ops;
1687
3e95b9ab 1688 spec->set_widgets_power_state = set_widgets_power_state_vt1812;
ab6734e7
LW
1689 return 0;
1690}
1691
43737e0a
LW
1692/* patch for vt3476 */
1693
1694static const struct hda_verb vt3476_init_verbs[] = {
1695 /* Enable DMic 8/16/32K */
1696 {0x1, 0xF7B, 0x30},
1697 /* Enable Boost Volume backdoor */
1698 {0x1, 0xFB9, 0x20},
1699 /* Enable AOW-MW9 path */
1700 {0x1, 0xFB8, 0x10},
1701 { }
1702};
1703
1704static void set_widgets_power_state_vt3476(struct hda_codec *codec)
1705{
1706 struct via_spec *spec = codec->spec;
1707 int imux_is_smixer;
1708 unsigned int parm, parm2;
1709 /* MUX10 (1eh) = stereo mixer */
1710 imux_is_smixer =
1711 snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 4;
1712 /* inputs */
1713 /* PW 5/6/7 (29h/2ah/2bh) */
1714 parm = AC_PWRST_D3;
1715 set_pin_power_state(codec, 0x29, &parm);
1716 set_pin_power_state(codec, 0x2a, &parm);
1717 set_pin_power_state(codec, 0x2b, &parm);
1718 if (imux_is_smixer)
1719 parm = AC_PWRST_D0;
1720 /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
1721 update_power_state(codec, 0x1e, parm);
1722 update_power_state(codec, 0x1f, parm);
1723 update_power_state(codec, 0x10, parm);
1724 update_power_state(codec, 0x11, parm);
1725
1726 /* outputs */
1727 /* PW3 (27h), MW3(37h), AOW3 (bh) */
1728 if (spec->codec_type == VT1705CF) {
1729 parm = AC_PWRST_D3;
1730 update_power_state(codec, 0x27, parm);
1731 update_power_state(codec, 0x37, parm);
1732 } else {
1733 parm = AC_PWRST_D3;
1734 set_pin_power_state(codec, 0x27, &parm);
1735 update_power_state(codec, 0x37, parm);
1736 }
1737
1738 /* PW2 (26h), MW2(36h), AOW2 (ah) */
1739 parm = AC_PWRST_D3;
1740 set_pin_power_state(codec, 0x26, &parm);
1741 update_power_state(codec, 0x36, parm);
b3f6008f 1742 if (smart51_enabled(codec)) {
43737e0a
LW
1743 /* PW7(2bh), MW7(3bh), MUX7(1Bh) */
1744 set_pin_power_state(codec, 0x2b, &parm);
1745 update_power_state(codec, 0x3b, parm);
1746 update_power_state(codec, 0x1b, parm);
1747 }
1748 update_conv_power_state(codec, 0xa, parm, 2);
1749
1750 /* PW1 (25h), MW1(35h), AOW1 (9h) */
1751 parm = AC_PWRST_D3;
1752 set_pin_power_state(codec, 0x25, &parm);
1753 update_power_state(codec, 0x35, parm);
b3f6008f 1754 if (smart51_enabled(codec)) {
43737e0a
LW
1755 /* PW6(2ah), MW6(3ah), MUX6(1ah) */
1756 set_pin_power_state(codec, 0x2a, &parm);
1757 update_power_state(codec, 0x3a, parm);
1758 update_power_state(codec, 0x1a, parm);
1759 }
1760 update_conv_power_state(codec, 0x9, parm, 1);
1761
1762 /* PW4 (28h), MW4 (38h), MUX4(18h), AOW3(bh)/AOW0(8h) */
1763 parm = AC_PWRST_D3;
1764 set_pin_power_state(codec, 0x28, &parm);
1765 update_power_state(codec, 0x38, parm);
1766 update_power_state(codec, 0x18, parm);
b3f6008f 1767 if (spec->gen.indep_hp_enabled)
43737e0a
LW
1768 update_conv_power_state(codec, 0xb, parm, 3);
1769 parm2 = parm; /* for pin 0x0b */
1770
1771 /* PW0 (24h), MW0(34h), MW9(3fh), AOW0 (8h) */
1772 parm = AC_PWRST_D3;
1773 set_pin_power_state(codec, 0x24, &parm);
1774 update_power_state(codec, 0x34, parm);
b3f6008f 1775 if (!spec->gen.indep_hp_enabled && parm2 != AC_PWRST_D3)
43737e0a
LW
1776 parm = parm2;
1777 update_conv_power_state(codec, 0x8, parm, 0);
1778 /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
1779 update_power_state(codec, 0x3f, imux_is_smixer ? AC_PWRST_D0 : parm);
1780}
1781
1782static int patch_vt3476(struct hda_codec *codec)
1783{
1784 struct via_spec *spec;
1785 int err;
1786
1787 /* create a codec specific record */
1788 spec = via_new_spec(codec);
1789 if (spec == NULL)
1790 return -ENOMEM;
1791
b3f6008f 1792 spec->gen.mixer_nid = 0x3f;
43737e0a
LW
1793 add_secret_dac_path(codec);
1794
1795 /* automatic parse from the BIOS config */
1796 err = via_parse_auto_config(codec);
1797 if (err < 0) {
1798 via_free(codec);
1799 return err;
1800 }
1801
1802 spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs;
1803
1804 codec->patch_ops = via_patch_ops;
1805
1806 spec->set_widgets_power_state = set_widgets_power_state_vt3476;
1807
1808 return 0;
1809}
1810
c577b8a1
JC
1811/*
1812 * patch entries
1813 */
90dd48a1 1814static const struct hda_codec_preset snd_hda_preset_via[] = {
3218c178
TI
1815 { .id = 0x11061708, .name = "VT1708", .patch = patch_vt1708},
1816 { .id = 0x11061709, .name = "VT1708", .patch = patch_vt1708},
1817 { .id = 0x1106170a, .name = "VT1708", .patch = patch_vt1708},
1818 { .id = 0x1106170b, .name = "VT1708", .patch = patch_vt1708},
1819 { .id = 0x1106e710, .name = "VT1709 10-Ch",
ddd304d8 1820 .patch = patch_vt1709},
3218c178 1821 { .id = 0x1106e711, .name = "VT1709 10-Ch",
ddd304d8 1822 .patch = patch_vt1709},
3218c178 1823 { .id = 0x1106e712, .name = "VT1709 10-Ch",
ddd304d8 1824 .patch = patch_vt1709},
3218c178 1825 { .id = 0x1106e713, .name = "VT1709 10-Ch",
ddd304d8 1826 .patch = patch_vt1709},
3218c178 1827 { .id = 0x1106e714, .name = "VT1709 6-Ch",
ddd304d8 1828 .patch = patch_vt1709},
3218c178 1829 { .id = 0x1106e715, .name = "VT1709 6-Ch",
ddd304d8 1830 .patch = patch_vt1709},
3218c178 1831 { .id = 0x1106e716, .name = "VT1709 6-Ch",
ddd304d8 1832 .patch = patch_vt1709},
3218c178 1833 { .id = 0x1106e717, .name = "VT1709 6-Ch",
ddd304d8 1834 .patch = patch_vt1709},
3218c178 1835 { .id = 0x1106e720, .name = "VT1708B 8-Ch",
ddd304d8 1836 .patch = patch_vt1708B},
3218c178 1837 { .id = 0x1106e721, .name = "VT1708B 8-Ch",
ddd304d8 1838 .patch = patch_vt1708B},
3218c178 1839 { .id = 0x1106e722, .name = "VT1708B 8-Ch",
ddd304d8 1840 .patch = patch_vt1708B},
3218c178 1841 { .id = 0x1106e723, .name = "VT1708B 8-Ch",
ddd304d8 1842 .patch = patch_vt1708B},
3218c178 1843 { .id = 0x1106e724, .name = "VT1708B 4-Ch",
ddd304d8 1844 .patch = patch_vt1708B},
3218c178 1845 { .id = 0x1106e725, .name = "VT1708B 4-Ch",
ddd304d8 1846 .patch = patch_vt1708B},
3218c178 1847 { .id = 0x1106e726, .name = "VT1708B 4-Ch",
ddd304d8 1848 .patch = patch_vt1708B},
3218c178 1849 { .id = 0x1106e727, .name = "VT1708B 4-Ch",
ddd304d8 1850 .patch = patch_vt1708B},
3218c178 1851 { .id = 0x11060397, .name = "VT1708S",
d949cac1 1852 .patch = patch_vt1708S},
3218c178 1853 { .id = 0x11061397, .name = "VT1708S",
d949cac1 1854 .patch = patch_vt1708S},
3218c178 1855 { .id = 0x11062397, .name = "VT1708S",
d949cac1 1856 .patch = patch_vt1708S},
3218c178 1857 { .id = 0x11063397, .name = "VT1708S",
d949cac1 1858 .patch = patch_vt1708S},
bc92df7f 1859 { .id = 0x11064397, .name = "VT1705",
d949cac1 1860 .patch = patch_vt1708S},
3218c178 1861 { .id = 0x11065397, .name = "VT1708S",
d949cac1 1862 .patch = patch_vt1708S},
3218c178 1863 { .id = 0x11066397, .name = "VT1708S",
d949cac1 1864 .patch = patch_vt1708S},
3218c178 1865 { .id = 0x11067397, .name = "VT1708S",
d949cac1 1866 .patch = patch_vt1708S},
3218c178 1867 { .id = 0x11060398, .name = "VT1702",
d949cac1 1868 .patch = patch_vt1702},
3218c178 1869 { .id = 0x11061398, .name = "VT1702",
d949cac1 1870 .patch = patch_vt1702},
3218c178 1871 { .id = 0x11062398, .name = "VT1702",
d949cac1 1872 .patch = patch_vt1702},
3218c178 1873 { .id = 0x11063398, .name = "VT1702",
d949cac1 1874 .patch = patch_vt1702},
3218c178 1875 { .id = 0x11064398, .name = "VT1702",
d949cac1 1876 .patch = patch_vt1702},
3218c178 1877 { .id = 0x11065398, .name = "VT1702",
d949cac1 1878 .patch = patch_vt1702},
3218c178 1879 { .id = 0x11066398, .name = "VT1702",
d949cac1 1880 .patch = patch_vt1702},
3218c178 1881 { .id = 0x11067398, .name = "VT1702",
d949cac1 1882 .patch = patch_vt1702},
eb7188ca
LW
1883 { .id = 0x11060428, .name = "VT1718S",
1884 .patch = patch_vt1718S},
1885 { .id = 0x11064428, .name = "VT1718S",
1886 .patch = patch_vt1718S},
bb3c6bfc
LW
1887 { .id = 0x11060441, .name = "VT2020",
1888 .patch = patch_vt1718S},
1889 { .id = 0x11064441, .name = "VT1828S",
1890 .patch = patch_vt1718S},
f3db423d
LW
1891 { .id = 0x11060433, .name = "VT1716S",
1892 .patch = patch_vt1716S},
1893 { .id = 0x1106a721, .name = "VT1716S",
1894 .patch = patch_vt1716S},
25eaba2f
LW
1895 { .id = 0x11060438, .name = "VT2002P", .patch = patch_vt2002P},
1896 { .id = 0x11064438, .name = "VT2002P", .patch = patch_vt2002P},
ab6734e7 1897 { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812},
36dd5c4a
LW
1898 { .id = 0x11060440, .name = "VT1818S",
1899 .patch = patch_vt1708S},
11890956
LW
1900 { .id = 0x11060446, .name = "VT1802",
1901 .patch = patch_vt2002P},
1902 { .id = 0x11068446, .name = "VT1802",
1903 .patch = patch_vt2002P},
43737e0a
LW
1904 { .id = 0x11064760, .name = "VT1705CF",
1905 .patch = patch_vt3476},
6121b84a
LW
1906 { .id = 0x11064761, .name = "VT1708SCE",
1907 .patch = patch_vt3476},
1908 { .id = 0x11064762, .name = "VT1808",
1909 .patch = patch_vt3476},
c577b8a1
JC
1910 {} /* terminator */
1911};
1289e9e8
TI
1912
1913MODULE_ALIAS("snd-hda-codec-id:1106*");
1914
1915static struct hda_codec_preset_list via_list = {
1916 .preset = snd_hda_preset_via,
1917 .owner = THIS_MODULE,
1918};
1919
1920MODULE_LICENSE("GPL");
1921MODULE_DESCRIPTION("VIA HD-audio codec");
1922
1923static int __init patch_via_init(void)
1924{
1925 return snd_hda_add_codec_preset(&via_list);
1926}
1927
1928static void __exit patch_via_exit(void)
1929{
1930 snd_hda_delete_codec_preset(&via_list);
1931}
1932
1933module_init(patch_via_init)
1934module_exit(patch_via_exit)
This page took 0.533975 seconds and 5 git commands to generate.