blob: f0ed41e1a884d07f2b530b5469738f62b232fd87 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
Takashi Iwai1d045db2011-07-07 18:23:21 +02004 * HD audio interface patch for Realtek ALC codecs
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Kailang Yangdf694da2005-12-05 19:42:22 +01006 * Copyright (c) 2004 Kailang Yang <kailang@realtek.com.tw>
7 * PeiSen Hou <pshou@realtek.com.tw>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Takashi Iwai <tiwai@suse.de>
Jonathan Woithe409a3e92012-03-27 13:01:01 +10309 * Jonathan Woithe <jwoithe@just42.net>
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 *
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/slab.h>
29#include <linux/pci.h>
Takashi Iwai08fb0d02013-01-10 17:33:58 +010030#include <linux/dmi.h>
Paul Gortmakerda155d52011-07-15 12:38:28 -040031#include <linux/module.h>
David Henningsson33f4acd2015-01-07 15:50:13 +010032#include <linux/input.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <sound/core.h>
Kailang Yang9ad0e492010-09-14 23:22:00 +020034#include <sound/jack.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include "hda_codec.h"
36#include "hda_local.h"
Takashi Iwai23d30f22012-05-07 17:17:32 +020037#include "hda_auto_parser.h"
Takashi Iwai1835a0f2011-10-27 22:12:46 +020038#include "hda_jack.h"
Takashi Iwai08c189f2012-12-19 15:22:24 +010039#include "hda_generic.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Takashi Iwaicd63a5f2013-07-05 12:13:59 +020041/* keep halting ALC5505 DSP, for power saving */
42#define HALT_REALTEK_ALC5505
43
Kailang Yangdf694da2005-12-05 19:42:22 +010044/* for GPIO Poll */
45#define GPIO_MASK 0x03
46
Takashi Iwai4a79ba32009-04-22 16:31:35 +020047/* extra amp-initialization sequence types */
48enum {
49 ALC_INIT_NONE,
50 ALC_INIT_DEFAULT,
51 ALC_INIT_GPIO1,
52 ALC_INIT_GPIO2,
53 ALC_INIT_GPIO3,
54};
55
David Henningsson73bdd592013-04-15 15:44:14 +020056enum {
57 ALC_HEADSET_MODE_UNKNOWN,
58 ALC_HEADSET_MODE_UNPLUGGED,
59 ALC_HEADSET_MODE_HEADSET,
60 ALC_HEADSET_MODE_MIC,
61 ALC_HEADSET_MODE_HEADPHONE,
62};
63
64enum {
65 ALC_HEADSET_TYPE_UNKNOWN,
66 ALC_HEADSET_TYPE_CTIA,
67 ALC_HEADSET_TYPE_OMTP,
68};
69
Hui Wangc7b60a82015-12-28 11:35:25 +080070enum {
71 ALC_KEY_MICMUTE_INDEX,
72};
73
Kailang Yangda00c242010-03-19 11:23:45 +010074struct alc_customize_define {
75 unsigned int sku_cfg;
76 unsigned char port_connectivity;
77 unsigned char check_sum;
78 unsigned char customization;
79 unsigned char external_amp;
80 unsigned int enable_pcbeep:1;
81 unsigned int platform_type:1;
82 unsigned int swap:1;
83 unsigned int override:1;
David Henningsson90622912010-10-14 14:50:18 +020084 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
Kailang Yangda00c242010-03-19 11:23:45 +010085};
86
Linus Torvalds1da177e2005-04-16 15:20:36 -070087struct alc_spec {
Takashi Iwai08c189f2012-12-19 15:22:24 +010088 struct hda_gen_spec gen; /* must be at head */
Takashi Iwai23d30f22012-05-07 17:17:32 +020089
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 /* codec parameterization */
Takashi Iwaia9111322011-05-02 11:30:18 +020091 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 unsigned int num_mixers;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010093 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Kailang Yangda00c242010-03-19 11:23:45 +010095 struct alc_customize_define cdefine;
Takashi Iwai08c189f2012-12-19 15:22:24 +010096 unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
97
Takashi Iwai08fb0d02013-01-10 17:33:58 +010098 /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
99 int mute_led_polarity;
100 hda_nid_t mute_led_nid;
Kailang Yang9c5dc3b2014-06-19 16:11:36 +0800101 hda_nid_t cap_mute_led_nid;
Takashi Iwai08fb0d02013-01-10 17:33:58 +0100102
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +0100103 unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
Takashi Iwai0f32fd192014-11-19 12:16:14 +0100104 unsigned int gpio_mute_led_mask;
105 unsigned int gpio_mic_led_mask;
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +0100106
David Henningsson73bdd592013-04-15 15:44:14 +0200107 hda_nid_t headset_mic_pin;
108 hda_nid_t headphone_mic_pin;
109 int current_headset_mode;
110 int current_headset_type;
111
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100112 /* hooks */
113 void (*init_hook)(struct hda_codec *codec);
Takashi Iwai83012a72012-08-24 18:38:08 +0200114#ifdef CONFIG_PM
Daniel T Chenc97259d2009-12-27 18:52:08 -0500115 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100116#endif
Takashi Iwai1c716152011-04-07 10:37:16 +0200117 void (*shutup)(struct hda_codec *codec);
Takashi Iwai70a09762015-12-15 14:59:58 +0100118 void (*reboot_notify)(struct hda_codec *codec);
Takashi Iwaid922b512011-04-28 12:18:53 +0200119
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200120 int init_amp;
Takashi Iwaid433a672010-09-20 15:11:54 +0200121 int codec_variant; /* flag for other variants */
Kailang Yang97a26572013-11-29 00:35:26 -0500122 unsigned int has_alc5505_dsp:1;
123 unsigned int no_depop_delay:1;
Takashi Iwaie64f14f2009-01-20 18:32:55 +0100124
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200125 /* for PLL fix */
126 hda_nid_t pll_nid;
127 unsigned int pll_coef_idx, pll_coef_bit;
Takashi Iwai1bb7e432011-10-17 16:50:59 +0200128 unsigned int coef0;
David Henningsson33f4acd2015-01-07 15:50:13 +0100129 struct input_dev *kb_dev;
Hui Wangc7b60a82015-12-28 11:35:25 +0800130 u8 alc_mute_keycode_map[1];
Kailang Yangdf694da2005-12-05 19:42:22 +0100131};
132
Takashi Iwai23f0c042009-02-26 13:03:58 +0100133/*
Takashi Iwaif2a227c2014-08-18 13:35:22 +0200134 * COEF access helper functions
135 */
136
137static int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
138 unsigned int coef_idx)
139{
140 unsigned int val;
141
142 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx);
143 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF, 0);
144 return val;
145}
146
147#define alc_read_coef_idx(codec, coef_idx) \
148 alc_read_coefex_idx(codec, 0x20, coef_idx)
149
150static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
151 unsigned int coef_idx, unsigned int coef_val)
152{
153 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx);
154 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF, coef_val);
155}
156
157#define alc_write_coef_idx(codec, coef_idx, coef_val) \
158 alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val)
159
Takashi Iwai98b24882014-08-18 13:47:50 +0200160static void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
161 unsigned int coef_idx, unsigned int mask,
162 unsigned int bits_set)
163{
164 unsigned int val = alc_read_coefex_idx(codec, nid, coef_idx);
165
166 if (val != -1)
167 alc_write_coefex_idx(codec, nid, coef_idx,
168 (val & ~mask) | bits_set);
169}
170
171#define alc_update_coef_idx(codec, coef_idx, mask, bits_set) \
172 alc_update_coefex_idx(codec, 0x20, coef_idx, mask, bits_set)
173
Takashi Iwaif2a227c2014-08-18 13:35:22 +0200174/* a special bypass for COEF 0; read the cached value at the second time */
175static unsigned int alc_get_coef0(struct hda_codec *codec)
176{
177 struct alc_spec *spec = codec->spec;
178
179 if (!spec->coef0)
180 spec->coef0 = alc_read_coef_idx(codec, 0);
181 return spec->coef0;
182}
183
Takashi Iwai54db6c32014-08-18 15:11:19 +0200184/* coef writes/updates batch */
185struct coef_fw {
186 unsigned char nid;
187 unsigned char idx;
188 unsigned short mask;
189 unsigned short val;
190};
191
192#define UPDATE_COEFEX(_nid, _idx, _mask, _val) \
193 { .nid = (_nid), .idx = (_idx), .mask = (_mask), .val = (_val) }
194#define WRITE_COEFEX(_nid, _idx, _val) UPDATE_COEFEX(_nid, _idx, -1, _val)
195#define WRITE_COEF(_idx, _val) WRITE_COEFEX(0x20, _idx, _val)
196#define UPDATE_COEF(_idx, _mask, _val) UPDATE_COEFEX(0x20, _idx, _mask, _val)
197
198static void alc_process_coef_fw(struct hda_codec *codec,
199 const struct coef_fw *fw)
200{
201 for (; fw->nid; fw++) {
202 if (fw->mask == (unsigned short)-1)
203 alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val);
204 else
205 alc_update_coefex_idx(codec, fw->nid, fw->idx,
206 fw->mask, fw->val);
207 }
208}
209
Takashi Iwaif2a227c2014-08-18 13:35:22 +0200210/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200211 * Append the given mixer and verb elements for the later use
212 * The mixer array is referred in build_controls(), and init_verbs are
213 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100214 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200215static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100216{
217 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
218 return;
219 spec->mixers[spec->num_mixers++] = mix;
220}
221
Takashi Iwaid88897e2008-10-31 15:01:37 +0100222/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200223 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100224 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200225/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200226static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200227 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
228 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
229 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
230 { }
231};
232
Takashi Iwaia9111322011-05-02 11:30:18 +0200233static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200234 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
235 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
236 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
237 { }
238};
239
Takashi Iwaia9111322011-05-02 11:30:18 +0200240static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200241 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
242 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
243 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
244 { }
245};
246
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200247/*
248 * Fix hardware PLL issue
249 * On some codecs, the analog PLL gating control must be off while
250 * the default value is 1.
251 */
252static void alc_fix_pll(struct hda_codec *codec)
253{
254 struct alc_spec *spec = codec->spec;
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200255
Takashi Iwai98b24882014-08-18 13:47:50 +0200256 if (spec->pll_nid)
257 alc_update_coefex_idx(codec, spec->pll_nid, spec->pll_coef_idx,
258 1 << spec->pll_coef_bit, 0);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200259}
260
261static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
262 unsigned int coef_idx, unsigned int coef_bit)
263{
264 struct alc_spec *spec = codec->spec;
265 spec->pll_nid = nid;
266 spec->pll_coef_idx = coef_idx;
267 spec->pll_coef_bit = coef_bit;
268 alc_fix_pll(codec);
269}
270
Takashi Iwaicf5a2272012-02-20 16:31:07 +0100271/* update the master volume per volume-knob's unsol event */
Takashi Iwai1a4f69d2014-09-11 15:22:46 +0200272static void alc_update_knob_master(struct hda_codec *codec,
273 struct hda_jack_callback *jack)
Takashi Iwaicf5a2272012-02-20 16:31:07 +0100274{
275 unsigned int val;
276 struct snd_kcontrol *kctl;
277 struct snd_ctl_elem_value *uctl;
278
279 kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
280 if (!kctl)
281 return;
282 uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
283 if (!uctl)
284 return;
Takashi Iwai1a4f69d2014-09-11 15:22:46 +0200285 val = snd_hda_codec_read(codec, jack->tbl->nid, 0,
Takashi Iwaicf5a2272012-02-20 16:31:07 +0100286 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
287 val &= HDA_AMP_VOLMASK;
288 uctl->value.integer.value[0] = val;
289 uctl->value.integer.value[1] = val;
290 kctl->put(kctl, uctl);
291 kfree(uctl);
292}
293
David Henningsson29adc4b2012-09-25 11:31:00 +0200294static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
Takashi Iwaif21d78e2012-01-19 12:10:29 +0100295{
David Henningsson29adc4b2012-09-25 11:31:00 +0200296 /* For some reason, the res given from ALC880 is broken.
297 Here we adjust it properly. */
298 snd_hda_jack_unsol_event(codec, res >> 2);
Takashi Iwaif21d78e2012-01-19 12:10:29 +0100299}
300
Kailang Yang394c97f2014-11-12 17:38:08 +0800301/* Change EAPD to verb control */
302static void alc_fill_eapd_coef(struct hda_codec *codec)
303{
304 int coef;
305
306 coef = alc_get_coef0(codec);
307
Takashi Iwai7639a062015-03-03 10:07:24 +0100308 switch (codec->core.vendor_id) {
Kailang Yang394c97f2014-11-12 17:38:08 +0800309 case 0x10ec0262:
310 alc_update_coef_idx(codec, 0x7, 0, 1<<5);
311 break;
312 case 0x10ec0267:
313 case 0x10ec0268:
314 alc_update_coef_idx(codec, 0x7, 0, 1<<13);
315 break;
316 case 0x10ec0269:
317 if ((coef & 0x00f0) == 0x0010)
318 alc_update_coef_idx(codec, 0xd, 0, 1<<14);
319 if ((coef & 0x00f0) == 0x0020)
320 alc_update_coef_idx(codec, 0x4, 1<<15, 0);
321 if ((coef & 0x00f0) == 0x0030)
322 alc_update_coef_idx(codec, 0x10, 1<<9, 0);
323 break;
324 case 0x10ec0280:
325 case 0x10ec0284:
326 case 0x10ec0290:
327 case 0x10ec0292:
328 alc_update_coef_idx(codec, 0x4, 1<<15, 0);
329 break;
330 case 0x10ec0233:
331 case 0x10ec0255:
Kailang Yang4344aec2014-12-17 17:39:05 +0800332 case 0x10ec0256:
Kailang Yang394c97f2014-11-12 17:38:08 +0800333 case 0x10ec0282:
334 case 0x10ec0283:
335 case 0x10ec0286:
336 case 0x10ec0288:
Kailang Yang506b62c2014-12-18 17:07:44 +0800337 case 0x10ec0298:
Kailang Yang394c97f2014-11-12 17:38:08 +0800338 alc_update_coef_idx(codec, 0x10, 1<<9, 0);
339 break;
340 case 0x10ec0285:
341 case 0x10ec0293:
342 alc_update_coef_idx(codec, 0xa, 1<<13, 0);
343 break;
344 case 0x10ec0662:
345 if ((coef & 0x00f0) == 0x0030)
346 alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */
347 break;
348 case 0x10ec0272:
349 case 0x10ec0273:
350 case 0x10ec0663:
351 case 0x10ec0665:
352 case 0x10ec0670:
353 case 0x10ec0671:
354 case 0x10ec0672:
355 alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
356 break;
357 case 0x10ec0668:
358 alc_update_coef_idx(codec, 0x7, 3<<13, 0);
359 break;
360 case 0x10ec0867:
361 alc_update_coef_idx(codec, 0x4, 1<<10, 0);
362 break;
363 case 0x10ec0888:
364 if ((coef & 0x00f0) == 0x0020 || (coef & 0x00f0) == 0x0030)
365 alc_update_coef_idx(codec, 0x7, 1<<5, 0);
366 break;
367 case 0x10ec0892:
368 alc_update_coef_idx(codec, 0x7, 1<<5, 0);
369 break;
370 case 0x10ec0899:
371 case 0x10ec0900:
372 alc_update_coef_idx(codec, 0x7, 1<<1, 0);
373 break;
374 }
375}
376
Kailang Yangf9423e72008-05-27 12:32:25 +0200377/* additional initialization for ALC888 variants */
378static void alc888_coef_init(struct hda_codec *codec)
379{
Kailang Yang1df88742014-10-29 16:10:13 +0800380 switch (alc_get_coef0(codec) & 0x00f0) {
381 /* alc888-VA */
382 case 0x00:
383 /* alc888-VB */
384 case 0x10:
385 alc_update_coef_idx(codec, 7, 0, 0x2030); /* Turn EAPD to High */
386 break;
387 }
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200388}
389
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100390/* turn on/off EAPD control (only if available) */
391static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
392{
393 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
394 return;
395 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
396 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
397 on ? 2 : 0);
398}
399
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200400/* turn on/off EAPD controls of the codec */
401static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
402{
403 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200404 static hda_nid_t pins[] = {
Hui Wangaf95b412015-03-26 17:14:55 +0800405 0x0f, 0x10, 0x14, 0x15, 0x17, 0
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200406 };
407 hda_nid_t *p;
408 for (p = pins; *p; p++)
409 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200410}
411
Takashi Iwai1c716152011-04-07 10:37:16 +0200412/* generic shutup callback;
413 * just turning off EPAD and a little pause for avoiding pop-noise
414 */
415static void alc_eapd_shutup(struct hda_codec *codec)
416{
Kailang Yang97a26572013-11-29 00:35:26 -0500417 struct alc_spec *spec = codec->spec;
418
Takashi Iwai1c716152011-04-07 10:37:16 +0200419 alc_auto_setup_eapd(codec, false);
Kailang Yang97a26572013-11-29 00:35:26 -0500420 if (!spec->no_depop_delay)
421 msleep(200);
Takashi Iwai9bfb2842013-07-24 14:31:50 +0200422 snd_hda_shutup_pins(codec);
Takashi Iwai1c716152011-04-07 10:37:16 +0200423}
424
Takashi Iwai1d045db2011-07-07 18:23:21 +0200425/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200426static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200427{
Kailang Yang394c97f2014-11-12 17:38:08 +0800428 alc_fill_eapd_coef(codec);
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200429 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200430 switch (type) {
431 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200432 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
433 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200434 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200435 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
436 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200437 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200438 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
439 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200440 case ALC_INIT_DEFAULT:
Takashi Iwai7639a062015-03-03 10:07:24 +0100441 switch (codec->core.vendor_id) {
Kailang Yangc9b58002007-10-16 14:30:01 +0200442 case 0x10ec0260:
Takashi Iwai98b24882014-08-18 13:47:50 +0200443 alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x2010);
Kailang Yangc9b58002007-10-16 14:30:01 +0200444 break;
Kailang Yangc9b58002007-10-16 14:30:01 +0200445 case 0x10ec0880:
446 case 0x10ec0882:
447 case 0x10ec0883:
448 case 0x10ec0885:
Kailang Yang1df88742014-10-29 16:10:13 +0800449 alc_update_coef_idx(codec, 7, 0, 0x2030);
Kailang Yangc9b58002007-10-16 14:30:01 +0200450 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200451 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200452 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200453 break;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200454 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200455 break;
456 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200457}
Kailang Yangea1fb292008-08-26 12:58:38 +0200458
Takashi Iwai1d045db2011-07-07 18:23:21 +0200459
460/*
461 * Realtek SSID verification
462 */
463
David Henningsson90622912010-10-14 14:50:18 +0200464/* Could be any non-zero and even value. When used as fixup, tells
465 * the driver to ignore any present sku defines.
466 */
467#define ALC_FIXUP_SKU_IGNORE (2)
468
Takashi Iwai23d30f22012-05-07 17:17:32 +0200469static void alc_fixup_sku_ignore(struct hda_codec *codec,
470 const struct hda_fixup *fix, int action)
471{
472 struct alc_spec *spec = codec->spec;
473 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
474 spec->cdefine.fixup = 1;
475 spec->cdefine.sku_cfg = ALC_FIXUP_SKU_IGNORE;
476 }
477}
478
Mengdong Linb5c66112013-11-29 00:35:35 -0500479static void alc_fixup_no_depop_delay(struct hda_codec *codec,
480 const struct hda_fixup *fix, int action)
481{
482 struct alc_spec *spec = codec->spec;
483
Mengdong Lin84d2dc32013-12-02 22:26:03 -0500484 if (action == HDA_FIXUP_ACT_PROBE) {
Mengdong Linb5c66112013-11-29 00:35:35 -0500485 spec->no_depop_delay = 1;
Mengdong Lin84d2dc32013-12-02 22:26:03 -0500486 codec->depop_delay = 0;
487 }
Mengdong Linb5c66112013-11-29 00:35:35 -0500488}
489
Kailang Yangda00c242010-03-19 11:23:45 +0100490static int alc_auto_parse_customize_define(struct hda_codec *codec)
491{
492 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +0100493 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +0100494 struct alc_spec *spec = codec->spec;
495
Takashi Iwaib6cbe512010-07-28 17:43:36 +0200496 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
497
David Henningsson90622912010-10-14 14:50:18 +0200498 if (spec->cdefine.fixup) {
499 ass = spec->cdefine.sku_cfg;
500 if (ass == ALC_FIXUP_SKU_IGNORE)
501 return -1;
502 goto do_sku;
503 }
504
Takashi Iwai5100cd02014-02-15 10:03:19 +0100505 if (!codec->bus->pci)
506 return -1;
Takashi Iwai7639a062015-03-03 10:07:24 +0100507 ass = codec->core.subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +0200508 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +0100509 goto do_sku;
510
511 nid = 0x1d;
Takashi Iwai7639a062015-03-03 10:07:24 +0100512 if (codec->core.vendor_id == 0x10ec0260)
Kailang Yangda00c242010-03-19 11:23:45 +0100513 nid = 0x17;
514 ass = snd_hda_codec_get_pincfg(codec, nid);
515
516 if (!(ass & 1)) {
Takashi Iwai4e76a882014-02-25 12:21:03 +0100517 codec_info(codec, "%s: SKU not ready 0x%08x\n",
Takashi Iwai7639a062015-03-03 10:07:24 +0100518 codec->core.chip_name, ass);
Kailang Yangda00c242010-03-19 11:23:45 +0100519 return -1;
520 }
521
522 /* check sum */
523 tmp = 0;
524 for (i = 1; i < 16; i++) {
525 if ((ass >> i) & 1)
526 tmp++;
527 }
528 if (((ass >> 16) & 0xf) != tmp)
529 return -1;
530
531 spec->cdefine.port_connectivity = ass >> 30;
532 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
533 spec->cdefine.check_sum = (ass >> 16) & 0xf;
534 spec->cdefine.customization = ass >> 8;
535do_sku:
536 spec->cdefine.sku_cfg = ass;
537 spec->cdefine.external_amp = (ass & 0x38) >> 3;
538 spec->cdefine.platform_type = (ass & 0x4) >> 2;
539 spec->cdefine.swap = (ass & 0x2) >> 1;
540 spec->cdefine.override = ass & 0x1;
541
Takashi Iwai4e76a882014-02-25 12:21:03 +0100542 codec_dbg(codec, "SKU: Nid=0x%x sku_cfg=0x%08x\n",
Kailang Yangda00c242010-03-19 11:23:45 +0100543 nid, spec->cdefine.sku_cfg);
Takashi Iwai4e76a882014-02-25 12:21:03 +0100544 codec_dbg(codec, "SKU: port_connectivity=0x%x\n",
Kailang Yangda00c242010-03-19 11:23:45 +0100545 spec->cdefine.port_connectivity);
Takashi Iwai4e76a882014-02-25 12:21:03 +0100546 codec_dbg(codec, "SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
547 codec_dbg(codec, "SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
548 codec_dbg(codec, "SKU: customization=0x%08x\n", spec->cdefine.customization);
549 codec_dbg(codec, "SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
550 codec_dbg(codec, "SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
551 codec_dbg(codec, "SKU: swap=0x%x\n", spec->cdefine.swap);
552 codec_dbg(codec, "SKU: override=0x%x\n", spec->cdefine.override);
Kailang Yangda00c242010-03-19 11:23:45 +0100553
554 return 0;
555}
556
Takashi Iwai08c189f2012-12-19 15:22:24 +0100557/* return the position of NID in the list, or -1 if not found */
558static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
559{
560 int i;
561 for (i = 0; i < nums; i++)
562 if (list[i] == nid)
563 return i;
564 return -1;
565}
Takashi Iwai1d045db2011-07-07 18:23:21 +0200566/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +0200567static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
568{
Takashi Iwai21268962011-07-07 15:01:13 +0200569 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +0200570}
571
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200572/* check subsystem ID and set up device-specific initialization;
573 * return 1 if initialized, 0 if invalid SSID
574 */
575/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
576 * 31 ~ 16 : Manufacture ID
577 * 15 ~ 8 : SKU ID
578 * 7 ~ 0 : Assembly ID
579 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
580 */
Takashi Iwai58c57cf2014-01-07 18:22:49 +0100581static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200582{
583 unsigned int ass, tmp, i;
584 unsigned nid;
585 struct alc_spec *spec = codec->spec;
586
David Henningsson90622912010-10-14 14:50:18 +0200587 if (spec->cdefine.fixup) {
588 ass = spec->cdefine.sku_cfg;
589 if (ass == ALC_FIXUP_SKU_IGNORE)
590 return 0;
591 goto do_sku;
592 }
593
Takashi Iwai7639a062015-03-03 10:07:24 +0100594 ass = codec->core.subsystem_id & 0xffff;
Takashi Iwai5100cd02014-02-15 10:03:19 +0100595 if (codec->bus->pci &&
596 ass != codec->bus->pci->subsystem_device && (ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200597 goto do_sku;
598
599 /* invalid SSID, check the special NID pin defcfg instead */
600 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -0400601 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200602 * 29~21 : reserve
603 * 20 : PCBEEP input
604 * 19~16 : Check sum (15:1)
605 * 15~1 : Custom
606 * 0 : override
607 */
608 nid = 0x1d;
Takashi Iwai7639a062015-03-03 10:07:24 +0100609 if (codec->core.vendor_id == 0x10ec0260)
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200610 nid = 0x17;
611 ass = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai4e76a882014-02-25 12:21:03 +0100612 codec_dbg(codec,
613 "realtek: No valid SSID, checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +0200614 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +0100615 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200616 return 0;
617 if ((ass >> 30) != 1) /* no physical connection */
618 return 0;
619
620 /* check sum */
621 tmp = 0;
622 for (i = 1; i < 16; i++) {
623 if ((ass >> i) & 1)
624 tmp++;
625 }
626 if (((ass >> 16) & 0xf) != tmp)
627 return 0;
628do_sku:
Takashi Iwai4e76a882014-02-25 12:21:03 +0100629 codec_dbg(codec, "realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
Takashi Iwai7639a062015-03-03 10:07:24 +0100630 ass & 0xffff, codec->core.vendor_id);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200631 /*
632 * 0 : override
633 * 1 : Swap Jack
634 * 2 : 0 --> Desktop, 1 --> Laptop
635 * 3~5 : External Amplifier control
636 * 7~6 : Reserved
637 */
638 tmp = (ass & 0x38) >> 3; /* external Amp control */
639 switch (tmp) {
640 case 1:
641 spec->init_amp = ALC_INIT_GPIO1;
642 break;
643 case 3:
644 spec->init_amp = ALC_INIT_GPIO2;
645 break;
646 case 7:
647 spec->init_amp = ALC_INIT_GPIO3;
648 break;
649 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +0100650 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200651 spec->init_amp = ALC_INIT_DEFAULT;
652 break;
653 }
654
655 /* is laptop or Desktop and enable the function "Mute internal speaker
656 * when the external headphone out jack is plugged"
657 */
658 if (!(ass & 0x8000))
659 return 1;
660 /*
661 * 10~8 : Jack location
662 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
663 * 14~13: Resvered
664 * 15 : 1 --> enable the function "Mute internal speaker
665 * when the external headphone out jack is plugged"
666 */
Takashi Iwai08c189f2012-12-19 15:22:24 +0100667 if (!spec->gen.autocfg.hp_pins[0] &&
668 !(spec->gen.autocfg.line_out_pins[0] &&
669 spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
Takashi Iwai01d48252009-10-06 13:21:54 +0200670 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +0200671 tmp = (ass >> 11) & 0x3; /* HP to chassis */
Takashi Iwai58c57cf2014-01-07 18:22:49 +0100672 nid = ports[tmp];
Takashi Iwai08c189f2012-12-19 15:22:24 +0100673 if (found_in_nid_list(nid, spec->gen.autocfg.line_out_pins,
674 spec->gen.autocfg.line_outs))
Takashi Iwai3af9ee62011-06-27 12:34:01 +0200675 return 1;
Takashi Iwai08c189f2012-12-19 15:22:24 +0100676 spec->gen.autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +0200677 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200678 return 1;
679}
Kailang Yangea1fb292008-08-26 12:58:38 +0200680
Takashi Iwai3e6179b2011-07-08 16:55:13 +0200681/* Check the validity of ALC subsystem-id
682 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
683static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200684{
Takashi Iwai58c57cf2014-01-07 18:22:49 +0100685 if (!alc_subsystem_id(codec, ports)) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200686 struct alc_spec *spec = codec->spec;
Takashi Iwai4e76a882014-02-25 12:21:03 +0100687 codec_dbg(codec,
688 "realtek: Enable default setup for auto mode as fallback\n");
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200689 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200690 }
Takashi Iwai21268962011-07-07 15:01:13 +0200691}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200692
Takashi Iwai41e41f12005-06-08 14:48:49 +0200693/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200694 */
695
David Henningsson9d36a7d2014-10-07 10:18:42 +0200696static void alc_fixup_inv_dmic(struct hda_codec *codec,
697 const struct hda_fixup *fix, int action)
Takashi Iwai125821a2012-06-22 14:30:29 +0200698{
699 struct alc_spec *spec = codec->spec;
Takashi Iwai668d1e92012-11-29 14:10:17 +0100700
David Henningsson9d36a7d2014-10-07 10:18:42 +0200701 spec->gen.inv_dmic_split = 1;
Takashi Iwai6e72aa52012-06-25 10:52:25 +0200702}
703
Takashi Iwai603c4012008-07-30 15:01:44 +0200704
Takashi Iwai67d634c2009-11-16 15:35:59 +0100705#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100706/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +0200707static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100708 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +0200709 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100710 { } /* end */
711};
Takashi Iwai67d634c2009-11-16 15:35:59 +0100712#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100713
Takashi Iwai2eab6942012-12-18 15:30:41 +0100714static int alc_build_controls(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715{
716 struct alc_spec *spec = codec->spec;
Takashi Iwai666a70d2012-12-17 20:29:29 +0100717 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Takashi Iwai08c189f2012-12-19 15:22:24 +0100719 err = snd_hda_gen_build_controls(codec);
720 if (err < 0)
721 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
723 for (i = 0; i < spec->num_mixers; i++) {
724 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
725 if (err < 0)
726 return err;
727 }
Takashi Iwai2134ea42008-01-10 16:53:55 +0100728
Takashi Iwai67d634c2009-11-16 15:35:59 +0100729#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100730 /* create beep controls if needed */
731 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +0200732 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100733 for (knew = alc_beep_mixer; knew->name; knew++) {
734 struct snd_kcontrol *kctl;
735 kctl = snd_ctl_new1(knew, codec);
736 if (!kctl)
737 return -ENOMEM;
738 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +0100739 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100740 if (err < 0)
741 return err;
742 }
743 }
Takashi Iwai67d634c2009-11-16 15:35:59 +0100744#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100745
Takashi Iwai1727a772013-01-10 09:52:52 +0100746 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
Takashi Iwai420b0fe2012-03-12 12:35:27 +0100747 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748}
749
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200750
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100752 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200753 */
Takashi Iwai16ded522005-06-10 19:58:24 +0200754
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755static int alc_init(struct hda_codec *codec)
756{
757 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200758
Takashi Iwai546bb672012-03-07 08:37:19 +0100759 if (spec->init_hook)
760 spec->init_hook(codec);
Kailang Yang526af6e2012-03-07 08:25:20 +0100761
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200762 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200763 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200764
Takashi Iwai08c189f2012-12-19 15:22:24 +0100765 snd_hda_gen_init(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100766
Takashi Iwai1727a772013-01-10 09:52:52 +0100767 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
Takashi Iwaie08a0072006-09-07 17:52:14 +0200768
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 return 0;
770}
771
Takashi Iwaia4e09aa2009-12-27 11:22:24 +0100772static inline void alc_shutup(struct hda_codec *codec)
773{
Takashi Iwai1c716152011-04-07 10:37:16 +0200774 struct alc_spec *spec = codec->spec;
775
776 if (spec && spec->shutup)
777 spec->shutup(codec);
Takashi Iwai9bfb2842013-07-24 14:31:50 +0200778 else
779 snd_hda_shutup_pins(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +0100780}
781
Takashi Iwai70a09762015-12-15 14:59:58 +0100782static void alc_reboot_notify(struct hda_codec *codec)
783{
784 struct alc_spec *spec = codec->spec;
785
786 if (spec && spec->reboot_notify)
787 spec->reboot_notify(codec);
788 else
789 alc_shutup(codec);
790}
791
792/* power down codec to D3 at reboot/shutdown; set as reboot_notify ops */
793static void alc_d3_at_reboot(struct hda_codec *codec)
794{
795 snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
796 snd_hda_codec_write(codec, codec->core.afg, 0,
797 AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
798 msleep(10);
799}
800
Takashi Iwai8a02c0c2014-02-10 18:09:45 +0100801#define alc_free snd_hda_gen_free
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
Takashi Iwai83012a72012-08-24 18:38:08 +0200803#ifdef CONFIG_PM
Daniel T Chenc97259d2009-12-27 18:52:08 -0500804static void alc_power_eapd(struct hda_codec *codec)
805{
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200806 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -0500807}
808
Takashi Iwai68cb2b52012-07-02 15:20:37 +0200809static int alc_suspend(struct hda_codec *codec)
Hector Martinf5de24b2009-12-20 22:51:31 +0100810{
811 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +0100812 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100813 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -0500814 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100815 return 0;
816}
817#endif
818
Takashi Iwai2a439522011-07-26 09:52:50 +0200819#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +0100820static int alc_resume(struct hda_codec *codec)
821{
Kailang Yang97a26572013-11-29 00:35:26 -0500822 struct alc_spec *spec = codec->spec;
823
824 if (!spec->no_depop_delay)
825 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +0100826 codec->patch_ops.init(codec);
Takashi Iwaieeecd9d2015-02-25 15:18:50 +0100827 regcache_sync(codec->core.regmap);
Takashi Iwai9e5341b2010-09-21 09:57:06 +0200828 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +0100829 return 0;
830}
Takashi Iwaie044c392008-10-27 16:56:24 +0100831#endif
832
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833/*
834 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200835static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 .build_controls = alc_build_controls,
Takashi Iwai08c189f2012-12-19 15:22:24 +0100837 .build_pcms = snd_hda_gen_build_pcms,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 .init = alc_init,
839 .free = alc_free,
David Henningsson29adc4b2012-09-25 11:31:00 +0200840 .unsol_event = snd_hda_jack_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +0200841#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +0100842 .resume = alc_resume,
Hector Martinf5de24b2009-12-20 22:51:31 +0100843 .suspend = alc_suspend,
Takashi Iwaifce52a32013-01-07 12:42:48 +0100844 .check_power_status = snd_hda_gen_check_power_status,
Takashi Iwaicb53c622007-08-10 17:21:45 +0200845#endif
Takashi Iwai70a09762015-12-15 14:59:58 +0100846 .reboot_notify = alc_reboot_notify,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847};
848
David Henningsson29adc4b2012-09-25 11:31:00 +0200849
Takashi Iwaided255b2015-10-01 17:59:43 +0200850#define alc_codec_rename(codec, name) snd_hda_codec_set_name(codec, name)
Kailang Yangc027ddc2010-03-19 11:33:06 +0100851
Takashi Iwai2fa522b2005-05-12 14:51:12 +0200852/*
Kailang Yang4b016932013-11-28 11:55:09 +0100853 * Rename codecs appropriately from COEF value or subvendor id
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200854 */
855struct alc_codec_rename_table {
856 unsigned int vendor_id;
857 unsigned short coef_mask;
858 unsigned short coef_bits;
859 const char *name;
860};
861
Kailang Yang4b016932013-11-28 11:55:09 +0100862struct alc_codec_rename_pci_table {
863 unsigned int codec_vendor_id;
864 unsigned short pci_subvendor;
865 unsigned short pci_subdevice;
866 const char *name;
867};
868
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200869static struct alc_codec_rename_table rename_tbl[] = {
Kailang Yange6e5f7a2014-06-06 16:46:43 +0800870 { 0x10ec0221, 0xf00f, 0x1003, "ALC231" },
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200871 { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
872 { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
873 { 0x10ec0269, 0xf0f0, 0x3010, "ALC258" },
874 { 0x10ec0269, 0x00f0, 0x0010, "ALC269VB" },
875 { 0x10ec0269, 0xffff, 0xa023, "ALC259" },
876 { 0x10ec0269, 0xffff, 0x6023, "ALC281X" },
877 { 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" },
Kailang Yangadcc70b2012-05-25 08:08:38 +0200878 { 0x10ec0269, 0x00f0, 0x0030, "ALC269VD" },
Kailang Yange6e5f7a2014-06-06 16:46:43 +0800879 { 0x10ec0662, 0xffff, 0x4020, "ALC656" },
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200880 { 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" },
881 { 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" },
882 { 0x10ec0888, 0xf0f0, 0x3020, "ALC886" },
883 { 0x10ec0899, 0x2000, 0x2000, "ALC899" },
884 { 0x10ec0892, 0xffff, 0x8020, "ALC661" },
885 { 0x10ec0892, 0xffff, 0x8011, "ALC661" },
886 { 0x10ec0892, 0xffff, 0x4011, "ALC656" },
887 { } /* terminator */
888};
889
Kailang Yang4b016932013-11-28 11:55:09 +0100890static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
891 { 0x10ec0280, 0x1028, 0, "ALC3220" },
892 { 0x10ec0282, 0x1028, 0, "ALC3221" },
893 { 0x10ec0283, 0x1028, 0, "ALC3223" },
Kailang Yang193177d2014-04-23 16:06:13 +0800894 { 0x10ec0288, 0x1028, 0, "ALC3263" },
Kailang Yang4b016932013-11-28 11:55:09 +0100895 { 0x10ec0292, 0x1028, 0, "ALC3226" },
Kailang Yang193177d2014-04-23 16:06:13 +0800896 { 0x10ec0293, 0x1028, 0, "ALC3235" },
Kailang Yang4b016932013-11-28 11:55:09 +0100897 { 0x10ec0255, 0x1028, 0, "ALC3234" },
898 { 0x10ec0668, 0x1028, 0, "ALC3661" },
Kailang Yange6e5f7a2014-06-06 16:46:43 +0800899 { 0x10ec0275, 0x1028, 0, "ALC3260" },
900 { 0x10ec0899, 0x1028, 0, "ALC3861" },
Kailang Yang2c674fa2015-05-05 15:02:42 +0800901 { 0x10ec0298, 0x1028, 0, "ALC3266" },
Kailang Yang82324502015-05-25 17:16:49 +0800902 { 0x10ec0256, 0x1028, 0, "ALC3246" },
Kailang Yange6e5f7a2014-06-06 16:46:43 +0800903 { 0x10ec0670, 0x1025, 0, "ALC669X" },
904 { 0x10ec0676, 0x1025, 0, "ALC679X" },
905 { 0x10ec0282, 0x1043, 0, "ALC3229" },
906 { 0x10ec0233, 0x1043, 0, "ALC3236" },
907 { 0x10ec0280, 0x103c, 0, "ALC3228" },
908 { 0x10ec0282, 0x103c, 0, "ALC3227" },
909 { 0x10ec0286, 0x103c, 0, "ALC3242" },
910 { 0x10ec0290, 0x103c, 0, "ALC3241" },
911 { 0x10ec0668, 0x103c, 0, "ALC3662" },
912 { 0x10ec0283, 0x17aa, 0, "ALC3239" },
913 { 0x10ec0292, 0x17aa, 0, "ALC3232" },
Kailang Yang4b016932013-11-28 11:55:09 +0100914 { } /* terminator */
915};
916
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200917static int alc_codec_rename_from_preset(struct hda_codec *codec)
918{
919 const struct alc_codec_rename_table *p;
Kailang Yang4b016932013-11-28 11:55:09 +0100920 const struct alc_codec_rename_pci_table *q;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200921
922 for (p = rename_tbl; p->vendor_id; p++) {
Takashi Iwai7639a062015-03-03 10:07:24 +0100923 if (p->vendor_id != codec->core.vendor_id)
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200924 continue;
Takashi Iwai1bb7e432011-10-17 16:50:59 +0200925 if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200926 return alc_codec_rename(codec, p->name);
927 }
Kailang Yang4b016932013-11-28 11:55:09 +0100928
Takashi Iwai5100cd02014-02-15 10:03:19 +0100929 if (!codec->bus->pci)
930 return 0;
Kailang Yang4b016932013-11-28 11:55:09 +0100931 for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
Takashi Iwai7639a062015-03-03 10:07:24 +0100932 if (q->codec_vendor_id != codec->core.vendor_id)
Kailang Yang4b016932013-11-28 11:55:09 +0100933 continue;
934 if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
935 continue;
936 if (!q->pci_subdevice ||
937 q->pci_subdevice == codec->bus->pci->subsystem_device)
938 return alc_codec_rename(codec, q->name);
939 }
940
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200941 return 0;
942}
943
Takashi Iwaie4770622011-07-08 11:11:35 +0200944
945/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200946 * Digital-beep handlers
947 */
948#ifdef CONFIG_SND_HDA_INPUT_BEEP
949#define set_beep_amp(spec, nid, idx, dir) \
950 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
951
952static const struct snd_pci_quirk beep_white_list[] = {
Duncan Roe71100052012-10-10 14:19:50 +0200953 SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1),
W. Trevor Kinga4b7f212014-03-29 17:47:24 -0700954 SND_PCI_QUIRK(0x1043, 0x115d, "ASUS", 1),
Takashi Iwai1d045db2011-07-07 18:23:21 +0200955 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
Takashi Iwai8554ee42013-02-25 09:54:43 +0100956 SND_PCI_QUIRK(0x1043, 0x8376, "EeePC", 1),
Takashi Iwai1d045db2011-07-07 18:23:21 +0200957 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
958 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
959 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
Takashi Iwai78f8baf2012-03-06 14:02:32 +0100960 SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1),
Takashi Iwai1d045db2011-07-07 18:23:21 +0200961 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
962 {}
963};
964
965static inline int has_cdefine_beep(struct hda_codec *codec)
966{
967 struct alc_spec *spec = codec->spec;
968 const struct snd_pci_quirk *q;
969 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
970 if (q)
971 return q->value;
972 return spec->cdefine.enable_pcbeep;
973}
974#else
975#define set_beep_amp(spec, nid, idx, dir) /* NOP */
976#define has_cdefine_beep(codec) 0
977#endif
978
979/* parse the BIOS configuration and set up the alc_spec */
980/* return 1 if successful, 0 if the proper config is not found,
981 * or a negative error code
982 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +0200983static int alc_parse_auto_config(struct hda_codec *codec,
984 const hda_nid_t *ignore_nids,
985 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +0200986{
987 struct alc_spec *spec = codec->spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +0100988 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200989 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +0200990
Takashi Iwai53c334a2011-08-23 18:27:14 +0200991 err = snd_hda_parse_pin_defcfg(codec, cfg, ignore_nids,
992 spec->parse_flags);
Takashi Iwai1d045db2011-07-07 18:23:21 +0200993 if (err < 0)
994 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +0200995
996 if (ssid_nids)
997 alc_ssid_check(codec, ssid_nids);
998
Takashi Iwai08c189f2012-12-19 15:22:24 +0100999 err = snd_hda_gen_parse_auto_config(codec, cfg);
1000 if (err < 0)
1001 return err;
Takashi Iwai070cff42012-02-21 12:54:17 +01001002
Takashi Iwai1d045db2011-07-07 18:23:21 +02001003 return 1;
1004}
1005
Takashi Iwai3de95172012-05-07 18:03:15 +02001006/* common preparation job for alc_spec */
1007static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
1008{
1009 struct alc_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1010 int err;
1011
1012 if (!spec)
1013 return -ENOMEM;
1014 codec->spec = spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +01001015 snd_hda_gen_spec_init(&spec->gen);
1016 spec->gen.mixer_nid = mixer_nid;
1017 spec->gen.own_eapd_ctl = 1;
Takashi Iwai1098b7c2012-12-17 20:03:15 +01001018 codec->single_adc_amp = 1;
Takashi Iwai08c189f2012-12-19 15:22:24 +01001019 /* FIXME: do we need this for all Realtek codec models? */
1020 codec->spdif_status_reset = 1;
Takashi Iwai225068a2015-05-29 10:42:14 +02001021 codec->patch_ops = alc_patch_ops;
Takashi Iwai3de95172012-05-07 18:03:15 +02001022
1023 err = alc_codec_rename_from_preset(codec);
1024 if (err < 0) {
1025 kfree(spec);
1026 return err;
1027 }
1028 return 0;
1029}
1030
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001031static int alc880_parse_auto_config(struct hda_codec *codec)
1032{
1033 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
Jesper Juhl7d7eb9e2012-04-12 22:11:25 +02001034 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001035 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
1036}
1037
Takashi Iwai1d045db2011-07-07 18:23:21 +02001038/*
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001039 * ALC880 fix-ups
1040 */
1041enum {
Takashi Iwai411225a2012-02-20 17:48:19 +01001042 ALC880_FIXUP_GPIO1,
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001043 ALC880_FIXUP_GPIO2,
1044 ALC880_FIXUP_MEDION_RIM,
Takashi Iwaidc6af522012-02-17 16:18:59 +01001045 ALC880_FIXUP_LG,
Takashi Iwaidb8a38e2013-08-09 12:34:42 +02001046 ALC880_FIXUP_LG_LW25,
Takashi Iwaif02aab52012-02-17 16:33:56 +01001047 ALC880_FIXUP_W810,
Takashi Iwai27e917f2012-02-17 17:49:54 +01001048 ALC880_FIXUP_EAPD_COEF,
Takashi Iwaib9368f52012-02-17 17:54:44 +01001049 ALC880_FIXUP_TCL_S700,
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001050 ALC880_FIXUP_VOL_KNOB,
1051 ALC880_FIXUP_FUJITSU,
Takashi Iwaiba533812012-02-20 16:36:52 +01001052 ALC880_FIXUP_F1734,
Takashi Iwai817de922012-02-20 17:20:48 +01001053 ALC880_FIXUP_UNIWILL,
Takashi Iwai967b88c2012-02-20 17:31:02 +01001054 ALC880_FIXUP_UNIWILL_DIG,
Takashi Iwai96e225f2012-02-20 17:41:51 +01001055 ALC880_FIXUP_Z71V,
Takashi Iwai487a5882013-11-07 07:29:30 +01001056 ALC880_FIXUP_ASUS_W5A,
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001057 ALC880_FIXUP_3ST_BASE,
1058 ALC880_FIXUP_3ST,
1059 ALC880_FIXUP_3ST_DIG,
1060 ALC880_FIXUP_5ST_BASE,
1061 ALC880_FIXUP_5ST,
1062 ALC880_FIXUP_5ST_DIG,
1063 ALC880_FIXUP_6ST_BASE,
1064 ALC880_FIXUP_6ST,
1065 ALC880_FIXUP_6ST_DIG,
Takashi Iwai53971452013-01-23 18:21:37 +01001066 ALC880_FIXUP_6ST_AUTOMUTE,
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001067};
1068
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001069/* enable the volume-knob widget support on NID 0x21 */
1070static void alc880_fixup_vol_knob(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001071 const struct hda_fixup *fix, int action)
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001072{
Takashi Iwai1727a772013-01-10 09:52:52 +01001073 if (action == HDA_FIXUP_ACT_PROBE)
Takashi Iwai62f949b2014-09-11 14:06:53 +02001074 snd_hda_jack_detect_enable_callback(codec, 0x21,
1075 alc_update_knob_master);
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001076}
1077
Takashi Iwai1727a772013-01-10 09:52:52 +01001078static const struct hda_fixup alc880_fixups[] = {
Takashi Iwai411225a2012-02-20 17:48:19 +01001079 [ALC880_FIXUP_GPIO1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001080 .type = HDA_FIXUP_VERBS,
Takashi Iwai411225a2012-02-20 17:48:19 +01001081 .v.verbs = alc_gpio1_init_verbs,
1082 },
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001083 [ALC880_FIXUP_GPIO2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001084 .type = HDA_FIXUP_VERBS,
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001085 .v.verbs = alc_gpio2_init_verbs,
1086 },
1087 [ALC880_FIXUP_MEDION_RIM] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001088 .type = HDA_FIXUP_VERBS,
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001089 .v.verbs = (const struct hda_verb[]) {
1090 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1091 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
1092 { }
1093 },
1094 .chained = true,
1095 .chain_id = ALC880_FIXUP_GPIO2,
1096 },
Takashi Iwaidc6af522012-02-17 16:18:59 +01001097 [ALC880_FIXUP_LG] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001098 .type = HDA_FIXUP_PINS,
1099 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaidc6af522012-02-17 16:18:59 +01001100 /* disable bogus unused pins */
1101 { 0x16, 0x411111f0 },
1102 { 0x18, 0x411111f0 },
1103 { 0x1a, 0x411111f0 },
1104 { }
1105 }
1106 },
Takashi Iwaidb8a38e2013-08-09 12:34:42 +02001107 [ALC880_FIXUP_LG_LW25] = {
1108 .type = HDA_FIXUP_PINS,
1109 .v.pins = (const struct hda_pintbl[]) {
1110 { 0x1a, 0x0181344f }, /* line-in */
1111 { 0x1b, 0x0321403f }, /* headphone */
1112 { }
1113 }
1114 },
Takashi Iwaif02aab52012-02-17 16:33:56 +01001115 [ALC880_FIXUP_W810] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001116 .type = HDA_FIXUP_PINS,
1117 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaif02aab52012-02-17 16:33:56 +01001118 /* disable bogus unused pins */
1119 { 0x17, 0x411111f0 },
1120 { }
1121 },
1122 .chained = true,
1123 .chain_id = ALC880_FIXUP_GPIO2,
1124 },
Takashi Iwai27e917f2012-02-17 17:49:54 +01001125 [ALC880_FIXUP_EAPD_COEF] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001126 .type = HDA_FIXUP_VERBS,
Takashi Iwai27e917f2012-02-17 17:49:54 +01001127 .v.verbs = (const struct hda_verb[]) {
1128 /* change to EAPD mode */
1129 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1130 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
1131 {}
1132 },
1133 },
Takashi Iwaib9368f52012-02-17 17:54:44 +01001134 [ALC880_FIXUP_TCL_S700] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001135 .type = HDA_FIXUP_VERBS,
Takashi Iwaib9368f52012-02-17 17:54:44 +01001136 .v.verbs = (const struct hda_verb[]) {
1137 /* change to EAPD mode */
1138 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1139 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
1140 {}
1141 },
1142 .chained = true,
1143 .chain_id = ALC880_FIXUP_GPIO2,
1144 },
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001145 [ALC880_FIXUP_VOL_KNOB] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001146 .type = HDA_FIXUP_FUNC,
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001147 .v.func = alc880_fixup_vol_knob,
1148 },
1149 [ALC880_FIXUP_FUJITSU] = {
1150 /* override all pins as BIOS on old Amilo is broken */
Takashi Iwai1727a772013-01-10 09:52:52 +01001151 .type = HDA_FIXUP_PINS,
1152 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaibb148bd2015-08-13 18:02:39 +02001153 { 0x14, 0x0121401f }, /* HP */
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001154 { 0x15, 0x99030120 }, /* speaker */
1155 { 0x16, 0x99030130 }, /* bass speaker */
1156 { 0x17, 0x411111f0 }, /* N/A */
1157 { 0x18, 0x411111f0 }, /* N/A */
1158 { 0x19, 0x01a19950 }, /* mic-in */
1159 { 0x1a, 0x411111f0 }, /* N/A */
1160 { 0x1b, 0x411111f0 }, /* N/A */
1161 { 0x1c, 0x411111f0 }, /* N/A */
1162 { 0x1d, 0x411111f0 }, /* N/A */
1163 { 0x1e, 0x01454140 }, /* SPDIF out */
1164 { }
1165 },
1166 .chained = true,
1167 .chain_id = ALC880_FIXUP_VOL_KNOB,
1168 },
Takashi Iwaiba533812012-02-20 16:36:52 +01001169 [ALC880_FIXUP_F1734] = {
1170 /* almost compatible with FUJITSU, but no bass and SPDIF */
Takashi Iwai1727a772013-01-10 09:52:52 +01001171 .type = HDA_FIXUP_PINS,
1172 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaibb148bd2015-08-13 18:02:39 +02001173 { 0x14, 0x0121401f }, /* HP */
Takashi Iwaiba533812012-02-20 16:36:52 +01001174 { 0x15, 0x99030120 }, /* speaker */
1175 { 0x16, 0x411111f0 }, /* N/A */
1176 { 0x17, 0x411111f0 }, /* N/A */
1177 { 0x18, 0x411111f0 }, /* N/A */
1178 { 0x19, 0x01a19950 }, /* mic-in */
1179 { 0x1a, 0x411111f0 }, /* N/A */
1180 { 0x1b, 0x411111f0 }, /* N/A */
1181 { 0x1c, 0x411111f0 }, /* N/A */
1182 { 0x1d, 0x411111f0 }, /* N/A */
1183 { 0x1e, 0x411111f0 }, /* N/A */
1184 { }
1185 },
1186 .chained = true,
1187 .chain_id = ALC880_FIXUP_VOL_KNOB,
1188 },
Takashi Iwai817de922012-02-20 17:20:48 +01001189 [ALC880_FIXUP_UNIWILL] = {
1190 /* need to fix HP and speaker pins to be parsed correctly */
Takashi Iwai1727a772013-01-10 09:52:52 +01001191 .type = HDA_FIXUP_PINS,
1192 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai817de922012-02-20 17:20:48 +01001193 { 0x14, 0x0121411f }, /* HP */
1194 { 0x15, 0x99030120 }, /* speaker */
1195 { 0x16, 0x99030130 }, /* bass speaker */
1196 { }
1197 },
1198 },
Takashi Iwai967b88c2012-02-20 17:31:02 +01001199 [ALC880_FIXUP_UNIWILL_DIG] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001200 .type = HDA_FIXUP_PINS,
1201 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai967b88c2012-02-20 17:31:02 +01001202 /* disable bogus unused pins */
1203 { 0x17, 0x411111f0 },
1204 { 0x19, 0x411111f0 },
1205 { 0x1b, 0x411111f0 },
1206 { 0x1f, 0x411111f0 },
1207 { }
1208 }
1209 },
Takashi Iwai96e225f2012-02-20 17:41:51 +01001210 [ALC880_FIXUP_Z71V] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001211 .type = HDA_FIXUP_PINS,
1212 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai96e225f2012-02-20 17:41:51 +01001213 /* set up the whole pins as BIOS is utterly broken */
1214 { 0x14, 0x99030120 }, /* speaker */
1215 { 0x15, 0x0121411f }, /* HP */
1216 { 0x16, 0x411111f0 }, /* N/A */
1217 { 0x17, 0x411111f0 }, /* N/A */
1218 { 0x18, 0x01a19950 }, /* mic-in */
1219 { 0x19, 0x411111f0 }, /* N/A */
1220 { 0x1a, 0x01813031 }, /* line-in */
1221 { 0x1b, 0x411111f0 }, /* N/A */
1222 { 0x1c, 0x411111f0 }, /* N/A */
1223 { 0x1d, 0x411111f0 }, /* N/A */
1224 { 0x1e, 0x0144111e }, /* SPDIF */
1225 { }
1226 }
1227 },
Takashi Iwai487a5882013-11-07 07:29:30 +01001228 [ALC880_FIXUP_ASUS_W5A] = {
1229 .type = HDA_FIXUP_PINS,
1230 .v.pins = (const struct hda_pintbl[]) {
1231 /* set up the whole pins as BIOS is utterly broken */
1232 { 0x14, 0x0121411f }, /* HP */
1233 { 0x15, 0x411111f0 }, /* N/A */
1234 { 0x16, 0x411111f0 }, /* N/A */
1235 { 0x17, 0x411111f0 }, /* N/A */
1236 { 0x18, 0x90a60160 }, /* mic */
1237 { 0x19, 0x411111f0 }, /* N/A */
1238 { 0x1a, 0x411111f0 }, /* N/A */
1239 { 0x1b, 0x411111f0 }, /* N/A */
1240 { 0x1c, 0x411111f0 }, /* N/A */
1241 { 0x1d, 0x411111f0 }, /* N/A */
1242 { 0x1e, 0xb743111e }, /* SPDIF out */
1243 { }
1244 },
1245 .chained = true,
1246 .chain_id = ALC880_FIXUP_GPIO1,
1247 },
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001248 [ALC880_FIXUP_3ST_BASE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001249 .type = HDA_FIXUP_PINS,
1250 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001251 { 0x14, 0x01014010 }, /* line-out */
1252 { 0x15, 0x411111f0 }, /* N/A */
1253 { 0x16, 0x411111f0 }, /* N/A */
1254 { 0x17, 0x411111f0 }, /* N/A */
1255 { 0x18, 0x01a19c30 }, /* mic-in */
1256 { 0x19, 0x0121411f }, /* HP */
1257 { 0x1a, 0x01813031 }, /* line-in */
1258 { 0x1b, 0x02a19c40 }, /* front-mic */
1259 { 0x1c, 0x411111f0 }, /* N/A */
1260 { 0x1d, 0x411111f0 }, /* N/A */
1261 /* 0x1e is filled in below */
1262 { 0x1f, 0x411111f0 }, /* N/A */
1263 { }
1264 }
1265 },
1266 [ALC880_FIXUP_3ST] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001267 .type = HDA_FIXUP_PINS,
1268 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001269 { 0x1e, 0x411111f0 }, /* N/A */
1270 { }
1271 },
1272 .chained = true,
1273 .chain_id = ALC880_FIXUP_3ST_BASE,
1274 },
1275 [ALC880_FIXUP_3ST_DIG] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001276 .type = HDA_FIXUP_PINS,
1277 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001278 { 0x1e, 0x0144111e }, /* SPDIF */
1279 { }
1280 },
1281 .chained = true,
1282 .chain_id = ALC880_FIXUP_3ST_BASE,
1283 },
1284 [ALC880_FIXUP_5ST_BASE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001285 .type = HDA_FIXUP_PINS,
1286 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001287 { 0x14, 0x01014010 }, /* front */
1288 { 0x15, 0x411111f0 }, /* N/A */
1289 { 0x16, 0x01011411 }, /* CLFE */
1290 { 0x17, 0x01016412 }, /* surr */
1291 { 0x18, 0x01a19c30 }, /* mic-in */
1292 { 0x19, 0x0121411f }, /* HP */
1293 { 0x1a, 0x01813031 }, /* line-in */
1294 { 0x1b, 0x02a19c40 }, /* front-mic */
1295 { 0x1c, 0x411111f0 }, /* N/A */
1296 { 0x1d, 0x411111f0 }, /* N/A */
1297 /* 0x1e is filled in below */
1298 { 0x1f, 0x411111f0 }, /* N/A */
1299 { }
1300 }
1301 },
1302 [ALC880_FIXUP_5ST] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001303 .type = HDA_FIXUP_PINS,
1304 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001305 { 0x1e, 0x411111f0 }, /* N/A */
1306 { }
1307 },
1308 .chained = true,
1309 .chain_id = ALC880_FIXUP_5ST_BASE,
1310 },
1311 [ALC880_FIXUP_5ST_DIG] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001312 .type = HDA_FIXUP_PINS,
1313 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001314 { 0x1e, 0x0144111e }, /* SPDIF */
1315 { }
1316 },
1317 .chained = true,
1318 .chain_id = ALC880_FIXUP_5ST_BASE,
1319 },
1320 [ALC880_FIXUP_6ST_BASE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001321 .type = HDA_FIXUP_PINS,
1322 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001323 { 0x14, 0x01014010 }, /* front */
1324 { 0x15, 0x01016412 }, /* surr */
1325 { 0x16, 0x01011411 }, /* CLFE */
1326 { 0x17, 0x01012414 }, /* side */
1327 { 0x18, 0x01a19c30 }, /* mic-in */
1328 { 0x19, 0x02a19c40 }, /* front-mic */
1329 { 0x1a, 0x01813031 }, /* line-in */
1330 { 0x1b, 0x0121411f }, /* HP */
1331 { 0x1c, 0x411111f0 }, /* N/A */
1332 { 0x1d, 0x411111f0 }, /* N/A */
1333 /* 0x1e is filled in below */
1334 { 0x1f, 0x411111f0 }, /* N/A */
1335 { }
1336 }
1337 },
1338 [ALC880_FIXUP_6ST] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001339 .type = HDA_FIXUP_PINS,
1340 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001341 { 0x1e, 0x411111f0 }, /* N/A */
1342 { }
1343 },
1344 .chained = true,
1345 .chain_id = ALC880_FIXUP_6ST_BASE,
1346 },
1347 [ALC880_FIXUP_6ST_DIG] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001348 .type = HDA_FIXUP_PINS,
1349 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001350 { 0x1e, 0x0144111e }, /* SPDIF */
1351 { }
1352 },
1353 .chained = true,
1354 .chain_id = ALC880_FIXUP_6ST_BASE,
1355 },
Takashi Iwai53971452013-01-23 18:21:37 +01001356 [ALC880_FIXUP_6ST_AUTOMUTE] = {
1357 .type = HDA_FIXUP_PINS,
1358 .v.pins = (const struct hda_pintbl[]) {
1359 { 0x1b, 0x0121401f }, /* HP with jack detect */
1360 { }
1361 },
1362 .chained_before = true,
1363 .chain_id = ALC880_FIXUP_6ST_BASE,
1364 },
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001365};
1366
1367static const struct snd_pci_quirk alc880_fixup_tbl[] = {
Takashi Iwaif02aab52012-02-17 16:33:56 +01001368 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
Takashi Iwai487a5882013-11-07 07:29:30 +01001369 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A),
Takashi Iwai96e225f2012-02-20 17:41:51 +01001370 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
Takashi Iwai29e3fdc2012-02-20 17:56:57 +01001371 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
David Henningsson6538de02014-06-10 10:52:50 +02001372 SND_PCI_QUIRK(0x147b, 0x1045, "ABit AA8XE", ALC880_FIXUP_6ST_AUTOMUTE),
Takashi Iwai29e3fdc2012-02-20 17:56:57 +01001373 SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
Takashi Iwai27e917f2012-02-17 17:49:54 +01001374 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF),
Takashi Iwai967b88c2012-02-20 17:31:02 +01001375 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG),
Takashi Iwaiba533812012-02-20 16:36:52 +01001376 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734),
Takashi Iwai817de922012-02-20 17:20:48 +01001377 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL),
Takashi Iwai7833c7e2012-02-20 17:11:38 +01001378 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
Takashi Iwaif02aab52012-02-17 16:33:56 +01001379 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001380 SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
Takashi Iwai53971452013-01-23 18:21:37 +01001381 SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST_AUTOMUTE),
Takashi Iwaia1615742015-08-13 18:05:06 +02001382 SND_PCI_QUIRK(0x1734, 0x107c, "FSC Amilo M1437", ALC880_FIXUP_FUJITSU),
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001383 SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
Takashi Iwaiba533812012-02-20 16:36:52 +01001384 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001385 SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU),
Takashi Iwaidc6af522012-02-17 16:18:59 +01001386 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
1387 SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
1388 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
Takashi Iwaidb8a38e2013-08-09 12:34:42 +02001389 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_FIXUP_LG_LW25),
Takashi Iwaib9368f52012-02-17 17:54:44 +01001390 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001391
1392 /* Below is the copied entries from alc880_quirks.c.
1393 * It's not quite sure whether BIOS sets the correct pin-config table
1394 * on these machines, thus they are kept to be compatible with
1395 * the old static quirks. Once when it's confirmed to work without
1396 * these overrides, it'd be better to remove.
1397 */
1398 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG),
1399 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST),
1400 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG),
1401 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG),
1402 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG),
1403 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG),
1404 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG),
1405 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST),
1406 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG),
1407 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST),
1408 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST),
1409 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST),
1410 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST),
1411 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST),
1412 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG),
1413 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG),
1414 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG),
1415 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG),
1416 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG),
1417 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG),
1418 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG),
1419 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */
1420 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG),
1421 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1422 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1423 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1424 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG),
1425 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1426 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG),
1427 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG),
1428 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1429 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1430 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1431 /* default Intel */
1432 SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST),
1433 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG),
1434 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG),
1435 {}
1436};
1437
Takashi Iwai1727a772013-01-10 09:52:52 +01001438static const struct hda_model_fixup alc880_fixup_models[] = {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001439 {.id = ALC880_FIXUP_3ST, .name = "3stack"},
1440 {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"},
1441 {.id = ALC880_FIXUP_5ST, .name = "5stack"},
1442 {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"},
1443 {.id = ALC880_FIXUP_6ST, .name = "6stack"},
1444 {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"},
Takashi Iwai53971452013-01-23 18:21:37 +01001445 {.id = ALC880_FIXUP_6ST_AUTOMUTE, .name = "6stack-automute"},
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001446 {}
1447};
1448
1449
1450/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001451 * OK, here we have finally the patch for ALC880
1452 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02001453static int patch_alc880(struct hda_codec *codec)
1454{
1455 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001456 int err;
1457
Takashi Iwai3de95172012-05-07 18:03:15 +02001458 err = alc_alloc_spec(codec, 0x0b);
1459 if (err < 0)
1460 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001461
Takashi Iwai3de95172012-05-07 18:03:15 +02001462 spec = codec->spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +01001463 spec->gen.need_dac_fix = 1;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01001464 spec->gen.beep_nid = 0x01;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001465
Takashi Iwai225068a2015-05-29 10:42:14 +02001466 codec->patch_ops.unsol_event = alc880_unsol_event;
1467
Takashi Iwai1727a772013-01-10 09:52:52 +01001468 snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001469 alc880_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01001470 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001471
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001472 /* automatic parse from the BIOS config */
1473 err = alc880_parse_auto_config(codec);
1474 if (err < 0)
1475 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001476
Takashi Iwai7504b6c2013-03-18 11:25:51 +01001477 if (!spec->gen.no_analog)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001478 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001479
Takashi Iwai1727a772013-01-10 09:52:52 +01001480 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01001481
Takashi Iwai1d045db2011-07-07 18:23:21 +02001482 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02001483
1484 error:
1485 alc_free(codec);
1486 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001487}
1488
1489
1490/*
1491 * ALC260 support
1492 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02001493static int alc260_parse_auto_config(struct hda_codec *codec)
1494{
Takashi Iwai1d045db2011-07-07 18:23:21 +02001495 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001496 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
1497 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001498}
1499
Takashi Iwai1d045db2011-07-07 18:23:21 +02001500/*
1501 * Pin config fixes
1502 */
1503enum {
Takashi Iwaica8f0422012-02-16 11:51:19 +01001504 ALC260_FIXUP_HP_DC5750,
1505 ALC260_FIXUP_HP_PIN_0F,
1506 ALC260_FIXUP_COEF,
Takashi Iwai15317ab2012-02-16 12:02:53 +01001507 ALC260_FIXUP_GPIO1,
Takashi Iwai20f7d922012-02-16 12:35:16 +01001508 ALC260_FIXUP_GPIO1_TOGGLE,
1509 ALC260_FIXUP_REPLACER,
Takashi Iwai0a1c4fa2012-02-16 12:42:30 +01001510 ALC260_FIXUP_HP_B1900,
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001511 ALC260_FIXUP_KN1,
Takashi Iwai39aedee2013-01-10 17:10:40 +01001512 ALC260_FIXUP_FSC_S7020,
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001513 ALC260_FIXUP_FSC_S7020_JWSE,
Takashi Iwaid08c5ef2013-11-22 08:06:36 +01001514 ALC260_FIXUP_VAIO_PINS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001515};
1516
Takashi Iwai20f7d922012-02-16 12:35:16 +01001517static void alc260_gpio1_automute(struct hda_codec *codec)
1518{
1519 struct alc_spec *spec = codec->spec;
1520 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
Takashi Iwai08c189f2012-12-19 15:22:24 +01001521 spec->gen.hp_jack_present);
Takashi Iwai20f7d922012-02-16 12:35:16 +01001522}
1523
1524static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001525 const struct hda_fixup *fix, int action)
Takashi Iwai20f7d922012-02-16 12:35:16 +01001526{
1527 struct alc_spec *spec = codec->spec;
Takashi Iwai1727a772013-01-10 09:52:52 +01001528 if (action == HDA_FIXUP_ACT_PROBE) {
Takashi Iwai20f7d922012-02-16 12:35:16 +01001529 /* although the machine has only one output pin, we need to
1530 * toggle GPIO1 according to the jack state
1531 */
Takashi Iwai08c189f2012-12-19 15:22:24 +01001532 spec->gen.automute_hook = alc260_gpio1_automute;
1533 spec->gen.detect_hp = 1;
1534 spec->gen.automute_speaker = 1;
1535 spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
Takashi Iwai62f949b2014-09-11 14:06:53 +02001536 snd_hda_jack_detect_enable_callback(codec, 0x0f,
Takashi Iwai08c189f2012-12-19 15:22:24 +01001537 snd_hda_gen_hp_automute);
Takashi Iwaic9ce6b22012-12-18 18:12:44 +01001538 snd_hda_add_verbs(codec, alc_gpio1_init_verbs);
Takashi Iwai20f7d922012-02-16 12:35:16 +01001539 }
1540}
1541
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001542static void alc260_fixup_kn1(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001543 const struct hda_fixup *fix, int action)
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001544{
1545 struct alc_spec *spec = codec->spec;
Takashi Iwai1727a772013-01-10 09:52:52 +01001546 static const struct hda_pintbl pincfgs[] = {
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001547 { 0x0f, 0x02214000 }, /* HP/speaker */
1548 { 0x12, 0x90a60160 }, /* int mic */
1549 { 0x13, 0x02a19000 }, /* ext mic */
1550 { 0x18, 0x01446000 }, /* SPDIF out */
1551 /* disable bogus I/O pins */
1552 { 0x10, 0x411111f0 },
1553 { 0x11, 0x411111f0 },
1554 { 0x14, 0x411111f0 },
1555 { 0x15, 0x411111f0 },
1556 { 0x16, 0x411111f0 },
1557 { 0x17, 0x411111f0 },
1558 { 0x19, 0x411111f0 },
1559 { }
1560 };
1561
1562 switch (action) {
Takashi Iwai1727a772013-01-10 09:52:52 +01001563 case HDA_FIXUP_ACT_PRE_PROBE:
1564 snd_hda_apply_pincfgs(codec, pincfgs);
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001565 break;
Takashi Iwai1727a772013-01-10 09:52:52 +01001566 case HDA_FIXUP_ACT_PROBE:
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001567 spec->init_amp = ALC_INIT_NONE;
1568 break;
1569 }
1570}
1571
Takashi Iwai39aedee2013-01-10 17:10:40 +01001572static void alc260_fixup_fsc_s7020(struct hda_codec *codec,
1573 const struct hda_fixup *fix, int action)
1574{
1575 struct alc_spec *spec = codec->spec;
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001576 if (action == HDA_FIXUP_ACT_PROBE)
Takashi Iwaie6e0ee52013-02-18 17:04:20 +01001577 spec->init_amp = ALC_INIT_NONE;
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001578}
1579
1580static void alc260_fixup_fsc_s7020_jwse(struct hda_codec *codec,
1581 const struct hda_fixup *fix, int action)
1582{
1583 struct alc_spec *spec = codec->spec;
1584 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwaif811c3c2013-03-07 18:32:59 +01001585 spec->gen.add_jack_modes = 1;
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001586 spec->gen.hp_mic = 1;
Takashi Iwaie6e0ee52013-02-18 17:04:20 +01001587 }
Takashi Iwai39aedee2013-01-10 17:10:40 +01001588}
1589
Takashi Iwai1727a772013-01-10 09:52:52 +01001590static const struct hda_fixup alc260_fixups[] = {
Takashi Iwaica8f0422012-02-16 11:51:19 +01001591 [ALC260_FIXUP_HP_DC5750] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001592 .type = HDA_FIXUP_PINS,
1593 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02001594 { 0x11, 0x90130110 }, /* speaker */
1595 { }
1596 }
1597 },
Takashi Iwaica8f0422012-02-16 11:51:19 +01001598 [ALC260_FIXUP_HP_PIN_0F] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001599 .type = HDA_FIXUP_PINS,
1600 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaica8f0422012-02-16 11:51:19 +01001601 { 0x0f, 0x01214000 }, /* HP */
1602 { }
1603 }
1604 },
1605 [ALC260_FIXUP_COEF] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001606 .type = HDA_FIXUP_VERBS,
Takashi Iwaica8f0422012-02-16 11:51:19 +01001607 .v.verbs = (const struct hda_verb[]) {
Ronan Marquete30cf2d2014-06-01 18:38:53 +02001608 { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
1609 { 0x1a, AC_VERB_SET_PROC_COEF, 0x3040 },
Takashi Iwaica8f0422012-02-16 11:51:19 +01001610 { }
1611 },
Takashi Iwaica8f0422012-02-16 11:51:19 +01001612 },
Takashi Iwai15317ab2012-02-16 12:02:53 +01001613 [ALC260_FIXUP_GPIO1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001614 .type = HDA_FIXUP_VERBS,
Takashi Iwai15317ab2012-02-16 12:02:53 +01001615 .v.verbs = alc_gpio1_init_verbs,
1616 },
Takashi Iwai20f7d922012-02-16 12:35:16 +01001617 [ALC260_FIXUP_GPIO1_TOGGLE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001618 .type = HDA_FIXUP_FUNC,
Takashi Iwai20f7d922012-02-16 12:35:16 +01001619 .v.func = alc260_fixup_gpio1_toggle,
1620 .chained = true,
1621 .chain_id = ALC260_FIXUP_HP_PIN_0F,
1622 },
1623 [ALC260_FIXUP_REPLACER] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001624 .type = HDA_FIXUP_VERBS,
Takashi Iwai20f7d922012-02-16 12:35:16 +01001625 .v.verbs = (const struct hda_verb[]) {
Takashi Iwai192a98e2014-06-02 15:16:07 +02001626 { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
1627 { 0x1a, AC_VERB_SET_PROC_COEF, 0x3050 },
Takashi Iwai20f7d922012-02-16 12:35:16 +01001628 { }
1629 },
1630 .chained = true,
1631 .chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
1632 },
Takashi Iwai0a1c4fa2012-02-16 12:42:30 +01001633 [ALC260_FIXUP_HP_B1900] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001634 .type = HDA_FIXUP_FUNC,
Takashi Iwai0a1c4fa2012-02-16 12:42:30 +01001635 .v.func = alc260_fixup_gpio1_toggle,
1636 .chained = true,
1637 .chain_id = ALC260_FIXUP_COEF,
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001638 },
1639 [ALC260_FIXUP_KN1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001640 .type = HDA_FIXUP_FUNC,
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001641 .v.func = alc260_fixup_kn1,
1642 },
Takashi Iwai39aedee2013-01-10 17:10:40 +01001643 [ALC260_FIXUP_FSC_S7020] = {
1644 .type = HDA_FIXUP_FUNC,
1645 .v.func = alc260_fixup_fsc_s7020,
1646 },
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001647 [ALC260_FIXUP_FSC_S7020_JWSE] = {
1648 .type = HDA_FIXUP_FUNC,
1649 .v.func = alc260_fixup_fsc_s7020_jwse,
1650 .chained = true,
1651 .chain_id = ALC260_FIXUP_FSC_S7020,
1652 },
Takashi Iwaid08c5ef2013-11-22 08:06:36 +01001653 [ALC260_FIXUP_VAIO_PINS] = {
1654 .type = HDA_FIXUP_PINS,
1655 .v.pins = (const struct hda_pintbl[]) {
1656 /* Pin configs are missing completely on some VAIOs */
1657 { 0x0f, 0x01211020 },
1658 { 0x10, 0x0001003f },
1659 { 0x11, 0x411111f0 },
1660 { 0x12, 0x01a15930 },
1661 { 0x13, 0x411111f0 },
1662 { 0x14, 0x411111f0 },
1663 { 0x15, 0x411111f0 },
1664 { 0x16, 0x411111f0 },
1665 { 0x17, 0x411111f0 },
1666 { 0x18, 0x411111f0 },
1667 { 0x19, 0x411111f0 },
1668 { }
1669 }
1670 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02001671};
1672
1673static const struct snd_pci_quirk alc260_fixup_tbl[] = {
Takashi Iwai15317ab2012-02-16 12:02:53 +01001674 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
Takashi Iwaica8f0422012-02-16 11:51:19 +01001675 SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
Takashi Iwai15317ab2012-02-16 12:02:53 +01001676 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
Takashi Iwaica8f0422012-02-16 11:51:19 +01001677 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
Takashi Iwai0a1c4fa2012-02-16 12:42:30 +01001678 SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
Takashi Iwaid08c5ef2013-11-22 08:06:36 +01001679 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_FIXUP_VAIO_PINS),
Takashi Iwai0f5a5b82013-11-21 09:12:52 +01001680 SND_PCI_QUIRK(0x104d, 0x81e2, "Sony VAIO TX", ALC260_FIXUP_HP_PIN_0F),
Takashi Iwai39aedee2013-01-10 17:10:40 +01001681 SND_PCI_QUIRK(0x10cf, 0x1326, "FSC LifeBook S7020", ALC260_FIXUP_FSC_S7020),
Takashi Iwaib1f58082012-02-16 12:45:03 +01001682 SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001683 SND_PCI_QUIRK(0x152d, 0x0729, "Quanta KN1", ALC260_FIXUP_KN1),
Takashi Iwai20f7d922012-02-16 12:35:16 +01001684 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
Takashi Iwaica8f0422012-02-16 11:51:19 +01001685 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
Takashi Iwai1d045db2011-07-07 18:23:21 +02001686 {}
1687};
1688
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001689static const struct hda_model_fixup alc260_fixup_models[] = {
1690 {.id = ALC260_FIXUP_GPIO1, .name = "gpio1"},
1691 {.id = ALC260_FIXUP_COEF, .name = "coef"},
1692 {.id = ALC260_FIXUP_FSC_S7020, .name = "fujitsu"},
1693 {.id = ALC260_FIXUP_FSC_S7020_JWSE, .name = "fujitsu-jwse"},
1694 {}
1695};
1696
Takashi Iwai1d045db2011-07-07 18:23:21 +02001697/*
1698 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02001699static int patch_alc260(struct hda_codec *codec)
1700{
1701 struct alc_spec *spec;
Takashi Iwaic3c2c9e2012-02-16 12:59:55 +01001702 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001703
Takashi Iwai3de95172012-05-07 18:03:15 +02001704 err = alc_alloc_spec(codec, 0x07);
1705 if (err < 0)
1706 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001707
Takashi Iwai3de95172012-05-07 18:03:15 +02001708 spec = codec->spec;
Takashi Iwaiea46c3c2013-01-15 18:45:53 +01001709 /* as quite a few machines require HP amp for speaker outputs,
1710 * it's easier to enable it unconditionally; even if it's unneeded,
1711 * it's almost harmless.
1712 */
1713 spec->gen.prefer_hp_amp = 1;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01001714 spec->gen.beep_nid = 0x01;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001715
Takashi Iwai225068a2015-05-29 10:42:14 +02001716 spec->shutup = alc_eapd_shutup;
1717
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001718 snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl,
1719 alc260_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01001720 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001721
Takashi Iwaic3c2c9e2012-02-16 12:59:55 +01001722 /* automatic parse from the BIOS config */
1723 err = alc260_parse_auto_config(codec);
1724 if (err < 0)
1725 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001726
Takashi Iwai7504b6c2013-03-18 11:25:51 +01001727 if (!spec->gen.no_analog)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001728 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001729
Takashi Iwai1727a772013-01-10 09:52:52 +01001730 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01001731
Takashi Iwai1d045db2011-07-07 18:23:21 +02001732 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02001733
1734 error:
1735 alc_free(codec);
1736 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001737}
1738
1739
1740/*
1741 * ALC882/883/885/888/889 support
1742 *
1743 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
1744 * configuration. Each pin widget can choose any input DACs and a mixer.
1745 * Each ADC is connected from a mixer of all inputs. This makes possible
1746 * 6-channel independent captures.
1747 *
1748 * In addition, an independent DAC for the multi-playback (not used in this
1749 * driver yet).
1750 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02001751
1752/*
1753 * Pin config fixes
1754 */
1755enum {
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01001756 ALC882_FIXUP_ABIT_AW9D_MAX,
1757 ALC882_FIXUP_LENOVO_Y530,
1758 ALC882_FIXUP_PB_M5210,
1759 ALC882_FIXUP_ACER_ASPIRE_7736,
1760 ALC882_FIXUP_ASUS_W90V,
Marton Balint8f239212012-03-05 21:33:23 +01001761 ALC889_FIXUP_CD,
David Henningssonb2c53e22014-01-01 14:01:34 +01001762 ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01001763 ALC889_FIXUP_VAIO_TT,
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01001764 ALC888_FIXUP_EEE1601,
Takashi Iwai177943a2011-11-09 12:55:18 +01001765 ALC882_FIXUP_EAPD,
Takashi Iwai7a6069b2011-11-09 15:22:01 +01001766 ALC883_FIXUP_EAPD,
Takashi Iwai8812c4f2011-11-09 17:39:15 +01001767 ALC883_FIXUP_ACER_EAPD,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001768 ALC882_FIXUP_GPIO1,
1769 ALC882_FIXUP_GPIO2,
Takashi Iwaieb844d52011-11-09 18:03:07 +01001770 ALC882_FIXUP_GPIO3,
Takashi Iwai68ef0562011-11-09 18:24:44 +01001771 ALC889_FIXUP_COEF,
1772 ALC882_FIXUP_ASUS_W2JC,
Takashi Iwaic3e837b2011-11-10 16:01:47 +01001773 ALC882_FIXUP_ACER_ASPIRE_4930G,
1774 ALC882_FIXUP_ACER_ASPIRE_8930G,
1775 ALC882_FIXUP_ASPIRE_8930G_VERBS,
Takashi Iwai56710872011-11-14 17:42:11 +01001776 ALC885_FIXUP_MACPRO_GPIO,
Takashi Iwai02a237b2012-02-13 15:25:07 +01001777 ALC889_FIXUP_DAC_ROUTE,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001778 ALC889_FIXUP_MBP_VREF,
1779 ALC889_FIXUP_IMAC91_VREF,
Adrien Vergée7729a42014-01-24 14:56:14 -05001780 ALC889_FIXUP_MBA11_VREF,
Takashi Iwai0756f092013-12-04 13:59:45 +01001781 ALC889_FIXUP_MBA21_VREF,
Takashi Iwaic20f31e2014-02-03 11:02:10 +01001782 ALC889_FIXUP_MP11_VREF,
Mario Kleiner9f660a12015-12-22 00:45:43 +01001783 ALC889_FIXUP_MP41_VREF,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02001784 ALC882_FIXUP_INV_DMIC,
Takashi Iwaie427c232012-07-29 10:04:08 +02001785 ALC882_FIXUP_NO_PRIMARY_HP,
Takashi Iwai1f0bbf02013-11-28 15:21:21 +01001786 ALC887_FIXUP_ASUS_BASS,
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01001787 ALC887_FIXUP_BASS_CHMAP,
Takashi Iwai0c25ad82015-11-24 20:02:12 +01001788 ALC882_FIXUP_DISABLE_AAMIX,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001789};
1790
Takashi Iwai68ef0562011-11-09 18:24:44 +01001791static void alc889_fixup_coef(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001792 const struct hda_fixup *fix, int action)
Takashi Iwai68ef0562011-11-09 18:24:44 +01001793{
Takashi Iwai1727a772013-01-10 09:52:52 +01001794 if (action != HDA_FIXUP_ACT_INIT)
Takashi Iwai68ef0562011-11-09 18:24:44 +01001795 return;
Kailang Yang1df88742014-10-29 16:10:13 +08001796 alc_update_coef_idx(codec, 7, 0, 0x2030);
Takashi Iwai68ef0562011-11-09 18:24:44 +01001797}
1798
Takashi Iwai56710872011-11-14 17:42:11 +01001799/* toggle speaker-output according to the hp-jack state */
1800static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
1801{
1802 unsigned int gpiostate, gpiomask, gpiodir;
1803
Takashi Iwai7639a062015-03-03 10:07:24 +01001804 gpiostate = snd_hda_codec_read(codec, codec->core.afg, 0,
Takashi Iwai56710872011-11-14 17:42:11 +01001805 AC_VERB_GET_GPIO_DATA, 0);
1806
1807 if (!muted)
1808 gpiostate |= (1 << pin);
1809 else
1810 gpiostate &= ~(1 << pin);
1811
Takashi Iwai7639a062015-03-03 10:07:24 +01001812 gpiomask = snd_hda_codec_read(codec, codec->core.afg, 0,
Takashi Iwai56710872011-11-14 17:42:11 +01001813 AC_VERB_GET_GPIO_MASK, 0);
1814 gpiomask |= (1 << pin);
1815
Takashi Iwai7639a062015-03-03 10:07:24 +01001816 gpiodir = snd_hda_codec_read(codec, codec->core.afg, 0,
Takashi Iwai56710872011-11-14 17:42:11 +01001817 AC_VERB_GET_GPIO_DIRECTION, 0);
1818 gpiodir |= (1 << pin);
1819
1820
Takashi Iwai7639a062015-03-03 10:07:24 +01001821 snd_hda_codec_write(codec, codec->core.afg, 0,
Takashi Iwai56710872011-11-14 17:42:11 +01001822 AC_VERB_SET_GPIO_MASK, gpiomask);
Takashi Iwai7639a062015-03-03 10:07:24 +01001823 snd_hda_codec_write(codec, codec->core.afg, 0,
Takashi Iwai56710872011-11-14 17:42:11 +01001824 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
1825
1826 msleep(1);
1827
Takashi Iwai7639a062015-03-03 10:07:24 +01001828 snd_hda_codec_write(codec, codec->core.afg, 0,
Takashi Iwai56710872011-11-14 17:42:11 +01001829 AC_VERB_SET_GPIO_DATA, gpiostate);
1830}
1831
1832/* set up GPIO at initialization */
1833static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001834 const struct hda_fixup *fix, int action)
Takashi Iwai56710872011-11-14 17:42:11 +01001835{
Takashi Iwai1727a772013-01-10 09:52:52 +01001836 if (action != HDA_FIXUP_ACT_INIT)
Takashi Iwai56710872011-11-14 17:42:11 +01001837 return;
1838 alc882_gpio_mute(codec, 0, 0);
1839 alc882_gpio_mute(codec, 1, 0);
1840}
1841
Takashi Iwai02a237b2012-02-13 15:25:07 +01001842/* Fix the connection of some pins for ALC889:
1843 * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
1844 * work correctly (bko#42740)
1845 */
1846static void alc889_fixup_dac_route(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001847 const struct hda_fixup *fix, int action)
Takashi Iwai02a237b2012-02-13 15:25:07 +01001848{
Takashi Iwai1727a772013-01-10 09:52:52 +01001849 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwaief8d60f2012-02-17 10:12:38 +01001850 /* fake the connections during parsing the tree */
Takashi Iwai02a237b2012-02-13 15:25:07 +01001851 hda_nid_t conn1[2] = { 0x0c, 0x0d };
1852 hda_nid_t conn2[2] = { 0x0e, 0x0f };
1853 snd_hda_override_conn_list(codec, 0x14, 2, conn1);
1854 snd_hda_override_conn_list(codec, 0x15, 2, conn1);
1855 snd_hda_override_conn_list(codec, 0x18, 2, conn2);
1856 snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
Takashi Iwai1727a772013-01-10 09:52:52 +01001857 } else if (action == HDA_FIXUP_ACT_PROBE) {
Takashi Iwaief8d60f2012-02-17 10:12:38 +01001858 /* restore the connections */
1859 hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
1860 snd_hda_override_conn_list(codec, 0x14, 5, conn);
1861 snd_hda_override_conn_list(codec, 0x15, 5, conn);
1862 snd_hda_override_conn_list(codec, 0x18, 5, conn);
1863 snd_hda_override_conn_list(codec, 0x1a, 5, conn);
Takashi Iwai02a237b2012-02-13 15:25:07 +01001864 }
1865}
1866
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001867/* Set VREF on HP pin */
1868static void alc889_fixup_mbp_vref(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001869 const struct hda_fixup *fix, int action)
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001870{
1871 struct alc_spec *spec = codec->spec;
Mario Kleiner9f660a12015-12-22 00:45:43 +01001872 static hda_nid_t nids[3] = { 0x14, 0x15, 0x19 };
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001873 int i;
1874
Takashi Iwai1727a772013-01-10 09:52:52 +01001875 if (action != HDA_FIXUP_ACT_INIT)
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001876 return;
1877 for (i = 0; i < ARRAY_SIZE(nids); i++) {
1878 unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]);
1879 if (get_defcfg_device(val) != AC_JACK_HP_OUT)
1880 continue;
Takashi Iwaid3f02d62013-01-10 10:12:22 +01001881 val = snd_hda_codec_get_pin_target(codec, nids[i]);
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001882 val |= AC_PINCTL_VREF_80;
Takashi Iwaicdd03ce2012-04-20 12:34:50 +02001883 snd_hda_set_pin_ctl(codec, nids[i], val);
Takashi Iwai08c189f2012-12-19 15:22:24 +01001884 spec->gen.keep_vref_in_automute = 1;
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001885 break;
1886 }
1887}
1888
Takashi Iwai0756f092013-12-04 13:59:45 +01001889static void alc889_fixup_mac_pins(struct hda_codec *codec,
1890 const hda_nid_t *nids, int num_nids)
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001891{
1892 struct alc_spec *spec = codec->spec;
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001893 int i;
1894
Takashi Iwai0756f092013-12-04 13:59:45 +01001895 for (i = 0; i < num_nids; i++) {
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001896 unsigned int val;
Takashi Iwaid3f02d62013-01-10 10:12:22 +01001897 val = snd_hda_codec_get_pin_target(codec, nids[i]);
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001898 val |= AC_PINCTL_VREF_50;
Takashi Iwaicdd03ce2012-04-20 12:34:50 +02001899 snd_hda_set_pin_ctl(codec, nids[i], val);
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001900 }
Takashi Iwai08c189f2012-12-19 15:22:24 +01001901 spec->gen.keep_vref_in_automute = 1;
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001902}
1903
Takashi Iwai0756f092013-12-04 13:59:45 +01001904/* Set VREF on speaker pins on imac91 */
1905static void alc889_fixup_imac91_vref(struct hda_codec *codec,
1906 const struct hda_fixup *fix, int action)
1907{
1908 static hda_nid_t nids[2] = { 0x18, 0x1a };
1909
1910 if (action == HDA_FIXUP_ACT_INIT)
1911 alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
1912}
1913
Adrien Vergée7729a42014-01-24 14:56:14 -05001914/* Set VREF on speaker pins on mba11 */
1915static void alc889_fixup_mba11_vref(struct hda_codec *codec,
1916 const struct hda_fixup *fix, int action)
1917{
1918 static hda_nid_t nids[1] = { 0x18 };
1919
1920 if (action == HDA_FIXUP_ACT_INIT)
1921 alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
1922}
1923
Takashi Iwai0756f092013-12-04 13:59:45 +01001924/* Set VREF on speaker pins on mba21 */
1925static void alc889_fixup_mba21_vref(struct hda_codec *codec,
1926 const struct hda_fixup *fix, int action)
1927{
1928 static hda_nid_t nids[2] = { 0x18, 0x19 };
1929
1930 if (action == HDA_FIXUP_ACT_INIT)
1931 alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
1932}
1933
Takashi Iwaie427c232012-07-29 10:04:08 +02001934/* Don't take HP output as primary
Fernando Luis Vázquez Caod9111492013-02-12 16:49:46 +09001935 * Strangely, the speaker output doesn't work on Vaio Z and some Vaio
1936 * all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05
Takashi Iwaie427c232012-07-29 10:04:08 +02001937 */
1938static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001939 const struct hda_fixup *fix, int action)
Takashi Iwaie427c232012-07-29 10:04:08 +02001940{
1941 struct alc_spec *spec = codec->spec;
Takashi Iwaida96fb52013-07-29 16:54:36 +02001942 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwai08c189f2012-12-19 15:22:24 +01001943 spec->gen.no_primary_hp = 1;
Takashi Iwaida96fb52013-07-29 16:54:36 +02001944 spec->gen.no_multi_io = 1;
1945 }
Takashi Iwaie427c232012-07-29 10:04:08 +02001946}
1947
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01001948static void alc_fixup_bass_chmap(struct hda_codec *codec,
1949 const struct hda_fixup *fix, int action);
Takashi Iwai0c25ad82015-11-24 20:02:12 +01001950static void alc_fixup_disable_aamix(struct hda_codec *codec,
1951 const struct hda_fixup *fix, int action);
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01001952
Takashi Iwai1727a772013-01-10 09:52:52 +01001953static const struct hda_fixup alc882_fixups[] = {
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01001954 [ALC882_FIXUP_ABIT_AW9D_MAX] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001955 .type = HDA_FIXUP_PINS,
1956 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02001957 { 0x15, 0x01080104 }, /* side */
1958 { 0x16, 0x01011012 }, /* rear */
1959 { 0x17, 0x01016011 }, /* clfe */
1960 { }
1961 }
1962 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01001963 [ALC882_FIXUP_LENOVO_Y530] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001964 .type = HDA_FIXUP_PINS,
1965 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02001966 { 0x15, 0x99130112 }, /* rear int speakers */
1967 { 0x16, 0x99130111 }, /* subwoofer */
1968 { }
1969 }
1970 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01001971 [ALC882_FIXUP_PB_M5210] = {
Takashi Iwaifd108212013-01-10 10:18:14 +01001972 .type = HDA_FIXUP_PINCTLS,
1973 .v.pins = (const struct hda_pintbl[]) {
1974 { 0x19, PIN_VREF50 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02001975 {}
1976 }
1977 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01001978 [ALC882_FIXUP_ACER_ASPIRE_7736] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001979 .type = HDA_FIXUP_FUNC,
Takashi Iwai23d30f22012-05-07 17:17:32 +02001980 .v.func = alc_fixup_sku_ignore,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001981 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01001982 [ALC882_FIXUP_ASUS_W90V] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001983 .type = HDA_FIXUP_PINS,
1984 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai5cdf7452011-10-26 23:04:08 +02001985 { 0x16, 0x99130110 }, /* fix sequence for CLFE */
1986 { }
1987 }
1988 },
Marton Balint8f239212012-03-05 21:33:23 +01001989 [ALC889_FIXUP_CD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001990 .type = HDA_FIXUP_PINS,
1991 .v.pins = (const struct hda_pintbl[]) {
Marton Balint8f239212012-03-05 21:33:23 +01001992 { 0x1c, 0x993301f0 }, /* CD */
1993 { }
1994 }
1995 },
David Henningssonb2c53e22014-01-01 14:01:34 +01001996 [ALC889_FIXUP_FRONT_HP_NO_PRESENCE] = {
1997 .type = HDA_FIXUP_PINS,
1998 .v.pins = (const struct hda_pintbl[]) {
1999 { 0x1b, 0x02214120 }, /* Front HP jack is flaky, disable jack detect */
2000 { }
2001 },
2002 .chained = true,
2003 .chain_id = ALC889_FIXUP_CD,
2004 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002005 [ALC889_FIXUP_VAIO_TT] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002006 .type = HDA_FIXUP_PINS,
2007 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002008 { 0x17, 0x90170111 }, /* hidden surround speaker */
2009 { }
2010 }
2011 },
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01002012 [ALC888_FIXUP_EEE1601] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002013 .type = HDA_FIXUP_VERBS,
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01002014 .v.verbs = (const struct hda_verb[]) {
2015 { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
2016 { 0x20, AC_VERB_SET_PROC_COEF, 0x0838 },
2017 { }
2018 }
Takashi Iwai177943a2011-11-09 12:55:18 +01002019 },
2020 [ALC882_FIXUP_EAPD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002021 .type = HDA_FIXUP_VERBS,
Takashi Iwai177943a2011-11-09 12:55:18 +01002022 .v.verbs = (const struct hda_verb[]) {
2023 /* change to EAPD mode */
2024 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2025 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
2026 { }
2027 }
2028 },
Takashi Iwai7a6069b2011-11-09 15:22:01 +01002029 [ALC883_FIXUP_EAPD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002030 .type = HDA_FIXUP_VERBS,
Takashi Iwai7a6069b2011-11-09 15:22:01 +01002031 .v.verbs = (const struct hda_verb[]) {
2032 /* change to EAPD mode */
2033 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2034 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
2035 { }
2036 }
2037 },
Takashi Iwai8812c4f2011-11-09 17:39:15 +01002038 [ALC883_FIXUP_ACER_EAPD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002039 .type = HDA_FIXUP_VERBS,
Takashi Iwai8812c4f2011-11-09 17:39:15 +01002040 .v.verbs = (const struct hda_verb[]) {
2041 /* eanable EAPD on Acer laptops */
2042 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2043 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2044 { }
2045 }
2046 },
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002047 [ALC882_FIXUP_GPIO1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002048 .type = HDA_FIXUP_VERBS,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002049 .v.verbs = alc_gpio1_init_verbs,
2050 },
2051 [ALC882_FIXUP_GPIO2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002052 .type = HDA_FIXUP_VERBS,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002053 .v.verbs = alc_gpio2_init_verbs,
2054 },
Takashi Iwaieb844d52011-11-09 18:03:07 +01002055 [ALC882_FIXUP_GPIO3] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002056 .type = HDA_FIXUP_VERBS,
Takashi Iwaieb844d52011-11-09 18:03:07 +01002057 .v.verbs = alc_gpio3_init_verbs,
2058 },
Takashi Iwai68ef0562011-11-09 18:24:44 +01002059 [ALC882_FIXUP_ASUS_W2JC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002060 .type = HDA_FIXUP_VERBS,
Takashi Iwai68ef0562011-11-09 18:24:44 +01002061 .v.verbs = alc_gpio1_init_verbs,
2062 .chained = true,
2063 .chain_id = ALC882_FIXUP_EAPD,
2064 },
2065 [ALC889_FIXUP_COEF] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002066 .type = HDA_FIXUP_FUNC,
Takashi Iwai68ef0562011-11-09 18:24:44 +01002067 .v.func = alc889_fixup_coef,
2068 },
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002069 [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002070 .type = HDA_FIXUP_PINS,
2071 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002072 { 0x16, 0x99130111 }, /* CLFE speaker */
2073 { 0x17, 0x99130112 }, /* surround speaker */
2074 { }
Takashi Iwai038d4fe2012-04-11 17:18:12 +02002075 },
2076 .chained = true,
2077 .chain_id = ALC882_FIXUP_GPIO1,
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002078 },
2079 [ALC882_FIXUP_ACER_ASPIRE_8930G] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002080 .type = HDA_FIXUP_PINS,
2081 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002082 { 0x16, 0x99130111 }, /* CLFE speaker */
2083 { 0x1b, 0x99130112 }, /* surround speaker */
2084 { }
2085 },
2086 .chained = true,
2087 .chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS,
2088 },
2089 [ALC882_FIXUP_ASPIRE_8930G_VERBS] = {
2090 /* additional init verbs for Acer Aspire 8930G */
Takashi Iwai1727a772013-01-10 09:52:52 +01002091 .type = HDA_FIXUP_VERBS,
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002092 .v.verbs = (const struct hda_verb[]) {
2093 /* Enable all DACs */
2094 /* DAC DISABLE/MUTE 1? */
2095 /* setting bits 1-5 disables DAC nids 0x02-0x06
2096 * apparently. Init=0x38 */
2097 { 0x20, AC_VERB_SET_COEF_INDEX, 0x03 },
2098 { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
2099 /* DAC DISABLE/MUTE 2? */
2100 /* some bit here disables the other DACs.
2101 * Init=0x4900 */
2102 { 0x20, AC_VERB_SET_COEF_INDEX, 0x08 },
2103 { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
2104 /* DMIC fix
2105 * This laptop has a stereo digital microphone.
2106 * The mics are only 1cm apart which makes the stereo
2107 * useless. However, either the mic or the ALC889
2108 * makes the signal become a difference/sum signal
2109 * instead of standard stereo, which is annoying.
2110 * So instead we flip this bit which makes the
2111 * codec replicate the sum signal to both channels,
2112 * turning it into a normal mono mic.
2113 */
2114 /* DMIC_CONTROL? Init value = 0x0001 */
2115 { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
2116 { 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
2117 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2118 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2119 { }
Takashi Iwai038d4fe2012-04-11 17:18:12 +02002120 },
2121 .chained = true,
2122 .chain_id = ALC882_FIXUP_GPIO1,
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002123 },
Takashi Iwai56710872011-11-14 17:42:11 +01002124 [ALC885_FIXUP_MACPRO_GPIO] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002125 .type = HDA_FIXUP_FUNC,
Takashi Iwai56710872011-11-14 17:42:11 +01002126 .v.func = alc885_fixup_macpro_gpio,
2127 },
Takashi Iwai02a237b2012-02-13 15:25:07 +01002128 [ALC889_FIXUP_DAC_ROUTE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002129 .type = HDA_FIXUP_FUNC,
Takashi Iwai02a237b2012-02-13 15:25:07 +01002130 .v.func = alc889_fixup_dac_route,
2131 },
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002132 [ALC889_FIXUP_MBP_VREF] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002133 .type = HDA_FIXUP_FUNC,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002134 .v.func = alc889_fixup_mbp_vref,
2135 .chained = true,
2136 .chain_id = ALC882_FIXUP_GPIO1,
2137 },
2138 [ALC889_FIXUP_IMAC91_VREF] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002139 .type = HDA_FIXUP_FUNC,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002140 .v.func = alc889_fixup_imac91_vref,
2141 .chained = true,
2142 .chain_id = ALC882_FIXUP_GPIO1,
2143 },
Adrien Vergée7729a42014-01-24 14:56:14 -05002144 [ALC889_FIXUP_MBA11_VREF] = {
2145 .type = HDA_FIXUP_FUNC,
2146 .v.func = alc889_fixup_mba11_vref,
2147 .chained = true,
2148 .chain_id = ALC889_FIXUP_MBP_VREF,
2149 },
Takashi Iwai0756f092013-12-04 13:59:45 +01002150 [ALC889_FIXUP_MBA21_VREF] = {
2151 .type = HDA_FIXUP_FUNC,
2152 .v.func = alc889_fixup_mba21_vref,
2153 .chained = true,
2154 .chain_id = ALC889_FIXUP_MBP_VREF,
2155 },
Takashi Iwaic20f31e2014-02-03 11:02:10 +01002156 [ALC889_FIXUP_MP11_VREF] = {
2157 .type = HDA_FIXUP_FUNC,
2158 .v.func = alc889_fixup_mba11_vref,
2159 .chained = true,
2160 .chain_id = ALC885_FIXUP_MACPRO_GPIO,
2161 },
Mario Kleiner9f660a12015-12-22 00:45:43 +01002162 [ALC889_FIXUP_MP41_VREF] = {
2163 .type = HDA_FIXUP_FUNC,
2164 .v.func = alc889_fixup_mbp_vref,
2165 .chained = true,
2166 .chain_id = ALC885_FIXUP_MACPRO_GPIO,
2167 },
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002168 [ALC882_FIXUP_INV_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002169 .type = HDA_FIXUP_FUNC,
David Henningsson9d36a7d2014-10-07 10:18:42 +02002170 .v.func = alc_fixup_inv_dmic,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002171 },
Takashi Iwaie427c232012-07-29 10:04:08 +02002172 [ALC882_FIXUP_NO_PRIMARY_HP] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002173 .type = HDA_FIXUP_FUNC,
Takashi Iwaie427c232012-07-29 10:04:08 +02002174 .v.func = alc882_fixup_no_primary_hp,
2175 },
Takashi Iwai1f0bbf02013-11-28 15:21:21 +01002176 [ALC887_FIXUP_ASUS_BASS] = {
2177 .type = HDA_FIXUP_PINS,
2178 .v.pins = (const struct hda_pintbl[]) {
2179 {0x16, 0x99130130}, /* bass speaker */
2180 {}
2181 },
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01002182 .chained = true,
2183 .chain_id = ALC887_FIXUP_BASS_CHMAP,
2184 },
2185 [ALC887_FIXUP_BASS_CHMAP] = {
2186 .type = HDA_FIXUP_FUNC,
2187 .v.func = alc_fixup_bass_chmap,
Takashi Iwai1f0bbf02013-11-28 15:21:21 +01002188 },
Takashi Iwai0c25ad82015-11-24 20:02:12 +01002189 [ALC882_FIXUP_DISABLE_AAMIX] = {
2190 .type = HDA_FIXUP_FUNC,
2191 .v.func = alc_fixup_disable_aamix,
2192 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02002193};
2194
2195static const struct snd_pci_quirk alc882_fixup_tbl[] = {
Takashi Iwai8812c4f2011-11-09 17:39:15 +01002196 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
2197 SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
Takashi Iwaib5d724b2015-06-02 19:57:08 +02002198 SND_PCI_QUIRK(0x1025, 0x0107, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
Takashi Iwai8812c4f2011-11-09 17:39:15 +01002199 SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD),
2200 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
2201 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD),
2202 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_FIXUP_ACER_EAPD),
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002203 SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
2204 ALC882_FIXUP_ACER_ASPIRE_4930G),
2205 SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
2206 ALC882_FIXUP_ACER_ASPIRE_4930G),
2207 SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
2208 ALC882_FIXUP_ACER_ASPIRE_8930G),
2209 SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
2210 ALC882_FIXUP_ACER_ASPIRE_8930G),
2211 SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
2212 ALC882_FIXUP_ACER_ASPIRE_4930G),
2213 SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
2214 ALC882_FIXUP_ACER_ASPIRE_4930G),
2215 SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
2216 ALC882_FIXUP_ACER_ASPIRE_4930G),
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002217 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
Takashi Iwaif5c53d82012-05-07 10:07:33 +02002218 SND_PCI_QUIRK(0x1025, 0x021e, "Acer Aspire 5739G",
2219 ALC882_FIXUP_ACER_ASPIRE_4930G),
Takashi Iwai02a237b2012-02-13 15:25:07 +01002220 SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
Takashi Iwaife97da12012-04-12 08:00:19 +02002221 SND_PCI_QUIRK(0x1025, 0x026b, "Acer Aspire 8940G", ALC882_FIXUP_ACER_ASPIRE_8930G),
Takashi Iwaiac9b1cd2011-11-09 17:45:55 +01002222 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
Takashi Iwai177943a2011-11-09 12:55:18 +01002223 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002224 SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
Takashi Iwai68ef0562011-11-09 18:24:44 +01002225 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01002226 SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
Takashi Iwai1f0bbf02013-11-28 15:21:21 +01002227 SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
Takashi Iwaiac9b1cd2011-11-09 17:45:55 +01002228 SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
Takashi Iwaie427c232012-07-29 10:04:08 +02002229 SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
Fernando Luis Vázquez Cao12e31a72013-02-12 16:47:44 +09002230 SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
Takashi Iwai56710872011-11-14 17:42:11 +01002231
2232 /* All Apple entries are in codec SSIDs */
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002233 SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
2234 SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
2235 SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
Takashi Iwaic20f31e2014-02-03 11:02:10 +01002236 SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC889_FIXUP_MP11_VREF),
Takashi Iwai56710872011-11-14 17:42:11 +01002237 SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
2238 SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002239 SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
2240 SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
Takashi Iwai56710872011-11-14 17:42:11 +01002241 SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
Adrien Vergée7729a42014-01-24 14:56:14 -05002242 SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBA11_VREF),
Takashi Iwai0756f092013-12-04 13:59:45 +01002243 SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF),
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002244 SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
2245 SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
Takashi Iwai56710872011-11-14 17:42:11 +01002246 SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002247 SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
2248 SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
2249 SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
Mario Kleiner9f660a12015-12-22 00:45:43 +01002250 SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 4,1/5,1", ALC889_FIXUP_MP41_VREF),
Takashi Iwai05193632012-11-12 10:07:36 +01002251 SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002252 SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
2253 SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
Takashi Iwai649ccd02015-07-30 22:30:29 +02002254 SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
Takashi Iwai56710872011-11-14 17:42:11 +01002255
Takashi Iwai7a6069b2011-11-09 15:22:01 +01002256 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
Takashi Iwaibca40132012-05-07 11:13:14 +02002257 SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
Takashi Iwaieb844d52011-11-09 18:03:07 +01002258 SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
David Henningssonb2c53e22014-01-01 14:01:34 +01002259 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
Takashi Iwai0c25ad82015-11-24 20:02:12 +01002260 SND_PCI_QUIRK(0x1458, 0xa182, "Gigabyte Z170X-UD3", ALC882_FIXUP_DISABLE_AAMIX),
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002261 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
Takashi Iwai7a6069b2011-11-09 15:22:01 +01002262 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
2263 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
Takashi Iwaiac9b1cd2011-11-09 17:45:55 +01002264 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
Takashi Iwai68ef0562011-11-09 18:24:44 +01002265 SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_FIXUP_COEF),
Takashi Iwai1d045db2011-07-07 18:23:21 +02002266 {}
2267};
2268
Takashi Iwai1727a772013-01-10 09:52:52 +01002269static const struct hda_model_fixup alc882_fixup_models[] = {
Takashi Iwai912093b2012-04-11 14:03:41 +02002270 {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"},
2271 {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"},
2272 {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"},
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002273 {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"},
Takashi Iwaie427c232012-07-29 10:04:08 +02002274 {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"},
Takashi Iwai912093b2012-04-11 14:03:41 +02002275 {}
2276};
2277
Takashi Iwai1d045db2011-07-07 18:23:21 +02002278/*
2279 * BIOS auto configuration
2280 */
2281/* almost identical with ALC880 parser... */
2282static int alc882_parse_auto_config(struct hda_codec *codec)
2283{
Takashi Iwai1d045db2011-07-07 18:23:21 +02002284 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002285 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2286 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002287}
2288
Takashi Iwai1d045db2011-07-07 18:23:21 +02002289/*
2290 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002291static int patch_alc882(struct hda_codec *codec)
2292{
2293 struct alc_spec *spec;
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002294 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002295
Takashi Iwai3de95172012-05-07 18:03:15 +02002296 err = alc_alloc_spec(codec, 0x0b);
2297 if (err < 0)
2298 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002299
Takashi Iwai3de95172012-05-07 18:03:15 +02002300 spec = codec->spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002301
Takashi Iwai7639a062015-03-03 10:07:24 +01002302 switch (codec->core.vendor_id) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002303 case 0x10ec0882:
2304 case 0x10ec0885:
Takashi Iwaiacf08082014-09-02 07:21:56 +02002305 case 0x10ec0900:
Takashi Iwai1d045db2011-07-07 18:23:21 +02002306 break;
2307 default:
2308 /* ALC883 and variants */
2309 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
2310 break;
2311 }
2312
Takashi Iwai1727a772013-01-10 09:52:52 +01002313 snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
Takashi Iwai912093b2012-04-11 14:03:41 +02002314 alc882_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01002315 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002316
2317 alc_auto_parse_customize_define(codec);
2318
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002319 if (has_cdefine_beep(codec))
2320 spec->gen.beep_nid = 0x01;
2321
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002322 /* automatic parse from the BIOS config */
2323 err = alc882_parse_auto_config(codec);
2324 if (err < 0)
2325 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002326
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002327 if (!spec->gen.no_analog && spec->gen.beep_nid)
Takashi Iwai1d045db2011-07-07 18:23:21 +02002328 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
2329
Takashi Iwai1727a772013-01-10 09:52:52 +01002330 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01002331
Takashi Iwai1d045db2011-07-07 18:23:21 +02002332 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002333
2334 error:
2335 alc_free(codec);
2336 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002337}
2338
2339
2340/*
2341 * ALC262 support
2342 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002343static int alc262_parse_auto_config(struct hda_codec *codec)
2344{
Takashi Iwai1d045db2011-07-07 18:23:21 +02002345 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002346 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2347 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002348}
2349
2350/*
2351 * Pin config fixes
2352 */
2353enum {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002354 ALC262_FIXUP_FSC_H270,
Takashi Iwai7513e6d2013-01-18 15:41:34 +01002355 ALC262_FIXUP_FSC_S7110,
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002356 ALC262_FIXUP_HP_Z200,
2357 ALC262_FIXUP_TYAN,
Takashi Iwaic4701502011-11-07 14:20:07 +01002358 ALC262_FIXUP_LENOVO_3000,
Takashi Iwaib42590b2011-11-07 14:41:01 +01002359 ALC262_FIXUP_BENQ,
2360 ALC262_FIXUP_BENQ_T31,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002361 ALC262_FIXUP_INV_DMIC,
Mengdong Linb5c66112013-11-29 00:35:35 -05002362 ALC262_FIXUP_INTEL_BAYLEYBAY,
Takashi Iwai1d045db2011-07-07 18:23:21 +02002363};
2364
Takashi Iwai1727a772013-01-10 09:52:52 +01002365static const struct hda_fixup alc262_fixups[] = {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002366 [ALC262_FIXUP_FSC_H270] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002367 .type = HDA_FIXUP_PINS,
2368 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002369 { 0x14, 0x99130110 }, /* speaker */
2370 { 0x15, 0x0221142f }, /* front HP */
2371 { 0x1b, 0x0121141f }, /* rear HP */
2372 { }
2373 }
2374 },
Takashi Iwai7513e6d2013-01-18 15:41:34 +01002375 [ALC262_FIXUP_FSC_S7110] = {
2376 .type = HDA_FIXUP_PINS,
2377 .v.pins = (const struct hda_pintbl[]) {
2378 { 0x15, 0x90170110 }, /* speaker */
2379 { }
2380 },
2381 .chained = true,
2382 .chain_id = ALC262_FIXUP_BENQ,
2383 },
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002384 [ALC262_FIXUP_HP_Z200] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002385 .type = HDA_FIXUP_PINS,
2386 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002387 { 0x16, 0x99130120 }, /* internal speaker */
2388 { }
2389 }
2390 },
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002391 [ALC262_FIXUP_TYAN] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002392 .type = HDA_FIXUP_PINS,
2393 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002394 { 0x14, 0x1993e1f0 }, /* int AUX */
2395 { }
2396 }
2397 },
Takashi Iwaic4701502011-11-07 14:20:07 +01002398 [ALC262_FIXUP_LENOVO_3000] = {
Takashi Iwaifd108212013-01-10 10:18:14 +01002399 .type = HDA_FIXUP_PINCTLS,
2400 .v.pins = (const struct hda_pintbl[]) {
2401 { 0x19, PIN_VREF50 },
Takashi Iwaib42590b2011-11-07 14:41:01 +01002402 {}
2403 },
2404 .chained = true,
2405 .chain_id = ALC262_FIXUP_BENQ,
2406 },
2407 [ALC262_FIXUP_BENQ] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002408 .type = HDA_FIXUP_VERBS,
Takashi Iwaib42590b2011-11-07 14:41:01 +01002409 .v.verbs = (const struct hda_verb[]) {
Takashi Iwaic4701502011-11-07 14:20:07 +01002410 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2411 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
2412 {}
2413 }
2414 },
Takashi Iwaib42590b2011-11-07 14:41:01 +01002415 [ALC262_FIXUP_BENQ_T31] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002416 .type = HDA_FIXUP_VERBS,
Takashi Iwaib42590b2011-11-07 14:41:01 +01002417 .v.verbs = (const struct hda_verb[]) {
2418 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2419 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2420 {}
2421 }
2422 },
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002423 [ALC262_FIXUP_INV_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002424 .type = HDA_FIXUP_FUNC,
David Henningsson9d36a7d2014-10-07 10:18:42 +02002425 .v.func = alc_fixup_inv_dmic,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002426 },
Mengdong Linb5c66112013-11-29 00:35:35 -05002427 [ALC262_FIXUP_INTEL_BAYLEYBAY] = {
2428 .type = HDA_FIXUP_FUNC,
2429 .v.func = alc_fixup_no_depop_delay,
2430 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02002431};
2432
2433static const struct snd_pci_quirk alc262_fixup_tbl[] = {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002434 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
Takashi Iwai7513e6d2013-01-18 15:41:34 +01002435 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110),
Takashi Iwai3dcd3be2011-11-07 14:59:40 +01002436 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002437 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
2438 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
Takashi Iwaic4701502011-11-07 14:20:07 +01002439 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
Takashi Iwaib42590b2011-11-07 14:41:01 +01002440 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
2441 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
Mengdong Linb5c66112013-11-29 00:35:35 -05002442 SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY),
Takashi Iwai1d045db2011-07-07 18:23:21 +02002443 {}
2444};
2445
Takashi Iwai1727a772013-01-10 09:52:52 +01002446static const struct hda_model_fixup alc262_fixup_models[] = {
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002447 {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"},
2448 {}
2449};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002450
Takashi Iwai1d045db2011-07-07 18:23:21 +02002451/*
2452 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002453static int patch_alc262(struct hda_codec *codec)
2454{
2455 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002456 int err;
2457
Takashi Iwai3de95172012-05-07 18:03:15 +02002458 err = alc_alloc_spec(codec, 0x0b);
2459 if (err < 0)
2460 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002461
Takashi Iwai3de95172012-05-07 18:03:15 +02002462 spec = codec->spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +01002463 spec->gen.shared_mic_vref_pin = 0x18;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002464
Takashi Iwai225068a2015-05-29 10:42:14 +02002465 spec->shutup = alc_eapd_shutup;
2466
Takashi Iwai1d045db2011-07-07 18:23:21 +02002467#if 0
2468 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
2469 * under-run
2470 */
Takashi Iwai98b24882014-08-18 13:47:50 +02002471 alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x80);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002472#endif
Takashi Iwai1d045db2011-07-07 18:23:21 +02002473 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
2474
Takashi Iwai1727a772013-01-10 09:52:52 +01002475 snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002476 alc262_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01002477 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002478
Takashi Iwaiaf741c12012-05-07 18:09:48 +02002479 alc_auto_parse_customize_define(codec);
2480
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002481 if (has_cdefine_beep(codec))
2482 spec->gen.beep_nid = 0x01;
2483
Takashi Iwai42399f72011-11-07 17:18:44 +01002484 /* automatic parse from the BIOS config */
2485 err = alc262_parse_auto_config(codec);
2486 if (err < 0)
2487 goto error;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002488
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002489 if (!spec->gen.no_analog && spec->gen.beep_nid)
Takashi Iwai1d045db2011-07-07 18:23:21 +02002490 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
2491
Takashi Iwai1727a772013-01-10 09:52:52 +01002492 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01002493
Takashi Iwai1d045db2011-07-07 18:23:21 +02002494 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002495
2496 error:
2497 alc_free(codec);
2498 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002499}
2500
2501/*
2502 * ALC268
2503 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002504/* bind Beep switches of both NID 0x0f and 0x10 */
2505static const struct hda_bind_ctls alc268_bind_beep_sw = {
2506 .ops = &snd_hda_bind_sw,
2507 .values = {
2508 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
2509 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
2510 0
2511 },
2512};
2513
2514static const struct snd_kcontrol_new alc268_beep_mixer[] = {
2515 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
2516 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
2517 { }
2518};
2519
2520/* set PCBEEP vol = 0, mute connections */
2521static const struct hda_verb alc268_beep_init_verbs[] = {
2522 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2523 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2524 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2525 { }
2526};
2527
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002528enum {
2529 ALC268_FIXUP_INV_DMIC,
Takashi Iwaicb766402012-10-20 10:55:21 +02002530 ALC268_FIXUP_HP_EAPD,
Takashi Iwai24eff322013-11-04 18:21:08 +01002531 ALC268_FIXUP_SPDIF,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002532};
2533
Takashi Iwai1727a772013-01-10 09:52:52 +01002534static const struct hda_fixup alc268_fixups[] = {
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002535 [ALC268_FIXUP_INV_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002536 .type = HDA_FIXUP_FUNC,
David Henningsson9d36a7d2014-10-07 10:18:42 +02002537 .v.func = alc_fixup_inv_dmic,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002538 },
Takashi Iwaicb766402012-10-20 10:55:21 +02002539 [ALC268_FIXUP_HP_EAPD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002540 .type = HDA_FIXUP_VERBS,
Takashi Iwaicb766402012-10-20 10:55:21 +02002541 .v.verbs = (const struct hda_verb[]) {
2542 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
2543 {}
2544 }
2545 },
Takashi Iwai24eff322013-11-04 18:21:08 +01002546 [ALC268_FIXUP_SPDIF] = {
2547 .type = HDA_FIXUP_PINS,
2548 .v.pins = (const struct hda_pintbl[]) {
2549 { 0x1e, 0x014b1180 }, /* enable SPDIF out */
2550 {}
2551 }
2552 },
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002553};
2554
Takashi Iwai1727a772013-01-10 09:52:52 +01002555static const struct hda_model_fixup alc268_fixup_models[] = {
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002556 {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
Takashi Iwaicb766402012-10-20 10:55:21 +02002557 {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
2558 {}
2559};
2560
2561static const struct snd_pci_quirk alc268_fixup_tbl[] = {
Takashi Iwai24eff322013-11-04 18:21:08 +01002562 SND_PCI_QUIRK(0x1025, 0x0139, "Acer TravelMate 6293", ALC268_FIXUP_SPDIF),
David Henningssonfcd8f3b2013-01-28 05:45:47 +01002563 SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
Takashi Iwaicb766402012-10-20 10:55:21 +02002564 /* below is codec SSID since multiple Toshiba laptops have the
2565 * same PCI SSID 1179:ff00
2566 */
2567 SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002568 {}
2569};
2570
Takashi Iwai1d045db2011-07-07 18:23:21 +02002571/*
2572 * BIOS auto configuration
2573 */
2574static int alc268_parse_auto_config(struct hda_codec *codec)
2575{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002576 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002577 return alc_parse_auto_config(codec, NULL, alc268_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002578}
2579
Takashi Iwai1d045db2011-07-07 18:23:21 +02002580/*
2581 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002582static int patch_alc268(struct hda_codec *codec)
2583{
2584 struct alc_spec *spec;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002585 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002586
Takashi Iwai1d045db2011-07-07 18:23:21 +02002587 /* ALC268 has no aa-loopback mixer */
Takashi Iwai3de95172012-05-07 18:03:15 +02002588 err = alc_alloc_spec(codec, 0);
2589 if (err < 0)
2590 return err;
2591
2592 spec = codec->spec;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002593 spec->gen.beep_nid = 0x01;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002594
Takashi Iwai225068a2015-05-29 10:42:14 +02002595 spec->shutup = alc_eapd_shutup;
2596
Takashi Iwai1727a772013-01-10 09:52:52 +01002597 snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
2598 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002599
Takashi Iwai6ebb8052011-08-16 15:15:40 +02002600 /* automatic parse from the BIOS config */
2601 err = alc268_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002602 if (err < 0)
2603 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002604
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002605 if (err > 0 && !spec->gen.no_analog &&
2606 spec->gen.autocfg.speaker_pins[0] != 0x1d) {
2607 add_mixer(spec, alc268_beep_mixer);
2608 snd_hda_add_verbs(codec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002609 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
2610 /* override the amp caps for beep generator */
2611 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
2612 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
2613 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
2614 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2615 (0 << AC_AMPCAP_MUTE_SHIFT));
2616 }
2617
Takashi Iwai1727a772013-01-10 09:52:52 +01002618 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002619
Takashi Iwai1d045db2011-07-07 18:23:21 +02002620 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002621
2622 error:
2623 alc_free(codec);
2624 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002625}
2626
2627/*
2628 * ALC269
2629 */
Takashi Iwai08c189f2012-12-19 15:22:24 +01002630
Takashi Iwai1d045db2011-07-07 18:23:21 +02002631static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002632 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002633};
2634
2635static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002636 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002637};
2638
Takashi Iwai1d045db2011-07-07 18:23:21 +02002639/* different alc269-variants */
2640enum {
2641 ALC269_TYPE_ALC269VA,
2642 ALC269_TYPE_ALC269VB,
2643 ALC269_TYPE_ALC269VC,
Kailang Yangadcc70b2012-05-25 08:08:38 +02002644 ALC269_TYPE_ALC269VD,
Kailang Yang065380f2013-01-10 10:25:48 +01002645 ALC269_TYPE_ALC280,
2646 ALC269_TYPE_ALC282,
Kailang Yang2af02be2013-08-22 10:03:50 +02002647 ALC269_TYPE_ALC283,
Kailang Yang065380f2013-01-10 10:25:48 +01002648 ALC269_TYPE_ALC284,
Kailang Yang161ebf22013-10-24 11:36:33 +02002649 ALC269_TYPE_ALC285,
Kailang Yang7fc7d042013-04-25 11:04:43 +02002650 ALC269_TYPE_ALC286,
Kailang Yang506b62c2014-12-18 17:07:44 +08002651 ALC269_TYPE_ALC298,
Kailang Yang1d04c9d2013-10-24 11:35:18 +02002652 ALC269_TYPE_ALC255,
Kailang Yang4344aec2014-12-17 17:39:05 +08002653 ALC269_TYPE_ALC256,
Takashi Iwai1d045db2011-07-07 18:23:21 +02002654};
2655
2656/*
2657 * BIOS auto configuration
2658 */
2659static int alc269_parse_auto_config(struct hda_codec *codec)
2660{
Takashi Iwai1d045db2011-07-07 18:23:21 +02002661 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002662 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
2663 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2664 struct alc_spec *spec = codec->spec;
Kailang Yangadcc70b2012-05-25 08:08:38 +02002665 const hda_nid_t *ssids;
2666
2667 switch (spec->codec_variant) {
2668 case ALC269_TYPE_ALC269VA:
2669 case ALC269_TYPE_ALC269VC:
Kailang Yang065380f2013-01-10 10:25:48 +01002670 case ALC269_TYPE_ALC280:
2671 case ALC269_TYPE_ALC284:
Kailang Yang161ebf22013-10-24 11:36:33 +02002672 case ALC269_TYPE_ALC285:
Kailang Yangadcc70b2012-05-25 08:08:38 +02002673 ssids = alc269va_ssids;
2674 break;
2675 case ALC269_TYPE_ALC269VB:
2676 case ALC269_TYPE_ALC269VD:
Kailang Yang065380f2013-01-10 10:25:48 +01002677 case ALC269_TYPE_ALC282:
Kailang Yang2af02be2013-08-22 10:03:50 +02002678 case ALC269_TYPE_ALC283:
Kailang Yang7fc7d042013-04-25 11:04:43 +02002679 case ALC269_TYPE_ALC286:
Kailang Yang506b62c2014-12-18 17:07:44 +08002680 case ALC269_TYPE_ALC298:
Kailang Yang1d04c9d2013-10-24 11:35:18 +02002681 case ALC269_TYPE_ALC255:
Kailang Yang4344aec2014-12-17 17:39:05 +08002682 case ALC269_TYPE_ALC256:
Kailang Yangadcc70b2012-05-25 08:08:38 +02002683 ssids = alc269_ssids;
2684 break;
2685 default:
2686 ssids = alc269_ssids;
2687 break;
2688 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02002689
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002690 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002691}
2692
Kailang Yangf7ae9ba2014-06-30 16:10:37 +08002693static int find_ext_mic_pin(struct hda_codec *codec);
2694
2695static void alc286_shutup(struct hda_codec *codec)
2696{
2697 int i;
2698 int mic_pin = find_ext_mic_pin(codec);
2699 /* don't shut up pins when unloading the driver; otherwise it breaks
2700 * the default pin setup at the next load of the driver
2701 */
2702 if (codec->bus->shutdown)
2703 return;
2704 for (i = 0; i < codec->init_pins.used; i++) {
2705 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
2706 /* use read here for syncing after issuing each verb */
2707 if (pin->nid != mic_pin)
2708 snd_hda_codec_read(codec, pin->nid, 0,
2709 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
2710 }
2711 codec->pins_shutup = 1;
2712}
2713
Kailang Yang1387e2d2012-11-08 10:23:18 +01002714static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
Takashi Iwai1d045db2011-07-07 18:23:21 +02002715{
Takashi Iwai98b24882014-08-18 13:47:50 +02002716 alc_update_coef_idx(codec, 0x04, 1 << 11, power_up ? (1 << 11) : 0);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002717}
2718
2719static void alc269_shutup(struct hda_codec *codec)
2720{
Kailang Yangadcc70b2012-05-25 08:08:38 +02002721 struct alc_spec *spec = codec->spec;
2722
Kailang Yang1387e2d2012-11-08 10:23:18 +01002723 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
2724 alc269vb_toggle_power_output(codec, 0);
2725 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
2726 (alc_get_coef0(codec) & 0x00ff) == 0x018) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002727 msleep(150);
2728 }
Takashi Iwai9bfb2842013-07-24 14:31:50 +02002729 snd_hda_shutup_pins(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002730}
2731
Takashi Iwai54db6c32014-08-18 15:11:19 +02002732static struct coef_fw alc282_coefs[] = {
2733 WRITE_COEF(0x03, 0x0002), /* Power Down Control */
Kailang Yang32fa7e42014-10-24 16:26:01 +08002734 UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
Takashi Iwai54db6c32014-08-18 15:11:19 +02002735 WRITE_COEF(0x07, 0x0200), /* DMIC control */
2736 UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
2737 UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
2738 WRITE_COEF(0x0a, 0xcccc), /* JD offset1 */
2739 WRITE_COEF(0x0b, 0xcccc), /* JD offset2 */
2740 WRITE_COEF(0x0e, 0x6e00), /* LDO1/2/3, DAC/ADC */
2741 UPDATE_COEF(0x0f, 0xf800, 0x1000), /* JD */
2742 UPDATE_COEF(0x10, 0xfc00, 0x0c00), /* Capless */
2743 WRITE_COEF(0x6f, 0x0), /* Class D test 4 */
2744 UPDATE_COEF(0x0c, 0xfe00, 0), /* IO power down directly */
2745 WRITE_COEF(0x34, 0xa0c0), /* ANC */
2746 UPDATE_COEF(0x16, 0x0008, 0), /* AGC MUX */
2747 UPDATE_COEF(0x1d, 0x00e0, 0), /* DAC simple content protection */
2748 UPDATE_COEF(0x1f, 0x00e0, 0), /* ADC simple content protection */
2749 WRITE_COEF(0x21, 0x8804), /* DAC ADC Zero Detection */
2750 WRITE_COEF(0x63, 0x2902), /* PLL */
2751 WRITE_COEF(0x68, 0xa080), /* capless control 2 */
2752 WRITE_COEF(0x69, 0x3400), /* capless control 3 */
2753 WRITE_COEF(0x6a, 0x2f3e), /* capless control 4 */
2754 WRITE_COEF(0x6b, 0x0), /* capless control 5 */
2755 UPDATE_COEF(0x6d, 0x0fff, 0x0900), /* class D test 2 */
2756 WRITE_COEF(0x6e, 0x110a), /* class D test 3 */
2757 UPDATE_COEF(0x70, 0x00f8, 0x00d8), /* class D test 5 */
2758 WRITE_COEF(0x71, 0x0014), /* class D test 6 */
2759 WRITE_COEF(0x72, 0xc2ba), /* classD OCP */
2760 UPDATE_COEF(0x77, 0x0f80, 0), /* classD pure DC test */
2761 WRITE_COEF(0x6c, 0xfc06), /* Class D amp control */
2762 {}
2763};
2764
Kailang Yangcb149cb2014-03-18 16:45:32 +08002765static void alc282_restore_default_value(struct hda_codec *codec)
2766{
Takashi Iwai54db6c32014-08-18 15:11:19 +02002767 alc_process_coef_fw(codec, alc282_coefs);
Kailang Yangcb149cb2014-03-18 16:45:32 +08002768}
2769
Kailang Yang7b5c7a02014-03-18 16:15:54 +08002770static void alc282_init(struct hda_codec *codec)
2771{
2772 struct alc_spec *spec = codec->spec;
2773 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
2774 bool hp_pin_sense;
2775 int coef78;
2776
Kailang Yangcb149cb2014-03-18 16:45:32 +08002777 alc282_restore_default_value(codec);
2778
Kailang Yang7b5c7a02014-03-18 16:15:54 +08002779 if (!hp_pin)
2780 return;
2781 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
2782 coef78 = alc_read_coef_idx(codec, 0x78);
2783
2784 /* Index 0x78 Direct Drive HP AMP LPM Control 1 */
2785 /* Headphone capless set to high power mode */
2786 alc_write_coef_idx(codec, 0x78, 0x9004);
2787
2788 if (hp_pin_sense)
2789 msleep(2);
2790
2791 snd_hda_codec_write(codec, hp_pin, 0,
2792 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
2793
2794 if (hp_pin_sense)
2795 msleep(85);
2796
2797 snd_hda_codec_write(codec, hp_pin, 0,
2798 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
2799
2800 if (hp_pin_sense)
2801 msleep(100);
2802
2803 /* Headphone capless set to normal mode */
2804 alc_write_coef_idx(codec, 0x78, coef78);
2805}
2806
2807static void alc282_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 coef78;
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 coef78 = alc_read_coef_idx(codec, 0x78);
2821 alc_write_coef_idx(codec, 0x78, 0x9004);
2822
2823 if (hp_pin_sense)
2824 msleep(2);
2825
2826 snd_hda_codec_write(codec, hp_pin, 0,
2827 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
2828
2829 if (hp_pin_sense)
2830 msleep(85);
2831
2832 snd_hda_codec_write(codec, hp_pin, 0,
2833 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
2834
2835 if (hp_pin_sense)
2836 msleep(100);
2837
2838 alc_auto_setup_eapd(codec, false);
2839 snd_hda_shutup_pins(codec);
2840 alc_write_coef_idx(codec, 0x78, coef78);
2841}
2842
Takashi Iwai54db6c32014-08-18 15:11:19 +02002843static struct coef_fw alc283_coefs[] = {
2844 WRITE_COEF(0x03, 0x0002), /* Power Down Control */
Kailang Yang56779862014-10-24 16:17:51 +08002845 UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
Takashi Iwai54db6c32014-08-18 15:11:19 +02002846 WRITE_COEF(0x07, 0x0200), /* DMIC control */
2847 UPDATE_COEF(0x06, 0x00f0, 0), /* Analog clock */
2848 UPDATE_COEF(0x08, 0xfffc, 0x0c2c), /* JD */
2849 WRITE_COEF(0x0a, 0xcccc), /* JD offset1 */
2850 WRITE_COEF(0x0b, 0xcccc), /* JD offset2 */
2851 WRITE_COEF(0x0e, 0x6fc0), /* LDO1/2/3, DAC/ADC */
2852 UPDATE_COEF(0x0f, 0xf800, 0x1000), /* JD */
2853 UPDATE_COEF(0x10, 0xfc00, 0x0c00), /* Capless */
2854 WRITE_COEF(0x3a, 0x0), /* Class D test 4 */
2855 UPDATE_COEF(0x0c, 0xfe00, 0x0), /* IO power down directly */
2856 WRITE_COEF(0x22, 0xa0c0), /* ANC */
2857 UPDATE_COEFEX(0x53, 0x01, 0x000f, 0x0008), /* AGC MUX */
2858 UPDATE_COEF(0x1d, 0x00e0, 0), /* DAC simple content protection */
2859 UPDATE_COEF(0x1f, 0x00e0, 0), /* ADC simple content protection */
2860 WRITE_COEF(0x21, 0x8804), /* DAC ADC Zero Detection */
2861 WRITE_COEF(0x2e, 0x2902), /* PLL */
2862 WRITE_COEF(0x33, 0xa080), /* capless control 2 */
2863 WRITE_COEF(0x34, 0x3400), /* capless control 3 */
2864 WRITE_COEF(0x35, 0x2f3e), /* capless control 4 */
2865 WRITE_COEF(0x36, 0x0), /* capless control 5 */
2866 UPDATE_COEF(0x38, 0x0fff, 0x0900), /* class D test 2 */
2867 WRITE_COEF(0x39, 0x110a), /* class D test 3 */
2868 UPDATE_COEF(0x3b, 0x00f8, 0x00d8), /* class D test 5 */
2869 WRITE_COEF(0x3c, 0x0014), /* class D test 6 */
2870 WRITE_COEF(0x3d, 0xc2ba), /* classD OCP */
2871 UPDATE_COEF(0x42, 0x0f80, 0x0), /* classD pure DC test */
2872 WRITE_COEF(0x49, 0x0), /* test mode */
2873 UPDATE_COEF(0x40, 0xf800, 0x9800), /* Class D DC enable */
2874 UPDATE_COEF(0x42, 0xf000, 0x2000), /* DC offset */
2875 WRITE_COEF(0x37, 0xfc06), /* Class D amp control */
Kailang Yang56779862014-10-24 16:17:51 +08002876 UPDATE_COEF(0x1b, 0x8000, 0), /* HP JD control */
Takashi Iwai54db6c32014-08-18 15:11:19 +02002877 {}
2878};
2879
Kailang Yang6bd55b02014-03-17 13:51:27 +08002880static void alc283_restore_default_value(struct hda_codec *codec)
2881{
Takashi Iwai54db6c32014-08-18 15:11:19 +02002882 alc_process_coef_fw(codec, alc283_coefs);
Kailang Yang6bd55b02014-03-17 13:51:27 +08002883}
2884
Kailang Yang2af02be2013-08-22 10:03:50 +02002885static void alc283_init(struct hda_codec *codec)
2886{
2887 struct alc_spec *spec = codec->spec;
2888 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
2889 bool hp_pin_sense;
Kailang Yang2af02be2013-08-22 10:03:50 +02002890
Kailang Yang8314f222014-04-03 17:28:39 +08002891 if (!spec->gen.autocfg.hp_outs) {
2892 if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
2893 hp_pin = spec->gen.autocfg.line_out_pins[0];
2894 }
2895
Kailang Yang6bd55b02014-03-17 13:51:27 +08002896 alc283_restore_default_value(codec);
2897
Kailang Yang2af02be2013-08-22 10:03:50 +02002898 if (!hp_pin)
2899 return;
Kailang Yanga59d7192015-04-08 16:34:00 +08002900
2901 msleep(30);
Kailang Yang2af02be2013-08-22 10:03:50 +02002902 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
2903
2904 /* Index 0x43 Direct Drive HP AMP LPM Control 1 */
2905 /* Headphone capless set to high power mode */
2906 alc_write_coef_idx(codec, 0x43, 0x9004);
2907
2908 snd_hda_codec_write(codec, hp_pin, 0,
2909 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
2910
2911 if (hp_pin_sense)
2912 msleep(85);
2913
2914 snd_hda_codec_write(codec, hp_pin, 0,
2915 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
2916
2917 if (hp_pin_sense)
2918 msleep(85);
2919 /* Index 0x46 Combo jack auto switch control 2 */
2920 /* 3k pull low control for Headset jack. */
Takashi Iwai98b24882014-08-18 13:47:50 +02002921 alc_update_coef_idx(codec, 0x46, 3 << 12, 0);
Kailang Yang2af02be2013-08-22 10:03:50 +02002922 /* Headphone capless set to normal mode */
2923 alc_write_coef_idx(codec, 0x43, 0x9614);
2924}
2925
2926static void alc283_shutup(struct hda_codec *codec)
2927{
2928 struct alc_spec *spec = codec->spec;
2929 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
2930 bool hp_pin_sense;
Kailang Yang2af02be2013-08-22 10:03:50 +02002931
Kailang Yang8314f222014-04-03 17:28:39 +08002932 if (!spec->gen.autocfg.hp_outs) {
2933 if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
2934 hp_pin = spec->gen.autocfg.line_out_pins[0];
2935 }
2936
Kailang Yang2af02be2013-08-22 10:03:50 +02002937 if (!hp_pin) {
2938 alc269_shutup(codec);
2939 return;
2940 }
2941
2942 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
2943
2944 alc_write_coef_idx(codec, 0x43, 0x9004);
2945
Harsha Priyab450b172014-10-09 11:04:56 +00002946 /*depop hp during suspend*/
2947 alc_write_coef_idx(codec, 0x06, 0x2100);
2948
Kailang Yang2af02be2013-08-22 10:03:50 +02002949 snd_hda_codec_write(codec, hp_pin, 0,
2950 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
2951
2952 if (hp_pin_sense)
Kailang Yang88011c092013-10-24 15:45:24 +02002953 msleep(100);
Kailang Yang2af02be2013-08-22 10:03:50 +02002954
2955 snd_hda_codec_write(codec, hp_pin, 0,
2956 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
2957
Takashi Iwai98b24882014-08-18 13:47:50 +02002958 alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
Kailang Yang2af02be2013-08-22 10:03:50 +02002959
2960 if (hp_pin_sense)
Kailang Yang88011c092013-10-24 15:45:24 +02002961 msleep(100);
Kailang Yang0435b3f2014-04-08 17:14:14 +08002962 alc_auto_setup_eapd(codec, false);
Kailang Yang2af02be2013-08-22 10:03:50 +02002963 snd_hda_shutup_pins(codec);
2964 alc_write_coef_idx(codec, 0x43, 0x9614);
2965}
2966
Kailang Yangad60d502013-06-28 12:03:01 +02002967static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
2968 unsigned int val)
2969{
2970 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
2971 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val & 0xffff); /* LSB */
2972 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val >> 16); /* MSB */
2973}
2974
2975static int alc5505_coef_get(struct hda_codec *codec, unsigned int index_reg)
2976{
2977 unsigned int val;
2978
2979 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
2980 val = snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
2981 & 0xffff;
2982 val |= snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
2983 << 16;
2984 return val;
2985}
2986
2987static void alc5505_dsp_halt(struct hda_codec *codec)
2988{
2989 unsigned int val;
2990
2991 alc5505_coef_set(codec, 0x3000, 0x000c); /* DSP CPU stop */
2992 alc5505_coef_set(codec, 0x880c, 0x0008); /* DDR enter self refresh */
2993 alc5505_coef_set(codec, 0x61c0, 0x11110080); /* Clock control for PLL and CPU */
2994 alc5505_coef_set(codec, 0x6230, 0xfc0d4011); /* Disable Input OP */
2995 alc5505_coef_set(codec, 0x61b4, 0x040a2b03); /* Stop PLL2 */
2996 alc5505_coef_set(codec, 0x61b0, 0x00005b17); /* Stop PLL1 */
2997 alc5505_coef_set(codec, 0x61b8, 0x04133303); /* Stop PLL3 */
2998 val = alc5505_coef_get(codec, 0x6220);
2999 alc5505_coef_set(codec, 0x6220, (val | 0x3000)); /* switch Ringbuffer clock to DBUS clock */
3000}
3001
3002static void alc5505_dsp_back_from_halt(struct hda_codec *codec)
3003{
3004 alc5505_coef_set(codec, 0x61b8, 0x04133302);
3005 alc5505_coef_set(codec, 0x61b0, 0x00005b16);
3006 alc5505_coef_set(codec, 0x61b4, 0x040a2b02);
3007 alc5505_coef_set(codec, 0x6230, 0xf80d4011);
3008 alc5505_coef_set(codec, 0x6220, 0x2002010f);
3009 alc5505_coef_set(codec, 0x880c, 0x00000004);
3010}
3011
3012static void alc5505_dsp_init(struct hda_codec *codec)
3013{
3014 unsigned int val;
3015
3016 alc5505_dsp_halt(codec);
3017 alc5505_dsp_back_from_halt(codec);
3018 alc5505_coef_set(codec, 0x61b0, 0x5b14); /* PLL1 control */
3019 alc5505_coef_set(codec, 0x61b0, 0x5b16);
3020 alc5505_coef_set(codec, 0x61b4, 0x04132b00); /* PLL2 control */
3021 alc5505_coef_set(codec, 0x61b4, 0x04132b02);
3022 alc5505_coef_set(codec, 0x61b8, 0x041f3300); /* PLL3 control*/
3023 alc5505_coef_set(codec, 0x61b8, 0x041f3302);
3024 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_CODEC_RESET, 0); /* Function reset */
3025 alc5505_coef_set(codec, 0x61b8, 0x041b3302);
3026 alc5505_coef_set(codec, 0x61b8, 0x04173302);
3027 alc5505_coef_set(codec, 0x61b8, 0x04163302);
3028 alc5505_coef_set(codec, 0x8800, 0x348b328b); /* DRAM control */
3029 alc5505_coef_set(codec, 0x8808, 0x00020022); /* DRAM control */
3030 alc5505_coef_set(codec, 0x8818, 0x00000400); /* DRAM control */
3031
3032 val = alc5505_coef_get(codec, 0x6200) >> 16; /* Read revision ID */
3033 if (val <= 3)
3034 alc5505_coef_set(codec, 0x6220, 0x2002010f); /* I/O PAD Configuration */
3035 else
3036 alc5505_coef_set(codec, 0x6220, 0x6002018f);
3037
3038 alc5505_coef_set(codec, 0x61ac, 0x055525f0); /**/
3039 alc5505_coef_set(codec, 0x61c0, 0x12230080); /* Clock control */
3040 alc5505_coef_set(codec, 0x61b4, 0x040e2b02); /* PLL2 control */
3041 alc5505_coef_set(codec, 0x61bc, 0x010234f8); /* OSC Control */
3042 alc5505_coef_set(codec, 0x880c, 0x00000004); /* DRAM Function control */
3043 alc5505_coef_set(codec, 0x880c, 0x00000003);
3044 alc5505_coef_set(codec, 0x880c, 0x00000010);
Takashi Iwaicd63a5f2013-07-05 12:13:59 +02003045
3046#ifdef HALT_REALTEK_ALC5505
3047 alc5505_dsp_halt(codec);
3048#endif
Kailang Yangad60d502013-06-28 12:03:01 +02003049}
3050
Takashi Iwaicd63a5f2013-07-05 12:13:59 +02003051#ifdef HALT_REALTEK_ALC5505
3052#define alc5505_dsp_suspend(codec) /* NOP */
3053#define alc5505_dsp_resume(codec) /* NOP */
3054#else
3055#define alc5505_dsp_suspend(codec) alc5505_dsp_halt(codec)
3056#define alc5505_dsp_resume(codec) alc5505_dsp_back_from_halt(codec)
3057#endif
3058
Takashi Iwai2a439522011-07-26 09:52:50 +02003059#ifdef CONFIG_PM
Kailang Yangad60d502013-06-28 12:03:01 +02003060static int alc269_suspend(struct hda_codec *codec)
3061{
3062 struct alc_spec *spec = codec->spec;
3063
3064 if (spec->has_alc5505_dsp)
Takashi Iwaicd63a5f2013-07-05 12:13:59 +02003065 alc5505_dsp_suspend(codec);
Kailang Yangad60d502013-06-28 12:03:01 +02003066 return alc_suspend(codec);
3067}
3068
Takashi Iwai1d045db2011-07-07 18:23:21 +02003069static int alc269_resume(struct hda_codec *codec)
3070{
Kailang Yangadcc70b2012-05-25 08:08:38 +02003071 struct alc_spec *spec = codec->spec;
3072
Kailang Yang1387e2d2012-11-08 10:23:18 +01003073 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
3074 alc269vb_toggle_power_output(codec, 0);
3075 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
Kailang Yangadcc70b2012-05-25 08:08:38 +02003076 (alc_get_coef0(codec) & 0x00ff) == 0x018) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003077 msleep(150);
3078 }
3079
3080 codec->patch_ops.init(codec);
3081
Kailang Yang1387e2d2012-11-08 10:23:18 +01003082 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
3083 alc269vb_toggle_power_output(codec, 1);
3084 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
Kailang Yangadcc70b2012-05-25 08:08:38 +02003085 (alc_get_coef0(codec) & 0x00ff) == 0x017) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003086 msleep(200);
3087 }
3088
Takashi Iwaieeecd9d2015-02-25 15:18:50 +01003089 regcache_sync(codec->core.regmap);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003090 hda_call_check_power_status(codec, 0x01);
Hui Wangf4753712014-08-19 12:07:03 +08003091
3092 /* on some machine, the BIOS will clear the codec gpio data when enter
3093 * suspend, and won't restore the data after resume, so we restore it
3094 * in the driver.
3095 */
3096 if (spec->gpio_led)
Takashi Iwai7639a062015-03-03 10:07:24 +01003097 snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_DATA,
Hui Wangf4753712014-08-19 12:07:03 +08003098 spec->gpio_led);
3099
Kailang Yangad60d502013-06-28 12:03:01 +02003100 if (spec->has_alc5505_dsp)
Takashi Iwaicd63a5f2013-07-05 12:13:59 +02003101 alc5505_dsp_resume(codec);
Kailang Yangc5177c82013-07-24 14:39:49 +02003102
Takashi Iwai1d045db2011-07-07 18:23:21 +02003103 return 0;
3104}
Takashi Iwai2a439522011-07-26 09:52:50 +02003105#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02003106
David Henningsson108cc102012-07-20 10:37:25 +02003107static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003108 const struct hda_fixup *fix, int action)
David Henningsson108cc102012-07-20 10:37:25 +02003109{
3110 struct alc_spec *spec = codec->spec;
3111
Takashi Iwai1727a772013-01-10 09:52:52 +01003112 if (action == HDA_FIXUP_ACT_PRE_PROBE)
David Henningsson108cc102012-07-20 10:37:25 +02003113 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
3114}
3115
Takashi Iwai1d045db2011-07-07 18:23:21 +02003116static void alc269_fixup_hweq(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003117 const struct hda_fixup *fix, int action)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003118{
Takashi Iwai98b24882014-08-18 13:47:50 +02003119 if (action == HDA_FIXUP_ACT_INIT)
3120 alc_update_coef_idx(codec, 0x1e, 0, 0x80);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003121}
3122
David Henningsson7c478f02013-10-11 10:18:46 +02003123static void alc269_fixup_headset_mic(struct hda_codec *codec,
3124 const struct hda_fixup *fix, int action)
3125{
3126 struct alc_spec *spec = codec->spec;
3127
3128 if (action == HDA_FIXUP_ACT_PRE_PROBE)
3129 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
3130}
3131
Takashi Iwai1d045db2011-07-07 18:23:21 +02003132static void alc271_fixup_dmic(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003133 const struct hda_fixup *fix, int action)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003134{
3135 static const struct hda_verb verbs[] = {
3136 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
3137 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
3138 {}
3139 };
3140 unsigned int cfg;
3141
Takashi Iwai7639a062015-03-03 10:07:24 +01003142 if (strcmp(codec->core.chip_name, "ALC271X") &&
3143 strcmp(codec->core.chip_name, "ALC269VB"))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003144 return;
3145 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
3146 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
3147 snd_hda_sequence_write(codec, verbs);
3148}
3149
Takashi Iwai017f2a12011-07-09 14:42:25 +02003150static void alc269_fixup_pcm_44k(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003151 const struct hda_fixup *fix, int action)
Takashi Iwai017f2a12011-07-09 14:42:25 +02003152{
3153 struct alc_spec *spec = codec->spec;
3154
Takashi Iwai1727a772013-01-10 09:52:52 +01003155 if (action != HDA_FIXUP_ACT_PROBE)
Takashi Iwai017f2a12011-07-09 14:42:25 +02003156 return;
3157
3158 /* Due to a hardware problem on Lenovo Ideadpad, we need to
3159 * fix the sample rate of analog I/O to 44.1kHz
3160 */
Takashi Iwai08c189f2012-12-19 15:22:24 +01003161 spec->gen.stream_analog_playback = &alc269_44k_pcm_analog_playback;
3162 spec->gen.stream_analog_capture = &alc269_44k_pcm_analog_capture;
Takashi Iwai017f2a12011-07-09 14:42:25 +02003163}
3164
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02003165static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003166 const struct hda_fixup *fix, int action)
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02003167{
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02003168 /* The digital-mic unit sends PDM (differential signal) instead of
3169 * the standard PCM, thus you can't record a valid mono stream as is.
3170 * Below is a workaround specific to ALC269 to control the dmic
3171 * signal source as mono.
3172 */
Takashi Iwai98b24882014-08-18 13:47:50 +02003173 if (action == HDA_FIXUP_ACT_INIT)
3174 alc_update_coef_idx(codec, 0x07, 0, 0x80);
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02003175}
3176
Takashi Iwai24519912011-08-16 15:08:49 +02003177static void alc269_quanta_automute(struct hda_codec *codec)
3178{
Takashi Iwai08c189f2012-12-19 15:22:24 +01003179 snd_hda_gen_update_outputs(codec);
Takashi Iwai24519912011-08-16 15:08:49 +02003180
Takashi Iwai1687ccc2014-08-18 13:49:35 +02003181 alc_write_coef_idx(codec, 0x0c, 0x680);
3182 alc_write_coef_idx(codec, 0x0c, 0x480);
Takashi Iwai24519912011-08-16 15:08:49 +02003183}
3184
3185static void alc269_fixup_quanta_mute(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003186 const struct hda_fixup *fix, int action)
Takashi Iwai24519912011-08-16 15:08:49 +02003187{
3188 struct alc_spec *spec = codec->spec;
Takashi Iwai1727a772013-01-10 09:52:52 +01003189 if (action != HDA_FIXUP_ACT_PROBE)
Takashi Iwai24519912011-08-16 15:08:49 +02003190 return;
Takashi Iwai08c189f2012-12-19 15:22:24 +01003191 spec->gen.automute_hook = alc269_quanta_automute;
Takashi Iwai24519912011-08-16 15:08:49 +02003192}
3193
David Henningssond240d1d2013-04-15 12:50:02 +02003194static void alc269_x101_hp_automute_hook(struct hda_codec *codec,
Takashi Iwai1a4f69d2014-09-11 15:22:46 +02003195 struct hda_jack_callback *jack)
David Henningssond240d1d2013-04-15 12:50:02 +02003196{
3197 struct alc_spec *spec = codec->spec;
3198 int vref;
3199 msleep(200);
3200 snd_hda_gen_hp_automute(codec, jack);
3201
3202 vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
3203 msleep(100);
3204 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3205 vref);
3206 msleep(500);
3207 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3208 vref);
3209}
3210
3211static void alc269_fixup_x101_headset_mic(struct hda_codec *codec,
3212 const struct hda_fixup *fix, int action)
3213{
3214 struct alc_spec *spec = codec->spec;
3215 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3216 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
3217 spec->gen.hp_automute_hook = alc269_x101_hp_automute_hook;
3218 }
3219}
3220
3221
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003222/* update mute-LED according to the speaker mute state via mic VREF pin */
3223static void alc269_fixup_mic_mute_hook(void *private_data, int enabled)
David Henningsson6d3cd5d2013-01-07 12:03:47 +01003224{
3225 struct hda_codec *codec = private_data;
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003226 struct alc_spec *spec = codec->spec;
3227 unsigned int pinval;
3228
3229 if (spec->mute_led_polarity)
3230 enabled = !enabled;
Takashi Iwai415d5552014-04-03 11:51:21 +02003231 pinval = snd_hda_codec_get_pin_target(codec, spec->mute_led_nid);
3232 pinval &= ~AC_PINCTL_VREFEN;
3233 pinval |= enabled ? AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80;
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003234 if (spec->mute_led_nid)
3235 snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval);
David Henningsson6d3cd5d2013-01-07 12:03:47 +01003236}
3237
David Henningssond5b6b652013-11-06 10:50:44 +01003238/* Make sure the led works even in runtime suspend */
3239static unsigned int led_power_filter(struct hda_codec *codec,
3240 hda_nid_t nid,
3241 unsigned int power_state)
3242{
3243 struct alc_spec *spec = codec->spec;
3244
Hui Wang50dd9052014-07-08 17:56:15 +08003245 if (power_state != AC_PWRST_D3 || nid == 0 ||
3246 (nid != spec->mute_led_nid && nid != spec->cap_mute_led_nid))
David Henningssond5b6b652013-11-06 10:50:44 +01003247 return power_state;
3248
3249 /* Set pin ctl again, it might have just been set to 0 */
3250 snd_hda_set_pin_ctl(codec, nid,
3251 snd_hda_codec_get_pin_target(codec, nid));
3252
Takashi Iwaicffd3962015-04-09 10:30:25 +02003253 return snd_hda_gen_path_power_filter(codec, nid, power_state);
David Henningssond5b6b652013-11-06 10:50:44 +01003254}
3255
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003256static void alc269_fixup_hp_mute_led(struct hda_codec *codec,
3257 const struct hda_fixup *fix, int action)
David Henningsson6d3cd5d2013-01-07 12:03:47 +01003258{
3259 struct alc_spec *spec = codec->spec;
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003260 const struct dmi_device *dev = NULL;
3261
3262 if (action != HDA_FIXUP_ACT_PRE_PROBE)
3263 return;
3264
3265 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
3266 int pol, pin;
3267 if (sscanf(dev->name, "HP_Mute_LED_%d_%x", &pol, &pin) != 2)
3268 continue;
3269 if (pin < 0x0a || pin >= 0x10)
3270 break;
3271 spec->mute_led_polarity = pol;
3272 spec->mute_led_nid = pin - 0x0a + 0x18;
3273 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
Takashi Iwaifd25a972012-12-20 14:57:18 +01003274 spec->gen.vmaster_mute_enum = 1;
David Henningssond5b6b652013-11-06 10:50:44 +01003275 codec->power_filter = led_power_filter;
Takashi Iwai4e76a882014-02-25 12:21:03 +01003276 codec_dbg(codec,
3277 "Detected mute LED for %x:%d\n", spec->mute_led_nid,
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003278 spec->mute_led_polarity);
David Henningsson6d3cd5d2013-01-07 12:03:47 +01003279 break;
3280 }
3281}
3282
David Henningssond06ac142013-02-18 11:41:55 +01003283static void alc269_fixup_hp_mute_led_mic1(struct hda_codec *codec,
3284 const struct hda_fixup *fix, int action)
3285{
3286 struct alc_spec *spec = codec->spec;
3287 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3288 spec->mute_led_polarity = 0;
3289 spec->mute_led_nid = 0x18;
3290 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
3291 spec->gen.vmaster_mute_enum = 1;
David Henningssond5b6b652013-11-06 10:50:44 +01003292 codec->power_filter = led_power_filter;
David Henningssond06ac142013-02-18 11:41:55 +01003293 }
3294}
3295
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003296static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec,
3297 const struct hda_fixup *fix, int action)
Takashi Iwai420b0fe2012-03-12 12:35:27 +01003298{
3299 struct alc_spec *spec = codec->spec;
Takashi Iwai9bb1f062013-01-10 17:14:29 +01003300 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003301 spec->mute_led_polarity = 0;
3302 spec->mute_led_nid = 0x19;
3303 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
Takashi Iwaifd25a972012-12-20 14:57:18 +01003304 spec->gen.vmaster_mute_enum = 1;
David Henningssond5b6b652013-11-06 10:50:44 +01003305 codec->power_filter = led_power_filter;
Takashi Iwai420b0fe2012-03-12 12:35:27 +01003306 }
3307}
3308
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003309/* update LED status via GPIO */
3310static void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask,
3311 bool enabled)
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003312{
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003313 struct alc_spec *spec = codec->spec;
3314 unsigned int oldval = spec->gpio_led;
3315
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003316 if (spec->mute_led_polarity)
3317 enabled = !enabled;
3318
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003319 if (enabled)
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003320 spec->gpio_led &= ~mask;
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003321 else
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003322 spec->gpio_led |= mask;
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003323 if (spec->gpio_led != oldval)
3324 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3325 spec->gpio_led);
3326}
3327
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003328/* turn on/off mute LED via GPIO per vmaster hook */
3329static void alc_fixup_gpio_mute_hook(void *private_data, int enabled)
3330{
3331 struct hda_codec *codec = private_data;
3332 struct alc_spec *spec = codec->spec;
3333
3334 alc_update_gpio_led(codec, spec->gpio_mute_led_mask, enabled);
3335}
3336
3337/* turn on/off mic-mute LED via GPIO per capture hook */
3338static void alc_fixup_gpio_mic_mute_hook(struct hda_codec *codec,
3339 struct snd_kcontrol *kcontrol,
3340 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003341{
3342 struct alc_spec *spec = codec->spec;
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003343
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003344 if (ucontrol)
3345 alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
3346 ucontrol->value.integer.value[0] ||
3347 ucontrol->value.integer.value[1]);
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003348}
3349
3350static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
3351 const struct hda_fixup *fix, int action)
3352{
3353 struct alc_spec *spec = codec->spec;
3354 static const struct hda_verb gpio_init[] = {
3355 { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
3356 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
3357 {}
3358 };
3359
3360 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003361 spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
3362 spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003363 spec->gpio_led = 0;
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003364 spec->mute_led_polarity = 0;
3365 spec->gpio_mute_led_mask = 0x08;
3366 spec->gpio_mic_led_mask = 0x10;
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003367 snd_hda_add_verbs(codec, gpio_init);
3368 }
3369}
3370
Kailang Yangeaa8e5e2014-11-21 15:49:11 +08003371static void alc286_fixup_hp_gpio_led(struct hda_codec *codec,
3372 const struct hda_fixup *fix, int action)
3373{
3374 struct alc_spec *spec = codec->spec;
3375 static const struct hda_verb gpio_init[] = {
3376 { 0x01, AC_VERB_SET_GPIO_MASK, 0x22 },
3377 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x22 },
3378 {}
3379 };
3380
3381 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3382 spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
3383 spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
3384 spec->gpio_led = 0;
3385 spec->mute_led_polarity = 0;
3386 spec->gpio_mute_led_mask = 0x02;
3387 spec->gpio_mic_led_mask = 0x20;
Takashi Iwai1d045db2011-07-07 18:23:21 +02003388 snd_hda_add_verbs(codec, gpio_init);
3389 }
3390}
3391
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08003392/* turn on/off mic-mute LED per capture hook */
3393static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec,
3394 struct snd_kcontrol *kcontrol,
3395 struct snd_ctl_elem_value *ucontrol)
3396{
3397 struct alc_spec *spec = codec->spec;
3398 unsigned int pinval, enable, disable;
3399
Hui Wangfc1fad92014-07-08 17:56:14 +08003400 pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid);
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08003401 pinval &= ~AC_PINCTL_VREFEN;
3402 enable = pinval | AC_PINCTL_VREF_80;
3403 disable = pinval | AC_PINCTL_VREF_HIZ;
3404
3405 if (!ucontrol)
3406 return;
3407
3408 if (ucontrol->value.integer.value[0] ||
3409 ucontrol->value.integer.value[1])
3410 pinval = disable;
3411 else
3412 pinval = enable;
3413
3414 if (spec->cap_mute_led_nid)
3415 snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
3416}
3417
3418static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
3419 const struct hda_fixup *fix, int action)
3420{
3421 struct alc_spec *spec = codec->spec;
3422 static const struct hda_verb gpio_init[] = {
3423 { 0x01, AC_VERB_SET_GPIO_MASK, 0x08 },
3424 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 },
3425 {}
3426 };
3427
3428 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003429 spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08003430 spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
3431 spec->gpio_led = 0;
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003432 spec->mute_led_polarity = 0;
3433 spec->gpio_mute_led_mask = 0x08;
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08003434 spec->cap_mute_led_nid = 0x18;
3435 snd_hda_add_verbs(codec, gpio_init);
Hui Wang50dd9052014-07-08 17:56:15 +08003436 codec->power_filter = led_power_filter;
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08003437 }
3438}
3439
David Henningsson7a5255f2014-10-30 08:26:01 +01003440static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
3441 const struct hda_fixup *fix, int action)
3442{
3443 /* Like hp_gpio_mic1_led, but also needs GPIO4 low to enable headphone amp */
3444 struct alc_spec *spec = codec->spec;
3445 static const struct hda_verb gpio_init[] = {
3446 { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
3447 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
3448 {}
3449 };
3450
3451 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003452 spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
David Henningsson7a5255f2014-10-30 08:26:01 +01003453 spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
3454 spec->gpio_led = 0;
Takashi Iwai0f32fd192014-11-19 12:16:14 +01003455 spec->mute_led_polarity = 0;
3456 spec->gpio_mute_led_mask = 0x08;
David Henningsson7a5255f2014-10-30 08:26:01 +01003457 spec->cap_mute_led_nid = 0x18;
3458 snd_hda_add_verbs(codec, gpio_init);
3459 codec->power_filter = led_power_filter;
3460 }
3461}
3462
David Henningsson33f4acd2015-01-07 15:50:13 +01003463static void gpio2_mic_hotkey_event(struct hda_codec *codec,
3464 struct hda_jack_callback *event)
3465{
3466 struct alc_spec *spec = codec->spec;
3467
3468 /* GPIO2 just toggles on a keypress/keyrelease cycle. Therefore
3469 send both key on and key off event for every interrupt. */
Hui Wangc7b60a82015-12-28 11:35:25 +08003470 input_report_key(spec->kb_dev, spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX], 1);
David Henningsson33f4acd2015-01-07 15:50:13 +01003471 input_sync(spec->kb_dev);
Hui Wangc7b60a82015-12-28 11:35:25 +08003472 input_report_key(spec->kb_dev, spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX], 0);
David Henningsson33f4acd2015-01-07 15:50:13 +01003473 input_sync(spec->kb_dev);
3474}
David Henningsson33f4acd2015-01-07 15:50:13 +01003475
Kailang3694cb22015-12-28 11:35:24 +08003476static int alc_register_micmute_input_device(struct hda_codec *codec)
3477{
3478 struct alc_spec *spec = codec->spec;
Hui Wangc7b60a82015-12-28 11:35:25 +08003479 int i;
Kailang3694cb22015-12-28 11:35:24 +08003480
3481 spec->kb_dev = input_allocate_device();
3482 if (!spec->kb_dev) {
3483 codec_err(codec, "Out of memory (input_allocate_device)\n");
3484 return -ENOMEM;
3485 }
Hui Wangc7b60a82015-12-28 11:35:25 +08003486
3487 spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX] = KEY_MICMUTE;
3488
Kailang3694cb22015-12-28 11:35:24 +08003489 spec->kb_dev->name = "Microphone Mute Button";
3490 spec->kb_dev->evbit[0] = BIT_MASK(EV_KEY);
Hui Wangc7b60a82015-12-28 11:35:25 +08003491 spec->kb_dev->keycodesize = sizeof(spec->alc_mute_keycode_map[0]);
3492 spec->kb_dev->keycodemax = ARRAY_SIZE(spec->alc_mute_keycode_map);
3493 spec->kb_dev->keycode = spec->alc_mute_keycode_map;
3494 for (i = 0; i < ARRAY_SIZE(spec->alc_mute_keycode_map); i++)
3495 set_bit(spec->alc_mute_keycode_map[i], spec->kb_dev->keybit);
Kailang3694cb22015-12-28 11:35:24 +08003496
3497 if (input_register_device(spec->kb_dev)) {
3498 codec_err(codec, "input_register_device failed\n");
3499 input_free_device(spec->kb_dev);
3500 spec->kb_dev = NULL;
3501 return -ENOMEM;
3502 }
3503
3504 return 0;
3505}
3506
David Henningsson33f4acd2015-01-07 15:50:13 +01003507static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
3508 const struct hda_fixup *fix, int action)
3509{
David Henningsson33f4acd2015-01-07 15:50:13 +01003510 /* GPIO1 = set according to SKU external amp
3511 GPIO2 = mic mute hotkey
3512 GPIO3 = mute LED
3513 GPIO4 = mic mute LED */
3514 static const struct hda_verb gpio_init[] = {
3515 { 0x01, AC_VERB_SET_GPIO_MASK, 0x1e },
3516 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x1a },
3517 { 0x01, AC_VERB_SET_GPIO_DATA, 0x02 },
3518 {}
3519 };
3520
3521 struct alc_spec *spec = codec->spec;
3522
3523 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Kailang3694cb22015-12-28 11:35:24 +08003524 if (alc_register_micmute_input_device(codec) != 0)
David Henningsson33f4acd2015-01-07 15:50:13 +01003525 return;
David Henningsson33f4acd2015-01-07 15:50:13 +01003526
3527 snd_hda_add_verbs(codec, gpio_init);
Takashi Iwai7639a062015-03-03 10:07:24 +01003528 snd_hda_codec_write_cache(codec, codec->core.afg, 0,
David Henningsson33f4acd2015-01-07 15:50:13 +01003529 AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x04);
Takashi Iwai7639a062015-03-03 10:07:24 +01003530 snd_hda_jack_detect_enable_callback(codec, codec->core.afg,
David Henningsson33f4acd2015-01-07 15:50:13 +01003531 gpio2_mic_hotkey_event);
3532
3533 spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
3534 spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
3535 spec->gpio_led = 0;
3536 spec->mute_led_polarity = 0;
3537 spec->gpio_mute_led_mask = 0x08;
3538 spec->gpio_mic_led_mask = 0x10;
3539 return;
3540 }
3541
3542 if (!spec->kb_dev)
3543 return;
3544
3545 switch (action) {
3546 case HDA_FIXUP_ACT_PROBE:
3547 spec->init_amp = ALC_INIT_DEFAULT;
3548 break;
3549 case HDA_FIXUP_ACT_FREE:
3550 input_unregister_device(spec->kb_dev);
David Henningsson33f4acd2015-01-07 15:50:13 +01003551 spec->kb_dev = NULL;
3552 }
David Henningsson33f4acd2015-01-07 15:50:13 +01003553}
3554
Kailang3694cb22015-12-28 11:35:24 +08003555static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec,
3556 const struct hda_fixup *fix, int action)
3557{
3558 /* Line2 = mic mute hotkey
3559 GPIO2 = mic mute LED */
3560 static const struct hda_verb gpio_init[] = {
3561 { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 },
3562 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 },
3563 {}
3564 };
3565
3566 struct alc_spec *spec = codec->spec;
3567
3568 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3569 if (alc_register_micmute_input_device(codec) != 0)
3570 return;
3571
3572 snd_hda_add_verbs(codec, gpio_init);
3573 snd_hda_jack_detect_enable_callback(codec, 0x1b,
3574 gpio2_mic_hotkey_event);
3575
3576 spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
3577 spec->gpio_led = 0;
3578 spec->mute_led_polarity = 0;
3579 spec->gpio_mic_led_mask = 0x04;
3580 return;
3581 }
3582
3583 if (!spec->kb_dev)
3584 return;
3585
3586 switch (action) {
3587 case HDA_FIXUP_ACT_PROBE:
3588 spec->init_amp = ALC_INIT_DEFAULT;
3589 break;
3590 case HDA_FIXUP_ACT_FREE:
3591 input_unregister_device(spec->kb_dev);
3592 spec->kb_dev = NULL;
3593 }
3594}
3595
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08003596static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
3597 const struct hda_fixup *fix, int action)
3598{
3599 struct alc_spec *spec = codec->spec;
3600
3601 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3602 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
3603 spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
3604 spec->mute_led_polarity = 0;
3605 spec->mute_led_nid = 0x1a;
3606 spec->cap_mute_led_nid = 0x18;
3607 spec->gen.vmaster_mute_enum = 1;
3608 codec->power_filter = led_power_filter;
3609 }
3610}
3611
David Henningsson73bdd592013-04-15 15:44:14 +02003612static void alc_headset_mode_unplugged(struct hda_codec *codec)
3613{
Takashi Iwai54db6c32014-08-18 15:11:19 +02003614 static struct coef_fw coef0255[] = {
3615 WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
3616 WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
3617 UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
3618 WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
3619 WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */
3620 {}
3621 };
3622 static struct coef_fw coef0233[] = {
3623 WRITE_COEF(0x1b, 0x0c0b),
3624 WRITE_COEF(0x45, 0xc429),
3625 UPDATE_COEF(0x35, 0x4000, 0),
3626 WRITE_COEF(0x06, 0x2104),
3627 WRITE_COEF(0x1a, 0x0001),
3628 WRITE_COEF(0x26, 0x0004),
3629 WRITE_COEF(0x32, 0x42a3),
3630 {}
3631 };
Kailang Yangf3b70332015-04-08 15:01:17 +08003632 static struct coef_fw coef0288[] = {
3633 UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
3634 UPDATE_COEF(0x50, 0x2000, 0x2000),
3635 UPDATE_COEF(0x56, 0x0006, 0x0006),
3636 UPDATE_COEF(0x66, 0x0008, 0),
3637 UPDATE_COEF(0x67, 0x2000, 0),
3638 {}
3639 };
Takashi Iwai54db6c32014-08-18 15:11:19 +02003640 static struct coef_fw coef0292[] = {
3641 WRITE_COEF(0x76, 0x000e),
3642 WRITE_COEF(0x6c, 0x2400),
3643 WRITE_COEF(0x18, 0x7308),
3644 WRITE_COEF(0x6b, 0xc429),
3645 {}
3646 };
3647 static struct coef_fw coef0293[] = {
3648 UPDATE_COEF(0x10, 7<<8, 6<<8), /* SET Line1 JD to 0 */
3649 UPDATE_COEFEX(0x57, 0x05, 1<<15|1<<13, 0x0), /* SET charge pump by verb */
3650 UPDATE_COEFEX(0x57, 0x03, 1<<10, 1<<10), /* SET EN_OSW to 1 */
3651 UPDATE_COEF(0x1a, 1<<3, 1<<3), /* Combo JD gating with LINE1-VREFO */
3652 WRITE_COEF(0x45, 0xc429), /* Set to TRS type */
3653 UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */
3654 {}
3655 };
3656 static struct coef_fw coef0668[] = {
3657 WRITE_COEF(0x15, 0x0d40),
3658 WRITE_COEF(0xb7, 0x802b),
3659 {}
3660 };
3661
Takashi Iwai7639a062015-03-03 10:07:24 +01003662 switch (codec->core.vendor_id) {
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003663 case 0x10ec0255:
Kailang Yang7081adf2015-03-30 17:05:37 +08003664 case 0x10ec0256:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003665 alc_process_coef_fw(codec, coef0255);
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003666 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003667 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003668 case 0x10ec0283:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003669 alc_process_coef_fw(codec, coef0233);
David Henningsson73bdd592013-04-15 15:44:14 +02003670 break;
Kailang Yangf3b70332015-04-08 15:01:17 +08003671 case 0x10ec0286:
3672 case 0x10ec0288:
Kailang Yang1a5bc8d2015-05-12 17:11:10 +08003673 case 0x10ec0298:
Kailang Yangf3b70332015-04-08 15:01:17 +08003674 alc_process_coef_fw(codec, coef0288);
3675 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003676 case 0x10ec0292:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003677 alc_process_coef_fw(codec, coef0292);
David Henningsson73bdd592013-04-15 15:44:14 +02003678 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003679 case 0x10ec0293:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003680 alc_process_coef_fw(codec, coef0293);
Kailang Yanga22aa262014-04-23 17:34:28 +08003681 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003682 case 0x10ec0668:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003683 alc_process_coef_fw(codec, coef0668);
David Henningsson73bdd592013-04-15 15:44:14 +02003684 break;
3685 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01003686 codec_dbg(codec, "Headset jack set to unplugged mode.\n");
David Henningsson73bdd592013-04-15 15:44:14 +02003687}
3688
3689
3690static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
3691 hda_nid_t mic_pin)
3692{
Takashi Iwai54db6c32014-08-18 15:11:19 +02003693 static struct coef_fw coef0255[] = {
3694 WRITE_COEFEX(0x57, 0x03, 0x8aa6),
3695 WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */
3696 {}
3697 };
3698 static struct coef_fw coef0233[] = {
3699 UPDATE_COEF(0x35, 0, 1<<14),
3700 WRITE_COEF(0x06, 0x2100),
3701 WRITE_COEF(0x1a, 0x0021),
3702 WRITE_COEF(0x26, 0x008c),
3703 {}
3704 };
Kailang Yangf3b70332015-04-08 15:01:17 +08003705 static struct coef_fw coef0288[] = {
3706 UPDATE_COEF(0x50, 0x2000, 0),
3707 UPDATE_COEF(0x56, 0x0006, 0),
3708 UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
3709 UPDATE_COEF(0x66, 0x0008, 0x0008),
3710 UPDATE_COEF(0x67, 0x2000, 0x2000),
3711 {}
3712 };
Takashi Iwai54db6c32014-08-18 15:11:19 +02003713 static struct coef_fw coef0292[] = {
3714 WRITE_COEF(0x19, 0xa208),
3715 WRITE_COEF(0x2e, 0xacf0),
3716 {}
3717 };
3718 static struct coef_fw coef0293[] = {
3719 UPDATE_COEFEX(0x57, 0x05, 0, 1<<15|1<<13), /* SET charge pump by verb */
3720 UPDATE_COEFEX(0x57, 0x03, 1<<10, 0), /* SET EN_OSW to 0 */
3721 UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */
3722 {}
3723 };
3724 static struct coef_fw coef0688[] = {
3725 WRITE_COEF(0xb7, 0x802b),
3726 WRITE_COEF(0xb5, 0x1040),
3727 UPDATE_COEF(0xc3, 0, 1<<12),
3728 {}
3729 };
3730
Takashi Iwai7639a062015-03-03 10:07:24 +01003731 switch (codec->core.vendor_id) {
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003732 case 0x10ec0255:
Kailang Yang7081adf2015-03-30 17:05:37 +08003733 case 0x10ec0256:
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003734 alc_write_coef_idx(codec, 0x45, 0xc489);
3735 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
Takashi Iwai54db6c32014-08-18 15:11:19 +02003736 alc_process_coef_fw(codec, coef0255);
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003737 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3738 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003739 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003740 case 0x10ec0283:
3741 alc_write_coef_idx(codec, 0x45, 0xc429);
3742 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
Takashi Iwai54db6c32014-08-18 15:11:19 +02003743 alc_process_coef_fw(codec, coef0233);
David Henningsson73bdd592013-04-15 15:44:14 +02003744 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3745 break;
Kailang Yangf3b70332015-04-08 15:01:17 +08003746 case 0x10ec0286:
3747 case 0x10ec0288:
Kailang Yang1a5bc8d2015-05-12 17:11:10 +08003748 case 0x10ec0298:
Kailang Yangf3b70332015-04-08 15:01:17 +08003749 alc_update_coef_idx(codec, 0x4f, 0x000c, 0);
3750 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3751 alc_process_coef_fw(codec, coef0288);
3752 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3753 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003754 case 0x10ec0292:
3755 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
Takashi Iwai54db6c32014-08-18 15:11:19 +02003756 alc_process_coef_fw(codec, coef0292);
David Henningsson73bdd592013-04-15 15:44:14 +02003757 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003758 case 0x10ec0293:
3759 /* Set to TRS mode */
3760 alc_write_coef_idx(codec, 0x45, 0xc429);
3761 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
Takashi Iwai54db6c32014-08-18 15:11:19 +02003762 alc_process_coef_fw(codec, coef0293);
Kailang Yanga22aa262014-04-23 17:34:28 +08003763 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3764 break;
David Henningsson1f8b46c2015-05-12 14:38:15 +02003765 case 0x10ec0662:
3766 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3767 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3768 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003769 case 0x10ec0668:
3770 alc_write_coef_idx(codec, 0x11, 0x0001);
3771 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
Takashi Iwai54db6c32014-08-18 15:11:19 +02003772 alc_process_coef_fw(codec, coef0688);
David Henningsson73bdd592013-04-15 15:44:14 +02003773 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3774 break;
3775 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01003776 codec_dbg(codec, "Headset jack set to mic-in mode.\n");
David Henningsson73bdd592013-04-15 15:44:14 +02003777}
3778
3779static void alc_headset_mode_default(struct hda_codec *codec)
3780{
Takashi Iwai54db6c32014-08-18 15:11:19 +02003781 static struct coef_fw coef0255[] = {
3782 WRITE_COEF(0x45, 0xc089),
3783 WRITE_COEF(0x45, 0xc489),
3784 WRITE_COEFEX(0x57, 0x03, 0x8ea6),
3785 WRITE_COEF(0x49, 0x0049),
3786 {}
3787 };
3788 static struct coef_fw coef0233[] = {
3789 WRITE_COEF(0x06, 0x2100),
3790 WRITE_COEF(0x32, 0x4ea3),
3791 {}
3792 };
Kailang Yangf3b70332015-04-08 15:01:17 +08003793 static struct coef_fw coef0288[] = {
3794 UPDATE_COEF(0x4f, 0xfcc0, 0xc400), /* Set to TRS type */
3795 UPDATE_COEF(0x50, 0x2000, 0x2000),
3796 UPDATE_COEF(0x56, 0x0006, 0x0006),
3797 UPDATE_COEF(0x66, 0x0008, 0),
3798 UPDATE_COEF(0x67, 0x2000, 0),
3799 {}
3800 };
Takashi Iwai54db6c32014-08-18 15:11:19 +02003801 static struct coef_fw coef0292[] = {
3802 WRITE_COEF(0x76, 0x000e),
3803 WRITE_COEF(0x6c, 0x2400),
3804 WRITE_COEF(0x6b, 0xc429),
3805 WRITE_COEF(0x18, 0x7308),
3806 {}
3807 };
3808 static struct coef_fw coef0293[] = {
3809 UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */
3810 WRITE_COEF(0x45, 0xC429), /* Set to TRS type */
3811 UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */
3812 {}
3813 };
3814 static struct coef_fw coef0688[] = {
3815 WRITE_COEF(0x11, 0x0041),
3816 WRITE_COEF(0x15, 0x0d40),
3817 WRITE_COEF(0xb7, 0x802b),
3818 {}
3819 };
3820
Takashi Iwai7639a062015-03-03 10:07:24 +01003821 switch (codec->core.vendor_id) {
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003822 case 0x10ec0255:
Kailang Yang7081adf2015-03-30 17:05:37 +08003823 case 0x10ec0256:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003824 alc_process_coef_fw(codec, coef0255);
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003825 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003826 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003827 case 0x10ec0283:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003828 alc_process_coef_fw(codec, coef0233);
David Henningsson73bdd592013-04-15 15:44:14 +02003829 break;
Kailang Yangf3b70332015-04-08 15:01:17 +08003830 case 0x10ec0286:
3831 case 0x10ec0288:
Kailang Yang1a5bc8d2015-05-12 17:11:10 +08003832 case 0x10ec0298:
Kailang Yangf3b70332015-04-08 15:01:17 +08003833 alc_process_coef_fw(codec, coef0288);
3834 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003835 case 0x10ec0292:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003836 alc_process_coef_fw(codec, coef0292);
David Henningsson73bdd592013-04-15 15:44:14 +02003837 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003838 case 0x10ec0293:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003839 alc_process_coef_fw(codec, coef0293);
Kailang Yanga22aa262014-04-23 17:34:28 +08003840 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003841 case 0x10ec0668:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003842 alc_process_coef_fw(codec, coef0688);
David Henningsson73bdd592013-04-15 15:44:14 +02003843 break;
3844 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01003845 codec_dbg(codec, "Headset jack set to headphone (default) mode.\n");
David Henningsson73bdd592013-04-15 15:44:14 +02003846}
3847
3848/* Iphone type */
3849static void alc_headset_mode_ctia(struct hda_codec *codec)
3850{
Takashi Iwai54db6c32014-08-18 15:11:19 +02003851 static struct coef_fw coef0255[] = {
3852 WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
3853 WRITE_COEF(0x1b, 0x0c2b),
3854 WRITE_COEFEX(0x57, 0x03, 0x8ea6),
3855 {}
3856 };
3857 static struct coef_fw coef0233[] = {
3858 WRITE_COEF(0x45, 0xd429),
3859 WRITE_COEF(0x1b, 0x0c2b),
3860 WRITE_COEF(0x32, 0x4ea3),
3861 {}
3862 };
Kailang Yangf3b70332015-04-08 15:01:17 +08003863 static struct coef_fw coef0288[] = {
3864 UPDATE_COEF(0x50, 0x2000, 0x2000),
3865 UPDATE_COEF(0x56, 0x0006, 0x0006),
3866 UPDATE_COEF(0x66, 0x0008, 0),
3867 UPDATE_COEF(0x67, 0x2000, 0),
3868 {}
3869 };
Takashi Iwai54db6c32014-08-18 15:11:19 +02003870 static struct coef_fw coef0292[] = {
3871 WRITE_COEF(0x6b, 0xd429),
3872 WRITE_COEF(0x76, 0x0008),
3873 WRITE_COEF(0x18, 0x7388),
3874 {}
3875 };
3876 static struct coef_fw coef0293[] = {
3877 WRITE_COEF(0x45, 0xd429), /* Set to ctia type */
3878 UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */
3879 {}
3880 };
3881 static struct coef_fw coef0688[] = {
3882 WRITE_COEF(0x11, 0x0001),
3883 WRITE_COEF(0x15, 0x0d60),
3884 WRITE_COEF(0xc3, 0x0000),
3885 {}
3886 };
3887
Takashi Iwai7639a062015-03-03 10:07:24 +01003888 switch (codec->core.vendor_id) {
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003889 case 0x10ec0255:
Kailang Yang7081adf2015-03-30 17:05:37 +08003890 case 0x10ec0256:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003891 alc_process_coef_fw(codec, coef0255);
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003892 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003893 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003894 case 0x10ec0283:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003895 alc_process_coef_fw(codec, coef0233);
David Henningsson73bdd592013-04-15 15:44:14 +02003896 break;
Kailang Yang1a5bc8d2015-05-12 17:11:10 +08003897 case 0x10ec0298:
3898 alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020);/* Headset output enable */
3899 /* ALC298 jack type setting is the same with ALC286/ALC288 */
Kailang Yangf3b70332015-04-08 15:01:17 +08003900 case 0x10ec0286:
3901 case 0x10ec0288:
3902 alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
3903 msleep(300);
3904 alc_process_coef_fw(codec, coef0288);
3905 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003906 case 0x10ec0292:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003907 alc_process_coef_fw(codec, coef0292);
David Henningsson73bdd592013-04-15 15:44:14 +02003908 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003909 case 0x10ec0293:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003910 alc_process_coef_fw(codec, coef0293);
Kailang Yanga22aa262014-04-23 17:34:28 +08003911 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003912 case 0x10ec0668:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003913 alc_process_coef_fw(codec, coef0688);
David Henningsson73bdd592013-04-15 15:44:14 +02003914 break;
3915 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01003916 codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n");
David Henningsson73bdd592013-04-15 15:44:14 +02003917}
3918
3919/* Nokia type */
3920static void alc_headset_mode_omtp(struct hda_codec *codec)
3921{
Takashi Iwai54db6c32014-08-18 15:11:19 +02003922 static struct coef_fw coef0255[] = {
3923 WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
3924 WRITE_COEF(0x1b, 0x0c2b),
3925 WRITE_COEFEX(0x57, 0x03, 0x8ea6),
3926 {}
3927 };
3928 static struct coef_fw coef0233[] = {
3929 WRITE_COEF(0x45, 0xe429),
3930 WRITE_COEF(0x1b, 0x0c2b),
3931 WRITE_COEF(0x32, 0x4ea3),
3932 {}
3933 };
Kailang Yangf3b70332015-04-08 15:01:17 +08003934 static struct coef_fw coef0288[] = {
3935 UPDATE_COEF(0x50, 0x2000, 0x2000),
3936 UPDATE_COEF(0x56, 0x0006, 0x0006),
3937 UPDATE_COEF(0x66, 0x0008, 0),
3938 UPDATE_COEF(0x67, 0x2000, 0),
3939 {}
3940 };
Takashi Iwai54db6c32014-08-18 15:11:19 +02003941 static struct coef_fw coef0292[] = {
3942 WRITE_COEF(0x6b, 0xe429),
3943 WRITE_COEF(0x76, 0x0008),
3944 WRITE_COEF(0x18, 0x7388),
3945 {}
3946 };
3947 static struct coef_fw coef0293[] = {
3948 WRITE_COEF(0x45, 0xe429), /* Set to omtp type */
3949 UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */
3950 {}
3951 };
3952 static struct coef_fw coef0688[] = {
3953 WRITE_COEF(0x11, 0x0001),
3954 WRITE_COEF(0x15, 0x0d50),
3955 WRITE_COEF(0xc3, 0x0000),
3956 {}
3957 };
3958
Takashi Iwai7639a062015-03-03 10:07:24 +01003959 switch (codec->core.vendor_id) {
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003960 case 0x10ec0255:
Kailang Yang7081adf2015-03-30 17:05:37 +08003961 case 0x10ec0256:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003962 alc_process_coef_fw(codec, coef0255);
Kailang Yang9a22a8f2013-11-08 15:54:49 +08003963 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003964 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003965 case 0x10ec0283:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003966 alc_process_coef_fw(codec, coef0233);
David Henningsson73bdd592013-04-15 15:44:14 +02003967 break;
Kailang Yang1a5bc8d2015-05-12 17:11:10 +08003968 case 0x10ec0298:
3969 alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);/* Headset output enable */
3970 /* ALC298 jack type setting is the same with ALC286/ALC288 */
Kailang Yangf3b70332015-04-08 15:01:17 +08003971 case 0x10ec0286:
3972 case 0x10ec0288:
3973 alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400);
3974 msleep(300);
3975 alc_process_coef_fw(codec, coef0288);
3976 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003977 case 0x10ec0292:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003978 alc_process_coef_fw(codec, coef0292);
David Henningsson73bdd592013-04-15 15:44:14 +02003979 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003980 case 0x10ec0293:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003981 alc_process_coef_fw(codec, coef0293);
Kailang Yanga22aa262014-04-23 17:34:28 +08003982 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003983 case 0x10ec0668:
Takashi Iwai54db6c32014-08-18 15:11:19 +02003984 alc_process_coef_fw(codec, coef0688);
David Henningsson73bdd592013-04-15 15:44:14 +02003985 break;
3986 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01003987 codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n");
David Henningsson73bdd592013-04-15 15:44:14 +02003988}
3989
3990static void alc_determine_headset_type(struct hda_codec *codec)
3991{
3992 int val;
3993 bool is_ctia = false;
3994 struct alc_spec *spec = codec->spec;
Takashi Iwai54db6c32014-08-18 15:11:19 +02003995 static struct coef_fw coef0255[] = {
3996 WRITE_COEF(0x45, 0xd089), /* combo jack auto switch control(Check type)*/
3997 WRITE_COEF(0x49, 0x0149), /* combo jack auto switch control(Vref
3998 conteol) */
3999 {}
4000 };
Kailang Yangf3b70332015-04-08 15:01:17 +08004001 static struct coef_fw coef0288[] = {
4002 UPDATE_COEF(0x4f, 0xfcc0, 0xd400), /* Check Type */
4003 {}
4004 };
Takashi Iwai54db6c32014-08-18 15:11:19 +02004005 static struct coef_fw coef0293[] = {
4006 UPDATE_COEF(0x4a, 0x000f, 0x0008), /* Combo Jack auto detect */
4007 WRITE_COEF(0x45, 0xD429), /* Set to ctia type */
4008 {}
4009 };
4010 static struct coef_fw coef0688[] = {
4011 WRITE_COEF(0x11, 0x0001),
4012 WRITE_COEF(0xb7, 0x802b),
4013 WRITE_COEF(0x15, 0x0d60),
4014 WRITE_COEF(0xc3, 0x0c00),
4015 {}
4016 };
David Henningsson73bdd592013-04-15 15:44:14 +02004017
Takashi Iwai7639a062015-03-03 10:07:24 +01004018 switch (codec->core.vendor_id) {
Kailang Yang9a22a8f2013-11-08 15:54:49 +08004019 case 0x10ec0255:
Kailang Yang7081adf2015-03-30 17:05:37 +08004020 case 0x10ec0256:
Takashi Iwai54db6c32014-08-18 15:11:19 +02004021 alc_process_coef_fw(codec, coef0255);
Kailang Yang9a22a8f2013-11-08 15:54:49 +08004022 msleep(300);
4023 val = alc_read_coef_idx(codec, 0x46);
4024 is_ctia = (val & 0x0070) == 0x0070;
4025 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08004026 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02004027 case 0x10ec0283:
4028 alc_write_coef_idx(codec, 0x45, 0xd029);
4029 msleep(300);
4030 val = alc_read_coef_idx(codec, 0x46);
4031 is_ctia = (val & 0x0070) == 0x0070;
4032 break;
Kailang Yang1a5bc8d2015-05-12 17:11:10 +08004033 case 0x10ec0298:
4034 alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020); /* Headset output enable */
4035 /* ALC298 check jack type is the same with ALC286/ALC288 */
Kailang Yangf3b70332015-04-08 15:01:17 +08004036 case 0x10ec0286:
4037 case 0x10ec0288:
4038 alc_process_coef_fw(codec, coef0288);
4039 msleep(350);
4040 val = alc_read_coef_idx(codec, 0x50);
4041 is_ctia = (val & 0x0070) == 0x0070;
4042 break;
David Henningsson73bdd592013-04-15 15:44:14 +02004043 case 0x10ec0292:
4044 alc_write_coef_idx(codec, 0x6b, 0xd429);
4045 msleep(300);
4046 val = alc_read_coef_idx(codec, 0x6c);
4047 is_ctia = (val & 0x001c) == 0x001c;
4048 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08004049 case 0x10ec0293:
Takashi Iwai54db6c32014-08-18 15:11:19 +02004050 alc_process_coef_fw(codec, coef0293);
Kailang Yanga22aa262014-04-23 17:34:28 +08004051 msleep(300);
4052 val = alc_read_coef_idx(codec, 0x46);
4053 is_ctia = (val & 0x0070) == 0x0070;
4054 break;
David Henningsson73bdd592013-04-15 15:44:14 +02004055 case 0x10ec0668:
Takashi Iwai54db6c32014-08-18 15:11:19 +02004056 alc_process_coef_fw(codec, coef0688);
David Henningsson73bdd592013-04-15 15:44:14 +02004057 msleep(300);
4058 val = alc_read_coef_idx(codec, 0xbe);
4059 is_ctia = (val & 0x1c02) == 0x1c02;
4060 break;
4061 }
4062
Takashi Iwai4e76a882014-02-25 12:21:03 +01004063 codec_dbg(codec, "Headset jack detected iPhone-style headset: %s\n",
David Henningsson73bdd592013-04-15 15:44:14 +02004064 is_ctia ? "yes" : "no");
4065 spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP;
4066}
4067
4068static void alc_update_headset_mode(struct hda_codec *codec)
4069{
4070 struct alc_spec *spec = codec->spec;
4071
4072 hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
4073 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
4074
4075 int new_headset_mode;
4076
4077 if (!snd_hda_jack_detect(codec, hp_pin))
4078 new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED;
4079 else if (mux_pin == spec->headset_mic_pin)
4080 new_headset_mode = ALC_HEADSET_MODE_HEADSET;
4081 else if (mux_pin == spec->headphone_mic_pin)
4082 new_headset_mode = ALC_HEADSET_MODE_MIC;
4083 else
4084 new_headset_mode = ALC_HEADSET_MODE_HEADPHONE;
4085
David Henningsson5959a6b2013-11-12 11:10:57 +01004086 if (new_headset_mode == spec->current_headset_mode) {
4087 snd_hda_gen_update_outputs(codec);
David Henningsson73bdd592013-04-15 15:44:14 +02004088 return;
David Henningsson5959a6b2013-11-12 11:10:57 +01004089 }
David Henningsson73bdd592013-04-15 15:44:14 +02004090
4091 switch (new_headset_mode) {
4092 case ALC_HEADSET_MODE_UNPLUGGED:
4093 alc_headset_mode_unplugged(codec);
4094 spec->gen.hp_jack_present = false;
4095 break;
4096 case ALC_HEADSET_MODE_HEADSET:
4097 if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)
4098 alc_determine_headset_type(codec);
4099 if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)
4100 alc_headset_mode_ctia(codec);
4101 else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP)
4102 alc_headset_mode_omtp(codec);
4103 spec->gen.hp_jack_present = true;
4104 break;
4105 case ALC_HEADSET_MODE_MIC:
4106 alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin);
4107 spec->gen.hp_jack_present = false;
4108 break;
4109 case ALC_HEADSET_MODE_HEADPHONE:
4110 alc_headset_mode_default(codec);
4111 spec->gen.hp_jack_present = true;
4112 break;
4113 }
4114 if (new_headset_mode != ALC_HEADSET_MODE_MIC) {
4115 snd_hda_set_pin_ctl_cache(codec, hp_pin,
4116 AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
David Henningsson1f8b46c2015-05-12 14:38:15 +02004117 if (spec->headphone_mic_pin && spec->headphone_mic_pin != hp_pin)
David Henningsson73bdd592013-04-15 15:44:14 +02004118 snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin,
4119 PIN_VREFHIZ);
4120 }
4121 spec->current_headset_mode = new_headset_mode;
4122
4123 snd_hda_gen_update_outputs(codec);
4124}
4125
4126static void alc_update_headset_mode_hook(struct hda_codec *codec,
Takashi Iwai7fe30712014-01-30 17:59:02 +01004127 struct snd_kcontrol *kcontrol,
4128 struct snd_ctl_elem_value *ucontrol)
David Henningsson73bdd592013-04-15 15:44:14 +02004129{
4130 alc_update_headset_mode(codec);
4131}
4132
Takashi Iwai1a4f69d2014-09-11 15:22:46 +02004133static void alc_update_headset_jack_cb(struct hda_codec *codec,
4134 struct hda_jack_callback *jack)
David Henningsson73bdd592013-04-15 15:44:14 +02004135{
4136 struct alc_spec *spec = codec->spec;
David Henningsson5db4d342013-11-22 12:17:06 +01004137 spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
David Henningsson73bdd592013-04-15 15:44:14 +02004138 snd_hda_gen_hp_automute(codec, jack);
4139}
4140
4141static void alc_probe_headset_mode(struct hda_codec *codec)
4142{
4143 int i;
4144 struct alc_spec *spec = codec->spec;
4145 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
4146
4147 /* Find mic pins */
4148 for (i = 0; i < cfg->num_inputs; i++) {
4149 if (cfg->inputs[i].is_headset_mic && !spec->headset_mic_pin)
4150 spec->headset_mic_pin = cfg->inputs[i].pin;
4151 if (cfg->inputs[i].is_headphone_mic && !spec->headphone_mic_pin)
4152 spec->headphone_mic_pin = cfg->inputs[i].pin;
4153 }
4154
4155 spec->gen.cap_sync_hook = alc_update_headset_mode_hook;
4156 spec->gen.automute_hook = alc_update_headset_mode;
4157 spec->gen.hp_automute_hook = alc_update_headset_jack_cb;
4158}
4159
4160static void alc_fixup_headset_mode(struct hda_codec *codec,
4161 const struct hda_fixup *fix, int action)
4162{
4163 struct alc_spec *spec = codec->spec;
4164
4165 switch (action) {
4166 case HDA_FIXUP_ACT_PRE_PROBE:
4167 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC | HDA_PINCFG_HEADPHONE_MIC;
4168 break;
4169 case HDA_FIXUP_ACT_PROBE:
4170 alc_probe_headset_mode(codec);
4171 break;
4172 case HDA_FIXUP_ACT_INIT:
4173 spec->current_headset_mode = 0;
4174 alc_update_headset_mode(codec);
4175 break;
4176 }
4177}
4178
4179static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
4180 const struct hda_fixup *fix, int action)
4181{
4182 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4183 struct alc_spec *spec = codec->spec;
4184 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
4185 }
4186 else
4187 alc_fixup_headset_mode(codec, fix, action);
4188}
4189
Kailang Yang31278992014-03-03 15:27:22 +08004190static void alc255_set_default_jack_type(struct hda_codec *codec)
4191{
4192 /* Set to iphone type */
Takashi Iwai54db6c32014-08-18 15:11:19 +02004193 static struct coef_fw fw[] = {
4194 WRITE_COEF(0x1b, 0x880b),
4195 WRITE_COEF(0x45, 0xd089),
4196 WRITE_COEF(0x1b, 0x080b),
4197 WRITE_COEF(0x46, 0x0004),
4198 WRITE_COEF(0x1b, 0x0c0b),
4199 {}
4200 };
4201 alc_process_coef_fw(codec, fw);
Kailang Yang31278992014-03-03 15:27:22 +08004202 msleep(30);
4203}
4204
Kailang Yang9a22a8f2013-11-08 15:54:49 +08004205static void alc_fixup_headset_mode_alc255(struct hda_codec *codec,
4206 const struct hda_fixup *fix, int action)
4207{
4208 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Kailang Yang31278992014-03-03 15:27:22 +08004209 alc255_set_default_jack_type(codec);
Kailang Yang9a22a8f2013-11-08 15:54:49 +08004210 }
4211 alc_fixup_headset_mode(codec, fix, action);
4212}
4213
Kailang Yang31278992014-03-03 15:27:22 +08004214static void alc_fixup_headset_mode_alc255_no_hp_mic(struct hda_codec *codec,
4215 const struct hda_fixup *fix, int action)
4216{
4217 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4218 struct alc_spec *spec = codec->spec;
4219 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
4220 alc255_set_default_jack_type(codec);
4221 }
4222 else
4223 alc_fixup_headset_mode(codec, fix, action);
4224}
4225
Kailang Yange1e62b92015-04-08 16:01:22 +08004226static void alc288_update_headset_jack_cb(struct hda_codec *codec,
4227 struct hda_jack_callback *jack)
4228{
4229 struct alc_spec *spec = codec->spec;
4230 int present;
4231
4232 alc_update_headset_jack_cb(codec, jack);
4233 /* Headset Mic enable or disable, only for Dell Dino */
4234 present = spec->gen.hp_jack_present ? 0x40 : 0;
4235 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
4236 present);
4237}
4238
4239static void alc_fixup_headset_mode_dell_alc288(struct hda_codec *codec,
4240 const struct hda_fixup *fix, int action)
4241{
4242 alc_fixup_headset_mode(codec, fix, action);
4243 if (action == HDA_FIXUP_ACT_PROBE) {
4244 struct alc_spec *spec = codec->spec;
4245 spec->gen.hp_automute_hook = alc288_update_headset_jack_cb;
4246 }
4247}
4248
Hui Wang493a52a2014-01-14 14:07:36 +08004249static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
4250 const struct hda_fixup *fix, int action)
4251{
4252 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4253 struct alc_spec *spec = codec->spec;
4254 spec->gen.auto_mute_via_amp = 1;
4255 }
4256}
4257
Takashi Iwai9b745ab2014-03-07 08:37:19 +01004258static void alc_no_shutup(struct hda_codec *codec)
4259{
4260}
4261
4262static void alc_fixup_no_shutup(struct hda_codec *codec,
4263 const struct hda_fixup *fix, int action)
4264{
4265 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4266 struct alc_spec *spec = codec->spec;
4267 spec->shutup = alc_no_shutup;
4268 }
4269}
4270
Gabriele Mazzotta5e6db662014-05-20 18:58:26 +02004271static void alc_fixup_disable_aamix(struct hda_codec *codec,
4272 const struct hda_fixup *fix, int action)
4273{
4274 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4275 struct alc_spec *spec = codec->spec;
4276 /* Disable AA-loopback as it causes white noise */
4277 spec->gen.mixer_nid = 0;
4278 }
4279}
4280
Takashi Iwai7f57d802015-09-24 17:36:51 +02004281/* fixup for Thinkpad docks: add dock pins, avoid HP parser fixup */
4282static void alc_fixup_tpt440_dock(struct hda_codec *codec,
4283 const struct hda_fixup *fix, int action)
4284{
4285 static const struct hda_pintbl pincfgs[] = {
4286 { 0x16, 0x21211010 }, /* dock headphone */
4287 { 0x19, 0x21a11010 }, /* dock mic */
4288 { }
4289 };
4290 struct alc_spec *spec = codec->spec;
4291
4292 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwai157f0b72015-12-10 23:30:43 +01004293 spec->shutup = alc_no_shutup; /* reduce click noise */
Takashi Iwai70a09762015-12-15 14:59:58 +01004294 spec->reboot_notify = alc_d3_at_reboot; /* reduce noise */
Takashi Iwai7f57d802015-09-24 17:36:51 +02004295 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
4296 codec->power_save_node = 0; /* avoid click noises */
4297 snd_hda_apply_pincfgs(codec, pincfgs);
4298 }
4299}
4300
Gabriele Mazzotta9476d3692015-04-19 19:00:40 +02004301static void alc_shutup_dell_xps13(struct hda_codec *codec)
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02004302{
4303 struct alc_spec *spec = codec->spec;
Gabriele Mazzotta9476d3692015-04-19 19:00:40 +02004304 int hp_pin = spec->gen.autocfg.hp_pins[0];
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02004305
Gabriele Mazzotta9476d3692015-04-19 19:00:40 +02004306 /* Prevent pop noises when headphones are plugged in */
4307 snd_hda_codec_write(codec, hp_pin, 0,
4308 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
4309 msleep(20);
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02004310}
4311
4312static void alc_fixup_dell_xps13(struct hda_codec *codec,
4313 const struct hda_fixup *fix, int action)
4314{
Takashi Iwai3e1b0c42015-04-27 10:43:22 +02004315 struct alc_spec *spec = codec->spec;
4316 struct hda_input_mux *imux = &spec->gen.input_mux;
4317 int i;
Gabriele Mazzottaf38663a2014-08-08 19:34:40 +02004318
Takashi Iwai3e1b0c42015-04-27 10:43:22 +02004319 switch (action) {
4320 case HDA_FIXUP_ACT_PRE_PROBE:
4321 /* mic pin 0x19 must be initialized with Vref Hi-Z, otherwise
4322 * it causes a click noise at start up
4323 */
4324 snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
4325 break;
4326 case HDA_FIXUP_ACT_PROBE:
Gabriele Mazzotta9476d3692015-04-19 19:00:40 +02004327 spec->shutup = alc_shutup_dell_xps13;
Gabriele Mazzottaf38663a2014-08-08 19:34:40 +02004328
4329 /* Make the internal mic the default input source. */
4330 for (i = 0; i < imux->num_items; i++) {
4331 if (spec->gen.imux_pins[i] == 0x12) {
4332 spec->gen.cur_mux[0] = i;
4333 break;
4334 }
4335 }
Takashi Iwai3e1b0c42015-04-27 10:43:22 +02004336 break;
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02004337 }
4338}
4339
David Henningsson1f8b46c2015-05-12 14:38:15 +02004340static void alc_fixup_headset_mode_alc662(struct hda_codec *codec,
4341 const struct hda_fixup *fix, int action)
4342{
4343 struct alc_spec *spec = codec->spec;
4344
4345 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4346 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
4347 spec->gen.hp_mic = 1; /* Mic-in is same pin as headphone */
David Henningssonb40eda62015-05-28 09:40:23 +02004348
4349 /* Disable boost for mic-in permanently. (This code is only called
4350 from quirks that guarantee that the headphone is at NID 0x1b.) */
4351 snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000);
4352 snd_hda_override_wcaps(codec, 0x1b, get_wcaps(codec, 0x1b) & ~AC_WCAP_IN_AMP);
David Henningsson1f8b46c2015-05-12 14:38:15 +02004353 } else
4354 alc_fixup_headset_mode(codec, fix, action);
4355}
4356
David Henningsson73bdd592013-04-15 15:44:14 +02004357static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
4358 const struct hda_fixup *fix, int action)
4359{
4360 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
David Henningsson73bdd592013-04-15 15:44:14 +02004361 alc_write_coef_idx(codec, 0xc4, 0x8000);
Takashi Iwai98b24882014-08-18 13:47:50 +02004362 alc_update_coef_idx(codec, 0xc2, ~0xfe, 0);
David Henningsson73bdd592013-04-15 15:44:14 +02004363 snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
4364 }
4365 alc_fixup_headset_mode(codec, fix, action);
4366}
4367
Chih-Chung Changbde7bc62013-08-05 16:38:42 +08004368/* Returns the nid of the external mic input pin, or 0 if it cannot be found. */
4369static int find_ext_mic_pin(struct hda_codec *codec)
4370{
4371 struct alc_spec *spec = codec->spec;
4372 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
4373 hda_nid_t nid;
4374 unsigned int defcfg;
4375 int i;
4376
4377 for (i = 0; i < cfg->num_inputs; i++) {
4378 if (cfg->inputs[i].type != AUTO_PIN_MIC)
4379 continue;
4380 nid = cfg->inputs[i].pin;
4381 defcfg = snd_hda_codec_get_pincfg(codec, nid);
4382 if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
4383 continue;
4384 return nid;
4385 }
4386
4387 return 0;
4388}
4389
Dylan Reid08a978d2012-11-18 22:56:40 -08004390static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01004391 const struct hda_fixup *fix,
Dylan Reid08a978d2012-11-18 22:56:40 -08004392 int action)
4393{
4394 struct alc_spec *spec = codec->spec;
4395
Takashi Iwai0db75792013-01-23 13:57:20 +01004396 if (action == HDA_FIXUP_ACT_PROBE) {
Chih-Chung Changbde7bc62013-08-05 16:38:42 +08004397 int mic_pin = find_ext_mic_pin(codec);
4398 int hp_pin = spec->gen.autocfg.hp_pins[0];
4399
4400 if (snd_BUG_ON(!mic_pin || !hp_pin))
Takashi Iwai0db75792013-01-23 13:57:20 +01004401 return;
Chih-Chung Changbde7bc62013-08-05 16:38:42 +08004402 snd_hda_jack_set_gating_jack(codec, mic_pin, hp_pin);
Takashi Iwai0db75792013-01-23 13:57:20 +01004403 }
Dylan Reid08a978d2012-11-18 22:56:40 -08004404}
David Henningsson693b6132012-06-22 19:12:10 +02004405
David Henningsson3e0d6112013-04-22 14:30:14 +02004406static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec,
4407 const struct hda_fixup *fix,
4408 int action)
4409{
4410 struct alc_spec *spec = codec->spec;
4411 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
4412 int i;
4413
4414 /* The mic boosts on level 2 and 3 are too noisy
4415 on the internal mic input.
4416 Therefore limit the boost to 0 or 1. */
4417
4418 if (action != HDA_FIXUP_ACT_PROBE)
4419 return;
4420
4421 for (i = 0; i < cfg->num_inputs; i++) {
4422 hda_nid_t nid = cfg->inputs[i].pin;
4423 unsigned int defcfg;
4424 if (cfg->inputs[i].type != AUTO_PIN_MIC)
4425 continue;
4426 defcfg = snd_hda_codec_get_pincfg(codec, nid);
4427 if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
4428 continue;
4429
4430 snd_hda_override_amp_caps(codec, nid, HDA_INPUT,
4431 (0x00 << AC_AMPCAP_OFFSET_SHIFT) |
4432 (0x01 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4433 (0x2f << AC_AMPCAP_STEP_SIZE_SHIFT) |
4434 (0 << AC_AMPCAP_MUTE_SHIFT));
4435 }
4436}
4437
Kailang Yangcd217a62013-08-22 10:15:24 +02004438static void alc283_hp_automute_hook(struct hda_codec *codec,
Takashi Iwai1a4f69d2014-09-11 15:22:46 +02004439 struct hda_jack_callback *jack)
Kailang Yangcd217a62013-08-22 10:15:24 +02004440{
4441 struct alc_spec *spec = codec->spec;
4442 int vref;
4443
4444 msleep(200);
4445 snd_hda_gen_hp_automute(codec, jack);
4446
4447 vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
4448
4449 msleep(600);
4450 snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4451 vref);
4452}
4453
Kailang Yangcd217a62013-08-22 10:15:24 +02004454static void alc283_fixup_chromebook(struct hda_codec *codec,
4455 const struct hda_fixup *fix, int action)
4456{
4457 struct alc_spec *spec = codec->spec;
Kailang Yangcd217a62013-08-22 10:15:24 +02004458
4459 switch (action) {
4460 case HDA_FIXUP_ACT_PRE_PROBE:
Kailang Yang0202e992013-12-02 15:20:15 +08004461 snd_hda_override_wcaps(codec, 0x03, 0);
Takashi Iwaid2e92702013-10-30 07:50:53 +01004462 /* Disable AA-loopback as it causes white noise */
4463 spec->gen.mixer_nid = 0;
Kailang Yang38070212013-11-01 15:57:35 +08004464 break;
4465 case HDA_FIXUP_ACT_INIT:
Kailang Yangde9481c2014-04-07 16:41:52 +08004466 /* MIC2-VREF control */
4467 /* Set to manual mode */
Takashi Iwai98b24882014-08-18 13:47:50 +02004468 alc_update_coef_idx(codec, 0x06, 0x000c, 0);
Kailang Yang0202e992013-12-02 15:20:15 +08004469 /* Enable Line1 input control by verb */
Takashi Iwai98b24882014-08-18 13:47:50 +02004470 alc_update_coef_idx(codec, 0x1a, 0, 1 << 4);
Kailang Yang0202e992013-12-02 15:20:15 +08004471 break;
4472 }
4473}
4474
4475static void alc283_fixup_sense_combo_jack(struct hda_codec *codec,
4476 const struct hda_fixup *fix, int action)
4477{
4478 struct alc_spec *spec = codec->spec;
Kailang Yang0202e992013-12-02 15:20:15 +08004479
4480 switch (action) {
4481 case HDA_FIXUP_ACT_PRE_PROBE:
Kailang Yangcd217a62013-08-22 10:15:24 +02004482 spec->gen.hp_automute_hook = alc283_hp_automute_hook;
4483 break;
4484 case HDA_FIXUP_ACT_INIT:
4485 /* MIC2-VREF control */
4486 /* Set to manual mode */
Takashi Iwai98b24882014-08-18 13:47:50 +02004487 alc_update_coef_idx(codec, 0x06, 0x000c, 0);
Kailang Yangcd217a62013-08-22 10:15:24 +02004488 break;
4489 }
4490}
4491
Takashi Iwai7bba2152013-09-06 15:45:38 +02004492/* mute tablet speaker pin (0x14) via dock plugging in addition */
4493static void asus_tx300_automute(struct hda_codec *codec)
4494{
4495 struct alc_spec *spec = codec->spec;
4496 snd_hda_gen_update_outputs(codec);
4497 if (snd_hda_jack_detect(codec, 0x1b))
4498 spec->gen.mute_bits |= (1ULL << 0x14);
4499}
4500
4501static void alc282_fixup_asus_tx300(struct hda_codec *codec,
4502 const struct hda_fixup *fix, int action)
4503{
4504 struct alc_spec *spec = codec->spec;
4505 /* TX300 needs to set up GPIO2 for the speaker amp */
4506 static const struct hda_verb gpio2_verbs[] = {
4507 { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 },
4508 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 },
4509 { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 },
4510 {}
4511 };
4512 static const struct hda_pintbl dock_pins[] = {
4513 { 0x1b, 0x21114000 }, /* dock speaker pin */
4514 {}
4515 };
4516 struct snd_kcontrol *kctl;
4517
4518 switch (action) {
4519 case HDA_FIXUP_ACT_PRE_PROBE:
4520 snd_hda_add_verbs(codec, gpio2_verbs);
4521 snd_hda_apply_pincfgs(codec, dock_pins);
4522 spec->gen.auto_mute_via_amp = 1;
4523 spec->gen.automute_hook = asus_tx300_automute;
4524 snd_hda_jack_detect_enable_callback(codec, 0x1b,
Takashi Iwai7bba2152013-09-06 15:45:38 +02004525 snd_hda_gen_hp_automute);
4526 break;
4527 case HDA_FIXUP_ACT_BUILD:
4528 /* this is a bit tricky; give more sane names for the main
4529 * (tablet) speaker and the dock speaker, respectively
4530 */
4531 kctl = snd_hda_find_mixer_ctl(codec, "Speaker Playback Switch");
4532 if (kctl)
4533 strcpy(kctl->id.name, "Dock Speaker Playback Switch");
4534 kctl = snd_hda_find_mixer_ctl(codec, "Bass Speaker Playback Switch");
4535 if (kctl)
4536 strcpy(kctl->id.name, "Speaker Playback Switch");
4537 break;
4538 }
4539}
4540
David Henningsson338cae52013-10-07 10:39:59 +02004541static void alc290_fixup_mono_speakers(struct hda_codec *codec,
4542 const struct hda_fixup *fix, int action)
4543{
David Henningsson0f4881d2013-12-20 16:08:13 +01004544 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4545 /* DAC node 0x03 is giving mono output. We therefore want to
4546 make sure 0x14 (front speaker) and 0x15 (headphones) use the
4547 stereo DAC, while leaving 0x17 (bass speaker) for node 0x03. */
4548 hda_nid_t conn1[2] = { 0x0c };
4549 snd_hda_override_conn_list(codec, 0x14, 1, conn1);
4550 snd_hda_override_conn_list(codec, 0x15, 1, conn1);
4551 }
David Henningsson338cae52013-10-07 10:39:59 +02004552}
4553
Keith Packard98973f22015-07-15 12:14:39 -07004554/* Hook to update amp GPIO4 for automute */
4555static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec,
4556 struct hda_jack_callback *jack)
4557{
4558 struct alc_spec *spec = codec->spec;
4559
4560 snd_hda_gen_hp_automute(codec, jack);
4561 /* mute_led_polarity is set to 0, so we pass inverted value here */
4562 alc_update_gpio_led(codec, 0x10, !spec->gen.hp_jack_present);
4563}
4564
4565/* Manage GPIOs for HP EliteBook Folio 9480m.
4566 *
4567 * GPIO4 is the headphone amplifier power control
4568 * GPIO3 is the audio output mute indicator LED
4569 */
4570
4571static void alc280_fixup_hp_9480m(struct hda_codec *codec,
4572 const struct hda_fixup *fix,
4573 int action)
4574{
4575 struct alc_spec *spec = codec->spec;
4576 static const struct hda_verb gpio_init[] = {
4577 { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
4578 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
4579 {}
4580 };
4581
4582 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4583 /* Set the hooks to turn the headphone amp on/off
4584 * as needed
4585 */
4586 spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
4587 spec->gen.hp_automute_hook = alc280_hp_gpio4_automute_hook;
4588
4589 /* The GPIOs are currently off */
4590 spec->gpio_led = 0;
4591
4592 /* GPIO3 is connected to the output mute LED,
4593 * high is on, low is off
4594 */
4595 spec->mute_led_polarity = 0;
4596 spec->gpio_mute_led_mask = 0x08;
4597
4598 /* Initialize GPIO configuration */
4599 snd_hda_add_verbs(codec, gpio_init);
4600 }
4601}
4602
Takashi Iwaib317b032014-01-08 11:44:21 +01004603/* for hda_fixup_thinkpad_acpi() */
4604#include "thinkpad_helper.c"
David Henningssonb67ae3f2013-11-05 13:11:37 +01004605
Hui Wang00ef9942014-07-31 11:52:38 +08004606/* for dell wmi mic mute led */
4607#include "dell_wmi_helper.c"
4608
Takashi Iwai1d045db2011-07-07 18:23:21 +02004609enum {
4610 ALC269_FIXUP_SONY_VAIO,
4611 ALC275_FIXUP_SONY_VAIO_GPIO2,
4612 ALC269_FIXUP_DELL_M101Z,
4613 ALC269_FIXUP_SKU_IGNORE,
4614 ALC269_FIXUP_ASUS_G73JW,
4615 ALC269_FIXUP_LENOVO_EAPD,
4616 ALC275_FIXUP_SONY_HWEQ,
Takashi Iwaie9bd7d52014-05-21 11:06:49 +02004617 ALC275_FIXUP_SONY_DISABLE_AAMIX,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004618 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004619 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004620 ALC269_FIXUP_STEREO_DMIC,
David Henningsson7c478f02013-10-11 10:18:46 +02004621 ALC269_FIXUP_HEADSET_MIC,
Takashi Iwai24519912011-08-16 15:08:49 +02004622 ALC269_FIXUP_QUANTA_MUTE,
4623 ALC269_FIXUP_LIFEBOOK,
David Henningsson2041d562014-06-13 11:15:44 +02004624 ALC269_FIXUP_LIFEBOOK_EXTMIC,
Takashi Iwaicc7016a2015-04-08 20:47:55 +02004625 ALC269_FIXUP_LIFEBOOK_HP_PIN,
Takashi Iwai4df3fd12015-06-29 08:38:02 +02004626 ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT,
Takashi Iwaia4297b52011-08-23 18:40:12 +02004627 ALC269_FIXUP_AMIC,
4628 ALC269_FIXUP_DMIC,
4629 ALC269VB_FIXUP_AMIC,
4630 ALC269VB_FIXUP_DMIC,
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004631 ALC269_FIXUP_HP_MUTE_LED,
David Henningssond06ac142013-02-18 11:41:55 +01004632 ALC269_FIXUP_HP_MUTE_LED_MIC1,
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004633 ALC269_FIXUP_HP_MUTE_LED_MIC2,
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01004634 ALC269_FIXUP_HP_GPIO_LED,
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08004635 ALC269_FIXUP_HP_GPIO_MIC1_LED,
4636 ALC269_FIXUP_HP_LINE1_MIC1_LED,
David Henningsson693b6132012-06-22 19:12:10 +02004637 ALC269_FIXUP_INV_DMIC,
David Henningsson108cc102012-07-20 10:37:25 +02004638 ALC269_FIXUP_LENOVO_DOCK,
Takashi Iwai9b745ab2014-03-07 08:37:19 +01004639 ALC269_FIXUP_NO_SHUTUP,
David Henningsson88cfcf82013-10-11 10:18:45 +02004640 ALC286_FIXUP_SONY_MIC_NO_PRESENCE,
David Henningsson108cc102012-07-20 10:37:25 +02004641 ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
David Henningsson73bdd592013-04-15 15:44:14 +02004642 ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
4643 ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
David Henningsson338cae52013-10-07 10:39:59 +02004644 ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
David Henningsson73bdd592013-04-15 15:44:14 +02004645 ALC269_FIXUP_HEADSET_MODE,
4646 ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC,
Takashi Iwai78197172015-06-27 10:21:13 +02004647 ALC269_FIXUP_ASPIRE_HEADSET_MIC,
David Henningssond240d1d2013-04-15 12:50:02 +02004648 ALC269_FIXUP_ASUS_X101_FUNC,
4649 ALC269_FIXUP_ASUS_X101_VERB,
4650 ALC269_FIXUP_ASUS_X101,
Dylan Reid08a978d2012-11-18 22:56:40 -08004651 ALC271_FIXUP_AMIC_MIC2,
4652 ALC271_FIXUP_HP_GATE_MIC_JACK,
Oleksij Rempelb1e89722013-12-04 20:50:53 +01004653 ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572,
Dylan Reid42397002013-04-05 14:58:22 -07004654 ALC269_FIXUP_ACER_AC700,
David Henningsson3e0d6112013-04-22 14:30:14 +02004655 ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
Oleksij Rempel2cede302013-11-27 17:12:03 +01004656 ALC269VB_FIXUP_ASUS_ZENBOOK,
Takashi Iwai23870832013-11-29 14:13:12 +01004657 ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A,
David Henningsson8e35cd42013-11-06 11:20:01 +01004658 ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED,
Anisse Astier02b504d2013-06-03 11:53:10 +02004659 ALC269VB_FIXUP_ORDISSIMO_EVE2,
Kailang Yangcd217a62013-08-22 10:15:24 +02004660 ALC283_FIXUP_CHROME_BOOK,
Kailang Yang0202e992013-12-02 15:20:15 +08004661 ALC283_FIXUP_SENSE_COMBO_JACK,
Takashi Iwai7bba2152013-09-06 15:45:38 +02004662 ALC282_FIXUP_ASUS_TX300,
Kailang Yang1bb3e062013-09-27 13:10:25 +02004663 ALC283_FIXUP_INT_MIC,
David Henningsson338cae52013-10-07 10:39:59 +02004664 ALC290_FIXUP_MONO_SPEAKERS,
David Henningsson0f4881d2013-12-20 16:08:13 +01004665 ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
4666 ALC290_FIXUP_SUBWOOFER,
4667 ALC290_FIXUP_SUBWOOFER_HSJACK,
David Henningssonb67ae3f2013-11-05 13:11:37 +01004668 ALC269_FIXUP_THINKPAD_ACPI,
David Henningsson56f27012016-01-11 09:33:14 +01004669 ALC269_FIXUP_DMIC_THINKPAD_ACPI,
Kailang Yang9a22a8f2013-11-08 15:54:49 +08004670 ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
Kailang Yang31278992014-03-03 15:27:22 +08004671 ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
Kailang Yang9a22a8f2013-11-08 15:54:49 +08004672 ALC255_FIXUP_HEADSET_MODE,
Kailang Yang31278992014-03-03 15:27:22 +08004673 ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
Kailang Yanga22aa262014-04-23 17:34:28 +08004674 ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
Takashi Iwai1c37c222014-05-06 17:34:42 +02004675 ALC292_FIXUP_TPT440_DOCK,
Takashi Iwai9a811232015-12-09 15:17:43 +01004676 ALC292_FIXUP_TPT440,
Daniel Drake9dc12862014-07-22 10:58:29 +01004677 ALC283_FIXUP_BXBT2807_MIC,
Hui Wang00ef9942014-07-31 11:52:38 +08004678 ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
Takashi Iwai1a22e772014-08-27 08:19:05 +02004679 ALC282_FIXUP_ASPIRE_V5_PINS,
David Henningsson7a5255f2014-10-30 08:26:01 +01004680 ALC280_FIXUP_HP_GPIO4,
Kailang Yangeaa8e5e2014-11-21 15:49:11 +08004681 ALC286_FIXUP_HP_GPIO_LED,
David Henningsson33f4acd2015-01-07 15:50:13 +01004682 ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY,
TienFu Chenb4b33f92015-01-20 15:06:21 +01004683 ALC280_FIXUP_HP_DOCK_PINS,
Keith Packard98973f22015-07-15 12:14:39 -07004684 ALC280_FIXUP_HP_9480M,
Kailang Yange1e62b92015-04-08 16:01:22 +08004685 ALC288_FIXUP_DELL_HEADSET_MODE,
4686 ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
4687 ALC288_FIXUP_DELL_XPS_13_GPIO6,
Hui Wang831bfdf2015-06-26 12:35:17 +08004688 ALC288_FIXUP_DELL_XPS_13,
4689 ALC288_FIXUP_DISABLE_AAMIX,
Takashi Iwai8b99aba2015-06-15 11:59:32 +02004690 ALC292_FIXUP_DELL_E7X,
4691 ALC292_FIXUP_DISABLE_AAMIX,
David Henningssonc04017e2015-12-15 14:44:03 +01004692 ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK,
Kailang Yang977e6272015-05-18 15:31:20 +08004693 ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
Kailang Yang6ed11312015-10-26 15:37:39 +08004694 ALC275_FIXUP_DELL_XPS,
Hui Wang8c697292015-11-24 11:08:18 +08004695 ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
Hui Wang23adc192015-12-08 12:27:18 +08004696 ALC293_FIXUP_LENOVO_SPK_NOISE,
Kailang3694cb22015-12-28 11:35:24 +08004697 ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004698};
4699
Takashi Iwai1727a772013-01-10 09:52:52 +01004700static const struct hda_fixup alc269_fixups[] = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004701 [ALC269_FIXUP_SONY_VAIO] = {
Takashi Iwaifd108212013-01-10 10:18:14 +01004702 .type = HDA_FIXUP_PINCTLS,
4703 .v.pins = (const struct hda_pintbl[]) {
4704 {0x19, PIN_VREFGRD},
Takashi Iwai1d045db2011-07-07 18:23:21 +02004705 {}
4706 }
4707 },
4708 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004709 .type = HDA_FIXUP_VERBS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004710 .v.verbs = (const struct hda_verb[]) {
4711 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4712 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4713 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4714 { }
4715 },
4716 .chained = true,
4717 .chain_id = ALC269_FIXUP_SONY_VAIO
4718 },
4719 [ALC269_FIXUP_DELL_M101Z] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004720 .type = HDA_FIXUP_VERBS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004721 .v.verbs = (const struct hda_verb[]) {
4722 /* Enables internal speaker */
4723 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4724 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4725 {}
4726 }
4727 },
4728 [ALC269_FIXUP_SKU_IGNORE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004729 .type = HDA_FIXUP_FUNC,
Takashi Iwai23d30f22012-05-07 17:17:32 +02004730 .v.func = alc_fixup_sku_ignore,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004731 },
4732 [ALC269_FIXUP_ASUS_G73JW] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004733 .type = HDA_FIXUP_PINS,
4734 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004735 { 0x17, 0x99130111 }, /* subwoofer */
4736 { }
4737 }
4738 },
4739 [ALC269_FIXUP_LENOVO_EAPD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004740 .type = HDA_FIXUP_VERBS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004741 .v.verbs = (const struct hda_verb[]) {
4742 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4743 {}
4744 }
4745 },
4746 [ALC275_FIXUP_SONY_HWEQ] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004747 .type = HDA_FIXUP_FUNC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004748 .v.func = alc269_fixup_hweq,
4749 .chained = true,
4750 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4751 },
Takashi Iwaie9bd7d52014-05-21 11:06:49 +02004752 [ALC275_FIXUP_SONY_DISABLE_AAMIX] = {
4753 .type = HDA_FIXUP_FUNC,
4754 .v.func = alc_fixup_disable_aamix,
4755 .chained = true,
4756 .chain_id = ALC269_FIXUP_SONY_VAIO
4757 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004758 [ALC271_FIXUP_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004759 .type = HDA_FIXUP_FUNC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004760 .v.func = alc271_fixup_dmic,
4761 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02004762 [ALC269_FIXUP_PCM_44K] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004763 .type = HDA_FIXUP_FUNC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004764 .v.func = alc269_fixup_pcm_44k,
David Henningsson012e7eb2012-08-08 08:43:37 +02004765 .chained = true,
4766 .chain_id = ALC269_FIXUP_QUANTA_MUTE
Takashi Iwai017f2a12011-07-09 14:42:25 +02004767 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004768 [ALC269_FIXUP_STEREO_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004769 .type = HDA_FIXUP_FUNC,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004770 .v.func = alc269_fixup_stereo_dmic,
4771 },
David Henningsson7c478f02013-10-11 10:18:46 +02004772 [ALC269_FIXUP_HEADSET_MIC] = {
4773 .type = HDA_FIXUP_FUNC,
4774 .v.func = alc269_fixup_headset_mic,
4775 },
Takashi Iwai24519912011-08-16 15:08:49 +02004776 [ALC269_FIXUP_QUANTA_MUTE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004777 .type = HDA_FIXUP_FUNC,
Takashi Iwai24519912011-08-16 15:08:49 +02004778 .v.func = alc269_fixup_quanta_mute,
4779 },
4780 [ALC269_FIXUP_LIFEBOOK] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004781 .type = HDA_FIXUP_PINS,
4782 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai24519912011-08-16 15:08:49 +02004783 { 0x1a, 0x2101103f }, /* dock line-out */
4784 { 0x1b, 0x23a11040 }, /* dock mic-in */
4785 { }
4786 },
4787 .chained = true,
4788 .chain_id = ALC269_FIXUP_QUANTA_MUTE
4789 },
David Henningsson2041d562014-06-13 11:15:44 +02004790 [ALC269_FIXUP_LIFEBOOK_EXTMIC] = {
4791 .type = HDA_FIXUP_PINS,
4792 .v.pins = (const struct hda_pintbl[]) {
4793 { 0x19, 0x01a1903c }, /* headset mic, with jack detect */
4794 { }
4795 },
4796 },
Takashi Iwaicc7016a2015-04-08 20:47:55 +02004797 [ALC269_FIXUP_LIFEBOOK_HP_PIN] = {
4798 .type = HDA_FIXUP_PINS,
4799 .v.pins = (const struct hda_pintbl[]) {
4800 { 0x21, 0x0221102f }, /* HP out */
4801 { }
4802 },
4803 },
Takashi Iwai4df3fd12015-06-29 08:38:02 +02004804 [ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT] = {
4805 .type = HDA_FIXUP_FUNC,
4806 .v.func = alc269_fixup_pincfg_no_hp_to_lineout,
4807 },
Takashi Iwaia4297b52011-08-23 18:40:12 +02004808 [ALC269_FIXUP_AMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004809 .type = HDA_FIXUP_PINS,
4810 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaia4297b52011-08-23 18:40:12 +02004811 { 0x14, 0x99130110 }, /* speaker */
4812 { 0x15, 0x0121401f }, /* HP out */
4813 { 0x18, 0x01a19c20 }, /* mic */
4814 { 0x19, 0x99a3092f }, /* int-mic */
4815 { }
4816 },
4817 },
4818 [ALC269_FIXUP_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004819 .type = HDA_FIXUP_PINS,
4820 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaia4297b52011-08-23 18:40:12 +02004821 { 0x12, 0x99a3092f }, /* int-mic */
4822 { 0x14, 0x99130110 }, /* speaker */
4823 { 0x15, 0x0121401f }, /* HP out */
4824 { 0x18, 0x01a19c20 }, /* mic */
4825 { }
4826 },
4827 },
4828 [ALC269VB_FIXUP_AMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004829 .type = HDA_FIXUP_PINS,
4830 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaia4297b52011-08-23 18:40:12 +02004831 { 0x14, 0x99130110 }, /* speaker */
4832 { 0x18, 0x01a19c20 }, /* mic */
4833 { 0x19, 0x99a3092f }, /* int-mic */
4834 { 0x21, 0x0121401f }, /* HP out */
4835 { }
4836 },
4837 },
David Henningsson2267ea92012-01-03 08:45:56 +01004838 [ALC269VB_FIXUP_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004839 .type = HDA_FIXUP_PINS,
4840 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaia4297b52011-08-23 18:40:12 +02004841 { 0x12, 0x99a3092f }, /* int-mic */
4842 { 0x14, 0x99130110 }, /* speaker */
4843 { 0x18, 0x01a19c20 }, /* mic */
4844 { 0x21, 0x0121401f }, /* HP out */
4845 { }
4846 },
4847 },
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004848 [ALC269_FIXUP_HP_MUTE_LED] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004849 .type = HDA_FIXUP_FUNC,
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004850 .v.func = alc269_fixup_hp_mute_led,
David Henningsson6d3cd5d2013-01-07 12:03:47 +01004851 },
David Henningssond06ac142013-02-18 11:41:55 +01004852 [ALC269_FIXUP_HP_MUTE_LED_MIC1] = {
4853 .type = HDA_FIXUP_FUNC,
4854 .v.func = alc269_fixup_hp_mute_led_mic1,
4855 },
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004856 [ALC269_FIXUP_HP_MUTE_LED_MIC2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004857 .type = HDA_FIXUP_FUNC,
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004858 .v.func = alc269_fixup_hp_mute_led_mic2,
Takashi Iwai420b0fe2012-03-12 12:35:27 +01004859 },
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01004860 [ALC269_FIXUP_HP_GPIO_LED] = {
4861 .type = HDA_FIXUP_FUNC,
4862 .v.func = alc269_fixup_hp_gpio_led,
4863 },
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08004864 [ALC269_FIXUP_HP_GPIO_MIC1_LED] = {
4865 .type = HDA_FIXUP_FUNC,
4866 .v.func = alc269_fixup_hp_gpio_mic1_led,
4867 },
4868 [ALC269_FIXUP_HP_LINE1_MIC1_LED] = {
4869 .type = HDA_FIXUP_FUNC,
4870 .v.func = alc269_fixup_hp_line1_mic1_led,
4871 },
David Henningsson693b6132012-06-22 19:12:10 +02004872 [ALC269_FIXUP_INV_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004873 .type = HDA_FIXUP_FUNC,
David Henningsson9d36a7d2014-10-07 10:18:42 +02004874 .v.func = alc_fixup_inv_dmic,
David Henningsson693b6132012-06-22 19:12:10 +02004875 },
Takashi Iwai9b745ab2014-03-07 08:37:19 +01004876 [ALC269_FIXUP_NO_SHUTUP] = {
4877 .type = HDA_FIXUP_FUNC,
4878 .v.func = alc_fixup_no_shutup,
4879 },
David Henningsson108cc102012-07-20 10:37:25 +02004880 [ALC269_FIXUP_LENOVO_DOCK] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004881 .type = HDA_FIXUP_PINS,
4882 .v.pins = (const struct hda_pintbl[]) {
David Henningsson108cc102012-07-20 10:37:25 +02004883 { 0x19, 0x23a11040 }, /* dock mic */
4884 { 0x1b, 0x2121103f }, /* dock headphone */
4885 { }
4886 },
4887 .chained = true,
4888 .chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT
4889 },
4890 [ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004891 .type = HDA_FIXUP_FUNC,
David Henningsson108cc102012-07-20 10:37:25 +02004892 .v.func = alc269_fixup_pincfg_no_hp_to_lineout,
David Henningsson52129002013-11-19 10:25:53 +01004893 .chained = true,
4894 .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
David Henningsson108cc102012-07-20 10:37:25 +02004895 },
David Henningsson73bdd592013-04-15 15:44:14 +02004896 [ALC269_FIXUP_DELL1_MIC_NO_PRESENCE] = {
4897 .type = HDA_FIXUP_PINS,
4898 .v.pins = (const struct hda_pintbl[]) {
4899 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4900 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
4901 { }
4902 },
4903 .chained = true,
4904 .chain_id = ALC269_FIXUP_HEADSET_MODE
4905 },
4906 [ALC269_FIXUP_DELL2_MIC_NO_PRESENCE] = {
4907 .type = HDA_FIXUP_PINS,
4908 .v.pins = (const struct hda_pintbl[]) {
4909 { 0x16, 0x21014020 }, /* dock line out */
4910 { 0x19, 0x21a19030 }, /* dock mic */
4911 { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4912 { }
4913 },
4914 .chained = true,
4915 .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
4916 },
David Henningsson338cae52013-10-07 10:39:59 +02004917 [ALC269_FIXUP_DELL3_MIC_NO_PRESENCE] = {
4918 .type = HDA_FIXUP_PINS,
4919 .v.pins = (const struct hda_pintbl[]) {
4920 { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4921 { }
4922 },
4923 .chained = true,
4924 .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
4925 },
David Henningsson73bdd592013-04-15 15:44:14 +02004926 [ALC269_FIXUP_HEADSET_MODE] = {
4927 .type = HDA_FIXUP_FUNC,
4928 .v.func = alc_fixup_headset_mode,
Hui Wang6676f302014-11-18 17:57:41 +08004929 .chained = true,
4930 .chain_id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED
David Henningsson73bdd592013-04-15 15:44:14 +02004931 },
4932 [ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
4933 .type = HDA_FIXUP_FUNC,
4934 .v.func = alc_fixup_headset_mode_no_hp_mic,
4935 },
Takashi Iwai78197172015-06-27 10:21:13 +02004936 [ALC269_FIXUP_ASPIRE_HEADSET_MIC] = {
4937 .type = HDA_FIXUP_PINS,
4938 .v.pins = (const struct hda_pintbl[]) {
4939 { 0x19, 0x01a1913c }, /* headset mic w/o jack detect */
4940 { }
4941 },
4942 .chained = true,
4943 .chain_id = ALC269_FIXUP_HEADSET_MODE,
4944 },
David Henningsson88cfcf82013-10-11 10:18:45 +02004945 [ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = {
4946 .type = HDA_FIXUP_PINS,
4947 .v.pins = (const struct hda_pintbl[]) {
4948 { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4949 { }
4950 },
David Henningssonfbc78ad2013-10-11 13:46:04 +02004951 .chained = true,
4952 .chain_id = ALC269_FIXUP_HEADSET_MIC
David Henningsson88cfcf82013-10-11 10:18:45 +02004953 },
David Henningssond240d1d2013-04-15 12:50:02 +02004954 [ALC269_FIXUP_ASUS_X101_FUNC] = {
4955 .type = HDA_FIXUP_FUNC,
4956 .v.func = alc269_fixup_x101_headset_mic,
4957 },
4958 [ALC269_FIXUP_ASUS_X101_VERB] = {
4959 .type = HDA_FIXUP_VERBS,
4960 .v.verbs = (const struct hda_verb[]) {
4961 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4962 {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
4963 {0x20, AC_VERB_SET_PROC_COEF, 0x0310},
4964 { }
4965 },
4966 .chained = true,
4967 .chain_id = ALC269_FIXUP_ASUS_X101_FUNC
4968 },
4969 [ALC269_FIXUP_ASUS_X101] = {
4970 .type = HDA_FIXUP_PINS,
4971 .v.pins = (const struct hda_pintbl[]) {
4972 { 0x18, 0x04a1182c }, /* Headset mic */
4973 { }
4974 },
4975 .chained = true,
4976 .chain_id = ALC269_FIXUP_ASUS_X101_VERB
4977 },
Dylan Reid08a978d2012-11-18 22:56:40 -08004978 [ALC271_FIXUP_AMIC_MIC2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004979 .type = HDA_FIXUP_PINS,
4980 .v.pins = (const struct hda_pintbl[]) {
Dylan Reid08a978d2012-11-18 22:56:40 -08004981 { 0x14, 0x99130110 }, /* speaker */
4982 { 0x19, 0x01a19c20 }, /* mic */
4983 { 0x1b, 0x99a7012f }, /* int-mic */
4984 { 0x21, 0x0121401f }, /* HP out */
4985 { }
4986 },
4987 },
4988 [ALC271_FIXUP_HP_GATE_MIC_JACK] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004989 .type = HDA_FIXUP_FUNC,
Dylan Reid08a978d2012-11-18 22:56:40 -08004990 .v.func = alc271_hp_gate_mic_jack,
4991 .chained = true,
4992 .chain_id = ALC271_FIXUP_AMIC_MIC2,
4993 },
Oleksij Rempelb1e89722013-12-04 20:50:53 +01004994 [ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572] = {
4995 .type = HDA_FIXUP_FUNC,
4996 .v.func = alc269_fixup_limit_int_mic_boost,
4997 .chained = true,
4998 .chain_id = ALC271_FIXUP_HP_GATE_MIC_JACK,
4999 },
Dylan Reid42397002013-04-05 14:58:22 -07005000 [ALC269_FIXUP_ACER_AC700] = {
5001 .type = HDA_FIXUP_PINS,
5002 .v.pins = (const struct hda_pintbl[]) {
5003 { 0x12, 0x99a3092f }, /* int-mic */
5004 { 0x14, 0x99130110 }, /* speaker */
5005 { 0x18, 0x03a11c20 }, /* mic */
5006 { 0x1e, 0x0346101e }, /* SPDIF1 */
5007 { 0x21, 0x0321101f }, /* HP out */
5008 { }
5009 },
5010 .chained = true,
5011 .chain_id = ALC271_FIXUP_DMIC,
5012 },
David Henningsson3e0d6112013-04-22 14:30:14 +02005013 [ALC269_FIXUP_LIMIT_INT_MIC_BOOST] = {
5014 .type = HDA_FIXUP_FUNC,
5015 .v.func = alc269_fixup_limit_int_mic_boost,
David Henningsson27937692013-11-18 11:51:47 +01005016 .chained = true,
5017 .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
David Henningsson3e0d6112013-04-22 14:30:14 +02005018 },
Oleksij Rempel2cede302013-11-27 17:12:03 +01005019 [ALC269VB_FIXUP_ASUS_ZENBOOK] = {
5020 .type = HDA_FIXUP_FUNC,
5021 .v.func = alc269_fixup_limit_int_mic_boost,
5022 .chained = true,
5023 .chain_id = ALC269VB_FIXUP_DMIC,
5024 },
Takashi Iwai23870832013-11-29 14:13:12 +01005025 [ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A] = {
5026 .type = HDA_FIXUP_VERBS,
5027 .v.verbs = (const struct hda_verb[]) {
5028 /* class-D output amp +5dB */
5029 { 0x20, AC_VERB_SET_COEF_INDEX, 0x12 },
5030 { 0x20, AC_VERB_SET_PROC_COEF, 0x2800 },
5031 {}
5032 },
5033 .chained = true,
5034 .chain_id = ALC269VB_FIXUP_ASUS_ZENBOOK,
5035 },
David Henningsson8e35cd42013-11-06 11:20:01 +01005036 [ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED] = {
5037 .type = HDA_FIXUP_FUNC,
5038 .v.func = alc269_fixup_limit_int_mic_boost,
5039 .chained = true,
5040 .chain_id = ALC269_FIXUP_HP_MUTE_LED_MIC1,
5041 },
Anisse Astier02b504d2013-06-03 11:53:10 +02005042 [ALC269VB_FIXUP_ORDISSIMO_EVE2] = {
5043 .type = HDA_FIXUP_PINS,
5044 .v.pins = (const struct hda_pintbl[]) {
5045 { 0x12, 0x99a3092f }, /* int-mic */
5046 { 0x18, 0x03a11d20 }, /* mic */
5047 { 0x19, 0x411111f0 }, /* Unused bogus pin */
5048 { }
5049 },
5050 },
Kailang Yangcd217a62013-08-22 10:15:24 +02005051 [ALC283_FIXUP_CHROME_BOOK] = {
5052 .type = HDA_FIXUP_FUNC,
5053 .v.func = alc283_fixup_chromebook,
5054 },
Kailang Yang0202e992013-12-02 15:20:15 +08005055 [ALC283_FIXUP_SENSE_COMBO_JACK] = {
5056 .type = HDA_FIXUP_FUNC,
5057 .v.func = alc283_fixup_sense_combo_jack,
5058 .chained = true,
5059 .chain_id = ALC283_FIXUP_CHROME_BOOK,
5060 },
Takashi Iwai7bba2152013-09-06 15:45:38 +02005061 [ALC282_FIXUP_ASUS_TX300] = {
5062 .type = HDA_FIXUP_FUNC,
5063 .v.func = alc282_fixup_asus_tx300,
5064 },
Kailang Yang1bb3e062013-09-27 13:10:25 +02005065 [ALC283_FIXUP_INT_MIC] = {
5066 .type = HDA_FIXUP_VERBS,
5067 .v.verbs = (const struct hda_verb[]) {
5068 {0x20, AC_VERB_SET_COEF_INDEX, 0x1a},
5069 {0x20, AC_VERB_SET_PROC_COEF, 0x0011},
5070 { }
5071 },
5072 .chained = true,
5073 .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
5074 },
David Henningsson0f4881d2013-12-20 16:08:13 +01005075 [ALC290_FIXUP_SUBWOOFER_HSJACK] = {
5076 .type = HDA_FIXUP_PINS,
5077 .v.pins = (const struct hda_pintbl[]) {
5078 { 0x17, 0x90170112 }, /* subwoofer */
5079 { }
5080 },
5081 .chained = true,
5082 .chain_id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
5083 },
5084 [ALC290_FIXUP_SUBWOOFER] = {
5085 .type = HDA_FIXUP_PINS,
5086 .v.pins = (const struct hda_pintbl[]) {
5087 { 0x17, 0x90170112 }, /* subwoofer */
5088 { }
5089 },
5090 .chained = true,
5091 .chain_id = ALC290_FIXUP_MONO_SPEAKERS,
5092 },
David Henningsson338cae52013-10-07 10:39:59 +02005093 [ALC290_FIXUP_MONO_SPEAKERS] = {
5094 .type = HDA_FIXUP_FUNC,
5095 .v.func = alc290_fixup_mono_speakers,
David Henningsson0f4881d2013-12-20 16:08:13 +01005096 },
5097 [ALC290_FIXUP_MONO_SPEAKERS_HSJACK] = {
5098 .type = HDA_FIXUP_FUNC,
5099 .v.func = alc290_fixup_mono_speakers,
David Henningsson338cae52013-10-07 10:39:59 +02005100 .chained = true,
5101 .chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
5102 },
David Henningssonb67ae3f2013-11-05 13:11:37 +01005103 [ALC269_FIXUP_THINKPAD_ACPI] = {
5104 .type = HDA_FIXUP_FUNC,
Takashi Iwaib317b032014-01-08 11:44:21 +01005105 .v.func = hda_fixup_thinkpad_acpi,
David Henningssonb67ae3f2013-11-05 13:11:37 +01005106 },
David Henningsson56f27012016-01-11 09:33:14 +01005107 [ALC269_FIXUP_DMIC_THINKPAD_ACPI] = {
5108 .type = HDA_FIXUP_FUNC,
5109 .v.func = alc_fixup_inv_dmic,
5110 .chained = true,
5111 .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
5112 },
Kailang Yang9a22a8f2013-11-08 15:54:49 +08005113 [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
5114 .type = HDA_FIXUP_PINS,
5115 .v.pins = (const struct hda_pintbl[]) {
5116 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
5117 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
5118 { }
5119 },
5120 .chained = true,
5121 .chain_id = ALC255_FIXUP_HEADSET_MODE
5122 },
Kailang Yang31278992014-03-03 15:27:22 +08005123 [ALC255_FIXUP_DELL2_MIC_NO_PRESENCE] = {
5124 .type = HDA_FIXUP_PINS,
5125 .v.pins = (const struct hda_pintbl[]) {
5126 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
5127 { }
5128 },
5129 .chained = true,
5130 .chain_id = ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC
5131 },
Kailang Yang9a22a8f2013-11-08 15:54:49 +08005132 [ALC255_FIXUP_HEADSET_MODE] = {
5133 .type = HDA_FIXUP_FUNC,
5134 .v.func = alc_fixup_headset_mode_alc255,
Hui Wang4a83d422014-11-18 17:57:40 +08005135 .chained = true,
5136 .chain_id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED
Kailang Yang9a22a8f2013-11-08 15:54:49 +08005137 },
Kailang Yang31278992014-03-03 15:27:22 +08005138 [ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
5139 .type = HDA_FIXUP_FUNC,
5140 .v.func = alc_fixup_headset_mode_alc255_no_hp_mic,
5141 },
Kailang Yanga22aa262014-04-23 17:34:28 +08005142 [ALC293_FIXUP_DELL1_MIC_NO_PRESENCE] = {
5143 .type = HDA_FIXUP_PINS,
5144 .v.pins = (const struct hda_pintbl[]) {
5145 { 0x18, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
5146 { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
5147 { }
5148 },
5149 .chained = true,
5150 .chain_id = ALC269_FIXUP_HEADSET_MODE
5151 },
Takashi Iwai1c37c222014-05-06 17:34:42 +02005152 [ALC292_FIXUP_TPT440_DOCK] = {
David Henningssonec56af62015-06-24 10:46:33 +02005153 .type = HDA_FIXUP_FUNC,
Takashi Iwai7f57d802015-09-24 17:36:51 +02005154 .v.func = alc_fixup_tpt440_dock,
Takashi Iwai1c37c222014-05-06 17:34:42 +02005155 .chained = true,
5156 .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
5157 },
Takashi Iwai9a811232015-12-09 15:17:43 +01005158 [ALC292_FIXUP_TPT440] = {
5159 .type = HDA_FIXUP_FUNC,
Takashi Iwai157f0b72015-12-10 23:30:43 +01005160 .v.func = alc_fixup_disable_aamix,
Takashi Iwai9a811232015-12-09 15:17:43 +01005161 .chained = true,
5162 .chain_id = ALC292_FIXUP_TPT440_DOCK,
5163 },
Daniel Drake9dc12862014-07-22 10:58:29 +01005164 [ALC283_FIXUP_BXBT2807_MIC] = {
5165 .type = HDA_FIXUP_PINS,
5166 .v.pins = (const struct hda_pintbl[]) {
5167 { 0x19, 0x04a110f0 },
5168 { },
5169 },
5170 },
Hui Wang00ef9942014-07-31 11:52:38 +08005171 [ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = {
5172 .type = HDA_FIXUP_FUNC,
5173 .v.func = alc_fixup_dell_wmi,
Hui Wang00ef9942014-07-31 11:52:38 +08005174 },
Takashi Iwai1a22e772014-08-27 08:19:05 +02005175 [ALC282_FIXUP_ASPIRE_V5_PINS] = {
5176 .type = HDA_FIXUP_PINS,
5177 .v.pins = (const struct hda_pintbl[]) {
5178 { 0x12, 0x90a60130 },
5179 { 0x14, 0x90170110 },
5180 { 0x17, 0x40000008 },
5181 { 0x18, 0x411111f0 },
Mateusz Sylwestrzak04206942015-07-19 17:38:56 +02005182 { 0x19, 0x01a1913c },
Takashi Iwai1a22e772014-08-27 08:19:05 +02005183 { 0x1a, 0x411111f0 },
5184 { 0x1b, 0x411111f0 },
5185 { 0x1d, 0x40f89b2d },
5186 { 0x1e, 0x411111f0 },
5187 { 0x21, 0x0321101f },
5188 { },
5189 },
5190 },
David Henningsson7a5255f2014-10-30 08:26:01 +01005191 [ALC280_FIXUP_HP_GPIO4] = {
5192 .type = HDA_FIXUP_FUNC,
5193 .v.func = alc280_fixup_hp_gpio4,
5194 },
Kailang Yangeaa8e5e2014-11-21 15:49:11 +08005195 [ALC286_FIXUP_HP_GPIO_LED] = {
5196 .type = HDA_FIXUP_FUNC,
5197 .v.func = alc286_fixup_hp_gpio_led,
5198 },
David Henningsson33f4acd2015-01-07 15:50:13 +01005199 [ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY] = {
5200 .type = HDA_FIXUP_FUNC,
5201 .v.func = alc280_fixup_hp_gpio2_mic_hotkey,
5202 },
TienFu Chenb4b33f92015-01-20 15:06:21 +01005203 [ALC280_FIXUP_HP_DOCK_PINS] = {
5204 .type = HDA_FIXUP_PINS,
5205 .v.pins = (const struct hda_pintbl[]) {
5206 { 0x1b, 0x21011020 }, /* line-out */
5207 { 0x1a, 0x01a1903c }, /* headset mic */
5208 { 0x18, 0x2181103f }, /* line-in */
5209 { },
5210 },
5211 .chained = true,
5212 .chain_id = ALC280_FIXUP_HP_GPIO4
5213 },
Keith Packard98973f22015-07-15 12:14:39 -07005214 [ALC280_FIXUP_HP_9480M] = {
5215 .type = HDA_FIXUP_FUNC,
5216 .v.func = alc280_fixup_hp_9480m,
5217 },
Kailang Yange1e62b92015-04-08 16:01:22 +08005218 [ALC288_FIXUP_DELL_HEADSET_MODE] = {
5219 .type = HDA_FIXUP_FUNC,
5220 .v.func = alc_fixup_headset_mode_dell_alc288,
5221 .chained = true,
5222 .chain_id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED
5223 },
5224 [ALC288_FIXUP_DELL1_MIC_NO_PRESENCE] = {
5225 .type = HDA_FIXUP_PINS,
5226 .v.pins = (const struct hda_pintbl[]) {
5227 { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
5228 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
5229 { }
5230 },
5231 .chained = true,
5232 .chain_id = ALC288_FIXUP_DELL_HEADSET_MODE
5233 },
5234 [ALC288_FIXUP_DELL_XPS_13_GPIO6] = {
5235 .type = HDA_FIXUP_VERBS,
5236 .v.verbs = (const struct hda_verb[]) {
5237 {0x01, AC_VERB_SET_GPIO_MASK, 0x40},
5238 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x40},
5239 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
5240 { }
5241 },
5242 .chained = true,
5243 .chain_id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE
5244 },
Hui Wang831bfdf2015-06-26 12:35:17 +08005245 [ALC288_FIXUP_DISABLE_AAMIX] = {
5246 .type = HDA_FIXUP_FUNC,
5247 .v.func = alc_fixup_disable_aamix,
5248 .chained = true,
5249 .chain_id = ALC288_FIXUP_DELL_XPS_13_GPIO6
5250 },
5251 [ALC288_FIXUP_DELL_XPS_13] = {
5252 .type = HDA_FIXUP_FUNC,
5253 .v.func = alc_fixup_dell_xps13,
5254 .chained = true,
5255 .chain_id = ALC288_FIXUP_DISABLE_AAMIX
5256 },
Takashi Iwai8b99aba2015-06-15 11:59:32 +02005257 [ALC292_FIXUP_DISABLE_AAMIX] = {
5258 .type = HDA_FIXUP_FUNC,
5259 .v.func = alc_fixup_disable_aamix,
Hui Wang831bfdf2015-06-26 12:35:17 +08005260 .chained = true,
5261 .chain_id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE
Takashi Iwai8b99aba2015-06-15 11:59:32 +02005262 },
David Henningssonc04017e2015-12-15 14:44:03 +01005263 [ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK] = {
5264 .type = HDA_FIXUP_FUNC,
5265 .v.func = alc_fixup_disable_aamix,
5266 .chained = true,
5267 .chain_id = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE
5268 },
Takashi Iwai8b99aba2015-06-15 11:59:32 +02005269 [ALC292_FIXUP_DELL_E7X] = {
5270 .type = HDA_FIXUP_FUNC,
5271 .v.func = alc_fixup_dell_xps13,
5272 .chained = true,
5273 .chain_id = ALC292_FIXUP_DISABLE_AAMIX
5274 },
Kailang Yang977e6272015-05-18 15:31:20 +08005275 [ALC298_FIXUP_DELL1_MIC_NO_PRESENCE] = {
5276 .type = HDA_FIXUP_PINS,
5277 .v.pins = (const struct hda_pintbl[]) {
5278 { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
5279 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
5280 { }
5281 },
5282 .chained = true,
5283 .chain_id = ALC269_FIXUP_HEADSET_MODE
5284 },
Kailang Yang6ed11312015-10-26 15:37:39 +08005285 [ALC275_FIXUP_DELL_XPS] = {
5286 .type = HDA_FIXUP_VERBS,
5287 .v.verbs = (const struct hda_verb[]) {
5288 /* Enables internal speaker */
5289 {0x20, AC_VERB_SET_COEF_INDEX, 0x1f},
5290 {0x20, AC_VERB_SET_PROC_COEF, 0x00c0},
5291 {0x20, AC_VERB_SET_COEF_INDEX, 0x30},
5292 {0x20, AC_VERB_SET_PROC_COEF, 0x00b1},
5293 {}
5294 }
5295 },
Hui Wang8c697292015-11-24 11:08:18 +08005296 [ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE] = {
5297 .type = HDA_FIXUP_VERBS,
5298 .v.verbs = (const struct hda_verb[]) {
5299 /* Disable pass-through path for FRONT 14h */
5300 {0x20, AC_VERB_SET_COEF_INDEX, 0x36},
5301 {0x20, AC_VERB_SET_PROC_COEF, 0x1737},
5302 {}
5303 },
5304 .chained = true,
5305 .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
5306 },
Hui Wang23adc192015-12-08 12:27:18 +08005307 [ALC293_FIXUP_LENOVO_SPK_NOISE] = {
5308 .type = HDA_FIXUP_FUNC,
5309 .v.func = alc_fixup_disable_aamix,
5310 .chained = true,
5311 .chain_id = ALC269_FIXUP_THINKPAD_ACPI
5312 },
Kailang3694cb22015-12-28 11:35:24 +08005313 [ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY] = {
5314 .type = HDA_FIXUP_FUNC,
5315 .v.func = alc233_fixup_lenovo_line2_mic_hotkey,
5316 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02005317};
5318
5319static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Marius Knausta6b92b62014-03-03 01:48:58 +01005320 SND_PCI_QUIRK(0x1025, 0x0283, "Acer TravelMate 8371", ALC269_FIXUP_INV_DMIC),
David Henningsson693b6132012-06-22 19:12:10 +02005321 SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
5322 SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
David Henningssonaaedfb42013-08-16 14:09:02 +02005323 SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
Takashi Iwai78197172015-06-27 10:21:13 +02005324 SND_PCI_QUIRK(0x1025, 0x072d, "Acer Aspire V5-571G", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
5325 SND_PCI_QUIRK(0x1025, 0x080d, "Acer Aspire V5-122P", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
David Henningssonaaedfb42013-08-16 14:09:02 +02005326 SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
5327 SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
Oleksij Rempelb1e89722013-12-04 20:50:53 +01005328 SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
Takashi Iwai1a22e772014-08-27 08:19:05 +02005329 SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
Takashi Iwaib9c2fa52015-11-19 16:39:50 +01005330 SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
David Henningssonaaedfb42013-08-16 14:09:02 +02005331 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
Kailang Yang6ed11312015-10-26 15:37:39 +08005332 SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
Takashi Iwai86f799b2015-11-14 17:46:31 +01005333 SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X),
Takashi Iwai8b99aba2015-06-15 11:59:32 +02005334 SND_PCI_QUIRK(0x1028, 0x05ca, "Dell Latitude E7240", ALC292_FIXUP_DELL_E7X),
5335 SND_PCI_QUIRK(0x1028, 0x05cb, "Dell Latitude E7440", ALC292_FIXUP_DELL_E7X),
David Henningsson0f4881d2013-12-20 16:08:13 +01005336 SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
David Henningsson73bdd592013-04-15 15:44:14 +02005337 SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
5338 SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
5339 SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
David Henningsson0f4881d2013-12-20 16:08:13 +01005340 SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
5341 SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
Takashi Iwai98070572016-01-12 21:06:39 +01005342 SND_PCI_QUIRK(0x1028, 0x062c, "Dell Latitude E5550", ALC292_FIXUP_DELL_E7X),
Takashi Iwai42755542015-06-29 10:56:53 +02005343 SND_PCI_QUIRK(0x1028, 0x062e, "Dell Latitude E7450", ALC292_FIXUP_DELL_E7X),
David Henningsson0f4881d2013-12-20 16:08:13 +01005344 SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
Kailang Yanga22aa262014-04-23 17:34:28 +08005345 SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
5346 SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
Hui Wang831bfdf2015-06-26 12:35:17 +08005347 SND_PCI_QUIRK(0x1028, 0x0665, "Dell XPS 13", ALC288_FIXUP_DELL_XPS_13),
Takashi Iwai3a05d122015-07-29 09:04:52 +02005348 SND_PCI_QUIRK(0x1028, 0x069a, "Dell Vostro 5480", ALC290_FIXUP_SUBWOOFER_HSJACK),
Kailang Yang8b724152014-12-17 17:08:59 +08005349 SND_PCI_QUIRK(0x1028, 0x06c7, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
Kailang Yangb7343042014-12-02 14:50:45 +08005350 SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
5351 SND_PCI_QUIRK(0x1028, 0x06da, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
David Henningssonc04017e2015-12-15 14:44:03 +01005352 SND_PCI_QUIRK(0x1028, 0x06db, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
5353 SND_PCI_QUIRK(0x1028, 0x06dd, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
5354 SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
5355 SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
5356 SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
Hui Wang8c697292015-11-24 11:08:18 +08005357 SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
Kailang Yanga22aa262014-04-23 17:34:28 +08005358 SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
5359 SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
Takashi Iwai08fb0d02013-01-10 17:33:58 +01005360 SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01005361 SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
David Henningsson8e35cd42013-11-06 11:20:01 +01005362 SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
David Henningsson33f4acd2015-01-07 15:50:13 +01005363 SND_PCI_QUIRK(0x103c, 0x225f, "HP", ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY),
Kailang Yangc60666b2014-02-21 16:23:35 +08005364 /* ALC282 */
Hui Wang7976eb42015-02-13 11:14:41 +08005365 SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang8a02b162014-06-13 17:16:31 +08005366 SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang8a02b162014-06-13 17:16:31 +08005367 SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005368 SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
5369 SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
5370 SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
5371 SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005372 SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
Kailang Yangc60666b2014-02-21 16:23:35 +08005373 SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08005374 SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5375 SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang8a02b162014-06-13 17:16:31 +08005376 SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangeaa8e5e2014-11-21 15:49:11 +08005377 SND_PCI_QUIRK(0x103c, 0x2271, "HP", ALC286_FIXUP_HP_GPIO_LED),
TienFu Chenb4b33f92015-01-20 15:06:21 +01005378 SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC280_FIXUP_HP_DOCK_PINS),
TienFu Chen3271cb22015-02-10 09:09:41 +01005379 SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC280_FIXUP_HP_DOCK_PINS),
Kailang Yangc60666b2014-02-21 16:23:35 +08005380 SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08005381 SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5382 SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5383 SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08005384 SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Keith Packard98973f22015-07-15 12:14:39 -07005385 SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC280_FIXUP_HP_9480M),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005386 SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5387 SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yangc60666b2014-02-21 16:23:35 +08005388 /* ALC290 */
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005389 SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005390 SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005391 SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005392 SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5393 SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5394 SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5395 SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5396 SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005397 SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5398 SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yangc60666b2014-02-21 16:23:35 +08005399 SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08005400 SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5401 SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5402 SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005403 SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5404 SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005405 SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yangc60666b2014-02-21 16:23:35 +08005406 SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08005407 SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08005408 SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08005409 SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5410 SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08005411 SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5412 SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08005413 SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang8a02b162014-06-13 17:16:31 +08005414 SND_PCI_QUIRK(0x103c, 0x2334, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5415 SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5416 SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5417 SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Takashi Iwai7bba2152013-09-06 15:45:38 +02005418 SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
David Henningsson3e0d6112013-04-22 14:30:14 +02005419 SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
5420 SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
Oleksij Rempel2cede302013-11-27 17:12:03 +01005421 SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
Takashi Iwai23870832013-11-29 14:13:12 +01005422 SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
David Henningsson3e0d6112013-04-22 14:30:14 +02005423 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai017f2a12011-07-09 14:42:25 +02005424 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
David Henningsson693b6132012-06-22 19:12:10 +02005425 SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
David Henningsson3e0d6112013-04-22 14:30:14 +02005426 SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02005427 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
5428 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
5429 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
5430 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
David Henningssond240d1d2013-04-15 12:50:02 +02005431 SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
Takashi Iwaif88abaa2014-02-07 12:07:59 +01005432 SND_PCI_QUIRK(0x104d, 0x90b5, "Sony VAIO Pro 11", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
David Henningsson88cfcf82013-10-11 10:18:45 +02005433 SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005434 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
5435 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
5436 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
Takashi Iwaie9bd7d52014-05-21 11:06:49 +02005437 SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX),
Takashi Iwai24519912011-08-16 15:08:49 +02005438 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
Takashi Iwai4df3fd12015-06-29 08:38:02 +02005439 SND_PCI_QUIRK(0x10cf, 0x159f, "Lifebook E780", ALC269_FIXUP_LIFEBOOK_NO_HP_TO_LINEOUT),
Takashi Iwaicc7016a2015-04-08 20:47:55 +02005440 SND_PCI_QUIRK(0x10cf, 0x15dc, "Lifebook T731", ALC269_FIXUP_LIFEBOOK_HP_PIN),
Takashi Iwai88776f32015-05-01 09:20:34 +02005441 SND_PCI_QUIRK(0x10cf, 0x1757, "Lifebook E752", ALC269_FIXUP_LIFEBOOK_HP_PIN),
David Henningsson2041d562014-06-13 11:15:44 +02005442 SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
David Henningssona33cc482014-10-07 10:18:41 +02005443 SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
Daniel Drake9dc12862014-07-22 10:58:29 +01005444 SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005445 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
5446 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
5447 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
5448 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
5449 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai707fba32012-08-02 09:04:39 +02005450 SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),
Felix Kaechelec8415a42012-08-06 23:02:01 +02005451 SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
Stefán Freyr84f98fd2012-10-19 22:46:00 +02005452 SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
Philipp A. Mohrenweiser4407be62012-08-06 13:14:18 +02005453 SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
David Henningsson108cc102012-07-20 10:37:25 +02005454 SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
David Henningssonaaedfb42013-08-16 14:09:02 +02005455 SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
Takashi Iwai9a811232015-12-09 15:17:43 +01005456 SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440),
Takashi Iwai1c37c222014-05-06 17:34:42 +02005457 SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
Takashi Iwaia12137e2014-06-27 12:14:35 +02005458 SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
Rick Sherman59a51a62015-08-18 21:04:30 -05005459 SND_PCI_QUIRK(0x17aa, 0x2211, "Thinkpad W541", ALC292_FIXUP_TPT440_DOCK),
Takashi Iwai6d169412014-10-07 17:27:02 +02005460 SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
Lukas Bossard7c215392014-10-29 18:31:07 +01005461 SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
David Henningssona4a9e082013-08-16 14:09:01 +02005462 SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
Takashi Iwaib6903c02015-12-10 12:20:20 +01005463 SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
Laura Abbottd05ea7d2015-10-02 11:09:54 -07005464 SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
Yves-Alexis Perezc0278662015-04-11 09:31:35 +02005465 SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
Hui Wang23adc192015-12-08 12:27:18 +08005466 SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
Kailang3694cb22015-12-28 11:35:24 +08005467 SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
David Henningsson56f27012016-01-11 09:33:14 +01005468 SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
Takashi Iwaifedb2242014-11-13 07:11:38 +01005469 SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
Takashi Iwai9b745ab2014-03-07 08:37:19 +01005470 SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
David Henningssona4a9e082013-08-16 14:09:01 +02005471 SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
Kailang Yang1bb3e062013-09-27 13:10:25 +02005472 SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
Takashi Iwaic497d9f2014-10-08 12:14:40 +02005473 SND_PCI_QUIRK(0x17aa, 0x501e, "Thinkpad L440", ALC292_FIXUP_TPT440_DOCK),
David Henningssoncd5302c2013-08-19 12:22:33 +02005474 SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
Jo-Philipp Wichf2aa1112015-04-13 12:47:26 +02005475 SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK),
Sebastian Wicki80b311d2015-03-23 17:23:11 +01005476 SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK),
Ansgar Hegerfeld09ea9972015-05-14 12:31:32 +02005477 SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
Hui Wang23adc192015-12-08 12:27:18 +08005478 SND_PCI_QUIRK(0x17aa, 0x504b, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
David Henningssoncd5302c2013-08-19 12:22:33 +02005479 SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
David Henningsson012e7eb2012-08-08 08:43:37 +02005480 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005481 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
Anisse Astier02b504d2013-06-03 11:53:10 +02005482 SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
Takashi Iwaia4297b52011-08-23 18:40:12 +02005483
Takashi Iwaia7f3eed2012-02-16 13:03:18 +01005484#if 0
Takashi Iwaia4297b52011-08-23 18:40:12 +02005485 /* Below is a quirk table taken from the old code.
5486 * Basically the device should work as is without the fixup table.
5487 * If BIOS doesn't give a proper info, enable the corresponding
5488 * fixup entry.
Jesper Juhl7d7eb9e2012-04-12 22:11:25 +02005489 */
Takashi Iwaia4297b52011-08-23 18:40:12 +02005490 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
5491 ALC269_FIXUP_AMIC),
5492 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
Takashi Iwaia4297b52011-08-23 18:40:12 +02005493 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
5494 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
5495 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
5496 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269_FIXUP_AMIC),
5497 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269_FIXUP_AMIC),
5498 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269_FIXUP_AMIC),
5499 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_FIXUP_AMIC),
5500 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269_FIXUP_AMIC),
5501 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_FIXUP_AMIC),
5502 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_FIXUP_AMIC),
5503 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_FIXUP_AMIC),
5504 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_FIXUP_AMIC),
5505 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_FIXUP_AMIC),
5506 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_FIXUP_AMIC),
5507 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_FIXUP_AMIC),
5508 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_FIXUP_AMIC),
5509 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_FIXUP_AMIC),
5510 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_FIXUP_AMIC),
5511 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_FIXUP_AMIC),
5512 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_FIXUP_AMIC),
5513 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_FIXUP_AMIC),
5514 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_FIXUP_AMIC),
5515 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_FIXUP_AMIC),
5516 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_FIXUP_AMIC),
5517 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_FIXUP_AMIC),
5518 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_FIXUP_AMIC),
5519 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_FIXUP_AMIC),
5520 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_FIXUP_AMIC),
5521 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_FIXUP_AMIC),
5522 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_FIXUP_AMIC),
5523 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_FIXUP_AMIC),
5524 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_FIXUP_AMIC),
5525 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_FIXUP_AMIC),
5526 SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_FIXUP_DMIC),
5527 SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_FIXUP_AMIC),
5528 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_AMIC),
5529 SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_FIXUP_DMIC),
5530 SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_FIXUP_DMIC),
5531#endif
5532 {}
5533};
5534
David Henningsson214eef72014-07-22 14:09:35 +02005535static const struct snd_pci_quirk alc269_fixup_vendor_tbl[] = {
5536 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
5537 SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
5538 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
5539 SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
5540 {}
5541};
5542
Takashi Iwai1727a772013-01-10 09:52:52 +01005543static const struct hda_model_fixup alc269_fixup_models[] = {
Takashi Iwaia4297b52011-08-23 18:40:12 +02005544 {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
5545 {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
Takashi Iwai6e72aa52012-06-25 10:52:25 +02005546 {.id = ALC269_FIXUP_STEREO_DMIC, .name = "alc269-dmic"},
5547 {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"},
5548 {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"},
David Henningsson7c478f02013-10-11 10:18:46 +02005549 {.id = ALC269_FIXUP_HEADSET_MIC, .name = "headset-mic"},
Takashi Iwaib0169512015-05-19 10:20:13 +02005550 {.id = ALC269_FIXUP_HEADSET_MODE, .name = "headset-mode"},
5551 {.id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, .name = "headset-mode-no-hp-mic"},
David Henningsson108cc102012-07-20 10:37:25 +02005552 {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"},
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01005553 {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
David Henningssone32aa852013-06-17 11:04:02 +02005554 {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
5555 {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
Kailang Yangbe8ef162014-04-08 15:19:49 +08005556 {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"},
Kailang Yang0202e992013-12-02 15:20:15 +08005557 {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
Takashi Iwai1c37c222014-05-06 17:34:42 +02005558 {.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"},
Takashi Iwai9a811232015-12-09 15:17:43 +01005559 {.id = ALC292_FIXUP_TPT440, .name = "tpt440"},
Takashi Iwai1d045db2011-07-07 18:23:21 +02005560 {}
5561};
5562
Hui Wange8191a82015-04-24 13:39:59 +08005563#define ALC256_STANDARD_PINS \
5564 {0x12, 0x90a60140}, \
5565 {0x14, 0x90170110}, \
Hui Wange8191a82015-04-24 13:39:59 +08005566 {0x21, 0x02211020}
5567
David Henningssonfea185e2014-09-03 10:23:04 +02005568#define ALC282_STANDARD_PINS \
Hui Wang11580292015-08-03 11:03:49 +08005569 {0x14, 0x90170110}
Kailang Yange1e62b92015-04-08 16:01:22 +08005570
David Henningssonfea185e2014-09-03 10:23:04 +02005571#define ALC290_STANDARD_PINS \
Hui Wang11580292015-08-03 11:03:49 +08005572 {0x12, 0x99a30130}
David Henningssonfea185e2014-09-03 10:23:04 +02005573
5574#define ALC292_STANDARD_PINS \
5575 {0x14, 0x90170110}, \
Hui Wang11580292015-08-03 11:03:49 +08005576 {0x15, 0x0221401f}
Kailang Yang977e6272015-05-18 15:31:20 +08005577
Woodrow Shen703867e2015-08-05 12:34:12 +08005578#define ALC298_STANDARD_PINS \
5579 {0x12, 0x90a60130}, \
5580 {0x21, 0x03211020}
5581
Hui Wange1918932014-05-26 16:22:44 +08005582static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
Hui Wangc77900e2014-09-03 11:31:07 +08005583 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
Hui Wangc77900e2014-09-03 11:31:07 +08005584 {0x14, 0x90170110},
Hui Wangc77900e2014-09-03 11:31:07 +08005585 {0x21, 0x02211020}),
David Henningsson76c21322014-06-24 14:46:54 +02005586 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5587 {0x12, 0x90a60140},
5588 {0x14, 0x90170110},
David Henningsson76c21322014-06-24 14:46:54 +02005589 {0x21, 0x02211020}),
5590 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5591 {0x12, 0x90a60160},
5592 {0x14, 0x90170120},
David Henningsson76c21322014-06-24 14:46:54 +02005593 {0x21, 0x02211030}),
5594 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
David Henningssoncba59972015-07-22 10:00:25 +02005595 {0x14, 0x90170130},
David Henningssoncba59972015-07-22 10:00:25 +02005596 {0x1b, 0x01014020},
David Henningssoncba59972015-07-22 10:00:25 +02005597 {0x21, 0x0221103f}),
5598 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
Woodrow Shene9c28e12015-07-25 10:36:16 +08005599 {0x14, 0x90170150},
Woodrow Shene9c28e12015-07-25 10:36:16 +08005600 {0x1b, 0x02011020},
Woodrow Shene9c28e12015-07-25 10:36:16 +08005601 {0x21, 0x0221105f}),
5602 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
Woodrow Shene9c28e12015-07-25 10:36:16 +08005603 {0x14, 0x90170110},
Woodrow Shene9c28e12015-07-25 10:36:16 +08005604 {0x1b, 0x01014020},
Woodrow Shene9c28e12015-07-25 10:36:16 +08005605 {0x21, 0x0221101f}),
5606 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
David Henningsson76c21322014-06-24 14:46:54 +02005607 {0x12, 0x90a60160},
5608 {0x14, 0x90170120},
5609 {0x17, 0x90170140},
David Henningsson76c21322014-06-24 14:46:54 +02005610 {0x21, 0x0321102f}),
5611 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5612 {0x12, 0x90a60160},
5613 {0x14, 0x90170130},
David Henningsson76c21322014-06-24 14:46:54 +02005614 {0x21, 0x02211040}),
5615 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5616 {0x12, 0x90a60160},
5617 {0x14, 0x90170140},
David Henningsson76c21322014-06-24 14:46:54 +02005618 {0x21, 0x02211050}),
5619 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5620 {0x12, 0x90a60170},
5621 {0x14, 0x90170120},
David Henningsson76c21322014-06-24 14:46:54 +02005622 {0x21, 0x02211030}),
5623 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5624 {0x12, 0x90a60170},
5625 {0x14, 0x90170130},
David Henningsson76c21322014-06-24 14:46:54 +02005626 {0x21, 0x02211040}),
Hui Wang70658b92015-03-06 14:03:57 +08005627 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
Hui Wang70658b92015-03-06 14:03:57 +08005628 {0x12, 0x90a60170},
5629 {0x14, 0x90170140},
Hui Wang70658b92015-03-06 14:03:57 +08005630 {0x21, 0x02211050}),
David Henningsson9b5a4e32015-05-11 14:04:14 +02005631 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5548", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
David Henningsson9b5a4e32015-05-11 14:04:14 +02005632 {0x12, 0x90a60180},
5633 {0x14, 0x90170130},
David Henningsson9b5a4e32015-05-11 14:04:14 +02005634 {0x21, 0x02211040}),
Kailang Yang7081adf2015-03-30 17:05:37 +08005635 SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
Kailang Yang81a12312015-05-28 16:48:22 +08005636 {0x12, 0x90a60160},
5637 {0x14, 0x90170120},
Kailang Yang81a12312015-05-28 16:48:22 +08005638 {0x21, 0x02211030}),
5639 SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
Hui Wang11580292015-08-03 11:03:49 +08005640 ALC256_STANDARD_PINS),
David Henningssoncf51eb92014-10-30 08:26:02 +01005641 SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
5642 {0x12, 0x90a60130},
David Henningssoncf51eb92014-10-30 08:26:02 +01005643 {0x14, 0x90170110},
5644 {0x15, 0x0421101f},
Hui Wang11580292015-08-03 11:03:49 +08005645 {0x1a, 0x04a11020}),
Hui Wang02796612014-09-03 11:31:11 +08005646 SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED,
5647 {0x12, 0x90a60140},
Hui Wang02796612014-09-03 11:31:11 +08005648 {0x14, 0x90170110},
5649 {0x15, 0x0421101f},
Hui Wang02796612014-09-03 11:31:11 +08005650 {0x18, 0x02811030},
Hui Wang02796612014-09-03 11:31:11 +08005651 {0x1a, 0x04a1103f},
Hui Wang11580292015-08-03 11:03:49 +08005652 {0x1b, 0x02011020}),
David Henningsson42304472014-07-22 11:42:17 +02005653 SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005654 ALC282_STANDARD_PINS,
David Henningsson42304472014-07-22 11:42:17 +02005655 {0x12, 0x99a30130},
David Henningsson42304472014-07-22 11:42:17 +02005656 {0x19, 0x03a11020},
David Henningsson42304472014-07-22 11:42:17 +02005657 {0x21, 0x0321101f}),
Hui Wang2c609992014-09-03 11:31:08 +08005658 SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005659 ALC282_STANDARD_PINS,
Hui Wang2c609992014-09-03 11:31:08 +08005660 {0x12, 0x99a30130},
Hui Wang2c609992014-09-03 11:31:08 +08005661 {0x19, 0x03a11020},
Hui Wang2c609992014-09-03 11:31:08 +08005662 {0x21, 0x03211040}),
5663 SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005664 ALC282_STANDARD_PINS,
Hui Wang2c609992014-09-03 11:31:08 +08005665 {0x12, 0x99a30130},
Hui Wang2c609992014-09-03 11:31:08 +08005666 {0x19, 0x03a11030},
Hui Wang2c609992014-09-03 11:31:08 +08005667 {0x21, 0x03211020}),
5668 SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005669 ALC282_STANDARD_PINS,
Hui Wang2c609992014-09-03 11:31:08 +08005670 {0x12, 0x99a30130},
Hui Wang2c609992014-09-03 11:31:08 +08005671 {0x19, 0x04a11020},
Hui Wang2c609992014-09-03 11:31:08 +08005672 {0x21, 0x0421101f}),
Hui Wang200afc02014-09-03 11:31:10 +08005673 SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED,
David Henningssonaec856d2014-09-03 10:23:05 +02005674 ALC282_STANDARD_PINS,
Hui Wang200afc02014-09-03 11:31:10 +08005675 {0x12, 0x90a60140},
Hui Wang200afc02014-09-03 11:31:10 +08005676 {0x19, 0x04a11030},
Hui Wang200afc02014-09-03 11:31:10 +08005677 {0x21, 0x04211020}),
David Henningsson76c21322014-06-24 14:46:54 +02005678 SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
David Henningssonaec856d2014-09-03 10:23:05 +02005679 ALC282_STANDARD_PINS,
David Henningsson76c21322014-06-24 14:46:54 +02005680 {0x12, 0x90a60130},
David Henningsson76c21322014-06-24 14:46:54 +02005681 {0x21, 0x0321101f}),
5682 SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
5683 {0x12, 0x90a60160},
5684 {0x14, 0x90170120},
David Henningsson76c21322014-06-24 14:46:54 +02005685 {0x21, 0x02211030}),
Hui Wangbc262172014-09-03 11:31:05 +08005686 SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
David Henningssonaec856d2014-09-03 10:23:05 +02005687 ALC282_STANDARD_PINS,
Hui Wangbc262172014-09-03 11:31:05 +08005688 {0x12, 0x90a60130},
Hui Wangbc262172014-09-03 11:31:05 +08005689 {0x19, 0x03a11020},
Hui Wangbc262172014-09-03 11:31:05 +08005690 {0x21, 0x0321101f}),
Kailang Yange1e62b92015-04-08 16:01:22 +08005691 SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL_XPS_13_GPIO6,
Kailang Yange1e62b92015-04-08 16:01:22 +08005692 {0x12, 0x90a60120},
Kailang Yange1e62b92015-04-08 16:01:22 +08005693 {0x14, 0x90170110},
Kailang Yange1e62b92015-04-08 16:01:22 +08005694 {0x21, 0x0321101f}),
Hui Wange4442bc2014-09-03 11:31:09 +08005695 SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005696 ALC290_STANDARD_PINS,
Hui Wange4442bc2014-09-03 11:31:09 +08005697 {0x15, 0x04211040},
Hui Wange4442bc2014-09-03 11:31:09 +08005698 {0x18, 0x90170112},
Hui Wang11580292015-08-03 11:03:49 +08005699 {0x1a, 0x04a11020}),
Hui Wange4442bc2014-09-03 11:31:09 +08005700 SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005701 ALC290_STANDARD_PINS,
Hui Wange4442bc2014-09-03 11:31:09 +08005702 {0x15, 0x04211040},
Hui Wange4442bc2014-09-03 11:31:09 +08005703 {0x18, 0x90170110},
Hui Wang11580292015-08-03 11:03:49 +08005704 {0x1a, 0x04a11020}),
Hui Wange4442bc2014-09-03 11:31:09 +08005705 SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005706 ALC290_STANDARD_PINS,
Hui Wange4442bc2014-09-03 11:31:09 +08005707 {0x15, 0x0421101f},
Hui Wang11580292015-08-03 11:03:49 +08005708 {0x1a, 0x04a11020}),
Hui Wange4442bc2014-09-03 11:31:09 +08005709 SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005710 ALC290_STANDARD_PINS,
Hui Wange4442bc2014-09-03 11:31:09 +08005711 {0x15, 0x04211020},
Hui Wang11580292015-08-03 11:03:49 +08005712 {0x1a, 0x04a11040}),
Hui Wange4442bc2014-09-03 11:31:09 +08005713 SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005714 ALC290_STANDARD_PINS,
Hui Wange4442bc2014-09-03 11:31:09 +08005715 {0x14, 0x90170110},
5716 {0x15, 0x04211020},
Hui Wang11580292015-08-03 11:03:49 +08005717 {0x1a, 0x04a11040}),
Hui Wange4442bc2014-09-03 11:31:09 +08005718 SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005719 ALC290_STANDARD_PINS,
Hui Wange4442bc2014-09-03 11:31:09 +08005720 {0x14, 0x90170110},
5721 {0x15, 0x04211020},
Hui Wang11580292015-08-03 11:03:49 +08005722 {0x1a, 0x04a11020}),
Hui Wange4442bc2014-09-03 11:31:09 +08005723 SND_HDA_PIN_QUIRK(0x10ec0290, 0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1,
David Henningssonaec856d2014-09-03 10:23:05 +02005724 ALC290_STANDARD_PINS,
Hui Wange4442bc2014-09-03 11:31:09 +08005725 {0x14, 0x90170110},
5726 {0x15, 0x0421101f},
Hui Wang11580292015-08-03 11:03:49 +08005727 {0x1a, 0x04a11020}),
Hui Wange8818fa2014-09-03 11:31:04 +08005728 SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
David Henningssonaec856d2014-09-03 10:23:05 +02005729 ALC292_STANDARD_PINS,
Hui Wange8818fa2014-09-03 11:31:04 +08005730 {0x12, 0x90a60140},
Hui Wange8818fa2014-09-03 11:31:04 +08005731 {0x16, 0x01014020},
Hui Wang11580292015-08-03 11:03:49 +08005732 {0x19, 0x01a19030}),
Hui Wange8818fa2014-09-03 11:31:04 +08005733 SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
David Henningssonaec856d2014-09-03 10:23:05 +02005734 ALC292_STANDARD_PINS,
Hui Wange8818fa2014-09-03 11:31:04 +08005735 {0x12, 0x90a60140},
Hui Wange8818fa2014-09-03 11:31:04 +08005736 {0x16, 0x01014020},
5737 {0x18, 0x02a19031},
Hui Wang11580292015-08-03 11:03:49 +08005738 {0x19, 0x01a1903e}),
David Henningsson76c21322014-06-24 14:46:54 +02005739 SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
David Henningssonaec856d2014-09-03 10:23:05 +02005740 ALC292_STANDARD_PINS,
Hui Wang11580292015-08-03 11:03:49 +08005741 {0x12, 0x90a60140}),
David Henningsson76c21322014-06-24 14:46:54 +02005742 SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
David Henningssonaec856d2014-09-03 10:23:05 +02005743 ALC292_STANDARD_PINS,
David Henningsson76c21322014-06-24 14:46:54 +02005744 {0x13, 0x90a60140},
David Henningsson76c21322014-06-24 14:46:54 +02005745 {0x16, 0x21014020},
Hui Wang11580292015-08-03 11:03:49 +08005746 {0x19, 0x21a19030}),
David Henningssone03fdbd2014-06-27 08:41:59 +02005747 SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
David Henningssonaec856d2014-09-03 10:23:05 +02005748 ALC292_STANDARD_PINS,
Hui Wang11580292015-08-03 11:03:49 +08005749 {0x13, 0x90a60140}),
Kailang Yang977e6272015-05-18 15:31:20 +08005750 SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
Woodrow Shen703867e2015-08-05 12:34:12 +08005751 ALC298_STANDARD_PINS,
Takashi Iwai9f502ff2015-08-05 12:09:45 +02005752 {0x17, 0x90170110}),
5753 SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
5754 ALC298_STANDARD_PINS,
Woodrow Shen703867e2015-08-05 12:34:12 +08005755 {0x17, 0x90170140}),
5756 SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
5757 ALC298_STANDARD_PINS,
Takashi Iwai9f502ff2015-08-05 12:09:45 +02005758 {0x17, 0x90170150}),
Hui Wange1918932014-05-26 16:22:44 +08005759 {}
5760};
Takashi Iwai1d045db2011-07-07 18:23:21 +02005761
Takashi Iwai546bb672012-03-07 08:37:19 +01005762static void alc269_fill_coef(struct hda_codec *codec)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005763{
Kailang Yang526af6e2012-03-07 08:25:20 +01005764 struct alc_spec *spec = codec->spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005765 int val;
5766
Kailang Yang526af6e2012-03-07 08:25:20 +01005767 if (spec->codec_variant != ALC269_TYPE_ALC269VB)
Takashi Iwai546bb672012-03-07 08:37:19 +01005768 return;
Kailang Yang526af6e2012-03-07 08:25:20 +01005769
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005770 if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005771 alc_write_coef_idx(codec, 0xf, 0x960b);
5772 alc_write_coef_idx(codec, 0xe, 0x8817);
5773 }
5774
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005775 if ((alc_get_coef0(codec) & 0x00ff) == 0x016) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005776 alc_write_coef_idx(codec, 0xf, 0x960b);
5777 alc_write_coef_idx(codec, 0xe, 0x8814);
5778 }
5779
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005780 if ((alc_get_coef0(codec) & 0x00ff) == 0x017) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005781 /* Power up output pin */
Takashi Iwai98b24882014-08-18 13:47:50 +02005782 alc_update_coef_idx(codec, 0x04, 0, 1<<11);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005783 }
5784
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005785 if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005786 val = alc_read_coef_idx(codec, 0xd);
Takashi Iwaif3ee07d2014-08-15 17:35:00 +02005787 if (val != -1 && (val & 0x0c00) >> 10 != 0x1) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005788 /* Capless ramp up clock control */
5789 alc_write_coef_idx(codec, 0xd, val | (1<<10));
5790 }
5791 val = alc_read_coef_idx(codec, 0x17);
Takashi Iwaif3ee07d2014-08-15 17:35:00 +02005792 if (val != -1 && (val & 0x01c0) >> 6 != 0x4) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005793 /* Class D power on reset */
5794 alc_write_coef_idx(codec, 0x17, val | (1<<7));
5795 }
5796 }
5797
Takashi Iwai98b24882014-08-18 13:47:50 +02005798 /* HP */
5799 alc_update_coef_idx(codec, 0x4, 0, 1<<11);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005800}
5801
5802/*
5803 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005804static int patch_alc269(struct hda_codec *codec)
5805{
5806 struct alc_spec *spec;
Takashi Iwai3de95172012-05-07 18:03:15 +02005807 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005808
Takashi Iwai3de95172012-05-07 18:03:15 +02005809 err = alc_alloc_spec(codec, 0x0b);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005810 if (err < 0)
Takashi Iwai3de95172012-05-07 18:03:15 +02005811 return err;
5812
5813 spec = codec->spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +01005814 spec->gen.shared_mic_vref_pin = 0x18;
Takashi Iwai8b99aba2015-06-15 11:59:32 +02005815 codec->power_save_node = 1;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005816
Takashi Iwai225068a2015-05-29 10:42:14 +02005817#ifdef CONFIG_PM
5818 codec->patch_ops.suspend = alc269_suspend;
5819 codec->patch_ops.resume = alc269_resume;
5820#endif
5821 spec->shutup = alc269_shutup;
5822
Takashi Iwai1727a772013-01-10 09:52:52 +01005823 snd_hda_pick_fixup(codec, alc269_fixup_models,
Herton Ronaldo Krzesinski9f720bb2012-09-27 10:38:14 -03005824 alc269_fixup_tbl, alc269_fixups);
Hui Wange1918932014-05-26 16:22:44 +08005825 snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups);
David Henningsson214eef72014-07-22 14:09:35 +02005826 snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl,
5827 alc269_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01005828 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Herton Ronaldo Krzesinski9f720bb2012-09-27 10:38:14 -03005829
5830 alc_auto_parse_customize_define(codec);
5831
Takashi Iwai7504b6c2013-03-18 11:25:51 +01005832 if (has_cdefine_beep(codec))
5833 spec->gen.beep_nid = 0x01;
5834
Takashi Iwai7639a062015-03-03 10:07:24 +01005835 switch (codec->core.vendor_id) {
Kailang Yang065380f2013-01-10 10:25:48 +01005836 case 0x10ec0269:
Takashi Iwai1d045db2011-07-07 18:23:21 +02005837 spec->codec_variant = ALC269_TYPE_ALC269VA;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005838 switch (alc_get_coef0(codec) & 0x00f0) {
5839 case 0x0010:
Takashi Iwai5100cd02014-02-15 10:03:19 +01005840 if (codec->bus->pci &&
5841 codec->bus->pci->subsystem_vendor == 0x1025 &&
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005842 spec->cdefine.platform_type == 1)
Takashi Iwai20ca0c32011-10-17 16:00:35 +02005843 err = alc_codec_rename(codec, "ALC271X");
Takashi Iwai1d045db2011-07-07 18:23:21 +02005844 spec->codec_variant = ALC269_TYPE_ALC269VB;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005845 break;
5846 case 0x0020:
Takashi Iwai5100cd02014-02-15 10:03:19 +01005847 if (codec->bus->pci &&
5848 codec->bus->pci->subsystem_vendor == 0x17aa &&
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005849 codec->bus->pci->subsystem_device == 0x21f3)
Takashi Iwai20ca0c32011-10-17 16:00:35 +02005850 err = alc_codec_rename(codec, "ALC3202");
Takashi Iwai1d045db2011-07-07 18:23:21 +02005851 spec->codec_variant = ALC269_TYPE_ALC269VC;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005852 break;
Kailang Yangadcc70b2012-05-25 08:08:38 +02005853 case 0x0030:
5854 spec->codec_variant = ALC269_TYPE_ALC269VD;
5855 break;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005856 default:
Takashi Iwai1d045db2011-07-07 18:23:21 +02005857 alc_fix_pll_init(codec, 0x20, 0x04, 15);
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005858 }
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005859 if (err < 0)
5860 goto error;
Takashi Iwai546bb672012-03-07 08:37:19 +01005861 spec->init_hook = alc269_fill_coef;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005862 alc269_fill_coef(codec);
Kailang Yang065380f2013-01-10 10:25:48 +01005863 break;
5864
5865 case 0x10ec0280:
5866 case 0x10ec0290:
5867 spec->codec_variant = ALC269_TYPE_ALC280;
5868 break;
5869 case 0x10ec0282:
Kailang Yang065380f2013-01-10 10:25:48 +01005870 spec->codec_variant = ALC269_TYPE_ALC282;
Kailang Yang7b5c7a02014-03-18 16:15:54 +08005871 spec->shutup = alc282_shutup;
5872 spec->init_hook = alc282_init;
Kailang Yang065380f2013-01-10 10:25:48 +01005873 break;
Kailang Yang2af02be2013-08-22 10:03:50 +02005874 case 0x10ec0233:
5875 case 0x10ec0283:
5876 spec->codec_variant = ALC269_TYPE_ALC283;
5877 spec->shutup = alc283_shutup;
5878 spec->init_hook = alc283_init;
5879 break;
Kailang Yang065380f2013-01-10 10:25:48 +01005880 case 0x10ec0284:
5881 case 0x10ec0292:
5882 spec->codec_variant = ALC269_TYPE_ALC284;
5883 break;
Kailang Yang161ebf22013-10-24 11:36:33 +02005884 case 0x10ec0285:
5885 case 0x10ec0293:
5886 spec->codec_variant = ALC269_TYPE_ALC285;
5887 break;
Kailang Yang7fc7d042013-04-25 11:04:43 +02005888 case 0x10ec0286:
Kailang Yang7c665932014-04-14 15:09:44 +08005889 case 0x10ec0288:
Kailang Yang7fc7d042013-04-25 11:04:43 +02005890 spec->codec_variant = ALC269_TYPE_ALC286;
Kailang Yangf7ae9ba2014-06-30 16:10:37 +08005891 spec->shutup = alc286_shutup;
Kailang Yang7fc7d042013-04-25 11:04:43 +02005892 break;
Kailang Yang506b62c2014-12-18 17:07:44 +08005893 case 0x10ec0298:
5894 spec->codec_variant = ALC269_TYPE_ALC298;
5895 break;
Kailang Yang1d04c9d2013-10-24 11:35:18 +02005896 case 0x10ec0255:
5897 spec->codec_variant = ALC269_TYPE_ALC255;
5898 break;
Kailang Yang4344aec2014-12-17 17:39:05 +08005899 case 0x10ec0256:
5900 spec->codec_variant = ALC269_TYPE_ALC256;
David Henningsson7d1b6e22015-04-21 10:48:46 +02005901 spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
Kailang Yangd32b6662015-04-23 15:10:53 +08005902 alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/
Kailang Yang4344aec2014-12-17 17:39:05 +08005903 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005904 }
5905
Kailang Yangad60d502013-06-28 12:03:01 +02005906 if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
Kailang Yang97a26572013-11-29 00:35:26 -05005907 spec->has_alc5505_dsp = 1;
Kailang Yangad60d502013-06-28 12:03:01 +02005908 spec->init_hook = alc5505_dsp_init;
5909 }
5910
Takashi Iwaia4297b52011-08-23 18:40:12 +02005911 /* automatic parse from the BIOS config */
5912 err = alc269_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005913 if (err < 0)
5914 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005915
David Henningsson7d1b6e22015-04-21 10:48:46 +02005916 if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid)
5917 set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005918
Takashi Iwai1727a772013-01-10 09:52:52 +01005919 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01005920
Takashi Iwai1d045db2011-07-07 18:23:21 +02005921 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005922
5923 error:
5924 alc_free(codec);
5925 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005926}
5927
5928/*
5929 * ALC861
5930 */
5931
Takashi Iwai1d045db2011-07-07 18:23:21 +02005932static int alc861_parse_auto_config(struct hda_codec *codec)
5933{
Takashi Iwai1d045db2011-07-07 18:23:21 +02005934 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005935 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
5936 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005937}
5938
Takashi Iwai1d045db2011-07-07 18:23:21 +02005939/* Pin config fixes */
5940enum {
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005941 ALC861_FIXUP_FSC_AMILO_PI1505,
5942 ALC861_FIXUP_AMP_VREF_0F,
5943 ALC861_FIXUP_NO_JACK_DETECT,
5944 ALC861_FIXUP_ASUS_A6RP,
Takashi Iwai6ddf0fd2013-11-29 12:47:34 +01005945 ALC660_FIXUP_ASUS_W7J,
Takashi Iwai1d045db2011-07-07 18:23:21 +02005946};
5947
Takashi Iwai31150f22012-01-30 10:54:08 +01005948/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
5949static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01005950 const struct hda_fixup *fix, int action)
Takashi Iwai31150f22012-01-30 10:54:08 +01005951{
5952 struct alc_spec *spec = codec->spec;
5953 unsigned int val;
5954
Takashi Iwai1727a772013-01-10 09:52:52 +01005955 if (action != HDA_FIXUP_ACT_INIT)
Takashi Iwai31150f22012-01-30 10:54:08 +01005956 return;
Takashi Iwaid3f02d62013-01-10 10:12:22 +01005957 val = snd_hda_codec_get_pin_target(codec, 0x0f);
Takashi Iwai31150f22012-01-30 10:54:08 +01005958 if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
5959 val |= AC_PINCTL_IN_EN;
5960 val |= AC_PINCTL_VREF_50;
Takashi Iwaicdd03ce2012-04-20 12:34:50 +02005961 snd_hda_set_pin_ctl(codec, 0x0f, val);
Takashi Iwai08c189f2012-12-19 15:22:24 +01005962 spec->gen.keep_vref_in_automute = 1;
Takashi Iwai31150f22012-01-30 10:54:08 +01005963}
5964
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005965/* suppress the jack-detection */
5966static void alc_fixup_no_jack_detect(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01005967 const struct hda_fixup *fix, int action)
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005968{
Takashi Iwai1727a772013-01-10 09:52:52 +01005969 if (action == HDA_FIXUP_ACT_PRE_PROBE)
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005970 codec->no_jack_detect = 1;
Jesper Juhl7d7eb9e2012-04-12 22:11:25 +02005971}
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005972
Takashi Iwai1727a772013-01-10 09:52:52 +01005973static const struct hda_fixup alc861_fixups[] = {
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005974 [ALC861_FIXUP_FSC_AMILO_PI1505] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005975 .type = HDA_FIXUP_PINS,
5976 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005977 { 0x0b, 0x0221101f }, /* HP */
5978 { 0x0f, 0x90170310 }, /* speaker */
5979 { }
5980 }
5981 },
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005982 [ALC861_FIXUP_AMP_VREF_0F] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005983 .type = HDA_FIXUP_FUNC,
Takashi Iwai31150f22012-01-30 10:54:08 +01005984 .v.func = alc861_fixup_asus_amp_vref_0f,
Takashi Iwai3b25eb62012-01-25 09:55:46 +01005985 },
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005986 [ALC861_FIXUP_NO_JACK_DETECT] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005987 .type = HDA_FIXUP_FUNC,
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005988 .v.func = alc_fixup_no_jack_detect,
5989 },
5990 [ALC861_FIXUP_ASUS_A6RP] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005991 .type = HDA_FIXUP_FUNC,
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005992 .v.func = alc861_fixup_asus_amp_vref_0f,
5993 .chained = true,
5994 .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
Takashi Iwai6ddf0fd2013-11-29 12:47:34 +01005995 },
5996 [ALC660_FIXUP_ASUS_W7J] = {
5997 .type = HDA_FIXUP_VERBS,
5998 .v.verbs = (const struct hda_verb[]) {
5999 /* ASUS W7J needs a magic pin setup on unused NID 0x10
6000 * for enabling outputs
6001 */
6002 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
6003 { }
6004 },
Takashi Iwaie652f4c2012-02-13 11:56:25 +01006005 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02006006};
6007
6008static const struct snd_pci_quirk alc861_fixup_tbl[] = {
Takashi Iwai6ddf0fd2013-11-29 12:47:34 +01006009 SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
Takashi Iwaie7ca2372013-12-02 15:27:19 +01006010 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
Takashi Iwaie652f4c2012-02-13 11:56:25 +01006011 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
6012 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
6013 SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
6014 SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F),
6015 SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F),
6016 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
Takashi Iwai1d045db2011-07-07 18:23:21 +02006017 {}
6018};
6019
6020/*
6021 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02006022static int patch_alc861(struct hda_codec *codec)
6023{
6024 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006025 int err;
6026
Takashi Iwai3de95172012-05-07 18:03:15 +02006027 err = alc_alloc_spec(codec, 0x15);
6028 if (err < 0)
6029 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006030
Takashi Iwai3de95172012-05-07 18:03:15 +02006031 spec = codec->spec;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01006032 spec->gen.beep_nid = 0x23;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006033
Takashi Iwai225068a2015-05-29 10:42:14 +02006034#ifdef CONFIG_PM
6035 spec->power_hook = alc_power_eapd;
6036#endif
6037
Takashi Iwai1727a772013-01-10 09:52:52 +01006038 snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
6039 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02006040
Takashi Iwaicb4e4822011-08-23 17:34:25 +02006041 /* automatic parse from the BIOS config */
6042 err = alc861_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006043 if (err < 0)
6044 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006045
Takashi Iwai7504b6c2013-03-18 11:25:51 +01006046 if (!spec->gen.no_analog)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006047 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
Takashi Iwai1d045db2011-07-07 18:23:21 +02006048
Takashi Iwai1727a772013-01-10 09:52:52 +01006049 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01006050
Takashi Iwai1d045db2011-07-07 18:23:21 +02006051 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006052
6053 error:
6054 alc_free(codec);
6055 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006056}
6057
6058/*
6059 * ALC861-VD support
6060 *
6061 * Based on ALC882
6062 *
6063 * In addition, an independent DAC
6064 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02006065static int alc861vd_parse_auto_config(struct hda_codec *codec)
6066{
Takashi Iwai1d045db2011-07-07 18:23:21 +02006067 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006068 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
6069 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02006070}
6071
Takashi Iwai1d045db2011-07-07 18:23:21 +02006072enum {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02006073 ALC660VD_FIX_ASUS_GPIO1,
6074 ALC861VD_FIX_DALLAS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02006075};
6076
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02006077/* exclude VREF80 */
6078static void alc861vd_fixup_dallas(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01006079 const struct hda_fixup *fix, int action)
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02006080{
Takashi Iwai1727a772013-01-10 09:52:52 +01006081 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwaib78562b2012-12-17 20:06:49 +01006082 snd_hda_override_pin_caps(codec, 0x18, 0x00000734);
6083 snd_hda_override_pin_caps(codec, 0x19, 0x0000073c);
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02006084 }
6085}
6086
Takashi Iwai1727a772013-01-10 09:52:52 +01006087static const struct hda_fixup alc861vd_fixups[] = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02006088 [ALC660VD_FIX_ASUS_GPIO1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006089 .type = HDA_FIXUP_VERBS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02006090 .v.verbs = (const struct hda_verb[]) {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02006091 /* reset GPIO1 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02006092 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
6093 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
6094 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
6095 { }
6096 }
6097 },
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02006098 [ALC861VD_FIX_DALLAS] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006099 .type = HDA_FIXUP_FUNC,
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02006100 .v.func = alc861vd_fixup_dallas,
6101 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02006102};
6103
6104static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02006105 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS),
Takashi Iwai1d045db2011-07-07 18:23:21 +02006106 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02006107 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS),
Takashi Iwai1d045db2011-07-07 18:23:21 +02006108 {}
6109};
6110
Takashi Iwai1d045db2011-07-07 18:23:21 +02006111/*
6112 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02006113static int patch_alc861vd(struct hda_codec *codec)
6114{
6115 struct alc_spec *spec;
Takashi Iwaicb4e4822011-08-23 17:34:25 +02006116 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006117
Takashi Iwai3de95172012-05-07 18:03:15 +02006118 err = alc_alloc_spec(codec, 0x0b);
6119 if (err < 0)
6120 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006121
Takashi Iwai3de95172012-05-07 18:03:15 +02006122 spec = codec->spec;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01006123 spec->gen.beep_nid = 0x23;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006124
Takashi Iwai225068a2015-05-29 10:42:14 +02006125 spec->shutup = alc_eapd_shutup;
6126
Takashi Iwai1727a772013-01-10 09:52:52 +01006127 snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
6128 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02006129
Takashi Iwaicb4e4822011-08-23 17:34:25 +02006130 /* automatic parse from the BIOS config */
6131 err = alc861vd_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006132 if (err < 0)
6133 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006134
Takashi Iwai7504b6c2013-03-18 11:25:51 +01006135 if (!spec->gen.no_analog)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006136 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai1d045db2011-07-07 18:23:21 +02006137
Takashi Iwai1727a772013-01-10 09:52:52 +01006138 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01006139
Takashi Iwai1d045db2011-07-07 18:23:21 +02006140 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006141
6142 error:
6143 alc_free(codec);
6144 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02006145}
6146
6147/*
6148 * ALC662 support
6149 *
6150 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
6151 * configuration. Each pin widget can choose any input DACs and a mixer.
6152 * Each ADC is connected from a mixer of all inputs. This makes possible
6153 * 6-channel independent captures.
6154 *
6155 * In addition, an independent DAC for the multi-playback (not used in this
6156 * driver yet).
6157 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02006158
6159/*
6160 * BIOS auto configuration
6161 */
6162
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006163static int alc662_parse_auto_config(struct hda_codec *codec)
6164{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02006165 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006166 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
6167 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
6168 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02006169
Takashi Iwai7639a062015-03-03 10:07:24 +01006170 if (codec->core.vendor_id == 0x10ec0272 || codec->core.vendor_id == 0x10ec0663 ||
6171 codec->core.vendor_id == 0x10ec0665 || codec->core.vendor_id == 0x10ec0670 ||
6172 codec->core.vendor_id == 0x10ec0671)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006173 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01006174 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006175 ssids = alc662_ssids;
6176 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006177}
6178
Todd Broch6be79482010-12-07 16:51:05 -08006179static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01006180 const struct hda_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01006181{
Takashi Iwai9bb1f062013-01-10 17:14:29 +01006182 if (action != HDA_FIXUP_ACT_PRE_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01006183 return;
Todd Broch6be79482010-12-07 16:51:05 -08006184 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
6185 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
6186 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
6187 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
6188 (0 << AC_AMPCAP_MUTE_SHIFT)))
Takashi Iwai4e76a882014-02-25 12:21:03 +01006189 codec_warn(codec, "failed to override amp caps for NID 0x2\n");
Todd Broch6be79482010-12-07 16:51:05 -08006190}
6191
Takashi Iwai8e383952013-10-30 17:41:12 +01006192static const struct snd_pcm_chmap_elem asus_pcm_2_1_chmaps[] = {
6193 { .channels = 2,
6194 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
6195 { .channels = 4,
6196 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
6197 SNDRV_CHMAP_NA, SNDRV_CHMAP_LFE } }, /* LFE only on right */
6198 { }
6199};
6200
6201/* override the 2.1 chmap */
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01006202static void alc_fixup_bass_chmap(struct hda_codec *codec,
Takashi Iwai8e383952013-10-30 17:41:12 +01006203 const struct hda_fixup *fix, int action)
6204{
6205 if (action == HDA_FIXUP_ACT_BUILD) {
6206 struct alc_spec *spec = codec->spec;
Takashi Iwaibbbc7e82015-02-27 17:43:19 +01006207 spec->gen.pcm_rec[0]->stream[0].chmap = asus_pcm_2_1_chmaps;
Takashi Iwai8e383952013-10-30 17:41:12 +01006208 }
6209}
6210
Takashi Iwaibf686652014-01-13 16:18:25 +01006211/* avoid D3 for keeping GPIO up */
6212static unsigned int gpio_led_power_filter(struct hda_codec *codec,
6213 hda_nid_t nid,
6214 unsigned int power_state)
6215{
6216 struct alc_spec *spec = codec->spec;
Takashi Iwai7639a062015-03-03 10:07:24 +01006217 if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_led)
Takashi Iwaibf686652014-01-13 16:18:25 +01006218 return AC_PWRST_D0;
6219 return power_state;
6220}
6221
Takashi Iwai3e887f32014-01-10 17:50:58 +01006222static void alc662_fixup_led_gpio1(struct hda_codec *codec,
6223 const struct hda_fixup *fix, int action)
6224{
6225 struct alc_spec *spec = codec->spec;
6226 static const struct hda_verb gpio_init[] = {
6227 { 0x01, AC_VERB_SET_GPIO_MASK, 0x01 },
6228 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01 },
6229 {}
6230 };
6231
6232 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwai0f32fd192014-11-19 12:16:14 +01006233 spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
Takashi Iwai3e887f32014-01-10 17:50:58 +01006234 spec->gpio_led = 0;
Takashi Iwai0f32fd192014-11-19 12:16:14 +01006235 spec->mute_led_polarity = 1;
6236 spec->gpio_mute_led_mask = 0x01;
Takashi Iwai3e887f32014-01-10 17:50:58 +01006237 snd_hda_add_verbs(codec, gpio_init);
Takashi Iwaibf686652014-01-13 16:18:25 +01006238 codec->power_filter = gpio_led_power_filter;
Takashi Iwai3e887f32014-01-10 17:50:58 +01006239 }
6240}
6241
Kailang Yangf3f91852014-10-24 15:43:46 +08006242static struct coef_fw alc668_coefs[] = {
6243 WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0),
6244 WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80),
6245 WRITE_COEF(0x08, 0x0031), WRITE_COEF(0x0a, 0x0060), WRITE_COEF(0x0b, 0x0),
6246 WRITE_COEF(0x0c, 0x7cf7), WRITE_COEF(0x0d, 0x1080), WRITE_COEF(0x0e, 0x7f7f),
6247 WRITE_COEF(0x0f, 0xcccc), WRITE_COEF(0x10, 0xddcc), WRITE_COEF(0x11, 0x0001),
6248 WRITE_COEF(0x13, 0x0), WRITE_COEF(0x14, 0x2aa0), WRITE_COEF(0x17, 0xa940),
6249 WRITE_COEF(0x19, 0x0), WRITE_COEF(0x1a, 0x0), WRITE_COEF(0x1b, 0x0),
6250 WRITE_COEF(0x1c, 0x0), WRITE_COEF(0x1d, 0x0), WRITE_COEF(0x1e, 0x7418),
6251 WRITE_COEF(0x1f, 0x0804), WRITE_COEF(0x20, 0x4200), WRITE_COEF(0x21, 0x0468),
6252 WRITE_COEF(0x22, 0x8ccc), WRITE_COEF(0x23, 0x0250), WRITE_COEF(0x24, 0x7418),
6253 WRITE_COEF(0x27, 0x0), WRITE_COEF(0x28, 0x8ccc), WRITE_COEF(0x2a, 0xff00),
6254 WRITE_COEF(0x2b, 0x8000), WRITE_COEF(0xa7, 0xff00), WRITE_COEF(0xa8, 0x8000),
6255 WRITE_COEF(0xaa, 0x2e17), WRITE_COEF(0xab, 0xa0c0), WRITE_COEF(0xac, 0x0),
6256 WRITE_COEF(0xad, 0x0), WRITE_COEF(0xae, 0x2ac6), WRITE_COEF(0xaf, 0xa480),
6257 WRITE_COEF(0xb0, 0x0), WRITE_COEF(0xb1, 0x0), WRITE_COEF(0xb2, 0x0),
6258 WRITE_COEF(0xb3, 0x0), WRITE_COEF(0xb4, 0x0), WRITE_COEF(0xb5, 0x1040),
6259 WRITE_COEF(0xb6, 0xd697), WRITE_COEF(0xb7, 0x902b), WRITE_COEF(0xb8, 0xd697),
6260 WRITE_COEF(0xb9, 0x902b), WRITE_COEF(0xba, 0xb8ba), WRITE_COEF(0xbb, 0xaaab),
6261 WRITE_COEF(0xbc, 0xaaaf), WRITE_COEF(0xbd, 0x6aaa), WRITE_COEF(0xbe, 0x1c02),
6262 WRITE_COEF(0xc0, 0x00ff), WRITE_COEF(0xc1, 0x0fa6),
6263 {}
6264};
6265
6266static void alc668_restore_default_value(struct hda_codec *codec)
6267{
6268 alc_process_coef_fw(codec, alc668_coefs);
6269}
6270
David Henningsson6cb3b702010-09-09 08:51:44 +02006271enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04006272 ALC662_FIXUP_ASPIRE,
Takashi Iwai3e887f32014-01-10 17:50:58 +01006273 ALC662_FIXUP_LED_GPIO1,
David Henningsson6cb3b702010-09-09 08:51:44 +02006274 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08006275 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01006276 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02006277 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02006278 ALC662_FIXUP_HP_RP5800,
Takashi Iwai53c334a2011-08-23 18:27:14 +02006279 ALC662_FIXUP_ASUS_MODE1,
6280 ALC662_FIXUP_ASUS_MODE2,
6281 ALC662_FIXUP_ASUS_MODE3,
6282 ALC662_FIXUP_ASUS_MODE4,
6283 ALC662_FIXUP_ASUS_MODE5,
6284 ALC662_FIXUP_ASUS_MODE6,
6285 ALC662_FIXUP_ASUS_MODE7,
6286 ALC662_FIXUP_ASUS_MODE8,
Takashi Iwai1565cc32012-02-13 12:03:25 +01006287 ALC662_FIXUP_NO_JACK_DETECT,
David Henningssonedfe3bf2012-06-12 13:15:12 +02006288 ALC662_FIXUP_ZOTAC_Z68,
Takashi Iwai125821a2012-06-22 14:30:29 +02006289 ALC662_FIXUP_INV_DMIC,
David Henningsson1f8b46c2015-05-12 14:38:15 +02006290 ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
David Henningsson73bdd592013-04-15 15:44:14 +02006291 ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
David Henningsson1f8b46c2015-05-12 14:38:15 +02006292 ALC662_FIXUP_HEADSET_MODE,
David Henningsson73bdd592013-04-15 15:44:14 +02006293 ALC668_FIXUP_HEADSET_MODE,
David Henningsson8e54b4a2014-02-07 09:31:07 +01006294 ALC662_FIXUP_BASS_MODE4_CHMAP,
David Henningsson61a75f12014-02-07 09:31:08 +01006295 ALC662_FIXUP_BASS_16,
Takashi Iwaia30c9aa2013-11-21 08:00:20 +01006296 ALC662_FIXUP_BASS_1A,
David Henningsson8e54b4a2014-02-07 09:31:07 +01006297 ALC662_FIXUP_BASS_CHMAP,
Hui Wang493a52a2014-01-14 14:07:36 +08006298 ALC668_FIXUP_AUTO_MUTE,
Gabriele Mazzotta5e6db662014-05-20 18:58:26 +02006299 ALC668_FIXUP_DELL_DISABLE_AAMIX,
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02006300 ALC668_FIXUP_DELL_XPS13,
David Henningsson6cb3b702010-09-09 08:51:44 +02006301};
6302
Takashi Iwai1727a772013-01-10 09:52:52 +01006303static const struct hda_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04006304 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006305 .type = HDA_FIXUP_PINS,
6306 .v.pins = (const struct hda_pintbl[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04006307 { 0x15, 0x99130112 }, /* subwoofer */
6308 { }
6309 }
6310 },
Takashi Iwai3e887f32014-01-10 17:50:58 +01006311 [ALC662_FIXUP_LED_GPIO1] = {
6312 .type = HDA_FIXUP_FUNC,
6313 .v.func = alc662_fixup_led_gpio1,
6314 },
David Henningsson6cb3b702010-09-09 08:51:44 +02006315 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006316 .type = HDA_FIXUP_PINS,
6317 .v.pins = (const struct hda_pintbl[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02006318 { 0x17, 0x99130112 }, /* subwoofer */
6319 { }
Takashi Iwai3e887f32014-01-10 17:50:58 +01006320 },
6321 .chained = true,
6322 .chain_id = ALC662_FIXUP_LED_GPIO1,
David Henningsson6cb3b702010-09-09 08:51:44 +02006323 },
Todd Broch6be79482010-12-07 16:51:05 -08006324 [ALC272_FIXUP_MARIO] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006325 .type = HDA_FIXUP_FUNC,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01006326 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01006327 },
6328 [ALC662_FIXUP_CZC_P10T] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006329 .type = HDA_FIXUP_VERBS,
Anisse Astierd2ebd472011-01-20 12:36:21 +01006330 .v.verbs = (const struct hda_verb[]) {
6331 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
6332 {}
6333 }
6334 },
David Henningsson94024cd2011-04-29 14:10:55 +02006335 [ALC662_FIXUP_SKU_IGNORE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006336 .type = HDA_FIXUP_FUNC,
Takashi Iwai23d30f22012-05-07 17:17:32 +02006337 .v.func = alc_fixup_sku_ignore,
Takashi Iwaic6b35872011-03-28 12:05:31 +02006338 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02006339 [ALC662_FIXUP_HP_RP5800] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006340 .type = HDA_FIXUP_PINS,
6341 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02006342 { 0x14, 0x0221201f }, /* HP out */
6343 { }
6344 },
6345 .chained = true,
6346 .chain_id = ALC662_FIXUP_SKU_IGNORE
6347 },
Takashi Iwai53c334a2011-08-23 18:27:14 +02006348 [ALC662_FIXUP_ASUS_MODE1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006349 .type = HDA_FIXUP_PINS,
6350 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02006351 { 0x14, 0x99130110 }, /* speaker */
6352 { 0x18, 0x01a19c20 }, /* mic */
6353 { 0x19, 0x99a3092f }, /* int-mic */
6354 { 0x21, 0x0121401f }, /* HP out */
6355 { }
6356 },
6357 .chained = true,
6358 .chain_id = ALC662_FIXUP_SKU_IGNORE
6359 },
6360 [ALC662_FIXUP_ASUS_MODE2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006361 .type = HDA_FIXUP_PINS,
6362 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai2996bdb2011-08-18 16:02:24 +02006363 { 0x14, 0x99130110 }, /* speaker */
6364 { 0x18, 0x01a19820 }, /* mic */
6365 { 0x19, 0x99a3092f }, /* int-mic */
6366 { 0x1b, 0x0121401f }, /* HP out */
6367 { }
6368 },
Takashi Iwai53c334a2011-08-23 18:27:14 +02006369 .chained = true,
6370 .chain_id = ALC662_FIXUP_SKU_IGNORE
6371 },
6372 [ALC662_FIXUP_ASUS_MODE3] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006373 .type = HDA_FIXUP_PINS,
6374 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02006375 { 0x14, 0x99130110 }, /* speaker */
6376 { 0x15, 0x0121441f }, /* HP */
6377 { 0x18, 0x01a19840 }, /* mic */
6378 { 0x19, 0x99a3094f }, /* int-mic */
6379 { 0x21, 0x01211420 }, /* HP2 */
6380 { }
6381 },
6382 .chained = true,
6383 .chain_id = ALC662_FIXUP_SKU_IGNORE
6384 },
6385 [ALC662_FIXUP_ASUS_MODE4] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006386 .type = HDA_FIXUP_PINS,
6387 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02006388 { 0x14, 0x99130110 }, /* speaker */
6389 { 0x16, 0x99130111 }, /* speaker */
6390 { 0x18, 0x01a19840 }, /* mic */
6391 { 0x19, 0x99a3094f }, /* int-mic */
6392 { 0x21, 0x0121441f }, /* HP */
6393 { }
6394 },
6395 .chained = true,
6396 .chain_id = ALC662_FIXUP_SKU_IGNORE
6397 },
6398 [ALC662_FIXUP_ASUS_MODE5] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006399 .type = HDA_FIXUP_PINS,
6400 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02006401 { 0x14, 0x99130110 }, /* speaker */
6402 { 0x15, 0x0121441f }, /* HP */
6403 { 0x16, 0x99130111 }, /* speaker */
6404 { 0x18, 0x01a19840 }, /* mic */
6405 { 0x19, 0x99a3094f }, /* int-mic */
6406 { }
6407 },
6408 .chained = true,
6409 .chain_id = ALC662_FIXUP_SKU_IGNORE
6410 },
6411 [ALC662_FIXUP_ASUS_MODE6] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006412 .type = HDA_FIXUP_PINS,
6413 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02006414 { 0x14, 0x99130110 }, /* speaker */
6415 { 0x15, 0x01211420 }, /* HP2 */
6416 { 0x18, 0x01a19840 }, /* mic */
6417 { 0x19, 0x99a3094f }, /* int-mic */
6418 { 0x1b, 0x0121441f }, /* HP */
6419 { }
6420 },
6421 .chained = true,
6422 .chain_id = ALC662_FIXUP_SKU_IGNORE
6423 },
6424 [ALC662_FIXUP_ASUS_MODE7] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006425 .type = HDA_FIXUP_PINS,
6426 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02006427 { 0x14, 0x99130110 }, /* speaker */
6428 { 0x17, 0x99130111 }, /* speaker */
6429 { 0x18, 0x01a19840 }, /* mic */
6430 { 0x19, 0x99a3094f }, /* int-mic */
6431 { 0x1b, 0x01214020 }, /* HP */
6432 { 0x21, 0x0121401f }, /* HP */
6433 { }
6434 },
6435 .chained = true,
6436 .chain_id = ALC662_FIXUP_SKU_IGNORE
6437 },
6438 [ALC662_FIXUP_ASUS_MODE8] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006439 .type = HDA_FIXUP_PINS,
6440 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02006441 { 0x14, 0x99130110 }, /* speaker */
6442 { 0x12, 0x99a30970 }, /* int-mic */
6443 { 0x15, 0x01214020 }, /* HP */
6444 { 0x17, 0x99130111 }, /* speaker */
6445 { 0x18, 0x01a19840 }, /* mic */
6446 { 0x21, 0x0121401f }, /* HP */
6447 { }
6448 },
6449 .chained = true,
6450 .chain_id = ALC662_FIXUP_SKU_IGNORE
Takashi Iwai2996bdb2011-08-18 16:02:24 +02006451 },
Takashi Iwai1565cc32012-02-13 12:03:25 +01006452 [ALC662_FIXUP_NO_JACK_DETECT] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006453 .type = HDA_FIXUP_FUNC,
Takashi Iwai1565cc32012-02-13 12:03:25 +01006454 .v.func = alc_fixup_no_jack_detect,
6455 },
David Henningssonedfe3bf2012-06-12 13:15:12 +02006456 [ALC662_FIXUP_ZOTAC_Z68] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006457 .type = HDA_FIXUP_PINS,
6458 .v.pins = (const struct hda_pintbl[]) {
David Henningssonedfe3bf2012-06-12 13:15:12 +02006459 { 0x1b, 0x02214020 }, /* Front HP */
6460 { }
6461 }
6462 },
Takashi Iwai125821a2012-06-22 14:30:29 +02006463 [ALC662_FIXUP_INV_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006464 .type = HDA_FIXUP_FUNC,
David Henningsson9d36a7d2014-10-07 10:18:42 +02006465 .v.func = alc_fixup_inv_dmic,
Takashi Iwai125821a2012-06-22 14:30:29 +02006466 },
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02006467 [ALC668_FIXUP_DELL_XPS13] = {
6468 .type = HDA_FIXUP_FUNC,
6469 .v.func = alc_fixup_dell_xps13,
6470 .chained = true,
6471 .chain_id = ALC668_FIXUP_DELL_DISABLE_AAMIX
6472 },
Gabriele Mazzotta5e6db662014-05-20 18:58:26 +02006473 [ALC668_FIXUP_DELL_DISABLE_AAMIX] = {
6474 .type = HDA_FIXUP_FUNC,
6475 .v.func = alc_fixup_disable_aamix,
6476 .chained = true,
6477 .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
6478 },
Hui Wang493a52a2014-01-14 14:07:36 +08006479 [ALC668_FIXUP_AUTO_MUTE] = {
6480 .type = HDA_FIXUP_FUNC,
6481 .v.func = alc_fixup_auto_mute_via_amp,
6482 .chained = true,
6483 .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
6484 },
David Henningsson1f8b46c2015-05-12 14:38:15 +02006485 [ALC662_FIXUP_DELL_MIC_NO_PRESENCE] = {
6486 .type = HDA_FIXUP_PINS,
6487 .v.pins = (const struct hda_pintbl[]) {
6488 { 0x19, 0x03a1113c }, /* use as headset mic, without its own jack detect */
6489 /* headphone mic by setting pin control of 0x1b (headphone out) to in + vref_50 */
6490 { }
6491 },
6492 .chained = true,
6493 .chain_id = ALC662_FIXUP_HEADSET_MODE
6494 },
6495 [ALC662_FIXUP_HEADSET_MODE] = {
6496 .type = HDA_FIXUP_FUNC,
6497 .v.func = alc_fixup_headset_mode_alc662,
6498 },
David Henningsson73bdd592013-04-15 15:44:14 +02006499 [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
6500 .type = HDA_FIXUP_PINS,
6501 .v.pins = (const struct hda_pintbl[]) {
6502 { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
6503 { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
6504 { }
6505 },
6506 .chained = true,
6507 .chain_id = ALC668_FIXUP_HEADSET_MODE
6508 },
6509 [ALC668_FIXUP_HEADSET_MODE] = {
6510 .type = HDA_FIXUP_FUNC,
6511 .v.func = alc_fixup_headset_mode_alc668,
6512 },
David Henningsson8e54b4a2014-02-07 09:31:07 +01006513 [ALC662_FIXUP_BASS_MODE4_CHMAP] = {
Takashi Iwai8e383952013-10-30 17:41:12 +01006514 .type = HDA_FIXUP_FUNC,
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01006515 .v.func = alc_fixup_bass_chmap,
Takashi Iwai8e383952013-10-30 17:41:12 +01006516 .chained = true,
6517 .chain_id = ALC662_FIXUP_ASUS_MODE4
6518 },
David Henningsson61a75f12014-02-07 09:31:08 +01006519 [ALC662_FIXUP_BASS_16] = {
6520 .type = HDA_FIXUP_PINS,
6521 .v.pins = (const struct hda_pintbl[]) {
6522 {0x16, 0x80106111}, /* bass speaker */
6523 {}
6524 },
6525 .chained = true,
6526 .chain_id = ALC662_FIXUP_BASS_CHMAP,
6527 },
Takashi Iwaia30c9aa2013-11-21 08:00:20 +01006528 [ALC662_FIXUP_BASS_1A] = {
6529 .type = HDA_FIXUP_PINS,
6530 .v.pins = (const struct hda_pintbl[]) {
6531 {0x1a, 0x80106111}, /* bass speaker */
6532 {}
6533 },
David Henningsson8e54b4a2014-02-07 09:31:07 +01006534 .chained = true,
6535 .chain_id = ALC662_FIXUP_BASS_CHMAP,
Takashi Iwaia30c9aa2013-11-21 08:00:20 +01006536 },
David Henningsson8e54b4a2014-02-07 09:31:07 +01006537 [ALC662_FIXUP_BASS_CHMAP] = {
Takashi Iwaia30c9aa2013-11-21 08:00:20 +01006538 .type = HDA_FIXUP_FUNC,
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01006539 .v.func = alc_fixup_bass_chmap,
Takashi Iwaia30c9aa2013-11-21 08:00:20 +01006540 },
David Henningsson6cb3b702010-09-09 08:51:44 +02006541};
6542
Takashi Iwaia9111322011-05-02 11:30:18 +02006543static const struct snd_pci_quirk alc662_fixup_tbl[] = {
Takashi Iwai53c334a2011-08-23 18:27:14 +02006544 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
Takashi Iwaid3d38352013-08-19 20:05:50 +02006545 SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
David Henningsson02f6ff92015-12-07 11:29:31 +01006546 SND_PCI_QUIRK(0x1025, 0x0241, "Packard Bell DOTS", ALC662_FIXUP_INV_DMIC),
David Henningssona6c47a82011-02-10 15:39:19 +01006547 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02006548 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Takashi Iwai125821a2012-06-22 14:30:29 +02006549 SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
Takashi Iwai18019282013-08-16 08:17:05 +02006550 SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
Daniel T Chen2df03512010-10-10 22:39:28 -04006551 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
David Henningsson73bdd592013-04-15 15:44:14 +02006552 SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
6553 SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
Takashi Iwaic5d019c2014-07-22 17:33:32 +02006554 SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13),
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02006555 SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13),
Niranjan Sivakumar467e1432015-09-05 18:20:35 +02006556 SND_PCI_QUIRK(0x1028, 0x060d, "Dell M3800", ALC668_FIXUP_DELL_XPS13),
David Henningsson09d20142013-11-20 11:43:30 +01006557 SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
David Henningssonad8ff992013-11-07 09:28:59 +01006558 SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
Kailang Yang8dc9abb2014-04-16 15:53:12 +08006559 SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
6560 SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
Kailang Yang6a98e342014-10-27 16:20:30 +08006561 SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02006562 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
David Henningsson8e54b4a2014-02-07 09:31:07 +01006563 SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A),
6564 SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
David Henningsson61a75f12014-02-07 09:31:08 +01006565 SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
6566 SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
David Henningsson8e54b4a2014-02-07 09:31:07 +01006567 SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
Takashi Iwai1565cc32012-02-13 12:03:25 +01006568 SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
Takashi Iwai53c334a2011-08-23 18:27:14 +02006569 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05006570 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06006571 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02006572 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
David Henningssonedfe3bf2012-06-12 13:15:12 +02006573 SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68),
Anisse Astierd2ebd472011-01-20 12:36:21 +01006574 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
Takashi Iwai53c334a2011-08-23 18:27:14 +02006575
6576#if 0
6577 /* Below is a quirk table taken from the old code.
6578 * Basically the device should work as is without the fixup table.
6579 * If BIOS doesn't give a proper info, enable the corresponding
6580 * fixup entry.
Jesper Juhl7d7eb9e2012-04-12 22:11:25 +02006581 */
Takashi Iwai53c334a2011-08-23 18:27:14 +02006582 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
6583 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
6584 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
6585 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
6586 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6587 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6588 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6589 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
6590 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
6591 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6592 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
6593 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
6594 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
6595 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
6596 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
6597 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6598 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
6599 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
6600 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6601 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
6602 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
6603 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6604 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
6605 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
6606 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
6607 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6608 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
6609 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
6610 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6611 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
6612 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6613 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6614 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
6615 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
6616 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
6617 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
6618 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
6619 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
6620 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
6621 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6622 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
6623 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
6624 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6625 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
6626 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
6627 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
6628 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
6629 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
6630 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6631 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
6632#endif
David Henningsson6cb3b702010-09-09 08:51:44 +02006633 {}
6634};
6635
Takashi Iwai1727a772013-01-10 09:52:52 +01006636static const struct hda_model_fixup alc662_fixup_models[] = {
Todd Broch6be79482010-12-07 16:51:05 -08006637 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
Takashi Iwai53c334a2011-08-23 18:27:14 +02006638 {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
6639 {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
6640 {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
6641 {.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
6642 {.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
6643 {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
6644 {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
6645 {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
Takashi Iwai6e72aa52012-06-25 10:52:25 +02006646 {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
David Henningssone32aa852013-06-17 11:04:02 +02006647 {.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
Todd Broch6be79482010-12-07 16:51:05 -08006648 {}
6649};
David Henningsson6cb3b702010-09-09 08:51:44 +02006650
Hui Wang532895c2014-05-29 15:59:19 +08006651static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = {
David Henningsson1f8b46c2015-05-12 14:38:15 +02006652 SND_HDA_PIN_QUIRK(0x10ec0662, 0x1028, "Dell", ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
David Henningsson1f8b46c2015-05-12 14:38:15 +02006653 {0x14, 0x01014010},
David Henningsson1f8b46c2015-05-12 14:38:15 +02006654 {0x18, 0x01a19020},
David Henningsson1f8b46c2015-05-12 14:38:15 +02006655 {0x1a, 0x0181302f},
Hui Wang11580292015-08-03 11:03:49 +08006656 {0x1b, 0x0221401f}),
David Henningsson76c21322014-06-24 14:46:54 +02006657 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
6658 {0x12, 0x99a30130},
6659 {0x14, 0x90170110},
6660 {0x15, 0x0321101f},
Hui Wang11580292015-08-03 11:03:49 +08006661 {0x16, 0x03011020}),
David Henningsson76c21322014-06-24 14:46:54 +02006662 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
6663 {0x12, 0x99a30140},
6664 {0x14, 0x90170110},
6665 {0x15, 0x0321101f},
Hui Wang11580292015-08-03 11:03:49 +08006666 {0x16, 0x03011020}),
David Henningsson76c21322014-06-24 14:46:54 +02006667 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
6668 {0x12, 0x99a30150},
6669 {0x14, 0x90170110},
6670 {0x15, 0x0321101f},
Hui Wang11580292015-08-03 11:03:49 +08006671 {0x16, 0x03011020}),
David Henningsson76c21322014-06-24 14:46:54 +02006672 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
David Henningsson76c21322014-06-24 14:46:54 +02006673 {0x14, 0x90170110},
6674 {0x15, 0x0321101f},
Hui Wang11580292015-08-03 11:03:49 +08006675 {0x16, 0x03011020}),
David Henningsson76c21322014-06-24 14:46:54 +02006676 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell XPS 15", ALC668_FIXUP_AUTO_MUTE,
6677 {0x12, 0x90a60130},
6678 {0x14, 0x90170110},
Hui Wang11580292015-08-03 11:03:49 +08006679 {0x15, 0x0321101f}),
Hui Wang532895c2014-05-29 15:59:19 +08006680 {}
6681};
6682
Takashi Iwai1d045db2011-07-07 18:23:21 +02006683/*
6684 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006685static int patch_alc662(struct hda_codec *codec)
6686{
6687 struct alc_spec *spec;
Takashi Iwai3de95172012-05-07 18:03:15 +02006688 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006689
Takashi Iwai3de95172012-05-07 18:03:15 +02006690 err = alc_alloc_spec(codec, 0x0b);
6691 if (err < 0)
6692 return err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006693
Takashi Iwai3de95172012-05-07 18:03:15 +02006694 spec = codec->spec;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02006695
Takashi Iwai225068a2015-05-29 10:42:14 +02006696 spec->shutup = alc_eapd_shutup;
6697
Takashi Iwai53c334a2011-08-23 18:27:14 +02006698 /* handle multiple HPs as is */
6699 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
6700
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02006701 alc_fix_pll_init(codec, 0x20, 0x04, 15);
6702
Takashi Iwai7639a062015-03-03 10:07:24 +01006703 switch (codec->core.vendor_id) {
Kailang Yangf3f91852014-10-24 15:43:46 +08006704 case 0x10ec0668:
6705 spec->init_hook = alc668_restore_default_value;
6706 break;
Kailang Yangf3f91852014-10-24 15:43:46 +08006707 }
Kailang Yang8663ff72012-06-29 09:35:52 +02006708
Takashi Iwai1727a772013-01-10 09:52:52 +01006709 snd_hda_pick_fixup(codec, alc662_fixup_models,
Takashi Iwai8e5a0502012-06-21 15:49:33 +02006710 alc662_fixup_tbl, alc662_fixups);
Hui Wang532895c2014-05-29 15:59:19 +08006711 snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01006712 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai8e5a0502012-06-21 15:49:33 +02006713
6714 alc_auto_parse_customize_define(codec);
6715
Takashi Iwai7504b6c2013-03-18 11:25:51 +01006716 if (has_cdefine_beep(codec))
6717 spec->gen.beep_nid = 0x01;
6718
Takashi Iwai1bb7e432011-10-17 16:50:59 +02006719 if ((alc_get_coef0(codec) & (1 << 14)) &&
Takashi Iwai5100cd02014-02-15 10:03:19 +01006720 codec->bus->pci && codec->bus->pci->subsystem_vendor == 0x1025 &&
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006721 spec->cdefine.platform_type == 1) {
Wei Yongjun6134b1a2013-04-18 11:12:59 +08006722 err = alc_codec_rename(codec, "ALC272X");
6723 if (err < 0)
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006724 goto error;
Takashi Iwai20ca0c32011-10-17 16:00:35 +02006725 }
Kailang Yang274693f2009-12-03 10:07:50 +01006726
Takashi Iwaib9c51062011-08-24 18:08:07 +02006727 /* automatic parse from the BIOS config */
6728 err = alc662_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006729 if (err < 0)
6730 goto error;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006731
Takashi Iwai7504b6c2013-03-18 11:25:51 +01006732 if (!spec->gen.no_analog && spec->gen.beep_nid) {
Takashi Iwai7639a062015-03-03 10:07:24 +01006733 switch (codec->core.vendor_id) {
Kailang Yangda00c242010-03-19 11:23:45 +01006734 case 0x10ec0662:
6735 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
6736 break;
6737 case 0x10ec0272:
6738 case 0x10ec0663:
6739 case 0x10ec0665:
Kailang Yang9ad54542013-11-26 15:41:40 +08006740 case 0x10ec0668:
Kailang Yangda00c242010-03-19 11:23:45 +01006741 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
6742 break;
6743 case 0x10ec0273:
6744 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
6745 break;
6746 }
Kailang Yangcec27c82010-02-04 14:18:18 +01006747 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01006748
Takashi Iwai1727a772013-01-10 09:52:52 +01006749 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01006750
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006751 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006752
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006753 error:
6754 alc_free(codec);
6755 return err;
Kailang Yangb478b992011-05-18 11:51:15 +02006756}
6757
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006758/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006759 * ALC680 support
6760 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006761
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006762static int alc680_parse_auto_config(struct hda_codec *codec)
6763{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006764 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006765}
6766
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006767/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006768 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006769static int patch_alc680(struct hda_codec *codec)
6770{
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006771 int err;
6772
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02006773 /* ALC680 has no aa-loopback mixer */
Takashi Iwai3de95172012-05-07 18:03:15 +02006774 err = alc_alloc_spec(codec, 0);
6775 if (err < 0)
6776 return err;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02006777
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02006778 /* automatic parse from the BIOS config */
6779 err = alc680_parse_auto_config(codec);
6780 if (err < 0) {
6781 alc_free(codec);
6782 return err;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006783 }
6784
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006785 return 0;
6786}
6787
6788/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006789 * patch entries
6790 */
Takashi Iwaib9a94a92015-10-01 16:20:04 +02006791static const struct hda_device_id snd_hda_id_realtek[] = {
6792 HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269),
6793 HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269),
6794 HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
6795 HDA_CODEC_ENTRY(0x10ec0235, "ALC233", patch_alc269),
6796 HDA_CODEC_ENTRY(0x10ec0255, "ALC255", patch_alc269),
6797 HDA_CODEC_ENTRY(0x10ec0256, "ALC256", patch_alc269),
6798 HDA_CODEC_ENTRY(0x10ec0260, "ALC260", patch_alc260),
6799 HDA_CODEC_ENTRY(0x10ec0262, "ALC262", patch_alc262),
6800 HDA_CODEC_ENTRY(0x10ec0267, "ALC267", patch_alc268),
6801 HDA_CODEC_ENTRY(0x10ec0268, "ALC268", patch_alc268),
6802 HDA_CODEC_ENTRY(0x10ec0269, "ALC269", patch_alc269),
6803 HDA_CODEC_ENTRY(0x10ec0270, "ALC270", patch_alc269),
6804 HDA_CODEC_ENTRY(0x10ec0272, "ALC272", patch_alc662),
6805 HDA_CODEC_ENTRY(0x10ec0275, "ALC275", patch_alc269),
6806 HDA_CODEC_ENTRY(0x10ec0276, "ALC276", patch_alc269),
6807 HDA_CODEC_ENTRY(0x10ec0280, "ALC280", patch_alc269),
6808 HDA_CODEC_ENTRY(0x10ec0282, "ALC282", patch_alc269),
6809 HDA_CODEC_ENTRY(0x10ec0283, "ALC283", patch_alc269),
6810 HDA_CODEC_ENTRY(0x10ec0284, "ALC284", patch_alc269),
6811 HDA_CODEC_ENTRY(0x10ec0285, "ALC285", patch_alc269),
6812 HDA_CODEC_ENTRY(0x10ec0286, "ALC286", patch_alc269),
6813 HDA_CODEC_ENTRY(0x10ec0288, "ALC288", patch_alc269),
6814 HDA_CODEC_ENTRY(0x10ec0290, "ALC290", patch_alc269),
6815 HDA_CODEC_ENTRY(0x10ec0292, "ALC292", patch_alc269),
6816 HDA_CODEC_ENTRY(0x10ec0293, "ALC293", patch_alc269),
6817 HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
6818 HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
6819 HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
6820 HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),
6821 HDA_CODEC_ENTRY(0x10ec0862, "ALC861-VD", patch_alc861vd),
6822 HDA_CODEC_REV_ENTRY(0x10ec0662, 0x100002, "ALC662 rev2", patch_alc882),
6823 HDA_CODEC_REV_ENTRY(0x10ec0662, 0x100101, "ALC662 rev1", patch_alc662),
6824 HDA_CODEC_REV_ENTRY(0x10ec0662, 0x100300, "ALC662 rev3", patch_alc662),
6825 HDA_CODEC_ENTRY(0x10ec0663, "ALC663", patch_alc662),
6826 HDA_CODEC_ENTRY(0x10ec0665, "ALC665", patch_alc662),
6827 HDA_CODEC_ENTRY(0x10ec0667, "ALC667", patch_alc662),
6828 HDA_CODEC_ENTRY(0x10ec0668, "ALC668", patch_alc662),
6829 HDA_CODEC_ENTRY(0x10ec0670, "ALC670", patch_alc662),
6830 HDA_CODEC_ENTRY(0x10ec0671, "ALC671", patch_alc662),
6831 HDA_CODEC_ENTRY(0x10ec0680, "ALC680", patch_alc680),
6832 HDA_CODEC_ENTRY(0x10ec0867, "ALC891", patch_alc882),
6833 HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880),
6834 HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882),
6835 HDA_CODEC_ENTRY(0x10ec0883, "ALC883", patch_alc882),
6836 HDA_CODEC_REV_ENTRY(0x10ec0885, 0x100101, "ALC889A", patch_alc882),
6837 HDA_CODEC_REV_ENTRY(0x10ec0885, 0x100103, "ALC889A", patch_alc882),
6838 HDA_CODEC_ENTRY(0x10ec0885, "ALC885", patch_alc882),
6839 HDA_CODEC_ENTRY(0x10ec0887, "ALC887", patch_alc882),
6840 HDA_CODEC_REV_ENTRY(0x10ec0888, 0x100101, "ALC1200", patch_alc882),
6841 HDA_CODEC_ENTRY(0x10ec0888, "ALC888", patch_alc882),
6842 HDA_CODEC_ENTRY(0x10ec0889, "ALC889", patch_alc882),
6843 HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662),
6844 HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882),
6845 HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882),
Linus Torvalds1da177e2005-04-16 15:20:36 -07006846 {} /* terminator */
6847};
Takashi Iwaib9a94a92015-10-01 16:20:04 +02006848MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_realtek);
Takashi Iwai1289e9e2008-11-27 15:47:11 +01006849
6850MODULE_LICENSE("GPL");
6851MODULE_DESCRIPTION("Realtek HD-audio codec");
6852
Takashi Iwaid8a766a2015-02-17 15:25:37 +01006853static struct hda_codec_driver realtek_driver = {
Takashi Iwaib9a94a92015-10-01 16:20:04 +02006854 .id = snd_hda_id_realtek,
Takashi Iwai1289e9e2008-11-27 15:47:11 +01006855};
6856
Takashi Iwaid8a766a2015-02-17 15:25:37 +01006857module_hda_codec_driver(realtek_driver);