]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - sound/pci/hda/patch_realtek.c
Merge tag 'asoc-v3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound...
[mirror_ubuntu-eoan-kernel.git] / sound / pci / hda / patch_realtek.c
CommitLineData
1da177e4
LT
1/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
1d045db9 4 * HD audio interface patch for Realtek ALC codecs
1da177e4 5 *
df694daa
KY
6 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
1da177e4 8 * Takashi Iwai <tiwai@suse.de>
409a3e98 9 * Jonathan Woithe <jwoithe@just42.net>
1da177e4
LT
10 *
11 * This driver is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This driver is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
1da177e4
LT
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
08fb0d0e 30#include <linux/dmi.h>
da155d5b 31#include <linux/module.h>
1da177e4 32#include <sound/core.h>
9ad0e496 33#include <sound/jack.h>
1da177e4
LT
34#include "hda_codec.h"
35#include "hda_local.h"
23d30f28 36#include "hda_auto_parser.h"
1835a0f9 37#include "hda_jack.h"
08c189f2 38#include "hda_generic.h"
1da177e4 39
cd63a5ff
TI
40/* keep halting ALC5505 DSP, for power saving */
41#define HALT_REALTEK_ALC5505
42
1d045db9 43/* unsol event tags */
08c189f2 44#define ALC_DCVOL_EVENT 0x08
d4a86d81 45
df694daa
KY
46/* for GPIO Poll */
47#define GPIO_MASK 0x03
48
4a79ba34
TI
49/* extra amp-initialization sequence types */
50enum {
51 ALC_INIT_NONE,
52 ALC_INIT_DEFAULT,
53 ALC_INIT_GPIO1,
54 ALC_INIT_GPIO2,
55 ALC_INIT_GPIO3,
56};
57
73bdd597
DH
58enum {
59 ALC_HEADSET_MODE_UNKNOWN,
60 ALC_HEADSET_MODE_UNPLUGGED,
61 ALC_HEADSET_MODE_HEADSET,
62 ALC_HEADSET_MODE_MIC,
63 ALC_HEADSET_MODE_HEADPHONE,
64};
65
66enum {
67 ALC_HEADSET_TYPE_UNKNOWN,
68 ALC_HEADSET_TYPE_CTIA,
69 ALC_HEADSET_TYPE_OMTP,
70};
71
da00c244
KY
72struct alc_customize_define {
73 unsigned int sku_cfg;
74 unsigned char port_connectivity;
75 unsigned char check_sum;
76 unsigned char customization;
77 unsigned char external_amp;
78 unsigned int enable_pcbeep:1;
79 unsigned int platform_type:1;
80 unsigned int swap:1;
81 unsigned int override:1;
90622917 82 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
da00c244
KY
83};
84
1da177e4 85struct alc_spec {
08c189f2 86 struct hda_gen_spec gen; /* must be at head */
23d30f28 87
1da177e4 88 /* codec parameterization */
a9111321 89 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
1da177e4 90 unsigned int num_mixers;
45bdd1c1 91 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
1da177e4 92
da00c244 93 struct alc_customize_define cdefine;
08c189f2 94 unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
834be88d 95
08c189f2
TI
96 /* inverted dmic fix */
97 unsigned int inv_dmic_fixup:1; /* has inverted digital-mic workaround */
98 unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */
125821ae 99 hda_nid_t inv_dmic_pin;
834be88d 100
08fb0d0e
TI
101 /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
102 int mute_led_polarity;
103 hda_nid_t mute_led_nid;
104
9f5c6faf
TI
105 unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
106
73bdd597
DH
107 hda_nid_t headset_mic_pin;
108 hda_nid_t headphone_mic_pin;
109 int current_headset_mode;
110 int current_headset_type;
111
ae6b813a
TI
112 /* hooks */
113 void (*init_hook)(struct hda_codec *codec);
83012a7c 114#ifdef CONFIG_PM
c97259df 115 void (*power_hook)(struct hda_codec *codec);
f5de24b0 116#endif
1c716153 117 void (*shutup)(struct hda_codec *codec);
d922b51d 118
4a79ba34 119 int init_amp;
d433a678 120 int codec_variant; /* flag for other variants */
97a26570
KY
121 unsigned int has_alc5505_dsp:1;
122 unsigned int no_depop_delay:1;
e64f14f4 123
2c3bf9ab
TI
124 /* for PLL fix */
125 hda_nid_t pll_nid;
126 unsigned int pll_coef_idx, pll_coef_bit;
1bb7e43e 127 unsigned int coef0;
df694daa
KY
128};
129
d88897ea 130/*
1d045db9
TI
131 * Append the given mixer and verb elements for the later use
132 * The mixer array is referred in build_controls(), and init_verbs are
133 * called in init().
d88897ea 134 */
a9111321 135static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
d88897ea
TI
136{
137 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
138 return;
139 spec->mixers[spec->num_mixers++] = mix;
140}
141
df694daa 142/*
1d045db9 143 * GPIO setup tables, used in initialization
df694daa 144 */
bc9f98a9 145/* Enable GPIO mask and set output */
a9111321 146static const struct hda_verb alc_gpio1_init_verbs[] = {
bc9f98a9
KY
147 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
148 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
149 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
150 { }
151};
152
a9111321 153static const struct hda_verb alc_gpio2_init_verbs[] = {
bc9f98a9
KY
154 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
155 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
156 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
157 { }
158};
159
a9111321 160static const struct hda_verb alc_gpio3_init_verbs[] = {
bdd148a3
KY
161 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
162 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
163 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
164 { }
165};
166
2c3bf9ab
TI
167/*
168 * Fix hardware PLL issue
169 * On some codecs, the analog PLL gating control must be off while
170 * the default value is 1.
171 */
172static void alc_fix_pll(struct hda_codec *codec)
173{
174 struct alc_spec *spec = codec->spec;
175 unsigned int val;
176
177 if (!spec->pll_nid)
178 return;
179 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
180 spec->pll_coef_idx);
181 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
182 AC_VERB_GET_PROC_COEF, 0);
183 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
184 spec->pll_coef_idx);
185 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
186 val & ~(1 << spec->pll_coef_bit));
187}
188
189static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
190 unsigned int coef_idx, unsigned int coef_bit)
191{
192 struct alc_spec *spec = codec->spec;
193 spec->pll_nid = nid;
194 spec->pll_coef_idx = coef_idx;
195 spec->pll_coef_bit = coef_bit;
196 alc_fix_pll(codec);
197}
198
cf5a2279 199/* update the master volume per volume-knob's unsol event */
29adc4b9 200static void alc_update_knob_master(struct hda_codec *codec, struct hda_jack_tbl *jack)
cf5a2279
TI
201{
202 unsigned int val;
203 struct snd_kcontrol *kctl;
204 struct snd_ctl_elem_value *uctl;
205
206 kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
207 if (!kctl)
208 return;
209 uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
210 if (!uctl)
211 return;
29adc4b9 212 val = snd_hda_codec_read(codec, jack->nid, 0,
cf5a2279
TI
213 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
214 val &= HDA_AMP_VOLMASK;
215 uctl->value.integer.value[0] = val;
216 uctl->value.integer.value[1] = val;
217 kctl->put(kctl, uctl);
218 kfree(uctl);
219}
220
29adc4b9 221static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
f21d78e2 222{
29adc4b9
DH
223 /* For some reason, the res given from ALC880 is broken.
224 Here we adjust it properly. */
225 snd_hda_jack_unsol_event(codec, res >> 2);
f21d78e2
TI
226}
227
f9423e7a
KY
228/* additional initialization for ALC888 variants */
229static void alc888_coef_init(struct hda_codec *codec)
230{
231 unsigned int tmp;
232
233 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
234 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
235 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
37db623a 236 if ((tmp & 0xf0) == 0x20)
f9423e7a
KY
237 /* alc888S-VC */
238 snd_hda_codec_read(codec, 0x20, 0,
239 AC_VERB_SET_PROC_COEF, 0x830);
240 else
241 /* alc888-VB */
242 snd_hda_codec_read(codec, 0x20, 0,
243 AC_VERB_SET_PROC_COEF, 0x3030);
244}
245
1d045db9 246/* additional initialization for ALC889 variants */
87a8c370
JK
247static void alc889_coef_init(struct hda_codec *codec)
248{
249 unsigned int tmp;
250
251 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
252 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
253 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
254 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
255}
256
3fb4a508
TI
257/* turn on/off EAPD control (only if available) */
258static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
259{
260 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
261 return;
262 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
263 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
264 on ? 2 : 0);
265}
266
691f1fcc
TI
267/* turn on/off EAPD controls of the codec */
268static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
269{
270 /* We currently only handle front, HP */
39fa84e9
TI
271 static hda_nid_t pins[] = {
272 0x0f, 0x10, 0x14, 0x15, 0
273 };
274 hda_nid_t *p;
275 for (p = pins; *p; p++)
276 set_eapd(codec, *p, on);
691f1fcc
TI
277}
278
1c716153
TI
279/* generic shutup callback;
280 * just turning off EPAD and a little pause for avoiding pop-noise
281 */
282static void alc_eapd_shutup(struct hda_codec *codec)
283{
97a26570
KY
284 struct alc_spec *spec = codec->spec;
285
1c716153 286 alc_auto_setup_eapd(codec, false);
97a26570
KY
287 if (!spec->no_depop_delay)
288 msleep(200);
9bfb2844 289 snd_hda_shutup_pins(codec);
1c716153
TI
290}
291
1d045db9 292/* generic EAPD initialization */
4a79ba34 293static void alc_auto_init_amp(struct hda_codec *codec, int type)
bc9f98a9 294{
4a79ba34 295 unsigned int tmp;
bc9f98a9 296
39fa84e9 297 alc_auto_setup_eapd(codec, true);
4a79ba34
TI
298 switch (type) {
299 case ALC_INIT_GPIO1:
bc9f98a9
KY
300 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
301 break;
4a79ba34 302 case ALC_INIT_GPIO2:
bc9f98a9
KY
303 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
304 break;
4a79ba34 305 case ALC_INIT_GPIO3:
bdd148a3
KY
306 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
307 break;
4a79ba34 308 case ALC_INIT_DEFAULT:
c9b58006
KY
309 switch (codec->vendor_id) {
310 case 0x10ec0260:
311 snd_hda_codec_write(codec, 0x1a, 0,
312 AC_VERB_SET_COEF_INDEX, 7);
313 tmp = snd_hda_codec_read(codec, 0x1a, 0,
314 AC_VERB_GET_PROC_COEF, 0);
315 snd_hda_codec_write(codec, 0x1a, 0,
316 AC_VERB_SET_COEF_INDEX, 7);
317 snd_hda_codec_write(codec, 0x1a, 0,
318 AC_VERB_SET_PROC_COEF,
319 tmp | 0x2010);
320 break;
321 case 0x10ec0262:
322 case 0x10ec0880:
323 case 0x10ec0882:
324 case 0x10ec0883:
325 case 0x10ec0885:
4a5a4c56 326 case 0x10ec0887:
20b67ddd 327 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
87a8c370 328 alc889_coef_init(codec);
c9b58006 329 break;
f9423e7a 330 case 0x10ec0888:
4a79ba34 331 alc888_coef_init(codec);
f9423e7a 332 break;
0aea778e 333#if 0 /* XXX: This may cause the silent output on speaker on some machines */
c9b58006
KY
334 case 0x10ec0267:
335 case 0x10ec0268:
336 snd_hda_codec_write(codec, 0x20, 0,
337 AC_VERB_SET_COEF_INDEX, 7);
338 tmp = snd_hda_codec_read(codec, 0x20, 0,
339 AC_VERB_GET_PROC_COEF, 0);
340 snd_hda_codec_write(codec, 0x20, 0,
ea1fb29a 341 AC_VERB_SET_COEF_INDEX, 7);
c9b58006
KY
342 snd_hda_codec_write(codec, 0x20, 0,
343 AC_VERB_SET_PROC_COEF,
344 tmp | 0x3000);
345 break;
0aea778e 346#endif /* XXX */
bc9f98a9 347 }
4a79ba34
TI
348 break;
349 }
350}
351
08c189f2 352
1d045db9 353/*
08c189f2 354 * Realtek SSID verification
1d045db9 355 */
42cf0d01 356
08c189f2
TI
357/* Could be any non-zero and even value. When used as fixup, tells
358 * the driver to ignore any present sku defines.
359 */
360#define ALC_FIXUP_SKU_IGNORE (2)
1a1455de 361
08c189f2
TI
362static void alc_fixup_sku_ignore(struct hda_codec *codec,
363 const struct hda_fixup *fix, int action)
1a1455de 364{
1a1455de 365 struct alc_spec *spec = codec->spec;
08c189f2
TI
366 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
367 spec->cdefine.fixup = 1;
368 spec->cdefine.sku_cfg = ALC_FIXUP_SKU_IGNORE;
1a1455de 369 }
1a1455de
TI
370}
371
b5c6611f
ML
372static void alc_fixup_no_depop_delay(struct hda_codec *codec,
373 const struct hda_fixup *fix, int action)
374{
375 struct alc_spec *spec = codec->spec;
376
84d2dc3e 377 if (action == HDA_FIXUP_ACT_PROBE) {
b5c6611f 378 spec->no_depop_delay = 1;
84d2dc3e
ML
379 codec->depop_delay = 0;
380 }
b5c6611f
ML
381}
382
08c189f2 383static int alc_auto_parse_customize_define(struct hda_codec *codec)
4a79ba34 384{
08c189f2
TI
385 unsigned int ass, tmp, i;
386 unsigned nid = 0;
4a79ba34
TI
387 struct alc_spec *spec = codec->spec;
388
08c189f2 389 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
4a79ba34 390
08c189f2
TI
391 if (spec->cdefine.fixup) {
392 ass = spec->cdefine.sku_cfg;
393 if (ass == ALC_FIXUP_SKU_IGNORE)
394 return -1;
395 goto do_sku;
bb35febd
TI
396 }
397
08c189f2
TI
398 ass = codec->subsystem_id & 0xffff;
399 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
400 goto do_sku;
4a79ba34 401
08c189f2
TI
402 nid = 0x1d;
403 if (codec->vendor_id == 0x10ec0260)
404 nid = 0x17;
405 ass = snd_hda_codec_get_pincfg(codec, nid);
42cf0d01 406
08c189f2
TI
407 if (!(ass & 1)) {
408 printk(KERN_INFO "hda_codec: %s: SKU not ready 0x%08x\n",
409 codec->chip_name, ass);
410 return -1;
42cf0d01
DH
411 }
412
08c189f2
TI
413 /* check sum */
414 tmp = 0;
415 for (i = 1; i < 16; i++) {
416 if ((ass >> i) & 1)
417 tmp++;
ae8a60a5 418 }
08c189f2
TI
419 if (((ass >> 16) & 0xf) != tmp)
420 return -1;
ae8a60a5 421
da00c244
KY
422 spec->cdefine.port_connectivity = ass >> 30;
423 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
424 spec->cdefine.check_sum = (ass >> 16) & 0xf;
425 spec->cdefine.customization = ass >> 8;
426do_sku:
427 spec->cdefine.sku_cfg = ass;
428 spec->cdefine.external_amp = (ass & 0x38) >> 3;
429 spec->cdefine.platform_type = (ass & 0x4) >> 2;
430 spec->cdefine.swap = (ass & 0x2) >> 1;
431 spec->cdefine.override = ass & 0x1;
432
433 snd_printd("SKU: Nid=0x%x sku_cfg=0x%08x\n",
434 nid, spec->cdefine.sku_cfg);
435 snd_printd("SKU: port_connectivity=0x%x\n",
436 spec->cdefine.port_connectivity);
437 snd_printd("SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
438 snd_printd("SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
439 snd_printd("SKU: customization=0x%08x\n", spec->cdefine.customization);
440 snd_printd("SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
441 snd_printd("SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
442 snd_printd("SKU: swap=0x%x\n", spec->cdefine.swap);
443 snd_printd("SKU: override=0x%x\n", spec->cdefine.override);
444
445 return 0;
446}
447
08c189f2
TI
448/* return the position of NID in the list, or -1 if not found */
449static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
450{
451 int i;
452 for (i = 0; i < nums; i++)
453 if (list[i] == nid)
454 return i;
455 return -1;
456}
1d045db9 457/* return true if the given NID is found in the list */
3af9ee6b
TI
458static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
459{
21268961 460 return find_idx_in_nid_list(nid, list, nums) >= 0;
3af9ee6b
TI
461}
462
4a79ba34
TI
463/* check subsystem ID and set up device-specific initialization;
464 * return 1 if initialized, 0 if invalid SSID
465 */
466/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
467 * 31 ~ 16 : Manufacture ID
468 * 15 ~ 8 : SKU ID
469 * 7 ~ 0 : Assembly ID
470 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
471 */
472static int alc_subsystem_id(struct hda_codec *codec,
473 hda_nid_t porta, hda_nid_t porte,
6227cdce 474 hda_nid_t portd, hda_nid_t porti)
4a79ba34
TI
475{
476 unsigned int ass, tmp, i;
477 unsigned nid;
478 struct alc_spec *spec = codec->spec;
479
90622917
DH
480 if (spec->cdefine.fixup) {
481 ass = spec->cdefine.sku_cfg;
482 if (ass == ALC_FIXUP_SKU_IGNORE)
483 return 0;
484 goto do_sku;
485 }
486
4a79ba34
TI
487 ass = codec->subsystem_id & 0xffff;
488 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
489 goto do_sku;
490
491 /* invalid SSID, check the special NID pin defcfg instead */
492 /*
def319f9 493 * 31~30 : port connectivity
4a79ba34
TI
494 * 29~21 : reserve
495 * 20 : PCBEEP input
496 * 19~16 : Check sum (15:1)
497 * 15~1 : Custom
498 * 0 : override
499 */
500 nid = 0x1d;
501 if (codec->vendor_id == 0x10ec0260)
502 nid = 0x17;
503 ass = snd_hda_codec_get_pincfg(codec, nid);
504 snd_printd("realtek: No valid SSID, "
505 "checking pincfg 0x%08x for NID 0x%x\n",
cb6605c1 506 ass, nid);
6227cdce 507 if (!(ass & 1))
4a79ba34
TI
508 return 0;
509 if ((ass >> 30) != 1) /* no physical connection */
510 return 0;
511
512 /* check sum */
513 tmp = 0;
514 for (i = 1; i < 16; i++) {
515 if ((ass >> i) & 1)
516 tmp++;
517 }
518 if (((ass >> 16) & 0xf) != tmp)
519 return 0;
520do_sku:
521 snd_printd("realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
522 ass & 0xffff, codec->vendor_id);
523 /*
524 * 0 : override
525 * 1 : Swap Jack
526 * 2 : 0 --> Desktop, 1 --> Laptop
527 * 3~5 : External Amplifier control
528 * 7~6 : Reserved
529 */
530 tmp = (ass & 0x38) >> 3; /* external Amp control */
531 switch (tmp) {
532 case 1:
533 spec->init_amp = ALC_INIT_GPIO1;
534 break;
535 case 3:
536 spec->init_amp = ALC_INIT_GPIO2;
537 break;
538 case 7:
539 spec->init_amp = ALC_INIT_GPIO3;
540 break;
541 case 5:
5a8cfb4e 542 default:
4a79ba34 543 spec->init_amp = ALC_INIT_DEFAULT;
bc9f98a9
KY
544 break;
545 }
ea1fb29a 546
8c427226 547 /* is laptop or Desktop and enable the function "Mute internal speaker
c9b58006
KY
548 * when the external headphone out jack is plugged"
549 */
8c427226 550 if (!(ass & 0x8000))
4a79ba34 551 return 1;
c9b58006
KY
552 /*
553 * 10~8 : Jack location
554 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
555 * 14~13: Resvered
556 * 15 : 1 --> enable the function "Mute internal speaker
557 * when the external headphone out jack is plugged"
558 */
08c189f2
TI
559 if (!spec->gen.autocfg.hp_pins[0] &&
560 !(spec->gen.autocfg.line_out_pins[0] &&
561 spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
01d4825d 562 hda_nid_t nid;
c9b58006
KY
563 tmp = (ass >> 11) & 0x3; /* HP to chassis */
564 if (tmp == 0)
01d4825d 565 nid = porta;
c9b58006 566 else if (tmp == 1)
01d4825d 567 nid = porte;
c9b58006 568 else if (tmp == 2)
01d4825d 569 nid = portd;
6227cdce
KY
570 else if (tmp == 3)
571 nid = porti;
08c189f2
TI
572 if (found_in_nid_list(nid, spec->gen.autocfg.line_out_pins,
573 spec->gen.autocfg.line_outs))
3af9ee6b 574 return 1;
08c189f2 575 spec->gen.autocfg.hp_pins[0] = nid;
c9b58006 576 }
4a79ba34
TI
577 return 1;
578}
ea1fb29a 579
3e6179b8
TI
580/* Check the validity of ALC subsystem-id
581 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
582static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
4a79ba34 583{
3e6179b8 584 if (!alc_subsystem_id(codec, ports[0], ports[1], ports[2], ports[3])) {
4a79ba34
TI
585 struct alc_spec *spec = codec->spec;
586 snd_printd("realtek: "
587 "Enable default setup for auto mode as fallback\n");
588 spec->init_amp = ALC_INIT_DEFAULT;
4a79ba34 589 }
21268961 590}
1a1455de 591
1d045db9
TI
592/*
593 * COEF access helper functions
594 */
9a22a8f5
KY
595
596static int alc_read_coefex_idx(struct hda_codec *codec,
597 hda_nid_t nid,
598 unsigned int coef_idx)
274693f3
KY
599{
600 unsigned int val;
9a22a8f5 601 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX,
274693f3 602 coef_idx);
9a22a8f5 603 val = snd_hda_codec_read(codec, nid, 0,
274693f3
KY
604 AC_VERB_GET_PROC_COEF, 0);
605 return val;
606}
607
9a22a8f5
KY
608#define alc_read_coef_idx(codec, coef_idx) \
609 alc_read_coefex_idx(codec, 0x20, coef_idx)
610
611static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
612 unsigned int coef_idx,
977ddd6b
KY
613 unsigned int coef_val)
614{
9a22a8f5 615 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX,
977ddd6b 616 coef_idx);
9a22a8f5 617 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF,
977ddd6b
KY
618 coef_val);
619}
620
9a22a8f5
KY
621#define alc_write_coef_idx(codec, coef_idx, coef_val) \
622 alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val)
623
1bb7e43e
TI
624/* a special bypass for COEF 0; read the cached value at the second time */
625static unsigned int alc_get_coef0(struct hda_codec *codec)
626{
627 struct alc_spec *spec = codec->spec;
628 if (!spec->coef0)
629 spec->coef0 = alc_read_coef_idx(codec, 0);
630 return spec->coef0;
631}
632
1d045db9 633/*
ef8ef5fb 634 */
f9e336f6 635
08c189f2 636static hda_nid_t get_adc_nid(struct hda_codec *codec, int adc_idx, int imux_idx)
f9e336f6 637{
08c189f2
TI
638 struct hda_gen_spec *spec = codec->spec;
639 if (spec->dyn_adc_switch)
640 adc_idx = spec->dyn_adc_idx[imux_idx];
641 return spec->adc_nids[adc_idx];
f9e336f6
TI
642}
643
666a70d4 644static void alc_inv_dmic_sync_adc(struct hda_codec *codec, int adc_idx)
f9e336f6 645{
f9e336f6 646 struct alc_spec *spec = codec->spec;
08c189f2 647 struct hda_input_mux *imux = &spec->gen.input_mux;
666a70d4
TI
648 struct nid_path *path;
649 hda_nid_t nid;
650 int i, dir, parm;
651 unsigned int val;
f9e336f6 652
666a70d4 653 for (i = 0; i < imux->num_items; i++) {
08c189f2 654 if (spec->gen.imux_pins[i] == spec->inv_dmic_pin)
666a70d4 655 break;
a23b688f 656 }
666a70d4
TI
657 if (i >= imux->num_items)
658 return;
a23b688f 659
08c189f2
TI
660 path = snd_hda_get_nid_path(codec, spec->inv_dmic_pin,
661 get_adc_nid(codec, adc_idx, i));
666a70d4
TI
662 val = path->ctls[NID_PATH_MUTE_CTL];
663 if (!val)
664 return;
665 nid = get_amp_nid_(val);
666 dir = get_amp_direction_(val);
667 parm = AC_AMP_SET_RIGHT |
668 (dir == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT);
a23b688f 669
c4f3ebed 670 /* flush all cached amps at first */
dc870f38 671 snd_hda_codec_flush_cache(codec);
a23b688f 672
666a70d4
TI
673 /* we care only right channel */
674 val = snd_hda_codec_amp_read(codec, nid, 1, dir, 0);
675 if (val & 0x80) /* if already muted, we don't need to touch */
676 return;
677 val |= 0x80;
678 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
679 parm | val);
f9e336f6
TI
680}
681
125821ae
TI
682/*
683 * Inverted digital-mic handling
684 *
685 * First off, it's a bit tricky. The "Inverted Internal Mic Capture Switch"
686 * gives the additional mute only to the right channel of the digital mic
687 * capture stream. This is a workaround for avoiding the almost silence
688 * by summing the stereo stream from some (known to be ForteMedia)
689 * digital mic unit.
690 *
691 * The logic is to call alc_inv_dmic_sync() after each action (possibly)
692 * modifying ADC amp. When the mute flag is set, it mutes the R-channel
693 * without caching so that the cache can still keep the original value.
694 * The cached value is then restored when the flag is set off or any other
695 * than d-mic is used as the current input source.
696 */
697static void alc_inv_dmic_sync(struct hda_codec *codec, bool force)
698{
699 struct alc_spec *spec = codec->spec;
666a70d4 700 int src, nums;
125821ae
TI
701
702 if (!spec->inv_dmic_fixup)
703 return;
704 if (!spec->inv_dmic_muted && !force)
705 return;
08c189f2 706 nums = spec->gen.dyn_adc_switch ? 1 : spec->gen.num_adc_nids;
666a70d4 707 for (src = 0; src < nums; src++) {
125821ae 708 bool dmic_fixup = false;
125821ae
TI
709
710 if (spec->inv_dmic_muted &&
08c189f2 711 spec->gen.imux_pins[spec->gen.cur_mux[src]] == spec->inv_dmic_pin)
125821ae
TI
712 dmic_fixup = true;
713 if (!dmic_fixup && !force)
714 continue;
666a70d4 715 alc_inv_dmic_sync_adc(codec, src);
125821ae
TI
716 }
717}
718
a90229e0
TI
719static void alc_inv_dmic_hook(struct hda_codec *codec,
720 struct snd_ctl_elem_value *ucontrol)
08c189f2
TI
721{
722 alc_inv_dmic_sync(codec, false);
723}
724
125821ae
TI
725static int alc_inv_dmic_sw_get(struct snd_kcontrol *kcontrol,
726 struct snd_ctl_elem_value *ucontrol)
727{
728 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
729 struct alc_spec *spec = codec->spec;
730
731 ucontrol->value.integer.value[0] = !spec->inv_dmic_muted;
732 return 0;
733}
734
735static int alc_inv_dmic_sw_put(struct snd_kcontrol *kcontrol,
736 struct snd_ctl_elem_value *ucontrol)
737{
738 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
739 struct alc_spec *spec = codec->spec;
740 unsigned int val = !ucontrol->value.integer.value[0];
741
742 if (val == spec->inv_dmic_muted)
743 return 0;
744 spec->inv_dmic_muted = val;
745 alc_inv_dmic_sync(codec, true);
746 return 0;
747}
748
749static const struct snd_kcontrol_new alc_inv_dmic_sw = {
750 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
bc549767 751 .name = "Inverted Internal Mic Capture Switch",
125821ae
TI
752 .info = snd_ctl_boolean_mono_info,
753 .get = alc_inv_dmic_sw_get,
754 .put = alc_inv_dmic_sw_put,
755};
756
757static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid)
758{
759 struct alc_spec *spec = codec->spec;
668d1e96 760
08c189f2 761 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &alc_inv_dmic_sw))
125821ae
TI
762 return -ENOMEM;
763 spec->inv_dmic_fixup = 1;
764 spec->inv_dmic_muted = 0;
765 spec->inv_dmic_pin = nid;
08c189f2 766 spec->gen.cap_sync_hook = alc_inv_dmic_hook;
125821ae
TI
767 return 0;
768}
769
6e72aa5f
TI
770/* typically the digital mic is put at node 0x12 */
771static void alc_fixup_inv_dmic_0x12(struct hda_codec *codec,
1727a771 772 const struct hda_fixup *fix, int action)
6e72aa5f 773{
1727a771 774 if (action == HDA_FIXUP_ACT_PROBE)
6e72aa5f
TI
775 alc_add_inv_dmic_mixer(codec, 0x12);
776}
777
e9edcee0 778
1d045db9
TI
779#ifdef CONFIG_SND_HDA_INPUT_BEEP
780/* additional beep mixers; the actual parameters are overwritten at build */
781static const struct snd_kcontrol_new alc_beep_mixer[] = {
782 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
783 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
16ded525
TI
784 { } /* end */
785};
1d045db9 786#endif
16ded525 787
08c189f2 788static int alc_build_controls(struct hda_codec *codec)
1d045db9
TI
789{
790 struct alc_spec *spec = codec->spec;
08c189f2 791 int i, err;
e9427969 792
08c189f2
TI
793 err = snd_hda_gen_build_controls(codec);
794 if (err < 0)
795 return err;
1da177e4
LT
796
797 for (i = 0; i < spec->num_mixers; i++) {
798 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
799 if (err < 0)
800 return err;
801 }
2134ea4f 802
67d634c0 803#ifdef CONFIG_SND_HDA_INPUT_BEEP
45bdd1c1
TI
804 /* create beep controls if needed */
805 if (spec->beep_amp) {
a9111321 806 const struct snd_kcontrol_new *knew;
45bdd1c1
TI
807 for (knew = alc_beep_mixer; knew->name; knew++) {
808 struct snd_kcontrol *kctl;
809 kctl = snd_ctl_new1(knew, codec);
810 if (!kctl)
08c189f2
TI
811 return -ENOMEM;
812 kctl->private_value = spec->beep_amp;
813 err = snd_hda_ctl_add(codec, 0, kctl);
814 if (err < 0)
815 return err;
1d045db9 816 }
863b4518 817 }
08c189f2 818#endif
1c4a54b4 819
1727a771 820 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
1c4a54b4 821 return 0;
a361d84b
KY
822}
823
a361d84b 824
df694daa 825/*
08c189f2 826 * Common callbacks
df694daa 827 */
a361d84b 828
08c189f2 829static int alc_init(struct hda_codec *codec)
1d045db9
TI
830{
831 struct alc_spec *spec = codec->spec;
a361d84b 832
08c189f2
TI
833 if (spec->init_hook)
834 spec->init_hook(codec);
a361d84b 835
08c189f2
TI
836 alc_fix_pll(codec);
837 alc_auto_init_amp(codec, spec->init_amp);
3abf2f36 838
08c189f2 839 snd_hda_gen_init(codec);
a361d84b 840
1727a771 841 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
a361d84b 842
1d045db9
TI
843 return 0;
844}
a361d84b 845
08c189f2 846static inline void alc_shutup(struct hda_codec *codec)
1d045db9
TI
847{
848 struct alc_spec *spec = codec->spec;
a361d84b 849
08c189f2
TI
850 if (spec && spec->shutup)
851 spec->shutup(codec);
9bfb2844
TI
852 else
853 snd_hda_shutup_pins(codec);
1d045db9
TI
854}
855
b67ae3f1
DH
856static void alc_free(struct hda_codec *codec)
857{
858 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
859 snd_hda_gen_free(codec);
860}
2134ea4f 861
08c189f2
TI
862#ifdef CONFIG_PM
863static void alc_power_eapd(struct hda_codec *codec)
1d045db9 864{
08c189f2 865 alc_auto_setup_eapd(codec, false);
1d045db9 866}
2134ea4f 867
08c189f2 868static int alc_suspend(struct hda_codec *codec)
1d045db9
TI
869{
870 struct alc_spec *spec = codec->spec;
08c189f2
TI
871 alc_shutup(codec);
872 if (spec && spec->power_hook)
873 spec->power_hook(codec);
a361d84b
KY
874 return 0;
875}
08c189f2 876#endif
a361d84b 877
08c189f2
TI
878#ifdef CONFIG_PM
879static int alc_resume(struct hda_codec *codec)
1d045db9 880{
97a26570
KY
881 struct alc_spec *spec = codec->spec;
882
883 if (!spec->no_depop_delay)
884 msleep(150); /* to avoid pop noise */
08c189f2
TI
885 codec->patch_ops.init(codec);
886 snd_hda_codec_resume_amp(codec);
887 snd_hda_codec_resume_cache(codec);
888 alc_inv_dmic_sync(codec, true);
889 hda_call_check_power_status(codec, 0x01);
890 return 0;
1d045db9 891}
08c189f2 892#endif
f6a92248 893
1d045db9 894/*
1d045db9 895 */
08c189f2
TI
896static const struct hda_codec_ops alc_patch_ops = {
897 .build_controls = alc_build_controls,
898 .build_pcms = snd_hda_gen_build_pcms,
899 .init = alc_init,
900 .free = alc_free,
901 .unsol_event = snd_hda_jack_unsol_event,
902#ifdef CONFIG_PM
903 .resume = alc_resume,
08c189f2 904 .suspend = alc_suspend,
fce52a3b 905 .check_power_status = snd_hda_gen_check_power_status,
08c189f2
TI
906#endif
907 .reboot_notify = alc_shutup,
908};
f6a92248 909
f53281e6 910
08c189f2
TI
911/* replace the codec chip_name with the given string */
912static int alc_codec_rename(struct hda_codec *codec, const char *name)
1d045db9 913{
08c189f2
TI
914 kfree(codec->chip_name);
915 codec->chip_name = kstrdup(name, GFP_KERNEL);
916 if (!codec->chip_name) {
917 alc_free(codec);
918 return -ENOMEM;
1d045db9 919 }
a361d84b 920 return 0;
1d045db9 921}
e01bf509 922
e4770629 923/*
4b016931 924 * Rename codecs appropriately from COEF value or subvendor id
e4770629 925 */
08c189f2
TI
926struct alc_codec_rename_table {
927 unsigned int vendor_id;
928 unsigned short coef_mask;
929 unsigned short coef_bits;
930 const char *name;
931};
84898e87 932
4b016931
KY
933struct alc_codec_rename_pci_table {
934 unsigned int codec_vendor_id;
935 unsigned short pci_subvendor;
936 unsigned short pci_subdevice;
937 const char *name;
938};
939
08c189f2
TI
940static struct alc_codec_rename_table rename_tbl[] = {
941 { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
942 { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
943 { 0x10ec0269, 0xf0f0, 0x3010, "ALC258" },
944 { 0x10ec0269, 0x00f0, 0x0010, "ALC269VB" },
945 { 0x10ec0269, 0xffff, 0xa023, "ALC259" },
946 { 0x10ec0269, 0xffff, 0x6023, "ALC281X" },
947 { 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" },
948 { 0x10ec0269, 0x00f0, 0x0030, "ALC269VD" },
949 { 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" },
950 { 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" },
951 { 0x10ec0888, 0xf0f0, 0x3020, "ALC886" },
952 { 0x10ec0899, 0x2000, 0x2000, "ALC899" },
953 { 0x10ec0892, 0xffff, 0x8020, "ALC661" },
954 { 0x10ec0892, 0xffff, 0x8011, "ALC661" },
955 { 0x10ec0892, 0xffff, 0x4011, "ALC656" },
956 { } /* terminator */
957};
84898e87 958
4b016931
KY
959static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
960 { 0x10ec0280, 0x1028, 0, "ALC3220" },
961 { 0x10ec0282, 0x1028, 0, "ALC3221" },
962 { 0x10ec0283, 0x1028, 0, "ALC3223" },
963 { 0x10ec0292, 0x1028, 0, "ALC3226" },
964 { 0x10ec0255, 0x1028, 0, "ALC3234" },
965 { 0x10ec0668, 0x1028, 0, "ALC3661" },
966 { } /* terminator */
967};
968
08c189f2 969static int alc_codec_rename_from_preset(struct hda_codec *codec)
1d045db9 970{
08c189f2 971 const struct alc_codec_rename_table *p;
4b016931 972 const struct alc_codec_rename_pci_table *q;
60db6b53 973
08c189f2
TI
974 for (p = rename_tbl; p->vendor_id; p++) {
975 if (p->vendor_id != codec->vendor_id)
976 continue;
977 if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
978 return alc_codec_rename(codec, p->name);
1d045db9 979 }
4b016931
KY
980
981 for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
982 if (q->codec_vendor_id != codec->vendor_id)
983 continue;
984 if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
985 continue;
986 if (!q->pci_subdevice ||
987 q->pci_subdevice == codec->bus->pci->subsystem_device)
988 return alc_codec_rename(codec, q->name);
989 }
990
08c189f2 991 return 0;
1d045db9 992}
f53281e6 993
e4770629 994
1d045db9
TI
995/*
996 * Digital-beep handlers
997 */
998#ifdef CONFIG_SND_HDA_INPUT_BEEP
999#define set_beep_amp(spec, nid, idx, dir) \
1000 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
84898e87 1001
1d045db9 1002static const struct snd_pci_quirk beep_white_list[] = {
7110005e 1003 SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1),
1d045db9 1004 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
8554ee40 1005 SND_PCI_QUIRK(0x1043, 0x8376, "EeePC", 1),
1d045db9
TI
1006 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
1007 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
1008 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
78f8baf1 1009 SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1),
1d045db9
TI
1010 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
1011 {}
fe3eb0a7
KY
1012};
1013
1d045db9
TI
1014static inline int has_cdefine_beep(struct hda_codec *codec)
1015{
1016 struct alc_spec *spec = codec->spec;
1017 const struct snd_pci_quirk *q;
1018 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
1019 if (q)
1020 return q->value;
1021 return spec->cdefine.enable_pcbeep;
1022}
1023#else
1024#define set_beep_amp(spec, nid, idx, dir) /* NOP */
1025#define has_cdefine_beep(codec) 0
1026#endif
84898e87 1027
1d045db9
TI
1028/* parse the BIOS configuration and set up the alc_spec */
1029/* return 1 if successful, 0 if the proper config is not found,
1030 * or a negative error code
1031 */
3e6179b8
TI
1032static int alc_parse_auto_config(struct hda_codec *codec,
1033 const hda_nid_t *ignore_nids,
1034 const hda_nid_t *ssid_nids)
1d045db9
TI
1035{
1036 struct alc_spec *spec = codec->spec;
08c189f2 1037 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
1d045db9 1038 int err;
26f5df26 1039
53c334ad
TI
1040 err = snd_hda_parse_pin_defcfg(codec, cfg, ignore_nids,
1041 spec->parse_flags);
1d045db9
TI
1042 if (err < 0)
1043 return err;
3e6179b8
TI
1044
1045 if (ssid_nids)
1046 alc_ssid_check(codec, ssid_nids);
64154835 1047
08c189f2
TI
1048 err = snd_hda_gen_parse_auto_config(codec, cfg);
1049 if (err < 0)
1050 return err;
070cff4c 1051
1d045db9 1052 return 1;
60db6b53 1053}
f6a92248 1054
3de95173
TI
1055/* common preparation job for alc_spec */
1056static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
1057{
1058 struct alc_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1059 int err;
1060
1061 if (!spec)
1062 return -ENOMEM;
1063 codec->spec = spec;
08c189f2
TI
1064 snd_hda_gen_spec_init(&spec->gen);
1065 spec->gen.mixer_nid = mixer_nid;
1066 spec->gen.own_eapd_ctl = 1;
1098b7c2 1067 codec->single_adc_amp = 1;
08c189f2
TI
1068 /* FIXME: do we need this for all Realtek codec models? */
1069 codec->spdif_status_reset = 1;
3de95173
TI
1070
1071 err = alc_codec_rename_from_preset(codec);
1072 if (err < 0) {
1073 kfree(spec);
1074 return err;
1075 }
1076 return 0;
1077}
1078
3e6179b8
TI
1079static int alc880_parse_auto_config(struct hda_codec *codec)
1080{
1081 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
7d7eb9ea 1082 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
3e6179b8
TI
1083 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
1084}
1085
ee3b2969
TI
1086/*
1087 * ALC880 fix-ups
1088 */
1089enum {
411225a0 1090 ALC880_FIXUP_GPIO1,
ee3b2969
TI
1091 ALC880_FIXUP_GPIO2,
1092 ALC880_FIXUP_MEDION_RIM,
dc6af52d 1093 ALC880_FIXUP_LG,
db8a38e5 1094 ALC880_FIXUP_LG_LW25,
f02aab5d 1095 ALC880_FIXUP_W810,
27e917f8 1096 ALC880_FIXUP_EAPD_COEF,
b9368f5c 1097 ALC880_FIXUP_TCL_S700,
cf5a2279
TI
1098 ALC880_FIXUP_VOL_KNOB,
1099 ALC880_FIXUP_FUJITSU,
ba533818 1100 ALC880_FIXUP_F1734,
817de92f 1101 ALC880_FIXUP_UNIWILL,
967b88c4 1102 ALC880_FIXUP_UNIWILL_DIG,
96e225f6 1103 ALC880_FIXUP_Z71V,
487a588d 1104 ALC880_FIXUP_ASUS_W5A,
67b6ec31
TI
1105 ALC880_FIXUP_3ST_BASE,
1106 ALC880_FIXUP_3ST,
1107 ALC880_FIXUP_3ST_DIG,
1108 ALC880_FIXUP_5ST_BASE,
1109 ALC880_FIXUP_5ST,
1110 ALC880_FIXUP_5ST_DIG,
1111 ALC880_FIXUP_6ST_BASE,
1112 ALC880_FIXUP_6ST,
1113 ALC880_FIXUP_6ST_DIG,
5397145f 1114 ALC880_FIXUP_6ST_AUTOMUTE,
ee3b2969
TI
1115};
1116
cf5a2279
TI
1117/* enable the volume-knob widget support on NID 0x21 */
1118static void alc880_fixup_vol_knob(struct hda_codec *codec,
1727a771 1119 const struct hda_fixup *fix, int action)
cf5a2279 1120{
1727a771 1121 if (action == HDA_FIXUP_ACT_PROBE)
29adc4b9 1122 snd_hda_jack_detect_enable_callback(codec, 0x21, ALC_DCVOL_EVENT, alc_update_knob_master);
cf5a2279
TI
1123}
1124
1727a771 1125static const struct hda_fixup alc880_fixups[] = {
411225a0 1126 [ALC880_FIXUP_GPIO1] = {
1727a771 1127 .type = HDA_FIXUP_VERBS,
411225a0
TI
1128 .v.verbs = alc_gpio1_init_verbs,
1129 },
ee3b2969 1130 [ALC880_FIXUP_GPIO2] = {
1727a771 1131 .type = HDA_FIXUP_VERBS,
ee3b2969
TI
1132 .v.verbs = alc_gpio2_init_verbs,
1133 },
1134 [ALC880_FIXUP_MEDION_RIM] = {
1727a771 1135 .type = HDA_FIXUP_VERBS,
ee3b2969
TI
1136 .v.verbs = (const struct hda_verb[]) {
1137 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1138 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
1139 { }
1140 },
1141 .chained = true,
1142 .chain_id = ALC880_FIXUP_GPIO2,
1143 },
dc6af52d 1144 [ALC880_FIXUP_LG] = {
1727a771
TI
1145 .type = HDA_FIXUP_PINS,
1146 .v.pins = (const struct hda_pintbl[]) {
dc6af52d
TI
1147 /* disable bogus unused pins */
1148 { 0x16, 0x411111f0 },
1149 { 0x18, 0x411111f0 },
1150 { 0x1a, 0x411111f0 },
1151 { }
1152 }
1153 },
db8a38e5
TI
1154 [ALC880_FIXUP_LG_LW25] = {
1155 .type = HDA_FIXUP_PINS,
1156 .v.pins = (const struct hda_pintbl[]) {
1157 { 0x1a, 0x0181344f }, /* line-in */
1158 { 0x1b, 0x0321403f }, /* headphone */
1159 { }
1160 }
1161 },
f02aab5d 1162 [ALC880_FIXUP_W810] = {
1727a771
TI
1163 .type = HDA_FIXUP_PINS,
1164 .v.pins = (const struct hda_pintbl[]) {
f02aab5d
TI
1165 /* disable bogus unused pins */
1166 { 0x17, 0x411111f0 },
1167 { }
1168 },
1169 .chained = true,
1170 .chain_id = ALC880_FIXUP_GPIO2,
1171 },
27e917f8 1172 [ALC880_FIXUP_EAPD_COEF] = {
1727a771 1173 .type = HDA_FIXUP_VERBS,
27e917f8
TI
1174 .v.verbs = (const struct hda_verb[]) {
1175 /* change to EAPD mode */
1176 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1177 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
1178 {}
1179 },
1180 },
b9368f5c 1181 [ALC880_FIXUP_TCL_S700] = {
1727a771 1182 .type = HDA_FIXUP_VERBS,
b9368f5c
TI
1183 .v.verbs = (const struct hda_verb[]) {
1184 /* change to EAPD mode */
1185 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1186 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
1187 {}
1188 },
1189 .chained = true,
1190 .chain_id = ALC880_FIXUP_GPIO2,
1191 },
cf5a2279 1192 [ALC880_FIXUP_VOL_KNOB] = {
1727a771 1193 .type = HDA_FIXUP_FUNC,
cf5a2279
TI
1194 .v.func = alc880_fixup_vol_knob,
1195 },
1196 [ALC880_FIXUP_FUJITSU] = {
1197 /* override all pins as BIOS on old Amilo is broken */
1727a771
TI
1198 .type = HDA_FIXUP_PINS,
1199 .v.pins = (const struct hda_pintbl[]) {
cf5a2279
TI
1200 { 0x14, 0x0121411f }, /* HP */
1201 { 0x15, 0x99030120 }, /* speaker */
1202 { 0x16, 0x99030130 }, /* bass speaker */
1203 { 0x17, 0x411111f0 }, /* N/A */
1204 { 0x18, 0x411111f0 }, /* N/A */
1205 { 0x19, 0x01a19950 }, /* mic-in */
1206 { 0x1a, 0x411111f0 }, /* N/A */
1207 { 0x1b, 0x411111f0 }, /* N/A */
1208 { 0x1c, 0x411111f0 }, /* N/A */
1209 { 0x1d, 0x411111f0 }, /* N/A */
1210 { 0x1e, 0x01454140 }, /* SPDIF out */
1211 { }
1212 },
1213 .chained = true,
1214 .chain_id = ALC880_FIXUP_VOL_KNOB,
1215 },
ba533818
TI
1216 [ALC880_FIXUP_F1734] = {
1217 /* almost compatible with FUJITSU, but no bass and SPDIF */
1727a771
TI
1218 .type = HDA_FIXUP_PINS,
1219 .v.pins = (const struct hda_pintbl[]) {
ba533818
TI
1220 { 0x14, 0x0121411f }, /* HP */
1221 { 0x15, 0x99030120 }, /* speaker */
1222 { 0x16, 0x411111f0 }, /* N/A */
1223 { 0x17, 0x411111f0 }, /* N/A */
1224 { 0x18, 0x411111f0 }, /* N/A */
1225 { 0x19, 0x01a19950 }, /* mic-in */
1226 { 0x1a, 0x411111f0 }, /* N/A */
1227 { 0x1b, 0x411111f0 }, /* N/A */
1228 { 0x1c, 0x411111f0 }, /* N/A */
1229 { 0x1d, 0x411111f0 }, /* N/A */
1230 { 0x1e, 0x411111f0 }, /* N/A */
1231 { }
1232 },
1233 .chained = true,
1234 .chain_id = ALC880_FIXUP_VOL_KNOB,
1235 },
817de92f
TI
1236 [ALC880_FIXUP_UNIWILL] = {
1237 /* need to fix HP and speaker pins to be parsed correctly */
1727a771
TI
1238 .type = HDA_FIXUP_PINS,
1239 .v.pins = (const struct hda_pintbl[]) {
817de92f
TI
1240 { 0x14, 0x0121411f }, /* HP */
1241 { 0x15, 0x99030120 }, /* speaker */
1242 { 0x16, 0x99030130 }, /* bass speaker */
1243 { }
1244 },
1245 },
967b88c4 1246 [ALC880_FIXUP_UNIWILL_DIG] = {
1727a771
TI
1247 .type = HDA_FIXUP_PINS,
1248 .v.pins = (const struct hda_pintbl[]) {
967b88c4
TI
1249 /* disable bogus unused pins */
1250 { 0x17, 0x411111f0 },
1251 { 0x19, 0x411111f0 },
1252 { 0x1b, 0x411111f0 },
1253 { 0x1f, 0x411111f0 },
1254 { }
1255 }
1256 },
96e225f6 1257 [ALC880_FIXUP_Z71V] = {
1727a771
TI
1258 .type = HDA_FIXUP_PINS,
1259 .v.pins = (const struct hda_pintbl[]) {
96e225f6
TI
1260 /* set up the whole pins as BIOS is utterly broken */
1261 { 0x14, 0x99030120 }, /* speaker */
1262 { 0x15, 0x0121411f }, /* HP */
1263 { 0x16, 0x411111f0 }, /* N/A */
1264 { 0x17, 0x411111f0 }, /* N/A */
1265 { 0x18, 0x01a19950 }, /* mic-in */
1266 { 0x19, 0x411111f0 }, /* N/A */
1267 { 0x1a, 0x01813031 }, /* line-in */
1268 { 0x1b, 0x411111f0 }, /* N/A */
1269 { 0x1c, 0x411111f0 }, /* N/A */
1270 { 0x1d, 0x411111f0 }, /* N/A */
1271 { 0x1e, 0x0144111e }, /* SPDIF */
1272 { }
1273 }
1274 },
487a588d
TI
1275 [ALC880_FIXUP_ASUS_W5A] = {
1276 .type = HDA_FIXUP_PINS,
1277 .v.pins = (const struct hda_pintbl[]) {
1278 /* set up the whole pins as BIOS is utterly broken */
1279 { 0x14, 0x0121411f }, /* HP */
1280 { 0x15, 0x411111f0 }, /* N/A */
1281 { 0x16, 0x411111f0 }, /* N/A */
1282 { 0x17, 0x411111f0 }, /* N/A */
1283 { 0x18, 0x90a60160 }, /* mic */
1284 { 0x19, 0x411111f0 }, /* N/A */
1285 { 0x1a, 0x411111f0 }, /* N/A */
1286 { 0x1b, 0x411111f0 }, /* N/A */
1287 { 0x1c, 0x411111f0 }, /* N/A */
1288 { 0x1d, 0x411111f0 }, /* N/A */
1289 { 0x1e, 0xb743111e }, /* SPDIF out */
1290 { }
1291 },
1292 .chained = true,
1293 .chain_id = ALC880_FIXUP_GPIO1,
1294 },
67b6ec31 1295 [ALC880_FIXUP_3ST_BASE] = {
1727a771
TI
1296 .type = HDA_FIXUP_PINS,
1297 .v.pins = (const struct hda_pintbl[]) {
67b6ec31
TI
1298 { 0x14, 0x01014010 }, /* line-out */
1299 { 0x15, 0x411111f0 }, /* N/A */
1300 { 0x16, 0x411111f0 }, /* N/A */
1301 { 0x17, 0x411111f0 }, /* N/A */
1302 { 0x18, 0x01a19c30 }, /* mic-in */
1303 { 0x19, 0x0121411f }, /* HP */
1304 { 0x1a, 0x01813031 }, /* line-in */
1305 { 0x1b, 0x02a19c40 }, /* front-mic */
1306 { 0x1c, 0x411111f0 }, /* N/A */
1307 { 0x1d, 0x411111f0 }, /* N/A */
1308 /* 0x1e is filled in below */
1309 { 0x1f, 0x411111f0 }, /* N/A */
1310 { }
1311 }
1312 },
1313 [ALC880_FIXUP_3ST] = {
1727a771
TI
1314 .type = HDA_FIXUP_PINS,
1315 .v.pins = (const struct hda_pintbl[]) {
67b6ec31
TI
1316 { 0x1e, 0x411111f0 }, /* N/A */
1317 { }
1318 },
1319 .chained = true,
1320 .chain_id = ALC880_FIXUP_3ST_BASE,
1321 },
1322 [ALC880_FIXUP_3ST_DIG] = {
1727a771
TI
1323 .type = HDA_FIXUP_PINS,
1324 .v.pins = (const struct hda_pintbl[]) {
67b6ec31
TI
1325 { 0x1e, 0x0144111e }, /* SPDIF */
1326 { }
1327 },
1328 .chained = true,
1329 .chain_id = ALC880_FIXUP_3ST_BASE,
1330 },
1331 [ALC880_FIXUP_5ST_BASE] = {
1727a771
TI
1332 .type = HDA_FIXUP_PINS,
1333 .v.pins = (const struct hda_pintbl[]) {
67b6ec31
TI
1334 { 0x14, 0x01014010 }, /* front */
1335 { 0x15, 0x411111f0 }, /* N/A */
1336 { 0x16, 0x01011411 }, /* CLFE */
1337 { 0x17, 0x01016412 }, /* surr */
1338 { 0x18, 0x01a19c30 }, /* mic-in */
1339 { 0x19, 0x0121411f }, /* HP */
1340 { 0x1a, 0x01813031 }, /* line-in */
1341 { 0x1b, 0x02a19c40 }, /* front-mic */
1342 { 0x1c, 0x411111f0 }, /* N/A */
1343 { 0x1d, 0x411111f0 }, /* N/A */
1344 /* 0x1e is filled in below */
1345 { 0x1f, 0x411111f0 }, /* N/A */
1346 { }
1347 }
1348 },
1349 [ALC880_FIXUP_5ST] = {
1727a771
TI
1350 .type = HDA_FIXUP_PINS,
1351 .v.pins = (const struct hda_pintbl[]) {
67b6ec31
TI
1352 { 0x1e, 0x411111f0 }, /* N/A */
1353 { }
1354 },
1355 .chained = true,
1356 .chain_id = ALC880_FIXUP_5ST_BASE,
1357 },
1358 [ALC880_FIXUP_5ST_DIG] = {
1727a771
TI
1359 .type = HDA_FIXUP_PINS,
1360 .v.pins = (const struct hda_pintbl[]) {
67b6ec31
TI
1361 { 0x1e, 0x0144111e }, /* SPDIF */
1362 { }
1363 },
1364 .chained = true,
1365 .chain_id = ALC880_FIXUP_5ST_BASE,
1366 },
1367 [ALC880_FIXUP_6ST_BASE] = {
1727a771
TI
1368 .type = HDA_FIXUP_PINS,
1369 .v.pins = (const struct hda_pintbl[]) {
67b6ec31
TI
1370 { 0x14, 0x01014010 }, /* front */
1371 { 0x15, 0x01016412 }, /* surr */
1372 { 0x16, 0x01011411 }, /* CLFE */
1373 { 0x17, 0x01012414 }, /* side */
1374 { 0x18, 0x01a19c30 }, /* mic-in */
1375 { 0x19, 0x02a19c40 }, /* front-mic */
1376 { 0x1a, 0x01813031 }, /* line-in */
1377 { 0x1b, 0x0121411f }, /* HP */
1378 { 0x1c, 0x411111f0 }, /* N/A */
1379 { 0x1d, 0x411111f0 }, /* N/A */
1380 /* 0x1e is filled in below */
1381 { 0x1f, 0x411111f0 }, /* N/A */
1382 { }
1383 }
1384 },
1385 [ALC880_FIXUP_6ST] = {
1727a771
TI
1386 .type = HDA_FIXUP_PINS,
1387 .v.pins = (const struct hda_pintbl[]) {
67b6ec31
TI
1388 { 0x1e, 0x411111f0 }, /* N/A */
1389 { }
1390 },
1391 .chained = true,
1392 .chain_id = ALC880_FIXUP_6ST_BASE,
1393 },
1394 [ALC880_FIXUP_6ST_DIG] = {
1727a771
TI
1395 .type = HDA_FIXUP_PINS,
1396 .v.pins = (const struct hda_pintbl[]) {
67b6ec31
TI
1397 { 0x1e, 0x0144111e }, /* SPDIF */
1398 { }
1399 },
1400 .chained = true,
1401 .chain_id = ALC880_FIXUP_6ST_BASE,
1402 },
5397145f
TI
1403 [ALC880_FIXUP_6ST_AUTOMUTE] = {
1404 .type = HDA_FIXUP_PINS,
1405 .v.pins = (const struct hda_pintbl[]) {
1406 { 0x1b, 0x0121401f }, /* HP with jack detect */
1407 { }
1408 },
1409 .chained_before = true,
1410 .chain_id = ALC880_FIXUP_6ST_BASE,
1411 },
ee3b2969
TI
1412};
1413
1414static const struct snd_pci_quirk alc880_fixup_tbl[] = {
f02aab5d 1415 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
487a588d 1416 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A),
96e225f6 1417 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
29e3fdcc
TI
1418 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
1419 SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
27e917f8 1420 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF),
967b88c4 1421 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG),
ba533818 1422 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734),
817de92f 1423 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL),
7833c7e8 1424 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
f02aab5d 1425 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
ee3b2969 1426 SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
5397145f 1427 SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST_AUTOMUTE),
ba533818 1428 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734),
cf5a2279 1429 SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
ba533818 1430 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
cf5a2279 1431 SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU),
dc6af52d
TI
1432 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
1433 SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
1434 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
db8a38e5 1435 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_FIXUP_LG_LW25),
b9368f5c 1436 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
67b6ec31
TI
1437
1438 /* Below is the copied entries from alc880_quirks.c.
1439 * It's not quite sure whether BIOS sets the correct pin-config table
1440 * on these machines, thus they are kept to be compatible with
1441 * the old static quirks. Once when it's confirmed to work without
1442 * these overrides, it'd be better to remove.
1443 */
1444 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG),
1445 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST),
1446 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG),
1447 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG),
1448 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG),
1449 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG),
1450 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG),
1451 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST),
1452 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG),
1453 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST),
1454 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST),
1455 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST),
1456 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST),
1457 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST),
1458 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG),
1459 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG),
1460 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG),
1461 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG),
1462 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG),
1463 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG),
1464 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG),
1465 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */
1466 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG),
1467 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1468 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1469 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1470 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG),
1471 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1472 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG),
1473 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG),
1474 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1475 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1476 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1477 /* default Intel */
1478 SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST),
1479 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG),
1480 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG),
1481 {}
1482};
1483
1727a771 1484static const struct hda_model_fixup alc880_fixup_models[] = {
67b6ec31
TI
1485 {.id = ALC880_FIXUP_3ST, .name = "3stack"},
1486 {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"},
1487 {.id = ALC880_FIXUP_5ST, .name = "5stack"},
1488 {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"},
1489 {.id = ALC880_FIXUP_6ST, .name = "6stack"},
1490 {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"},
5397145f 1491 {.id = ALC880_FIXUP_6ST_AUTOMUTE, .name = "6stack-automute"},
ee3b2969
TI
1492 {}
1493};
1494
1495
1d045db9
TI
1496/*
1497 * OK, here we have finally the patch for ALC880
1498 */
1d045db9 1499static int patch_alc880(struct hda_codec *codec)
60db6b53 1500{
1d045db9 1501 struct alc_spec *spec;
1d045db9 1502 int err;
f6a92248 1503
3de95173
TI
1504 err = alc_alloc_spec(codec, 0x0b);
1505 if (err < 0)
1506 return err;
64154835 1507
3de95173 1508 spec = codec->spec;
08c189f2 1509 spec->gen.need_dac_fix = 1;
7504b6cd 1510 spec->gen.beep_nid = 0x01;
f53281e6 1511
1727a771 1512 snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
67b6ec31 1513 alc880_fixups);
1727a771 1514 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
ee3b2969 1515
67b6ec31
TI
1516 /* automatic parse from the BIOS config */
1517 err = alc880_parse_auto_config(codec);
1518 if (err < 0)
1519 goto error;
fe3eb0a7 1520
7504b6cd 1521 if (!spec->gen.no_analog)
3e6179b8 1522 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
f53281e6 1523
1d045db9 1524 codec->patch_ops = alc_patch_ops;
29adc4b9
DH
1525 codec->patch_ops.unsol_event = alc880_unsol_event;
1526
f53281e6 1527
1727a771 1528 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 1529
1d045db9 1530 return 0;
e16fb6d1
TI
1531
1532 error:
1533 alc_free(codec);
1534 return err;
226b1ec8
KY
1535}
1536
1d045db9 1537
60db6b53 1538/*
1d045db9 1539 * ALC260 support
60db6b53 1540 */
1d045db9 1541static int alc260_parse_auto_config(struct hda_codec *codec)
f6a92248 1542{
1d045db9 1543 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
3e6179b8
TI
1544 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
1545 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
f6a92248
KY
1546}
1547
1d045db9
TI
1548/*
1549 * Pin config fixes
1550 */
1551enum {
ca8f0424
TI
1552 ALC260_FIXUP_HP_DC5750,
1553 ALC260_FIXUP_HP_PIN_0F,
1554 ALC260_FIXUP_COEF,
15317ab2 1555 ALC260_FIXUP_GPIO1,
20f7d928
TI
1556 ALC260_FIXUP_GPIO1_TOGGLE,
1557 ALC260_FIXUP_REPLACER,
0a1c4fa2 1558 ALC260_FIXUP_HP_B1900,
118cb4a4 1559 ALC260_FIXUP_KN1,
39aedee7 1560 ALC260_FIXUP_FSC_S7020,
5ebd3bbd 1561 ALC260_FIXUP_FSC_S7020_JWSE,
d08c5ef2 1562 ALC260_FIXUP_VAIO_PINS,
1d045db9
TI
1563};
1564
20f7d928
TI
1565static void alc260_gpio1_automute(struct hda_codec *codec)
1566{
1567 struct alc_spec *spec = codec->spec;
1568 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
08c189f2 1569 spec->gen.hp_jack_present);
20f7d928
TI
1570}
1571
1572static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
1727a771 1573 const struct hda_fixup *fix, int action)
20f7d928
TI
1574{
1575 struct alc_spec *spec = codec->spec;
1727a771 1576 if (action == HDA_FIXUP_ACT_PROBE) {
20f7d928
TI
1577 /* although the machine has only one output pin, we need to
1578 * toggle GPIO1 according to the jack state
1579 */
08c189f2
TI
1580 spec->gen.automute_hook = alc260_gpio1_automute;
1581 spec->gen.detect_hp = 1;
1582 spec->gen.automute_speaker = 1;
1583 spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
1584 snd_hda_jack_detect_enable_callback(codec, 0x0f, HDA_GEN_HP_EVENT,
1585 snd_hda_gen_hp_automute);
c9ce6b26 1586 snd_hda_add_verbs(codec, alc_gpio1_init_verbs);
20f7d928
TI
1587 }
1588}
1589
118cb4a4 1590static void alc260_fixup_kn1(struct hda_codec *codec,
1727a771 1591 const struct hda_fixup *fix, int action)
118cb4a4
TI
1592{
1593 struct alc_spec *spec = codec->spec;
1727a771 1594 static const struct hda_pintbl pincfgs[] = {
118cb4a4
TI
1595 { 0x0f, 0x02214000 }, /* HP/speaker */
1596 { 0x12, 0x90a60160 }, /* int mic */
1597 { 0x13, 0x02a19000 }, /* ext mic */
1598 { 0x18, 0x01446000 }, /* SPDIF out */
1599 /* disable bogus I/O pins */
1600 { 0x10, 0x411111f0 },
1601 { 0x11, 0x411111f0 },
1602 { 0x14, 0x411111f0 },
1603 { 0x15, 0x411111f0 },
1604 { 0x16, 0x411111f0 },
1605 { 0x17, 0x411111f0 },
1606 { 0x19, 0x411111f0 },
1607 { }
1608 };
1609
1610 switch (action) {
1727a771
TI
1611 case HDA_FIXUP_ACT_PRE_PROBE:
1612 snd_hda_apply_pincfgs(codec, pincfgs);
118cb4a4 1613 break;
1727a771 1614 case HDA_FIXUP_ACT_PROBE:
118cb4a4
TI
1615 spec->init_amp = ALC_INIT_NONE;
1616 break;
1617 }
1618}
1619
39aedee7
TI
1620static void alc260_fixup_fsc_s7020(struct hda_codec *codec,
1621 const struct hda_fixup *fix, int action)
1622{
1623 struct alc_spec *spec = codec->spec;
5ebd3bbd
TI
1624 if (action == HDA_FIXUP_ACT_PROBE)
1625 spec->init_amp = ALC_INIT_NONE;
1626}
39aedee7 1627
5ebd3bbd
TI
1628static void alc260_fixup_fsc_s7020_jwse(struct hda_codec *codec,
1629 const struct hda_fixup *fix, int action)
1630{
1631 struct alc_spec *spec = codec->spec;
1632 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
f811c3cf 1633 spec->gen.add_jack_modes = 1;
5ebd3bbd 1634 spec->gen.hp_mic = 1;
e6e0ee50 1635 }
39aedee7
TI
1636}
1637
1727a771 1638static const struct hda_fixup alc260_fixups[] = {
ca8f0424 1639 [ALC260_FIXUP_HP_DC5750] = {
1727a771
TI
1640 .type = HDA_FIXUP_PINS,
1641 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
1642 { 0x11, 0x90130110 }, /* speaker */
1643 { }
1644 }
1645 },
ca8f0424 1646 [ALC260_FIXUP_HP_PIN_0F] = {
1727a771
TI
1647 .type = HDA_FIXUP_PINS,
1648 .v.pins = (const struct hda_pintbl[]) {
ca8f0424
TI
1649 { 0x0f, 0x01214000 }, /* HP */
1650 { }
1651 }
1652 },
1653 [ALC260_FIXUP_COEF] = {
1727a771 1654 .type = HDA_FIXUP_VERBS,
ca8f0424
TI
1655 .v.verbs = (const struct hda_verb[]) {
1656 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1657 { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 },
1658 { }
1659 },
1660 .chained = true,
1661 .chain_id = ALC260_FIXUP_HP_PIN_0F,
1662 },
15317ab2 1663 [ALC260_FIXUP_GPIO1] = {
1727a771 1664 .type = HDA_FIXUP_VERBS,
15317ab2
TI
1665 .v.verbs = alc_gpio1_init_verbs,
1666 },
20f7d928 1667 [ALC260_FIXUP_GPIO1_TOGGLE] = {
1727a771 1668 .type = HDA_FIXUP_FUNC,
20f7d928
TI
1669 .v.func = alc260_fixup_gpio1_toggle,
1670 .chained = true,
1671 .chain_id = ALC260_FIXUP_HP_PIN_0F,
1672 },
1673 [ALC260_FIXUP_REPLACER] = {
1727a771 1674 .type = HDA_FIXUP_VERBS,
20f7d928
TI
1675 .v.verbs = (const struct hda_verb[]) {
1676 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1677 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
1678 { }
1679 },
1680 .chained = true,
1681 .chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
1682 },
0a1c4fa2 1683 [ALC260_FIXUP_HP_B1900] = {
1727a771 1684 .type = HDA_FIXUP_FUNC,
0a1c4fa2
TI
1685 .v.func = alc260_fixup_gpio1_toggle,
1686 .chained = true,
1687 .chain_id = ALC260_FIXUP_COEF,
118cb4a4
TI
1688 },
1689 [ALC260_FIXUP_KN1] = {
1727a771 1690 .type = HDA_FIXUP_FUNC,
118cb4a4
TI
1691 .v.func = alc260_fixup_kn1,
1692 },
39aedee7
TI
1693 [ALC260_FIXUP_FSC_S7020] = {
1694 .type = HDA_FIXUP_FUNC,
1695 .v.func = alc260_fixup_fsc_s7020,
1696 },
5ebd3bbd
TI
1697 [ALC260_FIXUP_FSC_S7020_JWSE] = {
1698 .type = HDA_FIXUP_FUNC,
1699 .v.func = alc260_fixup_fsc_s7020_jwse,
1700 .chained = true,
1701 .chain_id = ALC260_FIXUP_FSC_S7020,
1702 },
d08c5ef2
TI
1703 [ALC260_FIXUP_VAIO_PINS] = {
1704 .type = HDA_FIXUP_PINS,
1705 .v.pins = (const struct hda_pintbl[]) {
1706 /* Pin configs are missing completely on some VAIOs */
1707 { 0x0f, 0x01211020 },
1708 { 0x10, 0x0001003f },
1709 { 0x11, 0x411111f0 },
1710 { 0x12, 0x01a15930 },
1711 { 0x13, 0x411111f0 },
1712 { 0x14, 0x411111f0 },
1713 { 0x15, 0x411111f0 },
1714 { 0x16, 0x411111f0 },
1715 { 0x17, 0x411111f0 },
1716 { 0x18, 0x411111f0 },
1717 { 0x19, 0x411111f0 },
1718 { }
1719 }
1720 },
1d045db9
TI
1721};
1722
1723static const struct snd_pci_quirk alc260_fixup_tbl[] = {
15317ab2 1724 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
ca8f0424 1725 SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
15317ab2 1726 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
ca8f0424 1727 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
0a1c4fa2 1728 SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
d08c5ef2 1729 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_FIXUP_VAIO_PINS),
0f5a5b85 1730 SND_PCI_QUIRK(0x104d, 0x81e2, "Sony VAIO TX", ALC260_FIXUP_HP_PIN_0F),
39aedee7 1731 SND_PCI_QUIRK(0x10cf, 0x1326, "FSC LifeBook S7020", ALC260_FIXUP_FSC_S7020),
b1f58085 1732 SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
118cb4a4 1733 SND_PCI_QUIRK(0x152d, 0x0729, "Quanta KN1", ALC260_FIXUP_KN1),
20f7d928 1734 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
ca8f0424 1735 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
1d045db9
TI
1736 {}
1737};
1738
5ebd3bbd
TI
1739static const struct hda_model_fixup alc260_fixup_models[] = {
1740 {.id = ALC260_FIXUP_GPIO1, .name = "gpio1"},
1741 {.id = ALC260_FIXUP_COEF, .name = "coef"},
1742 {.id = ALC260_FIXUP_FSC_S7020, .name = "fujitsu"},
1743 {.id = ALC260_FIXUP_FSC_S7020_JWSE, .name = "fujitsu-jwse"},
1744 {}
1745};
1746
1d045db9
TI
1747/*
1748 */
1d045db9 1749static int patch_alc260(struct hda_codec *codec)
977ddd6b 1750{
1d045db9 1751 struct alc_spec *spec;
c3c2c9e7 1752 int err;
1d045db9 1753
3de95173
TI
1754 err = alc_alloc_spec(codec, 0x07);
1755 if (err < 0)
1756 return err;
1d045db9 1757
3de95173 1758 spec = codec->spec;
ea46c3c8
TI
1759 /* as quite a few machines require HP amp for speaker outputs,
1760 * it's easier to enable it unconditionally; even if it's unneeded,
1761 * it's almost harmless.
1762 */
1763 spec->gen.prefer_hp_amp = 1;
7504b6cd 1764 spec->gen.beep_nid = 0x01;
1d045db9 1765
5ebd3bbd
TI
1766 snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl,
1767 alc260_fixups);
1727a771 1768 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
977ddd6b 1769
c3c2c9e7
TI
1770 /* automatic parse from the BIOS config */
1771 err = alc260_parse_auto_config(codec);
1772 if (err < 0)
1773 goto error;
977ddd6b 1774
7504b6cd 1775 if (!spec->gen.no_analog)
3e6179b8 1776 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
977ddd6b 1777
1d045db9 1778 codec->patch_ops = alc_patch_ops;
1d045db9 1779 spec->shutup = alc_eapd_shutup;
6981d184 1780
1727a771 1781 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 1782
1d045db9 1783 return 0;
e16fb6d1
TI
1784
1785 error:
1786 alc_free(codec);
1787 return err;
6981d184
TI
1788}
1789
1d045db9
TI
1790
1791/*
1792 * ALC882/883/885/888/889 support
1793 *
1794 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
1795 * configuration. Each pin widget can choose any input DACs and a mixer.
1796 * Each ADC is connected from a mixer of all inputs. This makes possible
1797 * 6-channel independent captures.
1798 *
1799 * In addition, an independent DAC for the multi-playback (not used in this
1800 * driver yet).
1801 */
1d045db9
TI
1802
1803/*
1804 * Pin config fixes
1805 */
ff818c24 1806enum {
5c0ebfbe
TI
1807 ALC882_FIXUP_ABIT_AW9D_MAX,
1808 ALC882_FIXUP_LENOVO_Y530,
1809 ALC882_FIXUP_PB_M5210,
1810 ALC882_FIXUP_ACER_ASPIRE_7736,
1811 ALC882_FIXUP_ASUS_W90V,
8f239214 1812 ALC889_FIXUP_CD,
5c0ebfbe 1813 ALC889_FIXUP_VAIO_TT,
0e7cc2e7 1814 ALC888_FIXUP_EEE1601,
177943a3 1815 ALC882_FIXUP_EAPD,
7a6069bf 1816 ALC883_FIXUP_EAPD,
8812c4f9 1817 ALC883_FIXUP_ACER_EAPD,
1a97b7f2
TI
1818 ALC882_FIXUP_GPIO1,
1819 ALC882_FIXUP_GPIO2,
eb844d51 1820 ALC882_FIXUP_GPIO3,
68ef0561
TI
1821 ALC889_FIXUP_COEF,
1822 ALC882_FIXUP_ASUS_W2JC,
c3e837bb
TI
1823 ALC882_FIXUP_ACER_ASPIRE_4930G,
1824 ALC882_FIXUP_ACER_ASPIRE_8930G,
1825 ALC882_FIXUP_ASPIRE_8930G_VERBS,
5671087f 1826 ALC885_FIXUP_MACPRO_GPIO,
02a237b2 1827 ALC889_FIXUP_DAC_ROUTE,
1a97b7f2
TI
1828 ALC889_FIXUP_MBP_VREF,
1829 ALC889_FIXUP_IMAC91_VREF,
0756f09c 1830 ALC889_FIXUP_MBA21_VREF,
6e72aa5f 1831 ALC882_FIXUP_INV_DMIC,
e427c237 1832 ALC882_FIXUP_NO_PRIMARY_HP,
1f0bbf03 1833 ALC887_FIXUP_ASUS_BASS,
eb9ca3ab 1834 ALC887_FIXUP_BASS_CHMAP,
ff818c24
TI
1835};
1836
68ef0561 1837static void alc889_fixup_coef(struct hda_codec *codec,
1727a771 1838 const struct hda_fixup *fix, int action)
68ef0561 1839{
1727a771 1840 if (action != HDA_FIXUP_ACT_INIT)
68ef0561
TI
1841 return;
1842 alc889_coef_init(codec);
1843}
1844
5671087f
TI
1845/* toggle speaker-output according to the hp-jack state */
1846static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
1847{
1848 unsigned int gpiostate, gpiomask, gpiodir;
1849
1850 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
1851 AC_VERB_GET_GPIO_DATA, 0);
1852
1853 if (!muted)
1854 gpiostate |= (1 << pin);
1855 else
1856 gpiostate &= ~(1 << pin);
1857
1858 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
1859 AC_VERB_GET_GPIO_MASK, 0);
1860 gpiomask |= (1 << pin);
1861
1862 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
1863 AC_VERB_GET_GPIO_DIRECTION, 0);
1864 gpiodir |= (1 << pin);
1865
1866
1867 snd_hda_codec_write(codec, codec->afg, 0,
1868 AC_VERB_SET_GPIO_MASK, gpiomask);
1869 snd_hda_codec_write(codec, codec->afg, 0,
1870 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
1871
1872 msleep(1);
1873
1874 snd_hda_codec_write(codec, codec->afg, 0,
1875 AC_VERB_SET_GPIO_DATA, gpiostate);
1876}
1877
1878/* set up GPIO at initialization */
1879static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
1727a771 1880 const struct hda_fixup *fix, int action)
5671087f 1881{
1727a771 1882 if (action != HDA_FIXUP_ACT_INIT)
5671087f
TI
1883 return;
1884 alc882_gpio_mute(codec, 0, 0);
1885 alc882_gpio_mute(codec, 1, 0);
1886}
1887
02a237b2
TI
1888/* Fix the connection of some pins for ALC889:
1889 * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
1890 * work correctly (bko#42740)
1891 */
1892static void alc889_fixup_dac_route(struct hda_codec *codec,
1727a771 1893 const struct hda_fixup *fix, int action)
02a237b2 1894{
1727a771 1895 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
ef8d60fb 1896 /* fake the connections during parsing the tree */
02a237b2
TI
1897 hda_nid_t conn1[2] = { 0x0c, 0x0d };
1898 hda_nid_t conn2[2] = { 0x0e, 0x0f };
1899 snd_hda_override_conn_list(codec, 0x14, 2, conn1);
1900 snd_hda_override_conn_list(codec, 0x15, 2, conn1);
1901 snd_hda_override_conn_list(codec, 0x18, 2, conn2);
1902 snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
1727a771 1903 } else if (action == HDA_FIXUP_ACT_PROBE) {
ef8d60fb
TI
1904 /* restore the connections */
1905 hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
1906 snd_hda_override_conn_list(codec, 0x14, 5, conn);
1907 snd_hda_override_conn_list(codec, 0x15, 5, conn);
1908 snd_hda_override_conn_list(codec, 0x18, 5, conn);
1909 snd_hda_override_conn_list(codec, 0x1a, 5, conn);
02a237b2
TI
1910 }
1911}
1912
1a97b7f2
TI
1913/* Set VREF on HP pin */
1914static void alc889_fixup_mbp_vref(struct hda_codec *codec,
1727a771 1915 const struct hda_fixup *fix, int action)
1a97b7f2
TI
1916{
1917 struct alc_spec *spec = codec->spec;
1918 static hda_nid_t nids[2] = { 0x14, 0x15 };
1919 int i;
1920
1727a771 1921 if (action != HDA_FIXUP_ACT_INIT)
1a97b7f2
TI
1922 return;
1923 for (i = 0; i < ARRAY_SIZE(nids); i++) {
1924 unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]);
1925 if (get_defcfg_device(val) != AC_JACK_HP_OUT)
1926 continue;
d3f02d60 1927 val = snd_hda_codec_get_pin_target(codec, nids[i]);
1a97b7f2 1928 val |= AC_PINCTL_VREF_80;
cdd03ced 1929 snd_hda_set_pin_ctl(codec, nids[i], val);
08c189f2 1930 spec->gen.keep_vref_in_automute = 1;
1a97b7f2
TI
1931 break;
1932 }
1933}
1934
0756f09c
TI
1935static void alc889_fixup_mac_pins(struct hda_codec *codec,
1936 const hda_nid_t *nids, int num_nids)
1a97b7f2
TI
1937{
1938 struct alc_spec *spec = codec->spec;
1a97b7f2
TI
1939 int i;
1940
0756f09c 1941 for (i = 0; i < num_nids; i++) {
1a97b7f2 1942 unsigned int val;
d3f02d60 1943 val = snd_hda_codec_get_pin_target(codec, nids[i]);
1a97b7f2 1944 val |= AC_PINCTL_VREF_50;
cdd03ced 1945 snd_hda_set_pin_ctl(codec, nids[i], val);
1a97b7f2 1946 }
08c189f2 1947 spec->gen.keep_vref_in_automute = 1;
1a97b7f2
TI
1948}
1949
0756f09c
TI
1950/* Set VREF on speaker pins on imac91 */
1951static void alc889_fixup_imac91_vref(struct hda_codec *codec,
1952 const struct hda_fixup *fix, int action)
1953{
1954 static hda_nid_t nids[2] = { 0x18, 0x1a };
1955
1956 if (action == HDA_FIXUP_ACT_INIT)
1957 alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
1958}
1959
1960/* Set VREF on speaker pins on mba21 */
1961static void alc889_fixup_mba21_vref(struct hda_codec *codec,
1962 const struct hda_fixup *fix, int action)
1963{
1964 static hda_nid_t nids[2] = { 0x18, 0x19 };
1965
1966 if (action == HDA_FIXUP_ACT_INIT)
1967 alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
1968}
1969
e427c237 1970/* Don't take HP output as primary
d9111496
FLVC
1971 * Strangely, the speaker output doesn't work on Vaio Z and some Vaio
1972 * all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05
e427c237
TI
1973 */
1974static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
1727a771 1975 const struct hda_fixup *fix, int action)
e427c237
TI
1976{
1977 struct alc_spec *spec = codec->spec;
da96fb5b 1978 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
08c189f2 1979 spec->gen.no_primary_hp = 1;
da96fb5b
TI
1980 spec->gen.no_multi_io = 1;
1981 }
e427c237
TI
1982}
1983
eb9ca3ab
TI
1984static void alc_fixup_bass_chmap(struct hda_codec *codec,
1985 const struct hda_fixup *fix, int action);
1986
1727a771 1987static const struct hda_fixup alc882_fixups[] = {
5c0ebfbe 1988 [ALC882_FIXUP_ABIT_AW9D_MAX] = {
1727a771
TI
1989 .type = HDA_FIXUP_PINS,
1990 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
1991 { 0x15, 0x01080104 }, /* side */
1992 { 0x16, 0x01011012 }, /* rear */
1993 { 0x17, 0x01016011 }, /* clfe */
2785591a 1994 { }
145a902b
DH
1995 }
1996 },
5c0ebfbe 1997 [ALC882_FIXUP_LENOVO_Y530] = {
1727a771
TI
1998 .type = HDA_FIXUP_PINS,
1999 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
2000 { 0x15, 0x99130112 }, /* rear int speakers */
2001 { 0x16, 0x99130111 }, /* subwoofer */
ac612407
DH
2002 { }
2003 }
2004 },
5c0ebfbe 2005 [ALC882_FIXUP_PB_M5210] = {
fd108215
TI
2006 .type = HDA_FIXUP_PINCTLS,
2007 .v.pins = (const struct hda_pintbl[]) {
2008 { 0x19, PIN_VREF50 },
357f915e
KY
2009 {}
2010 }
2011 },
5c0ebfbe 2012 [ALC882_FIXUP_ACER_ASPIRE_7736] = {
1727a771 2013 .type = HDA_FIXUP_FUNC,
23d30f28 2014 .v.func = alc_fixup_sku_ignore,
6981d184 2015 },
5c0ebfbe 2016 [ALC882_FIXUP_ASUS_W90V] = {
1727a771
TI
2017 .type = HDA_FIXUP_PINS,
2018 .v.pins = (const struct hda_pintbl[]) {
5cdf745e
TI
2019 { 0x16, 0x99130110 }, /* fix sequence for CLFE */
2020 { }
2021 }
2022 },
8f239214 2023 [ALC889_FIXUP_CD] = {
1727a771
TI
2024 .type = HDA_FIXUP_PINS,
2025 .v.pins = (const struct hda_pintbl[]) {
8f239214
MB
2026 { 0x1c, 0x993301f0 }, /* CD */
2027 { }
2028 }
2029 },
5c0ebfbe 2030 [ALC889_FIXUP_VAIO_TT] = {
1727a771
TI
2031 .type = HDA_FIXUP_PINS,
2032 .v.pins = (const struct hda_pintbl[]) {
5c0ebfbe
TI
2033 { 0x17, 0x90170111 }, /* hidden surround speaker */
2034 { }
2035 }
2036 },
0e7cc2e7 2037 [ALC888_FIXUP_EEE1601] = {
1727a771 2038 .type = HDA_FIXUP_VERBS,
0e7cc2e7
TI
2039 .v.verbs = (const struct hda_verb[]) {
2040 { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
2041 { 0x20, AC_VERB_SET_PROC_COEF, 0x0838 },
2042 { }
2043 }
177943a3
TI
2044 },
2045 [ALC882_FIXUP_EAPD] = {
1727a771 2046 .type = HDA_FIXUP_VERBS,
177943a3
TI
2047 .v.verbs = (const struct hda_verb[]) {
2048 /* change to EAPD mode */
2049 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2050 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
2051 { }
2052 }
2053 },
7a6069bf 2054 [ALC883_FIXUP_EAPD] = {
1727a771 2055 .type = HDA_FIXUP_VERBS,
7a6069bf
TI
2056 .v.verbs = (const struct hda_verb[]) {
2057 /* change to EAPD mode */
2058 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2059 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
2060 { }
2061 }
2062 },
8812c4f9 2063 [ALC883_FIXUP_ACER_EAPD] = {
1727a771 2064 .type = HDA_FIXUP_VERBS,
8812c4f9
TI
2065 .v.verbs = (const struct hda_verb[]) {
2066 /* eanable EAPD on Acer laptops */
2067 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2068 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2069 { }
2070 }
2071 },
1a97b7f2 2072 [ALC882_FIXUP_GPIO1] = {
1727a771 2073 .type = HDA_FIXUP_VERBS,
1a97b7f2
TI
2074 .v.verbs = alc_gpio1_init_verbs,
2075 },
2076 [ALC882_FIXUP_GPIO2] = {
1727a771 2077 .type = HDA_FIXUP_VERBS,
1a97b7f2
TI
2078 .v.verbs = alc_gpio2_init_verbs,
2079 },
eb844d51 2080 [ALC882_FIXUP_GPIO3] = {
1727a771 2081 .type = HDA_FIXUP_VERBS,
eb844d51
TI
2082 .v.verbs = alc_gpio3_init_verbs,
2083 },
68ef0561 2084 [ALC882_FIXUP_ASUS_W2JC] = {
1727a771 2085 .type = HDA_FIXUP_VERBS,
68ef0561
TI
2086 .v.verbs = alc_gpio1_init_verbs,
2087 .chained = true,
2088 .chain_id = ALC882_FIXUP_EAPD,
2089 },
2090 [ALC889_FIXUP_COEF] = {
1727a771 2091 .type = HDA_FIXUP_FUNC,
68ef0561
TI
2092 .v.func = alc889_fixup_coef,
2093 },
c3e837bb 2094 [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
1727a771
TI
2095 .type = HDA_FIXUP_PINS,
2096 .v.pins = (const struct hda_pintbl[]) {
c3e837bb
TI
2097 { 0x16, 0x99130111 }, /* CLFE speaker */
2098 { 0x17, 0x99130112 }, /* surround speaker */
2099 { }
038d4fef
TI
2100 },
2101 .chained = true,
2102 .chain_id = ALC882_FIXUP_GPIO1,
c3e837bb
TI
2103 },
2104 [ALC882_FIXUP_ACER_ASPIRE_8930G] = {
1727a771
TI
2105 .type = HDA_FIXUP_PINS,
2106 .v.pins = (const struct hda_pintbl[]) {
c3e837bb
TI
2107 { 0x16, 0x99130111 }, /* CLFE speaker */
2108 { 0x1b, 0x99130112 }, /* surround speaker */
2109 { }
2110 },
2111 .chained = true,
2112 .chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS,
2113 },
2114 [ALC882_FIXUP_ASPIRE_8930G_VERBS] = {
2115 /* additional init verbs for Acer Aspire 8930G */
1727a771 2116 .type = HDA_FIXUP_VERBS,
c3e837bb
TI
2117 .v.verbs = (const struct hda_verb[]) {
2118 /* Enable all DACs */
2119 /* DAC DISABLE/MUTE 1? */
2120 /* setting bits 1-5 disables DAC nids 0x02-0x06
2121 * apparently. Init=0x38 */
2122 { 0x20, AC_VERB_SET_COEF_INDEX, 0x03 },
2123 { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
2124 /* DAC DISABLE/MUTE 2? */
2125 /* some bit here disables the other DACs.
2126 * Init=0x4900 */
2127 { 0x20, AC_VERB_SET_COEF_INDEX, 0x08 },
2128 { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
2129 /* DMIC fix
2130 * This laptop has a stereo digital microphone.
2131 * The mics are only 1cm apart which makes the stereo
2132 * useless. However, either the mic or the ALC889
2133 * makes the signal become a difference/sum signal
2134 * instead of standard stereo, which is annoying.
2135 * So instead we flip this bit which makes the
2136 * codec replicate the sum signal to both channels,
2137 * turning it into a normal mono mic.
2138 */
2139 /* DMIC_CONTROL? Init value = 0x0001 */
2140 { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
2141 { 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
2142 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2143 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2144 { }
038d4fef
TI
2145 },
2146 .chained = true,
2147 .chain_id = ALC882_FIXUP_GPIO1,
c3e837bb 2148 },
5671087f 2149 [ALC885_FIXUP_MACPRO_GPIO] = {
1727a771 2150 .type = HDA_FIXUP_FUNC,
5671087f
TI
2151 .v.func = alc885_fixup_macpro_gpio,
2152 },
02a237b2 2153 [ALC889_FIXUP_DAC_ROUTE] = {
1727a771 2154 .type = HDA_FIXUP_FUNC,
02a237b2
TI
2155 .v.func = alc889_fixup_dac_route,
2156 },
1a97b7f2 2157 [ALC889_FIXUP_MBP_VREF] = {
1727a771 2158 .type = HDA_FIXUP_FUNC,
1a97b7f2
TI
2159 .v.func = alc889_fixup_mbp_vref,
2160 .chained = true,
2161 .chain_id = ALC882_FIXUP_GPIO1,
2162 },
2163 [ALC889_FIXUP_IMAC91_VREF] = {
1727a771 2164 .type = HDA_FIXUP_FUNC,
1a97b7f2
TI
2165 .v.func = alc889_fixup_imac91_vref,
2166 .chained = true,
2167 .chain_id = ALC882_FIXUP_GPIO1,
2168 },
0756f09c
TI
2169 [ALC889_FIXUP_MBA21_VREF] = {
2170 .type = HDA_FIXUP_FUNC,
2171 .v.func = alc889_fixup_mba21_vref,
2172 .chained = true,
2173 .chain_id = ALC889_FIXUP_MBP_VREF,
2174 },
6e72aa5f 2175 [ALC882_FIXUP_INV_DMIC] = {
1727a771 2176 .type = HDA_FIXUP_FUNC,
6e72aa5f
TI
2177 .v.func = alc_fixup_inv_dmic_0x12,
2178 },
e427c237 2179 [ALC882_FIXUP_NO_PRIMARY_HP] = {
1727a771 2180 .type = HDA_FIXUP_FUNC,
e427c237
TI
2181 .v.func = alc882_fixup_no_primary_hp,
2182 },
1f0bbf03
TI
2183 [ALC887_FIXUP_ASUS_BASS] = {
2184 .type = HDA_FIXUP_PINS,
2185 .v.pins = (const struct hda_pintbl[]) {
2186 {0x16, 0x99130130}, /* bass speaker */
2187 {}
2188 },
eb9ca3ab
TI
2189 .chained = true,
2190 .chain_id = ALC887_FIXUP_BASS_CHMAP,
2191 },
2192 [ALC887_FIXUP_BASS_CHMAP] = {
2193 .type = HDA_FIXUP_FUNC,
2194 .v.func = alc_fixup_bass_chmap,
1f0bbf03 2195 },
ff818c24
TI
2196};
2197
1d045db9 2198static const struct snd_pci_quirk alc882_fixup_tbl[] = {
8812c4f9
TI
2199 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
2200 SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
2201 SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD),
2202 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
2203 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD),
2204 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_FIXUP_ACER_EAPD),
c3e837bb
TI
2205 SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
2206 ALC882_FIXUP_ACER_ASPIRE_4930G),
2207 SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
2208 ALC882_FIXUP_ACER_ASPIRE_4930G),
2209 SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
2210 ALC882_FIXUP_ACER_ASPIRE_8930G),
2211 SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
2212 ALC882_FIXUP_ACER_ASPIRE_8930G),
2213 SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
2214 ALC882_FIXUP_ACER_ASPIRE_4930G),
2215 SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
2216 ALC882_FIXUP_ACER_ASPIRE_4930G),
2217 SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
2218 ALC882_FIXUP_ACER_ASPIRE_4930G),
5c0ebfbe 2219 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
f5c53d89
TI
2220 SND_PCI_QUIRK(0x1025, 0x021e, "Acer Aspire 5739G",
2221 ALC882_FIXUP_ACER_ASPIRE_4930G),
02a237b2 2222 SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
fe97da1f 2223 SND_PCI_QUIRK(0x1025, 0x026b, "Acer Aspire 8940G", ALC882_FIXUP_ACER_ASPIRE_8930G),
ac9b1cdd 2224 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
177943a3 2225 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
5c0ebfbe 2226 SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
68ef0561 2227 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
0e7cc2e7 2228 SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
1f0bbf03 2229 SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
ac9b1cdd 2230 SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
e427c237 2231 SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
12e31a78 2232 SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
5671087f
TI
2233
2234 /* All Apple entries are in codec SSIDs */
1a97b7f2
TI
2235 SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
2236 SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
2237 SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
5671087f
TI
2238 SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO),
2239 SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
2240 SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
1a97b7f2
TI
2241 SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
2242 SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
5671087f 2243 SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
1a97b7f2 2244 SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF),
0756f09c 2245 SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF),
1a97b7f2
TI
2246 SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
2247 SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
5671087f 2248 SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
1a97b7f2
TI
2249 SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
2250 SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
2251 SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
29ebe402 2252 SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO),
05193639 2253 SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
1a97b7f2
TI
2254 SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
2255 SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
2256 SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
5671087f 2257
7a6069bf 2258 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
bca40138 2259 SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
eb844d51 2260 SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
8f239214 2261 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3", ALC889_FIXUP_CD),
5c0ebfbe 2262 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
7a6069bf
TI
2263 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
2264 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
ac9b1cdd 2265 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
68ef0561 2266 SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_FIXUP_COEF),
ff818c24
TI
2267 {}
2268};
2269
1727a771 2270static const struct hda_model_fixup alc882_fixup_models[] = {
912093bc
TI
2271 {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"},
2272 {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"},
2273 {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"},
6e72aa5f 2274 {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"},
e427c237 2275 {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"},
912093bc
TI
2276 {}
2277};
2278
f6a92248 2279/*
1d045db9 2280 * BIOS auto configuration
f6a92248 2281 */
1d045db9
TI
2282/* almost identical with ALC880 parser... */
2283static int alc882_parse_auto_config(struct hda_codec *codec)
2284{
1d045db9 2285 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
3e6179b8
TI
2286 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2287 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
1d045db9 2288}
b896b4eb 2289
1d045db9
TI
2290/*
2291 */
1d045db9 2292static int patch_alc882(struct hda_codec *codec)
f6a92248
KY
2293{
2294 struct alc_spec *spec;
1a97b7f2 2295 int err;
f6a92248 2296
3de95173
TI
2297 err = alc_alloc_spec(codec, 0x0b);
2298 if (err < 0)
2299 return err;
f6a92248 2300
3de95173 2301 spec = codec->spec;
1f0f4b80 2302
1d045db9
TI
2303 switch (codec->vendor_id) {
2304 case 0x10ec0882:
2305 case 0x10ec0885:
2306 break;
2307 default:
2308 /* ALC883 and variants */
2309 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
2310 break;
c793bec5 2311 }
977ddd6b 2312
1727a771 2313 snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
912093bc 2314 alc882_fixups);
1727a771 2315 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
ff818c24 2316
1d045db9
TI
2317 alc_auto_parse_customize_define(codec);
2318
7504b6cd
TI
2319 if (has_cdefine_beep(codec))
2320 spec->gen.beep_nid = 0x01;
2321
1a97b7f2
TI
2322 /* automatic parse from the BIOS config */
2323 err = alc882_parse_auto_config(codec);
2324 if (err < 0)
2325 goto error;
f6a92248 2326
7504b6cd 2327 if (!spec->gen.no_analog && spec->gen.beep_nid)
1d045db9 2328 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
f6a92248
KY
2329
2330 codec->patch_ops = alc_patch_ops;
bf1b0225 2331
1727a771 2332 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 2333
f6a92248 2334 return 0;
e16fb6d1
TI
2335
2336 error:
2337 alc_free(codec);
2338 return err;
f6a92248
KY
2339}
2340
df694daa 2341
df694daa 2342/*
1d045db9 2343 * ALC262 support
df694daa 2344 */
1d045db9 2345static int alc262_parse_auto_config(struct hda_codec *codec)
df694daa 2346{
1d045db9 2347 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
3e6179b8
TI
2348 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2349 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
df694daa
KY
2350}
2351
df694daa 2352/*
1d045db9 2353 * Pin config fixes
df694daa 2354 */
cfc9b06f 2355enum {
ea4e7af1 2356 ALC262_FIXUP_FSC_H270,
7513e6da 2357 ALC262_FIXUP_FSC_S7110,
ea4e7af1
TI
2358 ALC262_FIXUP_HP_Z200,
2359 ALC262_FIXUP_TYAN,
c470150c 2360 ALC262_FIXUP_LENOVO_3000,
b42590b8
TI
2361 ALC262_FIXUP_BENQ,
2362 ALC262_FIXUP_BENQ_T31,
6e72aa5f 2363 ALC262_FIXUP_INV_DMIC,
b5c6611f 2364 ALC262_FIXUP_INTEL_BAYLEYBAY,
cfc9b06f
TI
2365};
2366
1727a771 2367static const struct hda_fixup alc262_fixups[] = {
ea4e7af1 2368 [ALC262_FIXUP_FSC_H270] = {
1727a771
TI
2369 .type = HDA_FIXUP_PINS,
2370 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
2371 { 0x14, 0x99130110 }, /* speaker */
2372 { 0x15, 0x0221142f }, /* front HP */
2373 { 0x1b, 0x0121141f }, /* rear HP */
2374 { }
2375 }
2376 },
7513e6da
TI
2377 [ALC262_FIXUP_FSC_S7110] = {
2378 .type = HDA_FIXUP_PINS,
2379 .v.pins = (const struct hda_pintbl[]) {
2380 { 0x15, 0x90170110 }, /* speaker */
2381 { }
2382 },
2383 .chained = true,
2384 .chain_id = ALC262_FIXUP_BENQ,
2385 },
ea4e7af1 2386 [ALC262_FIXUP_HP_Z200] = {
1727a771
TI
2387 .type = HDA_FIXUP_PINS,
2388 .v.pins = (const struct hda_pintbl[]) {
1d045db9 2389 { 0x16, 0x99130120 }, /* internal speaker */
73413b12
TI
2390 { }
2391 }
cfc9b06f 2392 },
ea4e7af1 2393 [ALC262_FIXUP_TYAN] = {
1727a771
TI
2394 .type = HDA_FIXUP_PINS,
2395 .v.pins = (const struct hda_pintbl[]) {
ea4e7af1
TI
2396 { 0x14, 0x1993e1f0 }, /* int AUX */
2397 { }
2398 }
2399 },
c470150c 2400 [ALC262_FIXUP_LENOVO_3000] = {
fd108215
TI
2401 .type = HDA_FIXUP_PINCTLS,
2402 .v.pins = (const struct hda_pintbl[]) {
2403 { 0x19, PIN_VREF50 },
b42590b8
TI
2404 {}
2405 },
2406 .chained = true,
2407 .chain_id = ALC262_FIXUP_BENQ,
2408 },
2409 [ALC262_FIXUP_BENQ] = {
1727a771 2410 .type = HDA_FIXUP_VERBS,
b42590b8 2411 .v.verbs = (const struct hda_verb[]) {
c470150c
TI
2412 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2413 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
2414 {}
2415 }
2416 },
b42590b8 2417 [ALC262_FIXUP_BENQ_T31] = {
1727a771 2418 .type = HDA_FIXUP_VERBS,
b42590b8
TI
2419 .v.verbs = (const struct hda_verb[]) {
2420 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2421 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2422 {}
2423 }
2424 },
6e72aa5f 2425 [ALC262_FIXUP_INV_DMIC] = {
1727a771 2426 .type = HDA_FIXUP_FUNC,
6e72aa5f
TI
2427 .v.func = alc_fixup_inv_dmic_0x12,
2428 },
b5c6611f
ML
2429 [ALC262_FIXUP_INTEL_BAYLEYBAY] = {
2430 .type = HDA_FIXUP_FUNC,
2431 .v.func = alc_fixup_no_depop_delay,
2432 },
cfc9b06f
TI
2433};
2434
1d045db9 2435static const struct snd_pci_quirk alc262_fixup_tbl[] = {
ea4e7af1 2436 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
7513e6da 2437 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110),
3dcd3be3 2438 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
ea4e7af1
TI
2439 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
2440 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
c470150c 2441 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
b42590b8
TI
2442 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
2443 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
b5c6611f 2444 SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY),
cfc9b06f
TI
2445 {}
2446};
df694daa 2447
1727a771 2448static const struct hda_model_fixup alc262_fixup_models[] = {
6e72aa5f
TI
2449 {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"},
2450 {}
2451};
1d045db9 2452
1d045db9
TI
2453/*
2454 */
1d045db9 2455static int patch_alc262(struct hda_codec *codec)
df694daa
KY
2456{
2457 struct alc_spec *spec;
df694daa
KY
2458 int err;
2459
3de95173
TI
2460 err = alc_alloc_spec(codec, 0x0b);
2461 if (err < 0)
2462 return err;
df694daa 2463
3de95173 2464 spec = codec->spec;
08c189f2 2465 spec->gen.shared_mic_vref_pin = 0x18;
1d045db9
TI
2466
2467#if 0
2468 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
2469 * under-run
2470 */
2471 {
2472 int tmp;
2473 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
2474 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
2475 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
2476 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
2477 }
2478#endif
1d045db9
TI
2479 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
2480
1727a771 2481 snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl,
6e72aa5f 2482 alc262_fixups);
1727a771 2483 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
9c7f852e 2484
af741c15
TI
2485 alc_auto_parse_customize_define(codec);
2486
7504b6cd
TI
2487 if (has_cdefine_beep(codec))
2488 spec->gen.beep_nid = 0x01;
2489
42399f7a
TI
2490 /* automatic parse from the BIOS config */
2491 err = alc262_parse_auto_config(codec);
2492 if (err < 0)
2493 goto error;
df694daa 2494
7504b6cd 2495 if (!spec->gen.no_analog && spec->gen.beep_nid)
1d045db9 2496 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
2134ea4f 2497
df694daa 2498 codec->patch_ops = alc_patch_ops;
1d045db9
TI
2499 spec->shutup = alc_eapd_shutup;
2500
1727a771 2501 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 2502
1da177e4 2503 return 0;
e16fb6d1
TI
2504
2505 error:
2506 alc_free(codec);
2507 return err;
1da177e4
LT
2508}
2509
f32610ed 2510/*
1d045db9 2511 * ALC268
f32610ed 2512 */
1d045db9
TI
2513/* bind Beep switches of both NID 0x0f and 0x10 */
2514static const struct hda_bind_ctls alc268_bind_beep_sw = {
2515 .ops = &snd_hda_bind_sw,
2516 .values = {
2517 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
2518 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
2519 0
2520 },
f32610ed
JS
2521};
2522
1d045db9
TI
2523static const struct snd_kcontrol_new alc268_beep_mixer[] = {
2524 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
2525 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
2526 { }
f32610ed
JS
2527};
2528
1d045db9
TI
2529/* set PCBEEP vol = 0, mute connections */
2530static const struct hda_verb alc268_beep_init_verbs[] = {
2531 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2532 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2533 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2534 { }
f32610ed
JS
2535};
2536
6e72aa5f
TI
2537enum {
2538 ALC268_FIXUP_INV_DMIC,
cb766404 2539 ALC268_FIXUP_HP_EAPD,
24eff328 2540 ALC268_FIXUP_SPDIF,
6e72aa5f
TI
2541};
2542
1727a771 2543static const struct hda_fixup alc268_fixups[] = {
6e72aa5f 2544 [ALC268_FIXUP_INV_DMIC] = {
1727a771 2545 .type = HDA_FIXUP_FUNC,
6e72aa5f
TI
2546 .v.func = alc_fixup_inv_dmic_0x12,
2547 },
cb766404 2548 [ALC268_FIXUP_HP_EAPD] = {
1727a771 2549 .type = HDA_FIXUP_VERBS,
cb766404
TI
2550 .v.verbs = (const struct hda_verb[]) {
2551 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
2552 {}
2553 }
2554 },
24eff328
TI
2555 [ALC268_FIXUP_SPDIF] = {
2556 .type = HDA_FIXUP_PINS,
2557 .v.pins = (const struct hda_pintbl[]) {
2558 { 0x1e, 0x014b1180 }, /* enable SPDIF out */
2559 {}
2560 }
2561 },
6e72aa5f
TI
2562};
2563
1727a771 2564static const struct hda_model_fixup alc268_fixup_models[] = {
6e72aa5f 2565 {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
cb766404
TI
2566 {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
2567 {}
2568};
2569
2570static const struct snd_pci_quirk alc268_fixup_tbl[] = {
24eff328 2571 SND_PCI_QUIRK(0x1025, 0x0139, "Acer TravelMate 6293", ALC268_FIXUP_SPDIF),
fcd8f3b1 2572 SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
cb766404
TI
2573 /* below is codec SSID since multiple Toshiba laptops have the
2574 * same PCI SSID 1179:ff00
2575 */
2576 SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
6e72aa5f
TI
2577 {}
2578};
2579
f32610ed
JS
2580/*
2581 * BIOS auto configuration
2582 */
1d045db9 2583static int alc268_parse_auto_config(struct hda_codec *codec)
f32610ed 2584{
3e6179b8 2585 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
7504b6cd 2586 return alc_parse_auto_config(codec, NULL, alc268_ssids);
f32610ed
JS
2587}
2588
1d045db9
TI
2589/*
2590 */
1d045db9 2591static int patch_alc268(struct hda_codec *codec)
f32610ed
JS
2592{
2593 struct alc_spec *spec;
7504b6cd 2594 int err;
f32610ed 2595
1d045db9 2596 /* ALC268 has no aa-loopback mixer */
3de95173
TI
2597 err = alc_alloc_spec(codec, 0);
2598 if (err < 0)
2599 return err;
2600
2601 spec = codec->spec;
7504b6cd 2602 spec->gen.beep_nid = 0x01;
1f0f4b80 2603
1727a771
TI
2604 snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
2605 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
6e72aa5f 2606
6ebb8053
TI
2607 /* automatic parse from the BIOS config */
2608 err = alc268_parse_auto_config(codec);
e16fb6d1
TI
2609 if (err < 0)
2610 goto error;
f32610ed 2611
7504b6cd
TI
2612 if (err > 0 && !spec->gen.no_analog &&
2613 spec->gen.autocfg.speaker_pins[0] != 0x1d) {
2614 add_mixer(spec, alc268_beep_mixer);
2615 snd_hda_add_verbs(codec, alc268_beep_init_verbs);
1d045db9
TI
2616 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
2617 /* override the amp caps for beep generator */
2618 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
2619 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
2620 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
2621 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2622 (0 << AC_AMPCAP_MUTE_SHIFT));
2f893286
KY
2623 }
2624
f32610ed 2625 codec->patch_ops = alc_patch_ops;
1c716153 2626 spec->shutup = alc_eapd_shutup;
1d045db9 2627
1727a771 2628 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
6e72aa5f 2629
f32610ed 2630 return 0;
e16fb6d1
TI
2631
2632 error:
2633 alc_free(codec);
2634 return err;
f32610ed
JS
2635}
2636
bc9f98a9 2637/*
1d045db9 2638 * ALC269
bc9f98a9 2639 */
08c189f2
TI
2640
2641static int playback_pcm_open(struct hda_pcm_stream *hinfo,
2642 struct hda_codec *codec,
2643 struct snd_pcm_substream *substream)
2644{
2645 struct hda_gen_spec *spec = codec->spec;
2646 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2647 hinfo);
2648}
2649
2650static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
2651 struct hda_codec *codec,
2652 unsigned int stream_tag,
2653 unsigned int format,
2654 struct snd_pcm_substream *substream)
2655{
2656 struct hda_gen_spec *spec = codec->spec;
2657 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2658 stream_tag, format, substream);
2659}
2660
2661static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
2662 struct hda_codec *codec,
2663 struct snd_pcm_substream *substream)
2664{
2665 struct hda_gen_spec *spec = codec->spec;
2666 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2667}
2668
1d045db9
TI
2669static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
2670 .substreams = 1,
2671 .channels_min = 2,
2672 .channels_max = 8,
2673 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
2674 /* NID is set in alc_build_pcms */
2675 .ops = {
08c189f2
TI
2676 .open = playback_pcm_open,
2677 .prepare = playback_pcm_prepare,
2678 .cleanup = playback_pcm_cleanup
bc9f98a9
KY
2679 },
2680};
2681
1d045db9
TI
2682static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
2683 .substreams = 1,
2684 .channels_min = 2,
2685 .channels_max = 2,
2686 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
2687 /* NID is set in alc_build_pcms */
bc9f98a9 2688};
291702f0 2689
1d045db9
TI
2690/* different alc269-variants */
2691enum {
2692 ALC269_TYPE_ALC269VA,
2693 ALC269_TYPE_ALC269VB,
2694 ALC269_TYPE_ALC269VC,
adcc70b2 2695 ALC269_TYPE_ALC269VD,
065380f0
KY
2696 ALC269_TYPE_ALC280,
2697 ALC269_TYPE_ALC282,
2af02be7 2698 ALC269_TYPE_ALC283,
065380f0 2699 ALC269_TYPE_ALC284,
161ebf29 2700 ALC269_TYPE_ALC285,
7fc7d047 2701 ALC269_TYPE_ALC286,
1d04c9de 2702 ALC269_TYPE_ALC255,
bc9f98a9
KY
2703};
2704
2705/*
1d045db9 2706 * BIOS auto configuration
bc9f98a9 2707 */
1d045db9
TI
2708static int alc269_parse_auto_config(struct hda_codec *codec)
2709{
1d045db9 2710 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
3e6179b8
TI
2711 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
2712 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2713 struct alc_spec *spec = codec->spec;
adcc70b2
KY
2714 const hda_nid_t *ssids;
2715
2716 switch (spec->codec_variant) {
2717 case ALC269_TYPE_ALC269VA:
2718 case ALC269_TYPE_ALC269VC:
065380f0
KY
2719 case ALC269_TYPE_ALC280:
2720 case ALC269_TYPE_ALC284:
161ebf29 2721 case ALC269_TYPE_ALC285:
adcc70b2
KY
2722 ssids = alc269va_ssids;
2723 break;
2724 case ALC269_TYPE_ALC269VB:
2725 case ALC269_TYPE_ALC269VD:
065380f0 2726 case ALC269_TYPE_ALC282:
2af02be7 2727 case ALC269_TYPE_ALC283:
7fc7d047 2728 case ALC269_TYPE_ALC286:
1d04c9de 2729 case ALC269_TYPE_ALC255:
adcc70b2
KY
2730 ssids = alc269_ssids;
2731 break;
2732 default:
2733 ssids = alc269_ssids;
2734 break;
2735 }
bc9f98a9 2736
3e6179b8 2737 return alc_parse_auto_config(codec, alc269_ignore, ssids);
1d045db9 2738}
bc9f98a9 2739
1387e2d1 2740static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
1d045db9
TI
2741{
2742 int val = alc_read_coef_idx(codec, 0x04);
2743 if (power_up)
2744 val |= 1 << 11;
2745 else
2746 val &= ~(1 << 11);
2747 alc_write_coef_idx(codec, 0x04, val);
2748}
291702f0 2749
1d045db9
TI
2750static void alc269_shutup(struct hda_codec *codec)
2751{
adcc70b2
KY
2752 struct alc_spec *spec = codec->spec;
2753
1387e2d1
KY
2754 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
2755 alc269vb_toggle_power_output(codec, 0);
2756 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
2757 (alc_get_coef0(codec) & 0x00ff) == 0x018) {
1d045db9
TI
2758 msleep(150);
2759 }
9bfb2844 2760 snd_hda_shutup_pins(codec);
1d045db9 2761}
291702f0 2762
2af02be7
KY
2763static void alc283_init(struct hda_codec *codec)
2764{
2765 struct alc_spec *spec = codec->spec;
2766 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
2767 bool hp_pin_sense;
2768 int val;
2769
2770 if (!hp_pin)
2771 return;
2772 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
2773
2774 /* Index 0x43 Direct Drive HP AMP LPM Control 1 */
2775 /* Headphone capless set to high power mode */
2776 alc_write_coef_idx(codec, 0x43, 0x9004);
2777
2778 snd_hda_codec_write(codec, hp_pin, 0,
2779 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
2780
2781 if (hp_pin_sense)
2782 msleep(85);
2783
2784 snd_hda_codec_write(codec, hp_pin, 0,
2785 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
2786
2787 if (hp_pin_sense)
2788 msleep(85);
2789 /* Index 0x46 Combo jack auto switch control 2 */
2790 /* 3k pull low control for Headset jack. */
2791 val = alc_read_coef_idx(codec, 0x46);
2792 alc_write_coef_idx(codec, 0x46, val & ~(3 << 12));
2793 /* Headphone capless set to normal mode */
2794 alc_write_coef_idx(codec, 0x43, 0x9614);
2795}
2796
2797static void alc283_shutup(struct hda_codec *codec)
2798{
2799 struct alc_spec *spec = codec->spec;
2800 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
2801 bool hp_pin_sense;
2802 int val;
2803
2804 if (!hp_pin) {
2805 alc269_shutup(codec);
2806 return;
2807 }
2808
2809 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
2810
2811 alc_write_coef_idx(codec, 0x43, 0x9004);
2812
2813 snd_hda_codec_write(codec, hp_pin, 0,
2814 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
2815
2816 if (hp_pin_sense)
88011c09 2817 msleep(100);
2af02be7
KY
2818
2819 snd_hda_codec_write(codec, hp_pin, 0,
2820 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
2821
2822 val = alc_read_coef_idx(codec, 0x46);
2823 alc_write_coef_idx(codec, 0x46, val | (3 << 12));
2824
2825 if (hp_pin_sense)
88011c09 2826 msleep(100);
2af02be7
KY
2827 snd_hda_shutup_pins(codec);
2828 alc_write_coef_idx(codec, 0x43, 0x9614);
2829}
2830
ad60d502
KY
2831static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
2832 unsigned int val)
2833{
2834 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
2835 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val & 0xffff); /* LSB */
2836 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val >> 16); /* MSB */
2837}
2838
2839static int alc5505_coef_get(struct hda_codec *codec, unsigned int index_reg)
2840{
2841 unsigned int val;
2842
2843 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
2844 val = snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
2845 & 0xffff;
2846 val |= snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
2847 << 16;
2848 return val;
2849}
2850
2851static void alc5505_dsp_halt(struct hda_codec *codec)
2852{
2853 unsigned int val;
2854
2855 alc5505_coef_set(codec, 0x3000, 0x000c); /* DSP CPU stop */
2856 alc5505_coef_set(codec, 0x880c, 0x0008); /* DDR enter self refresh */
2857 alc5505_coef_set(codec, 0x61c0, 0x11110080); /* Clock control for PLL and CPU */
2858 alc5505_coef_set(codec, 0x6230, 0xfc0d4011); /* Disable Input OP */
2859 alc5505_coef_set(codec, 0x61b4, 0x040a2b03); /* Stop PLL2 */
2860 alc5505_coef_set(codec, 0x61b0, 0x00005b17); /* Stop PLL1 */
2861 alc5505_coef_set(codec, 0x61b8, 0x04133303); /* Stop PLL3 */
2862 val = alc5505_coef_get(codec, 0x6220);
2863 alc5505_coef_set(codec, 0x6220, (val | 0x3000)); /* switch Ringbuffer clock to DBUS clock */
2864}
2865
2866static void alc5505_dsp_back_from_halt(struct hda_codec *codec)
2867{
2868 alc5505_coef_set(codec, 0x61b8, 0x04133302);
2869 alc5505_coef_set(codec, 0x61b0, 0x00005b16);
2870 alc5505_coef_set(codec, 0x61b4, 0x040a2b02);
2871 alc5505_coef_set(codec, 0x6230, 0xf80d4011);
2872 alc5505_coef_set(codec, 0x6220, 0x2002010f);
2873 alc5505_coef_set(codec, 0x880c, 0x00000004);
2874}
2875
2876static void alc5505_dsp_init(struct hda_codec *codec)
2877{
2878 unsigned int val;
2879
2880 alc5505_dsp_halt(codec);
2881 alc5505_dsp_back_from_halt(codec);
2882 alc5505_coef_set(codec, 0x61b0, 0x5b14); /* PLL1 control */
2883 alc5505_coef_set(codec, 0x61b0, 0x5b16);
2884 alc5505_coef_set(codec, 0x61b4, 0x04132b00); /* PLL2 control */
2885 alc5505_coef_set(codec, 0x61b4, 0x04132b02);
2886 alc5505_coef_set(codec, 0x61b8, 0x041f3300); /* PLL3 control*/
2887 alc5505_coef_set(codec, 0x61b8, 0x041f3302);
2888 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_CODEC_RESET, 0); /* Function reset */
2889 alc5505_coef_set(codec, 0x61b8, 0x041b3302);
2890 alc5505_coef_set(codec, 0x61b8, 0x04173302);
2891 alc5505_coef_set(codec, 0x61b8, 0x04163302);
2892 alc5505_coef_set(codec, 0x8800, 0x348b328b); /* DRAM control */
2893 alc5505_coef_set(codec, 0x8808, 0x00020022); /* DRAM control */
2894 alc5505_coef_set(codec, 0x8818, 0x00000400); /* DRAM control */
2895
2896 val = alc5505_coef_get(codec, 0x6200) >> 16; /* Read revision ID */
2897 if (val <= 3)
2898 alc5505_coef_set(codec, 0x6220, 0x2002010f); /* I/O PAD Configuration */
2899 else
2900 alc5505_coef_set(codec, 0x6220, 0x6002018f);
2901
2902 alc5505_coef_set(codec, 0x61ac, 0x055525f0); /**/
2903 alc5505_coef_set(codec, 0x61c0, 0x12230080); /* Clock control */
2904 alc5505_coef_set(codec, 0x61b4, 0x040e2b02); /* PLL2 control */
2905 alc5505_coef_set(codec, 0x61bc, 0x010234f8); /* OSC Control */
2906 alc5505_coef_set(codec, 0x880c, 0x00000004); /* DRAM Function control */
2907 alc5505_coef_set(codec, 0x880c, 0x00000003);
2908 alc5505_coef_set(codec, 0x880c, 0x00000010);
cd63a5ff
TI
2909
2910#ifdef HALT_REALTEK_ALC5505
2911 alc5505_dsp_halt(codec);
2912#endif
ad60d502
KY
2913}
2914
cd63a5ff
TI
2915#ifdef HALT_REALTEK_ALC5505
2916#define alc5505_dsp_suspend(codec) /* NOP */
2917#define alc5505_dsp_resume(codec) /* NOP */
2918#else
2919#define alc5505_dsp_suspend(codec) alc5505_dsp_halt(codec)
2920#define alc5505_dsp_resume(codec) alc5505_dsp_back_from_halt(codec)
2921#endif
2922
2a43952a 2923#ifdef CONFIG_PM
ad60d502
KY
2924static int alc269_suspend(struct hda_codec *codec)
2925{
2926 struct alc_spec *spec = codec->spec;
2927
2928 if (spec->has_alc5505_dsp)
cd63a5ff 2929 alc5505_dsp_suspend(codec);
ad60d502
KY
2930 return alc_suspend(codec);
2931}
2932
1d045db9
TI
2933static int alc269_resume(struct hda_codec *codec)
2934{
adcc70b2
KY
2935 struct alc_spec *spec = codec->spec;
2936
1387e2d1
KY
2937 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
2938 alc269vb_toggle_power_output(codec, 0);
2939 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
adcc70b2 2940 (alc_get_coef0(codec) & 0x00ff) == 0x018) {
1d045db9
TI
2941 msleep(150);
2942 }
8c427226 2943
1d045db9 2944 codec->patch_ops.init(codec);
f1d4e28b 2945
1387e2d1
KY
2946 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
2947 alc269vb_toggle_power_output(codec, 1);
2948 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
adcc70b2 2949 (alc_get_coef0(codec) & 0x00ff) == 0x017) {
1d045db9
TI
2950 msleep(200);
2951 }
f1d4e28b 2952
1d045db9
TI
2953 snd_hda_codec_resume_amp(codec);
2954 snd_hda_codec_resume_cache(codec);
0623a889 2955 alc_inv_dmic_sync(codec, true);
1d045db9 2956 hda_call_check_power_status(codec, 0x01);
ad60d502 2957 if (spec->has_alc5505_dsp)
cd63a5ff 2958 alc5505_dsp_resume(codec);
c5177c86 2959
1d045db9
TI
2960 return 0;
2961}
2a43952a 2962#endif /* CONFIG_PM */
f1d4e28b 2963
108cc108 2964static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec,
1727a771 2965 const struct hda_fixup *fix, int action)
108cc108
DH
2966{
2967 struct alc_spec *spec = codec->spec;
2968
1727a771 2969 if (action == HDA_FIXUP_ACT_PRE_PROBE)
108cc108
DH
2970 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
2971}
2972
1d045db9 2973static void alc269_fixup_hweq(struct hda_codec *codec,
1727a771 2974 const struct hda_fixup *fix, int action)
1d045db9
TI
2975{
2976 int coef;
f1d4e28b 2977
1727a771 2978 if (action != HDA_FIXUP_ACT_INIT)
1d045db9
TI
2979 return;
2980 coef = alc_read_coef_idx(codec, 0x1e);
2981 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
2982}
f1d4e28b 2983
7c478f03
DH
2984static void alc269_fixup_headset_mic(struct hda_codec *codec,
2985 const struct hda_fixup *fix, int action)
2986{
2987 struct alc_spec *spec = codec->spec;
2988
2989 if (action == HDA_FIXUP_ACT_PRE_PROBE)
2990 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
2991}
2992
1d045db9 2993static void alc271_fixup_dmic(struct hda_codec *codec,
1727a771 2994 const struct hda_fixup *fix, int action)
1d045db9
TI
2995{
2996 static const struct hda_verb verbs[] = {
2997 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
2998 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
2999 {}
3000 };
3001 unsigned int cfg;
f1d4e28b 3002
42397004
DR
3003 if (strcmp(codec->chip_name, "ALC271X") &&
3004 strcmp(codec->chip_name, "ALC269VB"))
1d045db9
TI
3005 return;
3006 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
3007 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
3008 snd_hda_sequence_write(codec, verbs);
3009}
f1d4e28b 3010
017f2a10 3011static void alc269_fixup_pcm_44k(struct hda_codec *codec,
1727a771 3012 const struct hda_fixup *fix, int action)
017f2a10
TI
3013{
3014 struct alc_spec *spec = codec->spec;
3015
1727a771 3016 if (action != HDA_FIXUP_ACT_PROBE)
017f2a10
TI
3017 return;
3018
3019 /* Due to a hardware problem on Lenovo Ideadpad, we need to
3020 * fix the sample rate of analog I/O to 44.1kHz
3021 */
08c189f2
TI
3022 spec->gen.stream_analog_playback = &alc269_44k_pcm_analog_playback;
3023 spec->gen.stream_analog_capture = &alc269_44k_pcm_analog_capture;
017f2a10
TI
3024}
3025
adabb3ec 3026static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
1727a771 3027 const struct hda_fixup *fix, int action)
adabb3ec
TI
3028{
3029 int coef;
3030
1727a771 3031 if (action != HDA_FIXUP_ACT_INIT)
adabb3ec
TI
3032 return;
3033 /* The digital-mic unit sends PDM (differential signal) instead of
3034 * the standard PCM, thus you can't record a valid mono stream as is.
3035 * Below is a workaround specific to ALC269 to control the dmic
3036 * signal source as mono.
3037 */
3038 coef = alc_read_coef_idx(codec, 0x07);
3039 alc_write_coef_idx(codec, 0x07, coef | 0x80);
3040}
3041
24519911
TI
3042static void alc269_quanta_automute(struct hda_codec *codec)
3043{
08c189f2 3044 snd_hda_gen_update_outputs(codec);
24519911
TI
3045
3046 snd_hda_codec_write(codec, 0x20, 0,
3047 AC_VERB_SET_COEF_INDEX, 0x0c);
3048 snd_hda_codec_write(codec, 0x20, 0,
3049 AC_VERB_SET_PROC_COEF, 0x680);
3050
3051 snd_hda_codec_write(codec, 0x20, 0,
3052 AC_VERB_SET_COEF_INDEX, 0x0c);
3053 snd_hda_codec_write(codec, 0x20, 0,
3054 AC_VERB_SET_PROC_COEF, 0x480);
3055}
3056
3057static void alc269_fixup_quanta_mute(struct hda_codec *codec,
1727a771 3058 const struct hda_fixup *fix, int action)
24519911
TI
3059{
3060 struct alc_spec *spec = codec->spec;
1727a771 3061 if (action != HDA_FIXUP_ACT_PROBE)
24519911 3062 return;
08c189f2 3063 spec->gen.automute_hook = alc269_quanta_automute;
24519911
TI
3064}
3065
d240d1dc
DH
3066static void alc269_x101_hp_automute_hook(struct hda_codec *codec,
3067 struct hda_jack_tbl *jack)
3068{
3069 struct alc_spec *spec = codec->spec;
3070 int vref;
3071 msleep(200);
3072 snd_hda_gen_hp_automute(codec, jack);
3073
3074 vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
3075 msleep(100);
3076 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3077 vref);
3078 msleep(500);
3079 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3080 vref);
3081}
3082
3083static void alc269_fixup_x101_headset_mic(struct hda_codec *codec,
3084 const struct hda_fixup *fix, int action)
3085{
3086 struct alc_spec *spec = codec->spec;
3087 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3088 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
3089 spec->gen.hp_automute_hook = alc269_x101_hp_automute_hook;
3090 }
3091}
3092
3093
08fb0d0e
TI
3094/* update mute-LED according to the speaker mute state via mic VREF pin */
3095static void alc269_fixup_mic_mute_hook(void *private_data, int enabled)
6d3cd5d4
DH
3096{
3097 struct hda_codec *codec = private_data;
08fb0d0e
TI
3098 struct alc_spec *spec = codec->spec;
3099 unsigned int pinval;
3100
3101 if (spec->mute_led_polarity)
3102 enabled = !enabled;
3103 pinval = AC_PINCTL_IN_EN |
3104 (enabled ? AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80);
3105 if (spec->mute_led_nid)
3106 snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval);
6d3cd5d4
DH
3107}
3108
d5b6b65e
DH
3109/* Make sure the led works even in runtime suspend */
3110static unsigned int led_power_filter(struct hda_codec *codec,
3111 hda_nid_t nid,
3112 unsigned int power_state)
3113{
3114 struct alc_spec *spec = codec->spec;
3115
3116 if (power_state != AC_PWRST_D3 || nid != spec->mute_led_nid)
3117 return power_state;
3118
3119 /* Set pin ctl again, it might have just been set to 0 */
3120 snd_hda_set_pin_ctl(codec, nid,
3121 snd_hda_codec_get_pin_target(codec, nid));
3122
3123 return AC_PWRST_D0;
3124}
3125
08fb0d0e
TI
3126static void alc269_fixup_hp_mute_led(struct hda_codec *codec,
3127 const struct hda_fixup *fix, int action)
6d3cd5d4
DH
3128{
3129 struct alc_spec *spec = codec->spec;
08fb0d0e
TI
3130 const struct dmi_device *dev = NULL;
3131
3132 if (action != HDA_FIXUP_ACT_PRE_PROBE)
3133 return;
3134
3135 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
3136 int pol, pin;
3137 if (sscanf(dev->name, "HP_Mute_LED_%d_%x", &pol, &pin) != 2)
3138 continue;
3139 if (pin < 0x0a || pin >= 0x10)
3140 break;
3141 spec->mute_led_polarity = pol;
3142 spec->mute_led_nid = pin - 0x0a + 0x18;
3143 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
fd25a97a 3144 spec->gen.vmaster_mute_enum = 1;
d5b6b65e 3145 codec->power_filter = led_power_filter;
08fb0d0e
TI
3146 snd_printd("Detected mute LED for %x:%d\n", spec->mute_led_nid,
3147 spec->mute_led_polarity);
6d3cd5d4
DH
3148 break;
3149 }
3150}
3151
d06ac143
DH
3152static void alc269_fixup_hp_mute_led_mic1(struct hda_codec *codec,
3153 const struct hda_fixup *fix, int action)
3154{
3155 struct alc_spec *spec = codec->spec;
3156 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3157 spec->mute_led_polarity = 0;
3158 spec->mute_led_nid = 0x18;
3159 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
3160 spec->gen.vmaster_mute_enum = 1;
d5b6b65e 3161 codec->power_filter = led_power_filter;
d06ac143
DH
3162 }
3163}
3164
08fb0d0e
TI
3165static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec,
3166 const struct hda_fixup *fix, int action)
420b0feb
TI
3167{
3168 struct alc_spec *spec = codec->spec;
9bb1f06f 3169 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
08fb0d0e
TI
3170 spec->mute_led_polarity = 0;
3171 spec->mute_led_nid = 0x19;
3172 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
fd25a97a 3173 spec->gen.vmaster_mute_enum = 1;
d5b6b65e 3174 codec->power_filter = led_power_filter;
420b0feb
TI
3175 }
3176}
3177
9f5c6faf
TI
3178/* turn on/off mute LED per vmaster hook */
3179static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled)
3180{
3181 struct hda_codec *codec = private_data;
3182 struct alc_spec *spec = codec->spec;
3183 unsigned int oldval = spec->gpio_led;
3184
3185 if (enabled)
3186 spec->gpio_led &= ~0x08;
3187 else
3188 spec->gpio_led |= 0x08;
3189 if (spec->gpio_led != oldval)
3190 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3191 spec->gpio_led);
3192}
3193
3194/* turn on/off mic-mute LED per capture hook */
3195static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec,
3196 struct snd_ctl_elem_value *ucontrol)
3197{
3198 struct alc_spec *spec = codec->spec;
3199 unsigned int oldval = spec->gpio_led;
3200
3201 if (!ucontrol)
3202 return;
3203
3204 if (ucontrol->value.integer.value[0] ||
3205 ucontrol->value.integer.value[1])
3206 spec->gpio_led &= ~0x10;
3207 else
3208 spec->gpio_led |= 0x10;
3209 if (spec->gpio_led != oldval)
3210 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3211 spec->gpio_led);
3212}
3213
3214static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
3215 const struct hda_fixup *fix, int action)
3216{
3217 struct alc_spec *spec = codec->spec;
3218 static const struct hda_verb gpio_init[] = {
3219 { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
3220 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
3221 {}
3222 };
3223
3224 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3225 spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
3226 spec->gen.cap_sync_hook = alc269_fixup_hp_gpio_mic_mute_hook;
3227 spec->gpio_led = 0;
3228 snd_hda_add_verbs(codec, gpio_init);
3229 }
3230}
3231
73bdd597
DH
3232static void alc_headset_mode_unplugged(struct hda_codec *codec)
3233{
3234 int val;
3235
3236 switch (codec->vendor_id) {
9a22a8f5
KY
3237 case 0x10ec0255:
3238 /* LDO and MISC control */
3239 alc_write_coef_idx(codec, 0x1b, 0x0c0b);
3240 /* UAJ function set to menual mode */
3241 alc_write_coef_idx(codec, 0x45, 0xd089);
3242 /* Direct Drive HP Amp control(Set to verb control)*/
3243 val = alc_read_coefex_idx(codec, 0x57, 0x05);
3244 alc_write_coefex_idx(codec, 0x57, 0x05, val & ~(1<<14));
3245 /* Set MIC2 Vref gate with HP */
3246 alc_write_coef_idx(codec, 0x06, 0x6104);
3247 /* Direct Drive HP Amp control */
3248 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6);
3249 break;
73bdd597
DH
3250 case 0x10ec0283:
3251 alc_write_coef_idx(codec, 0x1b, 0x0c0b);
3252 alc_write_coef_idx(codec, 0x45, 0xc429);
3253 val = alc_read_coef_idx(codec, 0x35);
3254 alc_write_coef_idx(codec, 0x35, val & 0xbfff);
3255 alc_write_coef_idx(codec, 0x06, 0x2104);
3256 alc_write_coef_idx(codec, 0x1a, 0x0001);
3257 alc_write_coef_idx(codec, 0x26, 0x0004);
3258 alc_write_coef_idx(codec, 0x32, 0x42a3);
3259 break;
3260 case 0x10ec0292:
3261 alc_write_coef_idx(codec, 0x76, 0x000e);
3262 alc_write_coef_idx(codec, 0x6c, 0x2400);
3263 alc_write_coef_idx(codec, 0x18, 0x7308);
3264 alc_write_coef_idx(codec, 0x6b, 0xc429);
3265 break;
3266 case 0x10ec0668:
3267 alc_write_coef_idx(codec, 0x15, 0x0d40);
3268 alc_write_coef_idx(codec, 0xb7, 0x802b);
3269 break;
3270 }
3271 snd_printdd("Headset jack set to unplugged mode.\n");
3272}
3273
3274
3275static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
3276 hda_nid_t mic_pin)
3277{
3278 int val;
3279
3280 switch (codec->vendor_id) {
9a22a8f5
KY
3281 case 0x10ec0255:
3282 alc_write_coef_idx(codec, 0x45, 0xc489);
3283 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3284 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6);
3285 /* Set MIC2 Vref gate to normal */
3286 alc_write_coef_idx(codec, 0x06, 0x6100);
3287 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3288 break;
73bdd597
DH
3289 case 0x10ec0283:
3290 alc_write_coef_idx(codec, 0x45, 0xc429);
3291 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3292 val = alc_read_coef_idx(codec, 0x35);
3293 alc_write_coef_idx(codec, 0x35, val | 1<<14);
3294 alc_write_coef_idx(codec, 0x06, 0x2100);
3295 alc_write_coef_idx(codec, 0x1a, 0x0021);
3296 alc_write_coef_idx(codec, 0x26, 0x008c);
3297 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3298 break;
3299 case 0x10ec0292:
3300 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3301 alc_write_coef_idx(codec, 0x19, 0xa208);
3302 alc_write_coef_idx(codec, 0x2e, 0xacf0);
3303 break;
3304 case 0x10ec0668:
3305 alc_write_coef_idx(codec, 0x11, 0x0001);
3306 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3307 alc_write_coef_idx(codec, 0xb7, 0x802b);
3308 alc_write_coef_idx(codec, 0xb5, 0x1040);
3309 val = alc_read_coef_idx(codec, 0xc3);
3310 alc_write_coef_idx(codec, 0xc3, val | 1<<12);
3311 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3312 break;
3313 }
3314 snd_printdd("Headset jack set to mic-in mode.\n");
3315}
3316
3317static void alc_headset_mode_default(struct hda_codec *codec)
3318{
3319 switch (codec->vendor_id) {
9a22a8f5
KY
3320 case 0x10ec0255:
3321 alc_write_coef_idx(codec, 0x45, 0xc089);
3322 alc_write_coef_idx(codec, 0x45, 0xc489);
3323 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
3324 alc_write_coef_idx(codec, 0x49, 0x0049);
3325 break;
73bdd597
DH
3326 case 0x10ec0283:
3327 alc_write_coef_idx(codec, 0x06, 0x2100);
3328 alc_write_coef_idx(codec, 0x32, 0x4ea3);
3329 break;
3330 case 0x10ec0292:
3331 alc_write_coef_idx(codec, 0x76, 0x000e);
3332 alc_write_coef_idx(codec, 0x6c, 0x2400);
3333 alc_write_coef_idx(codec, 0x6b, 0xc429);
3334 alc_write_coef_idx(codec, 0x18, 0x7308);
3335 break;
3336 case 0x10ec0668:
3337 alc_write_coef_idx(codec, 0x11, 0x0041);
3338 alc_write_coef_idx(codec, 0x15, 0x0d40);
3339 alc_write_coef_idx(codec, 0xb7, 0x802b);
3340 break;
3341 }
3342 snd_printdd("Headset jack set to headphone (default) mode.\n");
3343}
3344
3345/* Iphone type */
3346static void alc_headset_mode_ctia(struct hda_codec *codec)
3347{
3348 switch (codec->vendor_id) {
9a22a8f5
KY
3349 case 0x10ec0255:
3350 /* Set to CTIA type */
3351 alc_write_coef_idx(codec, 0x45, 0xd489);
3352 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3353 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
3354 break;
73bdd597
DH
3355 case 0x10ec0283:
3356 alc_write_coef_idx(codec, 0x45, 0xd429);
3357 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3358 alc_write_coef_idx(codec, 0x32, 0x4ea3);
3359 break;
3360 case 0x10ec0292:
3361 alc_write_coef_idx(codec, 0x6b, 0xd429);
3362 alc_write_coef_idx(codec, 0x76, 0x0008);
3363 alc_write_coef_idx(codec, 0x18, 0x7388);
3364 break;
3365 case 0x10ec0668:
d59915d0 3366 alc_write_coef_idx(codec, 0x11, 0x0001);
73bdd597
DH
3367 alc_write_coef_idx(codec, 0x15, 0x0d60);
3368 alc_write_coef_idx(codec, 0xc3, 0x0000);
3369 break;
3370 }
3371 snd_printdd("Headset jack set to iPhone-style headset mode.\n");
3372}
3373
3374/* Nokia type */
3375static void alc_headset_mode_omtp(struct hda_codec *codec)
3376{
3377 switch (codec->vendor_id) {
9a22a8f5
KY
3378 case 0x10ec0255:
3379 /* Set to OMTP Type */
3380 alc_write_coef_idx(codec, 0x45, 0xe489);
3381 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3382 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
3383 break;
73bdd597
DH
3384 case 0x10ec0283:
3385 alc_write_coef_idx(codec, 0x45, 0xe429);
3386 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3387 alc_write_coef_idx(codec, 0x32, 0x4ea3);
3388 break;
3389 case 0x10ec0292:
3390 alc_write_coef_idx(codec, 0x6b, 0xe429);
3391 alc_write_coef_idx(codec, 0x76, 0x0008);
3392 alc_write_coef_idx(codec, 0x18, 0x7388);
3393 break;
3394 case 0x10ec0668:
d59915d0 3395 alc_write_coef_idx(codec, 0x11, 0x0001);
73bdd597
DH
3396 alc_write_coef_idx(codec, 0x15, 0x0d50);
3397 alc_write_coef_idx(codec, 0xc3, 0x0000);
3398 break;
3399 }
3400 snd_printdd("Headset jack set to Nokia-style headset mode.\n");
3401}
3402
3403static void alc_determine_headset_type(struct hda_codec *codec)
3404{
3405 int val;
3406 bool is_ctia = false;
3407 struct alc_spec *spec = codec->spec;
3408
3409 switch (codec->vendor_id) {
9a22a8f5
KY
3410 case 0x10ec0255:
3411 /* combo jack auto switch control(Check type)*/
3412 alc_write_coef_idx(codec, 0x45, 0xd089);
3413 /* combo jack auto switch control(Vref conteol) */
3414 alc_write_coef_idx(codec, 0x49, 0x0149);
3415 msleep(300);
3416 val = alc_read_coef_idx(codec, 0x46);
3417 is_ctia = (val & 0x0070) == 0x0070;
3418 break;
73bdd597
DH
3419 case 0x10ec0283:
3420 alc_write_coef_idx(codec, 0x45, 0xd029);
3421 msleep(300);
3422 val = alc_read_coef_idx(codec, 0x46);
3423 is_ctia = (val & 0x0070) == 0x0070;
3424 break;
3425 case 0x10ec0292:
3426 alc_write_coef_idx(codec, 0x6b, 0xd429);
3427 msleep(300);
3428 val = alc_read_coef_idx(codec, 0x6c);
3429 is_ctia = (val & 0x001c) == 0x001c;
3430 break;
3431 case 0x10ec0668:
3432 alc_write_coef_idx(codec, 0x11, 0x0001);
3433 alc_write_coef_idx(codec, 0xb7, 0x802b);
3434 alc_write_coef_idx(codec, 0x15, 0x0d60);
3435 alc_write_coef_idx(codec, 0xc3, 0x0c00);
3436 msleep(300);
3437 val = alc_read_coef_idx(codec, 0xbe);
3438 is_ctia = (val & 0x1c02) == 0x1c02;
3439 break;
3440 }
3441
3442 snd_printdd("Headset jack detected iPhone-style headset: %s\n",
3443 is_ctia ? "yes" : "no");
3444 spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP;
3445}
3446
3447static void alc_update_headset_mode(struct hda_codec *codec)
3448{
3449 struct alc_spec *spec = codec->spec;
3450
3451 hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
3452 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
3453
3454 int new_headset_mode;
3455
3456 if (!snd_hda_jack_detect(codec, hp_pin))
3457 new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED;
3458 else if (mux_pin == spec->headset_mic_pin)
3459 new_headset_mode = ALC_HEADSET_MODE_HEADSET;
3460 else if (mux_pin == spec->headphone_mic_pin)
3461 new_headset_mode = ALC_HEADSET_MODE_MIC;
3462 else
3463 new_headset_mode = ALC_HEADSET_MODE_HEADPHONE;
3464
5959a6bc
DH
3465 if (new_headset_mode == spec->current_headset_mode) {
3466 snd_hda_gen_update_outputs(codec);
73bdd597 3467 return;
5959a6bc 3468 }
73bdd597
DH
3469
3470 switch (new_headset_mode) {
3471 case ALC_HEADSET_MODE_UNPLUGGED:
3472 alc_headset_mode_unplugged(codec);
3473 spec->gen.hp_jack_present = false;
3474 break;
3475 case ALC_HEADSET_MODE_HEADSET:
3476 if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)
3477 alc_determine_headset_type(codec);
3478 if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)
3479 alc_headset_mode_ctia(codec);
3480 else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP)
3481 alc_headset_mode_omtp(codec);
3482 spec->gen.hp_jack_present = true;
3483 break;
3484 case ALC_HEADSET_MODE_MIC:
3485 alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin);
3486 spec->gen.hp_jack_present = false;
3487 break;
3488 case ALC_HEADSET_MODE_HEADPHONE:
3489 alc_headset_mode_default(codec);
3490 spec->gen.hp_jack_present = true;
3491 break;
3492 }
3493 if (new_headset_mode != ALC_HEADSET_MODE_MIC) {
3494 snd_hda_set_pin_ctl_cache(codec, hp_pin,
3495 AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
3496 if (spec->headphone_mic_pin)
3497 snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin,
3498 PIN_VREFHIZ);
3499 }
3500 spec->current_headset_mode = new_headset_mode;
3501
3502 snd_hda_gen_update_outputs(codec);
3503}
3504
3505static void alc_update_headset_mode_hook(struct hda_codec *codec,
3506 struct snd_ctl_elem_value *ucontrol)
3507{
3508 alc_update_headset_mode(codec);
3509}
3510
3511static void alc_update_headset_jack_cb(struct hda_codec *codec, struct hda_jack_tbl *jack)
3512{
3513 struct alc_spec *spec = codec->spec;
5db4d34b 3514 spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
73bdd597
DH
3515 snd_hda_gen_hp_automute(codec, jack);
3516}
3517
3518static void alc_probe_headset_mode(struct hda_codec *codec)
3519{
3520 int i;
3521 struct alc_spec *spec = codec->spec;
3522 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
3523
3524 /* Find mic pins */
3525 for (i = 0; i < cfg->num_inputs; i++) {
3526 if (cfg->inputs[i].is_headset_mic && !spec->headset_mic_pin)
3527 spec->headset_mic_pin = cfg->inputs[i].pin;
3528 if (cfg->inputs[i].is_headphone_mic && !spec->headphone_mic_pin)
3529 spec->headphone_mic_pin = cfg->inputs[i].pin;
3530 }
3531
3532 spec->gen.cap_sync_hook = alc_update_headset_mode_hook;
3533 spec->gen.automute_hook = alc_update_headset_mode;
3534 spec->gen.hp_automute_hook = alc_update_headset_jack_cb;
3535}
3536
3537static void alc_fixup_headset_mode(struct hda_codec *codec,
3538 const struct hda_fixup *fix, int action)
3539{
3540 struct alc_spec *spec = codec->spec;
3541
3542 switch (action) {
3543 case HDA_FIXUP_ACT_PRE_PROBE:
3544 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC | HDA_PINCFG_HEADPHONE_MIC;
3545 break;
3546 case HDA_FIXUP_ACT_PROBE:
3547 alc_probe_headset_mode(codec);
3548 break;
3549 case HDA_FIXUP_ACT_INIT:
3550 spec->current_headset_mode = 0;
3551 alc_update_headset_mode(codec);
3552 break;
3553 }
3554}
3555
3556static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
3557 const struct hda_fixup *fix, int action)
3558{
3559 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3560 struct alc_spec *spec = codec->spec;
3561 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
3562 }
3563 else
3564 alc_fixup_headset_mode(codec, fix, action);
3565}
3566
9a22a8f5
KY
3567static void alc_fixup_headset_mode_alc255(struct hda_codec *codec,
3568 const struct hda_fixup *fix, int action)
3569{
3570 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3571 /* Set to iphone type */
3572 alc_write_coef_idx(codec, 0x1b, 0x880b);
3573 alc_write_coef_idx(codec, 0x45, 0xd089);
3574 alc_write_coef_idx(codec, 0x1b, 0x080b);
3575 alc_write_coef_idx(codec, 0x46, 0x0004);
3576 alc_write_coef_idx(codec, 0x1b, 0x0c0b);
3577 msleep(30);
3578 }
3579 alc_fixup_headset_mode(codec, fix, action);
3580}
3581
73bdd597
DH
3582static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
3583 const struct hda_fixup *fix, int action)
3584{
3585 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3586 int val;
3587 alc_write_coef_idx(codec, 0xc4, 0x8000);
3588 val = alc_read_coef_idx(codec, 0xc2);
3589 alc_write_coef_idx(codec, 0xc2, val & 0xfe);
3590 snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
3591 }
3592 alc_fixup_headset_mode(codec, fix, action);
3593}
3594
bde7bc60
CCC
3595/* Returns the nid of the external mic input pin, or 0 if it cannot be found. */
3596static int find_ext_mic_pin(struct hda_codec *codec)
3597{
3598 struct alc_spec *spec = codec->spec;
3599 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
3600 hda_nid_t nid;
3601 unsigned int defcfg;
3602 int i;
3603
3604 for (i = 0; i < cfg->num_inputs; i++) {
3605 if (cfg->inputs[i].type != AUTO_PIN_MIC)
3606 continue;
3607 nid = cfg->inputs[i].pin;
3608 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3609 if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
3610 continue;
3611 return nid;
3612 }
3613
3614 return 0;
3615}
3616
08a978db 3617static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
1727a771 3618 const struct hda_fixup *fix,
08a978db
DR
3619 int action)
3620{
3621 struct alc_spec *spec = codec->spec;
3622
0db75790 3623 if (action == HDA_FIXUP_ACT_PROBE) {
bde7bc60
CCC
3624 int mic_pin = find_ext_mic_pin(codec);
3625 int hp_pin = spec->gen.autocfg.hp_pins[0];
3626
3627 if (snd_BUG_ON(!mic_pin || !hp_pin))
0db75790 3628 return;
bde7bc60 3629 snd_hda_jack_set_gating_jack(codec, mic_pin, hp_pin);
0db75790 3630 }
08a978db 3631}
693b613d 3632
3e0d611b
DH
3633static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec,
3634 const struct hda_fixup *fix,
3635 int action)
3636{
3637 struct alc_spec *spec = codec->spec;
3638 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
3639 int i;
3640
3641 /* The mic boosts on level 2 and 3 are too noisy
3642 on the internal mic input.
3643 Therefore limit the boost to 0 or 1. */
3644
3645 if (action != HDA_FIXUP_ACT_PROBE)
3646 return;
3647
3648 for (i = 0; i < cfg->num_inputs; i++) {
3649 hda_nid_t nid = cfg->inputs[i].pin;
3650 unsigned int defcfg;
3651 if (cfg->inputs[i].type != AUTO_PIN_MIC)
3652 continue;
3653 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3654 if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
3655 continue;
3656
3657 snd_hda_override_amp_caps(codec, nid, HDA_INPUT,
3658 (0x00 << AC_AMPCAP_OFFSET_SHIFT) |
3659 (0x01 << AC_AMPCAP_NUM_STEPS_SHIFT) |
3660 (0x2f << AC_AMPCAP_STEP_SIZE_SHIFT) |
3661 (0 << AC_AMPCAP_MUTE_SHIFT));
3662 }
3663}
3664
cd217a63
KY
3665static void alc283_hp_automute_hook(struct hda_codec *codec,
3666 struct hda_jack_tbl *jack)
3667{
3668 struct alc_spec *spec = codec->spec;
3669 int vref;
3670
3671 msleep(200);
3672 snd_hda_gen_hp_automute(codec, jack);
3673
3674 vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
3675
3676 msleep(600);
3677 snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3678 vref);
3679}
3680
cd217a63
KY
3681static void alc283_fixup_chromebook(struct hda_codec *codec,
3682 const struct hda_fixup *fix, int action)
3683{
3684 struct alc_spec *spec = codec->spec;
3685 int val;
3686
3687 switch (action) {
3688 case HDA_FIXUP_ACT_PRE_PROBE:
0202e99c 3689 snd_hda_override_wcaps(codec, 0x03, 0);
d2e92709
TI
3690 /* Disable AA-loopback as it causes white noise */
3691 spec->gen.mixer_nid = 0;
38070219 3692 break;
0202e99c
KY
3693 case HDA_FIXUP_ACT_INIT:
3694 /* Enable Line1 input control by verb */
3695 val = alc_read_coef_idx(codec, 0x1a);
3696 alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
3697 break;
3698 }
3699}
3700
3701static void alc283_fixup_sense_combo_jack(struct hda_codec *codec,
3702 const struct hda_fixup *fix, int action)
3703{
3704 struct alc_spec *spec = codec->spec;
3705 int val;
3706
3707 switch (action) {
3708 case HDA_FIXUP_ACT_PRE_PROBE:
cd217a63 3709 spec->gen.hp_automute_hook = alc283_hp_automute_hook;
38070219
KY
3710 break;
3711 case HDA_FIXUP_ACT_INIT:
cd217a63
KY
3712 /* MIC2-VREF control */
3713 /* Set to manual mode */
3714 val = alc_read_coef_idx(codec, 0x06);
3715 alc_write_coef_idx(codec, 0x06, val & ~0x000c);
3716 break;
3717 }
3718}
3719
7bba2157
TI
3720/* mute tablet speaker pin (0x14) via dock plugging in addition */
3721static void asus_tx300_automute(struct hda_codec *codec)
3722{
3723 struct alc_spec *spec = codec->spec;
3724 snd_hda_gen_update_outputs(codec);
3725 if (snd_hda_jack_detect(codec, 0x1b))
3726 spec->gen.mute_bits |= (1ULL << 0x14);
3727}
3728
3729static void alc282_fixup_asus_tx300(struct hda_codec *codec,
3730 const struct hda_fixup *fix, int action)
3731{
3732 struct alc_spec *spec = codec->spec;
3733 /* TX300 needs to set up GPIO2 for the speaker amp */
3734 static const struct hda_verb gpio2_verbs[] = {
3735 { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 },
3736 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 },
3737 { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 },
3738 {}
3739 };
3740 static const struct hda_pintbl dock_pins[] = {
3741 { 0x1b, 0x21114000 }, /* dock speaker pin */
3742 {}
3743 };
3744 struct snd_kcontrol *kctl;
3745
3746 switch (action) {
3747 case HDA_FIXUP_ACT_PRE_PROBE:
3748 snd_hda_add_verbs(codec, gpio2_verbs);
3749 snd_hda_apply_pincfgs(codec, dock_pins);
3750 spec->gen.auto_mute_via_amp = 1;
3751 spec->gen.automute_hook = asus_tx300_automute;
3752 snd_hda_jack_detect_enable_callback(codec, 0x1b,
3753 HDA_GEN_HP_EVENT,
3754 snd_hda_gen_hp_automute);
3755 break;
3756 case HDA_FIXUP_ACT_BUILD:
3757 /* this is a bit tricky; give more sane names for the main
3758 * (tablet) speaker and the dock speaker, respectively
3759 */
3760 kctl = snd_hda_find_mixer_ctl(codec, "Speaker Playback Switch");
3761 if (kctl)
3762 strcpy(kctl->id.name, "Dock Speaker Playback Switch");
3763 kctl = snd_hda_find_mixer_ctl(codec, "Bass Speaker Playback Switch");
3764 if (kctl)
3765 strcpy(kctl->id.name, "Speaker Playback Switch");
3766 break;
3767 }
3768}
3769
338cae56
DH
3770static void alc290_fixup_mono_speakers(struct hda_codec *codec,
3771 const struct hda_fixup *fix, int action)
3772{
0f4881dc
DH
3773 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3774 /* DAC node 0x03 is giving mono output. We therefore want to
3775 make sure 0x14 (front speaker) and 0x15 (headphones) use the
3776 stereo DAC, while leaving 0x17 (bass speaker) for node 0x03. */
3777 hda_nid_t conn1[2] = { 0x0c };
3778 snd_hda_override_conn_list(codec, 0x14, 1, conn1);
3779 snd_hda_override_conn_list(codec, 0x15, 1, conn1);
3780 }
338cae56
DH
3781}
3782
b67ae3f1
DH
3783#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
3784
3785#include <linux/thinkpad_acpi.h>
d171ebc5 3786#include <linux/acpi.h>
b67ae3f1
DH
3787
3788static int (*led_set_func)(int, bool);
3789
2793769f
DH
3790static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
3791 void **rv)
3792{
3793 bool *found = context;
3794 *found = true;
3795 return AE_OK;
3796}
3797
3798static bool is_thinkpad(struct hda_codec *codec)
3799{
3800 bool found = false;
3801 if (codec->subsystem_id >> 16 != 0x17aa)
3802 return false;
3803 if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
3804 return true;
3805 found = false;
3806 return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found;
3807}
3808
b67ae3f1
DH
3809static void update_tpacpi_mute_led(void *private_data, int enabled)
3810{
3811 if (led_set_func)
3812 led_set_func(TPACPI_LED_MUTE, !enabled);
3813}
3814
3815static void update_tpacpi_micmute_led(struct hda_codec *codec,
3816 struct snd_ctl_elem_value *ucontrol)
3817{
3818 if (!ucontrol || !led_set_func)
3819 return;
3820 if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
3821 /* TODO: How do I verify if it's a mono or stereo here? */
3822 bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
3823 led_set_func(TPACPI_LED_MICMUTE, !val);
3824 }
3825}
3826
3827static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
3828 const struct hda_fixup *fix, int action)
3829{
3830 struct alc_spec *spec = codec->spec;
3831 bool removefunc = false;
3832
3833 if (action == HDA_FIXUP_ACT_PROBE) {
2793769f
DH
3834 if (!is_thinkpad(codec))
3835 return;
b67ae3f1
DH
3836 if (!led_set_func)
3837 led_set_func = symbol_request(tpacpi_led_set);
3838 if (!led_set_func) {
3839 snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
3840 return;
3841 }
3842
3843 removefunc = true;
3844 if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
3845 spec->gen.vmaster_mute.hook = update_tpacpi_mute_led;
3846 removefunc = false;
3847 }
3848 if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
3849 if (spec->gen.num_adc_nids > 1)
3850 snd_printdd("Skipping micmute LED control due to several ADCs");
3851 else {
3852 spec->gen.cap_sync_hook = update_tpacpi_micmute_led;
3853 removefunc = false;
3854 }
3855 }
3856 }
3857
3858 if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
3859 symbol_put(tpacpi_led_set);
3860 led_set_func = NULL;
3861 }
3862}
3863
3864#else
3865
3866static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
3867 const struct hda_fixup *fix, int action)
3868{
3869}
3870
3871#endif
3872
1d045db9
TI
3873enum {
3874 ALC269_FIXUP_SONY_VAIO,
3875 ALC275_FIXUP_SONY_VAIO_GPIO2,
3876 ALC269_FIXUP_DELL_M101Z,
3877 ALC269_FIXUP_SKU_IGNORE,
3878 ALC269_FIXUP_ASUS_G73JW,
3879 ALC269_FIXUP_LENOVO_EAPD,
3880 ALC275_FIXUP_SONY_HWEQ,
3881 ALC271_FIXUP_DMIC,
017f2a10 3882 ALC269_FIXUP_PCM_44K,
adabb3ec 3883 ALC269_FIXUP_STEREO_DMIC,
7c478f03 3884 ALC269_FIXUP_HEADSET_MIC,
24519911
TI
3885 ALC269_FIXUP_QUANTA_MUTE,
3886 ALC269_FIXUP_LIFEBOOK,
a4297b5d
TI
3887 ALC269_FIXUP_AMIC,
3888 ALC269_FIXUP_DMIC,
3889 ALC269VB_FIXUP_AMIC,
3890 ALC269VB_FIXUP_DMIC,
08fb0d0e 3891 ALC269_FIXUP_HP_MUTE_LED,
d06ac143 3892 ALC269_FIXUP_HP_MUTE_LED_MIC1,
08fb0d0e 3893 ALC269_FIXUP_HP_MUTE_LED_MIC2,
9f5c6faf 3894 ALC269_FIXUP_HP_GPIO_LED,
693b613d 3895 ALC269_FIXUP_INV_DMIC,
108cc108 3896 ALC269_FIXUP_LENOVO_DOCK,
88cfcf86 3897 ALC286_FIXUP_SONY_MIC_NO_PRESENCE,
108cc108 3898 ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
73bdd597
DH
3899 ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
3900 ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
338cae56 3901 ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
73bdd597
DH
3902 ALC269_FIXUP_HEADSET_MODE,
3903 ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC,
d240d1dc
DH
3904 ALC269_FIXUP_ASUS_X101_FUNC,
3905 ALC269_FIXUP_ASUS_X101_VERB,
3906 ALC269_FIXUP_ASUS_X101,
08a978db
DR
3907 ALC271_FIXUP_AMIC_MIC2,
3908 ALC271_FIXUP_HP_GATE_MIC_JACK,
b1e8972e 3909 ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572,
42397004 3910 ALC269_FIXUP_ACER_AC700,
3e0d611b 3911 ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
2cede303 3912 ALC269VB_FIXUP_ASUS_ZENBOOK,
8e35cd4a 3913 ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED,
02b504d9 3914 ALC269VB_FIXUP_ORDISSIMO_EVE2,
cd217a63 3915 ALC283_FIXUP_CHROME_BOOK,
0202e99c 3916 ALC283_FIXUP_SENSE_COMBO_JACK,
7bba2157 3917 ALC282_FIXUP_ASUS_TX300,
1bb3e062 3918 ALC283_FIXUP_INT_MIC,
338cae56 3919 ALC290_FIXUP_MONO_SPEAKERS,
0f4881dc
DH
3920 ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
3921 ALC290_FIXUP_SUBWOOFER,
3922 ALC290_FIXUP_SUBWOOFER_HSJACK,
b67ae3f1 3923 ALC269_FIXUP_THINKPAD_ACPI,
9a22a8f5
KY
3924 ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
3925 ALC255_FIXUP_HEADSET_MODE,
f1d4e28b
KY
3926};
3927
1727a771 3928static const struct hda_fixup alc269_fixups[] = {
1d045db9 3929 [ALC269_FIXUP_SONY_VAIO] = {
fd108215
TI
3930 .type = HDA_FIXUP_PINCTLS,
3931 .v.pins = (const struct hda_pintbl[]) {
3932 {0x19, PIN_VREFGRD},
1d045db9
TI
3933 {}
3934 }
f1d4e28b 3935 },
1d045db9 3936 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
1727a771 3937 .type = HDA_FIXUP_VERBS,
1d045db9
TI
3938 .v.verbs = (const struct hda_verb[]) {
3939 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
3940 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
3941 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
3942 { }
3943 },
3944 .chained = true,
3945 .chain_id = ALC269_FIXUP_SONY_VAIO
3946 },
3947 [ALC269_FIXUP_DELL_M101Z] = {
1727a771 3948 .type = HDA_FIXUP_VERBS,
1d045db9
TI
3949 .v.verbs = (const struct hda_verb[]) {
3950 /* Enables internal speaker */
3951 {0x20, AC_VERB_SET_COEF_INDEX, 13},
3952 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
3953 {}
3954 }
3955 },
3956 [ALC269_FIXUP_SKU_IGNORE] = {
1727a771 3957 .type = HDA_FIXUP_FUNC,
23d30f28 3958 .v.func = alc_fixup_sku_ignore,
1d045db9
TI
3959 },
3960 [ALC269_FIXUP_ASUS_G73JW] = {
1727a771
TI
3961 .type = HDA_FIXUP_PINS,
3962 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
3963 { 0x17, 0x99130111 }, /* subwoofer */
3964 { }
3965 }
3966 },
3967 [ALC269_FIXUP_LENOVO_EAPD] = {
1727a771 3968 .type = HDA_FIXUP_VERBS,
1d045db9
TI
3969 .v.verbs = (const struct hda_verb[]) {
3970 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
3971 {}
3972 }
3973 },
3974 [ALC275_FIXUP_SONY_HWEQ] = {
1727a771 3975 .type = HDA_FIXUP_FUNC,
1d045db9
TI
3976 .v.func = alc269_fixup_hweq,
3977 .chained = true,
3978 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
3979 },
3980 [ALC271_FIXUP_DMIC] = {
1727a771 3981 .type = HDA_FIXUP_FUNC,
1d045db9 3982 .v.func = alc271_fixup_dmic,
f1d4e28b 3983 },
017f2a10 3984 [ALC269_FIXUP_PCM_44K] = {
1727a771 3985 .type = HDA_FIXUP_FUNC,
017f2a10 3986 .v.func = alc269_fixup_pcm_44k,
012e7eb1
DH
3987 .chained = true,
3988 .chain_id = ALC269_FIXUP_QUANTA_MUTE
017f2a10 3989 },
adabb3ec 3990 [ALC269_FIXUP_STEREO_DMIC] = {
1727a771 3991 .type = HDA_FIXUP_FUNC,
adabb3ec
TI
3992 .v.func = alc269_fixup_stereo_dmic,
3993 },
7c478f03
DH
3994 [ALC269_FIXUP_HEADSET_MIC] = {
3995 .type = HDA_FIXUP_FUNC,
3996 .v.func = alc269_fixup_headset_mic,
3997 },
24519911 3998 [ALC269_FIXUP_QUANTA_MUTE] = {
1727a771 3999 .type = HDA_FIXUP_FUNC,
24519911
TI
4000 .v.func = alc269_fixup_quanta_mute,
4001 },
4002 [ALC269_FIXUP_LIFEBOOK] = {
1727a771
TI
4003 .type = HDA_FIXUP_PINS,
4004 .v.pins = (const struct hda_pintbl[]) {
24519911
TI
4005 { 0x1a, 0x2101103f }, /* dock line-out */
4006 { 0x1b, 0x23a11040 }, /* dock mic-in */
4007 { }
4008 },
4009 .chained = true,
4010 .chain_id = ALC269_FIXUP_QUANTA_MUTE
4011 },
a4297b5d 4012 [ALC269_FIXUP_AMIC] = {
1727a771
TI
4013 .type = HDA_FIXUP_PINS,
4014 .v.pins = (const struct hda_pintbl[]) {
a4297b5d
TI
4015 { 0x14, 0x99130110 }, /* speaker */
4016 { 0x15, 0x0121401f }, /* HP out */
4017 { 0x18, 0x01a19c20 }, /* mic */
4018 { 0x19, 0x99a3092f }, /* int-mic */
4019 { }
4020 },
4021 },
4022 [ALC269_FIXUP_DMIC] = {
1727a771
TI
4023 .type = HDA_FIXUP_PINS,
4024 .v.pins = (const struct hda_pintbl[]) {
a4297b5d
TI
4025 { 0x12, 0x99a3092f }, /* int-mic */
4026 { 0x14, 0x99130110 }, /* speaker */
4027 { 0x15, 0x0121401f }, /* HP out */
4028 { 0x18, 0x01a19c20 }, /* mic */
4029 { }
4030 },
4031 },
4032 [ALC269VB_FIXUP_AMIC] = {
1727a771
TI
4033 .type = HDA_FIXUP_PINS,
4034 .v.pins = (const struct hda_pintbl[]) {
a4297b5d
TI
4035 { 0x14, 0x99130110 }, /* speaker */
4036 { 0x18, 0x01a19c20 }, /* mic */
4037 { 0x19, 0x99a3092f }, /* int-mic */
4038 { 0x21, 0x0121401f }, /* HP out */
4039 { }
4040 },
4041 },
2267ea97 4042 [ALC269VB_FIXUP_DMIC] = {
1727a771
TI
4043 .type = HDA_FIXUP_PINS,
4044 .v.pins = (const struct hda_pintbl[]) {
a4297b5d
TI
4045 { 0x12, 0x99a3092f }, /* int-mic */
4046 { 0x14, 0x99130110 }, /* speaker */
4047 { 0x18, 0x01a19c20 }, /* mic */
4048 { 0x21, 0x0121401f }, /* HP out */
4049 { }
4050 },
4051 },
08fb0d0e 4052 [ALC269_FIXUP_HP_MUTE_LED] = {
1727a771 4053 .type = HDA_FIXUP_FUNC,
08fb0d0e 4054 .v.func = alc269_fixup_hp_mute_led,
6d3cd5d4 4055 },
d06ac143
DH
4056 [ALC269_FIXUP_HP_MUTE_LED_MIC1] = {
4057 .type = HDA_FIXUP_FUNC,
4058 .v.func = alc269_fixup_hp_mute_led_mic1,
4059 },
08fb0d0e 4060 [ALC269_FIXUP_HP_MUTE_LED_MIC2] = {
1727a771 4061 .type = HDA_FIXUP_FUNC,
08fb0d0e 4062 .v.func = alc269_fixup_hp_mute_led_mic2,
420b0feb 4063 },
9f5c6faf
TI
4064 [ALC269_FIXUP_HP_GPIO_LED] = {
4065 .type = HDA_FIXUP_FUNC,
4066 .v.func = alc269_fixup_hp_gpio_led,
4067 },
693b613d 4068 [ALC269_FIXUP_INV_DMIC] = {
1727a771 4069 .type = HDA_FIXUP_FUNC,
6e72aa5f 4070 .v.func = alc_fixup_inv_dmic_0x12,
693b613d 4071 },
108cc108 4072 [ALC269_FIXUP_LENOVO_DOCK] = {
1727a771
TI
4073 .type = HDA_FIXUP_PINS,
4074 .v.pins = (const struct hda_pintbl[]) {
108cc108
DH
4075 { 0x19, 0x23a11040 }, /* dock mic */
4076 { 0x1b, 0x2121103f }, /* dock headphone */
4077 { }
4078 },
4079 .chained = true,
4080 .chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT
4081 },
4082 [ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT] = {
1727a771 4083 .type = HDA_FIXUP_FUNC,
108cc108 4084 .v.func = alc269_fixup_pincfg_no_hp_to_lineout,
52129000
DH
4085 .chained = true,
4086 .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
108cc108 4087 },
73bdd597
DH
4088 [ALC269_FIXUP_DELL1_MIC_NO_PRESENCE] = {
4089 .type = HDA_FIXUP_PINS,
4090 .v.pins = (const struct hda_pintbl[]) {
4091 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4092 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
4093 { }
4094 },
4095 .chained = true,
4096 .chain_id = ALC269_FIXUP_HEADSET_MODE
4097 },
4098 [ALC269_FIXUP_DELL2_MIC_NO_PRESENCE] = {
4099 .type = HDA_FIXUP_PINS,
4100 .v.pins = (const struct hda_pintbl[]) {
4101 { 0x16, 0x21014020 }, /* dock line out */
4102 { 0x19, 0x21a19030 }, /* dock mic */
4103 { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4104 { }
4105 },
4106 .chained = true,
4107 .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
4108 },
338cae56
DH
4109 [ALC269_FIXUP_DELL3_MIC_NO_PRESENCE] = {
4110 .type = HDA_FIXUP_PINS,
4111 .v.pins = (const struct hda_pintbl[]) {
4112 { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4113 { }
4114 },
4115 .chained = true,
4116 .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
4117 },
73bdd597
DH
4118 [ALC269_FIXUP_HEADSET_MODE] = {
4119 .type = HDA_FIXUP_FUNC,
4120 .v.func = alc_fixup_headset_mode,
4121 },
4122 [ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
4123 .type = HDA_FIXUP_FUNC,
4124 .v.func = alc_fixup_headset_mode_no_hp_mic,
4125 },
88cfcf86
DH
4126 [ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = {
4127 .type = HDA_FIXUP_PINS,
4128 .v.pins = (const struct hda_pintbl[]) {
4129 { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4130 { }
4131 },
fbc78ad6
DH
4132 .chained = true,
4133 .chain_id = ALC269_FIXUP_HEADSET_MIC
88cfcf86 4134 },
d240d1dc
DH
4135 [ALC269_FIXUP_ASUS_X101_FUNC] = {
4136 .type = HDA_FIXUP_FUNC,
4137 .v.func = alc269_fixup_x101_headset_mic,
4138 },
4139 [ALC269_FIXUP_ASUS_X101_VERB] = {
4140 .type = HDA_FIXUP_VERBS,
4141 .v.verbs = (const struct hda_verb[]) {
4142 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4143 {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
4144 {0x20, AC_VERB_SET_PROC_COEF, 0x0310},
4145 { }
4146 },
4147 .chained = true,
4148 .chain_id = ALC269_FIXUP_ASUS_X101_FUNC
4149 },
4150 [ALC269_FIXUP_ASUS_X101] = {
4151 .type = HDA_FIXUP_PINS,
4152 .v.pins = (const struct hda_pintbl[]) {
4153 { 0x18, 0x04a1182c }, /* Headset mic */
4154 { }
4155 },
4156 .chained = true,
4157 .chain_id = ALC269_FIXUP_ASUS_X101_VERB
4158 },
08a978db 4159 [ALC271_FIXUP_AMIC_MIC2] = {
1727a771
TI
4160 .type = HDA_FIXUP_PINS,
4161 .v.pins = (const struct hda_pintbl[]) {
08a978db
DR
4162 { 0x14, 0x99130110 }, /* speaker */
4163 { 0x19, 0x01a19c20 }, /* mic */
4164 { 0x1b, 0x99a7012f }, /* int-mic */
4165 { 0x21, 0x0121401f }, /* HP out */
4166 { }
4167 },
4168 },
4169 [ALC271_FIXUP_HP_GATE_MIC_JACK] = {
1727a771 4170 .type = HDA_FIXUP_FUNC,
08a978db
DR
4171 .v.func = alc271_hp_gate_mic_jack,
4172 .chained = true,
4173 .chain_id = ALC271_FIXUP_AMIC_MIC2,
4174 },
b1e8972e
OR
4175 [ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572] = {
4176 .type = HDA_FIXUP_FUNC,
4177 .v.func = alc269_fixup_limit_int_mic_boost,
4178 .chained = true,
4179 .chain_id = ALC271_FIXUP_HP_GATE_MIC_JACK,
4180 },
42397004
DR
4181 [ALC269_FIXUP_ACER_AC700] = {
4182 .type = HDA_FIXUP_PINS,
4183 .v.pins = (const struct hda_pintbl[]) {
4184 { 0x12, 0x99a3092f }, /* int-mic */
4185 { 0x14, 0x99130110 }, /* speaker */
4186 { 0x18, 0x03a11c20 }, /* mic */
4187 { 0x1e, 0x0346101e }, /* SPDIF1 */
4188 { 0x21, 0x0321101f }, /* HP out */
4189 { }
4190 },
4191 .chained = true,
4192 .chain_id = ALC271_FIXUP_DMIC,
4193 },
3e0d611b
DH
4194 [ALC269_FIXUP_LIMIT_INT_MIC_BOOST] = {
4195 .type = HDA_FIXUP_FUNC,
4196 .v.func = alc269_fixup_limit_int_mic_boost,
2793769f
DH
4197 .chained = true,
4198 .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
3e0d611b 4199 },
2cede303
OR
4200 [ALC269VB_FIXUP_ASUS_ZENBOOK] = {
4201 .type = HDA_FIXUP_FUNC,
4202 .v.func = alc269_fixup_limit_int_mic_boost,
4203 .chained = true,
4204 .chain_id = ALC269VB_FIXUP_DMIC,
4205 },
8e35cd4a
DH
4206 [ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED] = {
4207 .type = HDA_FIXUP_FUNC,
4208 .v.func = alc269_fixup_limit_int_mic_boost,
4209 .chained = true,
4210 .chain_id = ALC269_FIXUP_HP_MUTE_LED_MIC1,
4211 },
02b504d9
AA
4212 [ALC269VB_FIXUP_ORDISSIMO_EVE2] = {
4213 .type = HDA_FIXUP_PINS,
4214 .v.pins = (const struct hda_pintbl[]) {
4215 { 0x12, 0x99a3092f }, /* int-mic */
4216 { 0x18, 0x03a11d20 }, /* mic */
4217 { 0x19, 0x411111f0 }, /* Unused bogus pin */
4218 { }
4219 },
4220 },
cd217a63
KY
4221 [ALC283_FIXUP_CHROME_BOOK] = {
4222 .type = HDA_FIXUP_FUNC,
4223 .v.func = alc283_fixup_chromebook,
4224 },
0202e99c
KY
4225 [ALC283_FIXUP_SENSE_COMBO_JACK] = {
4226 .type = HDA_FIXUP_FUNC,
4227 .v.func = alc283_fixup_sense_combo_jack,
4228 .chained = true,
4229 .chain_id = ALC283_FIXUP_CHROME_BOOK,
4230 },
7bba2157
TI
4231 [ALC282_FIXUP_ASUS_TX300] = {
4232 .type = HDA_FIXUP_FUNC,
4233 .v.func = alc282_fixup_asus_tx300,
4234 },
1bb3e062
KY
4235 [ALC283_FIXUP_INT_MIC] = {
4236 .type = HDA_FIXUP_VERBS,
4237 .v.verbs = (const struct hda_verb[]) {
4238 {0x20, AC_VERB_SET_COEF_INDEX, 0x1a},
4239 {0x20, AC_VERB_SET_PROC_COEF, 0x0011},
4240 { }
4241 },
4242 .chained = true,
4243 .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
4244 },
0f4881dc
DH
4245 [ALC290_FIXUP_SUBWOOFER_HSJACK] = {
4246 .type = HDA_FIXUP_PINS,
4247 .v.pins = (const struct hda_pintbl[]) {
4248 { 0x17, 0x90170112 }, /* subwoofer */
4249 { }
4250 },
4251 .chained = true,
4252 .chain_id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
4253 },
4254 [ALC290_FIXUP_SUBWOOFER] = {
4255 .type = HDA_FIXUP_PINS,
4256 .v.pins = (const struct hda_pintbl[]) {
4257 { 0x17, 0x90170112 }, /* subwoofer */
4258 { }
4259 },
4260 .chained = true,
4261 .chain_id = ALC290_FIXUP_MONO_SPEAKERS,
4262 },
338cae56
DH
4263 [ALC290_FIXUP_MONO_SPEAKERS] = {
4264 .type = HDA_FIXUP_FUNC,
4265 .v.func = alc290_fixup_mono_speakers,
0f4881dc
DH
4266 },
4267 [ALC290_FIXUP_MONO_SPEAKERS_HSJACK] = {
4268 .type = HDA_FIXUP_FUNC,
4269 .v.func = alc290_fixup_mono_speakers,
338cae56
DH
4270 .chained = true,
4271 .chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
4272 },
b67ae3f1
DH
4273 [ALC269_FIXUP_THINKPAD_ACPI] = {
4274 .type = HDA_FIXUP_FUNC,
4275 .v.func = alc_fixup_thinkpad_acpi,
b67ae3f1 4276 },
9a22a8f5
KY
4277 [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
4278 .type = HDA_FIXUP_PINS,
4279 .v.pins = (const struct hda_pintbl[]) {
4280 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4281 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
4282 { }
4283 },
4284 .chained = true,
4285 .chain_id = ALC255_FIXUP_HEADSET_MODE
4286 },
4287 [ALC255_FIXUP_HEADSET_MODE] = {
4288 .type = HDA_FIXUP_FUNC,
4289 .v.func = alc_fixup_headset_mode_alc255,
4290 },
f1d4e28b
KY
4291};
4292
1d045db9 4293static const struct snd_pci_quirk alc269_fixup_tbl[] = {
693b613d
DH
4294 SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
4295 SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
aaedfb47
DH
4296 SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
4297 SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
4298 SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
4299 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
b1e8972e 4300 SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
aaedfb47 4301 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
73bdd597
DH
4302 SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4303 SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4304 SND_PCI_QUIRK(0x1028, 0x05c4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4305 SND_PCI_QUIRK(0x1028, 0x05c5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4306 SND_PCI_QUIRK(0x1028, 0x05c6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4307 SND_PCI_QUIRK(0x1028, 0x05c7, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4308 SND_PCI_QUIRK(0x1028, 0x05c8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4309 SND_PCI_QUIRK(0x1028, 0x05c9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4310 SND_PCI_QUIRK(0x1028, 0x05ca, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4311 SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
05843c07
KY
4312 SND_PCI_QUIRK(0x1028, 0x05cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4313 SND_PCI_QUIRK(0x1028, 0x05cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
0f4881dc 4314 SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
436c4a0c 4315 SND_PCI_QUIRK(0x1028, 0x05de, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
d81bf8cf 4316 SND_PCI_QUIRK(0x1028, 0x05e0, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
73bdd597
DH
4317 SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4318 SND_PCI_QUIRK(0x1028, 0x05ea, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4319 SND_PCI_QUIRK(0x1028, 0x05eb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4320 SND_PCI_QUIRK(0x1028, 0x05ec, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4321 SND_PCI_QUIRK(0x1028, 0x05ed, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4322 SND_PCI_QUIRK(0x1028, 0x05ee, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4323 SND_PCI_QUIRK(0x1028, 0x05f3, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4324 SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4325 SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4326 SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
3ee2102f 4327 SND_PCI_QUIRK(0x1028, 0x05f8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
cd6fb679
DH
4328 SND_PCI_QUIRK(0x1028, 0x05f9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4329 SND_PCI_QUIRK(0x1028, 0x05fb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
d81bf8cf
DH
4330 SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4331 SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
3ee2102f 4332 SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
c29cb5eb 4333 SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
6c29d68a 4334 SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
b8362e70 4335 SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
0f4881dc
DH
4336 SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
4337 SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
9a22a8f5 4338 SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
c29cb5eb 4339 SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
0f4881dc 4340 SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
c29cb5eb 4341 SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
9a22a8f5 4342 SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
3a6c5d8a 4343 SND_PCI_QUIRK(0x1028, 0x0640, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
05843c07
KY
4344 SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4345 SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
08fb0d0e 4346 SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
9f5c6faf 4347 SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
d06ac143
DH
4348 SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4349 SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
8e35cd4a 4350 SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
08fb0d0e 4351 SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
7bba2157 4352 SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
3e0d611b
DH
4353 SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
4354 SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
2cede303
OR
4355 SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
4356 SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK),
3e0d611b 4357 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
017f2a10 4358 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
693b613d 4359 SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
3e0d611b 4360 SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
adabb3ec
TI
4361 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4362 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4363 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4364 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
d240d1dc 4365 SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
88cfcf86 4366 SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
1d045db9
TI
4367 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4368 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4369 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4370 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
24519911 4371 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
1d045db9
TI
4372 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4373 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4374 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4375 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4376 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
707fba3f 4377 SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),
c8415a48 4378 SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
84f98fdf 4379 SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
4407be6b 4380 SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
108cc108 4381 SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
aaedfb47 4382 SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
cd5302c0
DH
4383 SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
4384 SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
2793769f 4385 SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
a4a9e082
DH
4386 SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
4387 SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
1bb3e062 4388 SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
cd5302c0
DH
4389 SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
4390 SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
012e7eb1 4391 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
1d045db9 4392 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
2793769f 4393 SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
02b504d9 4394 SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
a4297b5d 4395
a7f3eedc 4396#if 0
a4297b5d
TI
4397 /* Below is a quirk table taken from the old code.
4398 * Basically the device should work as is without the fixup table.
4399 * If BIOS doesn't give a proper info, enable the corresponding
4400 * fixup entry.
7d7eb9ea 4401 */
a4297b5d
TI
4402 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
4403 ALC269_FIXUP_AMIC),
4404 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
a4297b5d
TI
4405 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
4406 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
4407 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
4408 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269_FIXUP_AMIC),
4409 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269_FIXUP_AMIC),
4410 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269_FIXUP_AMIC),
4411 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_FIXUP_AMIC),
4412 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269_FIXUP_AMIC),
4413 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_FIXUP_AMIC),
4414 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_FIXUP_AMIC),
4415 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_FIXUP_AMIC),
4416 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_FIXUP_AMIC),
4417 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_FIXUP_AMIC),
4418 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_FIXUP_AMIC),
4419 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_FIXUP_AMIC),
4420 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_FIXUP_AMIC),
4421 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_FIXUP_AMIC),
4422 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_FIXUP_AMIC),
4423 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_FIXUP_AMIC),
4424 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_FIXUP_AMIC),
4425 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_FIXUP_AMIC),
4426 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_FIXUP_AMIC),
4427 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_FIXUP_AMIC),
4428 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_FIXUP_AMIC),
4429 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_FIXUP_AMIC),
4430 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_FIXUP_AMIC),
4431 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_FIXUP_AMIC),
4432 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_FIXUP_AMIC),
4433 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_FIXUP_AMIC),
4434 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_FIXUP_AMIC),
4435 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_FIXUP_AMIC),
4436 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_FIXUP_AMIC),
4437 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_FIXUP_AMIC),
4438 SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_FIXUP_DMIC),
4439 SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_FIXUP_AMIC),
4440 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_AMIC),
4441 SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_FIXUP_DMIC),
4442 SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_FIXUP_DMIC),
4443#endif
4444 {}
4445};
4446
1727a771 4447static const struct hda_model_fixup alc269_fixup_models[] = {
a4297b5d
TI
4448 {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
4449 {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
6e72aa5f
TI
4450 {.id = ALC269_FIXUP_STEREO_DMIC, .name = "alc269-dmic"},
4451 {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"},
4452 {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"},
7c478f03 4453 {.id = ALC269_FIXUP_HEADSET_MIC, .name = "headset-mic"},
108cc108 4454 {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"},
9f5c6faf 4455 {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
e32aa85a
DH
4456 {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
4457 {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
0202e99c
KY
4458 {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-chrome"},
4459 {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
1d045db9 4460 {}
6dda9f4a
KY
4461};
4462
6dda9f4a 4463
546bb678 4464static void alc269_fill_coef(struct hda_codec *codec)
1d045db9 4465{
526af6eb 4466 struct alc_spec *spec = codec->spec;
1d045db9 4467 int val;
ebb83eeb 4468
526af6eb 4469 if (spec->codec_variant != ALC269_TYPE_ALC269VB)
546bb678 4470 return;
526af6eb 4471
1bb7e43e 4472 if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
1d045db9
TI
4473 alc_write_coef_idx(codec, 0xf, 0x960b);
4474 alc_write_coef_idx(codec, 0xe, 0x8817);
4475 }
ebb83eeb 4476
1bb7e43e 4477 if ((alc_get_coef0(codec) & 0x00ff) == 0x016) {
1d045db9
TI
4478 alc_write_coef_idx(codec, 0xf, 0x960b);
4479 alc_write_coef_idx(codec, 0xe, 0x8814);
4480 }
ebb83eeb 4481
1bb7e43e 4482 if ((alc_get_coef0(codec) & 0x00ff) == 0x017) {
1d045db9
TI
4483 val = alc_read_coef_idx(codec, 0x04);
4484 /* Power up output pin */
4485 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4486 }
ebb83eeb 4487
1bb7e43e 4488 if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
1d045db9
TI
4489 val = alc_read_coef_idx(codec, 0xd);
4490 if ((val & 0x0c00) >> 10 != 0x1) {
4491 /* Capless ramp up clock control */
4492 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4493 }
4494 val = alc_read_coef_idx(codec, 0x17);
4495 if ((val & 0x01c0) >> 6 != 0x4) {
4496 /* Class D power on reset */
4497 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4498 }
4499 }
ebb83eeb 4500
1d045db9
TI
4501 val = alc_read_coef_idx(codec, 0xd); /* Class D */
4502 alc_write_coef_idx(codec, 0xd, val | (1<<14));
bc9f98a9 4503
1d045db9
TI
4504 val = alc_read_coef_idx(codec, 0x4); /* HP */
4505 alc_write_coef_idx(codec, 0x4, val | (1<<11));
1d045db9 4506}
a7f2371f 4507
1d045db9
TI
4508/*
4509 */
1d045db9
TI
4510static int patch_alc269(struct hda_codec *codec)
4511{
4512 struct alc_spec *spec;
3de95173 4513 int err;
f1d4e28b 4514
3de95173 4515 err = alc_alloc_spec(codec, 0x0b);
e16fb6d1 4516 if (err < 0)
3de95173
TI
4517 return err;
4518
4519 spec = codec->spec;
08c189f2 4520 spec->gen.shared_mic_vref_pin = 0x18;
e16fb6d1 4521
1727a771 4522 snd_hda_pick_fixup(codec, alc269_fixup_models,
9f720bb9 4523 alc269_fixup_tbl, alc269_fixups);
1727a771 4524 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
9f720bb9
HRK
4525
4526 alc_auto_parse_customize_define(codec);
4527
7504b6cd
TI
4528 if (has_cdefine_beep(codec))
4529 spec->gen.beep_nid = 0x01;
4530
065380f0
KY
4531 switch (codec->vendor_id) {
4532 case 0x10ec0269:
1d045db9 4533 spec->codec_variant = ALC269_TYPE_ALC269VA;
1bb7e43e
TI
4534 switch (alc_get_coef0(codec) & 0x00f0) {
4535 case 0x0010:
1d045db9 4536 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
e16fb6d1 4537 spec->cdefine.platform_type == 1)
20ca0c35 4538 err = alc_codec_rename(codec, "ALC271X");
1d045db9 4539 spec->codec_variant = ALC269_TYPE_ALC269VB;
1bb7e43e
TI
4540 break;
4541 case 0x0020:
e16fb6d1
TI
4542 if (codec->bus->pci->subsystem_vendor == 0x17aa &&
4543 codec->bus->pci->subsystem_device == 0x21f3)
20ca0c35 4544 err = alc_codec_rename(codec, "ALC3202");
1d045db9 4545 spec->codec_variant = ALC269_TYPE_ALC269VC;
1bb7e43e 4546 break;
adcc70b2
KY
4547 case 0x0030:
4548 spec->codec_variant = ALC269_TYPE_ALC269VD;
4549 break;
1bb7e43e 4550 default:
1d045db9 4551 alc_fix_pll_init(codec, 0x20, 0x04, 15);
1bb7e43e 4552 }
e16fb6d1
TI
4553 if (err < 0)
4554 goto error;
546bb678 4555 spec->init_hook = alc269_fill_coef;
1d045db9 4556 alc269_fill_coef(codec);
065380f0
KY
4557 break;
4558
4559 case 0x10ec0280:
4560 case 0x10ec0290:
4561 spec->codec_variant = ALC269_TYPE_ALC280;
4562 break;
4563 case 0x10ec0282:
065380f0
KY
4564 spec->codec_variant = ALC269_TYPE_ALC282;
4565 break;
2af02be7
KY
4566 case 0x10ec0233:
4567 case 0x10ec0283:
4568 spec->codec_variant = ALC269_TYPE_ALC283;
4569 spec->shutup = alc283_shutup;
4570 spec->init_hook = alc283_init;
4571 break;
065380f0
KY
4572 case 0x10ec0284:
4573 case 0x10ec0292:
4574 spec->codec_variant = ALC269_TYPE_ALC284;
4575 break;
161ebf29
KY
4576 case 0x10ec0285:
4577 case 0x10ec0293:
4578 spec->codec_variant = ALC269_TYPE_ALC285;
4579 break;
7fc7d047
KY
4580 case 0x10ec0286:
4581 spec->codec_variant = ALC269_TYPE_ALC286;
4582 break;
1d04c9de
KY
4583 case 0x10ec0255:
4584 spec->codec_variant = ALC269_TYPE_ALC255;
4585 break;
1d045db9 4586 }
6dda9f4a 4587
ad60d502 4588 if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
97a26570 4589 spec->has_alc5505_dsp = 1;
ad60d502
KY
4590 spec->init_hook = alc5505_dsp_init;
4591 }
4592
a4297b5d
TI
4593 /* automatic parse from the BIOS config */
4594 err = alc269_parse_auto_config(codec);
e16fb6d1
TI
4595 if (err < 0)
4596 goto error;
6dda9f4a 4597
7504b6cd 4598 if (!spec->gen.no_analog && spec->gen.beep_nid)
1d045db9 4599 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
f1d4e28b 4600
1d045db9 4601 codec->patch_ops = alc_patch_ops;
2a43952a 4602#ifdef CONFIG_PM
ad60d502 4603 codec->patch_ops.suspend = alc269_suspend;
1d045db9
TI
4604 codec->patch_ops.resume = alc269_resume;
4605#endif
c5177c86
KY
4606 if (!spec->shutup)
4607 spec->shutup = alc269_shutup;
ebb83eeb 4608
1727a771 4609 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 4610
1d045db9 4611 return 0;
e16fb6d1
TI
4612
4613 error:
4614 alc_free(codec);
4615 return err;
1d045db9 4616}
f1d4e28b 4617
1d045db9
TI
4618/*
4619 * ALC861
4620 */
622e84cd 4621
1d045db9 4622static int alc861_parse_auto_config(struct hda_codec *codec)
6dda9f4a 4623{
1d045db9 4624 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
3e6179b8
TI
4625 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
4626 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
604401a9
TI
4627}
4628
1d045db9
TI
4629/* Pin config fixes */
4630enum {
e652f4c8
TI
4631 ALC861_FIXUP_FSC_AMILO_PI1505,
4632 ALC861_FIXUP_AMP_VREF_0F,
4633 ALC861_FIXUP_NO_JACK_DETECT,
4634 ALC861_FIXUP_ASUS_A6RP,
6ddf0fd1 4635 ALC660_FIXUP_ASUS_W7J,
1d045db9 4636};
7085ec12 4637
31150f23
TI
4638/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
4639static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
1727a771 4640 const struct hda_fixup *fix, int action)
31150f23
TI
4641{
4642 struct alc_spec *spec = codec->spec;
4643 unsigned int val;
4644
1727a771 4645 if (action != HDA_FIXUP_ACT_INIT)
31150f23 4646 return;
d3f02d60 4647 val = snd_hda_codec_get_pin_target(codec, 0x0f);
31150f23
TI
4648 if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
4649 val |= AC_PINCTL_IN_EN;
4650 val |= AC_PINCTL_VREF_50;
cdd03ced 4651 snd_hda_set_pin_ctl(codec, 0x0f, val);
08c189f2 4652 spec->gen.keep_vref_in_automute = 1;
31150f23
TI
4653}
4654
e652f4c8
TI
4655/* suppress the jack-detection */
4656static void alc_fixup_no_jack_detect(struct hda_codec *codec,
1727a771 4657 const struct hda_fixup *fix, int action)
e652f4c8 4658{
1727a771 4659 if (action == HDA_FIXUP_ACT_PRE_PROBE)
e652f4c8 4660 codec->no_jack_detect = 1;
7d7eb9ea 4661}
e652f4c8 4662
1727a771 4663static const struct hda_fixup alc861_fixups[] = {
e652f4c8 4664 [ALC861_FIXUP_FSC_AMILO_PI1505] = {
1727a771
TI
4665 .type = HDA_FIXUP_PINS,
4666 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
4667 { 0x0b, 0x0221101f }, /* HP */
4668 { 0x0f, 0x90170310 }, /* speaker */
4669 { }
4670 }
4671 },
e652f4c8 4672 [ALC861_FIXUP_AMP_VREF_0F] = {
1727a771 4673 .type = HDA_FIXUP_FUNC,
31150f23 4674 .v.func = alc861_fixup_asus_amp_vref_0f,
3b25eb69 4675 },
e652f4c8 4676 [ALC861_FIXUP_NO_JACK_DETECT] = {
1727a771 4677 .type = HDA_FIXUP_FUNC,
e652f4c8
TI
4678 .v.func = alc_fixup_no_jack_detect,
4679 },
4680 [ALC861_FIXUP_ASUS_A6RP] = {
1727a771 4681 .type = HDA_FIXUP_FUNC,
e652f4c8
TI
4682 .v.func = alc861_fixup_asus_amp_vref_0f,
4683 .chained = true,
4684 .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
6ddf0fd1
TI
4685 },
4686 [ALC660_FIXUP_ASUS_W7J] = {
4687 .type = HDA_FIXUP_VERBS,
4688 .v.verbs = (const struct hda_verb[]) {
4689 /* ASUS W7J needs a magic pin setup on unused NID 0x10
4690 * for enabling outputs
4691 */
4692 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
4693 { }
4694 },
e652f4c8 4695 }
1d045db9 4696};
7085ec12 4697
1d045db9 4698static const struct snd_pci_quirk alc861_fixup_tbl[] = {
6ddf0fd1 4699 SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
e7ca237b 4700 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
e652f4c8
TI
4701 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
4702 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
4703 SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
4704 SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F),
4705 SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F),
4706 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
1d045db9
TI
4707 {}
4708};
3af9ee6b 4709
1d045db9
TI
4710/*
4711 */
1d045db9 4712static int patch_alc861(struct hda_codec *codec)
7085ec12 4713{
1d045db9 4714 struct alc_spec *spec;
1d045db9 4715 int err;
7085ec12 4716
3de95173
TI
4717 err = alc_alloc_spec(codec, 0x15);
4718 if (err < 0)
4719 return err;
1d045db9 4720
3de95173 4721 spec = codec->spec;
7504b6cd 4722 spec->gen.beep_nid = 0x23;
1d045db9 4723
1727a771
TI
4724 snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
4725 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
3af9ee6b 4726
cb4e4824
TI
4727 /* automatic parse from the BIOS config */
4728 err = alc861_parse_auto_config(codec);
e16fb6d1
TI
4729 if (err < 0)
4730 goto error;
3af9ee6b 4731
7504b6cd 4732 if (!spec->gen.no_analog)
3e6179b8 4733 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
7085ec12 4734
1d045db9 4735 codec->patch_ops = alc_patch_ops;
83012a7c 4736#ifdef CONFIG_PM
cb4e4824 4737 spec->power_hook = alc_power_eapd;
1d045db9
TI
4738#endif
4739
1727a771 4740 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 4741
1d045db9 4742 return 0;
e16fb6d1
TI
4743
4744 error:
4745 alc_free(codec);
4746 return err;
7085ec12
TI
4747}
4748
1d045db9
TI
4749/*
4750 * ALC861-VD support
4751 *
4752 * Based on ALC882
4753 *
4754 * In addition, an independent DAC
4755 */
1d045db9 4756static int alc861vd_parse_auto_config(struct hda_codec *codec)
bc9f98a9 4757{
1d045db9 4758 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
3e6179b8
TI
4759 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4760 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
ce764ab2
TI
4761}
4762
1d045db9 4763enum {
8fdcb6fe
TI
4764 ALC660VD_FIX_ASUS_GPIO1,
4765 ALC861VD_FIX_DALLAS,
1d045db9 4766};
ce764ab2 4767
8fdcb6fe
TI
4768/* exclude VREF80 */
4769static void alc861vd_fixup_dallas(struct hda_codec *codec,
1727a771 4770 const struct hda_fixup *fix, int action)
8fdcb6fe 4771{
1727a771 4772 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
b78562b1
TI
4773 snd_hda_override_pin_caps(codec, 0x18, 0x00000734);
4774 snd_hda_override_pin_caps(codec, 0x19, 0x0000073c);
8fdcb6fe
TI
4775 }
4776}
4777
1727a771 4778static const struct hda_fixup alc861vd_fixups[] = {
1d045db9 4779 [ALC660VD_FIX_ASUS_GPIO1] = {
1727a771 4780 .type = HDA_FIXUP_VERBS,
1d045db9 4781 .v.verbs = (const struct hda_verb[]) {
8fdcb6fe 4782 /* reset GPIO1 */
1d045db9
TI
4783 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
4784 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
4785 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
4786 { }
4787 }
4788 },
8fdcb6fe 4789 [ALC861VD_FIX_DALLAS] = {
1727a771 4790 .type = HDA_FIXUP_FUNC,
8fdcb6fe
TI
4791 .v.func = alc861vd_fixup_dallas,
4792 },
1d045db9 4793};
ce764ab2 4794
1d045db9 4795static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
8fdcb6fe 4796 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS),
1d045db9 4797 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
8fdcb6fe 4798 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS),
1d045db9
TI
4799 {}
4800};
ce764ab2 4801
1d045db9
TI
4802/*
4803 */
1d045db9 4804static int patch_alc861vd(struct hda_codec *codec)
ce764ab2 4805{
1d045db9 4806 struct alc_spec *spec;
cb4e4824 4807 int err;
ce764ab2 4808
3de95173
TI
4809 err = alc_alloc_spec(codec, 0x0b);
4810 if (err < 0)
4811 return err;
1d045db9 4812
3de95173 4813 spec = codec->spec;
7504b6cd 4814 spec->gen.beep_nid = 0x23;
1d045db9 4815
1727a771
TI
4816 snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
4817 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1d045db9 4818
cb4e4824
TI
4819 /* automatic parse from the BIOS config */
4820 err = alc861vd_parse_auto_config(codec);
e16fb6d1
TI
4821 if (err < 0)
4822 goto error;
ce764ab2 4823
7504b6cd 4824 if (!spec->gen.no_analog)
3e6179b8 4825 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
1d045db9 4826
1d045db9
TI
4827 codec->patch_ops = alc_patch_ops;
4828
1d045db9 4829 spec->shutup = alc_eapd_shutup;
1d045db9 4830
1727a771 4831 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 4832
ce764ab2 4833 return 0;
e16fb6d1
TI
4834
4835 error:
4836 alc_free(codec);
4837 return err;
ce764ab2
TI
4838}
4839
1d045db9
TI
4840/*
4841 * ALC662 support
4842 *
4843 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
4844 * configuration. Each pin widget can choose any input DACs and a mixer.
4845 * Each ADC is connected from a mixer of all inputs. This makes possible
4846 * 6-channel independent captures.
4847 *
4848 * In addition, an independent DAC for the multi-playback (not used in this
4849 * driver yet).
4850 */
1d045db9
TI
4851
4852/*
4853 * BIOS auto configuration
4854 */
4855
bc9f98a9
KY
4856static int alc662_parse_auto_config(struct hda_codec *codec)
4857{
4c6d72d1 4858 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
3e6179b8
TI
4859 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
4860 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4861 const hda_nid_t *ssids;
ee979a14 4862
6227cdce 4863 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
1d87caa6
RK
4864 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670 ||
4865 codec->vendor_id == 0x10ec0671)
3e6179b8 4866 ssids = alc663_ssids;
6227cdce 4867 else
3e6179b8
TI
4868 ssids = alc662_ssids;
4869 return alc_parse_auto_config(codec, alc662_ignore, ssids);
bc9f98a9
KY
4870}
4871
6be7948f 4872static void alc272_fixup_mario(struct hda_codec *codec,
1727a771 4873 const struct hda_fixup *fix, int action)
6fc398cb 4874{
9bb1f06f 4875 if (action != HDA_FIXUP_ACT_PRE_PROBE)
6fc398cb 4876 return;
6be7948f
TB
4877 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
4878 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
4879 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
4880 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4881 (0 << AC_AMPCAP_MUTE_SHIFT)))
4882 printk(KERN_WARNING
4883 "hda_codec: failed to override amp caps for NID 0x2\n");
4884}
4885
8e383953
TI
4886static const struct snd_pcm_chmap_elem asus_pcm_2_1_chmaps[] = {
4887 { .channels = 2,
4888 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
4889 { .channels = 4,
4890 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
4891 SNDRV_CHMAP_NA, SNDRV_CHMAP_LFE } }, /* LFE only on right */
4892 { }
4893};
4894
4895/* override the 2.1 chmap */
eb9ca3ab 4896static void alc_fixup_bass_chmap(struct hda_codec *codec,
8e383953
TI
4897 const struct hda_fixup *fix, int action)
4898{
4899 if (action == HDA_FIXUP_ACT_BUILD) {
4900 struct alc_spec *spec = codec->spec;
4901 spec->gen.pcm_rec[0].stream[0].chmap = asus_pcm_2_1_chmaps;
4902 }
4903}
4904
6cb3b707 4905enum {
2df03514 4906 ALC662_FIXUP_ASPIRE,
6cb3b707 4907 ALC662_FIXUP_IDEAPAD,
6be7948f 4908 ALC272_FIXUP_MARIO,
d2ebd479 4909 ALC662_FIXUP_CZC_P10T,
94024cd1 4910 ALC662_FIXUP_SKU_IGNORE,
e59ea3ed 4911 ALC662_FIXUP_HP_RP5800,
53c334ad
TI
4912 ALC662_FIXUP_ASUS_MODE1,
4913 ALC662_FIXUP_ASUS_MODE2,
4914 ALC662_FIXUP_ASUS_MODE3,
4915 ALC662_FIXUP_ASUS_MODE4,
4916 ALC662_FIXUP_ASUS_MODE5,
4917 ALC662_FIXUP_ASUS_MODE6,
4918 ALC662_FIXUP_ASUS_MODE7,
4919 ALC662_FIXUP_ASUS_MODE8,
1565cc35 4920 ALC662_FIXUP_NO_JACK_DETECT,
edfe3bfc 4921 ALC662_FIXUP_ZOTAC_Z68,
125821ae 4922 ALC662_FIXUP_INV_DMIC,
73bdd597
DH
4923 ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
4924 ALC668_FIXUP_HEADSET_MODE,
8e383953 4925 ALC662_FIXUP_BASS_CHMAP,
a30c9aaa
TI
4926 ALC662_FIXUP_BASS_1A,
4927 ALC662_FIXUP_BASS_1A_CHMAP,
6cb3b707
DH
4928};
4929
1727a771 4930static const struct hda_fixup alc662_fixups[] = {
2df03514 4931 [ALC662_FIXUP_ASPIRE] = {
1727a771
TI
4932 .type = HDA_FIXUP_PINS,
4933 .v.pins = (const struct hda_pintbl[]) {
2df03514
DC
4934 { 0x15, 0x99130112 }, /* subwoofer */
4935 { }
4936 }
4937 },
6cb3b707 4938 [ALC662_FIXUP_IDEAPAD] = {
1727a771
TI
4939 .type = HDA_FIXUP_PINS,
4940 .v.pins = (const struct hda_pintbl[]) {
6cb3b707
DH
4941 { 0x17, 0x99130112 }, /* subwoofer */
4942 { }
4943 }
4944 },
6be7948f 4945 [ALC272_FIXUP_MARIO] = {
1727a771 4946 .type = HDA_FIXUP_FUNC,
b5bfbc67 4947 .v.func = alc272_fixup_mario,
d2ebd479
AA
4948 },
4949 [ALC662_FIXUP_CZC_P10T] = {
1727a771 4950 .type = HDA_FIXUP_VERBS,
d2ebd479
AA
4951 .v.verbs = (const struct hda_verb[]) {
4952 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4953 {}
4954 }
4955 },
94024cd1 4956 [ALC662_FIXUP_SKU_IGNORE] = {
1727a771 4957 .type = HDA_FIXUP_FUNC,
23d30f28 4958 .v.func = alc_fixup_sku_ignore,
c6b35874 4959 },
e59ea3ed 4960 [ALC662_FIXUP_HP_RP5800] = {
1727a771
TI
4961 .type = HDA_FIXUP_PINS,
4962 .v.pins = (const struct hda_pintbl[]) {
e59ea3ed
TI
4963 { 0x14, 0x0221201f }, /* HP out */
4964 { }
4965 },
4966 .chained = true,
4967 .chain_id = ALC662_FIXUP_SKU_IGNORE
4968 },
53c334ad 4969 [ALC662_FIXUP_ASUS_MODE1] = {
1727a771
TI
4970 .type = HDA_FIXUP_PINS,
4971 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
4972 { 0x14, 0x99130110 }, /* speaker */
4973 { 0x18, 0x01a19c20 }, /* mic */
4974 { 0x19, 0x99a3092f }, /* int-mic */
4975 { 0x21, 0x0121401f }, /* HP out */
4976 { }
4977 },
4978 .chained = true,
4979 .chain_id = ALC662_FIXUP_SKU_IGNORE
4980 },
4981 [ALC662_FIXUP_ASUS_MODE2] = {
1727a771
TI
4982 .type = HDA_FIXUP_PINS,
4983 .v.pins = (const struct hda_pintbl[]) {
2996bdba
TI
4984 { 0x14, 0x99130110 }, /* speaker */
4985 { 0x18, 0x01a19820 }, /* mic */
4986 { 0x19, 0x99a3092f }, /* int-mic */
4987 { 0x1b, 0x0121401f }, /* HP out */
4988 { }
4989 },
53c334ad
TI
4990 .chained = true,
4991 .chain_id = ALC662_FIXUP_SKU_IGNORE
4992 },
4993 [ALC662_FIXUP_ASUS_MODE3] = {
1727a771
TI
4994 .type = HDA_FIXUP_PINS,
4995 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
4996 { 0x14, 0x99130110 }, /* speaker */
4997 { 0x15, 0x0121441f }, /* HP */
4998 { 0x18, 0x01a19840 }, /* mic */
4999 { 0x19, 0x99a3094f }, /* int-mic */
5000 { 0x21, 0x01211420 }, /* HP2 */
5001 { }
5002 },
5003 .chained = true,
5004 .chain_id = ALC662_FIXUP_SKU_IGNORE
5005 },
5006 [ALC662_FIXUP_ASUS_MODE4] = {
1727a771
TI
5007 .type = HDA_FIXUP_PINS,
5008 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5009 { 0x14, 0x99130110 }, /* speaker */
5010 { 0x16, 0x99130111 }, /* speaker */
5011 { 0x18, 0x01a19840 }, /* mic */
5012 { 0x19, 0x99a3094f }, /* int-mic */
5013 { 0x21, 0x0121441f }, /* HP */
5014 { }
5015 },
5016 .chained = true,
5017 .chain_id = ALC662_FIXUP_SKU_IGNORE
5018 },
5019 [ALC662_FIXUP_ASUS_MODE5] = {
1727a771
TI
5020 .type = HDA_FIXUP_PINS,
5021 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5022 { 0x14, 0x99130110 }, /* speaker */
5023 { 0x15, 0x0121441f }, /* HP */
5024 { 0x16, 0x99130111 }, /* speaker */
5025 { 0x18, 0x01a19840 }, /* mic */
5026 { 0x19, 0x99a3094f }, /* int-mic */
5027 { }
5028 },
5029 .chained = true,
5030 .chain_id = ALC662_FIXUP_SKU_IGNORE
5031 },
5032 [ALC662_FIXUP_ASUS_MODE6] = {
1727a771
TI
5033 .type = HDA_FIXUP_PINS,
5034 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5035 { 0x14, 0x99130110 }, /* speaker */
5036 { 0x15, 0x01211420 }, /* HP2 */
5037 { 0x18, 0x01a19840 }, /* mic */
5038 { 0x19, 0x99a3094f }, /* int-mic */
5039 { 0x1b, 0x0121441f }, /* HP */
5040 { }
5041 },
5042 .chained = true,
5043 .chain_id = ALC662_FIXUP_SKU_IGNORE
5044 },
5045 [ALC662_FIXUP_ASUS_MODE7] = {
1727a771
TI
5046 .type = HDA_FIXUP_PINS,
5047 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5048 { 0x14, 0x99130110 }, /* speaker */
5049 { 0x17, 0x99130111 }, /* speaker */
5050 { 0x18, 0x01a19840 }, /* mic */
5051 { 0x19, 0x99a3094f }, /* int-mic */
5052 { 0x1b, 0x01214020 }, /* HP */
5053 { 0x21, 0x0121401f }, /* HP */
5054 { }
5055 },
5056 .chained = true,
5057 .chain_id = ALC662_FIXUP_SKU_IGNORE
5058 },
5059 [ALC662_FIXUP_ASUS_MODE8] = {
1727a771
TI
5060 .type = HDA_FIXUP_PINS,
5061 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5062 { 0x14, 0x99130110 }, /* speaker */
5063 { 0x12, 0x99a30970 }, /* int-mic */
5064 { 0x15, 0x01214020 }, /* HP */
5065 { 0x17, 0x99130111 }, /* speaker */
5066 { 0x18, 0x01a19840 }, /* mic */
5067 { 0x21, 0x0121401f }, /* HP */
5068 { }
5069 },
5070 .chained = true,
5071 .chain_id = ALC662_FIXUP_SKU_IGNORE
2996bdba 5072 },
1565cc35 5073 [ALC662_FIXUP_NO_JACK_DETECT] = {
1727a771 5074 .type = HDA_FIXUP_FUNC,
1565cc35
TI
5075 .v.func = alc_fixup_no_jack_detect,
5076 },
edfe3bfc 5077 [ALC662_FIXUP_ZOTAC_Z68] = {
1727a771
TI
5078 .type = HDA_FIXUP_PINS,
5079 .v.pins = (const struct hda_pintbl[]) {
edfe3bfc
DH
5080 { 0x1b, 0x02214020 }, /* Front HP */
5081 { }
5082 }
5083 },
125821ae 5084 [ALC662_FIXUP_INV_DMIC] = {
1727a771 5085 .type = HDA_FIXUP_FUNC,
6e72aa5f 5086 .v.func = alc_fixup_inv_dmic_0x12,
125821ae 5087 },
73bdd597
DH
5088 [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
5089 .type = HDA_FIXUP_PINS,
5090 .v.pins = (const struct hda_pintbl[]) {
5091 { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
5092 { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
5093 { }
5094 },
5095 .chained = true,
5096 .chain_id = ALC668_FIXUP_HEADSET_MODE
5097 },
5098 [ALC668_FIXUP_HEADSET_MODE] = {
5099 .type = HDA_FIXUP_FUNC,
5100 .v.func = alc_fixup_headset_mode_alc668,
5101 },
8e383953
TI
5102 [ALC662_FIXUP_BASS_CHMAP] = {
5103 .type = HDA_FIXUP_FUNC,
eb9ca3ab 5104 .v.func = alc_fixup_bass_chmap,
8e383953
TI
5105 .chained = true,
5106 .chain_id = ALC662_FIXUP_ASUS_MODE4
5107 },
a30c9aaa
TI
5108 [ALC662_FIXUP_BASS_1A] = {
5109 .type = HDA_FIXUP_PINS,
5110 .v.pins = (const struct hda_pintbl[]) {
5111 {0x1a, 0x80106111}, /* bass speaker */
5112 {}
5113 },
5114 },
5115 [ALC662_FIXUP_BASS_1A_CHMAP] = {
5116 .type = HDA_FIXUP_FUNC,
eb9ca3ab 5117 .v.func = alc_fixup_bass_chmap,
a30c9aaa
TI
5118 .chained = true,
5119 .chain_id = ALC662_FIXUP_BASS_1A,
5120 },
6cb3b707
DH
5121};
5122
a9111321 5123static const struct snd_pci_quirk alc662_fixup_tbl[] = {
53c334ad 5124 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
d3d3835c 5125 SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
a6c47a85 5126 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
94024cd1 5127 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
125821ae 5128 SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
1801928e 5129 SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
2df03514 5130 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
73bdd597
DH
5131 SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
5132 SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
6c6eb427 5133 SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
7dca4bc6 5134 SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
09d2014f 5135 SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
ad8ff99e 5136 SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
0dfb9809 5137 SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
e59ea3ed 5138 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
a30c9aaa 5139 SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP),
8e383953
TI
5140 SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP),
5141 SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_CHMAP),
1565cc35 5142 SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
53c334ad 5143 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
a0e90acc 5144 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
d4118588 5145 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
6cb3b707 5146 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
edfe3bfc 5147 SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68),
d2ebd479 5148 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
53c334ad
TI
5149
5150#if 0
5151 /* Below is a quirk table taken from the old code.
5152 * Basically the device should work as is without the fixup table.
5153 * If BIOS doesn't give a proper info, enable the corresponding
5154 * fixup entry.
7d7eb9ea 5155 */
53c334ad
TI
5156 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
5157 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
5158 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
5159 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
5160 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5161 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5162 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5163 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
5164 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
5165 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5166 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
5167 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
5168 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
5169 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
5170 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
5171 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5172 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
5173 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
5174 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5175 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
5176 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
5177 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5178 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
5179 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
5180 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
5181 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5182 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
5183 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
5184 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5185 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
5186 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5187 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5188 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
5189 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
5190 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
5191 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
5192 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
5193 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
5194 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
5195 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5196 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
5197 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
5198 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5199 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
5200 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
5201 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
5202 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
5203 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
5204 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5205 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
5206#endif
6cb3b707
DH
5207 {}
5208};
5209
1727a771 5210static const struct hda_model_fixup alc662_fixup_models[] = {
6be7948f 5211 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
53c334ad
TI
5212 {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
5213 {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
5214 {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
5215 {.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
5216 {.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
5217 {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
5218 {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
5219 {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
6e72aa5f 5220 {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
e32aa85a 5221 {.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
6be7948f
TB
5222 {}
5223};
6cb3b707 5224
8663ff75
KY
5225static void alc662_fill_coef(struct hda_codec *codec)
5226{
5227 int val, coef;
5228
5229 coef = alc_get_coef0(codec);
5230
5231 switch (codec->vendor_id) {
5232 case 0x10ec0662:
5233 if ((coef & 0x00f0) == 0x0030) {
5234 val = alc_read_coef_idx(codec, 0x4); /* EAPD Ctrl */
5235 alc_write_coef_idx(codec, 0x4, val & ~(1<<10));
5236 }
5237 break;
5238 case 0x10ec0272:
5239 case 0x10ec0273:
5240 case 0x10ec0663:
5241 case 0x10ec0665:
5242 case 0x10ec0670:
5243 case 0x10ec0671:
5244 case 0x10ec0672:
5245 val = alc_read_coef_idx(codec, 0xd); /* EAPD Ctrl */
5246 alc_write_coef_idx(codec, 0xd, val | (1<<14));
5247 break;
5248 }
5249}
6cb3b707 5250
1d045db9
TI
5251/*
5252 */
bc9f98a9
KY
5253static int patch_alc662(struct hda_codec *codec)
5254{
5255 struct alc_spec *spec;
3de95173 5256 int err;
bc9f98a9 5257
3de95173
TI
5258 err = alc_alloc_spec(codec, 0x0b);
5259 if (err < 0)
5260 return err;
bc9f98a9 5261
3de95173 5262 spec = codec->spec;
1f0f4b80 5263
53c334ad
TI
5264 /* handle multiple HPs as is */
5265 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
5266
2c3bf9ab
TI
5267 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5268
8663ff75
KY
5269 spec->init_hook = alc662_fill_coef;
5270 alc662_fill_coef(codec);
5271
1727a771 5272 snd_hda_pick_fixup(codec, alc662_fixup_models,
8e5a0509 5273 alc662_fixup_tbl, alc662_fixups);
1727a771 5274 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
8e5a0509
TI
5275
5276 alc_auto_parse_customize_define(codec);
5277
7504b6cd
TI
5278 if (has_cdefine_beep(codec))
5279 spec->gen.beep_nid = 0x01;
5280
1bb7e43e 5281 if ((alc_get_coef0(codec) & (1 << 14)) &&
e16fb6d1
TI
5282 codec->bus->pci->subsystem_vendor == 0x1025 &&
5283 spec->cdefine.platform_type == 1) {
6134b1a2
WY
5284 err = alc_codec_rename(codec, "ALC272X");
5285 if (err < 0)
e16fb6d1 5286 goto error;
20ca0c35 5287 }
274693f3 5288
b9c5106c
TI
5289 /* automatic parse from the BIOS config */
5290 err = alc662_parse_auto_config(codec);
e16fb6d1
TI
5291 if (err < 0)
5292 goto error;
bc9f98a9 5293
7504b6cd 5294 if (!spec->gen.no_analog && spec->gen.beep_nid) {
da00c244
KY
5295 switch (codec->vendor_id) {
5296 case 0x10ec0662:
5297 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5298 break;
5299 case 0x10ec0272:
5300 case 0x10ec0663:
5301 case 0x10ec0665:
9ad54547 5302 case 0x10ec0668:
da00c244
KY
5303 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5304 break;
5305 case 0x10ec0273:
5306 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5307 break;
5308 }
cec27c89 5309 }
2134ea4f 5310
bc9f98a9 5311 codec->patch_ops = alc_patch_ops;
1c716153 5312 spec->shutup = alc_eapd_shutup;
6cb3b707 5313
1727a771 5314 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 5315
bc9f98a9 5316 return 0;
801f49d3 5317
e16fb6d1
TI
5318 error:
5319 alc_free(codec);
5320 return err;
b478b998
KY
5321}
5322
d1eb57f4
KY
5323/*
5324 * ALC680 support
5325 */
d1eb57f4 5326
d1eb57f4
KY
5327static int alc680_parse_auto_config(struct hda_codec *codec)
5328{
3e6179b8 5329 return alc_parse_auto_config(codec, NULL, NULL);
d1eb57f4
KY
5330}
5331
d1eb57f4 5332/*
d1eb57f4 5333 */
d1eb57f4
KY
5334static int patch_alc680(struct hda_codec *codec)
5335{
d1eb57f4
KY
5336 int err;
5337
1f0f4b80 5338 /* ALC680 has no aa-loopback mixer */
3de95173
TI
5339 err = alc_alloc_spec(codec, 0);
5340 if (err < 0)
5341 return err;
1f0f4b80 5342
1ebec5f2
TI
5343 /* automatic parse from the BIOS config */
5344 err = alc680_parse_auto_config(codec);
5345 if (err < 0) {
5346 alc_free(codec);
5347 return err;
d1eb57f4
KY
5348 }
5349
d1eb57f4 5350 codec->patch_ops = alc_patch_ops;
d1eb57f4
KY
5351
5352 return 0;
5353}
5354
1da177e4
LT
5355/*
5356 * patch entries
5357 */
a9111321 5358static const struct hda_codec_preset snd_hda_preset_realtek[] = {
296f0338 5359 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
ba4c4d0a 5360 { .id = 0x10ec0231, .name = "ALC231", .patch = patch_alc269 },
84dfd0ac 5361 { .id = 0x10ec0233, .name = "ALC233", .patch = patch_alc269 },
1d04c9de 5362 { .id = 0x10ec0255, .name = "ALC255", .patch = patch_alc269 },
1da177e4 5363 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
df694daa 5364 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
f6a92248 5365 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
a361d84b 5366 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
f6a92248 5367 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
ebb83eeb 5368 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
01afd41f 5369 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
ebb83eeb 5370 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
296f0338 5371 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
befae82e 5372 { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 },
4e01ec63 5373 { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
7ff34ad8 5374 { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
065380f0 5375 { .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 },
161ebf29 5376 { .id = 0x10ec0285, .name = "ALC285", .patch = patch_alc269 },
7fc7d047 5377 { .id = 0x10ec0286, .name = "ALC286", .patch = patch_alc269 },
7ff34ad8 5378 { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
af02dde8 5379 { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
161ebf29 5380 { .id = 0x10ec0293, .name = "ALC293", .patch = patch_alc269 },
f32610ed 5381 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
bc9f98a9 5382 .patch = patch_alc861 },
f32610ed
JS
5383 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5384 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5385 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
bc9f98a9 5386 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
4953550a 5387 .patch = patch_alc882 },
bc9f98a9
KY
5388 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5389 .patch = patch_alc662 },
cc667a72
DH
5390 { .id = 0x10ec0662, .rev = 0x100300, .name = "ALC662 rev3",
5391 .patch = patch_alc662 },
6dda9f4a 5392 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
cec27c89 5393 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
19a62823 5394 { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
6227cdce 5395 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
1d87caa6 5396 { .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 },
d1eb57f4 5397 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
f32610ed 5398 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
1da177e4 5399 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
4953550a 5400 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
669faba2 5401 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
4953550a 5402 .patch = patch_alc882 },
cb308f97 5403 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
4953550a 5404 .patch = patch_alc882 },
df694daa 5405 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
e16fb6d1 5406 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
4442608d 5407 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
4953550a 5408 .patch = patch_alc882 },
e16fb6d1 5409 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc882 },
4953550a 5410 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
274693f3 5411 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
e16fb6d1 5412 { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 },
19a62823 5413 { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 },
1da177e4
LT
5414 {} /* terminator */
5415};
1289e9e8
TI
5416
5417MODULE_ALIAS("snd-hda-codec-id:10ec*");
5418
5419MODULE_LICENSE("GPL");
5420MODULE_DESCRIPTION("Realtek HD-audio codec");
5421
5422static struct hda_codec_preset_list realtek_list = {
5423 .preset = snd_hda_preset_realtek,
5424 .owner = THIS_MODULE,
5425};
5426
5427static int __init patch_realtek_init(void)
5428{
5429 return snd_hda_add_codec_preset(&realtek_list);
5430}
5431
5432static void __exit patch_realtek_exit(void)
5433{
5434 snd_hda_delete_codec_preset(&realtek_list);
5435}
5436
5437module_init(patch_realtek_init)
5438module_exit(patch_realtek_exit)