]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - sound/pci/hda/patch_realtek.c
ALSA: compress: add num_sample_rates in snd_codec_desc
[mirror_ubuntu-bionic-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,
b2c53e20 1813 ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
5c0ebfbe 1814 ALC889_FIXUP_VAIO_TT,
0e7cc2e7 1815 ALC888_FIXUP_EEE1601,
177943a3 1816 ALC882_FIXUP_EAPD,
7a6069bf 1817 ALC883_FIXUP_EAPD,
8812c4f9 1818 ALC883_FIXUP_ACER_EAPD,
1a97b7f2
TI
1819 ALC882_FIXUP_GPIO1,
1820 ALC882_FIXUP_GPIO2,
eb844d51 1821 ALC882_FIXUP_GPIO3,
68ef0561
TI
1822 ALC889_FIXUP_COEF,
1823 ALC882_FIXUP_ASUS_W2JC,
c3e837bb
TI
1824 ALC882_FIXUP_ACER_ASPIRE_4930G,
1825 ALC882_FIXUP_ACER_ASPIRE_8930G,
1826 ALC882_FIXUP_ASPIRE_8930G_VERBS,
5671087f 1827 ALC885_FIXUP_MACPRO_GPIO,
02a237b2 1828 ALC889_FIXUP_DAC_ROUTE,
1a97b7f2
TI
1829 ALC889_FIXUP_MBP_VREF,
1830 ALC889_FIXUP_IMAC91_VREF,
0756f09c 1831 ALC889_FIXUP_MBA21_VREF,
6e72aa5f 1832 ALC882_FIXUP_INV_DMIC,
e427c237 1833 ALC882_FIXUP_NO_PRIMARY_HP,
1f0bbf03 1834 ALC887_FIXUP_ASUS_BASS,
eb9ca3ab 1835 ALC887_FIXUP_BASS_CHMAP,
ff818c24
TI
1836};
1837
68ef0561 1838static void alc889_fixup_coef(struct hda_codec *codec,
1727a771 1839 const struct hda_fixup *fix, int action)
68ef0561 1840{
1727a771 1841 if (action != HDA_FIXUP_ACT_INIT)
68ef0561
TI
1842 return;
1843 alc889_coef_init(codec);
1844}
1845
5671087f
TI
1846/* toggle speaker-output according to the hp-jack state */
1847static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
1848{
1849 unsigned int gpiostate, gpiomask, gpiodir;
1850
1851 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
1852 AC_VERB_GET_GPIO_DATA, 0);
1853
1854 if (!muted)
1855 gpiostate |= (1 << pin);
1856 else
1857 gpiostate &= ~(1 << pin);
1858
1859 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
1860 AC_VERB_GET_GPIO_MASK, 0);
1861 gpiomask |= (1 << pin);
1862
1863 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
1864 AC_VERB_GET_GPIO_DIRECTION, 0);
1865 gpiodir |= (1 << pin);
1866
1867
1868 snd_hda_codec_write(codec, codec->afg, 0,
1869 AC_VERB_SET_GPIO_MASK, gpiomask);
1870 snd_hda_codec_write(codec, codec->afg, 0,
1871 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
1872
1873 msleep(1);
1874
1875 snd_hda_codec_write(codec, codec->afg, 0,
1876 AC_VERB_SET_GPIO_DATA, gpiostate);
1877}
1878
1879/* set up GPIO at initialization */
1880static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
1727a771 1881 const struct hda_fixup *fix, int action)
5671087f 1882{
1727a771 1883 if (action != HDA_FIXUP_ACT_INIT)
5671087f
TI
1884 return;
1885 alc882_gpio_mute(codec, 0, 0);
1886 alc882_gpio_mute(codec, 1, 0);
1887}
1888
02a237b2
TI
1889/* Fix the connection of some pins for ALC889:
1890 * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
1891 * work correctly (bko#42740)
1892 */
1893static void alc889_fixup_dac_route(struct hda_codec *codec,
1727a771 1894 const struct hda_fixup *fix, int action)
02a237b2 1895{
1727a771 1896 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
ef8d60fb 1897 /* fake the connections during parsing the tree */
02a237b2
TI
1898 hda_nid_t conn1[2] = { 0x0c, 0x0d };
1899 hda_nid_t conn2[2] = { 0x0e, 0x0f };
1900 snd_hda_override_conn_list(codec, 0x14, 2, conn1);
1901 snd_hda_override_conn_list(codec, 0x15, 2, conn1);
1902 snd_hda_override_conn_list(codec, 0x18, 2, conn2);
1903 snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
1727a771 1904 } else if (action == HDA_FIXUP_ACT_PROBE) {
ef8d60fb
TI
1905 /* restore the connections */
1906 hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
1907 snd_hda_override_conn_list(codec, 0x14, 5, conn);
1908 snd_hda_override_conn_list(codec, 0x15, 5, conn);
1909 snd_hda_override_conn_list(codec, 0x18, 5, conn);
1910 snd_hda_override_conn_list(codec, 0x1a, 5, conn);
02a237b2
TI
1911 }
1912}
1913
1a97b7f2
TI
1914/* Set VREF on HP pin */
1915static void alc889_fixup_mbp_vref(struct hda_codec *codec,
1727a771 1916 const struct hda_fixup *fix, int action)
1a97b7f2
TI
1917{
1918 struct alc_spec *spec = codec->spec;
1919 static hda_nid_t nids[2] = { 0x14, 0x15 };
1920 int i;
1921
1727a771 1922 if (action != HDA_FIXUP_ACT_INIT)
1a97b7f2
TI
1923 return;
1924 for (i = 0; i < ARRAY_SIZE(nids); i++) {
1925 unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]);
1926 if (get_defcfg_device(val) != AC_JACK_HP_OUT)
1927 continue;
d3f02d60 1928 val = snd_hda_codec_get_pin_target(codec, nids[i]);
1a97b7f2 1929 val |= AC_PINCTL_VREF_80;
cdd03ced 1930 snd_hda_set_pin_ctl(codec, nids[i], val);
08c189f2 1931 spec->gen.keep_vref_in_automute = 1;
1a97b7f2
TI
1932 break;
1933 }
1934}
1935
0756f09c
TI
1936static void alc889_fixup_mac_pins(struct hda_codec *codec,
1937 const hda_nid_t *nids, int num_nids)
1a97b7f2
TI
1938{
1939 struct alc_spec *spec = codec->spec;
1a97b7f2
TI
1940 int i;
1941
0756f09c 1942 for (i = 0; i < num_nids; i++) {
1a97b7f2 1943 unsigned int val;
d3f02d60 1944 val = snd_hda_codec_get_pin_target(codec, nids[i]);
1a97b7f2 1945 val |= AC_PINCTL_VREF_50;
cdd03ced 1946 snd_hda_set_pin_ctl(codec, nids[i], val);
1a97b7f2 1947 }
08c189f2 1948 spec->gen.keep_vref_in_automute = 1;
1a97b7f2
TI
1949}
1950
0756f09c
TI
1951/* Set VREF on speaker pins on imac91 */
1952static void alc889_fixup_imac91_vref(struct hda_codec *codec,
1953 const struct hda_fixup *fix, int action)
1954{
1955 static hda_nid_t nids[2] = { 0x18, 0x1a };
1956
1957 if (action == HDA_FIXUP_ACT_INIT)
1958 alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
1959}
1960
1961/* Set VREF on speaker pins on mba21 */
1962static void alc889_fixup_mba21_vref(struct hda_codec *codec,
1963 const struct hda_fixup *fix, int action)
1964{
1965 static hda_nid_t nids[2] = { 0x18, 0x19 };
1966
1967 if (action == HDA_FIXUP_ACT_INIT)
1968 alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
1969}
1970
e427c237 1971/* Don't take HP output as primary
d9111496
FLVC
1972 * Strangely, the speaker output doesn't work on Vaio Z and some Vaio
1973 * all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05
e427c237
TI
1974 */
1975static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
1727a771 1976 const struct hda_fixup *fix, int action)
e427c237
TI
1977{
1978 struct alc_spec *spec = codec->spec;
da96fb5b 1979 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
08c189f2 1980 spec->gen.no_primary_hp = 1;
da96fb5b
TI
1981 spec->gen.no_multi_io = 1;
1982 }
e427c237
TI
1983}
1984
eb9ca3ab
TI
1985static void alc_fixup_bass_chmap(struct hda_codec *codec,
1986 const struct hda_fixup *fix, int action);
1987
1727a771 1988static const struct hda_fixup alc882_fixups[] = {
5c0ebfbe 1989 [ALC882_FIXUP_ABIT_AW9D_MAX] = {
1727a771
TI
1990 .type = HDA_FIXUP_PINS,
1991 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
1992 { 0x15, 0x01080104 }, /* side */
1993 { 0x16, 0x01011012 }, /* rear */
1994 { 0x17, 0x01016011 }, /* clfe */
2785591a 1995 { }
145a902b
DH
1996 }
1997 },
5c0ebfbe 1998 [ALC882_FIXUP_LENOVO_Y530] = {
1727a771
TI
1999 .type = HDA_FIXUP_PINS,
2000 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
2001 { 0x15, 0x99130112 }, /* rear int speakers */
2002 { 0x16, 0x99130111 }, /* subwoofer */
ac612407
DH
2003 { }
2004 }
2005 },
5c0ebfbe 2006 [ALC882_FIXUP_PB_M5210] = {
fd108215
TI
2007 .type = HDA_FIXUP_PINCTLS,
2008 .v.pins = (const struct hda_pintbl[]) {
2009 { 0x19, PIN_VREF50 },
357f915e
KY
2010 {}
2011 }
2012 },
5c0ebfbe 2013 [ALC882_FIXUP_ACER_ASPIRE_7736] = {
1727a771 2014 .type = HDA_FIXUP_FUNC,
23d30f28 2015 .v.func = alc_fixup_sku_ignore,
6981d184 2016 },
5c0ebfbe 2017 [ALC882_FIXUP_ASUS_W90V] = {
1727a771
TI
2018 .type = HDA_FIXUP_PINS,
2019 .v.pins = (const struct hda_pintbl[]) {
5cdf745e
TI
2020 { 0x16, 0x99130110 }, /* fix sequence for CLFE */
2021 { }
2022 }
2023 },
8f239214 2024 [ALC889_FIXUP_CD] = {
1727a771
TI
2025 .type = HDA_FIXUP_PINS,
2026 .v.pins = (const struct hda_pintbl[]) {
8f239214
MB
2027 { 0x1c, 0x993301f0 }, /* CD */
2028 { }
2029 }
2030 },
b2c53e20
DH
2031 [ALC889_FIXUP_FRONT_HP_NO_PRESENCE] = {
2032 .type = HDA_FIXUP_PINS,
2033 .v.pins = (const struct hda_pintbl[]) {
2034 { 0x1b, 0x02214120 }, /* Front HP jack is flaky, disable jack detect */
2035 { }
2036 },
2037 .chained = true,
2038 .chain_id = ALC889_FIXUP_CD,
2039 },
5c0ebfbe 2040 [ALC889_FIXUP_VAIO_TT] = {
1727a771
TI
2041 .type = HDA_FIXUP_PINS,
2042 .v.pins = (const struct hda_pintbl[]) {
5c0ebfbe
TI
2043 { 0x17, 0x90170111 }, /* hidden surround speaker */
2044 { }
2045 }
2046 },
0e7cc2e7 2047 [ALC888_FIXUP_EEE1601] = {
1727a771 2048 .type = HDA_FIXUP_VERBS,
0e7cc2e7
TI
2049 .v.verbs = (const struct hda_verb[]) {
2050 { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
2051 { 0x20, AC_VERB_SET_PROC_COEF, 0x0838 },
2052 { }
2053 }
177943a3
TI
2054 },
2055 [ALC882_FIXUP_EAPD] = {
1727a771 2056 .type = HDA_FIXUP_VERBS,
177943a3
TI
2057 .v.verbs = (const struct hda_verb[]) {
2058 /* change to EAPD mode */
2059 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2060 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
2061 { }
2062 }
2063 },
7a6069bf 2064 [ALC883_FIXUP_EAPD] = {
1727a771 2065 .type = HDA_FIXUP_VERBS,
7a6069bf
TI
2066 .v.verbs = (const struct hda_verb[]) {
2067 /* change to EAPD mode */
2068 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2069 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
2070 { }
2071 }
2072 },
8812c4f9 2073 [ALC883_FIXUP_ACER_EAPD] = {
1727a771 2074 .type = HDA_FIXUP_VERBS,
8812c4f9
TI
2075 .v.verbs = (const struct hda_verb[]) {
2076 /* eanable EAPD on Acer laptops */
2077 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2078 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2079 { }
2080 }
2081 },
1a97b7f2 2082 [ALC882_FIXUP_GPIO1] = {
1727a771 2083 .type = HDA_FIXUP_VERBS,
1a97b7f2
TI
2084 .v.verbs = alc_gpio1_init_verbs,
2085 },
2086 [ALC882_FIXUP_GPIO2] = {
1727a771 2087 .type = HDA_FIXUP_VERBS,
1a97b7f2
TI
2088 .v.verbs = alc_gpio2_init_verbs,
2089 },
eb844d51 2090 [ALC882_FIXUP_GPIO3] = {
1727a771 2091 .type = HDA_FIXUP_VERBS,
eb844d51
TI
2092 .v.verbs = alc_gpio3_init_verbs,
2093 },
68ef0561 2094 [ALC882_FIXUP_ASUS_W2JC] = {
1727a771 2095 .type = HDA_FIXUP_VERBS,
68ef0561
TI
2096 .v.verbs = alc_gpio1_init_verbs,
2097 .chained = true,
2098 .chain_id = ALC882_FIXUP_EAPD,
2099 },
2100 [ALC889_FIXUP_COEF] = {
1727a771 2101 .type = HDA_FIXUP_FUNC,
68ef0561
TI
2102 .v.func = alc889_fixup_coef,
2103 },
c3e837bb 2104 [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
1727a771
TI
2105 .type = HDA_FIXUP_PINS,
2106 .v.pins = (const struct hda_pintbl[]) {
c3e837bb
TI
2107 { 0x16, 0x99130111 }, /* CLFE speaker */
2108 { 0x17, 0x99130112 }, /* surround speaker */
2109 { }
038d4fef
TI
2110 },
2111 .chained = true,
2112 .chain_id = ALC882_FIXUP_GPIO1,
c3e837bb
TI
2113 },
2114 [ALC882_FIXUP_ACER_ASPIRE_8930G] = {
1727a771
TI
2115 .type = HDA_FIXUP_PINS,
2116 .v.pins = (const struct hda_pintbl[]) {
c3e837bb
TI
2117 { 0x16, 0x99130111 }, /* CLFE speaker */
2118 { 0x1b, 0x99130112 }, /* surround speaker */
2119 { }
2120 },
2121 .chained = true,
2122 .chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS,
2123 },
2124 [ALC882_FIXUP_ASPIRE_8930G_VERBS] = {
2125 /* additional init verbs for Acer Aspire 8930G */
1727a771 2126 .type = HDA_FIXUP_VERBS,
c3e837bb
TI
2127 .v.verbs = (const struct hda_verb[]) {
2128 /* Enable all DACs */
2129 /* DAC DISABLE/MUTE 1? */
2130 /* setting bits 1-5 disables DAC nids 0x02-0x06
2131 * apparently. Init=0x38 */
2132 { 0x20, AC_VERB_SET_COEF_INDEX, 0x03 },
2133 { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
2134 /* DAC DISABLE/MUTE 2? */
2135 /* some bit here disables the other DACs.
2136 * Init=0x4900 */
2137 { 0x20, AC_VERB_SET_COEF_INDEX, 0x08 },
2138 { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
2139 /* DMIC fix
2140 * This laptop has a stereo digital microphone.
2141 * The mics are only 1cm apart which makes the stereo
2142 * useless. However, either the mic or the ALC889
2143 * makes the signal become a difference/sum signal
2144 * instead of standard stereo, which is annoying.
2145 * So instead we flip this bit which makes the
2146 * codec replicate the sum signal to both channels,
2147 * turning it into a normal mono mic.
2148 */
2149 /* DMIC_CONTROL? Init value = 0x0001 */
2150 { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
2151 { 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
2152 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2153 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2154 { }
038d4fef
TI
2155 },
2156 .chained = true,
2157 .chain_id = ALC882_FIXUP_GPIO1,
c3e837bb 2158 },
5671087f 2159 [ALC885_FIXUP_MACPRO_GPIO] = {
1727a771 2160 .type = HDA_FIXUP_FUNC,
5671087f
TI
2161 .v.func = alc885_fixup_macpro_gpio,
2162 },
02a237b2 2163 [ALC889_FIXUP_DAC_ROUTE] = {
1727a771 2164 .type = HDA_FIXUP_FUNC,
02a237b2
TI
2165 .v.func = alc889_fixup_dac_route,
2166 },
1a97b7f2 2167 [ALC889_FIXUP_MBP_VREF] = {
1727a771 2168 .type = HDA_FIXUP_FUNC,
1a97b7f2
TI
2169 .v.func = alc889_fixup_mbp_vref,
2170 .chained = true,
2171 .chain_id = ALC882_FIXUP_GPIO1,
2172 },
2173 [ALC889_FIXUP_IMAC91_VREF] = {
1727a771 2174 .type = HDA_FIXUP_FUNC,
1a97b7f2
TI
2175 .v.func = alc889_fixup_imac91_vref,
2176 .chained = true,
2177 .chain_id = ALC882_FIXUP_GPIO1,
2178 },
0756f09c
TI
2179 [ALC889_FIXUP_MBA21_VREF] = {
2180 .type = HDA_FIXUP_FUNC,
2181 .v.func = alc889_fixup_mba21_vref,
2182 .chained = true,
2183 .chain_id = ALC889_FIXUP_MBP_VREF,
2184 },
6e72aa5f 2185 [ALC882_FIXUP_INV_DMIC] = {
1727a771 2186 .type = HDA_FIXUP_FUNC,
6e72aa5f
TI
2187 .v.func = alc_fixup_inv_dmic_0x12,
2188 },
e427c237 2189 [ALC882_FIXUP_NO_PRIMARY_HP] = {
1727a771 2190 .type = HDA_FIXUP_FUNC,
e427c237
TI
2191 .v.func = alc882_fixup_no_primary_hp,
2192 },
1f0bbf03
TI
2193 [ALC887_FIXUP_ASUS_BASS] = {
2194 .type = HDA_FIXUP_PINS,
2195 .v.pins = (const struct hda_pintbl[]) {
2196 {0x16, 0x99130130}, /* bass speaker */
2197 {}
2198 },
eb9ca3ab
TI
2199 .chained = true,
2200 .chain_id = ALC887_FIXUP_BASS_CHMAP,
2201 },
2202 [ALC887_FIXUP_BASS_CHMAP] = {
2203 .type = HDA_FIXUP_FUNC,
2204 .v.func = alc_fixup_bass_chmap,
1f0bbf03 2205 },
ff818c24
TI
2206};
2207
1d045db9 2208static const struct snd_pci_quirk alc882_fixup_tbl[] = {
8812c4f9
TI
2209 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
2210 SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
2211 SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD),
2212 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
2213 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD),
2214 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_FIXUP_ACER_EAPD),
c3e837bb
TI
2215 SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
2216 ALC882_FIXUP_ACER_ASPIRE_4930G),
2217 SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
2218 ALC882_FIXUP_ACER_ASPIRE_4930G),
2219 SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
2220 ALC882_FIXUP_ACER_ASPIRE_8930G),
2221 SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
2222 ALC882_FIXUP_ACER_ASPIRE_8930G),
2223 SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
2224 ALC882_FIXUP_ACER_ASPIRE_4930G),
2225 SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
2226 ALC882_FIXUP_ACER_ASPIRE_4930G),
2227 SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
2228 ALC882_FIXUP_ACER_ASPIRE_4930G),
5c0ebfbe 2229 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
f5c53d89
TI
2230 SND_PCI_QUIRK(0x1025, 0x021e, "Acer Aspire 5739G",
2231 ALC882_FIXUP_ACER_ASPIRE_4930G),
02a237b2 2232 SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
fe97da1f 2233 SND_PCI_QUIRK(0x1025, 0x026b, "Acer Aspire 8940G", ALC882_FIXUP_ACER_ASPIRE_8930G),
ac9b1cdd 2234 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
177943a3 2235 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
5c0ebfbe 2236 SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
68ef0561 2237 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
0e7cc2e7 2238 SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
1f0bbf03 2239 SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
ac9b1cdd 2240 SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
e427c237 2241 SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
12e31a78 2242 SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
5671087f
TI
2243
2244 /* All Apple entries are in codec SSIDs */
1a97b7f2
TI
2245 SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
2246 SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
2247 SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
5671087f
TI
2248 SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO),
2249 SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
2250 SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
1a97b7f2
TI
2251 SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
2252 SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
5671087f 2253 SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
1a97b7f2 2254 SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF),
0756f09c 2255 SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF),
1a97b7f2
TI
2256 SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
2257 SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
5671087f 2258 SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
1a97b7f2
TI
2259 SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
2260 SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
2261 SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
29ebe402 2262 SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO),
05193639 2263 SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
1a97b7f2
TI
2264 SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
2265 SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
2266 SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
5671087f 2267
7a6069bf 2268 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
bca40138 2269 SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
eb844d51 2270 SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
b2c53e20 2271 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
5c0ebfbe 2272 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
7a6069bf
TI
2273 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
2274 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
ac9b1cdd 2275 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
68ef0561 2276 SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_FIXUP_COEF),
ff818c24
TI
2277 {}
2278};
2279
1727a771 2280static const struct hda_model_fixup alc882_fixup_models[] = {
912093bc
TI
2281 {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"},
2282 {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"},
2283 {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"},
6e72aa5f 2284 {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"},
e427c237 2285 {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"},
912093bc
TI
2286 {}
2287};
2288
f6a92248 2289/*
1d045db9 2290 * BIOS auto configuration
f6a92248 2291 */
1d045db9
TI
2292/* almost identical with ALC880 parser... */
2293static int alc882_parse_auto_config(struct hda_codec *codec)
2294{
1d045db9 2295 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
3e6179b8
TI
2296 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2297 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
1d045db9 2298}
b896b4eb 2299
1d045db9
TI
2300/*
2301 */
1d045db9 2302static int patch_alc882(struct hda_codec *codec)
f6a92248
KY
2303{
2304 struct alc_spec *spec;
1a97b7f2 2305 int err;
f6a92248 2306
3de95173
TI
2307 err = alc_alloc_spec(codec, 0x0b);
2308 if (err < 0)
2309 return err;
f6a92248 2310
3de95173 2311 spec = codec->spec;
1f0f4b80 2312
1d045db9
TI
2313 switch (codec->vendor_id) {
2314 case 0x10ec0882:
2315 case 0x10ec0885:
2316 break;
2317 default:
2318 /* ALC883 and variants */
2319 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
2320 break;
c793bec5 2321 }
977ddd6b 2322
1727a771 2323 snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
912093bc 2324 alc882_fixups);
1727a771 2325 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
ff818c24 2326
1d045db9
TI
2327 alc_auto_parse_customize_define(codec);
2328
7504b6cd
TI
2329 if (has_cdefine_beep(codec))
2330 spec->gen.beep_nid = 0x01;
2331
1a97b7f2
TI
2332 /* automatic parse from the BIOS config */
2333 err = alc882_parse_auto_config(codec);
2334 if (err < 0)
2335 goto error;
f6a92248 2336
7504b6cd 2337 if (!spec->gen.no_analog && spec->gen.beep_nid)
1d045db9 2338 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
f6a92248
KY
2339
2340 codec->patch_ops = alc_patch_ops;
bf1b0225 2341
1727a771 2342 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 2343
f6a92248 2344 return 0;
e16fb6d1
TI
2345
2346 error:
2347 alc_free(codec);
2348 return err;
f6a92248
KY
2349}
2350
df694daa 2351
df694daa 2352/*
1d045db9 2353 * ALC262 support
df694daa 2354 */
1d045db9 2355static int alc262_parse_auto_config(struct hda_codec *codec)
df694daa 2356{
1d045db9 2357 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
3e6179b8
TI
2358 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2359 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
df694daa
KY
2360}
2361
df694daa 2362/*
1d045db9 2363 * Pin config fixes
df694daa 2364 */
cfc9b06f 2365enum {
ea4e7af1 2366 ALC262_FIXUP_FSC_H270,
7513e6da 2367 ALC262_FIXUP_FSC_S7110,
ea4e7af1
TI
2368 ALC262_FIXUP_HP_Z200,
2369 ALC262_FIXUP_TYAN,
c470150c 2370 ALC262_FIXUP_LENOVO_3000,
b42590b8
TI
2371 ALC262_FIXUP_BENQ,
2372 ALC262_FIXUP_BENQ_T31,
6e72aa5f 2373 ALC262_FIXUP_INV_DMIC,
b5c6611f 2374 ALC262_FIXUP_INTEL_BAYLEYBAY,
cfc9b06f
TI
2375};
2376
1727a771 2377static const struct hda_fixup alc262_fixups[] = {
ea4e7af1 2378 [ALC262_FIXUP_FSC_H270] = {
1727a771
TI
2379 .type = HDA_FIXUP_PINS,
2380 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
2381 { 0x14, 0x99130110 }, /* speaker */
2382 { 0x15, 0x0221142f }, /* front HP */
2383 { 0x1b, 0x0121141f }, /* rear HP */
2384 { }
2385 }
2386 },
7513e6da
TI
2387 [ALC262_FIXUP_FSC_S7110] = {
2388 .type = HDA_FIXUP_PINS,
2389 .v.pins = (const struct hda_pintbl[]) {
2390 { 0x15, 0x90170110 }, /* speaker */
2391 { }
2392 },
2393 .chained = true,
2394 .chain_id = ALC262_FIXUP_BENQ,
2395 },
ea4e7af1 2396 [ALC262_FIXUP_HP_Z200] = {
1727a771
TI
2397 .type = HDA_FIXUP_PINS,
2398 .v.pins = (const struct hda_pintbl[]) {
1d045db9 2399 { 0x16, 0x99130120 }, /* internal speaker */
73413b12
TI
2400 { }
2401 }
cfc9b06f 2402 },
ea4e7af1 2403 [ALC262_FIXUP_TYAN] = {
1727a771
TI
2404 .type = HDA_FIXUP_PINS,
2405 .v.pins = (const struct hda_pintbl[]) {
ea4e7af1
TI
2406 { 0x14, 0x1993e1f0 }, /* int AUX */
2407 { }
2408 }
2409 },
c470150c 2410 [ALC262_FIXUP_LENOVO_3000] = {
fd108215
TI
2411 .type = HDA_FIXUP_PINCTLS,
2412 .v.pins = (const struct hda_pintbl[]) {
2413 { 0x19, PIN_VREF50 },
b42590b8
TI
2414 {}
2415 },
2416 .chained = true,
2417 .chain_id = ALC262_FIXUP_BENQ,
2418 },
2419 [ALC262_FIXUP_BENQ] = {
1727a771 2420 .type = HDA_FIXUP_VERBS,
b42590b8 2421 .v.verbs = (const struct hda_verb[]) {
c470150c
TI
2422 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2423 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
2424 {}
2425 }
2426 },
b42590b8 2427 [ALC262_FIXUP_BENQ_T31] = {
1727a771 2428 .type = HDA_FIXUP_VERBS,
b42590b8
TI
2429 .v.verbs = (const struct hda_verb[]) {
2430 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2431 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2432 {}
2433 }
2434 },
6e72aa5f 2435 [ALC262_FIXUP_INV_DMIC] = {
1727a771 2436 .type = HDA_FIXUP_FUNC,
6e72aa5f
TI
2437 .v.func = alc_fixup_inv_dmic_0x12,
2438 },
b5c6611f
ML
2439 [ALC262_FIXUP_INTEL_BAYLEYBAY] = {
2440 .type = HDA_FIXUP_FUNC,
2441 .v.func = alc_fixup_no_depop_delay,
2442 },
cfc9b06f
TI
2443};
2444
1d045db9 2445static const struct snd_pci_quirk alc262_fixup_tbl[] = {
ea4e7af1 2446 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
7513e6da 2447 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110),
3dcd3be3 2448 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
ea4e7af1
TI
2449 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
2450 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
c470150c 2451 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
b42590b8
TI
2452 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
2453 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
b5c6611f 2454 SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY),
cfc9b06f
TI
2455 {}
2456};
df694daa 2457
1727a771 2458static const struct hda_model_fixup alc262_fixup_models[] = {
6e72aa5f
TI
2459 {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"},
2460 {}
2461};
1d045db9 2462
1d045db9
TI
2463/*
2464 */
1d045db9 2465static int patch_alc262(struct hda_codec *codec)
df694daa
KY
2466{
2467 struct alc_spec *spec;
df694daa
KY
2468 int err;
2469
3de95173
TI
2470 err = alc_alloc_spec(codec, 0x0b);
2471 if (err < 0)
2472 return err;
df694daa 2473
3de95173 2474 spec = codec->spec;
08c189f2 2475 spec->gen.shared_mic_vref_pin = 0x18;
1d045db9
TI
2476
2477#if 0
2478 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
2479 * under-run
2480 */
2481 {
2482 int tmp;
2483 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
2484 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
2485 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
2486 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
2487 }
2488#endif
1d045db9
TI
2489 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
2490
1727a771 2491 snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl,
6e72aa5f 2492 alc262_fixups);
1727a771 2493 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
9c7f852e 2494
af741c15
TI
2495 alc_auto_parse_customize_define(codec);
2496
7504b6cd
TI
2497 if (has_cdefine_beep(codec))
2498 spec->gen.beep_nid = 0x01;
2499
42399f7a
TI
2500 /* automatic parse from the BIOS config */
2501 err = alc262_parse_auto_config(codec);
2502 if (err < 0)
2503 goto error;
df694daa 2504
7504b6cd 2505 if (!spec->gen.no_analog && spec->gen.beep_nid)
1d045db9 2506 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
2134ea4f 2507
df694daa 2508 codec->patch_ops = alc_patch_ops;
1d045db9
TI
2509 spec->shutup = alc_eapd_shutup;
2510
1727a771 2511 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 2512
1da177e4 2513 return 0;
e16fb6d1
TI
2514
2515 error:
2516 alc_free(codec);
2517 return err;
1da177e4
LT
2518}
2519
f32610ed 2520/*
1d045db9 2521 * ALC268
f32610ed 2522 */
1d045db9
TI
2523/* bind Beep switches of both NID 0x0f and 0x10 */
2524static const struct hda_bind_ctls alc268_bind_beep_sw = {
2525 .ops = &snd_hda_bind_sw,
2526 .values = {
2527 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
2528 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
2529 0
2530 },
f32610ed
JS
2531};
2532
1d045db9
TI
2533static const struct snd_kcontrol_new alc268_beep_mixer[] = {
2534 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
2535 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
2536 { }
f32610ed
JS
2537};
2538
1d045db9
TI
2539/* set PCBEEP vol = 0, mute connections */
2540static const struct hda_verb alc268_beep_init_verbs[] = {
2541 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2542 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2543 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2544 { }
f32610ed
JS
2545};
2546
6e72aa5f
TI
2547enum {
2548 ALC268_FIXUP_INV_DMIC,
cb766404 2549 ALC268_FIXUP_HP_EAPD,
24eff328 2550 ALC268_FIXUP_SPDIF,
6e72aa5f
TI
2551};
2552
1727a771 2553static const struct hda_fixup alc268_fixups[] = {
6e72aa5f 2554 [ALC268_FIXUP_INV_DMIC] = {
1727a771 2555 .type = HDA_FIXUP_FUNC,
6e72aa5f
TI
2556 .v.func = alc_fixup_inv_dmic_0x12,
2557 },
cb766404 2558 [ALC268_FIXUP_HP_EAPD] = {
1727a771 2559 .type = HDA_FIXUP_VERBS,
cb766404
TI
2560 .v.verbs = (const struct hda_verb[]) {
2561 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
2562 {}
2563 }
2564 },
24eff328
TI
2565 [ALC268_FIXUP_SPDIF] = {
2566 .type = HDA_FIXUP_PINS,
2567 .v.pins = (const struct hda_pintbl[]) {
2568 { 0x1e, 0x014b1180 }, /* enable SPDIF out */
2569 {}
2570 }
2571 },
6e72aa5f
TI
2572};
2573
1727a771 2574static const struct hda_model_fixup alc268_fixup_models[] = {
6e72aa5f 2575 {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
cb766404
TI
2576 {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
2577 {}
2578};
2579
2580static const struct snd_pci_quirk alc268_fixup_tbl[] = {
24eff328 2581 SND_PCI_QUIRK(0x1025, 0x0139, "Acer TravelMate 6293", ALC268_FIXUP_SPDIF),
fcd8f3b1 2582 SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
cb766404
TI
2583 /* below is codec SSID since multiple Toshiba laptops have the
2584 * same PCI SSID 1179:ff00
2585 */
2586 SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
6e72aa5f
TI
2587 {}
2588};
2589
f32610ed
JS
2590/*
2591 * BIOS auto configuration
2592 */
1d045db9 2593static int alc268_parse_auto_config(struct hda_codec *codec)
f32610ed 2594{
3e6179b8 2595 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
7504b6cd 2596 return alc_parse_auto_config(codec, NULL, alc268_ssids);
f32610ed
JS
2597}
2598
1d045db9
TI
2599/*
2600 */
1d045db9 2601static int patch_alc268(struct hda_codec *codec)
f32610ed
JS
2602{
2603 struct alc_spec *spec;
7504b6cd 2604 int err;
f32610ed 2605
1d045db9 2606 /* ALC268 has no aa-loopback mixer */
3de95173
TI
2607 err = alc_alloc_spec(codec, 0);
2608 if (err < 0)
2609 return err;
2610
2611 spec = codec->spec;
7504b6cd 2612 spec->gen.beep_nid = 0x01;
1f0f4b80 2613
1727a771
TI
2614 snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
2615 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
6e72aa5f 2616
6ebb8053
TI
2617 /* automatic parse from the BIOS config */
2618 err = alc268_parse_auto_config(codec);
e16fb6d1
TI
2619 if (err < 0)
2620 goto error;
f32610ed 2621
7504b6cd
TI
2622 if (err > 0 && !spec->gen.no_analog &&
2623 spec->gen.autocfg.speaker_pins[0] != 0x1d) {
2624 add_mixer(spec, alc268_beep_mixer);
2625 snd_hda_add_verbs(codec, alc268_beep_init_verbs);
1d045db9
TI
2626 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
2627 /* override the amp caps for beep generator */
2628 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
2629 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
2630 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
2631 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2632 (0 << AC_AMPCAP_MUTE_SHIFT));
2f893286
KY
2633 }
2634
f32610ed 2635 codec->patch_ops = alc_patch_ops;
1c716153 2636 spec->shutup = alc_eapd_shutup;
1d045db9 2637
1727a771 2638 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
6e72aa5f 2639
f32610ed 2640 return 0;
e16fb6d1
TI
2641
2642 error:
2643 alc_free(codec);
2644 return err;
f32610ed
JS
2645}
2646
bc9f98a9 2647/*
1d045db9 2648 * ALC269
bc9f98a9 2649 */
08c189f2
TI
2650
2651static int playback_pcm_open(struct hda_pcm_stream *hinfo,
2652 struct hda_codec *codec,
2653 struct snd_pcm_substream *substream)
2654{
2655 struct hda_gen_spec *spec = codec->spec;
2656 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2657 hinfo);
2658}
2659
2660static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
2661 struct hda_codec *codec,
2662 unsigned int stream_tag,
2663 unsigned int format,
2664 struct snd_pcm_substream *substream)
2665{
2666 struct hda_gen_spec *spec = codec->spec;
2667 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2668 stream_tag, format, substream);
2669}
2670
2671static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
2672 struct hda_codec *codec,
2673 struct snd_pcm_substream *substream)
2674{
2675 struct hda_gen_spec *spec = codec->spec;
2676 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2677}
2678
1d045db9
TI
2679static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
2680 .substreams = 1,
2681 .channels_min = 2,
2682 .channels_max = 8,
2683 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
2684 /* NID is set in alc_build_pcms */
2685 .ops = {
08c189f2
TI
2686 .open = playback_pcm_open,
2687 .prepare = playback_pcm_prepare,
2688 .cleanup = playback_pcm_cleanup
bc9f98a9
KY
2689 },
2690};
2691
1d045db9
TI
2692static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
2693 .substreams = 1,
2694 .channels_min = 2,
2695 .channels_max = 2,
2696 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
2697 /* NID is set in alc_build_pcms */
bc9f98a9 2698};
291702f0 2699
1d045db9
TI
2700/* different alc269-variants */
2701enum {
2702 ALC269_TYPE_ALC269VA,
2703 ALC269_TYPE_ALC269VB,
2704 ALC269_TYPE_ALC269VC,
adcc70b2 2705 ALC269_TYPE_ALC269VD,
065380f0
KY
2706 ALC269_TYPE_ALC280,
2707 ALC269_TYPE_ALC282,
2af02be7 2708 ALC269_TYPE_ALC283,
065380f0 2709 ALC269_TYPE_ALC284,
161ebf29 2710 ALC269_TYPE_ALC285,
7fc7d047 2711 ALC269_TYPE_ALC286,
1d04c9de 2712 ALC269_TYPE_ALC255,
bc9f98a9
KY
2713};
2714
2715/*
1d045db9 2716 * BIOS auto configuration
bc9f98a9 2717 */
1d045db9
TI
2718static int alc269_parse_auto_config(struct hda_codec *codec)
2719{
1d045db9 2720 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
3e6179b8
TI
2721 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
2722 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2723 struct alc_spec *spec = codec->spec;
adcc70b2
KY
2724 const hda_nid_t *ssids;
2725
2726 switch (spec->codec_variant) {
2727 case ALC269_TYPE_ALC269VA:
2728 case ALC269_TYPE_ALC269VC:
065380f0
KY
2729 case ALC269_TYPE_ALC280:
2730 case ALC269_TYPE_ALC284:
161ebf29 2731 case ALC269_TYPE_ALC285:
adcc70b2
KY
2732 ssids = alc269va_ssids;
2733 break;
2734 case ALC269_TYPE_ALC269VB:
2735 case ALC269_TYPE_ALC269VD:
065380f0 2736 case ALC269_TYPE_ALC282:
2af02be7 2737 case ALC269_TYPE_ALC283:
7fc7d047 2738 case ALC269_TYPE_ALC286:
1d04c9de 2739 case ALC269_TYPE_ALC255:
adcc70b2
KY
2740 ssids = alc269_ssids;
2741 break;
2742 default:
2743 ssids = alc269_ssids;
2744 break;
2745 }
bc9f98a9 2746
3e6179b8 2747 return alc_parse_auto_config(codec, alc269_ignore, ssids);
1d045db9 2748}
bc9f98a9 2749
1387e2d1 2750static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
1d045db9
TI
2751{
2752 int val = alc_read_coef_idx(codec, 0x04);
2753 if (power_up)
2754 val |= 1 << 11;
2755 else
2756 val &= ~(1 << 11);
2757 alc_write_coef_idx(codec, 0x04, val);
2758}
291702f0 2759
1d045db9
TI
2760static void alc269_shutup(struct hda_codec *codec)
2761{
adcc70b2
KY
2762 struct alc_spec *spec = codec->spec;
2763
1387e2d1
KY
2764 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
2765 alc269vb_toggle_power_output(codec, 0);
2766 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
2767 (alc_get_coef0(codec) & 0x00ff) == 0x018) {
1d045db9
TI
2768 msleep(150);
2769 }
9bfb2844 2770 snd_hda_shutup_pins(codec);
1d045db9 2771}
291702f0 2772
2af02be7
KY
2773static void alc283_init(struct hda_codec *codec)
2774{
2775 struct alc_spec *spec = codec->spec;
2776 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
2777 bool hp_pin_sense;
2778 int val;
2779
2780 if (!hp_pin)
2781 return;
2782 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
2783
2784 /* Index 0x43 Direct Drive HP AMP LPM Control 1 */
2785 /* Headphone capless set to high power mode */
2786 alc_write_coef_idx(codec, 0x43, 0x9004);
2787
2788 snd_hda_codec_write(codec, hp_pin, 0,
2789 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
2790
2791 if (hp_pin_sense)
2792 msleep(85);
2793
2794 snd_hda_codec_write(codec, hp_pin, 0,
2795 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
2796
2797 if (hp_pin_sense)
2798 msleep(85);
2799 /* Index 0x46 Combo jack auto switch control 2 */
2800 /* 3k pull low control for Headset jack. */
2801 val = alc_read_coef_idx(codec, 0x46);
2802 alc_write_coef_idx(codec, 0x46, val & ~(3 << 12));
2803 /* Headphone capless set to normal mode */
2804 alc_write_coef_idx(codec, 0x43, 0x9614);
2805}
2806
2807static void alc283_shutup(struct hda_codec *codec)
2808{
2809 struct alc_spec *spec = codec->spec;
2810 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
2811 bool hp_pin_sense;
2812 int val;
2813
2814 if (!hp_pin) {
2815 alc269_shutup(codec);
2816 return;
2817 }
2818
2819 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
2820
2821 alc_write_coef_idx(codec, 0x43, 0x9004);
2822
2823 snd_hda_codec_write(codec, hp_pin, 0,
2824 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
2825
2826 if (hp_pin_sense)
88011c09 2827 msleep(100);
2af02be7
KY
2828
2829 snd_hda_codec_write(codec, hp_pin, 0,
2830 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
2831
2832 val = alc_read_coef_idx(codec, 0x46);
2833 alc_write_coef_idx(codec, 0x46, val | (3 << 12));
2834
2835 if (hp_pin_sense)
88011c09 2836 msleep(100);
2af02be7
KY
2837 snd_hda_shutup_pins(codec);
2838 alc_write_coef_idx(codec, 0x43, 0x9614);
2839}
2840
ad60d502
KY
2841static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
2842 unsigned int val)
2843{
2844 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
2845 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val & 0xffff); /* LSB */
2846 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val >> 16); /* MSB */
2847}
2848
2849static int alc5505_coef_get(struct hda_codec *codec, unsigned int index_reg)
2850{
2851 unsigned int val;
2852
2853 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
2854 val = snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
2855 & 0xffff;
2856 val |= snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
2857 << 16;
2858 return val;
2859}
2860
2861static void alc5505_dsp_halt(struct hda_codec *codec)
2862{
2863 unsigned int val;
2864
2865 alc5505_coef_set(codec, 0x3000, 0x000c); /* DSP CPU stop */
2866 alc5505_coef_set(codec, 0x880c, 0x0008); /* DDR enter self refresh */
2867 alc5505_coef_set(codec, 0x61c0, 0x11110080); /* Clock control for PLL and CPU */
2868 alc5505_coef_set(codec, 0x6230, 0xfc0d4011); /* Disable Input OP */
2869 alc5505_coef_set(codec, 0x61b4, 0x040a2b03); /* Stop PLL2 */
2870 alc5505_coef_set(codec, 0x61b0, 0x00005b17); /* Stop PLL1 */
2871 alc5505_coef_set(codec, 0x61b8, 0x04133303); /* Stop PLL3 */
2872 val = alc5505_coef_get(codec, 0x6220);
2873 alc5505_coef_set(codec, 0x6220, (val | 0x3000)); /* switch Ringbuffer clock to DBUS clock */
2874}
2875
2876static void alc5505_dsp_back_from_halt(struct hda_codec *codec)
2877{
2878 alc5505_coef_set(codec, 0x61b8, 0x04133302);
2879 alc5505_coef_set(codec, 0x61b0, 0x00005b16);
2880 alc5505_coef_set(codec, 0x61b4, 0x040a2b02);
2881 alc5505_coef_set(codec, 0x6230, 0xf80d4011);
2882 alc5505_coef_set(codec, 0x6220, 0x2002010f);
2883 alc5505_coef_set(codec, 0x880c, 0x00000004);
2884}
2885
2886static void alc5505_dsp_init(struct hda_codec *codec)
2887{
2888 unsigned int val;
2889
2890 alc5505_dsp_halt(codec);
2891 alc5505_dsp_back_from_halt(codec);
2892 alc5505_coef_set(codec, 0x61b0, 0x5b14); /* PLL1 control */
2893 alc5505_coef_set(codec, 0x61b0, 0x5b16);
2894 alc5505_coef_set(codec, 0x61b4, 0x04132b00); /* PLL2 control */
2895 alc5505_coef_set(codec, 0x61b4, 0x04132b02);
2896 alc5505_coef_set(codec, 0x61b8, 0x041f3300); /* PLL3 control*/
2897 alc5505_coef_set(codec, 0x61b8, 0x041f3302);
2898 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_CODEC_RESET, 0); /* Function reset */
2899 alc5505_coef_set(codec, 0x61b8, 0x041b3302);
2900 alc5505_coef_set(codec, 0x61b8, 0x04173302);
2901 alc5505_coef_set(codec, 0x61b8, 0x04163302);
2902 alc5505_coef_set(codec, 0x8800, 0x348b328b); /* DRAM control */
2903 alc5505_coef_set(codec, 0x8808, 0x00020022); /* DRAM control */
2904 alc5505_coef_set(codec, 0x8818, 0x00000400); /* DRAM control */
2905
2906 val = alc5505_coef_get(codec, 0x6200) >> 16; /* Read revision ID */
2907 if (val <= 3)
2908 alc5505_coef_set(codec, 0x6220, 0x2002010f); /* I/O PAD Configuration */
2909 else
2910 alc5505_coef_set(codec, 0x6220, 0x6002018f);
2911
2912 alc5505_coef_set(codec, 0x61ac, 0x055525f0); /**/
2913 alc5505_coef_set(codec, 0x61c0, 0x12230080); /* Clock control */
2914 alc5505_coef_set(codec, 0x61b4, 0x040e2b02); /* PLL2 control */
2915 alc5505_coef_set(codec, 0x61bc, 0x010234f8); /* OSC Control */
2916 alc5505_coef_set(codec, 0x880c, 0x00000004); /* DRAM Function control */
2917 alc5505_coef_set(codec, 0x880c, 0x00000003);
2918 alc5505_coef_set(codec, 0x880c, 0x00000010);
cd63a5ff
TI
2919
2920#ifdef HALT_REALTEK_ALC5505
2921 alc5505_dsp_halt(codec);
2922#endif
ad60d502
KY
2923}
2924
cd63a5ff
TI
2925#ifdef HALT_REALTEK_ALC5505
2926#define alc5505_dsp_suspend(codec) /* NOP */
2927#define alc5505_dsp_resume(codec) /* NOP */
2928#else
2929#define alc5505_dsp_suspend(codec) alc5505_dsp_halt(codec)
2930#define alc5505_dsp_resume(codec) alc5505_dsp_back_from_halt(codec)
2931#endif
2932
2a43952a 2933#ifdef CONFIG_PM
ad60d502
KY
2934static int alc269_suspend(struct hda_codec *codec)
2935{
2936 struct alc_spec *spec = codec->spec;
2937
2938 if (spec->has_alc5505_dsp)
cd63a5ff 2939 alc5505_dsp_suspend(codec);
ad60d502
KY
2940 return alc_suspend(codec);
2941}
2942
1d045db9
TI
2943static int alc269_resume(struct hda_codec *codec)
2944{
adcc70b2
KY
2945 struct alc_spec *spec = codec->spec;
2946
1387e2d1
KY
2947 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
2948 alc269vb_toggle_power_output(codec, 0);
2949 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
adcc70b2 2950 (alc_get_coef0(codec) & 0x00ff) == 0x018) {
1d045db9
TI
2951 msleep(150);
2952 }
8c427226 2953
1d045db9 2954 codec->patch_ops.init(codec);
f1d4e28b 2955
1387e2d1
KY
2956 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
2957 alc269vb_toggle_power_output(codec, 1);
2958 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
adcc70b2 2959 (alc_get_coef0(codec) & 0x00ff) == 0x017) {
1d045db9
TI
2960 msleep(200);
2961 }
f1d4e28b 2962
1d045db9
TI
2963 snd_hda_codec_resume_amp(codec);
2964 snd_hda_codec_resume_cache(codec);
0623a889 2965 alc_inv_dmic_sync(codec, true);
1d045db9 2966 hda_call_check_power_status(codec, 0x01);
ad60d502 2967 if (spec->has_alc5505_dsp)
cd63a5ff 2968 alc5505_dsp_resume(codec);
c5177c86 2969
1d045db9
TI
2970 return 0;
2971}
2a43952a 2972#endif /* CONFIG_PM */
f1d4e28b 2973
108cc108 2974static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec,
1727a771 2975 const struct hda_fixup *fix, int action)
108cc108
DH
2976{
2977 struct alc_spec *spec = codec->spec;
2978
1727a771 2979 if (action == HDA_FIXUP_ACT_PRE_PROBE)
108cc108
DH
2980 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
2981}
2982
1d045db9 2983static void alc269_fixup_hweq(struct hda_codec *codec,
1727a771 2984 const struct hda_fixup *fix, int action)
1d045db9
TI
2985{
2986 int coef;
f1d4e28b 2987
1727a771 2988 if (action != HDA_FIXUP_ACT_INIT)
1d045db9
TI
2989 return;
2990 coef = alc_read_coef_idx(codec, 0x1e);
2991 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
2992}
f1d4e28b 2993
7c478f03
DH
2994static void alc269_fixup_headset_mic(struct hda_codec *codec,
2995 const struct hda_fixup *fix, int action)
2996{
2997 struct alc_spec *spec = codec->spec;
2998
2999 if (action == HDA_FIXUP_ACT_PRE_PROBE)
3000 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
3001}
3002
1d045db9 3003static void alc271_fixup_dmic(struct hda_codec *codec,
1727a771 3004 const struct hda_fixup *fix, int action)
1d045db9
TI
3005{
3006 static const struct hda_verb verbs[] = {
3007 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
3008 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
3009 {}
3010 };
3011 unsigned int cfg;
f1d4e28b 3012
42397004
DR
3013 if (strcmp(codec->chip_name, "ALC271X") &&
3014 strcmp(codec->chip_name, "ALC269VB"))
1d045db9
TI
3015 return;
3016 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
3017 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
3018 snd_hda_sequence_write(codec, verbs);
3019}
f1d4e28b 3020
017f2a10 3021static void alc269_fixup_pcm_44k(struct hda_codec *codec,
1727a771 3022 const struct hda_fixup *fix, int action)
017f2a10
TI
3023{
3024 struct alc_spec *spec = codec->spec;
3025
1727a771 3026 if (action != HDA_FIXUP_ACT_PROBE)
017f2a10
TI
3027 return;
3028
3029 /* Due to a hardware problem on Lenovo Ideadpad, we need to
3030 * fix the sample rate of analog I/O to 44.1kHz
3031 */
08c189f2
TI
3032 spec->gen.stream_analog_playback = &alc269_44k_pcm_analog_playback;
3033 spec->gen.stream_analog_capture = &alc269_44k_pcm_analog_capture;
017f2a10
TI
3034}
3035
adabb3ec 3036static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
1727a771 3037 const struct hda_fixup *fix, int action)
adabb3ec
TI
3038{
3039 int coef;
3040
1727a771 3041 if (action != HDA_FIXUP_ACT_INIT)
adabb3ec
TI
3042 return;
3043 /* The digital-mic unit sends PDM (differential signal) instead of
3044 * the standard PCM, thus you can't record a valid mono stream as is.
3045 * Below is a workaround specific to ALC269 to control the dmic
3046 * signal source as mono.
3047 */
3048 coef = alc_read_coef_idx(codec, 0x07);
3049 alc_write_coef_idx(codec, 0x07, coef | 0x80);
3050}
3051
24519911
TI
3052static void alc269_quanta_automute(struct hda_codec *codec)
3053{
08c189f2 3054 snd_hda_gen_update_outputs(codec);
24519911
TI
3055
3056 snd_hda_codec_write(codec, 0x20, 0,
3057 AC_VERB_SET_COEF_INDEX, 0x0c);
3058 snd_hda_codec_write(codec, 0x20, 0,
3059 AC_VERB_SET_PROC_COEF, 0x680);
3060
3061 snd_hda_codec_write(codec, 0x20, 0,
3062 AC_VERB_SET_COEF_INDEX, 0x0c);
3063 snd_hda_codec_write(codec, 0x20, 0,
3064 AC_VERB_SET_PROC_COEF, 0x480);
3065}
3066
3067static void alc269_fixup_quanta_mute(struct hda_codec *codec,
1727a771 3068 const struct hda_fixup *fix, int action)
24519911
TI
3069{
3070 struct alc_spec *spec = codec->spec;
1727a771 3071 if (action != HDA_FIXUP_ACT_PROBE)
24519911 3072 return;
08c189f2 3073 spec->gen.automute_hook = alc269_quanta_automute;
24519911
TI
3074}
3075
d240d1dc
DH
3076static void alc269_x101_hp_automute_hook(struct hda_codec *codec,
3077 struct hda_jack_tbl *jack)
3078{
3079 struct alc_spec *spec = codec->spec;
3080 int vref;
3081 msleep(200);
3082 snd_hda_gen_hp_automute(codec, jack);
3083
3084 vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
3085 msleep(100);
3086 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3087 vref);
3088 msleep(500);
3089 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3090 vref);
3091}
3092
3093static void alc269_fixup_x101_headset_mic(struct hda_codec *codec,
3094 const struct hda_fixup *fix, int action)
3095{
3096 struct alc_spec *spec = codec->spec;
3097 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3098 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
3099 spec->gen.hp_automute_hook = alc269_x101_hp_automute_hook;
3100 }
3101}
3102
3103
08fb0d0e
TI
3104/* update mute-LED according to the speaker mute state via mic VREF pin */
3105static void alc269_fixup_mic_mute_hook(void *private_data, int enabled)
6d3cd5d4
DH
3106{
3107 struct hda_codec *codec = private_data;
08fb0d0e
TI
3108 struct alc_spec *spec = codec->spec;
3109 unsigned int pinval;
3110
3111 if (spec->mute_led_polarity)
3112 enabled = !enabled;
3113 pinval = AC_PINCTL_IN_EN |
3114 (enabled ? AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80);
3115 if (spec->mute_led_nid)
3116 snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval);
6d3cd5d4
DH
3117}
3118
d5b6b65e
DH
3119/* Make sure the led works even in runtime suspend */
3120static unsigned int led_power_filter(struct hda_codec *codec,
3121 hda_nid_t nid,
3122 unsigned int power_state)
3123{
3124 struct alc_spec *spec = codec->spec;
3125
3126 if (power_state != AC_PWRST_D3 || nid != spec->mute_led_nid)
3127 return power_state;
3128
3129 /* Set pin ctl again, it might have just been set to 0 */
3130 snd_hda_set_pin_ctl(codec, nid,
3131 snd_hda_codec_get_pin_target(codec, nid));
3132
3133 return AC_PWRST_D0;
3134}
3135
08fb0d0e
TI
3136static void alc269_fixup_hp_mute_led(struct hda_codec *codec,
3137 const struct hda_fixup *fix, int action)
6d3cd5d4
DH
3138{
3139 struct alc_spec *spec = codec->spec;
08fb0d0e
TI
3140 const struct dmi_device *dev = NULL;
3141
3142 if (action != HDA_FIXUP_ACT_PRE_PROBE)
3143 return;
3144
3145 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
3146 int pol, pin;
3147 if (sscanf(dev->name, "HP_Mute_LED_%d_%x", &pol, &pin) != 2)
3148 continue;
3149 if (pin < 0x0a || pin >= 0x10)
3150 break;
3151 spec->mute_led_polarity = pol;
3152 spec->mute_led_nid = pin - 0x0a + 0x18;
3153 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
fd25a97a 3154 spec->gen.vmaster_mute_enum = 1;
d5b6b65e 3155 codec->power_filter = led_power_filter;
08fb0d0e
TI
3156 snd_printd("Detected mute LED for %x:%d\n", spec->mute_led_nid,
3157 spec->mute_led_polarity);
6d3cd5d4
DH
3158 break;
3159 }
3160}
3161
d06ac143
DH
3162static void alc269_fixup_hp_mute_led_mic1(struct hda_codec *codec,
3163 const struct hda_fixup *fix, int action)
3164{
3165 struct alc_spec *spec = codec->spec;
3166 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3167 spec->mute_led_polarity = 0;
3168 spec->mute_led_nid = 0x18;
3169 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
3170 spec->gen.vmaster_mute_enum = 1;
d5b6b65e 3171 codec->power_filter = led_power_filter;
d06ac143
DH
3172 }
3173}
3174
08fb0d0e
TI
3175static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec,
3176 const struct hda_fixup *fix, int action)
420b0feb
TI
3177{
3178 struct alc_spec *spec = codec->spec;
9bb1f06f 3179 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
08fb0d0e
TI
3180 spec->mute_led_polarity = 0;
3181 spec->mute_led_nid = 0x19;
3182 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
fd25a97a 3183 spec->gen.vmaster_mute_enum = 1;
d5b6b65e 3184 codec->power_filter = led_power_filter;
420b0feb
TI
3185 }
3186}
3187
9f5c6faf
TI
3188/* turn on/off mute LED per vmaster hook */
3189static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled)
3190{
3191 struct hda_codec *codec = private_data;
3192 struct alc_spec *spec = codec->spec;
3193 unsigned int oldval = spec->gpio_led;
3194
3195 if (enabled)
3196 spec->gpio_led &= ~0x08;
3197 else
3198 spec->gpio_led |= 0x08;
3199 if (spec->gpio_led != oldval)
3200 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3201 spec->gpio_led);
3202}
3203
3204/* turn on/off mic-mute LED per capture hook */
3205static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec,
3206 struct snd_ctl_elem_value *ucontrol)
3207{
3208 struct alc_spec *spec = codec->spec;
3209 unsigned int oldval = spec->gpio_led;
3210
3211 if (!ucontrol)
3212 return;
3213
3214 if (ucontrol->value.integer.value[0] ||
3215 ucontrol->value.integer.value[1])
3216 spec->gpio_led &= ~0x10;
3217 else
3218 spec->gpio_led |= 0x10;
3219 if (spec->gpio_led != oldval)
3220 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3221 spec->gpio_led);
3222}
3223
3224static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
3225 const struct hda_fixup *fix, int action)
3226{
3227 struct alc_spec *spec = codec->spec;
3228 static const struct hda_verb gpio_init[] = {
3229 { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
3230 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
3231 {}
3232 };
3233
3234 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3235 spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
3236 spec->gen.cap_sync_hook = alc269_fixup_hp_gpio_mic_mute_hook;
3237 spec->gpio_led = 0;
3238 snd_hda_add_verbs(codec, gpio_init);
3239 }
3240}
3241
73bdd597
DH
3242static void alc_headset_mode_unplugged(struct hda_codec *codec)
3243{
3244 int val;
3245
3246 switch (codec->vendor_id) {
9a22a8f5
KY
3247 case 0x10ec0255:
3248 /* LDO and MISC control */
3249 alc_write_coef_idx(codec, 0x1b, 0x0c0b);
3250 /* UAJ function set to menual mode */
3251 alc_write_coef_idx(codec, 0x45, 0xd089);
3252 /* Direct Drive HP Amp control(Set to verb control)*/
3253 val = alc_read_coefex_idx(codec, 0x57, 0x05);
3254 alc_write_coefex_idx(codec, 0x57, 0x05, val & ~(1<<14));
3255 /* Set MIC2 Vref gate with HP */
3256 alc_write_coef_idx(codec, 0x06, 0x6104);
3257 /* Direct Drive HP Amp control */
3258 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6);
3259 break;
73bdd597
DH
3260 case 0x10ec0283:
3261 alc_write_coef_idx(codec, 0x1b, 0x0c0b);
3262 alc_write_coef_idx(codec, 0x45, 0xc429);
3263 val = alc_read_coef_idx(codec, 0x35);
3264 alc_write_coef_idx(codec, 0x35, val & 0xbfff);
3265 alc_write_coef_idx(codec, 0x06, 0x2104);
3266 alc_write_coef_idx(codec, 0x1a, 0x0001);
3267 alc_write_coef_idx(codec, 0x26, 0x0004);
3268 alc_write_coef_idx(codec, 0x32, 0x42a3);
3269 break;
3270 case 0x10ec0292:
3271 alc_write_coef_idx(codec, 0x76, 0x000e);
3272 alc_write_coef_idx(codec, 0x6c, 0x2400);
3273 alc_write_coef_idx(codec, 0x18, 0x7308);
3274 alc_write_coef_idx(codec, 0x6b, 0xc429);
3275 break;
3276 case 0x10ec0668:
3277 alc_write_coef_idx(codec, 0x15, 0x0d40);
3278 alc_write_coef_idx(codec, 0xb7, 0x802b);
3279 break;
3280 }
3281 snd_printdd("Headset jack set to unplugged mode.\n");
3282}
3283
3284
3285static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
3286 hda_nid_t mic_pin)
3287{
3288 int val;
3289
3290 switch (codec->vendor_id) {
9a22a8f5
KY
3291 case 0x10ec0255:
3292 alc_write_coef_idx(codec, 0x45, 0xc489);
3293 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3294 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6);
3295 /* Set MIC2 Vref gate to normal */
3296 alc_write_coef_idx(codec, 0x06, 0x6100);
3297 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3298 break;
73bdd597
DH
3299 case 0x10ec0283:
3300 alc_write_coef_idx(codec, 0x45, 0xc429);
3301 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3302 val = alc_read_coef_idx(codec, 0x35);
3303 alc_write_coef_idx(codec, 0x35, val | 1<<14);
3304 alc_write_coef_idx(codec, 0x06, 0x2100);
3305 alc_write_coef_idx(codec, 0x1a, 0x0021);
3306 alc_write_coef_idx(codec, 0x26, 0x008c);
3307 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3308 break;
3309 case 0x10ec0292:
3310 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3311 alc_write_coef_idx(codec, 0x19, 0xa208);
3312 alc_write_coef_idx(codec, 0x2e, 0xacf0);
3313 break;
3314 case 0x10ec0668:
3315 alc_write_coef_idx(codec, 0x11, 0x0001);
3316 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3317 alc_write_coef_idx(codec, 0xb7, 0x802b);
3318 alc_write_coef_idx(codec, 0xb5, 0x1040);
3319 val = alc_read_coef_idx(codec, 0xc3);
3320 alc_write_coef_idx(codec, 0xc3, val | 1<<12);
3321 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3322 break;
3323 }
3324 snd_printdd("Headset jack set to mic-in mode.\n");
3325}
3326
3327static void alc_headset_mode_default(struct hda_codec *codec)
3328{
3329 switch (codec->vendor_id) {
9a22a8f5
KY
3330 case 0x10ec0255:
3331 alc_write_coef_idx(codec, 0x45, 0xc089);
3332 alc_write_coef_idx(codec, 0x45, 0xc489);
3333 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
3334 alc_write_coef_idx(codec, 0x49, 0x0049);
3335 break;
73bdd597
DH
3336 case 0x10ec0283:
3337 alc_write_coef_idx(codec, 0x06, 0x2100);
3338 alc_write_coef_idx(codec, 0x32, 0x4ea3);
3339 break;
3340 case 0x10ec0292:
3341 alc_write_coef_idx(codec, 0x76, 0x000e);
3342 alc_write_coef_idx(codec, 0x6c, 0x2400);
3343 alc_write_coef_idx(codec, 0x6b, 0xc429);
3344 alc_write_coef_idx(codec, 0x18, 0x7308);
3345 break;
3346 case 0x10ec0668:
3347 alc_write_coef_idx(codec, 0x11, 0x0041);
3348 alc_write_coef_idx(codec, 0x15, 0x0d40);
3349 alc_write_coef_idx(codec, 0xb7, 0x802b);
3350 break;
3351 }
3352 snd_printdd("Headset jack set to headphone (default) mode.\n");
3353}
3354
3355/* Iphone type */
3356static void alc_headset_mode_ctia(struct hda_codec *codec)
3357{
3358 switch (codec->vendor_id) {
9a22a8f5
KY
3359 case 0x10ec0255:
3360 /* Set to CTIA type */
3361 alc_write_coef_idx(codec, 0x45, 0xd489);
3362 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3363 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
3364 break;
73bdd597
DH
3365 case 0x10ec0283:
3366 alc_write_coef_idx(codec, 0x45, 0xd429);
3367 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3368 alc_write_coef_idx(codec, 0x32, 0x4ea3);
3369 break;
3370 case 0x10ec0292:
3371 alc_write_coef_idx(codec, 0x6b, 0xd429);
3372 alc_write_coef_idx(codec, 0x76, 0x0008);
3373 alc_write_coef_idx(codec, 0x18, 0x7388);
3374 break;
3375 case 0x10ec0668:
d59915d0 3376 alc_write_coef_idx(codec, 0x11, 0x0001);
73bdd597
DH
3377 alc_write_coef_idx(codec, 0x15, 0x0d60);
3378 alc_write_coef_idx(codec, 0xc3, 0x0000);
3379 break;
3380 }
3381 snd_printdd("Headset jack set to iPhone-style headset mode.\n");
3382}
3383
3384/* Nokia type */
3385static void alc_headset_mode_omtp(struct hda_codec *codec)
3386{
3387 switch (codec->vendor_id) {
9a22a8f5
KY
3388 case 0x10ec0255:
3389 /* Set to OMTP Type */
3390 alc_write_coef_idx(codec, 0x45, 0xe489);
3391 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3392 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
3393 break;
73bdd597
DH
3394 case 0x10ec0283:
3395 alc_write_coef_idx(codec, 0x45, 0xe429);
3396 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3397 alc_write_coef_idx(codec, 0x32, 0x4ea3);
3398 break;
3399 case 0x10ec0292:
3400 alc_write_coef_idx(codec, 0x6b, 0xe429);
3401 alc_write_coef_idx(codec, 0x76, 0x0008);
3402 alc_write_coef_idx(codec, 0x18, 0x7388);
3403 break;
3404 case 0x10ec0668:
d59915d0 3405 alc_write_coef_idx(codec, 0x11, 0x0001);
73bdd597
DH
3406 alc_write_coef_idx(codec, 0x15, 0x0d50);
3407 alc_write_coef_idx(codec, 0xc3, 0x0000);
3408 break;
3409 }
3410 snd_printdd("Headset jack set to Nokia-style headset mode.\n");
3411}
3412
3413static void alc_determine_headset_type(struct hda_codec *codec)
3414{
3415 int val;
3416 bool is_ctia = false;
3417 struct alc_spec *spec = codec->spec;
3418
3419 switch (codec->vendor_id) {
9a22a8f5
KY
3420 case 0x10ec0255:
3421 /* combo jack auto switch control(Check type)*/
3422 alc_write_coef_idx(codec, 0x45, 0xd089);
3423 /* combo jack auto switch control(Vref conteol) */
3424 alc_write_coef_idx(codec, 0x49, 0x0149);
3425 msleep(300);
3426 val = alc_read_coef_idx(codec, 0x46);
3427 is_ctia = (val & 0x0070) == 0x0070;
3428 break;
73bdd597
DH
3429 case 0x10ec0283:
3430 alc_write_coef_idx(codec, 0x45, 0xd029);
3431 msleep(300);
3432 val = alc_read_coef_idx(codec, 0x46);
3433 is_ctia = (val & 0x0070) == 0x0070;
3434 break;
3435 case 0x10ec0292:
3436 alc_write_coef_idx(codec, 0x6b, 0xd429);
3437 msleep(300);
3438 val = alc_read_coef_idx(codec, 0x6c);
3439 is_ctia = (val & 0x001c) == 0x001c;
3440 break;
3441 case 0x10ec0668:
3442 alc_write_coef_idx(codec, 0x11, 0x0001);
3443 alc_write_coef_idx(codec, 0xb7, 0x802b);
3444 alc_write_coef_idx(codec, 0x15, 0x0d60);
3445 alc_write_coef_idx(codec, 0xc3, 0x0c00);
3446 msleep(300);
3447 val = alc_read_coef_idx(codec, 0xbe);
3448 is_ctia = (val & 0x1c02) == 0x1c02;
3449 break;
3450 }
3451
3452 snd_printdd("Headset jack detected iPhone-style headset: %s\n",
3453 is_ctia ? "yes" : "no");
3454 spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP;
3455}
3456
3457static void alc_update_headset_mode(struct hda_codec *codec)
3458{
3459 struct alc_spec *spec = codec->spec;
3460
3461 hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
3462 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
3463
3464 int new_headset_mode;
3465
3466 if (!snd_hda_jack_detect(codec, hp_pin))
3467 new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED;
3468 else if (mux_pin == spec->headset_mic_pin)
3469 new_headset_mode = ALC_HEADSET_MODE_HEADSET;
3470 else if (mux_pin == spec->headphone_mic_pin)
3471 new_headset_mode = ALC_HEADSET_MODE_MIC;
3472 else
3473 new_headset_mode = ALC_HEADSET_MODE_HEADPHONE;
3474
5959a6bc
DH
3475 if (new_headset_mode == spec->current_headset_mode) {
3476 snd_hda_gen_update_outputs(codec);
73bdd597 3477 return;
5959a6bc 3478 }
73bdd597
DH
3479
3480 switch (new_headset_mode) {
3481 case ALC_HEADSET_MODE_UNPLUGGED:
3482 alc_headset_mode_unplugged(codec);
3483 spec->gen.hp_jack_present = false;
3484 break;
3485 case ALC_HEADSET_MODE_HEADSET:
3486 if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)
3487 alc_determine_headset_type(codec);
3488 if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)
3489 alc_headset_mode_ctia(codec);
3490 else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP)
3491 alc_headset_mode_omtp(codec);
3492 spec->gen.hp_jack_present = true;
3493 break;
3494 case ALC_HEADSET_MODE_MIC:
3495 alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin);
3496 spec->gen.hp_jack_present = false;
3497 break;
3498 case ALC_HEADSET_MODE_HEADPHONE:
3499 alc_headset_mode_default(codec);
3500 spec->gen.hp_jack_present = true;
3501 break;
3502 }
3503 if (new_headset_mode != ALC_HEADSET_MODE_MIC) {
3504 snd_hda_set_pin_ctl_cache(codec, hp_pin,
3505 AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
3506 if (spec->headphone_mic_pin)
3507 snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin,
3508 PIN_VREFHIZ);
3509 }
3510 spec->current_headset_mode = new_headset_mode;
3511
3512 snd_hda_gen_update_outputs(codec);
3513}
3514
3515static void alc_update_headset_mode_hook(struct hda_codec *codec,
3516 struct snd_ctl_elem_value *ucontrol)
3517{
3518 alc_update_headset_mode(codec);
3519}
3520
3521static void alc_update_headset_jack_cb(struct hda_codec *codec, struct hda_jack_tbl *jack)
3522{
3523 struct alc_spec *spec = codec->spec;
5db4d34b 3524 spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
73bdd597
DH
3525 snd_hda_gen_hp_automute(codec, jack);
3526}
3527
3528static void alc_probe_headset_mode(struct hda_codec *codec)
3529{
3530 int i;
3531 struct alc_spec *spec = codec->spec;
3532 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
3533
3534 /* Find mic pins */
3535 for (i = 0; i < cfg->num_inputs; i++) {
3536 if (cfg->inputs[i].is_headset_mic && !spec->headset_mic_pin)
3537 spec->headset_mic_pin = cfg->inputs[i].pin;
3538 if (cfg->inputs[i].is_headphone_mic && !spec->headphone_mic_pin)
3539 spec->headphone_mic_pin = cfg->inputs[i].pin;
3540 }
3541
3542 spec->gen.cap_sync_hook = alc_update_headset_mode_hook;
3543 spec->gen.automute_hook = alc_update_headset_mode;
3544 spec->gen.hp_automute_hook = alc_update_headset_jack_cb;
3545}
3546
3547static void alc_fixup_headset_mode(struct hda_codec *codec,
3548 const struct hda_fixup *fix, int action)
3549{
3550 struct alc_spec *spec = codec->spec;
3551
3552 switch (action) {
3553 case HDA_FIXUP_ACT_PRE_PROBE:
3554 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC | HDA_PINCFG_HEADPHONE_MIC;
3555 break;
3556 case HDA_FIXUP_ACT_PROBE:
3557 alc_probe_headset_mode(codec);
3558 break;
3559 case HDA_FIXUP_ACT_INIT:
3560 spec->current_headset_mode = 0;
3561 alc_update_headset_mode(codec);
3562 break;
3563 }
3564}
3565
3566static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
3567 const struct hda_fixup *fix, int action)
3568{
3569 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3570 struct alc_spec *spec = codec->spec;
3571 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
3572 }
3573 else
3574 alc_fixup_headset_mode(codec, fix, action);
3575}
3576
9a22a8f5
KY
3577static void alc_fixup_headset_mode_alc255(struct hda_codec *codec,
3578 const struct hda_fixup *fix, int action)
3579{
3580 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3581 /* Set to iphone type */
3582 alc_write_coef_idx(codec, 0x1b, 0x880b);
3583 alc_write_coef_idx(codec, 0x45, 0xd089);
3584 alc_write_coef_idx(codec, 0x1b, 0x080b);
3585 alc_write_coef_idx(codec, 0x46, 0x0004);
3586 alc_write_coef_idx(codec, 0x1b, 0x0c0b);
3587 msleep(30);
3588 }
3589 alc_fixup_headset_mode(codec, fix, action);
3590}
3591
73bdd597
DH
3592static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
3593 const struct hda_fixup *fix, int action)
3594{
3595 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3596 int val;
3597 alc_write_coef_idx(codec, 0xc4, 0x8000);
3598 val = alc_read_coef_idx(codec, 0xc2);
3599 alc_write_coef_idx(codec, 0xc2, val & 0xfe);
3600 snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
3601 }
3602 alc_fixup_headset_mode(codec, fix, action);
3603}
3604
bde7bc60
CCC
3605/* Returns the nid of the external mic input pin, or 0 if it cannot be found. */
3606static int find_ext_mic_pin(struct hda_codec *codec)
3607{
3608 struct alc_spec *spec = codec->spec;
3609 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
3610 hda_nid_t nid;
3611 unsigned int defcfg;
3612 int i;
3613
3614 for (i = 0; i < cfg->num_inputs; i++) {
3615 if (cfg->inputs[i].type != AUTO_PIN_MIC)
3616 continue;
3617 nid = cfg->inputs[i].pin;
3618 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3619 if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
3620 continue;
3621 return nid;
3622 }
3623
3624 return 0;
3625}
3626
08a978db 3627static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
1727a771 3628 const struct hda_fixup *fix,
08a978db
DR
3629 int action)
3630{
3631 struct alc_spec *spec = codec->spec;
3632
0db75790 3633 if (action == HDA_FIXUP_ACT_PROBE) {
bde7bc60
CCC
3634 int mic_pin = find_ext_mic_pin(codec);
3635 int hp_pin = spec->gen.autocfg.hp_pins[0];
3636
3637 if (snd_BUG_ON(!mic_pin || !hp_pin))
0db75790 3638 return;
bde7bc60 3639 snd_hda_jack_set_gating_jack(codec, mic_pin, hp_pin);
0db75790 3640 }
08a978db 3641}
693b613d 3642
3e0d611b
DH
3643static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec,
3644 const struct hda_fixup *fix,
3645 int action)
3646{
3647 struct alc_spec *spec = codec->spec;
3648 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
3649 int i;
3650
3651 /* The mic boosts on level 2 and 3 are too noisy
3652 on the internal mic input.
3653 Therefore limit the boost to 0 or 1. */
3654
3655 if (action != HDA_FIXUP_ACT_PROBE)
3656 return;
3657
3658 for (i = 0; i < cfg->num_inputs; i++) {
3659 hda_nid_t nid = cfg->inputs[i].pin;
3660 unsigned int defcfg;
3661 if (cfg->inputs[i].type != AUTO_PIN_MIC)
3662 continue;
3663 defcfg = snd_hda_codec_get_pincfg(codec, nid);
3664 if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
3665 continue;
3666
3667 snd_hda_override_amp_caps(codec, nid, HDA_INPUT,
3668 (0x00 << AC_AMPCAP_OFFSET_SHIFT) |
3669 (0x01 << AC_AMPCAP_NUM_STEPS_SHIFT) |
3670 (0x2f << AC_AMPCAP_STEP_SIZE_SHIFT) |
3671 (0 << AC_AMPCAP_MUTE_SHIFT));
3672 }
3673}
3674
cd217a63
KY
3675static void alc283_hp_automute_hook(struct hda_codec *codec,
3676 struct hda_jack_tbl *jack)
3677{
3678 struct alc_spec *spec = codec->spec;
3679 int vref;
3680
3681 msleep(200);
3682 snd_hda_gen_hp_automute(codec, jack);
3683
3684 vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
3685
3686 msleep(600);
3687 snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3688 vref);
3689}
3690
cd217a63
KY
3691static void alc283_fixup_chromebook(struct hda_codec *codec,
3692 const struct hda_fixup *fix, int action)
3693{
3694 struct alc_spec *spec = codec->spec;
3695 int val;
3696
3697 switch (action) {
3698 case HDA_FIXUP_ACT_PRE_PROBE:
0202e99c 3699 snd_hda_override_wcaps(codec, 0x03, 0);
d2e92709
TI
3700 /* Disable AA-loopback as it causes white noise */
3701 spec->gen.mixer_nid = 0;
38070219 3702 break;
0202e99c
KY
3703 case HDA_FIXUP_ACT_INIT:
3704 /* Enable Line1 input control by verb */
3705 val = alc_read_coef_idx(codec, 0x1a);
3706 alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
3707 break;
3708 }
3709}
3710
3711static void alc283_fixup_sense_combo_jack(struct hda_codec *codec,
3712 const struct hda_fixup *fix, int action)
3713{
3714 struct alc_spec *spec = codec->spec;
3715 int val;
3716
3717 switch (action) {
3718 case HDA_FIXUP_ACT_PRE_PROBE:
cd217a63 3719 spec->gen.hp_automute_hook = alc283_hp_automute_hook;
38070219
KY
3720 break;
3721 case HDA_FIXUP_ACT_INIT:
cd217a63
KY
3722 /* MIC2-VREF control */
3723 /* Set to manual mode */
3724 val = alc_read_coef_idx(codec, 0x06);
3725 alc_write_coef_idx(codec, 0x06, val & ~0x000c);
3726 break;
3727 }
3728}
3729
7bba2157
TI
3730/* mute tablet speaker pin (0x14) via dock plugging in addition */
3731static void asus_tx300_automute(struct hda_codec *codec)
3732{
3733 struct alc_spec *spec = codec->spec;
3734 snd_hda_gen_update_outputs(codec);
3735 if (snd_hda_jack_detect(codec, 0x1b))
3736 spec->gen.mute_bits |= (1ULL << 0x14);
3737}
3738
3739static void alc282_fixup_asus_tx300(struct hda_codec *codec,
3740 const struct hda_fixup *fix, int action)
3741{
3742 struct alc_spec *spec = codec->spec;
3743 /* TX300 needs to set up GPIO2 for the speaker amp */
3744 static const struct hda_verb gpio2_verbs[] = {
3745 { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 },
3746 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 },
3747 { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 },
3748 {}
3749 };
3750 static const struct hda_pintbl dock_pins[] = {
3751 { 0x1b, 0x21114000 }, /* dock speaker pin */
3752 {}
3753 };
3754 struct snd_kcontrol *kctl;
3755
3756 switch (action) {
3757 case HDA_FIXUP_ACT_PRE_PROBE:
3758 snd_hda_add_verbs(codec, gpio2_verbs);
3759 snd_hda_apply_pincfgs(codec, dock_pins);
3760 spec->gen.auto_mute_via_amp = 1;
3761 spec->gen.automute_hook = asus_tx300_automute;
3762 snd_hda_jack_detect_enable_callback(codec, 0x1b,
3763 HDA_GEN_HP_EVENT,
3764 snd_hda_gen_hp_automute);
3765 break;
3766 case HDA_FIXUP_ACT_BUILD:
3767 /* this is a bit tricky; give more sane names for the main
3768 * (tablet) speaker and the dock speaker, respectively
3769 */
3770 kctl = snd_hda_find_mixer_ctl(codec, "Speaker Playback Switch");
3771 if (kctl)
3772 strcpy(kctl->id.name, "Dock Speaker Playback Switch");
3773 kctl = snd_hda_find_mixer_ctl(codec, "Bass Speaker Playback Switch");
3774 if (kctl)
3775 strcpy(kctl->id.name, "Speaker Playback Switch");
3776 break;
3777 }
3778}
3779
338cae56
DH
3780static void alc290_fixup_mono_speakers(struct hda_codec *codec,
3781 const struct hda_fixup *fix, int action)
3782{
0f4881dc
DH
3783 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3784 /* DAC node 0x03 is giving mono output. We therefore want to
3785 make sure 0x14 (front speaker) and 0x15 (headphones) use the
3786 stereo DAC, while leaving 0x17 (bass speaker) for node 0x03. */
3787 hda_nid_t conn1[2] = { 0x0c };
3788 snd_hda_override_conn_list(codec, 0x14, 1, conn1);
3789 snd_hda_override_conn_list(codec, 0x15, 1, conn1);
3790 }
338cae56
DH
3791}
3792
b67ae3f1
DH
3793#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
3794
3795#include <linux/thinkpad_acpi.h>
d171ebc5 3796#include <linux/acpi.h>
b67ae3f1
DH
3797
3798static int (*led_set_func)(int, bool);
3799
2793769f
DH
3800static acpi_status acpi_check_cb(acpi_handle handle, u32 lvl, void *context,
3801 void **rv)
3802{
3803 bool *found = context;
3804 *found = true;
3805 return AE_OK;
3806}
3807
3808static bool is_thinkpad(struct hda_codec *codec)
3809{
3810 bool found = false;
3811 if (codec->subsystem_id >> 16 != 0x17aa)
3812 return false;
3813 if (ACPI_SUCCESS(acpi_get_devices("LEN0068", acpi_check_cb, &found, NULL)) && found)
3814 return true;
3815 found = false;
3816 return ACPI_SUCCESS(acpi_get_devices("IBM0068", acpi_check_cb, &found, NULL)) && found;
3817}
3818
b67ae3f1
DH
3819static void update_tpacpi_mute_led(void *private_data, int enabled)
3820{
3821 if (led_set_func)
3822 led_set_func(TPACPI_LED_MUTE, !enabled);
3823}
3824
3825static void update_tpacpi_micmute_led(struct hda_codec *codec,
3826 struct snd_ctl_elem_value *ucontrol)
3827{
3828 if (!ucontrol || !led_set_func)
3829 return;
3830 if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
3831 /* TODO: How do I verify if it's a mono or stereo here? */
3832 bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
3833 led_set_func(TPACPI_LED_MICMUTE, !val);
3834 }
3835}
3836
3837static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
3838 const struct hda_fixup *fix, int action)
3839{
3840 struct alc_spec *spec = codec->spec;
3841 bool removefunc = false;
3842
3843 if (action == HDA_FIXUP_ACT_PROBE) {
2793769f
DH
3844 if (!is_thinkpad(codec))
3845 return;
b67ae3f1
DH
3846 if (!led_set_func)
3847 led_set_func = symbol_request(tpacpi_led_set);
3848 if (!led_set_func) {
3849 snd_printk(KERN_WARNING "Failed to find thinkpad-acpi symbol tpacpi_led_set\n");
3850 return;
3851 }
3852
3853 removefunc = true;
3854 if (led_set_func(TPACPI_LED_MUTE, false) >= 0) {
3855 spec->gen.vmaster_mute.hook = update_tpacpi_mute_led;
3856 removefunc = false;
3857 }
3858 if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
3859 if (spec->gen.num_adc_nids > 1)
3860 snd_printdd("Skipping micmute LED control due to several ADCs");
3861 else {
3862 spec->gen.cap_sync_hook = update_tpacpi_micmute_led;
3863 removefunc = false;
3864 }
3865 }
3866 }
3867
3868 if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
3869 symbol_put(tpacpi_led_set);
3870 led_set_func = NULL;
3871 }
3872}
3873
3874#else
3875
3876static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
3877 const struct hda_fixup *fix, int action)
3878{
3879}
3880
3881#endif
3882
1d045db9
TI
3883enum {
3884 ALC269_FIXUP_SONY_VAIO,
3885 ALC275_FIXUP_SONY_VAIO_GPIO2,
3886 ALC269_FIXUP_DELL_M101Z,
3887 ALC269_FIXUP_SKU_IGNORE,
3888 ALC269_FIXUP_ASUS_G73JW,
3889 ALC269_FIXUP_LENOVO_EAPD,
3890 ALC275_FIXUP_SONY_HWEQ,
3891 ALC271_FIXUP_DMIC,
017f2a10 3892 ALC269_FIXUP_PCM_44K,
adabb3ec 3893 ALC269_FIXUP_STEREO_DMIC,
7c478f03 3894 ALC269_FIXUP_HEADSET_MIC,
24519911
TI
3895 ALC269_FIXUP_QUANTA_MUTE,
3896 ALC269_FIXUP_LIFEBOOK,
a4297b5d
TI
3897 ALC269_FIXUP_AMIC,
3898 ALC269_FIXUP_DMIC,
3899 ALC269VB_FIXUP_AMIC,
3900 ALC269VB_FIXUP_DMIC,
08fb0d0e 3901 ALC269_FIXUP_HP_MUTE_LED,
d06ac143 3902 ALC269_FIXUP_HP_MUTE_LED_MIC1,
08fb0d0e 3903 ALC269_FIXUP_HP_MUTE_LED_MIC2,
9f5c6faf 3904 ALC269_FIXUP_HP_GPIO_LED,
693b613d 3905 ALC269_FIXUP_INV_DMIC,
108cc108 3906 ALC269_FIXUP_LENOVO_DOCK,
88cfcf86 3907 ALC286_FIXUP_SONY_MIC_NO_PRESENCE,
108cc108 3908 ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
73bdd597
DH
3909 ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
3910 ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
338cae56 3911 ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
73bdd597
DH
3912 ALC269_FIXUP_HEADSET_MODE,
3913 ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC,
d240d1dc
DH
3914 ALC269_FIXUP_ASUS_X101_FUNC,
3915 ALC269_FIXUP_ASUS_X101_VERB,
3916 ALC269_FIXUP_ASUS_X101,
08a978db
DR
3917 ALC271_FIXUP_AMIC_MIC2,
3918 ALC271_FIXUP_HP_GATE_MIC_JACK,
b1e8972e 3919 ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572,
42397004 3920 ALC269_FIXUP_ACER_AC700,
3e0d611b 3921 ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
2cede303 3922 ALC269VB_FIXUP_ASUS_ZENBOOK,
8e35cd4a 3923 ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED,
02b504d9 3924 ALC269VB_FIXUP_ORDISSIMO_EVE2,
cd217a63 3925 ALC283_FIXUP_CHROME_BOOK,
0202e99c 3926 ALC283_FIXUP_SENSE_COMBO_JACK,
7bba2157 3927 ALC282_FIXUP_ASUS_TX300,
1bb3e062 3928 ALC283_FIXUP_INT_MIC,
338cae56 3929 ALC290_FIXUP_MONO_SPEAKERS,
0f4881dc
DH
3930 ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
3931 ALC290_FIXUP_SUBWOOFER,
3932 ALC290_FIXUP_SUBWOOFER_HSJACK,
b67ae3f1 3933 ALC269_FIXUP_THINKPAD_ACPI,
9a22a8f5
KY
3934 ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
3935 ALC255_FIXUP_HEADSET_MODE,
f1d4e28b
KY
3936};
3937
1727a771 3938static const struct hda_fixup alc269_fixups[] = {
1d045db9 3939 [ALC269_FIXUP_SONY_VAIO] = {
fd108215
TI
3940 .type = HDA_FIXUP_PINCTLS,
3941 .v.pins = (const struct hda_pintbl[]) {
3942 {0x19, PIN_VREFGRD},
1d045db9
TI
3943 {}
3944 }
f1d4e28b 3945 },
1d045db9 3946 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
1727a771 3947 .type = HDA_FIXUP_VERBS,
1d045db9
TI
3948 .v.verbs = (const struct hda_verb[]) {
3949 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
3950 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
3951 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
3952 { }
3953 },
3954 .chained = true,
3955 .chain_id = ALC269_FIXUP_SONY_VAIO
3956 },
3957 [ALC269_FIXUP_DELL_M101Z] = {
1727a771 3958 .type = HDA_FIXUP_VERBS,
1d045db9
TI
3959 .v.verbs = (const struct hda_verb[]) {
3960 /* Enables internal speaker */
3961 {0x20, AC_VERB_SET_COEF_INDEX, 13},
3962 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
3963 {}
3964 }
3965 },
3966 [ALC269_FIXUP_SKU_IGNORE] = {
1727a771 3967 .type = HDA_FIXUP_FUNC,
23d30f28 3968 .v.func = alc_fixup_sku_ignore,
1d045db9
TI
3969 },
3970 [ALC269_FIXUP_ASUS_G73JW] = {
1727a771
TI
3971 .type = HDA_FIXUP_PINS,
3972 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
3973 { 0x17, 0x99130111 }, /* subwoofer */
3974 { }
3975 }
3976 },
3977 [ALC269_FIXUP_LENOVO_EAPD] = {
1727a771 3978 .type = HDA_FIXUP_VERBS,
1d045db9
TI
3979 .v.verbs = (const struct hda_verb[]) {
3980 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
3981 {}
3982 }
3983 },
3984 [ALC275_FIXUP_SONY_HWEQ] = {
1727a771 3985 .type = HDA_FIXUP_FUNC,
1d045db9
TI
3986 .v.func = alc269_fixup_hweq,
3987 .chained = true,
3988 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
3989 },
3990 [ALC271_FIXUP_DMIC] = {
1727a771 3991 .type = HDA_FIXUP_FUNC,
1d045db9 3992 .v.func = alc271_fixup_dmic,
f1d4e28b 3993 },
017f2a10 3994 [ALC269_FIXUP_PCM_44K] = {
1727a771 3995 .type = HDA_FIXUP_FUNC,
017f2a10 3996 .v.func = alc269_fixup_pcm_44k,
012e7eb1
DH
3997 .chained = true,
3998 .chain_id = ALC269_FIXUP_QUANTA_MUTE
017f2a10 3999 },
adabb3ec 4000 [ALC269_FIXUP_STEREO_DMIC] = {
1727a771 4001 .type = HDA_FIXUP_FUNC,
adabb3ec
TI
4002 .v.func = alc269_fixup_stereo_dmic,
4003 },
7c478f03
DH
4004 [ALC269_FIXUP_HEADSET_MIC] = {
4005 .type = HDA_FIXUP_FUNC,
4006 .v.func = alc269_fixup_headset_mic,
4007 },
24519911 4008 [ALC269_FIXUP_QUANTA_MUTE] = {
1727a771 4009 .type = HDA_FIXUP_FUNC,
24519911
TI
4010 .v.func = alc269_fixup_quanta_mute,
4011 },
4012 [ALC269_FIXUP_LIFEBOOK] = {
1727a771
TI
4013 .type = HDA_FIXUP_PINS,
4014 .v.pins = (const struct hda_pintbl[]) {
24519911
TI
4015 { 0x1a, 0x2101103f }, /* dock line-out */
4016 { 0x1b, 0x23a11040 }, /* dock mic-in */
4017 { }
4018 },
4019 .chained = true,
4020 .chain_id = ALC269_FIXUP_QUANTA_MUTE
4021 },
a4297b5d 4022 [ALC269_FIXUP_AMIC] = {
1727a771
TI
4023 .type = HDA_FIXUP_PINS,
4024 .v.pins = (const struct hda_pintbl[]) {
a4297b5d
TI
4025 { 0x14, 0x99130110 }, /* speaker */
4026 { 0x15, 0x0121401f }, /* HP out */
4027 { 0x18, 0x01a19c20 }, /* mic */
4028 { 0x19, 0x99a3092f }, /* int-mic */
4029 { }
4030 },
4031 },
4032 [ALC269_FIXUP_DMIC] = {
1727a771
TI
4033 .type = HDA_FIXUP_PINS,
4034 .v.pins = (const struct hda_pintbl[]) {
a4297b5d
TI
4035 { 0x12, 0x99a3092f }, /* int-mic */
4036 { 0x14, 0x99130110 }, /* speaker */
4037 { 0x15, 0x0121401f }, /* HP out */
4038 { 0x18, 0x01a19c20 }, /* mic */
4039 { }
4040 },
4041 },
4042 [ALC269VB_FIXUP_AMIC] = {
1727a771
TI
4043 .type = HDA_FIXUP_PINS,
4044 .v.pins = (const struct hda_pintbl[]) {
a4297b5d
TI
4045 { 0x14, 0x99130110 }, /* speaker */
4046 { 0x18, 0x01a19c20 }, /* mic */
4047 { 0x19, 0x99a3092f }, /* int-mic */
4048 { 0x21, 0x0121401f }, /* HP out */
4049 { }
4050 },
4051 },
2267ea97 4052 [ALC269VB_FIXUP_DMIC] = {
1727a771
TI
4053 .type = HDA_FIXUP_PINS,
4054 .v.pins = (const struct hda_pintbl[]) {
a4297b5d
TI
4055 { 0x12, 0x99a3092f }, /* int-mic */
4056 { 0x14, 0x99130110 }, /* speaker */
4057 { 0x18, 0x01a19c20 }, /* mic */
4058 { 0x21, 0x0121401f }, /* HP out */
4059 { }
4060 },
4061 },
08fb0d0e 4062 [ALC269_FIXUP_HP_MUTE_LED] = {
1727a771 4063 .type = HDA_FIXUP_FUNC,
08fb0d0e 4064 .v.func = alc269_fixup_hp_mute_led,
6d3cd5d4 4065 },
d06ac143
DH
4066 [ALC269_FIXUP_HP_MUTE_LED_MIC1] = {
4067 .type = HDA_FIXUP_FUNC,
4068 .v.func = alc269_fixup_hp_mute_led_mic1,
4069 },
08fb0d0e 4070 [ALC269_FIXUP_HP_MUTE_LED_MIC2] = {
1727a771 4071 .type = HDA_FIXUP_FUNC,
08fb0d0e 4072 .v.func = alc269_fixup_hp_mute_led_mic2,
420b0feb 4073 },
9f5c6faf
TI
4074 [ALC269_FIXUP_HP_GPIO_LED] = {
4075 .type = HDA_FIXUP_FUNC,
4076 .v.func = alc269_fixup_hp_gpio_led,
4077 },
693b613d 4078 [ALC269_FIXUP_INV_DMIC] = {
1727a771 4079 .type = HDA_FIXUP_FUNC,
6e72aa5f 4080 .v.func = alc_fixup_inv_dmic_0x12,
693b613d 4081 },
108cc108 4082 [ALC269_FIXUP_LENOVO_DOCK] = {
1727a771
TI
4083 .type = HDA_FIXUP_PINS,
4084 .v.pins = (const struct hda_pintbl[]) {
108cc108
DH
4085 { 0x19, 0x23a11040 }, /* dock mic */
4086 { 0x1b, 0x2121103f }, /* dock headphone */
4087 { }
4088 },
4089 .chained = true,
4090 .chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT
4091 },
4092 [ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT] = {
1727a771 4093 .type = HDA_FIXUP_FUNC,
108cc108 4094 .v.func = alc269_fixup_pincfg_no_hp_to_lineout,
52129000
DH
4095 .chained = true,
4096 .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
108cc108 4097 },
73bdd597
DH
4098 [ALC269_FIXUP_DELL1_MIC_NO_PRESENCE] = {
4099 .type = HDA_FIXUP_PINS,
4100 .v.pins = (const struct hda_pintbl[]) {
4101 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4102 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
4103 { }
4104 },
4105 .chained = true,
4106 .chain_id = ALC269_FIXUP_HEADSET_MODE
4107 },
4108 [ALC269_FIXUP_DELL2_MIC_NO_PRESENCE] = {
4109 .type = HDA_FIXUP_PINS,
4110 .v.pins = (const struct hda_pintbl[]) {
4111 { 0x16, 0x21014020 }, /* dock line out */
4112 { 0x19, 0x21a19030 }, /* dock mic */
4113 { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4114 { }
4115 },
4116 .chained = true,
4117 .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
4118 },
338cae56
DH
4119 [ALC269_FIXUP_DELL3_MIC_NO_PRESENCE] = {
4120 .type = HDA_FIXUP_PINS,
4121 .v.pins = (const struct hda_pintbl[]) {
4122 { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4123 { }
4124 },
4125 .chained = true,
4126 .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
4127 },
73bdd597
DH
4128 [ALC269_FIXUP_HEADSET_MODE] = {
4129 .type = HDA_FIXUP_FUNC,
4130 .v.func = alc_fixup_headset_mode,
4131 },
4132 [ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
4133 .type = HDA_FIXUP_FUNC,
4134 .v.func = alc_fixup_headset_mode_no_hp_mic,
4135 },
88cfcf86
DH
4136 [ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = {
4137 .type = HDA_FIXUP_PINS,
4138 .v.pins = (const struct hda_pintbl[]) {
4139 { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4140 { }
4141 },
fbc78ad6
DH
4142 .chained = true,
4143 .chain_id = ALC269_FIXUP_HEADSET_MIC
88cfcf86 4144 },
d240d1dc
DH
4145 [ALC269_FIXUP_ASUS_X101_FUNC] = {
4146 .type = HDA_FIXUP_FUNC,
4147 .v.func = alc269_fixup_x101_headset_mic,
4148 },
4149 [ALC269_FIXUP_ASUS_X101_VERB] = {
4150 .type = HDA_FIXUP_VERBS,
4151 .v.verbs = (const struct hda_verb[]) {
4152 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4153 {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
4154 {0x20, AC_VERB_SET_PROC_COEF, 0x0310},
4155 { }
4156 },
4157 .chained = true,
4158 .chain_id = ALC269_FIXUP_ASUS_X101_FUNC
4159 },
4160 [ALC269_FIXUP_ASUS_X101] = {
4161 .type = HDA_FIXUP_PINS,
4162 .v.pins = (const struct hda_pintbl[]) {
4163 { 0x18, 0x04a1182c }, /* Headset mic */
4164 { }
4165 },
4166 .chained = true,
4167 .chain_id = ALC269_FIXUP_ASUS_X101_VERB
4168 },
08a978db 4169 [ALC271_FIXUP_AMIC_MIC2] = {
1727a771
TI
4170 .type = HDA_FIXUP_PINS,
4171 .v.pins = (const struct hda_pintbl[]) {
08a978db
DR
4172 { 0x14, 0x99130110 }, /* speaker */
4173 { 0x19, 0x01a19c20 }, /* mic */
4174 { 0x1b, 0x99a7012f }, /* int-mic */
4175 { 0x21, 0x0121401f }, /* HP out */
4176 { }
4177 },
4178 },
4179 [ALC271_FIXUP_HP_GATE_MIC_JACK] = {
1727a771 4180 .type = HDA_FIXUP_FUNC,
08a978db
DR
4181 .v.func = alc271_hp_gate_mic_jack,
4182 .chained = true,
4183 .chain_id = ALC271_FIXUP_AMIC_MIC2,
4184 },
b1e8972e
OR
4185 [ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572] = {
4186 .type = HDA_FIXUP_FUNC,
4187 .v.func = alc269_fixup_limit_int_mic_boost,
4188 .chained = true,
4189 .chain_id = ALC271_FIXUP_HP_GATE_MIC_JACK,
4190 },
42397004
DR
4191 [ALC269_FIXUP_ACER_AC700] = {
4192 .type = HDA_FIXUP_PINS,
4193 .v.pins = (const struct hda_pintbl[]) {
4194 { 0x12, 0x99a3092f }, /* int-mic */
4195 { 0x14, 0x99130110 }, /* speaker */
4196 { 0x18, 0x03a11c20 }, /* mic */
4197 { 0x1e, 0x0346101e }, /* SPDIF1 */
4198 { 0x21, 0x0321101f }, /* HP out */
4199 { }
4200 },
4201 .chained = true,
4202 .chain_id = ALC271_FIXUP_DMIC,
4203 },
3e0d611b
DH
4204 [ALC269_FIXUP_LIMIT_INT_MIC_BOOST] = {
4205 .type = HDA_FIXUP_FUNC,
4206 .v.func = alc269_fixup_limit_int_mic_boost,
2793769f
DH
4207 .chained = true,
4208 .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
3e0d611b 4209 },
2cede303
OR
4210 [ALC269VB_FIXUP_ASUS_ZENBOOK] = {
4211 .type = HDA_FIXUP_FUNC,
4212 .v.func = alc269_fixup_limit_int_mic_boost,
4213 .chained = true,
4214 .chain_id = ALC269VB_FIXUP_DMIC,
4215 },
8e35cd4a
DH
4216 [ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED] = {
4217 .type = HDA_FIXUP_FUNC,
4218 .v.func = alc269_fixup_limit_int_mic_boost,
4219 .chained = true,
4220 .chain_id = ALC269_FIXUP_HP_MUTE_LED_MIC1,
4221 },
02b504d9
AA
4222 [ALC269VB_FIXUP_ORDISSIMO_EVE2] = {
4223 .type = HDA_FIXUP_PINS,
4224 .v.pins = (const struct hda_pintbl[]) {
4225 { 0x12, 0x99a3092f }, /* int-mic */
4226 { 0x18, 0x03a11d20 }, /* mic */
4227 { 0x19, 0x411111f0 }, /* Unused bogus pin */
4228 { }
4229 },
4230 },
cd217a63
KY
4231 [ALC283_FIXUP_CHROME_BOOK] = {
4232 .type = HDA_FIXUP_FUNC,
4233 .v.func = alc283_fixup_chromebook,
4234 },
0202e99c
KY
4235 [ALC283_FIXUP_SENSE_COMBO_JACK] = {
4236 .type = HDA_FIXUP_FUNC,
4237 .v.func = alc283_fixup_sense_combo_jack,
4238 .chained = true,
4239 .chain_id = ALC283_FIXUP_CHROME_BOOK,
4240 },
7bba2157
TI
4241 [ALC282_FIXUP_ASUS_TX300] = {
4242 .type = HDA_FIXUP_FUNC,
4243 .v.func = alc282_fixup_asus_tx300,
4244 },
1bb3e062
KY
4245 [ALC283_FIXUP_INT_MIC] = {
4246 .type = HDA_FIXUP_VERBS,
4247 .v.verbs = (const struct hda_verb[]) {
4248 {0x20, AC_VERB_SET_COEF_INDEX, 0x1a},
4249 {0x20, AC_VERB_SET_PROC_COEF, 0x0011},
4250 { }
4251 },
4252 .chained = true,
4253 .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
4254 },
0f4881dc
DH
4255 [ALC290_FIXUP_SUBWOOFER_HSJACK] = {
4256 .type = HDA_FIXUP_PINS,
4257 .v.pins = (const struct hda_pintbl[]) {
4258 { 0x17, 0x90170112 }, /* subwoofer */
4259 { }
4260 },
4261 .chained = true,
4262 .chain_id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
4263 },
4264 [ALC290_FIXUP_SUBWOOFER] = {
4265 .type = HDA_FIXUP_PINS,
4266 .v.pins = (const struct hda_pintbl[]) {
4267 { 0x17, 0x90170112 }, /* subwoofer */
4268 { }
4269 },
4270 .chained = true,
4271 .chain_id = ALC290_FIXUP_MONO_SPEAKERS,
4272 },
338cae56
DH
4273 [ALC290_FIXUP_MONO_SPEAKERS] = {
4274 .type = HDA_FIXUP_FUNC,
4275 .v.func = alc290_fixup_mono_speakers,
0f4881dc
DH
4276 },
4277 [ALC290_FIXUP_MONO_SPEAKERS_HSJACK] = {
4278 .type = HDA_FIXUP_FUNC,
4279 .v.func = alc290_fixup_mono_speakers,
338cae56
DH
4280 .chained = true,
4281 .chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
4282 },
b67ae3f1
DH
4283 [ALC269_FIXUP_THINKPAD_ACPI] = {
4284 .type = HDA_FIXUP_FUNC,
4285 .v.func = alc_fixup_thinkpad_acpi,
b67ae3f1 4286 },
9a22a8f5
KY
4287 [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
4288 .type = HDA_FIXUP_PINS,
4289 .v.pins = (const struct hda_pintbl[]) {
4290 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4291 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
4292 { }
4293 },
4294 .chained = true,
4295 .chain_id = ALC255_FIXUP_HEADSET_MODE
4296 },
4297 [ALC255_FIXUP_HEADSET_MODE] = {
4298 .type = HDA_FIXUP_FUNC,
4299 .v.func = alc_fixup_headset_mode_alc255,
4300 },
f1d4e28b
KY
4301};
4302
1d045db9 4303static const struct snd_pci_quirk alc269_fixup_tbl[] = {
693b613d
DH
4304 SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
4305 SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
aaedfb47
DH
4306 SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
4307 SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
4308 SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
4309 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
b1e8972e 4310 SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
aaedfb47 4311 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
73bdd597
DH
4312 SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4313 SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4314 SND_PCI_QUIRK(0x1028, 0x05c4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4315 SND_PCI_QUIRK(0x1028, 0x05c5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4316 SND_PCI_QUIRK(0x1028, 0x05c6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4317 SND_PCI_QUIRK(0x1028, 0x05c7, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4318 SND_PCI_QUIRK(0x1028, 0x05c8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4319 SND_PCI_QUIRK(0x1028, 0x05c9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4320 SND_PCI_QUIRK(0x1028, 0x05ca, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4321 SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
05843c07
KY
4322 SND_PCI_QUIRK(0x1028, 0x05cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4323 SND_PCI_QUIRK(0x1028, 0x05cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
0f4881dc 4324 SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
436c4a0c 4325 SND_PCI_QUIRK(0x1028, 0x05de, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
d81bf8cf 4326 SND_PCI_QUIRK(0x1028, 0x05e0, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
73bdd597
DH
4327 SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4328 SND_PCI_QUIRK(0x1028, 0x05ea, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4329 SND_PCI_QUIRK(0x1028, 0x05eb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4330 SND_PCI_QUIRK(0x1028, 0x05ec, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4331 SND_PCI_QUIRK(0x1028, 0x05ed, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4332 SND_PCI_QUIRK(0x1028, 0x05ee, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4333 SND_PCI_QUIRK(0x1028, 0x05f3, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4334 SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4335 SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4336 SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
3ee2102f 4337 SND_PCI_QUIRK(0x1028, 0x05f8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
cd6fb679
DH
4338 SND_PCI_QUIRK(0x1028, 0x05f9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4339 SND_PCI_QUIRK(0x1028, 0x05fb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
d81bf8cf
DH
4340 SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4341 SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
3ee2102f 4342 SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
c29cb5eb 4343 SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
6c29d68a 4344 SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
b8362e70 4345 SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
0f4881dc
DH
4346 SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
4347 SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
9a22a8f5 4348 SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
c29cb5eb 4349 SND_PCI_QUIRK(0x1028, 0x0629, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
0f4881dc 4350 SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
c29cb5eb 4351 SND_PCI_QUIRK(0x1028, 0x063e, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
9a22a8f5 4352 SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
3a6c5d8a 4353 SND_PCI_QUIRK(0x1028, 0x0640, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
05843c07
KY
4354 SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4355 SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
08fb0d0e 4356 SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
9f5c6faf 4357 SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
d06ac143
DH
4358 SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4359 SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
8e35cd4a 4360 SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
08fb0d0e 4361 SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
7bba2157 4362 SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
3e0d611b
DH
4363 SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
4364 SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
2cede303
OR
4365 SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
4366 SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK),
3e0d611b 4367 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
017f2a10 4368 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
693b613d 4369 SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
3e0d611b 4370 SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
adabb3ec
TI
4371 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
4372 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
4373 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
4374 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
d240d1dc 4375 SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
88cfcf86 4376 SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
1d045db9
TI
4377 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
4378 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4379 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
4380 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
24519911 4381 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
1d045db9
TI
4382 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
4383 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
4384 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
4385 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
4386 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
707fba3f 4387 SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),
c8415a48 4388 SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
84f98fdf 4389 SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
4407be6b 4390 SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
108cc108 4391 SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
aaedfb47 4392 SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
cd5302c0
DH
4393 SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
4394 SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
2793769f 4395 SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
a4a9e082
DH
4396 SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
4397 SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
1bb3e062 4398 SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
cd5302c0
DH
4399 SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
4400 SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
012e7eb1 4401 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
1d045db9 4402 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
2793769f 4403 SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
02b504d9 4404 SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
a4297b5d 4405
a7f3eedc 4406#if 0
a4297b5d
TI
4407 /* Below is a quirk table taken from the old code.
4408 * Basically the device should work as is without the fixup table.
4409 * If BIOS doesn't give a proper info, enable the corresponding
4410 * fixup entry.
7d7eb9ea 4411 */
a4297b5d
TI
4412 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
4413 ALC269_FIXUP_AMIC),
4414 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
a4297b5d
TI
4415 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
4416 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
4417 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
4418 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269_FIXUP_AMIC),
4419 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269_FIXUP_AMIC),
4420 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269_FIXUP_AMIC),
4421 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_FIXUP_AMIC),
4422 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269_FIXUP_AMIC),
4423 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_FIXUP_AMIC),
4424 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_FIXUP_AMIC),
4425 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_FIXUP_AMIC),
4426 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_FIXUP_AMIC),
4427 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_FIXUP_AMIC),
4428 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_FIXUP_AMIC),
4429 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_FIXUP_AMIC),
4430 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_FIXUP_AMIC),
4431 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_FIXUP_AMIC),
4432 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_FIXUP_AMIC),
4433 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_FIXUP_AMIC),
4434 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_FIXUP_AMIC),
4435 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_FIXUP_AMIC),
4436 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_FIXUP_AMIC),
4437 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_FIXUP_AMIC),
4438 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_FIXUP_AMIC),
4439 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_FIXUP_AMIC),
4440 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_FIXUP_AMIC),
4441 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_FIXUP_AMIC),
4442 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_FIXUP_AMIC),
4443 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_FIXUP_AMIC),
4444 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_FIXUP_AMIC),
4445 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_FIXUP_AMIC),
4446 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_FIXUP_AMIC),
4447 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_FIXUP_AMIC),
4448 SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_FIXUP_DMIC),
4449 SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_FIXUP_AMIC),
4450 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_AMIC),
4451 SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_FIXUP_DMIC),
4452 SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_FIXUP_DMIC),
4453#endif
4454 {}
4455};
4456
1727a771 4457static const struct hda_model_fixup alc269_fixup_models[] = {
a4297b5d
TI
4458 {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
4459 {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
6e72aa5f
TI
4460 {.id = ALC269_FIXUP_STEREO_DMIC, .name = "alc269-dmic"},
4461 {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"},
4462 {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"},
7c478f03 4463 {.id = ALC269_FIXUP_HEADSET_MIC, .name = "headset-mic"},
108cc108 4464 {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"},
9f5c6faf 4465 {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
e32aa85a
DH
4466 {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
4467 {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
0202e99c
KY
4468 {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-chrome"},
4469 {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
1d045db9 4470 {}
6dda9f4a
KY
4471};
4472
6dda9f4a 4473
546bb678 4474static void alc269_fill_coef(struct hda_codec *codec)
1d045db9 4475{
526af6eb 4476 struct alc_spec *spec = codec->spec;
1d045db9 4477 int val;
ebb83eeb 4478
526af6eb 4479 if (spec->codec_variant != ALC269_TYPE_ALC269VB)
546bb678 4480 return;
526af6eb 4481
1bb7e43e 4482 if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
1d045db9
TI
4483 alc_write_coef_idx(codec, 0xf, 0x960b);
4484 alc_write_coef_idx(codec, 0xe, 0x8817);
4485 }
ebb83eeb 4486
1bb7e43e 4487 if ((alc_get_coef0(codec) & 0x00ff) == 0x016) {
1d045db9
TI
4488 alc_write_coef_idx(codec, 0xf, 0x960b);
4489 alc_write_coef_idx(codec, 0xe, 0x8814);
4490 }
ebb83eeb 4491
1bb7e43e 4492 if ((alc_get_coef0(codec) & 0x00ff) == 0x017) {
1d045db9
TI
4493 val = alc_read_coef_idx(codec, 0x04);
4494 /* Power up output pin */
4495 alc_write_coef_idx(codec, 0x04, val | (1<<11));
4496 }
ebb83eeb 4497
1bb7e43e 4498 if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
1d045db9
TI
4499 val = alc_read_coef_idx(codec, 0xd);
4500 if ((val & 0x0c00) >> 10 != 0x1) {
4501 /* Capless ramp up clock control */
4502 alc_write_coef_idx(codec, 0xd, val | (1<<10));
4503 }
4504 val = alc_read_coef_idx(codec, 0x17);
4505 if ((val & 0x01c0) >> 6 != 0x4) {
4506 /* Class D power on reset */
4507 alc_write_coef_idx(codec, 0x17, val | (1<<7));
4508 }
4509 }
ebb83eeb 4510
1d045db9
TI
4511 val = alc_read_coef_idx(codec, 0xd); /* Class D */
4512 alc_write_coef_idx(codec, 0xd, val | (1<<14));
bc9f98a9 4513
1d045db9
TI
4514 val = alc_read_coef_idx(codec, 0x4); /* HP */
4515 alc_write_coef_idx(codec, 0x4, val | (1<<11));
1d045db9 4516}
a7f2371f 4517
1d045db9
TI
4518/*
4519 */
1d045db9
TI
4520static int patch_alc269(struct hda_codec *codec)
4521{
4522 struct alc_spec *spec;
3de95173 4523 int err;
f1d4e28b 4524
3de95173 4525 err = alc_alloc_spec(codec, 0x0b);
e16fb6d1 4526 if (err < 0)
3de95173
TI
4527 return err;
4528
4529 spec = codec->spec;
08c189f2 4530 spec->gen.shared_mic_vref_pin = 0x18;
e16fb6d1 4531
1727a771 4532 snd_hda_pick_fixup(codec, alc269_fixup_models,
9f720bb9 4533 alc269_fixup_tbl, alc269_fixups);
1727a771 4534 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
9f720bb9
HRK
4535
4536 alc_auto_parse_customize_define(codec);
4537
7504b6cd
TI
4538 if (has_cdefine_beep(codec))
4539 spec->gen.beep_nid = 0x01;
4540
065380f0
KY
4541 switch (codec->vendor_id) {
4542 case 0x10ec0269:
1d045db9 4543 spec->codec_variant = ALC269_TYPE_ALC269VA;
1bb7e43e
TI
4544 switch (alc_get_coef0(codec) & 0x00f0) {
4545 case 0x0010:
1d045db9 4546 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
e16fb6d1 4547 spec->cdefine.platform_type == 1)
20ca0c35 4548 err = alc_codec_rename(codec, "ALC271X");
1d045db9 4549 spec->codec_variant = ALC269_TYPE_ALC269VB;
1bb7e43e
TI
4550 break;
4551 case 0x0020:
e16fb6d1
TI
4552 if (codec->bus->pci->subsystem_vendor == 0x17aa &&
4553 codec->bus->pci->subsystem_device == 0x21f3)
20ca0c35 4554 err = alc_codec_rename(codec, "ALC3202");
1d045db9 4555 spec->codec_variant = ALC269_TYPE_ALC269VC;
1bb7e43e 4556 break;
adcc70b2
KY
4557 case 0x0030:
4558 spec->codec_variant = ALC269_TYPE_ALC269VD;
4559 break;
1bb7e43e 4560 default:
1d045db9 4561 alc_fix_pll_init(codec, 0x20, 0x04, 15);
1bb7e43e 4562 }
e16fb6d1
TI
4563 if (err < 0)
4564 goto error;
546bb678 4565 spec->init_hook = alc269_fill_coef;
1d045db9 4566 alc269_fill_coef(codec);
065380f0
KY
4567 break;
4568
4569 case 0x10ec0280:
4570 case 0x10ec0290:
4571 spec->codec_variant = ALC269_TYPE_ALC280;
4572 break;
4573 case 0x10ec0282:
065380f0
KY
4574 spec->codec_variant = ALC269_TYPE_ALC282;
4575 break;
2af02be7
KY
4576 case 0x10ec0233:
4577 case 0x10ec0283:
4578 spec->codec_variant = ALC269_TYPE_ALC283;
4579 spec->shutup = alc283_shutup;
4580 spec->init_hook = alc283_init;
4581 break;
065380f0
KY
4582 case 0x10ec0284:
4583 case 0x10ec0292:
4584 spec->codec_variant = ALC269_TYPE_ALC284;
4585 break;
161ebf29
KY
4586 case 0x10ec0285:
4587 case 0x10ec0293:
4588 spec->codec_variant = ALC269_TYPE_ALC285;
4589 break;
7fc7d047
KY
4590 case 0x10ec0286:
4591 spec->codec_variant = ALC269_TYPE_ALC286;
4592 break;
1d04c9de
KY
4593 case 0x10ec0255:
4594 spec->codec_variant = ALC269_TYPE_ALC255;
4595 break;
1d045db9 4596 }
6dda9f4a 4597
ad60d502 4598 if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
97a26570 4599 spec->has_alc5505_dsp = 1;
ad60d502
KY
4600 spec->init_hook = alc5505_dsp_init;
4601 }
4602
a4297b5d
TI
4603 /* automatic parse from the BIOS config */
4604 err = alc269_parse_auto_config(codec);
e16fb6d1
TI
4605 if (err < 0)
4606 goto error;
6dda9f4a 4607
7504b6cd 4608 if (!spec->gen.no_analog && spec->gen.beep_nid)
1d045db9 4609 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
f1d4e28b 4610
1d045db9 4611 codec->patch_ops = alc_patch_ops;
2a43952a 4612#ifdef CONFIG_PM
ad60d502 4613 codec->patch_ops.suspend = alc269_suspend;
1d045db9
TI
4614 codec->patch_ops.resume = alc269_resume;
4615#endif
c5177c86
KY
4616 if (!spec->shutup)
4617 spec->shutup = alc269_shutup;
ebb83eeb 4618
1727a771 4619 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 4620
1d045db9 4621 return 0;
e16fb6d1
TI
4622
4623 error:
4624 alc_free(codec);
4625 return err;
1d045db9 4626}
f1d4e28b 4627
1d045db9
TI
4628/*
4629 * ALC861
4630 */
622e84cd 4631
1d045db9 4632static int alc861_parse_auto_config(struct hda_codec *codec)
6dda9f4a 4633{
1d045db9 4634 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
3e6179b8
TI
4635 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
4636 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
604401a9
TI
4637}
4638
1d045db9
TI
4639/* Pin config fixes */
4640enum {
e652f4c8
TI
4641 ALC861_FIXUP_FSC_AMILO_PI1505,
4642 ALC861_FIXUP_AMP_VREF_0F,
4643 ALC861_FIXUP_NO_JACK_DETECT,
4644 ALC861_FIXUP_ASUS_A6RP,
6ddf0fd1 4645 ALC660_FIXUP_ASUS_W7J,
1d045db9 4646};
7085ec12 4647
31150f23
TI
4648/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
4649static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
1727a771 4650 const struct hda_fixup *fix, int action)
31150f23
TI
4651{
4652 struct alc_spec *spec = codec->spec;
4653 unsigned int val;
4654
1727a771 4655 if (action != HDA_FIXUP_ACT_INIT)
31150f23 4656 return;
d3f02d60 4657 val = snd_hda_codec_get_pin_target(codec, 0x0f);
31150f23
TI
4658 if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
4659 val |= AC_PINCTL_IN_EN;
4660 val |= AC_PINCTL_VREF_50;
cdd03ced 4661 snd_hda_set_pin_ctl(codec, 0x0f, val);
08c189f2 4662 spec->gen.keep_vref_in_automute = 1;
31150f23
TI
4663}
4664
e652f4c8
TI
4665/* suppress the jack-detection */
4666static void alc_fixup_no_jack_detect(struct hda_codec *codec,
1727a771 4667 const struct hda_fixup *fix, int action)
e652f4c8 4668{
1727a771 4669 if (action == HDA_FIXUP_ACT_PRE_PROBE)
e652f4c8 4670 codec->no_jack_detect = 1;
7d7eb9ea 4671}
e652f4c8 4672
1727a771 4673static const struct hda_fixup alc861_fixups[] = {
e652f4c8 4674 [ALC861_FIXUP_FSC_AMILO_PI1505] = {
1727a771
TI
4675 .type = HDA_FIXUP_PINS,
4676 .v.pins = (const struct hda_pintbl[]) {
1d045db9
TI
4677 { 0x0b, 0x0221101f }, /* HP */
4678 { 0x0f, 0x90170310 }, /* speaker */
4679 { }
4680 }
4681 },
e652f4c8 4682 [ALC861_FIXUP_AMP_VREF_0F] = {
1727a771 4683 .type = HDA_FIXUP_FUNC,
31150f23 4684 .v.func = alc861_fixup_asus_amp_vref_0f,
3b25eb69 4685 },
e652f4c8 4686 [ALC861_FIXUP_NO_JACK_DETECT] = {
1727a771 4687 .type = HDA_FIXUP_FUNC,
e652f4c8
TI
4688 .v.func = alc_fixup_no_jack_detect,
4689 },
4690 [ALC861_FIXUP_ASUS_A6RP] = {
1727a771 4691 .type = HDA_FIXUP_FUNC,
e652f4c8
TI
4692 .v.func = alc861_fixup_asus_amp_vref_0f,
4693 .chained = true,
4694 .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
6ddf0fd1
TI
4695 },
4696 [ALC660_FIXUP_ASUS_W7J] = {
4697 .type = HDA_FIXUP_VERBS,
4698 .v.verbs = (const struct hda_verb[]) {
4699 /* ASUS W7J needs a magic pin setup on unused NID 0x10
4700 * for enabling outputs
4701 */
4702 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
4703 { }
4704 },
e652f4c8 4705 }
1d045db9 4706};
7085ec12 4707
1d045db9 4708static const struct snd_pci_quirk alc861_fixup_tbl[] = {
6ddf0fd1 4709 SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
e7ca237b 4710 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
e652f4c8
TI
4711 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
4712 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
4713 SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
4714 SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F),
4715 SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F),
4716 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
1d045db9
TI
4717 {}
4718};
3af9ee6b 4719
1d045db9
TI
4720/*
4721 */
1d045db9 4722static int patch_alc861(struct hda_codec *codec)
7085ec12 4723{
1d045db9 4724 struct alc_spec *spec;
1d045db9 4725 int err;
7085ec12 4726
3de95173
TI
4727 err = alc_alloc_spec(codec, 0x15);
4728 if (err < 0)
4729 return err;
1d045db9 4730
3de95173 4731 spec = codec->spec;
7504b6cd 4732 spec->gen.beep_nid = 0x23;
1d045db9 4733
1727a771
TI
4734 snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
4735 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
3af9ee6b 4736
cb4e4824
TI
4737 /* automatic parse from the BIOS config */
4738 err = alc861_parse_auto_config(codec);
e16fb6d1
TI
4739 if (err < 0)
4740 goto error;
3af9ee6b 4741
7504b6cd 4742 if (!spec->gen.no_analog)
3e6179b8 4743 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
7085ec12 4744
1d045db9 4745 codec->patch_ops = alc_patch_ops;
83012a7c 4746#ifdef CONFIG_PM
cb4e4824 4747 spec->power_hook = alc_power_eapd;
1d045db9
TI
4748#endif
4749
1727a771 4750 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 4751
1d045db9 4752 return 0;
e16fb6d1
TI
4753
4754 error:
4755 alc_free(codec);
4756 return err;
7085ec12
TI
4757}
4758
1d045db9
TI
4759/*
4760 * ALC861-VD support
4761 *
4762 * Based on ALC882
4763 *
4764 * In addition, an independent DAC
4765 */
1d045db9 4766static int alc861vd_parse_auto_config(struct hda_codec *codec)
bc9f98a9 4767{
1d045db9 4768 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
3e6179b8
TI
4769 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4770 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
ce764ab2
TI
4771}
4772
1d045db9 4773enum {
8fdcb6fe
TI
4774 ALC660VD_FIX_ASUS_GPIO1,
4775 ALC861VD_FIX_DALLAS,
1d045db9 4776};
ce764ab2 4777
8fdcb6fe
TI
4778/* exclude VREF80 */
4779static void alc861vd_fixup_dallas(struct hda_codec *codec,
1727a771 4780 const struct hda_fixup *fix, int action)
8fdcb6fe 4781{
1727a771 4782 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
b78562b1
TI
4783 snd_hda_override_pin_caps(codec, 0x18, 0x00000734);
4784 snd_hda_override_pin_caps(codec, 0x19, 0x0000073c);
8fdcb6fe
TI
4785 }
4786}
4787
1727a771 4788static const struct hda_fixup alc861vd_fixups[] = {
1d045db9 4789 [ALC660VD_FIX_ASUS_GPIO1] = {
1727a771 4790 .type = HDA_FIXUP_VERBS,
1d045db9 4791 .v.verbs = (const struct hda_verb[]) {
8fdcb6fe 4792 /* reset GPIO1 */
1d045db9
TI
4793 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
4794 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
4795 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
4796 { }
4797 }
4798 },
8fdcb6fe 4799 [ALC861VD_FIX_DALLAS] = {
1727a771 4800 .type = HDA_FIXUP_FUNC,
8fdcb6fe
TI
4801 .v.func = alc861vd_fixup_dallas,
4802 },
1d045db9 4803};
ce764ab2 4804
1d045db9 4805static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
8fdcb6fe 4806 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS),
1d045db9 4807 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
8fdcb6fe 4808 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS),
1d045db9
TI
4809 {}
4810};
ce764ab2 4811
1d045db9
TI
4812/*
4813 */
1d045db9 4814static int patch_alc861vd(struct hda_codec *codec)
ce764ab2 4815{
1d045db9 4816 struct alc_spec *spec;
cb4e4824 4817 int err;
ce764ab2 4818
3de95173
TI
4819 err = alc_alloc_spec(codec, 0x0b);
4820 if (err < 0)
4821 return err;
1d045db9 4822
3de95173 4823 spec = codec->spec;
7504b6cd 4824 spec->gen.beep_nid = 0x23;
1d045db9 4825
1727a771
TI
4826 snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
4827 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1d045db9 4828
cb4e4824
TI
4829 /* automatic parse from the BIOS config */
4830 err = alc861vd_parse_auto_config(codec);
e16fb6d1
TI
4831 if (err < 0)
4832 goto error;
ce764ab2 4833
7504b6cd 4834 if (!spec->gen.no_analog)
3e6179b8 4835 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
1d045db9 4836
1d045db9
TI
4837 codec->patch_ops = alc_patch_ops;
4838
1d045db9 4839 spec->shutup = alc_eapd_shutup;
1d045db9 4840
1727a771 4841 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 4842
ce764ab2 4843 return 0;
e16fb6d1
TI
4844
4845 error:
4846 alc_free(codec);
4847 return err;
ce764ab2
TI
4848}
4849
1d045db9
TI
4850/*
4851 * ALC662 support
4852 *
4853 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
4854 * configuration. Each pin widget can choose any input DACs and a mixer.
4855 * Each ADC is connected from a mixer of all inputs. This makes possible
4856 * 6-channel independent captures.
4857 *
4858 * In addition, an independent DAC for the multi-playback (not used in this
4859 * driver yet).
4860 */
1d045db9
TI
4861
4862/*
4863 * BIOS auto configuration
4864 */
4865
bc9f98a9
KY
4866static int alc662_parse_auto_config(struct hda_codec *codec)
4867{
4c6d72d1 4868 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
3e6179b8
TI
4869 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
4870 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
4871 const hda_nid_t *ssids;
ee979a14 4872
6227cdce 4873 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
1d87caa6
RK
4874 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670 ||
4875 codec->vendor_id == 0x10ec0671)
3e6179b8 4876 ssids = alc663_ssids;
6227cdce 4877 else
3e6179b8
TI
4878 ssids = alc662_ssids;
4879 return alc_parse_auto_config(codec, alc662_ignore, ssids);
bc9f98a9
KY
4880}
4881
6be7948f 4882static void alc272_fixup_mario(struct hda_codec *codec,
1727a771 4883 const struct hda_fixup *fix, int action)
6fc398cb 4884{
9bb1f06f 4885 if (action != HDA_FIXUP_ACT_PRE_PROBE)
6fc398cb 4886 return;
6be7948f
TB
4887 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
4888 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
4889 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
4890 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4891 (0 << AC_AMPCAP_MUTE_SHIFT)))
4892 printk(KERN_WARNING
4893 "hda_codec: failed to override amp caps for NID 0x2\n");
4894}
4895
8e383953
TI
4896static const struct snd_pcm_chmap_elem asus_pcm_2_1_chmaps[] = {
4897 { .channels = 2,
4898 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
4899 { .channels = 4,
4900 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
4901 SNDRV_CHMAP_NA, SNDRV_CHMAP_LFE } }, /* LFE only on right */
4902 { }
4903};
4904
4905/* override the 2.1 chmap */
eb9ca3ab 4906static void alc_fixup_bass_chmap(struct hda_codec *codec,
8e383953
TI
4907 const struct hda_fixup *fix, int action)
4908{
4909 if (action == HDA_FIXUP_ACT_BUILD) {
4910 struct alc_spec *spec = codec->spec;
4911 spec->gen.pcm_rec[0].stream[0].chmap = asus_pcm_2_1_chmaps;
4912 }
4913}
4914
6cb3b707 4915enum {
2df03514 4916 ALC662_FIXUP_ASPIRE,
6cb3b707 4917 ALC662_FIXUP_IDEAPAD,
6be7948f 4918 ALC272_FIXUP_MARIO,
d2ebd479 4919 ALC662_FIXUP_CZC_P10T,
94024cd1 4920 ALC662_FIXUP_SKU_IGNORE,
e59ea3ed 4921 ALC662_FIXUP_HP_RP5800,
53c334ad
TI
4922 ALC662_FIXUP_ASUS_MODE1,
4923 ALC662_FIXUP_ASUS_MODE2,
4924 ALC662_FIXUP_ASUS_MODE3,
4925 ALC662_FIXUP_ASUS_MODE4,
4926 ALC662_FIXUP_ASUS_MODE5,
4927 ALC662_FIXUP_ASUS_MODE6,
4928 ALC662_FIXUP_ASUS_MODE7,
4929 ALC662_FIXUP_ASUS_MODE8,
1565cc35 4930 ALC662_FIXUP_NO_JACK_DETECT,
edfe3bfc 4931 ALC662_FIXUP_ZOTAC_Z68,
125821ae 4932 ALC662_FIXUP_INV_DMIC,
73bdd597
DH
4933 ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
4934 ALC668_FIXUP_HEADSET_MODE,
8e383953 4935 ALC662_FIXUP_BASS_CHMAP,
a30c9aaa
TI
4936 ALC662_FIXUP_BASS_1A,
4937 ALC662_FIXUP_BASS_1A_CHMAP,
6cb3b707
DH
4938};
4939
1727a771 4940static const struct hda_fixup alc662_fixups[] = {
2df03514 4941 [ALC662_FIXUP_ASPIRE] = {
1727a771
TI
4942 .type = HDA_FIXUP_PINS,
4943 .v.pins = (const struct hda_pintbl[]) {
2df03514
DC
4944 { 0x15, 0x99130112 }, /* subwoofer */
4945 { }
4946 }
4947 },
6cb3b707 4948 [ALC662_FIXUP_IDEAPAD] = {
1727a771
TI
4949 .type = HDA_FIXUP_PINS,
4950 .v.pins = (const struct hda_pintbl[]) {
6cb3b707
DH
4951 { 0x17, 0x99130112 }, /* subwoofer */
4952 { }
4953 }
4954 },
6be7948f 4955 [ALC272_FIXUP_MARIO] = {
1727a771 4956 .type = HDA_FIXUP_FUNC,
b5bfbc67 4957 .v.func = alc272_fixup_mario,
d2ebd479
AA
4958 },
4959 [ALC662_FIXUP_CZC_P10T] = {
1727a771 4960 .type = HDA_FIXUP_VERBS,
d2ebd479
AA
4961 .v.verbs = (const struct hda_verb[]) {
4962 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4963 {}
4964 }
4965 },
94024cd1 4966 [ALC662_FIXUP_SKU_IGNORE] = {
1727a771 4967 .type = HDA_FIXUP_FUNC,
23d30f28 4968 .v.func = alc_fixup_sku_ignore,
c6b35874 4969 },
e59ea3ed 4970 [ALC662_FIXUP_HP_RP5800] = {
1727a771
TI
4971 .type = HDA_FIXUP_PINS,
4972 .v.pins = (const struct hda_pintbl[]) {
e59ea3ed
TI
4973 { 0x14, 0x0221201f }, /* HP out */
4974 { }
4975 },
4976 .chained = true,
4977 .chain_id = ALC662_FIXUP_SKU_IGNORE
4978 },
53c334ad 4979 [ALC662_FIXUP_ASUS_MODE1] = {
1727a771
TI
4980 .type = HDA_FIXUP_PINS,
4981 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
4982 { 0x14, 0x99130110 }, /* speaker */
4983 { 0x18, 0x01a19c20 }, /* mic */
4984 { 0x19, 0x99a3092f }, /* int-mic */
4985 { 0x21, 0x0121401f }, /* HP out */
4986 { }
4987 },
4988 .chained = true,
4989 .chain_id = ALC662_FIXUP_SKU_IGNORE
4990 },
4991 [ALC662_FIXUP_ASUS_MODE2] = {
1727a771
TI
4992 .type = HDA_FIXUP_PINS,
4993 .v.pins = (const struct hda_pintbl[]) {
2996bdba
TI
4994 { 0x14, 0x99130110 }, /* speaker */
4995 { 0x18, 0x01a19820 }, /* mic */
4996 { 0x19, 0x99a3092f }, /* int-mic */
4997 { 0x1b, 0x0121401f }, /* HP out */
4998 { }
4999 },
53c334ad
TI
5000 .chained = true,
5001 .chain_id = ALC662_FIXUP_SKU_IGNORE
5002 },
5003 [ALC662_FIXUP_ASUS_MODE3] = {
1727a771
TI
5004 .type = HDA_FIXUP_PINS,
5005 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5006 { 0x14, 0x99130110 }, /* speaker */
5007 { 0x15, 0x0121441f }, /* HP */
5008 { 0x18, 0x01a19840 }, /* mic */
5009 { 0x19, 0x99a3094f }, /* int-mic */
5010 { 0x21, 0x01211420 }, /* HP2 */
5011 { }
5012 },
5013 .chained = true,
5014 .chain_id = ALC662_FIXUP_SKU_IGNORE
5015 },
5016 [ALC662_FIXUP_ASUS_MODE4] = {
1727a771
TI
5017 .type = HDA_FIXUP_PINS,
5018 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5019 { 0x14, 0x99130110 }, /* speaker */
5020 { 0x16, 0x99130111 }, /* speaker */
5021 { 0x18, 0x01a19840 }, /* mic */
5022 { 0x19, 0x99a3094f }, /* int-mic */
5023 { 0x21, 0x0121441f }, /* HP */
5024 { }
5025 },
5026 .chained = true,
5027 .chain_id = ALC662_FIXUP_SKU_IGNORE
5028 },
5029 [ALC662_FIXUP_ASUS_MODE5] = {
1727a771
TI
5030 .type = HDA_FIXUP_PINS,
5031 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5032 { 0x14, 0x99130110 }, /* speaker */
5033 { 0x15, 0x0121441f }, /* HP */
5034 { 0x16, 0x99130111 }, /* speaker */
5035 { 0x18, 0x01a19840 }, /* mic */
5036 { 0x19, 0x99a3094f }, /* int-mic */
5037 { }
5038 },
5039 .chained = true,
5040 .chain_id = ALC662_FIXUP_SKU_IGNORE
5041 },
5042 [ALC662_FIXUP_ASUS_MODE6] = {
1727a771
TI
5043 .type = HDA_FIXUP_PINS,
5044 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5045 { 0x14, 0x99130110 }, /* speaker */
5046 { 0x15, 0x01211420 }, /* HP2 */
5047 { 0x18, 0x01a19840 }, /* mic */
5048 { 0x19, 0x99a3094f }, /* int-mic */
5049 { 0x1b, 0x0121441f }, /* HP */
5050 { }
5051 },
5052 .chained = true,
5053 .chain_id = ALC662_FIXUP_SKU_IGNORE
5054 },
5055 [ALC662_FIXUP_ASUS_MODE7] = {
1727a771
TI
5056 .type = HDA_FIXUP_PINS,
5057 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5058 { 0x14, 0x99130110 }, /* speaker */
5059 { 0x17, 0x99130111 }, /* speaker */
5060 { 0x18, 0x01a19840 }, /* mic */
5061 { 0x19, 0x99a3094f }, /* int-mic */
5062 { 0x1b, 0x01214020 }, /* HP */
5063 { 0x21, 0x0121401f }, /* HP */
5064 { }
5065 },
5066 .chained = true,
5067 .chain_id = ALC662_FIXUP_SKU_IGNORE
5068 },
5069 [ALC662_FIXUP_ASUS_MODE8] = {
1727a771
TI
5070 .type = HDA_FIXUP_PINS,
5071 .v.pins = (const struct hda_pintbl[]) {
53c334ad
TI
5072 { 0x14, 0x99130110 }, /* speaker */
5073 { 0x12, 0x99a30970 }, /* int-mic */
5074 { 0x15, 0x01214020 }, /* HP */
5075 { 0x17, 0x99130111 }, /* speaker */
5076 { 0x18, 0x01a19840 }, /* mic */
5077 { 0x21, 0x0121401f }, /* HP */
5078 { }
5079 },
5080 .chained = true,
5081 .chain_id = ALC662_FIXUP_SKU_IGNORE
2996bdba 5082 },
1565cc35 5083 [ALC662_FIXUP_NO_JACK_DETECT] = {
1727a771 5084 .type = HDA_FIXUP_FUNC,
1565cc35
TI
5085 .v.func = alc_fixup_no_jack_detect,
5086 },
edfe3bfc 5087 [ALC662_FIXUP_ZOTAC_Z68] = {
1727a771
TI
5088 .type = HDA_FIXUP_PINS,
5089 .v.pins = (const struct hda_pintbl[]) {
edfe3bfc
DH
5090 { 0x1b, 0x02214020 }, /* Front HP */
5091 { }
5092 }
5093 },
125821ae 5094 [ALC662_FIXUP_INV_DMIC] = {
1727a771 5095 .type = HDA_FIXUP_FUNC,
6e72aa5f 5096 .v.func = alc_fixup_inv_dmic_0x12,
125821ae 5097 },
73bdd597
DH
5098 [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
5099 .type = HDA_FIXUP_PINS,
5100 .v.pins = (const struct hda_pintbl[]) {
5101 { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
5102 { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
5103 { }
5104 },
5105 .chained = true,
5106 .chain_id = ALC668_FIXUP_HEADSET_MODE
5107 },
5108 [ALC668_FIXUP_HEADSET_MODE] = {
5109 .type = HDA_FIXUP_FUNC,
5110 .v.func = alc_fixup_headset_mode_alc668,
5111 },
8e383953
TI
5112 [ALC662_FIXUP_BASS_CHMAP] = {
5113 .type = HDA_FIXUP_FUNC,
eb9ca3ab 5114 .v.func = alc_fixup_bass_chmap,
8e383953
TI
5115 .chained = true,
5116 .chain_id = ALC662_FIXUP_ASUS_MODE4
5117 },
a30c9aaa
TI
5118 [ALC662_FIXUP_BASS_1A] = {
5119 .type = HDA_FIXUP_PINS,
5120 .v.pins = (const struct hda_pintbl[]) {
5121 {0x1a, 0x80106111}, /* bass speaker */
5122 {}
5123 },
5124 },
5125 [ALC662_FIXUP_BASS_1A_CHMAP] = {
5126 .type = HDA_FIXUP_FUNC,
eb9ca3ab 5127 .v.func = alc_fixup_bass_chmap,
a30c9aaa
TI
5128 .chained = true,
5129 .chain_id = ALC662_FIXUP_BASS_1A,
5130 },
6cb3b707
DH
5131};
5132
a9111321 5133static const struct snd_pci_quirk alc662_fixup_tbl[] = {
53c334ad 5134 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
d3d3835c 5135 SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
a6c47a85 5136 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
94024cd1 5137 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
125821ae 5138 SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
1801928e 5139 SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
2df03514 5140 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
73bdd597
DH
5141 SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
5142 SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
6c6eb427 5143 SND_PCI_QUIRK(0x1028, 0x0623, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
7dca4bc6 5144 SND_PCI_QUIRK(0x1028, 0x0624, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
09d2014f 5145 SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
ad8ff99e 5146 SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
0dfb9809 5147 SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
e59ea3ed 5148 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
a30c9aaa 5149 SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A_CHMAP),
8e383953
TI
5150 SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_CHMAP),
5151 SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_CHMAP),
1565cc35 5152 SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
53c334ad 5153 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
a0e90acc 5154 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
d4118588 5155 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
6cb3b707 5156 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
edfe3bfc 5157 SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68),
d2ebd479 5158 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
53c334ad
TI
5159
5160#if 0
5161 /* Below is a quirk table taken from the old code.
5162 * Basically the device should work as is without the fixup table.
5163 * If BIOS doesn't give a proper info, enable the corresponding
5164 * fixup entry.
7d7eb9ea 5165 */
53c334ad
TI
5166 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
5167 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
5168 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
5169 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
5170 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5171 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5172 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5173 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
5174 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
5175 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5176 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
5177 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
5178 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
5179 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
5180 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
5181 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5182 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
5183 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
5184 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5185 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
5186 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
5187 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5188 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
5189 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
5190 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
5191 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5192 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
5193 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
5194 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5195 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
5196 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5197 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5198 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
5199 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
5200 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
5201 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
5202 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
5203 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
5204 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
5205 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
5206 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
5207 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
5208 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5209 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
5210 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
5211 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
5212 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
5213 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
5214 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
5215 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
5216#endif
6cb3b707
DH
5217 {}
5218};
5219
1727a771 5220static const struct hda_model_fixup alc662_fixup_models[] = {
6be7948f 5221 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
53c334ad
TI
5222 {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
5223 {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
5224 {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
5225 {.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
5226 {.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
5227 {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
5228 {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
5229 {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
6e72aa5f 5230 {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
e32aa85a 5231 {.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
6be7948f
TB
5232 {}
5233};
6cb3b707 5234
8663ff75
KY
5235static void alc662_fill_coef(struct hda_codec *codec)
5236{
5237 int val, coef;
5238
5239 coef = alc_get_coef0(codec);
5240
5241 switch (codec->vendor_id) {
5242 case 0x10ec0662:
5243 if ((coef & 0x00f0) == 0x0030) {
5244 val = alc_read_coef_idx(codec, 0x4); /* EAPD Ctrl */
5245 alc_write_coef_idx(codec, 0x4, val & ~(1<<10));
5246 }
5247 break;
5248 case 0x10ec0272:
5249 case 0x10ec0273:
5250 case 0x10ec0663:
5251 case 0x10ec0665:
5252 case 0x10ec0670:
5253 case 0x10ec0671:
5254 case 0x10ec0672:
5255 val = alc_read_coef_idx(codec, 0xd); /* EAPD Ctrl */
5256 alc_write_coef_idx(codec, 0xd, val | (1<<14));
5257 break;
5258 }
5259}
6cb3b707 5260
1d045db9
TI
5261/*
5262 */
bc9f98a9
KY
5263static int patch_alc662(struct hda_codec *codec)
5264{
5265 struct alc_spec *spec;
3de95173 5266 int err;
bc9f98a9 5267
3de95173
TI
5268 err = alc_alloc_spec(codec, 0x0b);
5269 if (err < 0)
5270 return err;
bc9f98a9 5271
3de95173 5272 spec = codec->spec;
1f0f4b80 5273
53c334ad
TI
5274 /* handle multiple HPs as is */
5275 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
5276
2c3bf9ab
TI
5277 alc_fix_pll_init(codec, 0x20, 0x04, 15);
5278
8663ff75
KY
5279 spec->init_hook = alc662_fill_coef;
5280 alc662_fill_coef(codec);
5281
1727a771 5282 snd_hda_pick_fixup(codec, alc662_fixup_models,
8e5a0509 5283 alc662_fixup_tbl, alc662_fixups);
1727a771 5284 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
8e5a0509
TI
5285
5286 alc_auto_parse_customize_define(codec);
5287
7504b6cd
TI
5288 if (has_cdefine_beep(codec))
5289 spec->gen.beep_nid = 0x01;
5290
1bb7e43e 5291 if ((alc_get_coef0(codec) & (1 << 14)) &&
e16fb6d1
TI
5292 codec->bus->pci->subsystem_vendor == 0x1025 &&
5293 spec->cdefine.platform_type == 1) {
6134b1a2
WY
5294 err = alc_codec_rename(codec, "ALC272X");
5295 if (err < 0)
e16fb6d1 5296 goto error;
20ca0c35 5297 }
274693f3 5298
b9c5106c
TI
5299 /* automatic parse from the BIOS config */
5300 err = alc662_parse_auto_config(codec);
e16fb6d1
TI
5301 if (err < 0)
5302 goto error;
bc9f98a9 5303
7504b6cd 5304 if (!spec->gen.no_analog && spec->gen.beep_nid) {
da00c244
KY
5305 switch (codec->vendor_id) {
5306 case 0x10ec0662:
5307 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
5308 break;
5309 case 0x10ec0272:
5310 case 0x10ec0663:
5311 case 0x10ec0665:
9ad54547 5312 case 0x10ec0668:
da00c244
KY
5313 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5314 break;
5315 case 0x10ec0273:
5316 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
5317 break;
5318 }
cec27c89 5319 }
2134ea4f 5320
bc9f98a9 5321 codec->patch_ops = alc_patch_ops;
1c716153 5322 spec->shutup = alc_eapd_shutup;
6cb3b707 5323
1727a771 5324 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
589876e2 5325
bc9f98a9 5326 return 0;
801f49d3 5327
e16fb6d1
TI
5328 error:
5329 alc_free(codec);
5330 return err;
b478b998
KY
5331}
5332
d1eb57f4
KY
5333/*
5334 * ALC680 support
5335 */
d1eb57f4 5336
d1eb57f4
KY
5337static int alc680_parse_auto_config(struct hda_codec *codec)
5338{
3e6179b8 5339 return alc_parse_auto_config(codec, NULL, NULL);
d1eb57f4
KY
5340}
5341
d1eb57f4 5342/*
d1eb57f4 5343 */
d1eb57f4
KY
5344static int patch_alc680(struct hda_codec *codec)
5345{
d1eb57f4
KY
5346 int err;
5347
1f0f4b80 5348 /* ALC680 has no aa-loopback mixer */
3de95173
TI
5349 err = alc_alloc_spec(codec, 0);
5350 if (err < 0)
5351 return err;
1f0f4b80 5352
1ebec5f2
TI
5353 /* automatic parse from the BIOS config */
5354 err = alc680_parse_auto_config(codec);
5355 if (err < 0) {
5356 alc_free(codec);
5357 return err;
d1eb57f4
KY
5358 }
5359
d1eb57f4 5360 codec->patch_ops = alc_patch_ops;
d1eb57f4
KY
5361
5362 return 0;
5363}
5364
1da177e4
LT
5365/*
5366 * patch entries
5367 */
a9111321 5368static const struct hda_codec_preset snd_hda_preset_realtek[] = {
296f0338 5369 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
ba4c4d0a 5370 { .id = 0x10ec0231, .name = "ALC231", .patch = patch_alc269 },
84dfd0ac 5371 { .id = 0x10ec0233, .name = "ALC233", .patch = patch_alc269 },
1d04c9de 5372 { .id = 0x10ec0255, .name = "ALC255", .patch = patch_alc269 },
1da177e4 5373 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
df694daa 5374 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
f6a92248 5375 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
a361d84b 5376 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
f6a92248 5377 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
ebb83eeb 5378 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
01afd41f 5379 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
ebb83eeb 5380 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
296f0338 5381 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
befae82e 5382 { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 },
4e01ec63 5383 { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
7ff34ad8 5384 { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
065380f0 5385 { .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 },
161ebf29 5386 { .id = 0x10ec0285, .name = "ALC285", .patch = patch_alc269 },
7fc7d047 5387 { .id = 0x10ec0286, .name = "ALC286", .patch = patch_alc269 },
7ff34ad8 5388 { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
af02dde8 5389 { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
161ebf29 5390 { .id = 0x10ec0293, .name = "ALC293", .patch = patch_alc269 },
f32610ed 5391 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
bc9f98a9 5392 .patch = patch_alc861 },
f32610ed
JS
5393 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
5394 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
5395 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
bc9f98a9 5396 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
4953550a 5397 .patch = patch_alc882 },
bc9f98a9
KY
5398 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
5399 .patch = patch_alc662 },
cc667a72
DH
5400 { .id = 0x10ec0662, .rev = 0x100300, .name = "ALC662 rev3",
5401 .patch = patch_alc662 },
6dda9f4a 5402 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
cec27c89 5403 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
19a62823 5404 { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
6227cdce 5405 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
1d87caa6 5406 { .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 },
d1eb57f4 5407 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
f32610ed 5408 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
1da177e4 5409 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
4953550a 5410 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
669faba2 5411 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
4953550a 5412 .patch = patch_alc882 },
cb308f97 5413 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
4953550a 5414 .patch = patch_alc882 },
df694daa 5415 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
e16fb6d1 5416 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
4442608d 5417 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
4953550a 5418 .patch = patch_alc882 },
e16fb6d1 5419 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc882 },
4953550a 5420 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
274693f3 5421 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
e16fb6d1 5422 { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 },
19a62823 5423 { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 },
1da177e4
LT
5424 {} /* terminator */
5425};
1289e9e8
TI
5426
5427MODULE_ALIAS("snd-hda-codec-id:10ec*");
5428
5429MODULE_LICENSE("GPL");
5430MODULE_DESCRIPTION("Realtek HD-audio codec");
5431
5432static struct hda_codec_preset_list realtek_list = {
5433 .preset = snd_hda_preset_realtek,
5434 .owner = THIS_MODULE,
5435};
5436
5437static int __init patch_realtek_init(void)
5438{
5439 return snd_hda_add_codec_preset(&realtek_list);
5440}
5441
5442static void __exit patch_realtek_exit(void)
5443{
5444 snd_hda_delete_codec_preset(&realtek_list);
5445}
5446
5447module_init(patch_realtek_init)
5448module_exit(patch_realtek_exit)