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