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