ALSA: hda - Create capture source ctls when stereo mix input is added
[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);
b3f6008f
TI
121
122static struct via_spec *via_new_spec(struct hda_codec *codec)
5b0cb1d8
JK
123{
124 struct via_spec *spec;
125
126 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
127 if (spec == NULL)
128 return NULL;
129
130 codec->spec = spec;
b3f6008f 131 snd_hda_gen_spec_init(&spec->gen);
0341ccd7
LW
132 spec->codec_type = get_codec_type(codec);
133 /* VT1708BCE & VT1708S are almost same */
134 if (spec->codec_type == VT1708BCE)
135 spec->codec_type = VT1708S;
b3f6008f 136 spec->no_pin_power_ctl = 1;
13961170 137 spec->gen.indep_hp = 1;
05909d5c 138 spec->gen.keep_eapd_on = 1;
b3f6008f 139 spec->gen.pcm_playback_hook = via_playback_pcm_hook;
f1e762dd 140 spec->gen.add_stereo_mix_input = 1;
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 209 snd_hda_codec_write(codec, 0x1, 0, 0xf81, 1);
7eaa9161 210 codec->jackpoll_interval = 0;
b3f6008f
TI
211 cancel_delayed_work_sync(&codec->jackpoll_work);
212 spec->hp_work_active = false;
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 466{
b3f6008f 467 vt1708_stop_hp_work(codec);
a8dca460 468 snd_hda_gen_free(codec);
a86a88ea
TI
469}
470
b3f6008f
TI
471#ifdef CONFIG_PM
472static int via_suspend(struct hda_codec *codec)
a86a88ea
TI
473{
474 struct via_spec *spec = codec->spec;
b3f6008f 475 vt1708_stop_hp_work(codec);
d7a99cce 476
2c38d990
TI
477 /* Fix pop noise on headphones */
478 if (spec->codec_type == VT1802)
479 snd_hda_shutup_pins(codec);
d7a99cce 480
a86a88ea
TI
481 return 0;
482}
b3f6008f 483#endif
a86a88ea 484
b3f6008f
TI
485#ifdef CONFIG_PM
486static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid)
a86a88ea
TI
487{
488 struct via_spec *spec = codec->spec;
b3f6008f
TI
489 set_widgets_power_state(codec);
490 analog_low_current_mode(codec);
491 vt1708_update_hp_work(codec);
492 return snd_hda_check_amp_list_power(codec, &spec->gen.loopback, nid);
493}
494#endif
a86a88ea 495
b3f6008f
TI
496/*
497 */
a86a88ea 498
b3f6008f 499static int via_init(struct hda_codec *codec);
a86a88ea 500
b3f6008f
TI
501static const struct hda_codec_ops via_patch_ops = {
502 .build_controls = via_build_controls,
503 .build_pcms = snd_hda_gen_build_pcms,
504 .init = via_init,
505 .free = via_free,
506 .unsol_event = snd_hda_jack_unsol_event,
507#ifdef CONFIG_PM
508 .suspend = via_suspend,
509 .check_power_status = via_check_power_status,
510#endif
511};
a86a88ea 512
c577b8a1 513
b3f6008f
TI
514static const struct hda_verb vt1708_init_verbs[] = {
515 /* power down jack detect function */
516 {0x1, 0xf81, 0x1},
517 { }
518};
76d9b0dd
HW
519static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
520{
521 unsigned int def_conf;
522 unsigned char seqassoc;
523
2f334f92 524 def_conf = snd_hda_codec_get_pincfg(codec, nid);
76d9b0dd
HW
525 seqassoc = (unsigned char) get_defcfg_association(def_conf);
526 seqassoc = (seqassoc << 4) | get_defcfg_sequence(def_conf);
82ef9e45
LW
527 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE
528 && (seqassoc == 0xf0 || seqassoc == 0xff)) {
529 def_conf = def_conf & (~(AC_JACK_PORT_BOTH << 30));
530 snd_hda_codec_set_pincfg(codec, nid, def_conf);
76d9b0dd
HW
531 }
532
533 return;
534}
535
e06e5a29 536static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
1f2e99fe
LW
537 struct snd_ctl_elem_value *ucontrol)
538{
539 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
540 struct via_spec *spec = codec->spec;
541
542 if (spec->codec_type != VT1708)
543 return 0;
e06e5a29 544 ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
1f2e99fe
LW
545 return 0;
546}
547
e06e5a29 548static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
1f2e99fe
LW
549 struct snd_ctl_elem_value *ucontrol)
550{
551 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
552 struct via_spec *spec = codec->spec;
187d333e 553 int val;
1f2e99fe
LW
554
555 if (spec->codec_type != VT1708)
556 return 0;
187d333e
TI
557 val = !!ucontrol->value.integer.value[0];
558 if (spec->vt1708_jack_detect == val)
559 return 0;
560 spec->vt1708_jack_detect = val;
b3f6008f 561 vt1708_update_hp_work(codec);
187d333e 562 return 1;
1f2e99fe
LW
563}
564
b3f6008f
TI
565static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = {
566 {
e06e5a29
TI
567 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
568 .name = "Jack Detect",
569 .count = 1,
570 .info = snd_ctl_boolean_mono_info,
571 .get = vt1708_jack_detect_get,
572 .put = vt1708_jack_detect_put,
b3f6008f
TI
573 },
574 {} /* terminator */
1f2e99fe
LW
575};
576
1a4f69d5
TI
577static void via_jack_powerstate_event(struct hda_codec *codec,
578 struct hda_jack_callback *tbl)
4e2d16d3
DH
579{
580 set_widgets_power_state(codec);
581}
582
b3f6008f 583static void via_set_jack_unsol_events(struct hda_codec *codec)
4a918ffe
TI
584{
585 struct via_spec *spec = codec->spec;
b3f6008f
TI
586 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
587 hda_nid_t pin;
4a918ffe 588 int i;
4a918ffe 589
4a918ffe 590 for (i = 0; i < cfg->line_outs; i++) {
b3f6008f 591 pin = cfg->line_out_pins[i];
7c3008c4 592 if (pin && is_jack_detectable(codec, pin))
b3f6008f 593 snd_hda_jack_detect_enable_callback(codec, pin,
b3f6008f 594 via_jack_powerstate_event);
4a918ffe
TI
595 }
596
597 for (i = 0; i < cfg->num_inputs; i++) {
b3f6008f 598 pin = cfg->line_out_pins[i];
7c3008c4 599 if (pin && is_jack_detectable(codec, pin))
b3f6008f 600 snd_hda_jack_detect_enable_callback(codec, pin,
4e2d16d3 601 via_jack_powerstate_event);
4a918ffe
TI
602 }
603}
604
4abdbd1c
TI
605static const struct badness_table via_main_out_badness = {
606 .no_primary_dac = 0x10000,
607 .no_dac = 0x4000,
608 .shared_primary = 0x10000,
609 .shared_surr = 0x20,
610 .shared_clfe = 0x20,
611 .shared_surr_main = 0x20,
612};
613static const struct badness_table via_extra_out_badness = {
614 .no_primary_dac = 0x4000,
615 .no_dac = 0x4000,
616 .shared_primary = 0x12,
617 .shared_surr = 0x20,
618 .shared_clfe = 0x20,
619 .shared_surr_main = 0x10,
620};
621
b3f6008f
TI
622static int via_parse_auto_config(struct hda_codec *codec)
623{
624 struct via_spec *spec = codec->spec;
625 int err;
626
4abdbd1c
TI
627 spec->gen.main_out_badness = &via_main_out_badness;
628 spec->gen.extra_out_badness = &via_extra_out_badness;
629
b3f6008f
TI
630 err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
631 if (err < 0)
632 return err;
633
634 err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg);
635 if (err < 0)
636 return err;
637
638 via_set_jack_unsol_events(codec);
639 return 0;
640}
641
5d41762a
TI
642static int via_init(struct hda_codec *codec)
643{
644 struct via_spec *spec = codec->spec;
645 int i;
646
647 for (i = 0; i < spec->num_iverbs; i++)
648 snd_hda_sequence_write(codec, spec->init_verbs[i]);
25eaba2f 649
e9d010c2
TI
650 /* init power states */
651 set_widgets_power_state(codec);
652 __analog_low_current_mode(codec, true);
653
b3f6008f 654 snd_hda_gen_init(codec);
4a918ffe 655
b3f6008f 656 vt1708_update_hp_work(codec);
25eaba2f 657
c577b8a1
JC
658 return 0;
659}
660
f672f65a
DH
661static int vt1708_build_controls(struct hda_codec *codec)
662{
663 /* In order not to create "Phantom Jack" controls,
664 temporary enable jackpoll */
665 int err;
666 int old_interval = codec->jackpoll_interval;
667 codec->jackpoll_interval = msecs_to_jiffies(100);
668 err = via_build_controls(codec);
669 codec->jackpoll_interval = old_interval;
670 return err;
671}
672
b3f6008f 673static int vt1708_build_pcms(struct hda_codec *codec)
337b9d02
TI
674{
675 struct via_spec *spec = codec->spec;
b3f6008f
TI
676 int i, err;
677
678 err = snd_hda_gen_build_pcms(codec);
679 if (err < 0 || codec->vendor_id != 0x11061708)
680 return err;
681
682 /* We got noisy outputs on the right channel on VT1708 when
683 * 24bit samples are used. Until any workaround is found,
684 * disable the 24bit format, so far.
685 */
686 for (i = 0; i < codec->num_pcms; i++) {
687 struct hda_pcm *info = &spec->gen.pcm_rec[i];
688 if (!info->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams ||
689 info->pcm_type != HDA_PCM_TYPE_AUDIO)
690 continue;
691 info->stream[SNDRV_PCM_STREAM_PLAYBACK].formats =
692 SNDRV_PCM_FMTBIT_S16_LE;
337b9d02 693 }
b3f6008f 694
1c55d521 695 return 0;
337b9d02
TI
696}
697
c577b8a1
JC
698static int patch_vt1708(struct hda_codec *codec)
699{
700 struct via_spec *spec;
701 int err;
702
703 /* create a codec specific record */
5b0cb1d8 704 spec = via_new_spec(codec);
c577b8a1
JC
705 if (spec == NULL)
706 return -ENOMEM;
707
b3f6008f
TI
708 spec->gen.mixer_nid = 0x17;
709
710 /* set jackpoll_interval while parsing the codec */
711 codec->jackpoll_interval = msecs_to_jiffies(100);
712 spec->vt1708_jack_detect = 1;
713
714 /* don't support the input jack switching due to lack of unsol event */
715 /* (it may work with polling, though, but it needs testing) */
716 spec->gen.suppress_auto_mic = 1;
eb33ccf7
TI
717 /* Some machines show the broken speaker mute */
718 spec->gen.auto_mute_via_amp = 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{
d045c5dc
TI
883 snd_hda_override_wcaps(codec, pin,
884 get_wcaps(codec, pin) | AC_WCAP_IN_AMP);
6369bcfc
LW
885 snd_hda_override_amp_caps(codec, pin, HDA_INPUT,
886 (offset << AC_AMPCAP_OFFSET_SHIFT) |
887 (num_steps << AC_AMPCAP_NUM_STEPS_SHIFT) |
888 (step_size << AC_AMPCAP_STEP_SIZE_SHIFT) |
889 (0 << AC_AMPCAP_MUTE_SHIFT));
890}
891
d949cac1
HW
892static int patch_vt1708S(struct hda_codec *codec)
893{
894 struct via_spec *spec;
895 int err;
896
897 /* create a codec specific record */
5b0cb1d8 898 spec = via_new_spec(codec);
d949cac1
HW
899 if (spec == NULL)
900 return -ENOMEM;
901
b3f6008f 902 spec->gen.mixer_nid = 0x16;
d7a99cce
TI
903 override_mic_boost(codec, 0x1a, 0, 3, 40);
904 override_mic_boost(codec, 0x1e, 0, 3, 40);
620e2b28 905
518bf3ba
LW
906 /* correct names for VT1708BCE */
907 if (get_codec_type(codec) == VT1708BCE) {
908 kfree(codec->chip_name);
909 codec->chip_name = kstrdup("VT1708BCE", GFP_KERNEL);
910 snprintf(codec->bus->card->mixername,
911 sizeof(codec->bus->card->mixername),
912 "%s %s", codec->vendor_name, codec->chip_name);
970f630f 913 }
bc92df7f
LW
914 /* correct names for VT1705 */
915 if (codec->vendor_id == 0x11064397) {
916 kfree(codec->chip_name);
917 codec->chip_name = kstrdup("VT1705", GFP_KERNEL);
918 snprintf(codec->bus->card->mixername,
919 sizeof(codec->bus->card->mixername),
920 "%s %s", codec->vendor_name, codec->chip_name);
921 }
b3f6008f
TI
922
923 /* automatic parse from the BIOS config */
924 err = via_parse_auto_config(codec);
925 if (err < 0) {
926 via_free(codec);
927 return err;
928 }
929
930 spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs;
931
932 codec->patch_ops = via_patch_ops;
933
3e95b9ab 934 spec->set_widgets_power_state = set_widgets_power_state_vt1708B;
d949cac1
HW
935 return 0;
936}
937
938/* Patch for VT1702 */
939
096a8854 940static const struct hda_verb vt1702_init_verbs[] = {
bc7e7e5c
LW
941 /* mixer enable */
942 {0x1, 0xF88, 0x3},
943 /* GPIO 0~2 */
944 {0x1, 0xF82, 0x3F},
d949cac1
HW
945 { }
946};
947
3e95b9ab
LW
948static void set_widgets_power_state_vt1702(struct hda_codec *codec)
949{
950 int imux_is_smixer =
951 snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
952 unsigned int parm;
953 /* inputs */
954 /* PW 1/2/5 (14h/15h/18h) */
955 parm = AC_PWRST_D3;
956 set_pin_power_state(codec, 0x14, &parm);
957 set_pin_power_state(codec, 0x15, &parm);
958 set_pin_power_state(codec, 0x18, &parm);
959 if (imux_is_smixer)
960 parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
961 /* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
054d867e
TI
962 update_power_state(codec, 0x13, parm);
963 update_power_state(codec, 0x12, parm);
964 update_power_state(codec, 0x1f, parm);
965 update_power_state(codec, 0x20, parm);
3e95b9ab
LW
966
967 /* outputs */
968 /* PW 3/4 (16h/17h) */
969 parm = AC_PWRST_D3;
970 set_pin_power_state(codec, 0x17, &parm);
971 set_pin_power_state(codec, 0x16, &parm);
972 /* MW0 (1ah), AOW 0/1 (10h/1dh) */
054d867e
TI
973 update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm);
974 update_power_state(codec, 0x10, parm);
975 update_power_state(codec, 0x1d, parm);
3e95b9ab
LW
976}
977
d949cac1
HW
978static int patch_vt1702(struct hda_codec *codec)
979{
980 struct via_spec *spec;
981 int err;
d949cac1
HW
982
983 /* create a codec specific record */
5b0cb1d8 984 spec = via_new_spec(codec);
d949cac1
HW
985 if (spec == NULL)
986 return -ENOMEM;
987
b3f6008f 988 spec->gen.mixer_nid = 0x1a;
620e2b28 989
12daef65
TI
990 /* limit AA path volume to 0 dB */
991 snd_hda_override_amp_caps(codec, 0x1A, HDA_INPUT,
992 (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
993 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
994 (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
995 (1 << AC_AMPCAP_MUTE_SHIFT));
996
d949cac1 997 /* automatic parse from the BIOS config */
12daef65 998 err = via_parse_auto_config(codec);
d949cac1
HW
999 if (err < 0) {
1000 via_free(codec);
1001 return err;
d949cac1
HW
1002 }
1003
096a8854 1004 spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs;
d949cac1 1005
d949cac1
HW
1006 codec->patch_ops = via_patch_ops;
1007
3e95b9ab 1008 spec->set_widgets_power_state = set_widgets_power_state_vt1702;
d949cac1
HW
1009 return 0;
1010}
1011
eb7188ca
LW
1012/* Patch for VT1718S */
1013
096a8854 1014static const struct hda_verb vt1718S_init_verbs[] = {
4ab2d53a
LW
1015 /* Enable MW0 adjust Gain 5 */
1016 {0x1, 0xfb2, 0x10},
eb7188ca
LW
1017 /* Enable Boost Volume backdoor */
1018 {0x1, 0xf88, 0x8},
5d41762a 1019
eb7188ca
LW
1020 { }
1021};
1022
3e95b9ab
LW
1023static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
1024{
1025 struct via_spec *spec = codec->spec;
1026 int imux_is_smixer;
6162552b 1027 unsigned int parm, parm2;
3e95b9ab
LW
1028 /* MUX6 (1eh) = stereo mixer */
1029 imux_is_smixer =
1030 snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
1031 /* inputs */
1032 /* PW 5/6/7 (29h/2ah/2bh) */
1033 parm = AC_PWRST_D3;
1034 set_pin_power_state(codec, 0x29, &parm);
1035 set_pin_power_state(codec, 0x2a, &parm);
1036 set_pin_power_state(codec, 0x2b, &parm);
1037 if (imux_is_smixer)
1038 parm = AC_PWRST_D0;
1039 /* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
054d867e
TI
1040 update_power_state(codec, 0x1e, parm);
1041 update_power_state(codec, 0x1f, parm);
1042 update_power_state(codec, 0x10, parm);
1043 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1044
1045 /* outputs */
1046 /* PW3 (27h), MW2 (1ah), AOW3 (bh) */
1047 parm = AC_PWRST_D3;
1048 set_pin_power_state(codec, 0x27, &parm);
054d867e 1049 update_power_state(codec, 0x1a, parm);
6162552b 1050 parm2 = parm; /* for pin 0x0b */
3e95b9ab
LW
1051
1052 /* PW2 (26h), AOW2 (ah) */
1053 parm = AC_PWRST_D3;
1054 set_pin_power_state(codec, 0x26, &parm);
b3f6008f 1055 if (smart51_enabled(codec))
3e95b9ab 1056 set_pin_power_state(codec, 0x2b, &parm);
054d867e 1057 update_power_state(codec, 0xa, parm);
3e95b9ab
LW
1058
1059 /* PW0 (24h), AOW0 (8h) */
1060 parm = AC_PWRST_D3;
1061 set_pin_power_state(codec, 0x24, &parm);
b3f6008f 1062 if (!spec->gen.indep_hp_enabled) /* check for redirected HP */
3e95b9ab 1063 set_pin_power_state(codec, 0x28, &parm);
054d867e 1064 update_power_state(codec, 0x8, parm);
b3f6008f 1065 if (!spec->gen.indep_hp_enabled && parm2 != AC_PWRST_D3)
6162552b
TI
1066 parm = parm2;
1067 update_power_state(codec, 0xb, parm);
3e95b9ab 1068 /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
054d867e 1069 update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm);
3e95b9ab
LW
1070
1071 /* PW1 (25h), AOW1 (9h) */
1072 parm = AC_PWRST_D3;
1073 set_pin_power_state(codec, 0x25, &parm);
b3f6008f 1074 if (smart51_enabled(codec))
3e95b9ab 1075 set_pin_power_state(codec, 0x2a, &parm);
054d867e 1076 update_power_state(codec, 0x9, parm);
3e95b9ab 1077
b3f6008f 1078 if (spec->gen.indep_hp_enabled) {
3e95b9ab
LW
1079 /* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
1080 parm = AC_PWRST_D3;
1081 set_pin_power_state(codec, 0x28, &parm);
054d867e
TI
1082 update_power_state(codec, 0x1b, parm);
1083 update_power_state(codec, 0x34, parm);
1084 update_power_state(codec, 0xc, parm);
3e95b9ab
LW
1085 }
1086}
1087
30b45033
TI
1088/* Add a connection to the primary DAC from AA-mixer for some codecs
1089 * This isn't listed from the raw info, but the chip has a secret connection.
1090 */
1091static int add_secret_dac_path(struct hda_codec *codec)
1092{
1093 struct via_spec *spec = codec->spec;
1094 int i, nums;
1095 hda_nid_t conn[8];
1096 hda_nid_t nid;
1097
b3f6008f 1098 if (!spec->gen.mixer_nid)
30b45033 1099 return 0;
b3f6008f 1100 nums = snd_hda_get_connections(codec, spec->gen.mixer_nid, conn,
30b45033
TI
1101 ARRAY_SIZE(conn) - 1);
1102 for (i = 0; i < nums; i++) {
1103 if (get_wcaps_type(get_wcaps(codec, conn[i])) == AC_WID_AUD_OUT)
1104 return 0;
1105 }
1106
1107 /* find the primary DAC and add to the connection list */
1108 nid = codec->start_nid;
1109 for (i = 0; i < codec->num_nodes; i++, nid++) {
1110 unsigned int caps = get_wcaps(codec, nid);
1111 if (get_wcaps_type(caps) == AC_WID_AUD_OUT &&
1112 !(caps & AC_WCAP_DIGITAL)) {
1113 conn[nums++] = nid;
1114 return snd_hda_override_conn_list(codec,
b3f6008f 1115 spec->gen.mixer_nid,
30b45033
TI
1116 nums, conn);
1117 }
1118 }
1119 return 0;
1120}
1121
1122
eb7188ca
LW
1123static int patch_vt1718S(struct hda_codec *codec)
1124{
1125 struct via_spec *spec;
1126 int err;
1127
1128 /* create a codec specific record */
5b0cb1d8 1129 spec = via_new_spec(codec);
eb7188ca
LW
1130 if (spec == NULL)
1131 return -ENOMEM;
1132
b3f6008f 1133 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1134 override_mic_boost(codec, 0x2b, 0, 3, 40);
1135 override_mic_boost(codec, 0x29, 0, 3, 40);
30b45033 1136 add_secret_dac_path(codec);
620e2b28 1137
eb7188ca 1138 /* automatic parse from the BIOS config */
12daef65 1139 err = via_parse_auto_config(codec);
eb7188ca
LW
1140 if (err < 0) {
1141 via_free(codec);
1142 return err;
eb7188ca
LW
1143 }
1144
096a8854 1145 spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs;
eb7188ca 1146
eb7188ca
LW
1147 codec->patch_ops = via_patch_ops;
1148
3e95b9ab
LW
1149 spec->set_widgets_power_state = set_widgets_power_state_vt1718S;
1150
eb7188ca
LW
1151 return 0;
1152}
f3db423d
LW
1153
1154/* Patch for VT1716S */
1155
1156static int vt1716s_dmic_info(struct snd_kcontrol *kcontrol,
1157 struct snd_ctl_elem_info *uinfo)
1158{
1159 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1160 uinfo->count = 1;
1161 uinfo->value.integer.min = 0;
1162 uinfo->value.integer.max = 1;
1163 return 0;
1164}
1165
1166static int vt1716s_dmic_get(struct snd_kcontrol *kcontrol,
1167 struct snd_ctl_elem_value *ucontrol)
1168{
1169 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1170 int index = 0;
1171
1172 index = snd_hda_codec_read(codec, 0x26, 0,
1173 AC_VERB_GET_CONNECT_SEL, 0);
1174 if (index != -1)
1175 *ucontrol->value.integer.value = index;
1176
1177 return 0;
1178}
1179
1180static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol,
1181 struct snd_ctl_elem_value *ucontrol)
1182{
1183 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1184 struct via_spec *spec = codec->spec;
1185 int index = *ucontrol->value.integer.value;
1186
1187 snd_hda_codec_write(codec, 0x26, 0,
1188 AC_VERB_SET_CONNECT_SEL, index);
1189 spec->dmic_enabled = index;
3e95b9ab 1190 set_widgets_power_state(codec);
f3db423d
LW
1191 return 1;
1192}
1193
90dd48a1 1194static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = {
f3db423d
LW
1195 HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT),
1196 {
1197 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1198 .name = "Digital Mic Capture Switch",
5b0cb1d8 1199 .subdevice = HDA_SUBDEV_NID_FLAG | 0x26,
f3db423d
LW
1200 .count = 1,
1201 .info = vt1716s_dmic_info,
1202 .get = vt1716s_dmic_get,
1203 .put = vt1716s_dmic_put,
1204 },
1205 {} /* end */
1206};
1207
1208
1209/* mono-out mixer elements */
90dd48a1 1210static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = {
f3db423d
LW
1211 HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT),
1212 { } /* end */
1213};
1214
096a8854 1215static const struct hda_verb vt1716S_init_verbs[] = {
f3db423d
LW
1216 /* Enable Boost Volume backdoor */
1217 {0x1, 0xf8a, 0x80},
1218 /* don't bybass mixer */
1219 {0x1, 0xf88, 0xc0},
1220 /* Enable mono output */
1221 {0x1, 0xf90, 0x08},
1222 { }
1223};
1224
3e95b9ab
LW
1225static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
1226{
1227 struct via_spec *spec = codec->spec;
1228 int imux_is_smixer;
1229 unsigned int parm;
1230 unsigned int mono_out, present;
1231 /* SW0 (17h) = stereo mixer */
1232 imux_is_smixer =
1233 (snd_hda_codec_read(codec, 0x17, 0,
1234 AC_VERB_GET_CONNECT_SEL, 0x00) == 5);
1235 /* inputs */
1236 /* PW 1/2/5 (1ah/1bh/1eh) */
1237 parm = AC_PWRST_D3;
1238 set_pin_power_state(codec, 0x1a, &parm);
1239 set_pin_power_state(codec, 0x1b, &parm);
1240 set_pin_power_state(codec, 0x1e, &parm);
1241 if (imux_is_smixer)
1242 parm = AC_PWRST_D0;
1243 /* SW0 (17h), AIW0(13h) */
054d867e
TI
1244 update_power_state(codec, 0x17, parm);
1245 update_power_state(codec, 0x13, parm);
3e95b9ab
LW
1246
1247 parm = AC_PWRST_D3;
1248 set_pin_power_state(codec, 0x1e, &parm);
1249 /* PW11 (22h) */
1250 if (spec->dmic_enabled)
1251 set_pin_power_state(codec, 0x22, &parm);
1252 else
054d867e 1253 update_power_state(codec, 0x22, AC_PWRST_D3);
3e95b9ab
LW
1254
1255 /* SW2(26h), AIW1(14h) */
054d867e
TI
1256 update_power_state(codec, 0x26, parm);
1257 update_power_state(codec, 0x14, parm);
3e95b9ab
LW
1258
1259 /* outputs */
1260 /* PW0 (19h), SW1 (18h), AOW1 (11h) */
1261 parm = AC_PWRST_D3;
1262 set_pin_power_state(codec, 0x19, &parm);
1263 /* Smart 5.1 PW2(1bh) */
b3f6008f 1264 if (smart51_enabled(codec))
3e95b9ab 1265 set_pin_power_state(codec, 0x1b, &parm);
054d867e
TI
1266 update_power_state(codec, 0x18, parm);
1267 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1268
1269 /* PW7 (23h), SW3 (27h), AOW3 (25h) */
1270 parm = AC_PWRST_D3;
1271 set_pin_power_state(codec, 0x23, &parm);
1272 /* Smart 5.1 PW1(1ah) */
b3f6008f 1273 if (smart51_enabled(codec))
3e95b9ab 1274 set_pin_power_state(codec, 0x1a, &parm);
054d867e 1275 update_power_state(codec, 0x27, parm);
3e95b9ab
LW
1276
1277 /* Smart 5.1 PW5(1eh) */
b3f6008f 1278 if (smart51_enabled(codec))
3e95b9ab 1279 set_pin_power_state(codec, 0x1e, &parm);
054d867e 1280 update_power_state(codec, 0x25, parm);
3e95b9ab
LW
1281
1282 /* Mono out */
1283 /* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
1284 present = snd_hda_jack_detect(codec, 0x1c);
1285
1286 if (present)
1287 mono_out = 0;
1288 else {
1289 present = snd_hda_jack_detect(codec, 0x1d);
b3f6008f 1290 if (!spec->gen.indep_hp_enabled && present)
3e95b9ab
LW
1291 mono_out = 0;
1292 else
1293 mono_out = 1;
1294 }
1295 parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
054d867e
TI
1296 update_power_state(codec, 0x28, parm);
1297 update_power_state(codec, 0x29, parm);
1298 update_power_state(codec, 0x2a, parm);
3e95b9ab
LW
1299
1300 /* PW 3/4 (1ch/1dh) */
1301 parm = AC_PWRST_D3;
1302 set_pin_power_state(codec, 0x1c, &parm);
1303 set_pin_power_state(codec, 0x1d, &parm);
1304 /* HP Independent Mode, power on AOW3 */
b3f6008f 1305 if (spec->gen.indep_hp_enabled)
054d867e 1306 update_power_state(codec, 0x25, parm);
3e95b9ab
LW
1307
1308 /* force to D0 for internal Speaker */
1309 /* MW0 (16h), AOW0 (10h) */
054d867e
TI
1310 update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
1311 update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm);
3e95b9ab
LW
1312}
1313
f3db423d
LW
1314static int patch_vt1716S(struct hda_codec *codec)
1315{
1316 struct via_spec *spec;
1317 int err;
1318
1319 /* create a codec specific record */
5b0cb1d8 1320 spec = via_new_spec(codec);
f3db423d
LW
1321 if (spec == NULL)
1322 return -ENOMEM;
1323
b3f6008f 1324 spec->gen.mixer_nid = 0x16;
d7a99cce
TI
1325 override_mic_boost(codec, 0x1a, 0, 3, 40);
1326 override_mic_boost(codec, 0x1e, 0, 3, 40);
620e2b28 1327
f3db423d 1328 /* automatic parse from the BIOS config */
12daef65 1329 err = via_parse_auto_config(codec);
f3db423d
LW
1330 if (err < 0) {
1331 via_free(codec);
1332 return err;
f3db423d
LW
1333 }
1334
096a8854 1335 spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs;
f3db423d 1336
b3f6008f 1337 spec->mixers[spec->num_mixers++] = vt1716s_dmic_mixer;
f3db423d
LW
1338 spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer;
1339
1340 codec->patch_ops = via_patch_ops;
1341
3e95b9ab 1342 spec->set_widgets_power_state = set_widgets_power_state_vt1716S;
f3db423d
LW
1343 return 0;
1344}
25eaba2f
LW
1345
1346/* for vt2002P */
1347
096a8854 1348static const struct hda_verb vt2002P_init_verbs[] = {
eadb9a80
LW
1349 /* Class-D speaker related verbs */
1350 {0x1, 0xfe0, 0x4},
1351 {0x1, 0xfe9, 0x80},
1352 {0x1, 0xfe2, 0x22},
25eaba2f
LW
1353 /* Enable Boost Volume backdoor */
1354 {0x1, 0xfb9, 0x24},
25eaba2f
LW
1355 /* Enable AOW0 to MW9 */
1356 {0x1, 0xfb8, 0x88},
1357 { }
1358};
4a918ffe 1359
096a8854 1360static const struct hda_verb vt1802_init_verbs[] = {
11890956
LW
1361 /* Enable Boost Volume backdoor */
1362 {0x1, 0xfb9, 0x24},
11890956
LW
1363 /* Enable AOW0 to MW9 */
1364 {0x1, 0xfb8, 0x88},
1365 { }
1366};
25eaba2f 1367
3e95b9ab
LW
1368static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
1369{
1370 struct via_spec *spec = codec->spec;
1371 int imux_is_smixer;
1372 unsigned int parm;
1373 unsigned int present;
1374 /* MUX9 (1eh) = stereo mixer */
1375 imux_is_smixer =
1376 snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
1377 /* inputs */
1378 /* PW 5/6/7 (29h/2ah/2bh) */
1379 parm = AC_PWRST_D3;
1380 set_pin_power_state(codec, 0x29, &parm);
1381 set_pin_power_state(codec, 0x2a, &parm);
1382 set_pin_power_state(codec, 0x2b, &parm);
1383 parm = AC_PWRST_D0;
1384 /* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
054d867e
TI
1385 update_power_state(codec, 0x1e, parm);
1386 update_power_state(codec, 0x1f, parm);
1387 update_power_state(codec, 0x10, parm);
1388 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1389
1390 /* outputs */
1391 /* AOW0 (8h)*/
054d867e 1392 update_power_state(codec, 0x8, parm);
3e95b9ab 1393
11890956
LW
1394 if (spec->codec_type == VT1802) {
1395 /* PW4 (28h), MW4 (18h), MUX4(38h) */
1396 parm = AC_PWRST_D3;
1397 set_pin_power_state(codec, 0x28, &parm);
054d867e
TI
1398 update_power_state(codec, 0x18, parm);
1399 update_power_state(codec, 0x38, parm);
11890956
LW
1400 } else {
1401 /* PW4 (26h), MW4 (1ch), MUX4(37h) */
1402 parm = AC_PWRST_D3;
1403 set_pin_power_state(codec, 0x26, &parm);
054d867e
TI
1404 update_power_state(codec, 0x1c, parm);
1405 update_power_state(codec, 0x37, parm);
11890956 1406 }
3e95b9ab 1407
11890956
LW
1408 if (spec->codec_type == VT1802) {
1409 /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
1410 parm = AC_PWRST_D3;
1411 set_pin_power_state(codec, 0x25, &parm);
054d867e
TI
1412 update_power_state(codec, 0x15, parm);
1413 update_power_state(codec, 0x35, parm);
11890956
LW
1414 } else {
1415 /* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
1416 parm = AC_PWRST_D3;
1417 set_pin_power_state(codec, 0x25, &parm);
054d867e
TI
1418 update_power_state(codec, 0x19, parm);
1419 update_power_state(codec, 0x35, parm);
11890956 1420 }
3e95b9ab 1421
b3f6008f 1422 if (spec->gen.indep_hp_enabled)
054d867e 1423 update_power_state(codec, 0x9, AC_PWRST_D0);
3e95b9ab
LW
1424
1425 /* Class-D */
1426 /* PW0 (24h), MW0(18h/14h), MUX0(34h) */
1427 present = snd_hda_jack_detect(codec, 0x25);
1428
1429 parm = AC_PWRST_D3;
1430 set_pin_power_state(codec, 0x24, &parm);
1431 parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
11890956 1432 if (spec->codec_type == VT1802)
054d867e 1433 update_power_state(codec, 0x14, parm);
11890956 1434 else
054d867e
TI
1435 update_power_state(codec, 0x18, parm);
1436 update_power_state(codec, 0x34, parm);
3e95b9ab
LW
1437
1438 /* Mono Out */
1439 present = snd_hda_jack_detect(codec, 0x26);
1440
1441 parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
11890956
LW
1442 if (spec->codec_type == VT1802) {
1443 /* PW15 (33h), MW8(1ch), MUX8(3ch) */
054d867e
TI
1444 update_power_state(codec, 0x33, parm);
1445 update_power_state(codec, 0x1c, parm);
1446 update_power_state(codec, 0x3c, parm);
11890956
LW
1447 } else {
1448 /* PW15 (31h), MW8(17h), MUX8(3bh) */
054d867e
TI
1449 update_power_state(codec, 0x31, parm);
1450 update_power_state(codec, 0x17, parm);
1451 update_power_state(codec, 0x3b, parm);
11890956 1452 }
3e95b9ab
LW
1453 /* MW9 (21h) */
1454 if (imux_is_smixer || !is_aa_path_mute(codec))
054d867e 1455 update_power_state(codec, 0x21, AC_PWRST_D0);
3e95b9ab 1456 else
054d867e 1457 update_power_state(codec, 0x21, AC_PWRST_D3);
3e95b9ab 1458}
25eaba2f 1459
4b527b65
DH
1460/*
1461 * pin fix-up
1462 */
1463enum {
1464 VIA_FIXUP_INTMIC_BOOST,
d5266125 1465 VIA_FIXUP_ASUS_G75,
4b527b65
DH
1466};
1467
1468static void via_fixup_intmic_boost(struct hda_codec *codec,
1469 const struct hda_fixup *fix, int action)
1470{
1471 if (action == HDA_FIXUP_ACT_PRE_PROBE)
1472 override_mic_boost(codec, 0x30, 0, 2, 40);
1473}
1474
1475static const struct hda_fixup via_fixups[] = {
1476 [VIA_FIXUP_INTMIC_BOOST] = {
1477 .type = HDA_FIXUP_FUNC,
1478 .v.func = via_fixup_intmic_boost,
1479 },
d5266125
TI
1480 [VIA_FIXUP_ASUS_G75] = {
1481 .type = HDA_FIXUP_PINS,
1482 .v.pins = (const struct hda_pintbl[]) {
1483 /* set 0x24 and 0x33 as speakers */
1484 { 0x24, 0x991301f0 },
1485 { 0x33, 0x991301f1 }, /* subwoofer */
1486 { }
1487 }
1488 },
4b527b65
DH
1489};
1490
1491static const struct snd_pci_quirk vt2002p_fixups[] = {
d5266125 1492 SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
4b527b65
DH
1493 SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
1494 {}
1495};
1496
ef4da458
TI
1497/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
1498 * Replace this with mixer NID 0x1c
1499 */
1500static void fix_vt1802_connections(struct hda_codec *codec)
1501{
1502 static hda_nid_t conn_24[] = { 0x14, 0x1c };
1503 static hda_nid_t conn_33[] = { 0x1c };
1504
1505 snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
1506 snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
1507}
1508
25eaba2f
LW
1509/* patch for vt2002P */
1510static int patch_vt2002P(struct hda_codec *codec)
1511{
1512 struct via_spec *spec;
1513 int err;
1514
1515 /* create a codec specific record */
5b0cb1d8 1516 spec = via_new_spec(codec);
25eaba2f
LW
1517 if (spec == NULL)
1518 return -ENOMEM;
1519
b3f6008f 1520 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1521 override_mic_boost(codec, 0x2b, 0, 3, 40);
1522 override_mic_boost(codec, 0x29, 0, 3, 40);
ef4da458
TI
1523 if (spec->codec_type == VT1802)
1524 fix_vt1802_connections(codec);
30b45033 1525 add_secret_dac_path(codec);
620e2b28 1526
4b527b65
DH
1527 snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
1528 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1529
25eaba2f 1530 /* automatic parse from the BIOS config */
12daef65 1531 err = via_parse_auto_config(codec);
25eaba2f
LW
1532 if (err < 0) {
1533 via_free(codec);
1534 return err;
25eaba2f
LW
1535 }
1536
11890956 1537 if (spec->codec_type == VT1802)
4a918ffe 1538 spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs;
11890956 1539 else
4a918ffe 1540 spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs;
11890956 1541
25eaba2f
LW
1542 codec->patch_ops = via_patch_ops;
1543
3e95b9ab 1544 spec->set_widgets_power_state = set_widgets_power_state_vt2002P;
25eaba2f
LW
1545 return 0;
1546}
ab6734e7
LW
1547
1548/* for vt1812 */
1549
096a8854 1550static const struct hda_verb vt1812_init_verbs[] = {
ab6734e7
LW
1551 /* Enable Boost Volume backdoor */
1552 {0x1, 0xfb9, 0x24},
ab6734e7
LW
1553 /* Enable AOW0 to MW9 */
1554 {0x1, 0xfb8, 0xa8},
1555 { }
1556};
1557
3e95b9ab
LW
1558static void set_widgets_power_state_vt1812(struct hda_codec *codec)
1559{
1560 struct via_spec *spec = codec->spec;
3e95b9ab
LW
1561 unsigned int parm;
1562 unsigned int present;
3e95b9ab
LW
1563 /* inputs */
1564 /* PW 5/6/7 (29h/2ah/2bh) */
1565 parm = AC_PWRST_D3;
1566 set_pin_power_state(codec, 0x29, &parm);
1567 set_pin_power_state(codec, 0x2a, &parm);
1568 set_pin_power_state(codec, 0x2b, &parm);
1569 parm = AC_PWRST_D0;
1570 /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
054d867e
TI
1571 update_power_state(codec, 0x1e, parm);
1572 update_power_state(codec, 0x1f, parm);
1573 update_power_state(codec, 0x10, parm);
1574 update_power_state(codec, 0x11, parm);
3e95b9ab
LW
1575
1576 /* outputs */
1577 /* AOW0 (8h)*/
054d867e 1578 update_power_state(codec, 0x8, AC_PWRST_D0);
3e95b9ab
LW
1579
1580 /* PW4 (28h), MW4 (18h), MUX4(38h) */
1581 parm = AC_PWRST_D3;
1582 set_pin_power_state(codec, 0x28, &parm);
054d867e
TI
1583 update_power_state(codec, 0x18, parm);
1584 update_power_state(codec, 0x38, parm);
3e95b9ab
LW
1585
1586 /* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
1587 parm = AC_PWRST_D3;
1588 set_pin_power_state(codec, 0x25, &parm);
054d867e
TI
1589 update_power_state(codec, 0x15, parm);
1590 update_power_state(codec, 0x35, parm);
b3f6008f 1591 if (spec->gen.indep_hp_enabled)
054d867e 1592 update_power_state(codec, 0x9, AC_PWRST_D0);
3e95b9ab
LW
1593
1594 /* Internal Speaker */
1595 /* PW0 (24h), MW0(14h), MUX0(34h) */
1596 present = snd_hda_jack_detect(codec, 0x25);
1597
1598 parm = AC_PWRST_D3;
1599 set_pin_power_state(codec, 0x24, &parm);
1600 if (present) {
054d867e
TI
1601 update_power_state(codec, 0x14, AC_PWRST_D3);
1602 update_power_state(codec, 0x34, AC_PWRST_D3);
3e95b9ab 1603 } else {
054d867e
TI
1604 update_power_state(codec, 0x14, AC_PWRST_D0);
1605 update_power_state(codec, 0x34, AC_PWRST_D0);
3e95b9ab
LW
1606 }
1607
1608
1609 /* Mono Out */
1610 /* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
1611 present = snd_hda_jack_detect(codec, 0x28);
1612
1613 parm = AC_PWRST_D3;
1614 set_pin_power_state(codec, 0x31, &parm);
1615 if (present) {
054d867e
TI
1616 update_power_state(codec, 0x1c, AC_PWRST_D3);
1617 update_power_state(codec, 0x3c, AC_PWRST_D3);
1618 update_power_state(codec, 0x3e, AC_PWRST_D3);
3e95b9ab 1619 } else {
054d867e
TI
1620 update_power_state(codec, 0x1c, AC_PWRST_D0);
1621 update_power_state(codec, 0x3c, AC_PWRST_D0);
1622 update_power_state(codec, 0x3e, AC_PWRST_D0);
3e95b9ab
LW
1623 }
1624
1625 /* PW15 (33h), MW15 (1dh), MUX15(3dh) */
1626 parm = AC_PWRST_D3;
1627 set_pin_power_state(codec, 0x33, &parm);
054d867e
TI
1628 update_power_state(codec, 0x1d, parm);
1629 update_power_state(codec, 0x3d, parm);
3e95b9ab
LW
1630
1631}
ab6734e7
LW
1632
1633/* patch for vt1812 */
1634static int patch_vt1812(struct hda_codec *codec)
1635{
1636 struct via_spec *spec;
1637 int err;
1638
1639 /* create a codec specific record */
5b0cb1d8 1640 spec = via_new_spec(codec);
ab6734e7
LW
1641 if (spec == NULL)
1642 return -ENOMEM;
1643
b3f6008f 1644 spec->gen.mixer_nid = 0x21;
d7a99cce
TI
1645 override_mic_boost(codec, 0x2b, 0, 3, 40);
1646 override_mic_boost(codec, 0x29, 0, 3, 40);
30b45033 1647 add_secret_dac_path(codec);
620e2b28 1648
ab6734e7 1649 /* automatic parse from the BIOS config */
12daef65 1650 err = via_parse_auto_config(codec);
ab6734e7
LW
1651 if (err < 0) {
1652 via_free(codec);
1653 return err;
ab6734e7
LW
1654 }
1655
096a8854 1656 spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs;
ab6734e7 1657
ab6734e7
LW
1658 codec->patch_ops = via_patch_ops;
1659
3e95b9ab 1660 spec->set_widgets_power_state = set_widgets_power_state_vt1812;
ab6734e7
LW
1661 return 0;
1662}
1663
43737e0a
LW
1664/* patch for vt3476 */
1665
1666static const struct hda_verb vt3476_init_verbs[] = {
1667 /* Enable DMic 8/16/32K */
1668 {0x1, 0xF7B, 0x30},
1669 /* Enable Boost Volume backdoor */
1670 {0x1, 0xFB9, 0x20},
1671 /* Enable AOW-MW9 path */
1672 {0x1, 0xFB8, 0x10},
1673 { }
1674};
1675
1676static void set_widgets_power_state_vt3476(struct hda_codec *codec)
1677{
1678 struct via_spec *spec = codec->spec;
1679 int imux_is_smixer;
1680 unsigned int parm, parm2;
1681 /* MUX10 (1eh) = stereo mixer */
1682 imux_is_smixer =
1683 snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 4;
1684 /* inputs */
1685 /* PW 5/6/7 (29h/2ah/2bh) */
1686 parm = AC_PWRST_D3;
1687 set_pin_power_state(codec, 0x29, &parm);
1688 set_pin_power_state(codec, 0x2a, &parm);
1689 set_pin_power_state(codec, 0x2b, &parm);
1690 if (imux_is_smixer)
1691 parm = AC_PWRST_D0;
1692 /* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
1693 update_power_state(codec, 0x1e, parm);
1694 update_power_state(codec, 0x1f, parm);
1695 update_power_state(codec, 0x10, parm);
1696 update_power_state(codec, 0x11, parm);
1697
1698 /* outputs */
1699 /* PW3 (27h), MW3(37h), AOW3 (bh) */
1700 if (spec->codec_type == VT1705CF) {
1701 parm = AC_PWRST_D3;
1702 update_power_state(codec, 0x27, parm);
1703 update_power_state(codec, 0x37, parm);
1704 } else {
1705 parm = AC_PWRST_D3;
1706 set_pin_power_state(codec, 0x27, &parm);
1707 update_power_state(codec, 0x37, parm);
1708 }
1709
1710 /* PW2 (26h), MW2(36h), AOW2 (ah) */
1711 parm = AC_PWRST_D3;
1712 set_pin_power_state(codec, 0x26, &parm);
1713 update_power_state(codec, 0x36, parm);
b3f6008f 1714 if (smart51_enabled(codec)) {
43737e0a
LW
1715 /* PW7(2bh), MW7(3bh), MUX7(1Bh) */
1716 set_pin_power_state(codec, 0x2b, &parm);
1717 update_power_state(codec, 0x3b, parm);
1718 update_power_state(codec, 0x1b, parm);
1719 }
1720 update_conv_power_state(codec, 0xa, parm, 2);
1721
1722 /* PW1 (25h), MW1(35h), AOW1 (9h) */
1723 parm = AC_PWRST_D3;
1724 set_pin_power_state(codec, 0x25, &parm);
1725 update_power_state(codec, 0x35, parm);
b3f6008f 1726 if (smart51_enabled(codec)) {
43737e0a
LW
1727 /* PW6(2ah), MW6(3ah), MUX6(1ah) */
1728 set_pin_power_state(codec, 0x2a, &parm);
1729 update_power_state(codec, 0x3a, parm);
1730 update_power_state(codec, 0x1a, parm);
1731 }
1732 update_conv_power_state(codec, 0x9, parm, 1);
1733
1734 /* PW4 (28h), MW4 (38h), MUX4(18h), AOW3(bh)/AOW0(8h) */
1735 parm = AC_PWRST_D3;
1736 set_pin_power_state(codec, 0x28, &parm);
1737 update_power_state(codec, 0x38, parm);
1738 update_power_state(codec, 0x18, parm);
b3f6008f 1739 if (spec->gen.indep_hp_enabled)
43737e0a
LW
1740 update_conv_power_state(codec, 0xb, parm, 3);
1741 parm2 = parm; /* for pin 0x0b */
1742
1743 /* PW0 (24h), MW0(34h), MW9(3fh), AOW0 (8h) */
1744 parm = AC_PWRST_D3;
1745 set_pin_power_state(codec, 0x24, &parm);
1746 update_power_state(codec, 0x34, parm);
b3f6008f 1747 if (!spec->gen.indep_hp_enabled && parm2 != AC_PWRST_D3)
43737e0a
LW
1748 parm = parm2;
1749 update_conv_power_state(codec, 0x8, parm, 0);
1750 /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
1751 update_power_state(codec, 0x3f, imux_is_smixer ? AC_PWRST_D0 : parm);
1752}
1753
1754static int patch_vt3476(struct hda_codec *codec)
1755{
1756 struct via_spec *spec;
1757 int err;
1758
1759 /* create a codec specific record */
1760 spec = via_new_spec(codec);
1761 if (spec == NULL)
1762 return -ENOMEM;
1763
b3f6008f 1764 spec->gen.mixer_nid = 0x3f;
43737e0a
LW
1765 add_secret_dac_path(codec);
1766
1767 /* automatic parse from the BIOS config */
1768 err = via_parse_auto_config(codec);
1769 if (err < 0) {
1770 via_free(codec);
1771 return err;
1772 }
1773
1774 spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs;
1775
1776 codec->patch_ops = via_patch_ops;
1777
1778 spec->set_widgets_power_state = set_widgets_power_state_vt3476;
1779
1780 return 0;
1781}
1782
c577b8a1
JC
1783/*
1784 * patch entries
1785 */
90dd48a1 1786static const struct hda_codec_preset snd_hda_preset_via[] = {
3218c178
TI
1787 { .id = 0x11061708, .name = "VT1708", .patch = patch_vt1708},
1788 { .id = 0x11061709, .name = "VT1708", .patch = patch_vt1708},
1789 { .id = 0x1106170a, .name = "VT1708", .patch = patch_vt1708},
1790 { .id = 0x1106170b, .name = "VT1708", .patch = patch_vt1708},
1791 { .id = 0x1106e710, .name = "VT1709 10-Ch",
ddd304d8 1792 .patch = patch_vt1709},
3218c178 1793 { .id = 0x1106e711, .name = "VT1709 10-Ch",
ddd304d8 1794 .patch = patch_vt1709},
3218c178 1795 { .id = 0x1106e712, .name = "VT1709 10-Ch",
ddd304d8 1796 .patch = patch_vt1709},
3218c178 1797 { .id = 0x1106e713, .name = "VT1709 10-Ch",
ddd304d8 1798 .patch = patch_vt1709},
3218c178 1799 { .id = 0x1106e714, .name = "VT1709 6-Ch",
ddd304d8 1800 .patch = patch_vt1709},
3218c178 1801 { .id = 0x1106e715, .name = "VT1709 6-Ch",
ddd304d8 1802 .patch = patch_vt1709},
3218c178 1803 { .id = 0x1106e716, .name = "VT1709 6-Ch",
ddd304d8 1804 .patch = patch_vt1709},
3218c178 1805 { .id = 0x1106e717, .name = "VT1709 6-Ch",
ddd304d8 1806 .patch = patch_vt1709},
3218c178 1807 { .id = 0x1106e720, .name = "VT1708B 8-Ch",
ddd304d8 1808 .patch = patch_vt1708B},
3218c178 1809 { .id = 0x1106e721, .name = "VT1708B 8-Ch",
ddd304d8 1810 .patch = patch_vt1708B},
3218c178 1811 { .id = 0x1106e722, .name = "VT1708B 8-Ch",
ddd304d8 1812 .patch = patch_vt1708B},
3218c178 1813 { .id = 0x1106e723, .name = "VT1708B 8-Ch",
ddd304d8 1814 .patch = patch_vt1708B},
3218c178 1815 { .id = 0x1106e724, .name = "VT1708B 4-Ch",
ddd304d8 1816 .patch = patch_vt1708B},
3218c178 1817 { .id = 0x1106e725, .name = "VT1708B 4-Ch",
ddd304d8 1818 .patch = patch_vt1708B},
3218c178 1819 { .id = 0x1106e726, .name = "VT1708B 4-Ch",
ddd304d8 1820 .patch = patch_vt1708B},
3218c178 1821 { .id = 0x1106e727, .name = "VT1708B 4-Ch",
ddd304d8 1822 .patch = patch_vt1708B},
3218c178 1823 { .id = 0x11060397, .name = "VT1708S",
d949cac1 1824 .patch = patch_vt1708S},
3218c178 1825 { .id = 0x11061397, .name = "VT1708S",
d949cac1 1826 .patch = patch_vt1708S},
3218c178 1827 { .id = 0x11062397, .name = "VT1708S",
d949cac1 1828 .patch = patch_vt1708S},
3218c178 1829 { .id = 0x11063397, .name = "VT1708S",
d949cac1 1830 .patch = patch_vt1708S},
bc92df7f 1831 { .id = 0x11064397, .name = "VT1705",
d949cac1 1832 .patch = patch_vt1708S},
3218c178 1833 { .id = 0x11065397, .name = "VT1708S",
d949cac1 1834 .patch = patch_vt1708S},
3218c178 1835 { .id = 0x11066397, .name = "VT1708S",
d949cac1 1836 .patch = patch_vt1708S},
3218c178 1837 { .id = 0x11067397, .name = "VT1708S",
d949cac1 1838 .patch = patch_vt1708S},
3218c178 1839 { .id = 0x11060398, .name = "VT1702",
d949cac1 1840 .patch = patch_vt1702},
3218c178 1841 { .id = 0x11061398, .name = "VT1702",
d949cac1 1842 .patch = patch_vt1702},
3218c178 1843 { .id = 0x11062398, .name = "VT1702",
d949cac1 1844 .patch = patch_vt1702},
3218c178 1845 { .id = 0x11063398, .name = "VT1702",
d949cac1 1846 .patch = patch_vt1702},
3218c178 1847 { .id = 0x11064398, .name = "VT1702",
d949cac1 1848 .patch = patch_vt1702},
3218c178 1849 { .id = 0x11065398, .name = "VT1702",
d949cac1 1850 .patch = patch_vt1702},
3218c178 1851 { .id = 0x11066398, .name = "VT1702",
d949cac1 1852 .patch = patch_vt1702},
3218c178 1853 { .id = 0x11067398, .name = "VT1702",
d949cac1 1854 .patch = patch_vt1702},
eb7188ca
LW
1855 { .id = 0x11060428, .name = "VT1718S",
1856 .patch = patch_vt1718S},
1857 { .id = 0x11064428, .name = "VT1718S",
1858 .patch = patch_vt1718S},
bb3c6bfc
LW
1859 { .id = 0x11060441, .name = "VT2020",
1860 .patch = patch_vt1718S},
1861 { .id = 0x11064441, .name = "VT1828S",
1862 .patch = patch_vt1718S},
f3db423d
LW
1863 { .id = 0x11060433, .name = "VT1716S",
1864 .patch = patch_vt1716S},
1865 { .id = 0x1106a721, .name = "VT1716S",
1866 .patch = patch_vt1716S},
25eaba2f
LW
1867 { .id = 0x11060438, .name = "VT2002P", .patch = patch_vt2002P},
1868 { .id = 0x11064438, .name = "VT2002P", .patch = patch_vt2002P},
ab6734e7 1869 { .id = 0x11060448, .name = "VT1812", .patch = patch_vt1812},
36dd5c4a
LW
1870 { .id = 0x11060440, .name = "VT1818S",
1871 .patch = patch_vt1708S},
11890956
LW
1872 { .id = 0x11060446, .name = "VT1802",
1873 .patch = patch_vt2002P},
1874 { .id = 0x11068446, .name = "VT1802",
1875 .patch = patch_vt2002P},
43737e0a
LW
1876 { .id = 0x11064760, .name = "VT1705CF",
1877 .patch = patch_vt3476},
6121b84a
LW
1878 { .id = 0x11064761, .name = "VT1708SCE",
1879 .patch = patch_vt3476},
1880 { .id = 0x11064762, .name = "VT1808",
1881 .patch = patch_vt3476},
c577b8a1
JC
1882 {} /* terminator */
1883};
1289e9e8
TI
1884
1885MODULE_ALIAS("snd-hda-codec-id:1106*");
1886
1887static struct hda_codec_preset_list via_list = {
1888 .preset = snd_hda_preset_via,
1889 .owner = THIS_MODULE,
1890};
1891
1892MODULE_LICENSE("GPL");
1893MODULE_DESCRIPTION("VIA HD-audio codec");
1894
1895static int __init patch_via_init(void)
1896{
1897 return snd_hda_add_codec_preset(&via_list);
1898}
1899
1900static void __exit patch_via_exit(void)
1901{
1902 snd_hda_delete_codec_preset(&via_list);
1903}
1904
1905module_init(patch_via_init)
1906module_exit(patch_via_exit)
This page took 0.567927 seconds and 5 git commands to generate.