ALSA: hda - Add auto_mute_via_amp flag to generic parser
[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
2c38d990
TI
483 /* Fix pop noise on headphones */
484 if (spec->codec_type == VT1802)
485 snd_hda_shutup_pins(codec);
d7a99cce 486
a86a88ea
TI
487 return 0;
488}
b3f6008f 489#endif
a86a88ea 490
b3f6008f
TI
491#ifdef CONFIG_PM
492static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
a86a88ea
TI
493{
494 struct via_spec *spec = codec->spec;
b3f6008f
TI
495 set_widgets_power_state(codec);
496 analog_low_current_mode(codec);
497 vt1708_update_hp_work(codec);
498 return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid);
499}
500#endif
a86a88ea 501
b3f6008f
TI
502/*
503 */
a86a88ea 504
b3f6008f 505static int via_init(struct hda_codec *codec);
a86a88ea 506
b3f6008f
TI
507static const struct hda_codec_ops via_patch_ops = {
508 .build_controls = via_build_controls,
509 .build_pcms = snd_hda_gen_build_pcms,
510 .init = via_init,
511 .free = via_free,
512 .unsol_event = snd_hda_jack_unsol_event,
513#ifdef CONFIG_PM
514 .suspend = via_suspend,
515 .check_power_status = via_check_power_status,
516#endif
517};
a86a88ea 518
c577b8a1 519
b3f6008f
TI
520static const struct hda_verb vt1708_init_verbs[] = {
521 /* power down jack detect function */
522 {0x1, 0xf81, 0x1},
523 { }
524};
76d9b0dd
HW
525static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
526{
527 unsigned int def_conf;
528 unsigned char seqassoc;
529
2f334f92 530 def_conf = snd_hda_codec_get_pincfg(codec, nid);
76d9b0dd
HW
531 seqassoc = (unsigned char) get_defcfg_association(def_conf);
532 seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
82ef9e45
LW
533 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
534 && (seqassoc == 0xf0 || seqassoc == 0xff)) {
535 def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
536 snd_hda_codec_set_pincfg(codec, nid, def_conf);
76d9b0dd
HW
537 }
538
539 return;
540}
541
e06e5a29 542static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
1f2e99fe
LW
543 struct snd_ctl_elem_value *ucontrol)
544{
545 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
546 struct via_spec *spec = codec->spec;
547
548 if (spec->codec_type != VT1708)
549 return 0;
e06e5a29 550 ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
1f2e99fe
LW
551 return 0;
552}
553
e06e5a29 554static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
1f2e99fe
LW
555 struct snd_ctl_elem_value *ucontrol)
556{
557 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
558 struct via_spec *spec = codec->spec;
187d333e 559 int val;
1f2e99fe
LW
560
561 if (spec->codec_type != VT1708)
562 return 0;
187d333e
TI
563 val = !!ucontrol->value.integer.value[0];
564 if (spec->vt1708_jack_detect == val)
565 return 0;
566 spec->vt1708_jack_detect = val;
b3f6008f 567 vt1708_update_hp_work(codec);
187d333e 568 return 1;
1f2e99fe
LW
569}
570
b3f6008f
TI
571static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = {
572 {
e06e5a29
TI
573 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
574 .name = "Jack Detect",
575 .count = 1,
576 .info = snd_ctl_boolean_mono_info,
577 .get = vt1708_jack_detect_get,
578 .put = vt1708_jack_detect_put,
b3f6008f
TI
579 },
580 {} /* terminator */
1f2e99fe
LW
581};
582
b3f6008f 583static void via_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl)
c577b8a1 584{
b3f6008f
TI
585 set_widgets_power_state(codec);
586 snd_hda_gen_hp_automute(codec, tbl);
5d41762a
TI
587}
588
b3f6008f 589static void via_line_automute(struct hda_codec *codec, struct hda_jack_tbl *tbl)
4e2d16d3
DH
590{
591 set_widgets_power_state(codec);
b3f6008f 592 snd_hda_gen_line_automute(codec, tbl);
4e2d16d3
DH
593}
594
595static void via_jack_powerstate_event(struct hda_codec *codec, struct hda_jack_tbl *tbl)
596{
597 set_widgets_power_state(codec);
598}
599
b3f6008f
TI
600#define VIA_JACK_EVENT (HDA_GEN_LAST_EVENT + 1)
601
602static void via_set_jack_unsol_events(struct hda_codec *codec)
4a918ffe
TI
603{
604 struct via_spec *spec = codec->spec;
b3f6008f
TI
605 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
606 hda_nid_t pin;
4a918ffe 607 int i;
4a918ffe 608
b3f6008f 609 spec->gen.hp_automute_hook = via_hp_automute;
4a918ffe 610 if (cfg->speaker_pins[0])
b3f6008f 611 spec->gen.line_automute_hook = via_line_automute;
4e2d16d3 612
4a918ffe 613 for (i = 0; i < cfg->line_outs; i++) {
b3f6008f
TI
614 pin = cfg->line_out_pins[i];
615 if (pin && !snd_hda_jack_tbl_get(codec, pin) &&
616 is_jack_detectable(codec, pin))
617 snd_hda_jack_detect_enable_callback(codec, pin,
618 VIA_JACK_EVENT,
619 via_jack_powerstate_event);
4a918ffe
TI
620 }
621
622 for (i = 0; i < cfg->num_inputs; i++) {
b3f6008f
TI
623 pin = cfg->line_out_pins[i];
624 if (pin && !snd_hda_jack_tbl_get(codec, pin) &&
625 is_jack_detectable(codec, pin))
626 snd_hda_jack_detect_enable_callback(codec, pin,
4e2d16d3
DH
627 VIA_JACK_EVENT,
628 via_jack_powerstate_event);
4a918ffe
TI
629 }
630}
631
4abdbd1c
TI
632static const struct badness_table via_main_out_badness = {
633 .no_primary_dac = 0x10000,
634 .no_dac = 0x4000,
635 .shared_primary = 0x10000,
636 .shared_surr = 0x20,
637 .shared_clfe = 0x20,
638 .shared_surr_main = 0x20,
639};
640static const struct badness_table via_extra_out_badness = {
641 .no_primary_dac = 0x4000,
642 .no_dac = 0x4000,
643 .shared_primary = 0x12,
644 .shared_surr = 0x20,
645 .shared_clfe = 0x20,
646 .shared_surr_main = 0x10,
647};
648
b3f6008f
TI
649static int via_parse_auto_config(struct hda_codec *codec)
650{
651 struct via_spec *spec = codec->spec;
652 int err;
653
4abdbd1c
TI
654 spec->gen.main_out_badness = &via_main_out_badness;
655 spec->gen.extra_out_badness = &via_extra_out_badness;
656
b3f6008f
TI
657 err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
658 if (err < 0)
659 return err;
660
661 err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
662 if (err < 0)
663 return err;
664
665 via_set_jack_unsol_events(codec);
666 return 0;
667}
668
5d41762a
TI
669static int via_init(struct hda_codec *codec)
670{
671 struct via_spec *spec = codec->spec;
672 int i;
673
674 for (i = 0; i < spec->num_iverbs; i++)
675 snd_hda_sequence_write(codec, spec->init_verbs[i]);
25eaba2f 676
e9d010c2
TI
677 /* init power states */
678 set_widgets_power_state(codec);
679 __analog_low_current_mode(codec, true);
680
b3f6008f 681 snd_hda_gen_init(codec);
4a918ffe 682
b3f6008f 683 vt1708_update_hp_work(codec);
25eaba2f 684
c577b8a1
JC
685 return 0;
686}
687
f672f65a
DH
688static int vt1708_build_controls(struct hda_codec *codec)
689{
690 /* In order not to create "Phantom Jack" controls,
691 temporary enable jackpoll */
692 int err;
693 int old_interval = codec->jackpoll_interval;
694 codec->jackpoll_interval = msecs_to_jiffies(100);
695 err = via_build_controls(codec);
696 codec->jackpoll_interval = old_interval;
697 return err;
698}
699
b3f6008f 700static int vt1708_build_pcms(struct hda_codec *codec)
337b9d02
TI
701{
702 struct via_spec *spec = codec->spec;
b3f6008f
TI
703 int i, err;
704
705 err = snd_hda_gen_build_pcms(codec);
706 if (err < 0 || codec->vendor_id != 0x11061708)
707 return err;
708
709 /* We got noisy outputs on the right channel on VT1708 when
710 * 24bit samples are used. Until any workaround is found,
711 * disable the 24bit format, so far.
712 */
713 for (i = 0; i < codec->num_pcms; i++) {
714 struct hda_pcm *info = &spec->gen.pcm_rec[i];
715 if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
716 info->pcm_type != HDA_PCM_TYPE_AUDIO)
717 continue;
718 info->stream[SNDRV_PCM_STREAM_PLAYBACK].formats =
719 SNDRV_PCM_FMTBIT_S16_LE;
337b9d02 720 }
b3f6008f 721
1c55d521 722 return 0;
337b9d02
TI
723}
724
c577b8a1
JC
725static int patch_vt1708(struct hda_codec *codec)
726{
727 struct via_spec *spec;
728 int err;
729
730 /* create a codec specific record */
5b0cb1d8 731 spec = via_new_spec(codec);
c577b8a1
JC
732 if (spec == NULL)
733 return -ENOMEM;
734
b3f6008f
TI
735 spec->gen.mixer_nid = 0x17;
736
737 /* set jackpoll_interval while parsing the codec */
738 codec->jackpoll_interval = msecs_to_jiffies(100);
739 spec->vt1708_jack_detect = 1;
740
741 /* don't support the input jack switching due to lack of unsol event */
742 /* (it may work with polling, though, but it needs testing) */
743 spec->gen.suppress_auto_mic = 1;
620e2b28 744
12daef65
TI
745 /* Add HP and CD pin config connect bit re-config action */
746 vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID);
747 vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
748
c577b8a1 749 /* automatic parse from the BIOS config */
12daef65 750 err = via_parse_auto_config(codec);
c577b8a1
JC
751 if (err < 0) {
752 via_free(codec);
753 return err;
c577b8a1
JC
754 }
755
12daef65 756 /* add jack detect on/off control */
b3f6008f 757 spec->mixers[spec->num_mixers++] = vt1708_jack_detect_ctl;
c577b8a1 758
e322a36d
LW
759 spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs;
760
c577b8a1 761 codec->patch_ops = via_patch_ops;
f672f65a 762 codec->patch_ops.build_controls = vt1708_build_controls;
b3f6008f
TI
763 codec->patch_ops.build_pcms = vt1708_build_pcms;
764
765 /* clear jackpoll_interval again; it's set dynamically */
766 codec->jackpoll_interval = 0;
c577b8a1 767
c577b8a1
JC
768 return 0;
769}
770
ddd304d8 771static int patch_vt1709(struct hda_codec *codec)
c577b8a1
JC
772{
773 struct via_spec *spec;
774 int err;
775
776 /* create a codec specific record */
5b0cb1d8 777 spec = via_new_spec(codec);
c577b8a1
JC
778 if (spec == NULL)
779 return -ENOMEM;
780
b3f6008f 781 spec->gen.mixer_nid = 0x18;
620e2b28 782
12daef65 783 err = via_parse_auto_config(codec);
c577b8a1
JC
784 if (err < 0) {
785 via_free(codec);
786 return err;
c577b8a1
JC
787 }
788
c577b8a1
JC
789 codec->patch_ops = via_patch_ops;
790
f7278fd0
JC
791 return 0;
792}
793
3e95b9ab
LW
794static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
795{
796 struct via_spec *spec = codec->spec;
797 int imux_is_smixer;
798 unsigned int parm;
799 int is_8ch = 0;
bc92df7f
LW
800 if ((spec->codec_type != VT1708B_4CH) &&
801 (codec->vendor_id != 0x11064397))
3e95b9ab
LW
802 is_8ch = 1;
803
804 /* SW0 (17h) = stereo mixer */
805 imux_is_smixer =
806 (snd_hda_codec_read(codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
807 == ((spec->codec_type == VT1708S) ? 5 : 0));
808 /* inputs */
809 /* PW 1/2/5 (1ah/1bh/1eh) */
810 parm = AC_PWRST_D3;
811 set_pin_power_state(codec, 0x1a, &parm);
812 set_pin_power_state(codec, 0x1b, &parm);
813 set_pin_power_state(codec, 0x1e, &parm);
814 if (imux_is_smixer)
815 parm = AC_PWRST_D0;
816 /* SW0 (17h), AIW 0/1 (13h/14h) */
054d867e
TI
817 update_power_state(codec, 0x17, parm);
818 update_power_state(codec, 0x13, parm);
819 update_power_state(codec, 0x14, parm);
3e95b9ab
LW
820
821 /* outputs */
822 /* PW0 (19h), SW1 (18h), AOW1 (11h) */
823 parm = AC_PWRST_D3;
824 set_pin_power_state(codec, 0x19, &parm);
b3f6008f 825 if (smart51_enabled(codec))
3e95b9ab 826 set_pin_power_state(codec, 0x1b, &parm);
054d867e
TI
827 update_power_state(codec, 0x18, parm);
828 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
829
830 /* PW6 (22h), SW2 (26h), AOW2 (24h) */
831 if (is_8ch) {
832 parm = AC_PWRST_D3;
833 set_pin_power_state(codec, 0x22, &parm);
b3f6008f 834 if (smart51_enabled(codec))
3e95b9ab 835 set_pin_power_state(codec, 0x1a, &parm);
054d867e
TI
836 update_power_state(codec, 0x26, parm);
837 update_power_state(codec, 0x24, parm);
bc92df7f
LW
838 } else if (codec->vendor_id == 0x11064397) {
839 /* PW7(23h), SW2(27h), AOW2(25h) */
840 parm = AC_PWRST_D3;
841 set_pin_power_state(codec, 0x23, &parm);
b3f6008f 842 if (smart51_enabled(codec))
bc92df7f 843 set_pin_power_state(codec, 0x1a, &parm);
054d867e
TI
844 update_power_state(codec, 0x27, parm);
845 update_power_state(codec, 0x25, parm);
3e95b9ab
LW
846 }
847
848 /* PW 3/4/7 (1ch/1dh/23h) */
849 parm = AC_PWRST_D3;
850 /* force to D0 for internal Speaker */
851 set_pin_power_state(codec, 0x1c, &parm);
852 set_pin_power_state(codec, 0x1d, &parm);
853 if (is_8ch)
854 set_pin_power_state(codec, 0x23, &parm);
855
856 /* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
054d867e
TI
857 update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
858 update_power_state(codec, 0x10, parm);
3e95b9ab 859 if (is_8ch) {
054d867e
TI
860 update_power_state(codec, 0x25, parm);
861 update_power_state(codec, 0x27, parm);
b3f6008f 862 } else if (codec->vendor_id == 0x11064397 && spec->gen.indep_hp_enabled)
054d867e 863 update_power_state(codec, 0x25, parm);
3e95b9ab
LW
864}
865
518bf3ba 866static int patch_vt1708S(struct hda_codec *codec);
ddd304d8 867static int patch_vt1708B(struct hda_codec *codec)
f7278fd0
JC
868{
869 struct via_spec *spec;
870 int err;
871
518bf3ba
LW
872 if (get_codec_type(codec) == VT1708BCE)
873 return patch_vt1708S(codec);
ddd304d8 874
f7278fd0 875 /* create a codec specific record */
5b0cb1d8 876 spec = via_new_spec(codec);
f7278fd0
JC
877 if (spec == NULL)
878 return -ENOMEM;
879
b3f6008f 880 spec->gen.mixer_nid = 0x16;
620e2b28 881
f7278fd0 882 /* automatic parse from the BIOS config */
12daef65 883 err = via_parse_auto_config(codec);
f7278fd0
JC
884 if (err < 0) {
885 via_free(codec);
886 return err;
f7278fd0
JC
887 }
888
f7278fd0
JC
889 codec->patch_ops = via_patch_ops;
890
3e95b9ab
LW
891 spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
892
f7278fd0
JC
893 return 0;
894}
895
d949cac1 896/* Patch for VT1708S */
096a8854 897static const struct hda_verb vt1708S_init_verbs[] = {
d7426329
HW
898 /* Enable Mic Boost Volume backdoor */
899 {0x1, 0xf98, 0x1},
bc7e7e5c
LW
900 /* don't bybass mixer */
901 {0x1, 0xf88, 0xc0},
d949cac1
HW
902 { }
903};
904
6369bcfc
LW
905static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
906 int offset, int num_steps, int step_size)
907{
d045c5dc
TI
908 snd_hda_override_wcaps(codec, pin,
909 get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
6369bcfc
LW
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.530879 seconds and 5 git commands to generate.