blob: d446ac3137b37ac6f3512f8fa7830b537632bca8 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <sound/core.h>
Kailang Yang9ad0e492010-09-14 23:22:00 +020033#include <sound/jack.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include "hda_codec.h"
35#include "hda_local.h"
Takashi Iwai23d30f22012-05-07 17:17:32 +020036#include "hda_auto_parser.h"
Takashi Iwai1835a0f2011-10-27 22:12:46 +020037#include "hda_jack.h"
Takashi Iwai08c189f2012-12-19 15:22:24 +010038#include "hda_generic.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Takashi Iwaicd63a5f2013-07-05 12:13:59 +020040/* keep halting ALC5505 DSP, for power saving */
41#define HALT_REALTEK_ALC5505
42
Takashi Iwai1d045db2011-07-07 18:23:21 +020043/* unsol event tags */
Takashi Iwai08c189f2012-12-19 15:22:24 +010044#define ALC_DCVOL_EVENT 0x08
Takashi Iwaid4a86d82010-06-23 17:51:26 +020045
Kailang Yangdf694da2005-12-05 19:42:22 +010046/* for GPIO Poll */
47#define GPIO_MASK 0x03
48
Takashi Iwai4a79ba32009-04-22 16:31:35 +020049/* extra amp-initialization sequence types */
50enum {
51 ALC_INIT_NONE,
52 ALC_INIT_DEFAULT,
53 ALC_INIT_GPIO1,
54 ALC_INIT_GPIO2,
55 ALC_INIT_GPIO3,
56};
57
David Henningsson73bdd592013-04-15 15:44:14 +020058enum {
59 ALC_HEADSET_MODE_UNKNOWN,
60 ALC_HEADSET_MODE_UNPLUGGED,
61 ALC_HEADSET_MODE_HEADSET,
62 ALC_HEADSET_MODE_MIC,
63 ALC_HEADSET_MODE_HEADPHONE,
64};
65
66enum {
67 ALC_HEADSET_TYPE_UNKNOWN,
68 ALC_HEADSET_TYPE_CTIA,
69 ALC_HEADSET_TYPE_OMTP,
70};
71
Kailang Yangda00c242010-03-19 11:23:45 +010072struct alc_customize_define {
73 unsigned int sku_cfg;
74 unsigned char port_connectivity;
75 unsigned char check_sum;
76 unsigned char customization;
77 unsigned char external_amp;
78 unsigned int enable_pcbeep:1;
79 unsigned int platform_type:1;
80 unsigned int swap:1;
81 unsigned int override:1;
David Henningsson90622912010-10-14 14:50:18 +020082 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
Kailang Yangda00c242010-03-19 11:23:45 +010083};
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085struct alc_spec {
Takashi Iwai08c189f2012-12-19 15:22:24 +010086 struct hda_gen_spec gen; /* must be at head */
Takashi Iwai23d30f22012-05-07 17:17:32 +020087
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 /* codec parameterization */
Takashi Iwaia9111322011-05-02 11:30:18 +020089 const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 unsigned int num_mixers;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +010091 unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
Kailang Yangda00c242010-03-19 11:23:45 +010093 struct alc_customize_define cdefine;
Takashi Iwai08c189f2012-12-19 15:22:24 +010094 unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
95
96 /* inverted dmic fix */
97 unsigned int inv_dmic_fixup:1; /* has inverted digital-mic workaround */
98 unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */
Takashi Iwai125821a2012-06-22 14:30:29 +020099 hda_nid_t inv_dmic_pin;
Takashi Iwai834be882006-03-01 14:16:17 +0100100
Takashi Iwai08fb0d02013-01-10 17:33:58 +0100101 /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
102 int mute_led_polarity;
103 hda_nid_t mute_led_nid;
Kailang Yang9c5dc3b2014-06-19 16:11:36 +0800104 hda_nid_t cap_mute_led_nid;
Takashi Iwai08fb0d02013-01-10 17:33:58 +0100105
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +0100106 unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
107
David Henningsson73bdd592013-04-15 15:44:14 +0200108 hda_nid_t headset_mic_pin;
109 hda_nid_t headphone_mic_pin;
110 int current_headset_mode;
111 int current_headset_type;
112
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100113 /* hooks */
114 void (*init_hook)(struct hda_codec *codec);
Takashi Iwai83012a72012-08-24 18:38:08 +0200115#ifdef CONFIG_PM
Daniel T Chenc97259d2009-12-27 18:52:08 -0500116 void (*power_hook)(struct hda_codec *codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100117#endif
Takashi Iwai1c7161532011-04-07 10:37:16 +0200118 void (*shutup)(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;
Kailang Yangdf694da2005-12-05 19:42:22 +0100129};
130
Takashi Iwai23f0c042009-02-26 13:03:58 +0100131/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200132 * Append the given mixer and verb elements for the later use
133 * The mixer array is referred in build_controls(), and init_verbs are
134 * called in init().
Takashi Iwaid88897e2008-10-31 15:01:37 +0100135 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200136static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix)
Takashi Iwaid88897e2008-10-31 15:01:37 +0100137{
138 if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
139 return;
140 spec->mixers[spec->num_mixers++] = mix;
141}
142
Takashi Iwaid88897e2008-10-31 15:01:37 +0100143/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200144 * GPIO setup tables, used in initialization
Kailang Yangdf694da2005-12-05 19:42:22 +0100145 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200146/* Enable GPIO mask and set output */
Takashi Iwaia9111322011-05-02 11:30:18 +0200147static const struct hda_verb alc_gpio1_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200148 {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
149 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
150 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
151 { }
152};
153
Takashi Iwaia9111322011-05-02 11:30:18 +0200154static const struct hda_verb alc_gpio2_init_verbs[] = {
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200155 {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
156 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
157 {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
158 { }
159};
160
Takashi Iwaia9111322011-05-02 11:30:18 +0200161static const struct hda_verb alc_gpio3_init_verbs[] = {
Kailang Yangbdd148a2007-05-08 15:19:08 +0200162 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
163 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
164 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
165 { }
166};
167
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200168/*
169 * Fix hardware PLL issue
170 * On some codecs, the analog PLL gating control must be off while
171 * the default value is 1.
172 */
173static void alc_fix_pll(struct hda_codec *codec)
174{
175 struct alc_spec *spec = codec->spec;
176 unsigned int val;
177
178 if (!spec->pll_nid)
179 return;
180 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
181 spec->pll_coef_idx);
182 val = snd_hda_codec_read(codec, spec->pll_nid, 0,
183 AC_VERB_GET_PROC_COEF, 0);
Takashi Iwaif3ee07d2014-08-15 17:35:00 +0200184 if (val == -1)
185 return;
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200186 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_COEF_INDEX,
187 spec->pll_coef_idx);
188 snd_hda_codec_write(codec, spec->pll_nid, 0, AC_VERB_SET_PROC_COEF,
189 val & ~(1 << spec->pll_coef_bit));
190}
191
192static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
193 unsigned int coef_idx, unsigned int coef_bit)
194{
195 struct alc_spec *spec = codec->spec;
196 spec->pll_nid = nid;
197 spec->pll_coef_idx = coef_idx;
198 spec->pll_coef_bit = coef_bit;
199 alc_fix_pll(codec);
200}
201
Takashi Iwaicf5a2272012-02-20 16:31:07 +0100202/* update the master volume per volume-knob's unsol event */
David Henningsson29adc4b2012-09-25 11:31:00 +0200203static void alc_update_knob_master(struct hda_codec *codec, struct hda_jack_tbl *jack)
Takashi Iwaicf5a2272012-02-20 16:31:07 +0100204{
205 unsigned int val;
206 struct snd_kcontrol *kctl;
207 struct snd_ctl_elem_value *uctl;
208
209 kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
210 if (!kctl)
211 return;
212 uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
213 if (!uctl)
214 return;
David Henningsson29adc4b2012-09-25 11:31:00 +0200215 val = snd_hda_codec_read(codec, jack->nid, 0,
Takashi Iwaicf5a2272012-02-20 16:31:07 +0100216 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
217 val &= HDA_AMP_VOLMASK;
218 uctl->value.integer.value[0] = val;
219 uctl->value.integer.value[1] = val;
220 kctl->put(kctl, uctl);
221 kfree(uctl);
222}
223
David Henningsson29adc4b2012-09-25 11:31:00 +0200224static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
Takashi Iwaif21d78e2012-01-19 12:10:29 +0100225{
David Henningsson29adc4b2012-09-25 11:31:00 +0200226 /* For some reason, the res given from ALC880 is broken.
227 Here we adjust it properly. */
228 snd_hda_jack_unsol_event(codec, res >> 2);
Takashi Iwaif21d78e2012-01-19 12:10:29 +0100229}
230
Kailang Yangf9423e72008-05-27 12:32:25 +0200231/* additional initialization for ALC888 variants */
232static void alc888_coef_init(struct hda_codec *codec)
233{
234 unsigned int tmp;
235
236 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 0);
237 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
238 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
Takashi Iwai37db6232009-03-05 09:40:16 +0100239 if ((tmp & 0xf0) == 0x20)
Kailang Yangf9423e72008-05-27 12:32:25 +0200240 /* alc888S-VC */
241 snd_hda_codec_read(codec, 0x20, 0,
242 AC_VERB_SET_PROC_COEF, 0x830);
243 else
244 /* alc888-VB */
245 snd_hda_codec_read(codec, 0x20, 0,
246 AC_VERB_SET_PROC_COEF, 0x3030);
247}
248
Takashi Iwai1d045db2011-07-07 18:23:21 +0200249/* additional initialization for ALC889 variants */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200250static void alc889_coef_init(struct hda_codec *codec)
251{
252 unsigned int tmp;
253
254 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
255 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
256 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7);
257 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, tmp|0x2010);
258}
259
Takashi Iwai3fb4a502010-01-19 15:46:37 +0100260/* turn on/off EAPD control (only if available) */
261static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
262{
263 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
264 return;
265 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
266 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
267 on ? 2 : 0);
268}
269
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200270/* turn on/off EAPD controls of the codec */
271static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
272{
273 /* We currently only handle front, HP */
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200274 static hda_nid_t pins[] = {
275 0x0f, 0x10, 0x14, 0x15, 0
276 };
277 hda_nid_t *p;
278 for (p = pins; *p; p++)
279 set_eapd(codec, *p, on);
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200280}
281
Takashi Iwai1c7161532011-04-07 10:37:16 +0200282/* generic shutup callback;
283 * just turning off EPAD and a little pause for avoiding pop-noise
284 */
285static void alc_eapd_shutup(struct hda_codec *codec)
286{
Kailang Yang97a26572013-11-29 00:35:26 -0500287 struct alc_spec *spec = codec->spec;
288
Takashi Iwai1c7161532011-04-07 10:37:16 +0200289 alc_auto_setup_eapd(codec, false);
Kailang Yang97a26572013-11-29 00:35:26 -0500290 if (!spec->no_depop_delay)
291 msleep(200);
Takashi Iwai9bfb2842013-07-24 14:31:50 +0200292 snd_hda_shutup_pins(codec);
Takashi Iwai1c7161532011-04-07 10:37:16 +0200293}
294
Takashi Iwai1d045db2011-07-07 18:23:21 +0200295/* generic EAPD initialization */
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200296static void alc_auto_init_amp(struct hda_codec *codec, int type)
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200297{
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200298 unsigned int tmp;
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200299
Takashi Iwai39fa84e2011-06-27 15:28:57 +0200300 alc_auto_setup_eapd(codec, true);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200301 switch (type) {
302 case ALC_INIT_GPIO1:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200303 snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
304 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200305 case ALC_INIT_GPIO2:
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200306 snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
307 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200308 case ALC_INIT_GPIO3:
Kailang Yangbdd148a2007-05-08 15:19:08 +0200309 snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
310 break;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200311 case ALC_INIT_DEFAULT:
Kailang Yangc9b58002007-10-16 14:30:01 +0200312 switch (codec->vendor_id) {
313 case 0x10ec0260:
314 snd_hda_codec_write(codec, 0x1a, 0,
315 AC_VERB_SET_COEF_INDEX, 7);
316 tmp = snd_hda_codec_read(codec, 0x1a, 0,
317 AC_VERB_GET_PROC_COEF, 0);
318 snd_hda_codec_write(codec, 0x1a, 0,
319 AC_VERB_SET_COEF_INDEX, 7);
320 snd_hda_codec_write(codec, 0x1a, 0,
321 AC_VERB_SET_PROC_COEF,
322 tmp | 0x2010);
323 break;
324 case 0x10ec0262:
325 case 0x10ec0880:
326 case 0x10ec0882:
327 case 0x10ec0883:
328 case 0x10ec0885:
Takashi Iwai4a5a4c52009-02-06 12:46:59 +0100329 case 0x10ec0887:
Takashi Iwai20b67dd2011-03-23 22:54:32 +0100330 /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
Jaroslav Kysela87a8c372009-07-23 10:58:29 +0200331 alc889_coef_init(codec);
Kailang Yangc9b58002007-10-16 14:30:01 +0200332 break;
Kailang Yangf9423e72008-05-27 12:32:25 +0200333 case 0x10ec0888:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200334 alc888_coef_init(codec);
Kailang Yangf9423e72008-05-27 12:32:25 +0200335 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100336#if 0 /* XXX: This may cause the silent output on speaker on some machines */
Kailang Yangc9b58002007-10-16 14:30:01 +0200337 case 0x10ec0267:
338 case 0x10ec0268:
339 snd_hda_codec_write(codec, 0x20, 0,
340 AC_VERB_SET_COEF_INDEX, 7);
341 tmp = snd_hda_codec_read(codec, 0x20, 0,
342 AC_VERB_GET_PROC_COEF, 0);
343 snd_hda_codec_write(codec, 0x20, 0,
Kailang Yangea1fb292008-08-26 12:58:38 +0200344 AC_VERB_SET_COEF_INDEX, 7);
Kailang Yangc9b58002007-10-16 14:30:01 +0200345 snd_hda_codec_write(codec, 0x20, 0,
346 AC_VERB_SET_PROC_COEF,
347 tmp | 0x3000);
348 break;
Takashi Iwai0aea7782010-01-25 15:44:11 +0100349#endif /* XXX */
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200350 }
Kailang Yangbc9f98a2007-04-12 13:06:07 +0200351 break;
352 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200353}
Kailang Yangea1fb292008-08-26 12:58:38 +0200354
Takashi Iwai1d045db2011-07-07 18:23:21 +0200355
356/*
357 * Realtek SSID verification
358 */
359
David Henningsson90622912010-10-14 14:50:18 +0200360/* Could be any non-zero and even value. When used as fixup, tells
361 * the driver to ignore any present sku defines.
362 */
363#define ALC_FIXUP_SKU_IGNORE (2)
364
Takashi Iwai23d30f22012-05-07 17:17:32 +0200365static void alc_fixup_sku_ignore(struct hda_codec *codec,
366 const struct hda_fixup *fix, int action)
367{
368 struct alc_spec *spec = codec->spec;
369 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
370 spec->cdefine.fixup = 1;
371 spec->cdefine.sku_cfg = ALC_FIXUP_SKU_IGNORE;
372 }
373}
374
Mengdong Linb5c66112013-11-29 00:35:35 -0500375static void alc_fixup_no_depop_delay(struct hda_codec *codec,
376 const struct hda_fixup *fix, int action)
377{
378 struct alc_spec *spec = codec->spec;
379
Mengdong Lin84d2dc32013-12-02 22:26:03 -0500380 if (action == HDA_FIXUP_ACT_PROBE) {
Mengdong Linb5c66112013-11-29 00:35:35 -0500381 spec->no_depop_delay = 1;
Mengdong Lin84d2dc32013-12-02 22:26:03 -0500382 codec->depop_delay = 0;
383 }
Mengdong Linb5c66112013-11-29 00:35:35 -0500384}
385
Kailang Yangda00c242010-03-19 11:23:45 +0100386static int alc_auto_parse_customize_define(struct hda_codec *codec)
387{
388 unsigned int ass, tmp, i;
Takashi Iwai7fb56222010-03-22 17:09:47 +0100389 unsigned nid = 0;
Kailang Yangda00c242010-03-19 11:23:45 +0100390 struct alc_spec *spec = codec->spec;
391
Takashi Iwaib6cbe512010-07-28 17:43:36 +0200392 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
393
David Henningsson90622912010-10-14 14:50:18 +0200394 if (spec->cdefine.fixup) {
395 ass = spec->cdefine.sku_cfg;
396 if (ass == ALC_FIXUP_SKU_IGNORE)
397 return -1;
398 goto do_sku;
399 }
400
Takashi Iwai5100cd02014-02-15 10:03:19 +0100401 if (!codec->bus->pci)
402 return -1;
Kailang Yangda00c242010-03-19 11:23:45 +0100403 ass = codec->subsystem_id & 0xffff;
Takashi Iwaib6cbe512010-07-28 17:43:36 +0200404 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
Kailang Yangda00c242010-03-19 11:23:45 +0100405 goto do_sku;
406
407 nid = 0x1d;
408 if (codec->vendor_id == 0x10ec0260)
409 nid = 0x17;
410 ass = snd_hda_codec_get_pincfg(codec, nid);
411
412 if (!(ass & 1)) {
Takashi Iwai4e76a882014-02-25 12:21:03 +0100413 codec_info(codec, "%s: SKU not ready 0x%08x\n",
414 codec->chip_name, ass);
Kailang Yangda00c242010-03-19 11:23:45 +0100415 return -1;
416 }
417
418 /* check sum */
419 tmp = 0;
420 for (i = 1; i < 16; i++) {
421 if ((ass >> i) & 1)
422 tmp++;
423 }
424 if (((ass >> 16) & 0xf) != tmp)
425 return -1;
426
427 spec->cdefine.port_connectivity = ass >> 30;
428 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
429 spec->cdefine.check_sum = (ass >> 16) & 0xf;
430 spec->cdefine.customization = ass >> 8;
431do_sku:
432 spec->cdefine.sku_cfg = ass;
433 spec->cdefine.external_amp = (ass & 0x38) >> 3;
434 spec->cdefine.platform_type = (ass & 0x4) >> 2;
435 spec->cdefine.swap = (ass & 0x2) >> 1;
436 spec->cdefine.override = ass & 0x1;
437
Takashi Iwai4e76a882014-02-25 12:21:03 +0100438 codec_dbg(codec, "SKU: Nid=0x%x sku_cfg=0x%08x\n",
Kailang Yangda00c242010-03-19 11:23:45 +0100439 nid, spec->cdefine.sku_cfg);
Takashi Iwai4e76a882014-02-25 12:21:03 +0100440 codec_dbg(codec, "SKU: port_connectivity=0x%x\n",
Kailang Yangda00c242010-03-19 11:23:45 +0100441 spec->cdefine.port_connectivity);
Takashi Iwai4e76a882014-02-25 12:21:03 +0100442 codec_dbg(codec, "SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
443 codec_dbg(codec, "SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
444 codec_dbg(codec, "SKU: customization=0x%08x\n", spec->cdefine.customization);
445 codec_dbg(codec, "SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
446 codec_dbg(codec, "SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
447 codec_dbg(codec, "SKU: swap=0x%x\n", spec->cdefine.swap);
448 codec_dbg(codec, "SKU: override=0x%x\n", spec->cdefine.override);
Kailang Yangda00c242010-03-19 11:23:45 +0100449
450 return 0;
451}
452
Takashi Iwai08c189f2012-12-19 15:22:24 +0100453/* return the position of NID in the list, or -1 if not found */
454static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
455{
456 int i;
457 for (i = 0; i < nums; i++)
458 if (list[i] == nid)
459 return i;
460 return -1;
461}
Takashi Iwai1d045db2011-07-07 18:23:21 +0200462/* return true if the given NID is found in the list */
Takashi Iwai3af9ee62011-06-27 12:34:01 +0200463static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
464{
Takashi Iwai21268962011-07-07 15:01:13 +0200465 return find_idx_in_nid_list(nid, list, nums) >= 0;
Takashi Iwai3af9ee62011-06-27 12:34:01 +0200466}
467
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200468/* check subsystem ID and set up device-specific initialization;
469 * return 1 if initialized, 0 if invalid SSID
470 */
471/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
472 * 31 ~ 16 : Manufacture ID
473 * 15 ~ 8 : SKU ID
474 * 7 ~ 0 : Assembly ID
475 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
476 */
Takashi Iwai58c57cf2014-01-07 18:22:49 +0100477static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200478{
479 unsigned int ass, tmp, i;
480 unsigned nid;
481 struct alc_spec *spec = codec->spec;
482
David Henningsson90622912010-10-14 14:50:18 +0200483 if (spec->cdefine.fixup) {
484 ass = spec->cdefine.sku_cfg;
485 if (ass == ALC_FIXUP_SKU_IGNORE)
486 return 0;
487 goto do_sku;
488 }
489
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200490 ass = codec->subsystem_id & 0xffff;
Takashi Iwai5100cd02014-02-15 10:03:19 +0100491 if (codec->bus->pci &&
492 ass != codec->bus->pci->subsystem_device && (ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200493 goto do_sku;
494
495 /* invalid SSID, check the special NID pin defcfg instead */
496 /*
Sasha Alexandrdef319f2009-06-16 16:00:15 -0400497 * 31~30 : port connectivity
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200498 * 29~21 : reserve
499 * 20 : PCBEEP input
500 * 19~16 : Check sum (15:1)
501 * 15~1 : Custom
502 * 0 : override
503 */
504 nid = 0x1d;
505 if (codec->vendor_id == 0x10ec0260)
506 nid = 0x17;
507 ass = snd_hda_codec_get_pincfg(codec, nid);
Takashi Iwai4e76a882014-02-25 12:21:03 +0100508 codec_dbg(codec,
509 "realtek: No valid SSID, checking pincfg 0x%08x for NID 0x%x\n",
Takashi Iwaicb6605c2009-04-28 13:03:19 +0200510 ass, nid);
Kailang Yang6227cdc2010-02-25 08:36:52 +0100511 if (!(ass & 1))
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200512 return 0;
513 if ((ass >> 30) != 1) /* no physical connection */
514 return 0;
515
516 /* check sum */
517 tmp = 0;
518 for (i = 1; i < 16; i++) {
519 if ((ass >> i) & 1)
520 tmp++;
521 }
522 if (((ass >> 16) & 0xf) != tmp)
523 return 0;
524do_sku:
Takashi Iwai4e76a882014-02-25 12:21:03 +0100525 codec_dbg(codec, "realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200526 ass & 0xffff, codec->vendor_id);
527 /*
528 * 0 : override
529 * 1 : Swap Jack
530 * 2 : 0 --> Desktop, 1 --> Laptop
531 * 3~5 : External Amplifier control
532 * 7~6 : Reserved
533 */
534 tmp = (ass & 0x38) >> 3; /* external Amp control */
535 switch (tmp) {
536 case 1:
537 spec->init_amp = ALC_INIT_GPIO1;
538 break;
539 case 3:
540 spec->init_amp = ALC_INIT_GPIO2;
541 break;
542 case 7:
543 spec->init_amp = ALC_INIT_GPIO3;
544 break;
545 case 5:
Takashi Iwai5a8cfb42010-11-26 17:11:18 +0100546 default:
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200547 spec->init_amp = ALC_INIT_DEFAULT;
548 break;
549 }
550
551 /* is laptop or Desktop and enable the function "Mute internal speaker
552 * when the external headphone out jack is plugged"
553 */
554 if (!(ass & 0x8000))
555 return 1;
556 /*
557 * 10~8 : Jack location
558 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
559 * 14~13: Resvered
560 * 15 : 1 --> enable the function "Mute internal speaker
561 * when the external headphone out jack is plugged"
562 */
Takashi Iwai08c189f2012-12-19 15:22:24 +0100563 if (!spec->gen.autocfg.hp_pins[0] &&
564 !(spec->gen.autocfg.line_out_pins[0] &&
565 spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
Takashi Iwai01d48252009-10-06 13:21:54 +0200566 hda_nid_t nid;
Kailang Yangc9b58002007-10-16 14:30:01 +0200567 tmp = (ass >> 11) & 0x3; /* HP to chassis */
Takashi Iwai58c57cf2014-01-07 18:22:49 +0100568 nid = ports[tmp];
Takashi Iwai08c189f2012-12-19 15:22:24 +0100569 if (found_in_nid_list(nid, spec->gen.autocfg.line_out_pins,
570 spec->gen.autocfg.line_outs))
Takashi Iwai3af9ee62011-06-27 12:34:01 +0200571 return 1;
Takashi Iwai08c189f2012-12-19 15:22:24 +0100572 spec->gen.autocfg.hp_pins[0] = nid;
Kailang Yangc9b58002007-10-16 14:30:01 +0200573 }
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200574 return 1;
575}
Kailang Yangea1fb292008-08-26 12:58:38 +0200576
Takashi Iwai3e6179b2011-07-08 16:55:13 +0200577/* Check the validity of ALC subsystem-id
578 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
579static void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200580{
Takashi Iwai58c57cf2014-01-07 18:22:49 +0100581 if (!alc_subsystem_id(codec, ports)) {
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200582 struct alc_spec *spec = codec->spec;
Takashi Iwai4e76a882014-02-25 12:21:03 +0100583 codec_dbg(codec,
584 "realtek: Enable default setup for auto mode as fallback\n");
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200585 spec->init_amp = ALC_INIT_DEFAULT;
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200586 }
Takashi Iwai21268962011-07-07 15:01:13 +0200587}
Takashi Iwai1a1455d2011-04-28 17:36:18 +0200588
Takashi Iwai41e41f12005-06-08 14:48:49 +0200589/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200590 * COEF access helper functions
591 */
Kailang Yang9a22a8f52013-11-08 15:54:49 +0800592
593static int alc_read_coefex_idx(struct hda_codec *codec,
594 hda_nid_t nid,
595 unsigned int coef_idx)
Kailang Yang274693f2009-12-03 10:07:50 +0100596{
597 unsigned int val;
Kailang Yang9a22a8f52013-11-08 15:54:49 +0800598 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX,
Kailang Yang274693f2009-12-03 10:07:50 +0100599 coef_idx);
Kailang Yang9a22a8f52013-11-08 15:54:49 +0800600 val = snd_hda_codec_read(codec, nid, 0,
Kailang Yang274693f2009-12-03 10:07:50 +0100601 AC_VERB_GET_PROC_COEF, 0);
602 return val;
603}
604
Kailang Yang9a22a8f52013-11-08 15:54:49 +0800605#define alc_read_coef_idx(codec, coef_idx) \
606 alc_read_coefex_idx(codec, 0x20, coef_idx)
607
608static void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
609 unsigned int coef_idx,
Kailang Yang977ddd62010-09-15 10:02:29 +0200610 unsigned int coef_val)
611{
Kailang Yang9a22a8f52013-11-08 15:54:49 +0800612 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX,
Kailang Yang977ddd62010-09-15 10:02:29 +0200613 coef_idx);
Kailang Yang9a22a8f52013-11-08 15:54:49 +0800614 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF,
Kailang Yang977ddd62010-09-15 10:02:29 +0200615 coef_val);
616}
617
Kailang Yang9a22a8f52013-11-08 15:54:49 +0800618#define alc_write_coef_idx(codec, coef_idx, coef_val) \
619 alc_write_coefex_idx(codec, 0x20, coef_idx, coef_val)
620
Takashi Iwai1bb7e432011-10-17 16:50:59 +0200621/* a special bypass for COEF 0; read the cached value at the second time */
622static unsigned int alc_get_coef0(struct hda_codec *codec)
623{
624 struct alc_spec *spec = codec->spec;
625 if (!spec->coef0)
626 spec->coef0 = alc_read_coef_idx(codec, 0);
627 return spec->coef0;
628}
629
Takashi Iwai1d045db2011-07-07 18:23:21 +0200630/*
Takashi Iwai1d045db2011-07-07 18:23:21 +0200631 */
632
Takashi Iwai08c189f2012-12-19 15:22:24 +0100633static hda_nid_t get_adc_nid(struct hda_codec *codec, int adc_idx, int imux_idx)
Takashi Iwai757899a2010-07-30 10:48:14 +0200634{
Takashi Iwai08c189f2012-12-19 15:22:24 +0100635 struct hda_gen_spec *spec = codec->spec;
636 if (spec->dyn_adc_switch)
637 adc_idx = spec->dyn_adc_idx[imux_idx];
638 return spec->adc_nids[adc_idx];
Takashi Iwaif9e336f2008-10-31 16:37:07 +0100639}
640
Takashi Iwai666a70d2012-12-17 20:29:29 +0100641static void alc_inv_dmic_sync_adc(struct hda_codec *codec, int adc_idx)
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200642{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 struct alc_spec *spec = codec->spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +0100644 struct hda_input_mux *imux = &spec->gen.input_mux;
Takashi Iwai666a70d2012-12-17 20:29:29 +0100645 struct nid_path *path;
646 hda_nid_t nid;
647 int i, dir, parm;
648 unsigned int val;
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200649
Takashi Iwai666a70d2012-12-17 20:29:29 +0100650 for (i = 0; i < imux->num_items; i++) {
Takashi Iwai08c189f2012-12-19 15:22:24 +0100651 if (spec->gen.imux_pins[i] == spec->inv_dmic_pin)
Takashi Iwai666a70d2012-12-17 20:29:29 +0100652 break;
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200653 }
Takashi Iwai666a70d2012-12-17 20:29:29 +0100654 if (i >= imux->num_items)
655 return;
Takashi Iwaia23b6882009-03-23 15:21:36 +0100656
Takashi Iwai08c189f2012-12-19 15:22:24 +0100657 path = snd_hda_get_nid_path(codec, spec->inv_dmic_pin,
658 get_adc_nid(codec, adc_idx, i));
Takashi Iwai666a70d2012-12-17 20:29:29 +0100659 val = path->ctls[NID_PATH_MUTE_CTL];
660 if (!val)
661 return;
662 nid = get_amp_nid_(val);
663 dir = get_amp_direction_(val);
664 parm = AC_AMP_SET_RIGHT |
665 (dir == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT);
Takashi Iwaia23b6882009-03-23 15:21:36 +0100666
Takashi Iwaic4f3ebe2012-12-20 11:33:20 +0100667 /* flush all cached amps at first */
Takashi Iwaidc870f32013-01-22 15:24:30 +0100668 snd_hda_codec_flush_cache(codec);
Takashi Iwaic4f3ebe2012-12-20 11:33:20 +0100669
Takashi Iwai666a70d2012-12-17 20:29:29 +0100670 /* we care only right channel */
671 val = snd_hda_codec_amp_read(codec, nid, 1, dir, 0);
672 if (val & 0x80) /* if already muted, we don't need to touch */
673 return;
674 val |= 0x80;
675 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
676 parm | val);
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200677}
678
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200679/*
Takashi Iwai125821a2012-06-22 14:30:29 +0200680 * Inverted digital-mic handling
681 *
682 * First off, it's a bit tricky. The "Inverted Internal Mic Capture Switch"
683 * gives the additional mute only to the right channel of the digital mic
684 * capture stream. This is a workaround for avoiding the almost silence
685 * by summing the stereo stream from some (known to be ForteMedia)
686 * digital mic unit.
687 *
688 * The logic is to call alc_inv_dmic_sync() after each action (possibly)
689 * modifying ADC amp. When the mute flag is set, it mutes the R-channel
690 * without caching so that the cache can still keep the original value.
691 * The cached value is then restored when the flag is set off or any other
692 * than d-mic is used as the current input source.
693 */
694static void alc_inv_dmic_sync(struct hda_codec *codec, bool force)
695{
696 struct alc_spec *spec = codec->spec;
Takashi Iwai666a70d2012-12-17 20:29:29 +0100697 int src, nums;
Takashi Iwai125821a2012-06-22 14:30:29 +0200698
699 if (!spec->inv_dmic_fixup)
700 return;
701 if (!spec->inv_dmic_muted && !force)
702 return;
Takashi Iwai08c189f2012-12-19 15:22:24 +0100703 nums = spec->gen.dyn_adc_switch ? 1 : spec->gen.num_adc_nids;
Takashi Iwai666a70d2012-12-17 20:29:29 +0100704 for (src = 0; src < nums; src++) {
Takashi Iwai125821a2012-06-22 14:30:29 +0200705 bool dmic_fixup = false;
Takashi Iwai125821a2012-06-22 14:30:29 +0200706
707 if (spec->inv_dmic_muted &&
Takashi Iwai08c189f2012-12-19 15:22:24 +0100708 spec->gen.imux_pins[spec->gen.cur_mux[src]] == spec->inv_dmic_pin)
Takashi Iwai125821a2012-06-22 14:30:29 +0200709 dmic_fixup = true;
710 if (!dmic_fixup && !force)
711 continue;
Takashi Iwai666a70d2012-12-17 20:29:29 +0100712 alc_inv_dmic_sync_adc(codec, src);
Takashi Iwai125821a2012-06-22 14:30:29 +0200713 }
714}
715
Takashi Iwaia90229e2013-01-18 14:10:00 +0100716static void alc_inv_dmic_hook(struct hda_codec *codec,
Takashi Iwai7fe30712014-01-30 17:59:02 +0100717 struct snd_kcontrol *kcontrol,
718 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai08c189f2012-12-19 15:22:24 +0100719{
720 alc_inv_dmic_sync(codec, false);
721}
722
Takashi Iwai125821a2012-06-22 14:30:29 +0200723static int alc_inv_dmic_sw_get(struct snd_kcontrol *kcontrol,
724 struct snd_ctl_elem_value *ucontrol)
725{
726 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
727 struct alc_spec *spec = codec->spec;
728
729 ucontrol->value.integer.value[0] = !spec->inv_dmic_muted;
730 return 0;
731}
732
733static int alc_inv_dmic_sw_put(struct snd_kcontrol *kcontrol,
734 struct snd_ctl_elem_value *ucontrol)
735{
736 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
737 struct alc_spec *spec = codec->spec;
738 unsigned int val = !ucontrol->value.integer.value[0];
739
740 if (val == spec->inv_dmic_muted)
741 return 0;
742 spec->inv_dmic_muted = val;
743 alc_inv_dmic_sync(codec, true);
744 return 0;
745}
746
747static const struct snd_kcontrol_new alc_inv_dmic_sw = {
748 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
Takashi Iwaibc549762012-12-18 15:35:11 +0100749 .name = "Inverted Internal Mic Capture Switch",
Takashi Iwai125821a2012-06-22 14:30:29 +0200750 .info = snd_ctl_boolean_mono_info,
751 .get = alc_inv_dmic_sw_get,
752 .put = alc_inv_dmic_sw_put,
753};
754
755static int alc_add_inv_dmic_mixer(struct hda_codec *codec, hda_nid_t nid)
756{
757 struct alc_spec *spec = codec->spec;
Takashi Iwai668d1e92012-11-29 14:10:17 +0100758
Takashi Iwai08c189f2012-12-19 15:22:24 +0100759 if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &alc_inv_dmic_sw))
Takashi Iwai125821a2012-06-22 14:30:29 +0200760 return -ENOMEM;
761 spec->inv_dmic_fixup = 1;
762 spec->inv_dmic_muted = 0;
763 spec->inv_dmic_pin = nid;
Takashi Iwai08c189f2012-12-19 15:22:24 +0100764 spec->gen.cap_sync_hook = alc_inv_dmic_hook;
Takashi Iwai125821a2012-06-22 14:30:29 +0200765 return 0;
766}
767
Takashi Iwai6e72aa52012-06-25 10:52:25 +0200768/* typically the digital mic is put at node 0x12 */
769static void alc_fixup_inv_dmic_0x12(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +0100770 const struct hda_fixup *fix, int action)
Takashi Iwai6e72aa52012-06-25 10:52:25 +0200771{
Takashi Iwai1727a772013-01-10 09:52:52 +0100772 if (action == HDA_FIXUP_ACT_PROBE)
Takashi Iwai6e72aa52012-06-25 10:52:25 +0200773 alc_add_inv_dmic_mixer(codec, 0x12);
774}
775
Takashi Iwai603c4012008-07-30 15:01:44 +0200776
Takashi Iwai67d634c2009-11-16 15:35:59 +0100777#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100778/* additional beep mixers; the actual parameters are overwritten at build */
Takashi Iwaia9111322011-05-02 11:30:18 +0200779static const struct snd_kcontrol_new alc_beep_mixer[] = {
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100780 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
Jaroslav Kysela123c07a2009-10-21 14:48:23 +0200781 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100782 { } /* end */
783};
Takashi Iwai67d634c2009-11-16 15:35:59 +0100784#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100785
Takashi Iwai2eab6942012-12-18 15:30:41 +0100786static int alc_build_controls(struct hda_codec *codec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787{
788 struct alc_spec *spec = codec->spec;
Takashi Iwai666a70d2012-12-17 20:29:29 +0100789 int i, err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Takashi Iwai08c189f2012-12-19 15:22:24 +0100791 err = snd_hda_gen_build_controls(codec);
792 if (err < 0)
793 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
795 for (i = 0; i < spec->num_mixers; i++) {
796 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
797 if (err < 0)
798 return err;
799 }
Takashi Iwai2134ea42008-01-10 16:53:55 +0100800
Takashi Iwai67d634c2009-11-16 15:35:59 +0100801#ifdef CONFIG_SND_HDA_INPUT_BEEP
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100802 /* create beep controls if needed */
803 if (spec->beep_amp) {
Takashi Iwaia9111322011-05-02 11:30:18 +0200804 const struct snd_kcontrol_new *knew;
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100805 for (knew = alc_beep_mixer; knew->name; knew++) {
806 struct snd_kcontrol *kctl;
807 kctl = snd_ctl_new1(knew, codec);
808 if (!kctl)
809 return -ENOMEM;
810 kctl->private_value = spec->beep_amp;
Jaroslav Kysela5e26dfd2009-12-10 13:57:01 +0100811 err = snd_hda_ctl_add(codec, 0, kctl);
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100812 if (err < 0)
813 return err;
814 }
815 }
Takashi Iwai67d634c2009-11-16 15:35:59 +0100816#endif
Takashi Iwai45bdd1c2009-02-06 16:11:25 +0100817
Takashi Iwai1727a772013-01-10 09:52:52 +0100818 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
Takashi Iwai420b0fe2012-03-12 12:35:27 +0100819 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820}
821
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200822
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823/*
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100824 * Common callbacks
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200825 */
Takashi Iwai16ded522005-06-10 19:58:24 +0200826
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827static int alc_init(struct hda_codec *codec)
828{
829 struct alc_spec *spec = codec->spec;
Takashi Iwaie9edcee2005-06-13 14:16:38 +0200830
Takashi Iwai546bb672012-03-07 08:37:19 +0100831 if (spec->init_hook)
832 spec->init_hook(codec);
Kailang Yang526af6e2012-03-07 08:25:20 +0100833
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200834 alc_fix_pll(codec);
Takashi Iwai4a79ba32009-04-22 16:31:35 +0200835 alc_auto_init_amp(codec, spec->init_amp);
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +0200836
Takashi Iwai08c189f2012-12-19 15:22:24 +0100837 snd_hda_gen_init(codec);
Takashi Iwaiae6b8132006-03-03 16:47:17 +0100838
Takashi Iwai1727a772013-01-10 09:52:52 +0100839 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
Takashi Iwaie08a0072006-09-07 17:52:14 +0200840
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 return 0;
842}
843
Takashi Iwaia4e09aa2009-12-27 11:22:24 +0100844static inline void alc_shutup(struct hda_codec *codec)
845{
Takashi Iwai1c7161532011-04-07 10:37:16 +0200846 struct alc_spec *spec = codec->spec;
847
848 if (spec && spec->shutup)
849 spec->shutup(codec);
Takashi Iwai9bfb2842013-07-24 14:31:50 +0200850 else
851 snd_hda_shutup_pins(codec);
Takashi Iwaia4e09aa2009-12-27 11:22:24 +0100852}
853
Takashi Iwai8a02c0c2014-02-10 18:09:45 +0100854#define alc_free snd_hda_gen_free
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855
Takashi Iwai83012a72012-08-24 18:38:08 +0200856#ifdef CONFIG_PM
Daniel T Chenc97259d2009-12-27 18:52:08 -0500857static void alc_power_eapd(struct hda_codec *codec)
858{
Takashi Iwai691f1fc2011-04-07 10:31:43 +0200859 alc_auto_setup_eapd(codec, false);
Daniel T Chenc97259d2009-12-27 18:52:08 -0500860}
861
Takashi Iwai68cb2b52012-07-02 15:20:37 +0200862static int alc_suspend(struct hda_codec *codec)
Hector Martinf5de24b2009-12-20 22:51:31 +0100863{
864 struct alc_spec *spec = codec->spec;
Takashi Iwaia4e09aa2009-12-27 11:22:24 +0100865 alc_shutup(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100866 if (spec && spec->power_hook)
Daniel T Chenc97259d2009-12-27 18:52:08 -0500867 spec->power_hook(codec);
Hector Martinf5de24b2009-12-20 22:51:31 +0100868 return 0;
869}
870#endif
871
Takashi Iwai2a439522011-07-26 09:52:50 +0200872#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +0100873static int alc_resume(struct hda_codec *codec)
874{
Kailang Yang97a26572013-11-29 00:35:26 -0500875 struct alc_spec *spec = codec->spec;
876
877 if (!spec->no_depop_delay)
878 msleep(150); /* to avoid pop noise */
Takashi Iwaie044c392008-10-27 16:56:24 +0100879 codec->patch_ops.init(codec);
880 snd_hda_codec_resume_amp(codec);
881 snd_hda_codec_resume_cache(codec);
Takashi Iwai125821a2012-06-22 14:30:29 +0200882 alc_inv_dmic_sync(codec, true);
Takashi Iwai9e5341b2010-09-21 09:57:06 +0200883 hda_call_check_power_status(codec, 0x01);
Takashi Iwaie044c392008-10-27 16:56:24 +0100884 return 0;
885}
Takashi Iwaie044c392008-10-27 16:56:24 +0100886#endif
887
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888/*
889 */
Takashi Iwaia9111322011-05-02 11:30:18 +0200890static const struct hda_codec_ops alc_patch_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 .build_controls = alc_build_controls,
Takashi Iwai08c189f2012-12-19 15:22:24 +0100892 .build_pcms = snd_hda_gen_build_pcms,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 .init = alc_init,
894 .free = alc_free,
David Henningsson29adc4b2012-09-25 11:31:00 +0200895 .unsol_event = snd_hda_jack_unsol_event,
Takashi Iwai2a439522011-07-26 09:52:50 +0200896#ifdef CONFIG_PM
Takashi Iwaie044c392008-10-27 16:56:24 +0100897 .resume = alc_resume,
Hector Martinf5de24b2009-12-20 22:51:31 +0100898 .suspend = alc_suspend,
Takashi Iwaifce52a32013-01-07 12:42:48 +0100899 .check_power_status = snd_hda_gen_check_power_status,
Takashi Iwaicb53c622007-08-10 17:21:45 +0200900#endif
Daniel T Chenc97259d2009-12-27 18:52:08 -0500901 .reboot_notify = alc_shutup,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902};
903
David Henningsson29adc4b2012-09-25 11:31:00 +0200904
Kailang Yangc027ddc2010-03-19 11:33:06 +0100905/* replace the codec chip_name with the given string */
906static int alc_codec_rename(struct hda_codec *codec, const char *name)
907{
908 kfree(codec->chip_name);
909 codec->chip_name = kstrdup(name, GFP_KERNEL);
910 if (!codec->chip_name) {
911 alc_free(codec);
912 return -ENOMEM;
913 }
914 return 0;
915}
916
Takashi Iwai2fa522b2005-05-12 14:51:12 +0200917/*
Kailang Yang4b016932013-11-28 11:55:09 +0100918 * Rename codecs appropriately from COEF value or subvendor id
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200919 */
920struct alc_codec_rename_table {
921 unsigned int vendor_id;
922 unsigned short coef_mask;
923 unsigned short coef_bits;
924 const char *name;
925};
926
Kailang Yang4b016932013-11-28 11:55:09 +0100927struct alc_codec_rename_pci_table {
928 unsigned int codec_vendor_id;
929 unsigned short pci_subvendor;
930 unsigned short pci_subdevice;
931 const char *name;
932};
933
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200934static struct alc_codec_rename_table rename_tbl[] = {
Kailang Yange6e5f7a2014-06-06 16:46:43 +0800935 { 0x10ec0221, 0xf00f, 0x1003, "ALC231" },
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200936 { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
937 { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
938 { 0x10ec0269, 0xf0f0, 0x3010, "ALC258" },
939 { 0x10ec0269, 0x00f0, 0x0010, "ALC269VB" },
940 { 0x10ec0269, 0xffff, 0xa023, "ALC259" },
941 { 0x10ec0269, 0xffff, 0x6023, "ALC281X" },
942 { 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" },
Kailang Yangadcc70b2012-05-25 08:08:38 +0200943 { 0x10ec0269, 0x00f0, 0x0030, "ALC269VD" },
Kailang Yange6e5f7a2014-06-06 16:46:43 +0800944 { 0x10ec0662, 0xffff, 0x4020, "ALC656" },
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200945 { 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" },
946 { 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" },
947 { 0x10ec0888, 0xf0f0, 0x3020, "ALC886" },
948 { 0x10ec0899, 0x2000, 0x2000, "ALC899" },
949 { 0x10ec0892, 0xffff, 0x8020, "ALC661" },
950 { 0x10ec0892, 0xffff, 0x8011, "ALC661" },
951 { 0x10ec0892, 0xffff, 0x4011, "ALC656" },
952 { } /* terminator */
953};
954
Kailang Yang4b016932013-11-28 11:55:09 +0100955static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
956 { 0x10ec0280, 0x1028, 0, "ALC3220" },
957 { 0x10ec0282, 0x1028, 0, "ALC3221" },
958 { 0x10ec0283, 0x1028, 0, "ALC3223" },
Kailang Yang193177d2014-04-23 16:06:13 +0800959 { 0x10ec0288, 0x1028, 0, "ALC3263" },
Kailang Yang4b016932013-11-28 11:55:09 +0100960 { 0x10ec0292, 0x1028, 0, "ALC3226" },
Kailang Yang193177d2014-04-23 16:06:13 +0800961 { 0x10ec0293, 0x1028, 0, "ALC3235" },
Kailang Yang4b016932013-11-28 11:55:09 +0100962 { 0x10ec0255, 0x1028, 0, "ALC3234" },
963 { 0x10ec0668, 0x1028, 0, "ALC3661" },
Kailang Yange6e5f7a2014-06-06 16:46:43 +0800964 { 0x10ec0275, 0x1028, 0, "ALC3260" },
965 { 0x10ec0899, 0x1028, 0, "ALC3861" },
966 { 0x10ec0670, 0x1025, 0, "ALC669X" },
967 { 0x10ec0676, 0x1025, 0, "ALC679X" },
968 { 0x10ec0282, 0x1043, 0, "ALC3229" },
969 { 0x10ec0233, 0x1043, 0, "ALC3236" },
970 { 0x10ec0280, 0x103c, 0, "ALC3228" },
971 { 0x10ec0282, 0x103c, 0, "ALC3227" },
972 { 0x10ec0286, 0x103c, 0, "ALC3242" },
973 { 0x10ec0290, 0x103c, 0, "ALC3241" },
974 { 0x10ec0668, 0x103c, 0, "ALC3662" },
975 { 0x10ec0283, 0x17aa, 0, "ALC3239" },
976 { 0x10ec0292, 0x17aa, 0, "ALC3232" },
Kailang Yang4b016932013-11-28 11:55:09 +0100977 { } /* terminator */
978};
979
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200980static int alc_codec_rename_from_preset(struct hda_codec *codec)
981{
982 const struct alc_codec_rename_table *p;
Kailang Yang4b016932013-11-28 11:55:09 +0100983 const struct alc_codec_rename_pci_table *q;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200984
985 for (p = rename_tbl; p->vendor_id; p++) {
986 if (p->vendor_id != codec->vendor_id)
987 continue;
Takashi Iwai1bb7e432011-10-17 16:50:59 +0200988 if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
Takashi Iwaie16fb6d2011-10-17 16:39:09 +0200989 return alc_codec_rename(codec, p->name);
990 }
Kailang Yang4b016932013-11-28 11:55:09 +0100991
Takashi Iwai5100cd02014-02-15 10:03:19 +0100992 if (!codec->bus->pci)
993 return 0;
Kailang Yang4b016932013-11-28 11:55:09 +0100994 for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
995 if (q->codec_vendor_id != codec->vendor_id)
996 continue;
997 if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
998 continue;
999 if (!q->pci_subdevice ||
1000 q->pci_subdevice == codec->bus->pci->subsystem_device)
1001 return alc_codec_rename(codec, q->name);
1002 }
1003
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02001004 return 0;
1005}
1006
Takashi Iwaie4770622011-07-08 11:11:35 +02001007
1008/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001009 * Digital-beep handlers
1010 */
1011#ifdef CONFIG_SND_HDA_INPUT_BEEP
1012#define set_beep_amp(spec, nid, idx, dir) \
1013 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
1014
1015static const struct snd_pci_quirk beep_white_list[] = {
Duncan Roe71100052012-10-10 14:19:50 +02001016 SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1),
W. Trevor Kinga4b7f21d2014-03-29 17:47:24 -07001017 SND_PCI_QUIRK(0x1043, 0x115d, "ASUS", 1),
Takashi Iwai1d045db2011-07-07 18:23:21 +02001018 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
Takashi Iwai8554ee42013-02-25 09:54:43 +01001019 SND_PCI_QUIRK(0x1043, 0x8376, "EeePC", 1),
Takashi Iwai1d045db2011-07-07 18:23:21 +02001020 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
1021 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
1022 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
Takashi Iwai78f8baf2012-03-06 14:02:32 +01001023 SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1),
Takashi Iwai1d045db2011-07-07 18:23:21 +02001024 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
1025 {}
1026};
1027
1028static inline int has_cdefine_beep(struct hda_codec *codec)
1029{
1030 struct alc_spec *spec = codec->spec;
1031 const struct snd_pci_quirk *q;
1032 q = snd_pci_quirk_lookup(codec->bus->pci, beep_white_list);
1033 if (q)
1034 return q->value;
1035 return spec->cdefine.enable_pcbeep;
1036}
1037#else
1038#define set_beep_amp(spec, nid, idx, dir) /* NOP */
1039#define has_cdefine_beep(codec) 0
1040#endif
1041
1042/* parse the BIOS configuration and set up the alc_spec */
1043/* return 1 if successful, 0 if the proper config is not found,
1044 * or a negative error code
1045 */
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001046static int alc_parse_auto_config(struct hda_codec *codec,
1047 const hda_nid_t *ignore_nids,
1048 const hda_nid_t *ssid_nids)
Takashi Iwai1d045db2011-07-07 18:23:21 +02001049{
1050 struct alc_spec *spec = codec->spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +01001051 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001052 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001053
Takashi Iwai53c334a2011-08-23 18:27:14 +02001054 err = snd_hda_parse_pin_defcfg(codec, cfg, ignore_nids,
1055 spec->parse_flags);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001056 if (err < 0)
1057 return err;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001058
1059 if (ssid_nids)
1060 alc_ssid_check(codec, ssid_nids);
1061
Takashi Iwai08c189f2012-12-19 15:22:24 +01001062 err = snd_hda_gen_parse_auto_config(codec, cfg);
1063 if (err < 0)
1064 return err;
Takashi Iwai070cff42012-02-21 12:54:17 +01001065
Takashi Iwai1d045db2011-07-07 18:23:21 +02001066 return 1;
1067}
1068
Takashi Iwai3de95172012-05-07 18:03:15 +02001069/* common preparation job for alc_spec */
1070static int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
1071{
1072 struct alc_spec *spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1073 int err;
1074
1075 if (!spec)
1076 return -ENOMEM;
1077 codec->spec = spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +01001078 snd_hda_gen_spec_init(&spec->gen);
1079 spec->gen.mixer_nid = mixer_nid;
1080 spec->gen.own_eapd_ctl = 1;
Takashi Iwai1098b7c2012-12-17 20:03:15 +01001081 codec->single_adc_amp = 1;
Takashi Iwai08c189f2012-12-19 15:22:24 +01001082 /* FIXME: do we need this for all Realtek codec models? */
1083 codec->spdif_status_reset = 1;
Takashi Iwai3de95172012-05-07 18:03:15 +02001084
1085 err = alc_codec_rename_from_preset(codec);
1086 if (err < 0) {
1087 kfree(spec);
1088 return err;
1089 }
1090 return 0;
1091}
1092
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001093static int alc880_parse_auto_config(struct hda_codec *codec)
1094{
1095 static const hda_nid_t alc880_ignore[] = { 0x1d, 0 };
Jesper Juhl7d7eb9e2012-04-12 22:11:25 +02001096 static const hda_nid_t alc880_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001097 return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
1098}
1099
Takashi Iwai1d045db2011-07-07 18:23:21 +02001100/*
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001101 * ALC880 fix-ups
1102 */
1103enum {
Takashi Iwai411225a2012-02-20 17:48:19 +01001104 ALC880_FIXUP_GPIO1,
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001105 ALC880_FIXUP_GPIO2,
1106 ALC880_FIXUP_MEDION_RIM,
Takashi Iwaidc6af522012-02-17 16:18:59 +01001107 ALC880_FIXUP_LG,
Takashi Iwaidb8a38e2013-08-09 12:34:42 +02001108 ALC880_FIXUP_LG_LW25,
Takashi Iwaif02aab52012-02-17 16:33:56 +01001109 ALC880_FIXUP_W810,
Takashi Iwai27e917f2012-02-17 17:49:54 +01001110 ALC880_FIXUP_EAPD_COEF,
Takashi Iwaib9368f52012-02-17 17:54:44 +01001111 ALC880_FIXUP_TCL_S700,
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001112 ALC880_FIXUP_VOL_KNOB,
1113 ALC880_FIXUP_FUJITSU,
Takashi Iwaiba533812012-02-20 16:36:52 +01001114 ALC880_FIXUP_F1734,
Takashi Iwai817de922012-02-20 17:20:48 +01001115 ALC880_FIXUP_UNIWILL,
Takashi Iwai967b88c2012-02-20 17:31:02 +01001116 ALC880_FIXUP_UNIWILL_DIG,
Takashi Iwai96e225f2012-02-20 17:41:51 +01001117 ALC880_FIXUP_Z71V,
Takashi Iwai487a5882013-11-07 07:29:30 +01001118 ALC880_FIXUP_ASUS_W5A,
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001119 ALC880_FIXUP_3ST_BASE,
1120 ALC880_FIXUP_3ST,
1121 ALC880_FIXUP_3ST_DIG,
1122 ALC880_FIXUP_5ST_BASE,
1123 ALC880_FIXUP_5ST,
1124 ALC880_FIXUP_5ST_DIG,
1125 ALC880_FIXUP_6ST_BASE,
1126 ALC880_FIXUP_6ST,
1127 ALC880_FIXUP_6ST_DIG,
Takashi Iwai53971452013-01-23 18:21:37 +01001128 ALC880_FIXUP_6ST_AUTOMUTE,
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001129};
1130
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001131/* enable the volume-knob widget support on NID 0x21 */
1132static void alc880_fixup_vol_knob(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001133 const struct hda_fixup *fix, int action)
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001134{
Takashi Iwai1727a772013-01-10 09:52:52 +01001135 if (action == HDA_FIXUP_ACT_PROBE)
David Henningsson29adc4b2012-09-25 11:31:00 +02001136 snd_hda_jack_detect_enable_callback(codec, 0x21, ALC_DCVOL_EVENT, alc_update_knob_master);
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001137}
1138
Takashi Iwai1727a772013-01-10 09:52:52 +01001139static const struct hda_fixup alc880_fixups[] = {
Takashi Iwai411225a2012-02-20 17:48:19 +01001140 [ALC880_FIXUP_GPIO1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001141 .type = HDA_FIXUP_VERBS,
Takashi Iwai411225a2012-02-20 17:48:19 +01001142 .v.verbs = alc_gpio1_init_verbs,
1143 },
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001144 [ALC880_FIXUP_GPIO2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001145 .type = HDA_FIXUP_VERBS,
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001146 .v.verbs = alc_gpio2_init_verbs,
1147 },
1148 [ALC880_FIXUP_MEDION_RIM] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001149 .type = HDA_FIXUP_VERBS,
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001150 .v.verbs = (const struct hda_verb[]) {
1151 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1152 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
1153 { }
1154 },
1155 .chained = true,
1156 .chain_id = ALC880_FIXUP_GPIO2,
1157 },
Takashi Iwaidc6af522012-02-17 16:18:59 +01001158 [ALC880_FIXUP_LG] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001159 .type = HDA_FIXUP_PINS,
1160 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaidc6af522012-02-17 16:18:59 +01001161 /* disable bogus unused pins */
1162 { 0x16, 0x411111f0 },
1163 { 0x18, 0x411111f0 },
1164 { 0x1a, 0x411111f0 },
1165 { }
1166 }
1167 },
Takashi Iwaidb8a38e2013-08-09 12:34:42 +02001168 [ALC880_FIXUP_LG_LW25] = {
1169 .type = HDA_FIXUP_PINS,
1170 .v.pins = (const struct hda_pintbl[]) {
1171 { 0x1a, 0x0181344f }, /* line-in */
1172 { 0x1b, 0x0321403f }, /* headphone */
1173 { }
1174 }
1175 },
Takashi Iwaif02aab52012-02-17 16:33:56 +01001176 [ALC880_FIXUP_W810] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001177 .type = HDA_FIXUP_PINS,
1178 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaif02aab52012-02-17 16:33:56 +01001179 /* disable bogus unused pins */
1180 { 0x17, 0x411111f0 },
1181 { }
1182 },
1183 .chained = true,
1184 .chain_id = ALC880_FIXUP_GPIO2,
1185 },
Takashi Iwai27e917f2012-02-17 17:49:54 +01001186 [ALC880_FIXUP_EAPD_COEF] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001187 .type = HDA_FIXUP_VERBS,
Takashi Iwai27e917f2012-02-17 17:49:54 +01001188 .v.verbs = (const struct hda_verb[]) {
1189 /* change to EAPD mode */
1190 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1191 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
1192 {}
1193 },
1194 },
Takashi Iwaib9368f52012-02-17 17:54:44 +01001195 [ALC880_FIXUP_TCL_S700] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001196 .type = HDA_FIXUP_VERBS,
Takashi Iwaib9368f52012-02-17 17:54:44 +01001197 .v.verbs = (const struct hda_verb[]) {
1198 /* change to EAPD mode */
1199 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
1200 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
1201 {}
1202 },
1203 .chained = true,
1204 .chain_id = ALC880_FIXUP_GPIO2,
1205 },
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001206 [ALC880_FIXUP_VOL_KNOB] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001207 .type = HDA_FIXUP_FUNC,
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001208 .v.func = alc880_fixup_vol_knob,
1209 },
1210 [ALC880_FIXUP_FUJITSU] = {
1211 /* override all pins as BIOS on old Amilo is broken */
Takashi Iwai1727a772013-01-10 09:52:52 +01001212 .type = HDA_FIXUP_PINS,
1213 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001214 { 0x14, 0x0121411f }, /* HP */
1215 { 0x15, 0x99030120 }, /* speaker */
1216 { 0x16, 0x99030130 }, /* bass speaker */
1217 { 0x17, 0x411111f0 }, /* N/A */
1218 { 0x18, 0x411111f0 }, /* N/A */
1219 { 0x19, 0x01a19950 }, /* mic-in */
1220 { 0x1a, 0x411111f0 }, /* N/A */
1221 { 0x1b, 0x411111f0 }, /* N/A */
1222 { 0x1c, 0x411111f0 }, /* N/A */
1223 { 0x1d, 0x411111f0 }, /* N/A */
1224 { 0x1e, 0x01454140 }, /* SPDIF out */
1225 { }
1226 },
1227 .chained = true,
1228 .chain_id = ALC880_FIXUP_VOL_KNOB,
1229 },
Takashi Iwaiba533812012-02-20 16:36:52 +01001230 [ALC880_FIXUP_F1734] = {
1231 /* almost compatible with FUJITSU, but no bass and SPDIF */
Takashi Iwai1727a772013-01-10 09:52:52 +01001232 .type = HDA_FIXUP_PINS,
1233 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaiba533812012-02-20 16:36:52 +01001234 { 0x14, 0x0121411f }, /* HP */
1235 { 0x15, 0x99030120 }, /* speaker */
1236 { 0x16, 0x411111f0 }, /* N/A */
1237 { 0x17, 0x411111f0 }, /* N/A */
1238 { 0x18, 0x411111f0 }, /* N/A */
1239 { 0x19, 0x01a19950 }, /* mic-in */
1240 { 0x1a, 0x411111f0 }, /* N/A */
1241 { 0x1b, 0x411111f0 }, /* N/A */
1242 { 0x1c, 0x411111f0 }, /* N/A */
1243 { 0x1d, 0x411111f0 }, /* N/A */
1244 { 0x1e, 0x411111f0 }, /* N/A */
1245 { }
1246 },
1247 .chained = true,
1248 .chain_id = ALC880_FIXUP_VOL_KNOB,
1249 },
Takashi Iwai817de922012-02-20 17:20:48 +01001250 [ALC880_FIXUP_UNIWILL] = {
1251 /* need to fix HP and speaker pins to be parsed correctly */
Takashi Iwai1727a772013-01-10 09:52:52 +01001252 .type = HDA_FIXUP_PINS,
1253 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai817de922012-02-20 17:20:48 +01001254 { 0x14, 0x0121411f }, /* HP */
1255 { 0x15, 0x99030120 }, /* speaker */
1256 { 0x16, 0x99030130 }, /* bass speaker */
1257 { }
1258 },
1259 },
Takashi Iwai967b88c2012-02-20 17:31:02 +01001260 [ALC880_FIXUP_UNIWILL_DIG] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001261 .type = HDA_FIXUP_PINS,
1262 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai967b88c2012-02-20 17:31:02 +01001263 /* disable bogus unused pins */
1264 { 0x17, 0x411111f0 },
1265 { 0x19, 0x411111f0 },
1266 { 0x1b, 0x411111f0 },
1267 { 0x1f, 0x411111f0 },
1268 { }
1269 }
1270 },
Takashi Iwai96e225f2012-02-20 17:41:51 +01001271 [ALC880_FIXUP_Z71V] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001272 .type = HDA_FIXUP_PINS,
1273 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai96e225f2012-02-20 17:41:51 +01001274 /* set up the whole pins as BIOS is utterly broken */
1275 { 0x14, 0x99030120 }, /* speaker */
1276 { 0x15, 0x0121411f }, /* HP */
1277 { 0x16, 0x411111f0 }, /* N/A */
1278 { 0x17, 0x411111f0 }, /* N/A */
1279 { 0x18, 0x01a19950 }, /* mic-in */
1280 { 0x19, 0x411111f0 }, /* N/A */
1281 { 0x1a, 0x01813031 }, /* line-in */
1282 { 0x1b, 0x411111f0 }, /* N/A */
1283 { 0x1c, 0x411111f0 }, /* N/A */
1284 { 0x1d, 0x411111f0 }, /* N/A */
1285 { 0x1e, 0x0144111e }, /* SPDIF */
1286 { }
1287 }
1288 },
Takashi Iwai487a5882013-11-07 07:29:30 +01001289 [ALC880_FIXUP_ASUS_W5A] = {
1290 .type = HDA_FIXUP_PINS,
1291 .v.pins = (const struct hda_pintbl[]) {
1292 /* set up the whole pins as BIOS is utterly broken */
1293 { 0x14, 0x0121411f }, /* HP */
1294 { 0x15, 0x411111f0 }, /* N/A */
1295 { 0x16, 0x411111f0 }, /* N/A */
1296 { 0x17, 0x411111f0 }, /* N/A */
1297 { 0x18, 0x90a60160 }, /* mic */
1298 { 0x19, 0x411111f0 }, /* N/A */
1299 { 0x1a, 0x411111f0 }, /* N/A */
1300 { 0x1b, 0x411111f0 }, /* N/A */
1301 { 0x1c, 0x411111f0 }, /* N/A */
1302 { 0x1d, 0x411111f0 }, /* N/A */
1303 { 0x1e, 0xb743111e }, /* SPDIF out */
1304 { }
1305 },
1306 .chained = true,
1307 .chain_id = ALC880_FIXUP_GPIO1,
1308 },
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001309 [ALC880_FIXUP_3ST_BASE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001310 .type = HDA_FIXUP_PINS,
1311 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001312 { 0x14, 0x01014010 }, /* line-out */
1313 { 0x15, 0x411111f0 }, /* N/A */
1314 { 0x16, 0x411111f0 }, /* N/A */
1315 { 0x17, 0x411111f0 }, /* N/A */
1316 { 0x18, 0x01a19c30 }, /* mic-in */
1317 { 0x19, 0x0121411f }, /* HP */
1318 { 0x1a, 0x01813031 }, /* line-in */
1319 { 0x1b, 0x02a19c40 }, /* front-mic */
1320 { 0x1c, 0x411111f0 }, /* N/A */
1321 { 0x1d, 0x411111f0 }, /* N/A */
1322 /* 0x1e is filled in below */
1323 { 0x1f, 0x411111f0 }, /* N/A */
1324 { }
1325 }
1326 },
1327 [ALC880_FIXUP_3ST] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001328 .type = HDA_FIXUP_PINS,
1329 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001330 { 0x1e, 0x411111f0 }, /* N/A */
1331 { }
1332 },
1333 .chained = true,
1334 .chain_id = ALC880_FIXUP_3ST_BASE,
1335 },
1336 [ALC880_FIXUP_3ST_DIG] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001337 .type = HDA_FIXUP_PINS,
1338 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001339 { 0x1e, 0x0144111e }, /* SPDIF */
1340 { }
1341 },
1342 .chained = true,
1343 .chain_id = ALC880_FIXUP_3ST_BASE,
1344 },
1345 [ALC880_FIXUP_5ST_BASE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001346 .type = HDA_FIXUP_PINS,
1347 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001348 { 0x14, 0x01014010 }, /* front */
1349 { 0x15, 0x411111f0 }, /* N/A */
1350 { 0x16, 0x01011411 }, /* CLFE */
1351 { 0x17, 0x01016412 }, /* surr */
1352 { 0x18, 0x01a19c30 }, /* mic-in */
1353 { 0x19, 0x0121411f }, /* HP */
1354 { 0x1a, 0x01813031 }, /* line-in */
1355 { 0x1b, 0x02a19c40 }, /* front-mic */
1356 { 0x1c, 0x411111f0 }, /* N/A */
1357 { 0x1d, 0x411111f0 }, /* N/A */
1358 /* 0x1e is filled in below */
1359 { 0x1f, 0x411111f0 }, /* N/A */
1360 { }
1361 }
1362 },
1363 [ALC880_FIXUP_5ST] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001364 .type = HDA_FIXUP_PINS,
1365 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001366 { 0x1e, 0x411111f0 }, /* N/A */
1367 { }
1368 },
1369 .chained = true,
1370 .chain_id = ALC880_FIXUP_5ST_BASE,
1371 },
1372 [ALC880_FIXUP_5ST_DIG] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001373 .type = HDA_FIXUP_PINS,
1374 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001375 { 0x1e, 0x0144111e }, /* SPDIF */
1376 { }
1377 },
1378 .chained = true,
1379 .chain_id = ALC880_FIXUP_5ST_BASE,
1380 },
1381 [ALC880_FIXUP_6ST_BASE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001382 .type = HDA_FIXUP_PINS,
1383 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001384 { 0x14, 0x01014010 }, /* front */
1385 { 0x15, 0x01016412 }, /* surr */
1386 { 0x16, 0x01011411 }, /* CLFE */
1387 { 0x17, 0x01012414 }, /* side */
1388 { 0x18, 0x01a19c30 }, /* mic-in */
1389 { 0x19, 0x02a19c40 }, /* front-mic */
1390 { 0x1a, 0x01813031 }, /* line-in */
1391 { 0x1b, 0x0121411f }, /* HP */
1392 { 0x1c, 0x411111f0 }, /* N/A */
1393 { 0x1d, 0x411111f0 }, /* N/A */
1394 /* 0x1e is filled in below */
1395 { 0x1f, 0x411111f0 }, /* N/A */
1396 { }
1397 }
1398 },
1399 [ALC880_FIXUP_6ST] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001400 .type = HDA_FIXUP_PINS,
1401 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001402 { 0x1e, 0x411111f0 }, /* N/A */
1403 { }
1404 },
1405 .chained = true,
1406 .chain_id = ALC880_FIXUP_6ST_BASE,
1407 },
1408 [ALC880_FIXUP_6ST_DIG] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001409 .type = HDA_FIXUP_PINS,
1410 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001411 { 0x1e, 0x0144111e }, /* SPDIF */
1412 { }
1413 },
1414 .chained = true,
1415 .chain_id = ALC880_FIXUP_6ST_BASE,
1416 },
Takashi Iwai53971452013-01-23 18:21:37 +01001417 [ALC880_FIXUP_6ST_AUTOMUTE] = {
1418 .type = HDA_FIXUP_PINS,
1419 .v.pins = (const struct hda_pintbl[]) {
1420 { 0x1b, 0x0121401f }, /* HP with jack detect */
1421 { }
1422 },
1423 .chained_before = true,
1424 .chain_id = ALC880_FIXUP_6ST_BASE,
1425 },
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001426};
1427
1428static const struct snd_pci_quirk alc880_fixup_tbl[] = {
Takashi Iwaif02aab52012-02-17 16:33:56 +01001429 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
Takashi Iwai487a5882013-11-07 07:29:30 +01001430 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS W5A", ALC880_FIXUP_ASUS_W5A),
Takashi Iwai96e225f2012-02-20 17:41:51 +01001431 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
Takashi Iwai29e3fdc2012-02-20 17:56:57 +01001432 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
David Henningsson6538de02014-06-10 10:52:50 +02001433 SND_PCI_QUIRK(0x147b, 0x1045, "ABit AA8XE", ALC880_FIXUP_6ST_AUTOMUTE),
Takashi Iwai29e3fdc2012-02-20 17:56:57 +01001434 SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
Takashi Iwai27e917f2012-02-17 17:49:54 +01001435 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF),
Takashi Iwai967b88c2012-02-20 17:31:02 +01001436 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG),
Takashi Iwaiba533812012-02-20 16:36:52 +01001437 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734),
Takashi Iwai817de922012-02-20 17:20:48 +01001438 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL),
Takashi Iwai7833c7e2012-02-20 17:11:38 +01001439 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
Takashi Iwaif02aab52012-02-17 16:33:56 +01001440 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001441 SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
Takashi Iwai53971452013-01-23 18:21:37 +01001442 SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST_AUTOMUTE),
Takashi Iwaiba533812012-02-20 16:36:52 +01001443 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734),
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001444 SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
Takashi Iwaiba533812012-02-20 16:36:52 +01001445 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
Takashi Iwaicf5a2272012-02-20 16:31:07 +01001446 SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU),
Takashi Iwaidc6af522012-02-17 16:18:59 +01001447 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
1448 SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
1449 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
Takashi Iwaidb8a38e2013-08-09 12:34:42 +02001450 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_FIXUP_LG_LW25),
Takashi Iwaib9368f52012-02-17 17:54:44 +01001451 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001452
1453 /* Below is the copied entries from alc880_quirks.c.
1454 * It's not quite sure whether BIOS sets the correct pin-config table
1455 * on these machines, thus they are kept to be compatible with
1456 * the old static quirks. Once when it's confirmed to work without
1457 * these overrides, it'd be better to remove.
1458 */
1459 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG),
1460 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST),
1461 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG),
1462 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG),
1463 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG),
1464 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG),
1465 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG),
1466 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST),
1467 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG),
1468 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST),
1469 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST),
1470 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST),
1471 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST),
1472 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST),
1473 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG),
1474 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG),
1475 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG),
1476 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG),
1477 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG),
1478 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG),
1479 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG),
1480 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */
1481 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG),
1482 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1483 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1484 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1485 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG),
1486 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1487 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG),
1488 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG),
1489 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1490 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1491 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG),
1492 /* default Intel */
1493 SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST),
1494 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG),
1495 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG),
1496 {}
1497};
1498
Takashi Iwai1727a772013-01-10 09:52:52 +01001499static const struct hda_model_fixup alc880_fixup_models[] = {
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001500 {.id = ALC880_FIXUP_3ST, .name = "3stack"},
1501 {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"},
1502 {.id = ALC880_FIXUP_5ST, .name = "5stack"},
1503 {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"},
1504 {.id = ALC880_FIXUP_6ST, .name = "6stack"},
1505 {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"},
Takashi Iwai53971452013-01-23 18:21:37 +01001506 {.id = ALC880_FIXUP_6ST_AUTOMUTE, .name = "6stack-automute"},
Takashi Iwaiee3b2962011-11-15 14:26:54 +01001507 {}
1508};
1509
1510
1511/*
Takashi Iwai1d045db2011-07-07 18:23:21 +02001512 * OK, here we have finally the patch for ALC880
1513 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02001514static int patch_alc880(struct hda_codec *codec)
1515{
1516 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001517 int err;
1518
Takashi Iwai3de95172012-05-07 18:03:15 +02001519 err = alc_alloc_spec(codec, 0x0b);
1520 if (err < 0)
1521 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001522
Takashi Iwai3de95172012-05-07 18:03:15 +02001523 spec = codec->spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +01001524 spec->gen.need_dac_fix = 1;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01001525 spec->gen.beep_nid = 0x01;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001526
Takashi Iwai1727a772013-01-10 09:52:52 +01001527 snd_hda_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001528 alc880_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01001529 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001530
Takashi Iwai67b6ec32012-02-20 18:20:42 +01001531 /* automatic parse from the BIOS config */
1532 err = alc880_parse_auto_config(codec);
1533 if (err < 0)
1534 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001535
Takashi Iwai7504b6c2013-03-18 11:25:51 +01001536 if (!spec->gen.no_analog)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001537 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001538
Takashi Iwai1d045db2011-07-07 18:23:21 +02001539 codec->patch_ops = alc_patch_ops;
David Henningsson29adc4b2012-09-25 11:31:00 +02001540 codec->patch_ops.unsol_event = alc880_unsol_event;
1541
Takashi Iwai1d045db2011-07-07 18:23:21 +02001542
Takashi Iwai1727a772013-01-10 09:52:52 +01001543 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01001544
Takashi Iwai1d045db2011-07-07 18:23:21 +02001545 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02001546
1547 error:
1548 alc_free(codec);
1549 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001550}
1551
1552
1553/*
1554 * ALC260 support
1555 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02001556static int alc260_parse_auto_config(struct hda_codec *codec)
1557{
Takashi Iwai1d045db2011-07-07 18:23:21 +02001558 static const hda_nid_t alc260_ignore[] = { 0x17, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001559 static const hda_nid_t alc260_ssids[] = { 0x10, 0x15, 0x0f, 0 };
1560 return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001561}
1562
Takashi Iwai1d045db2011-07-07 18:23:21 +02001563/*
1564 * Pin config fixes
1565 */
1566enum {
Takashi Iwaica8f0422012-02-16 11:51:19 +01001567 ALC260_FIXUP_HP_DC5750,
1568 ALC260_FIXUP_HP_PIN_0F,
1569 ALC260_FIXUP_COEF,
Takashi Iwai15317ab2012-02-16 12:02:53 +01001570 ALC260_FIXUP_GPIO1,
Takashi Iwai20f7d922012-02-16 12:35:16 +01001571 ALC260_FIXUP_GPIO1_TOGGLE,
1572 ALC260_FIXUP_REPLACER,
Takashi Iwai0a1c4fa2012-02-16 12:42:30 +01001573 ALC260_FIXUP_HP_B1900,
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001574 ALC260_FIXUP_KN1,
Takashi Iwai39aedee2013-01-10 17:10:40 +01001575 ALC260_FIXUP_FSC_S7020,
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001576 ALC260_FIXUP_FSC_S7020_JWSE,
Takashi Iwaid08c5ef2013-11-22 08:06:36 +01001577 ALC260_FIXUP_VAIO_PINS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001578};
1579
Takashi Iwai20f7d922012-02-16 12:35:16 +01001580static void alc260_gpio1_automute(struct hda_codec *codec)
1581{
1582 struct alc_spec *spec = codec->spec;
1583 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
Takashi Iwai08c189f2012-12-19 15:22:24 +01001584 spec->gen.hp_jack_present);
Takashi Iwai20f7d922012-02-16 12:35:16 +01001585}
1586
1587static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001588 const struct hda_fixup *fix, int action)
Takashi Iwai20f7d922012-02-16 12:35:16 +01001589{
1590 struct alc_spec *spec = codec->spec;
Takashi Iwai1727a772013-01-10 09:52:52 +01001591 if (action == HDA_FIXUP_ACT_PROBE) {
Takashi Iwai20f7d922012-02-16 12:35:16 +01001592 /* although the machine has only one output pin, we need to
1593 * toggle GPIO1 according to the jack state
1594 */
Takashi Iwai08c189f2012-12-19 15:22:24 +01001595 spec->gen.automute_hook = alc260_gpio1_automute;
1596 spec->gen.detect_hp = 1;
1597 spec->gen.automute_speaker = 1;
1598 spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
1599 snd_hda_jack_detect_enable_callback(codec, 0x0f, HDA_GEN_HP_EVENT,
1600 snd_hda_gen_hp_automute);
Takashi Iwaic9ce6b22012-12-18 18:12:44 +01001601 snd_hda_add_verbs(codec, alc_gpio1_init_verbs);
Takashi Iwai20f7d922012-02-16 12:35:16 +01001602 }
1603}
1604
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001605static void alc260_fixup_kn1(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001606 const struct hda_fixup *fix, int action)
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001607{
1608 struct alc_spec *spec = codec->spec;
Takashi Iwai1727a772013-01-10 09:52:52 +01001609 static const struct hda_pintbl pincfgs[] = {
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001610 { 0x0f, 0x02214000 }, /* HP/speaker */
1611 { 0x12, 0x90a60160 }, /* int mic */
1612 { 0x13, 0x02a19000 }, /* ext mic */
1613 { 0x18, 0x01446000 }, /* SPDIF out */
1614 /* disable bogus I/O pins */
1615 { 0x10, 0x411111f0 },
1616 { 0x11, 0x411111f0 },
1617 { 0x14, 0x411111f0 },
1618 { 0x15, 0x411111f0 },
1619 { 0x16, 0x411111f0 },
1620 { 0x17, 0x411111f0 },
1621 { 0x19, 0x411111f0 },
1622 { }
1623 };
1624
1625 switch (action) {
Takashi Iwai1727a772013-01-10 09:52:52 +01001626 case HDA_FIXUP_ACT_PRE_PROBE:
1627 snd_hda_apply_pincfgs(codec, pincfgs);
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001628 break;
Takashi Iwai1727a772013-01-10 09:52:52 +01001629 case HDA_FIXUP_ACT_PROBE:
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001630 spec->init_amp = ALC_INIT_NONE;
1631 break;
1632 }
1633}
1634
Takashi Iwai39aedee2013-01-10 17:10:40 +01001635static void alc260_fixup_fsc_s7020(struct hda_codec *codec,
1636 const struct hda_fixup *fix, int action)
1637{
1638 struct alc_spec *spec = codec->spec;
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001639 if (action == HDA_FIXUP_ACT_PROBE)
Takashi Iwaie6e0ee52013-02-18 17:04:20 +01001640 spec->init_amp = ALC_INIT_NONE;
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001641}
1642
1643static void alc260_fixup_fsc_s7020_jwse(struct hda_codec *codec,
1644 const struct hda_fixup *fix, int action)
1645{
1646 struct alc_spec *spec = codec->spec;
1647 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwaif811c3c2013-03-07 18:32:59 +01001648 spec->gen.add_jack_modes = 1;
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001649 spec->gen.hp_mic = 1;
Takashi Iwaie6e0ee52013-02-18 17:04:20 +01001650 }
Takashi Iwai39aedee2013-01-10 17:10:40 +01001651}
1652
Takashi Iwai1727a772013-01-10 09:52:52 +01001653static const struct hda_fixup alc260_fixups[] = {
Takashi Iwaica8f0422012-02-16 11:51:19 +01001654 [ALC260_FIXUP_HP_DC5750] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001655 .type = HDA_FIXUP_PINS,
1656 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02001657 { 0x11, 0x90130110 }, /* speaker */
1658 { }
1659 }
1660 },
Takashi Iwaica8f0422012-02-16 11:51:19 +01001661 [ALC260_FIXUP_HP_PIN_0F] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001662 .type = HDA_FIXUP_PINS,
1663 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaica8f0422012-02-16 11:51:19 +01001664 { 0x0f, 0x01214000 }, /* HP */
1665 { }
1666 }
1667 },
1668 [ALC260_FIXUP_COEF] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001669 .type = HDA_FIXUP_VERBS,
Takashi Iwaica8f0422012-02-16 11:51:19 +01001670 .v.verbs = (const struct hda_verb[]) {
Ronan Marquete30cf2d2014-06-01 18:38:53 +02001671 { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
1672 { 0x1a, AC_VERB_SET_PROC_COEF, 0x3040 },
Takashi Iwaica8f0422012-02-16 11:51:19 +01001673 { }
1674 },
Takashi Iwaica8f0422012-02-16 11:51:19 +01001675 },
Takashi Iwai15317ab2012-02-16 12:02:53 +01001676 [ALC260_FIXUP_GPIO1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001677 .type = HDA_FIXUP_VERBS,
Takashi Iwai15317ab2012-02-16 12:02:53 +01001678 .v.verbs = alc_gpio1_init_verbs,
1679 },
Takashi Iwai20f7d922012-02-16 12:35:16 +01001680 [ALC260_FIXUP_GPIO1_TOGGLE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001681 .type = HDA_FIXUP_FUNC,
Takashi Iwai20f7d922012-02-16 12:35:16 +01001682 .v.func = alc260_fixup_gpio1_toggle,
1683 .chained = true,
1684 .chain_id = ALC260_FIXUP_HP_PIN_0F,
1685 },
1686 [ALC260_FIXUP_REPLACER] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001687 .type = HDA_FIXUP_VERBS,
Takashi Iwai20f7d922012-02-16 12:35:16 +01001688 .v.verbs = (const struct hda_verb[]) {
Takashi Iwai192a98e2014-06-02 15:16:07 +02001689 { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
1690 { 0x1a, AC_VERB_SET_PROC_COEF, 0x3050 },
Takashi Iwai20f7d922012-02-16 12:35:16 +01001691 { }
1692 },
1693 .chained = true,
1694 .chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
1695 },
Takashi Iwai0a1c4fa2012-02-16 12:42:30 +01001696 [ALC260_FIXUP_HP_B1900] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001697 .type = HDA_FIXUP_FUNC,
Takashi Iwai0a1c4fa2012-02-16 12:42:30 +01001698 .v.func = alc260_fixup_gpio1_toggle,
1699 .chained = true,
1700 .chain_id = ALC260_FIXUP_COEF,
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001701 },
1702 [ALC260_FIXUP_KN1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01001703 .type = HDA_FIXUP_FUNC,
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001704 .v.func = alc260_fixup_kn1,
1705 },
Takashi Iwai39aedee2013-01-10 17:10:40 +01001706 [ALC260_FIXUP_FSC_S7020] = {
1707 .type = HDA_FIXUP_FUNC,
1708 .v.func = alc260_fixup_fsc_s7020,
1709 },
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001710 [ALC260_FIXUP_FSC_S7020_JWSE] = {
1711 .type = HDA_FIXUP_FUNC,
1712 .v.func = alc260_fixup_fsc_s7020_jwse,
1713 .chained = true,
1714 .chain_id = ALC260_FIXUP_FSC_S7020,
1715 },
Takashi Iwaid08c5ef2013-11-22 08:06:36 +01001716 [ALC260_FIXUP_VAIO_PINS] = {
1717 .type = HDA_FIXUP_PINS,
1718 .v.pins = (const struct hda_pintbl[]) {
1719 /* Pin configs are missing completely on some VAIOs */
1720 { 0x0f, 0x01211020 },
1721 { 0x10, 0x0001003f },
1722 { 0x11, 0x411111f0 },
1723 { 0x12, 0x01a15930 },
1724 { 0x13, 0x411111f0 },
1725 { 0x14, 0x411111f0 },
1726 { 0x15, 0x411111f0 },
1727 { 0x16, 0x411111f0 },
1728 { 0x17, 0x411111f0 },
1729 { 0x18, 0x411111f0 },
1730 { 0x19, 0x411111f0 },
1731 { }
1732 }
1733 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02001734};
1735
1736static const struct snd_pci_quirk alc260_fixup_tbl[] = {
Takashi Iwai15317ab2012-02-16 12:02:53 +01001737 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
Takashi Iwaica8f0422012-02-16 11:51:19 +01001738 SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
Takashi Iwai15317ab2012-02-16 12:02:53 +01001739 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
Takashi Iwaica8f0422012-02-16 11:51:19 +01001740 SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
Takashi Iwai0a1c4fa2012-02-16 12:42:30 +01001741 SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
Takashi Iwaid08c5ef2013-11-22 08:06:36 +01001742 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_FIXUP_VAIO_PINS),
Takashi Iwai0f5a5b82013-11-21 09:12:52 +01001743 SND_PCI_QUIRK(0x104d, 0x81e2, "Sony VAIO TX", ALC260_FIXUP_HP_PIN_0F),
Takashi Iwai39aedee2013-01-10 17:10:40 +01001744 SND_PCI_QUIRK(0x10cf, 0x1326, "FSC LifeBook S7020", ALC260_FIXUP_FSC_S7020),
Takashi Iwaib1f58082012-02-16 12:45:03 +01001745 SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
Takashi Iwai118cb4a2012-04-19 07:33:27 +02001746 SND_PCI_QUIRK(0x152d, 0x0729, "Quanta KN1", ALC260_FIXUP_KN1),
Takashi Iwai20f7d922012-02-16 12:35:16 +01001747 SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
Takashi Iwaica8f0422012-02-16 11:51:19 +01001748 SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
Takashi Iwai1d045db2011-07-07 18:23:21 +02001749 {}
1750};
1751
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001752static const struct hda_model_fixup alc260_fixup_models[] = {
1753 {.id = ALC260_FIXUP_GPIO1, .name = "gpio1"},
1754 {.id = ALC260_FIXUP_COEF, .name = "coef"},
1755 {.id = ALC260_FIXUP_FSC_S7020, .name = "fujitsu"},
1756 {.id = ALC260_FIXUP_FSC_S7020_JWSE, .name = "fujitsu-jwse"},
1757 {}
1758};
1759
Takashi Iwai1d045db2011-07-07 18:23:21 +02001760/*
1761 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02001762static int patch_alc260(struct hda_codec *codec)
1763{
1764 struct alc_spec *spec;
Takashi Iwaic3c2c9e2012-02-16 12:59:55 +01001765 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001766
Takashi Iwai3de95172012-05-07 18:03:15 +02001767 err = alc_alloc_spec(codec, 0x07);
1768 if (err < 0)
1769 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001770
Takashi Iwai3de95172012-05-07 18:03:15 +02001771 spec = codec->spec;
Takashi Iwaiea46c3c2013-01-15 18:45:53 +01001772 /* as quite a few machines require HP amp for speaker outputs,
1773 * it's easier to enable it unconditionally; even if it's unneeded,
1774 * it's almost harmless.
1775 */
1776 spec->gen.prefer_hp_amp = 1;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01001777 spec->gen.beep_nid = 0x01;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001778
Takashi Iwai5ebd3bb2013-02-19 18:23:31 +01001779 snd_hda_pick_fixup(codec, alc260_fixup_models, alc260_fixup_tbl,
1780 alc260_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01001781 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001782
Takashi Iwaic3c2c9e2012-02-16 12:59:55 +01001783 /* automatic parse from the BIOS config */
1784 err = alc260_parse_auto_config(codec);
1785 if (err < 0)
1786 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001787
Takashi Iwai7504b6c2013-03-18 11:25:51 +01001788 if (!spec->gen.no_analog)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02001789 set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
Takashi Iwai1d045db2011-07-07 18:23:21 +02001790
Takashi Iwai1d045db2011-07-07 18:23:21 +02001791 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001792 spec->shutup = alc_eapd_shutup;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001793
Takashi Iwai1727a772013-01-10 09:52:52 +01001794 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01001795
Takashi Iwai1d045db2011-07-07 18:23:21 +02001796 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02001797
1798 error:
1799 alc_free(codec);
1800 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02001801}
1802
1803
1804/*
1805 * ALC882/883/885/888/889 support
1806 *
1807 * ALC882 is almost identical with ALC880 but has cleaner and more flexible
1808 * configuration. Each pin widget can choose any input DACs and a mixer.
1809 * Each ADC is connected from a mixer of all inputs. This makes possible
1810 * 6-channel independent captures.
1811 *
1812 * In addition, an independent DAC for the multi-playback (not used in this
1813 * driver yet).
1814 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02001815
1816/*
1817 * Pin config fixes
1818 */
1819enum {
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01001820 ALC882_FIXUP_ABIT_AW9D_MAX,
1821 ALC882_FIXUP_LENOVO_Y530,
1822 ALC882_FIXUP_PB_M5210,
1823 ALC882_FIXUP_ACER_ASPIRE_7736,
1824 ALC882_FIXUP_ASUS_W90V,
Marton Balint8f239212012-03-05 21:33:23 +01001825 ALC889_FIXUP_CD,
David Henningssonb2c53e22014-01-01 14:01:34 +01001826 ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01001827 ALC889_FIXUP_VAIO_TT,
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01001828 ALC888_FIXUP_EEE1601,
Takashi Iwai177943a2011-11-09 12:55:18 +01001829 ALC882_FIXUP_EAPD,
Takashi Iwai7a6069b2011-11-09 15:22:01 +01001830 ALC883_FIXUP_EAPD,
Takashi Iwai8812c4f2011-11-09 17:39:15 +01001831 ALC883_FIXUP_ACER_EAPD,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001832 ALC882_FIXUP_GPIO1,
1833 ALC882_FIXUP_GPIO2,
Takashi Iwaieb844d52011-11-09 18:03:07 +01001834 ALC882_FIXUP_GPIO3,
Takashi Iwai68ef0562011-11-09 18:24:44 +01001835 ALC889_FIXUP_COEF,
1836 ALC882_FIXUP_ASUS_W2JC,
Takashi Iwaic3e837b2011-11-10 16:01:47 +01001837 ALC882_FIXUP_ACER_ASPIRE_4930G,
1838 ALC882_FIXUP_ACER_ASPIRE_8930G,
1839 ALC882_FIXUP_ASPIRE_8930G_VERBS,
Takashi Iwai56710872011-11-14 17:42:11 +01001840 ALC885_FIXUP_MACPRO_GPIO,
Takashi Iwai02a237b2012-02-13 15:25:07 +01001841 ALC889_FIXUP_DAC_ROUTE,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001842 ALC889_FIXUP_MBP_VREF,
1843 ALC889_FIXUP_IMAC91_VREF,
Adrien Vergée7729a42014-01-24 14:56:14 -05001844 ALC889_FIXUP_MBA11_VREF,
Takashi Iwai0756f092013-12-04 13:59:45 +01001845 ALC889_FIXUP_MBA21_VREF,
Takashi Iwaic20f31e2014-02-03 11:02:10 +01001846 ALC889_FIXUP_MP11_VREF,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02001847 ALC882_FIXUP_INV_DMIC,
Takashi Iwaie427c232012-07-29 10:04:08 +02001848 ALC882_FIXUP_NO_PRIMARY_HP,
Takashi Iwai1f0bbf02013-11-28 15:21:21 +01001849 ALC887_FIXUP_ASUS_BASS,
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01001850 ALC887_FIXUP_BASS_CHMAP,
Takashi Iwai1d045db2011-07-07 18:23:21 +02001851};
1852
Takashi Iwai68ef0562011-11-09 18:24:44 +01001853static void alc889_fixup_coef(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001854 const struct hda_fixup *fix, int action)
Takashi Iwai68ef0562011-11-09 18:24:44 +01001855{
Takashi Iwai1727a772013-01-10 09:52:52 +01001856 if (action != HDA_FIXUP_ACT_INIT)
Takashi Iwai68ef0562011-11-09 18:24:44 +01001857 return;
1858 alc889_coef_init(codec);
1859}
1860
Takashi Iwai56710872011-11-14 17:42:11 +01001861/* toggle speaker-output according to the hp-jack state */
1862static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
1863{
1864 unsigned int gpiostate, gpiomask, gpiodir;
1865
1866 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
1867 AC_VERB_GET_GPIO_DATA, 0);
1868
1869 if (!muted)
1870 gpiostate |= (1 << pin);
1871 else
1872 gpiostate &= ~(1 << pin);
1873
1874 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
1875 AC_VERB_GET_GPIO_MASK, 0);
1876 gpiomask |= (1 << pin);
1877
1878 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
1879 AC_VERB_GET_GPIO_DIRECTION, 0);
1880 gpiodir |= (1 << pin);
1881
1882
1883 snd_hda_codec_write(codec, codec->afg, 0,
1884 AC_VERB_SET_GPIO_MASK, gpiomask);
1885 snd_hda_codec_write(codec, codec->afg, 0,
1886 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
1887
1888 msleep(1);
1889
1890 snd_hda_codec_write(codec, codec->afg, 0,
1891 AC_VERB_SET_GPIO_DATA, gpiostate);
1892}
1893
1894/* set up GPIO at initialization */
1895static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001896 const struct hda_fixup *fix, int action)
Takashi Iwai56710872011-11-14 17:42:11 +01001897{
Takashi Iwai1727a772013-01-10 09:52:52 +01001898 if (action != HDA_FIXUP_ACT_INIT)
Takashi Iwai56710872011-11-14 17:42:11 +01001899 return;
1900 alc882_gpio_mute(codec, 0, 0);
1901 alc882_gpio_mute(codec, 1, 0);
1902}
1903
Takashi Iwai02a237b2012-02-13 15:25:07 +01001904/* Fix the connection of some pins for ALC889:
1905 * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
1906 * work correctly (bko#42740)
1907 */
1908static void alc889_fixup_dac_route(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001909 const struct hda_fixup *fix, int action)
Takashi Iwai02a237b2012-02-13 15:25:07 +01001910{
Takashi Iwai1727a772013-01-10 09:52:52 +01001911 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwaief8d60f2012-02-17 10:12:38 +01001912 /* fake the connections during parsing the tree */
Takashi Iwai02a237b2012-02-13 15:25:07 +01001913 hda_nid_t conn1[2] = { 0x0c, 0x0d };
1914 hda_nid_t conn2[2] = { 0x0e, 0x0f };
1915 snd_hda_override_conn_list(codec, 0x14, 2, conn1);
1916 snd_hda_override_conn_list(codec, 0x15, 2, conn1);
1917 snd_hda_override_conn_list(codec, 0x18, 2, conn2);
1918 snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
Takashi Iwai1727a772013-01-10 09:52:52 +01001919 } else if (action == HDA_FIXUP_ACT_PROBE) {
Takashi Iwaief8d60f2012-02-17 10:12:38 +01001920 /* restore the connections */
1921 hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
1922 snd_hda_override_conn_list(codec, 0x14, 5, conn);
1923 snd_hda_override_conn_list(codec, 0x15, 5, conn);
1924 snd_hda_override_conn_list(codec, 0x18, 5, conn);
1925 snd_hda_override_conn_list(codec, 0x1a, 5, conn);
Takashi Iwai02a237b2012-02-13 15:25:07 +01001926 }
1927}
1928
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001929/* Set VREF on HP pin */
1930static void alc889_fixup_mbp_vref(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01001931 const struct hda_fixup *fix, int action)
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001932{
1933 struct alc_spec *spec = codec->spec;
1934 static hda_nid_t nids[2] = { 0x14, 0x15 };
1935 int i;
1936
Takashi Iwai1727a772013-01-10 09:52:52 +01001937 if (action != HDA_FIXUP_ACT_INIT)
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001938 return;
1939 for (i = 0; i < ARRAY_SIZE(nids); i++) {
1940 unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]);
1941 if (get_defcfg_device(val) != AC_JACK_HP_OUT)
1942 continue;
Takashi Iwaid3f02d62013-01-10 10:12:22 +01001943 val = snd_hda_codec_get_pin_target(codec, nids[i]);
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001944 val |= AC_PINCTL_VREF_80;
Takashi Iwaicdd03ce2012-04-20 12:34:50 +02001945 snd_hda_set_pin_ctl(codec, nids[i], val);
Takashi Iwai08c189f2012-12-19 15:22:24 +01001946 spec->gen.keep_vref_in_automute = 1;
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001947 break;
1948 }
1949}
1950
Takashi Iwai0756f092013-12-04 13:59:45 +01001951static void alc889_fixup_mac_pins(struct hda_codec *codec,
1952 const hda_nid_t *nids, int num_nids)
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001953{
1954 struct alc_spec *spec = codec->spec;
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001955 int i;
1956
Takashi Iwai0756f092013-12-04 13:59:45 +01001957 for (i = 0; i < num_nids; i++) {
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001958 unsigned int val;
Takashi Iwaid3f02d62013-01-10 10:12:22 +01001959 val = snd_hda_codec_get_pin_target(codec, nids[i]);
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001960 val |= AC_PINCTL_VREF_50;
Takashi Iwaicdd03ce2012-04-20 12:34:50 +02001961 snd_hda_set_pin_ctl(codec, nids[i], val);
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001962 }
Takashi Iwai08c189f2012-12-19 15:22:24 +01001963 spec->gen.keep_vref_in_automute = 1;
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01001964}
1965
Takashi Iwai0756f092013-12-04 13:59:45 +01001966/* Set VREF on speaker pins on imac91 */
1967static void alc889_fixup_imac91_vref(struct hda_codec *codec,
1968 const struct hda_fixup *fix, int action)
1969{
1970 static hda_nid_t nids[2] = { 0x18, 0x1a };
1971
1972 if (action == HDA_FIXUP_ACT_INIT)
1973 alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
1974}
1975
Adrien Vergée7729a42014-01-24 14:56:14 -05001976/* Set VREF on speaker pins on mba11 */
1977static void alc889_fixup_mba11_vref(struct hda_codec *codec,
1978 const struct hda_fixup *fix, int action)
1979{
1980 static hda_nid_t nids[1] = { 0x18 };
1981
1982 if (action == HDA_FIXUP_ACT_INIT)
1983 alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
1984}
1985
Takashi Iwai0756f092013-12-04 13:59:45 +01001986/* Set VREF on speaker pins on mba21 */
1987static void alc889_fixup_mba21_vref(struct hda_codec *codec,
1988 const struct hda_fixup *fix, int action)
1989{
1990 static hda_nid_t nids[2] = { 0x18, 0x19 };
1991
1992 if (action == HDA_FIXUP_ACT_INIT)
1993 alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
1994}
1995
Takashi Iwaie427c232012-07-29 10:04:08 +02001996/* Don't take HP output as primary
Fernando Luis Vázquez Caod9111492013-02-12 16:49:46 +09001997 * Strangely, the speaker output doesn't work on Vaio Z and some Vaio
1998 * all-in-one desktop PCs (for example VGC-LN51JGB) through DAC 0x05
Takashi Iwaie427c232012-07-29 10:04:08 +02001999 */
2000static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01002001 const struct hda_fixup *fix, int action)
Takashi Iwaie427c232012-07-29 10:04:08 +02002002{
2003 struct alc_spec *spec = codec->spec;
Takashi Iwaida96fb52013-07-29 16:54:36 +02002004 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwai08c189f2012-12-19 15:22:24 +01002005 spec->gen.no_primary_hp = 1;
Takashi Iwaida96fb52013-07-29 16:54:36 +02002006 spec->gen.no_multi_io = 1;
2007 }
Takashi Iwaie427c232012-07-29 10:04:08 +02002008}
2009
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01002010static void alc_fixup_bass_chmap(struct hda_codec *codec,
2011 const struct hda_fixup *fix, int action);
2012
Takashi Iwai1727a772013-01-10 09:52:52 +01002013static const struct hda_fixup alc882_fixups[] = {
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002014 [ALC882_FIXUP_ABIT_AW9D_MAX] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002015 .type = HDA_FIXUP_PINS,
2016 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002017 { 0x15, 0x01080104 }, /* side */
2018 { 0x16, 0x01011012 }, /* rear */
2019 { 0x17, 0x01016011 }, /* clfe */
2020 { }
2021 }
2022 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002023 [ALC882_FIXUP_LENOVO_Y530] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002024 .type = HDA_FIXUP_PINS,
2025 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002026 { 0x15, 0x99130112 }, /* rear int speakers */
2027 { 0x16, 0x99130111 }, /* subwoofer */
2028 { }
2029 }
2030 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002031 [ALC882_FIXUP_PB_M5210] = {
Takashi Iwaifd108212013-01-10 10:18:14 +01002032 .type = HDA_FIXUP_PINCTLS,
2033 .v.pins = (const struct hda_pintbl[]) {
2034 { 0x19, PIN_VREF50 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02002035 {}
2036 }
2037 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002038 [ALC882_FIXUP_ACER_ASPIRE_7736] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002039 .type = HDA_FIXUP_FUNC,
Takashi Iwai23d30f22012-05-07 17:17:32 +02002040 .v.func = alc_fixup_sku_ignore,
Takashi Iwai1d045db2011-07-07 18:23:21 +02002041 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002042 [ALC882_FIXUP_ASUS_W90V] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002043 .type = HDA_FIXUP_PINS,
2044 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai5cdf7452011-10-26 23:04:08 +02002045 { 0x16, 0x99130110 }, /* fix sequence for CLFE */
2046 { }
2047 }
2048 },
Marton Balint8f239212012-03-05 21:33:23 +01002049 [ALC889_FIXUP_CD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002050 .type = HDA_FIXUP_PINS,
2051 .v.pins = (const struct hda_pintbl[]) {
Marton Balint8f239212012-03-05 21:33:23 +01002052 { 0x1c, 0x993301f0 }, /* CD */
2053 { }
2054 }
2055 },
David Henningssonb2c53e22014-01-01 14:01:34 +01002056 [ALC889_FIXUP_FRONT_HP_NO_PRESENCE] = {
2057 .type = HDA_FIXUP_PINS,
2058 .v.pins = (const struct hda_pintbl[]) {
2059 { 0x1b, 0x02214120 }, /* Front HP jack is flaky, disable jack detect */
2060 { }
2061 },
2062 .chained = true,
2063 .chain_id = ALC889_FIXUP_CD,
2064 },
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002065 [ALC889_FIXUP_VAIO_TT] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002066 .type = HDA_FIXUP_PINS,
2067 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002068 { 0x17, 0x90170111 }, /* hidden surround speaker */
2069 { }
2070 }
2071 },
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01002072 [ALC888_FIXUP_EEE1601] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002073 .type = HDA_FIXUP_VERBS,
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01002074 .v.verbs = (const struct hda_verb[]) {
2075 { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
2076 { 0x20, AC_VERB_SET_PROC_COEF, 0x0838 },
2077 { }
2078 }
Takashi Iwai177943a2011-11-09 12:55:18 +01002079 },
2080 [ALC882_FIXUP_EAPD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002081 .type = HDA_FIXUP_VERBS,
Takashi Iwai177943a2011-11-09 12:55:18 +01002082 .v.verbs = (const struct hda_verb[]) {
2083 /* change to EAPD mode */
2084 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2085 { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
2086 { }
2087 }
2088 },
Takashi Iwai7a6069b2011-11-09 15:22:01 +01002089 [ALC883_FIXUP_EAPD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002090 .type = HDA_FIXUP_VERBS,
Takashi Iwai7a6069b2011-11-09 15:22:01 +01002091 .v.verbs = (const struct hda_verb[]) {
2092 /* change to EAPD mode */
2093 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2094 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
2095 { }
2096 }
2097 },
Takashi Iwai8812c4f2011-11-09 17:39:15 +01002098 [ALC883_FIXUP_ACER_EAPD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002099 .type = HDA_FIXUP_VERBS,
Takashi Iwai8812c4f2011-11-09 17:39:15 +01002100 .v.verbs = (const struct hda_verb[]) {
2101 /* eanable EAPD on Acer laptops */
2102 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2103 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2104 { }
2105 }
2106 },
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002107 [ALC882_FIXUP_GPIO1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002108 .type = HDA_FIXUP_VERBS,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002109 .v.verbs = alc_gpio1_init_verbs,
2110 },
2111 [ALC882_FIXUP_GPIO2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002112 .type = HDA_FIXUP_VERBS,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002113 .v.verbs = alc_gpio2_init_verbs,
2114 },
Takashi Iwaieb844d52011-11-09 18:03:07 +01002115 [ALC882_FIXUP_GPIO3] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002116 .type = HDA_FIXUP_VERBS,
Takashi Iwaieb844d52011-11-09 18:03:07 +01002117 .v.verbs = alc_gpio3_init_verbs,
2118 },
Takashi Iwai68ef0562011-11-09 18:24:44 +01002119 [ALC882_FIXUP_ASUS_W2JC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002120 .type = HDA_FIXUP_VERBS,
Takashi Iwai68ef0562011-11-09 18:24:44 +01002121 .v.verbs = alc_gpio1_init_verbs,
2122 .chained = true,
2123 .chain_id = ALC882_FIXUP_EAPD,
2124 },
2125 [ALC889_FIXUP_COEF] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002126 .type = HDA_FIXUP_FUNC,
Takashi Iwai68ef0562011-11-09 18:24:44 +01002127 .v.func = alc889_fixup_coef,
2128 },
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002129 [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002130 .type = HDA_FIXUP_PINS,
2131 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002132 { 0x16, 0x99130111 }, /* CLFE speaker */
2133 { 0x17, 0x99130112 }, /* surround speaker */
2134 { }
Takashi Iwai038d4fe2012-04-11 17:18:12 +02002135 },
2136 .chained = true,
2137 .chain_id = ALC882_FIXUP_GPIO1,
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002138 },
2139 [ALC882_FIXUP_ACER_ASPIRE_8930G] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002140 .type = HDA_FIXUP_PINS,
2141 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002142 { 0x16, 0x99130111 }, /* CLFE speaker */
2143 { 0x1b, 0x99130112 }, /* surround speaker */
2144 { }
2145 },
2146 .chained = true,
2147 .chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS,
2148 },
2149 [ALC882_FIXUP_ASPIRE_8930G_VERBS] = {
2150 /* additional init verbs for Acer Aspire 8930G */
Takashi Iwai1727a772013-01-10 09:52:52 +01002151 .type = HDA_FIXUP_VERBS,
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002152 .v.verbs = (const struct hda_verb[]) {
2153 /* Enable all DACs */
2154 /* DAC DISABLE/MUTE 1? */
2155 /* setting bits 1-5 disables DAC nids 0x02-0x06
2156 * apparently. Init=0x38 */
2157 { 0x20, AC_VERB_SET_COEF_INDEX, 0x03 },
2158 { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
2159 /* DAC DISABLE/MUTE 2? */
2160 /* some bit here disables the other DACs.
2161 * Init=0x4900 */
2162 { 0x20, AC_VERB_SET_COEF_INDEX, 0x08 },
2163 { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
2164 /* DMIC fix
2165 * This laptop has a stereo digital microphone.
2166 * The mics are only 1cm apart which makes the stereo
2167 * useless. However, either the mic or the ALC889
2168 * makes the signal become a difference/sum signal
2169 * instead of standard stereo, which is annoying.
2170 * So instead we flip this bit which makes the
2171 * codec replicate the sum signal to both channels,
2172 * turning it into a normal mono mic.
2173 */
2174 /* DMIC_CONTROL? Init value = 0x0001 */
2175 { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
2176 { 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
2177 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2178 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2179 { }
Takashi Iwai038d4fe2012-04-11 17:18:12 +02002180 },
2181 .chained = true,
2182 .chain_id = ALC882_FIXUP_GPIO1,
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002183 },
Takashi Iwai56710872011-11-14 17:42:11 +01002184 [ALC885_FIXUP_MACPRO_GPIO] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002185 .type = HDA_FIXUP_FUNC,
Takashi Iwai56710872011-11-14 17:42:11 +01002186 .v.func = alc885_fixup_macpro_gpio,
2187 },
Takashi Iwai02a237b2012-02-13 15:25:07 +01002188 [ALC889_FIXUP_DAC_ROUTE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002189 .type = HDA_FIXUP_FUNC,
Takashi Iwai02a237b2012-02-13 15:25:07 +01002190 .v.func = alc889_fixup_dac_route,
2191 },
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002192 [ALC889_FIXUP_MBP_VREF] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002193 .type = HDA_FIXUP_FUNC,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002194 .v.func = alc889_fixup_mbp_vref,
2195 .chained = true,
2196 .chain_id = ALC882_FIXUP_GPIO1,
2197 },
2198 [ALC889_FIXUP_IMAC91_VREF] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002199 .type = HDA_FIXUP_FUNC,
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002200 .v.func = alc889_fixup_imac91_vref,
2201 .chained = true,
2202 .chain_id = ALC882_FIXUP_GPIO1,
2203 },
Adrien Vergée7729a42014-01-24 14:56:14 -05002204 [ALC889_FIXUP_MBA11_VREF] = {
2205 .type = HDA_FIXUP_FUNC,
2206 .v.func = alc889_fixup_mba11_vref,
2207 .chained = true,
2208 .chain_id = ALC889_FIXUP_MBP_VREF,
2209 },
Takashi Iwai0756f092013-12-04 13:59:45 +01002210 [ALC889_FIXUP_MBA21_VREF] = {
2211 .type = HDA_FIXUP_FUNC,
2212 .v.func = alc889_fixup_mba21_vref,
2213 .chained = true,
2214 .chain_id = ALC889_FIXUP_MBP_VREF,
2215 },
Takashi Iwaic20f31e2014-02-03 11:02:10 +01002216 [ALC889_FIXUP_MP11_VREF] = {
2217 .type = HDA_FIXUP_FUNC,
2218 .v.func = alc889_fixup_mba11_vref,
2219 .chained = true,
2220 .chain_id = ALC885_FIXUP_MACPRO_GPIO,
2221 },
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002222 [ALC882_FIXUP_INV_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002223 .type = HDA_FIXUP_FUNC,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002224 .v.func = alc_fixup_inv_dmic_0x12,
2225 },
Takashi Iwaie427c232012-07-29 10:04:08 +02002226 [ALC882_FIXUP_NO_PRIMARY_HP] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002227 .type = HDA_FIXUP_FUNC,
Takashi Iwaie427c232012-07-29 10:04:08 +02002228 .v.func = alc882_fixup_no_primary_hp,
2229 },
Takashi Iwai1f0bbf02013-11-28 15:21:21 +01002230 [ALC887_FIXUP_ASUS_BASS] = {
2231 .type = HDA_FIXUP_PINS,
2232 .v.pins = (const struct hda_pintbl[]) {
2233 {0x16, 0x99130130}, /* bass speaker */
2234 {}
2235 },
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01002236 .chained = true,
2237 .chain_id = ALC887_FIXUP_BASS_CHMAP,
2238 },
2239 [ALC887_FIXUP_BASS_CHMAP] = {
2240 .type = HDA_FIXUP_FUNC,
2241 .v.func = alc_fixup_bass_chmap,
Takashi Iwai1f0bbf02013-11-28 15:21:21 +01002242 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02002243};
2244
2245static const struct snd_pci_quirk alc882_fixup_tbl[] = {
Takashi Iwai8812c4f2011-11-09 17:39:15 +01002246 SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
2247 SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
2248 SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD),
2249 SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
2250 SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD),
2251 SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_FIXUP_ACER_EAPD),
Takashi Iwaic3e837b2011-11-10 16:01:47 +01002252 SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
2253 ALC882_FIXUP_ACER_ASPIRE_4930G),
2254 SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
2255 ALC882_FIXUP_ACER_ASPIRE_4930G),
2256 SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
2257 ALC882_FIXUP_ACER_ASPIRE_8930G),
2258 SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
2259 ALC882_FIXUP_ACER_ASPIRE_8930G),
2260 SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
2261 ALC882_FIXUP_ACER_ASPIRE_4930G),
2262 SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
2263 ALC882_FIXUP_ACER_ASPIRE_4930G),
2264 SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
2265 ALC882_FIXUP_ACER_ASPIRE_4930G),
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002266 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
Takashi Iwaif5c53d82012-05-07 10:07:33 +02002267 SND_PCI_QUIRK(0x1025, 0x021e, "Acer Aspire 5739G",
2268 ALC882_FIXUP_ACER_ASPIRE_4930G),
Takashi Iwai02a237b2012-02-13 15:25:07 +01002269 SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
Takashi Iwaife97da12012-04-12 08:00:19 +02002270 SND_PCI_QUIRK(0x1025, 0x026b, "Acer Aspire 8940G", ALC882_FIXUP_ACER_ASPIRE_8930G),
Takashi Iwaiac9b1cd2011-11-09 17:45:55 +01002271 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
Takashi Iwai177943a2011-11-09 12:55:18 +01002272 SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002273 SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
Takashi Iwai68ef0562011-11-09 18:24:44 +01002274 SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
Takashi Iwai0e7cc2e2011-11-09 12:42:48 +01002275 SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
Takashi Iwai1f0bbf02013-11-28 15:21:21 +01002276 SND_PCI_QUIRK(0x1043, 0x84bc, "ASUS ET2700", ALC887_FIXUP_ASUS_BASS),
Takashi Iwaiac9b1cd2011-11-09 17:45:55 +01002277 SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
Takashi Iwaie427c232012-07-29 10:04:08 +02002278 SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
Fernando Luis Vázquez Cao12e31a72013-02-12 16:47:44 +09002279 SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
Takashi Iwai56710872011-11-14 17:42:11 +01002280
2281 /* All Apple entries are in codec SSIDs */
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002282 SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
2283 SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
2284 SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
Takashi Iwaic20f31e2014-02-03 11:02:10 +01002285 SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC889_FIXUP_MP11_VREF),
Takashi Iwai56710872011-11-14 17:42:11 +01002286 SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
2287 SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002288 SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
2289 SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
Takashi Iwai56710872011-11-14 17:42:11 +01002290 SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
Adrien Vergée7729a42014-01-24 14:56:14 -05002291 SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBA11_VREF),
Takashi Iwai0756f092013-12-04 13:59:45 +01002292 SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBA21_VREF),
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002293 SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
2294 SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
Takashi Iwai56710872011-11-14 17:42:11 +01002295 SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002296 SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
2297 SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
2298 SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
Josh Boyer29ebe402012-04-12 13:55:36 -04002299 SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO),
Takashi Iwai05193632012-11-12 10:07:36 +01002300 SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002301 SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
2302 SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
2303 SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
Takashi Iwai56710872011-11-14 17:42:11 +01002304
Takashi Iwai7a6069b2011-11-09 15:22:01 +01002305 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
Takashi Iwaibca40132012-05-07 11:13:14 +02002306 SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
Takashi Iwaieb844d52011-11-09 18:03:07 +01002307 SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
David Henningssonb2c53e22014-01-01 14:01:34 +01002308 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
Takashi Iwai5c0ebfb2011-11-07 17:59:13 +01002309 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
Takashi Iwai7a6069b2011-11-09 15:22:01 +01002310 SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
2311 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
Takashi Iwaiac9b1cd2011-11-09 17:45:55 +01002312 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
Takashi Iwai68ef0562011-11-09 18:24:44 +01002313 SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_FIXUP_COEF),
Takashi Iwai1d045db2011-07-07 18:23:21 +02002314 {}
2315};
2316
Takashi Iwai1727a772013-01-10 09:52:52 +01002317static const struct hda_model_fixup alc882_fixup_models[] = {
Takashi Iwai912093b2012-04-11 14:03:41 +02002318 {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"},
2319 {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"},
2320 {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"},
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002321 {.id = ALC882_FIXUP_INV_DMIC, .name = "inv-dmic"},
Takashi Iwaie427c232012-07-29 10:04:08 +02002322 {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"},
Takashi Iwai912093b2012-04-11 14:03:41 +02002323 {}
2324};
2325
Takashi Iwai1d045db2011-07-07 18:23:21 +02002326/*
2327 * BIOS auto configuration
2328 */
2329/* almost identical with ALC880 parser... */
2330static int alc882_parse_auto_config(struct hda_codec *codec)
2331{
Takashi Iwai1d045db2011-07-07 18:23:21 +02002332 static const hda_nid_t alc882_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002333 static const hda_nid_t alc882_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2334 return alc_parse_auto_config(codec, alc882_ignore, alc882_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002335}
2336
Takashi Iwai1d045db2011-07-07 18:23:21 +02002337/*
2338 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002339static int patch_alc882(struct hda_codec *codec)
2340{
2341 struct alc_spec *spec;
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002342 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002343
Takashi Iwai3de95172012-05-07 18:03:15 +02002344 err = alc_alloc_spec(codec, 0x0b);
2345 if (err < 0)
2346 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002347
Takashi Iwai3de95172012-05-07 18:03:15 +02002348 spec = codec->spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002349
2350 switch (codec->vendor_id) {
2351 case 0x10ec0882:
2352 case 0x10ec0885:
2353 break;
2354 default:
2355 /* ALC883 and variants */
2356 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
2357 break;
2358 }
2359
Takashi Iwai1727a772013-01-10 09:52:52 +01002360 snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
Takashi Iwai912093b2012-04-11 14:03:41 +02002361 alc882_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01002362 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002363
2364 alc_auto_parse_customize_define(codec);
2365
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002366 if (has_cdefine_beep(codec))
2367 spec->gen.beep_nid = 0x01;
2368
Takashi Iwai1a97b7f2012-02-21 11:11:48 +01002369 /* automatic parse from the BIOS config */
2370 err = alc882_parse_auto_config(codec);
2371 if (err < 0)
2372 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002373
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002374 if (!spec->gen.no_analog && spec->gen.beep_nid)
Takashi Iwai1d045db2011-07-07 18:23:21 +02002375 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
2376
Takashi Iwai1d045db2011-07-07 18:23:21 +02002377 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002378
Takashi Iwai1727a772013-01-10 09:52:52 +01002379 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01002380
Takashi Iwai1d045db2011-07-07 18:23:21 +02002381 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002382
2383 error:
2384 alc_free(codec);
2385 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002386}
2387
2388
2389/*
2390 * ALC262 support
2391 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002392static int alc262_parse_auto_config(struct hda_codec *codec)
2393{
Takashi Iwai1d045db2011-07-07 18:23:21 +02002394 static const hda_nid_t alc262_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002395 static const hda_nid_t alc262_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2396 return alc_parse_auto_config(codec, alc262_ignore, alc262_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002397}
2398
2399/*
2400 * Pin config fixes
2401 */
2402enum {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002403 ALC262_FIXUP_FSC_H270,
Takashi Iwai7513e6d2013-01-18 15:41:34 +01002404 ALC262_FIXUP_FSC_S7110,
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002405 ALC262_FIXUP_HP_Z200,
2406 ALC262_FIXUP_TYAN,
Takashi Iwaic4701502011-11-07 14:20:07 +01002407 ALC262_FIXUP_LENOVO_3000,
Takashi Iwaib42590b2011-11-07 14:41:01 +01002408 ALC262_FIXUP_BENQ,
2409 ALC262_FIXUP_BENQ_T31,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002410 ALC262_FIXUP_INV_DMIC,
Mengdong Linb5c66112013-11-29 00:35:35 -05002411 ALC262_FIXUP_INTEL_BAYLEYBAY,
Takashi Iwai1d045db2011-07-07 18:23:21 +02002412};
2413
Takashi Iwai1727a772013-01-10 09:52:52 +01002414static const struct hda_fixup alc262_fixups[] = {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002415 [ALC262_FIXUP_FSC_H270] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002416 .type = HDA_FIXUP_PINS,
2417 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002418 { 0x14, 0x99130110 }, /* speaker */
2419 { 0x15, 0x0221142f }, /* front HP */
2420 { 0x1b, 0x0121141f }, /* rear HP */
2421 { }
2422 }
2423 },
Takashi Iwai7513e6d2013-01-18 15:41:34 +01002424 [ALC262_FIXUP_FSC_S7110] = {
2425 .type = HDA_FIXUP_PINS,
2426 .v.pins = (const struct hda_pintbl[]) {
2427 { 0x15, 0x90170110 }, /* speaker */
2428 { }
2429 },
2430 .chained = true,
2431 .chain_id = ALC262_FIXUP_BENQ,
2432 },
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002433 [ALC262_FIXUP_HP_Z200] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002434 .type = HDA_FIXUP_PINS,
2435 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002436 { 0x16, 0x99130120 }, /* internal speaker */
2437 { }
2438 }
2439 },
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002440 [ALC262_FIXUP_TYAN] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002441 .type = HDA_FIXUP_PINS,
2442 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002443 { 0x14, 0x1993e1f0 }, /* int AUX */
2444 { }
2445 }
2446 },
Takashi Iwaic4701502011-11-07 14:20:07 +01002447 [ALC262_FIXUP_LENOVO_3000] = {
Takashi Iwaifd108212013-01-10 10:18:14 +01002448 .type = HDA_FIXUP_PINCTLS,
2449 .v.pins = (const struct hda_pintbl[]) {
2450 { 0x19, PIN_VREF50 },
Takashi Iwaib42590b2011-11-07 14:41:01 +01002451 {}
2452 },
2453 .chained = true,
2454 .chain_id = ALC262_FIXUP_BENQ,
2455 },
2456 [ALC262_FIXUP_BENQ] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002457 .type = HDA_FIXUP_VERBS,
Takashi Iwaib42590b2011-11-07 14:41:01 +01002458 .v.verbs = (const struct hda_verb[]) {
Takashi Iwaic4701502011-11-07 14:20:07 +01002459 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2460 { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
2461 {}
2462 }
2463 },
Takashi Iwaib42590b2011-11-07 14:41:01 +01002464 [ALC262_FIXUP_BENQ_T31] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002465 .type = HDA_FIXUP_VERBS,
Takashi Iwaib42590b2011-11-07 14:41:01 +01002466 .v.verbs = (const struct hda_verb[]) {
2467 { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
2468 { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
2469 {}
2470 }
2471 },
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002472 [ALC262_FIXUP_INV_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002473 .type = HDA_FIXUP_FUNC,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002474 .v.func = alc_fixup_inv_dmic_0x12,
2475 },
Mengdong Linb5c66112013-11-29 00:35:35 -05002476 [ALC262_FIXUP_INTEL_BAYLEYBAY] = {
2477 .type = HDA_FIXUP_FUNC,
2478 .v.func = alc_fixup_no_depop_delay,
2479 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02002480};
2481
2482static const struct snd_pci_quirk alc262_fixup_tbl[] = {
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002483 SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
Takashi Iwai7513e6d2013-01-18 15:41:34 +01002484 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu Lifebook S7110", ALC262_FIXUP_FSC_S7110),
Takashi Iwai3dcd3be2011-11-07 14:59:40 +01002485 SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
Takashi Iwaiea4e7af2011-11-07 12:23:55 +01002486 SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
2487 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
Takashi Iwaic4701502011-11-07 14:20:07 +01002488 SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
Takashi Iwaib42590b2011-11-07 14:41:01 +01002489 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
2490 SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
Mengdong Linb5c66112013-11-29 00:35:35 -05002491 SND_PCI_QUIRK(0x8086, 0x7270, "BayleyBay", ALC262_FIXUP_INTEL_BAYLEYBAY),
Takashi Iwai1d045db2011-07-07 18:23:21 +02002492 {}
2493};
2494
Takashi Iwai1727a772013-01-10 09:52:52 +01002495static const struct hda_model_fixup alc262_fixup_models[] = {
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002496 {.id = ALC262_FIXUP_INV_DMIC, .name = "inv-dmic"},
2497 {}
2498};
Takashi Iwai1d045db2011-07-07 18:23:21 +02002499
Takashi Iwai1d045db2011-07-07 18:23:21 +02002500/*
2501 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002502static int patch_alc262(struct hda_codec *codec)
2503{
2504 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002505 int err;
2506
Takashi Iwai3de95172012-05-07 18:03:15 +02002507 err = alc_alloc_spec(codec, 0x0b);
2508 if (err < 0)
2509 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002510
Takashi Iwai3de95172012-05-07 18:03:15 +02002511 spec = codec->spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +01002512 spec->gen.shared_mic_vref_pin = 0x18;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002513
2514#if 0
2515 /* pshou 07/11/05 set a zero PCM sample to DAC when FIFO is
2516 * under-run
2517 */
2518 {
2519 int tmp;
2520 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
2521 tmp = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_PROC_COEF, 0);
2522 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
2523 snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF, tmp | 0x80);
2524 }
2525#endif
Takashi Iwai1d045db2011-07-07 18:23:21 +02002526 alc_fix_pll_init(codec, 0x20, 0x0a, 10);
2527
Takashi Iwai1727a772013-01-10 09:52:52 +01002528 snd_hda_pick_fixup(codec, alc262_fixup_models, alc262_fixup_tbl,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002529 alc262_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01002530 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002531
Takashi Iwaiaf741c12012-05-07 18:09:48 +02002532 alc_auto_parse_customize_define(codec);
2533
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002534 if (has_cdefine_beep(codec))
2535 spec->gen.beep_nid = 0x01;
2536
Takashi Iwai42399f72011-11-07 17:18:44 +01002537 /* automatic parse from the BIOS config */
2538 err = alc262_parse_auto_config(codec);
2539 if (err < 0)
2540 goto error;
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002541
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002542 if (!spec->gen.no_analog && spec->gen.beep_nid)
Takashi Iwai1d045db2011-07-07 18:23:21 +02002543 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
2544
Takashi Iwai1d045db2011-07-07 18:23:21 +02002545 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002546 spec->shutup = alc_eapd_shutup;
2547
Takashi Iwai1727a772013-01-10 09:52:52 +01002548 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01002549
Takashi Iwai1d045db2011-07-07 18:23:21 +02002550 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002551
2552 error:
2553 alc_free(codec);
2554 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002555}
2556
2557/*
2558 * ALC268
2559 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002560/* bind Beep switches of both NID 0x0f and 0x10 */
2561static const struct hda_bind_ctls alc268_bind_beep_sw = {
2562 .ops = &snd_hda_bind_sw,
2563 .values = {
2564 HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
2565 HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
2566 0
2567 },
2568};
2569
2570static const struct snd_kcontrol_new alc268_beep_mixer[] = {
2571 HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
2572 HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
2573 { }
2574};
2575
2576/* set PCBEEP vol = 0, mute connections */
2577static const struct hda_verb alc268_beep_init_verbs[] = {
2578 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
2579 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2580 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
2581 { }
2582};
2583
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002584enum {
2585 ALC268_FIXUP_INV_DMIC,
Takashi Iwaicb766402012-10-20 10:55:21 +02002586 ALC268_FIXUP_HP_EAPD,
Takashi Iwai24eff322013-11-04 18:21:08 +01002587 ALC268_FIXUP_SPDIF,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002588};
2589
Takashi Iwai1727a772013-01-10 09:52:52 +01002590static const struct hda_fixup alc268_fixups[] = {
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002591 [ALC268_FIXUP_INV_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002592 .type = HDA_FIXUP_FUNC,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002593 .v.func = alc_fixup_inv_dmic_0x12,
2594 },
Takashi Iwaicb766402012-10-20 10:55:21 +02002595 [ALC268_FIXUP_HP_EAPD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01002596 .type = HDA_FIXUP_VERBS,
Takashi Iwaicb766402012-10-20 10:55:21 +02002597 .v.verbs = (const struct hda_verb[]) {
2598 {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
2599 {}
2600 }
2601 },
Takashi Iwai24eff322013-11-04 18:21:08 +01002602 [ALC268_FIXUP_SPDIF] = {
2603 .type = HDA_FIXUP_PINS,
2604 .v.pins = (const struct hda_pintbl[]) {
2605 { 0x1e, 0x014b1180 }, /* enable SPDIF out */
2606 {}
2607 }
2608 },
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002609};
2610
Takashi Iwai1727a772013-01-10 09:52:52 +01002611static const struct hda_model_fixup alc268_fixup_models[] = {
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002612 {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
Takashi Iwaicb766402012-10-20 10:55:21 +02002613 {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
2614 {}
2615};
2616
2617static const struct snd_pci_quirk alc268_fixup_tbl[] = {
Takashi Iwai24eff322013-11-04 18:21:08 +01002618 SND_PCI_QUIRK(0x1025, 0x0139, "Acer TravelMate 6293", ALC268_FIXUP_SPDIF),
David Henningssonfcd8f3b2013-01-28 05:45:47 +01002619 SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
Takashi Iwaicb766402012-10-20 10:55:21 +02002620 /* below is codec SSID since multiple Toshiba laptops have the
2621 * same PCI SSID 1179:ff00
2622 */
2623 SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002624 {}
2625};
2626
Takashi Iwai1d045db2011-07-07 18:23:21 +02002627/*
2628 * BIOS auto configuration
2629 */
2630static int alc268_parse_auto_config(struct hda_codec *codec)
2631{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002632 static const hda_nid_t alc268_ssids[] = { 0x15, 0x1b, 0x14, 0 };
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002633 return alc_parse_auto_config(codec, NULL, alc268_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002634}
2635
Takashi Iwai1d045db2011-07-07 18:23:21 +02002636/*
2637 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02002638static int patch_alc268(struct hda_codec *codec)
2639{
2640 struct alc_spec *spec;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002641 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002642
Takashi Iwai1d045db2011-07-07 18:23:21 +02002643 /* ALC268 has no aa-loopback mixer */
Takashi Iwai3de95172012-05-07 18:03:15 +02002644 err = alc_alloc_spec(codec, 0);
2645 if (err < 0)
2646 return err;
2647
2648 spec = codec->spec;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002649 spec->gen.beep_nid = 0x01;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002650
Takashi Iwai1727a772013-01-10 09:52:52 +01002651 snd_hda_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
2652 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002653
Takashi Iwai6ebb8052011-08-16 15:15:40 +02002654 /* automatic parse from the BIOS config */
2655 err = alc268_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002656 if (err < 0)
2657 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002658
Takashi Iwai7504b6c2013-03-18 11:25:51 +01002659 if (err > 0 && !spec->gen.no_analog &&
2660 spec->gen.autocfg.speaker_pins[0] != 0x1d) {
2661 add_mixer(spec, alc268_beep_mixer);
2662 snd_hda_add_verbs(codec, alc268_beep_init_verbs);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002663 if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
2664 /* override the amp caps for beep generator */
2665 snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
2666 (0x0c << AC_AMPCAP_OFFSET_SHIFT) |
2667 (0x0c << AC_AMPCAP_NUM_STEPS_SHIFT) |
2668 (0x07 << AC_AMPCAP_STEP_SIZE_SHIFT) |
2669 (0 << AC_AMPCAP_MUTE_SHIFT));
2670 }
2671
Takashi Iwai1d045db2011-07-07 18:23:21 +02002672 codec->patch_ops = alc_patch_ops;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002673 spec->shutup = alc_eapd_shutup;
2674
Takashi Iwai1727a772013-01-10 09:52:52 +01002675 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai6e72aa52012-06-25 10:52:25 +02002676
Takashi Iwai1d045db2011-07-07 18:23:21 +02002677 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02002678
2679 error:
2680 alc_free(codec);
2681 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002682}
2683
2684/*
2685 * ALC269
2686 */
Takashi Iwai08c189f2012-12-19 15:22:24 +01002687
2688static int playback_pcm_open(struct hda_pcm_stream *hinfo,
2689 struct hda_codec *codec,
2690 struct snd_pcm_substream *substream)
2691{
2692 struct hda_gen_spec *spec = codec->spec;
2693 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
2694 hinfo);
2695}
2696
2697static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
2698 struct hda_codec *codec,
2699 unsigned int stream_tag,
2700 unsigned int format,
2701 struct snd_pcm_substream *substream)
2702{
2703 struct hda_gen_spec *spec = codec->spec;
2704 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
2705 stream_tag, format, substream);
2706}
2707
2708static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
2709 struct hda_codec *codec,
2710 struct snd_pcm_substream *substream)
2711{
2712 struct hda_gen_spec *spec = codec->spec;
2713 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
2714}
2715
Takashi Iwai1d045db2011-07-07 18:23:21 +02002716static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
2717 .substreams = 1,
2718 .channels_min = 2,
2719 .channels_max = 8,
2720 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
2721 /* NID is set in alc_build_pcms */
2722 .ops = {
Takashi Iwai08c189f2012-12-19 15:22:24 +01002723 .open = playback_pcm_open,
2724 .prepare = playback_pcm_prepare,
2725 .cleanup = playback_pcm_cleanup
Takashi Iwai1d045db2011-07-07 18:23:21 +02002726 },
2727};
2728
2729static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
2730 .substreams = 1,
2731 .channels_min = 2,
2732 .channels_max = 2,
2733 .rates = SNDRV_PCM_RATE_44100, /* fixed rate */
2734 /* NID is set in alc_build_pcms */
2735};
2736
Takashi Iwai1d045db2011-07-07 18:23:21 +02002737/* different alc269-variants */
2738enum {
2739 ALC269_TYPE_ALC269VA,
2740 ALC269_TYPE_ALC269VB,
2741 ALC269_TYPE_ALC269VC,
Kailang Yangadcc70b2012-05-25 08:08:38 +02002742 ALC269_TYPE_ALC269VD,
Kailang Yang065380f2013-01-10 10:25:48 +01002743 ALC269_TYPE_ALC280,
2744 ALC269_TYPE_ALC282,
Kailang Yang2af02be2013-08-22 10:03:50 +02002745 ALC269_TYPE_ALC283,
Kailang Yang065380f2013-01-10 10:25:48 +01002746 ALC269_TYPE_ALC284,
Kailang Yang161ebf22013-10-24 11:36:33 +02002747 ALC269_TYPE_ALC285,
Kailang Yang7fc7d042013-04-25 11:04:43 +02002748 ALC269_TYPE_ALC286,
Kailang Yang1d04c9d2013-10-24 11:35:18 +02002749 ALC269_TYPE_ALC255,
Takashi Iwai1d045db2011-07-07 18:23:21 +02002750};
2751
2752/*
2753 * BIOS auto configuration
2754 */
2755static int alc269_parse_auto_config(struct hda_codec *codec)
2756{
Takashi Iwai1d045db2011-07-07 18:23:21 +02002757 static const hda_nid_t alc269_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002758 static const hda_nid_t alc269_ssids[] = { 0, 0x1b, 0x14, 0x21 };
2759 static const hda_nid_t alc269va_ssids[] = { 0x15, 0x1b, 0x14, 0 };
2760 struct alc_spec *spec = codec->spec;
Kailang Yangadcc70b2012-05-25 08:08:38 +02002761 const hda_nid_t *ssids;
2762
2763 switch (spec->codec_variant) {
2764 case ALC269_TYPE_ALC269VA:
2765 case ALC269_TYPE_ALC269VC:
Kailang Yang065380f2013-01-10 10:25:48 +01002766 case ALC269_TYPE_ALC280:
2767 case ALC269_TYPE_ALC284:
Kailang Yang161ebf22013-10-24 11:36:33 +02002768 case ALC269_TYPE_ALC285:
Kailang Yangadcc70b2012-05-25 08:08:38 +02002769 ssids = alc269va_ssids;
2770 break;
2771 case ALC269_TYPE_ALC269VB:
2772 case ALC269_TYPE_ALC269VD:
Kailang Yang065380f2013-01-10 10:25:48 +01002773 case ALC269_TYPE_ALC282:
Kailang Yang2af02be2013-08-22 10:03:50 +02002774 case ALC269_TYPE_ALC283:
Kailang Yang7fc7d042013-04-25 11:04:43 +02002775 case ALC269_TYPE_ALC286:
Kailang Yang1d04c9d2013-10-24 11:35:18 +02002776 case ALC269_TYPE_ALC255:
Kailang Yangadcc70b2012-05-25 08:08:38 +02002777 ssids = alc269_ssids;
2778 break;
2779 default:
2780 ssids = alc269_ssids;
2781 break;
2782 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02002783
Takashi Iwai3e6179b2011-07-08 16:55:13 +02002784 return alc_parse_auto_config(codec, alc269_ignore, ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002785}
2786
Kailang Yangf7ae9ba2014-06-30 16:10:37 +08002787static int find_ext_mic_pin(struct hda_codec *codec);
2788
2789static void alc286_shutup(struct hda_codec *codec)
2790{
2791 int i;
2792 int mic_pin = find_ext_mic_pin(codec);
2793 /* don't shut up pins when unloading the driver; otherwise it breaks
2794 * the default pin setup at the next load of the driver
2795 */
2796 if (codec->bus->shutdown)
2797 return;
2798 for (i = 0; i < codec->init_pins.used; i++) {
2799 struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
2800 /* use read here for syncing after issuing each verb */
2801 if (pin->nid != mic_pin)
2802 snd_hda_codec_read(codec, pin->nid, 0,
2803 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
2804 }
2805 codec->pins_shutup = 1;
2806}
2807
Kailang Yang1387e2d2012-11-08 10:23:18 +01002808static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
Takashi Iwai1d045db2011-07-07 18:23:21 +02002809{
2810 int val = alc_read_coef_idx(codec, 0x04);
Takashi Iwaif3ee07d2014-08-15 17:35:00 +02002811 if (val == -1)
2812 return;
Takashi Iwai1d045db2011-07-07 18:23:21 +02002813 if (power_up)
2814 val |= 1 << 11;
2815 else
2816 val &= ~(1 << 11);
2817 alc_write_coef_idx(codec, 0x04, val);
2818}
2819
2820static void alc269_shutup(struct hda_codec *codec)
2821{
Kailang Yangadcc70b2012-05-25 08:08:38 +02002822 struct alc_spec *spec = codec->spec;
2823
Kailang Yang1387e2d2012-11-08 10:23:18 +01002824 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
2825 alc269vb_toggle_power_output(codec, 0);
2826 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
2827 (alc_get_coef0(codec) & 0x00ff) == 0x018) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02002828 msleep(150);
2829 }
Takashi Iwai9bfb2842013-07-24 14:31:50 +02002830 snd_hda_shutup_pins(codec);
Takashi Iwai1d045db2011-07-07 18:23:21 +02002831}
2832
Kailang Yangcb149cb2014-03-18 16:45:32 +08002833static void alc282_restore_default_value(struct hda_codec *codec)
2834{
2835 int val;
2836
2837 /* Power Down Control */
2838 alc_write_coef_idx(codec, 0x03, 0x0002);
2839 /* FIFO and filter clock */
2840 alc_write_coef_idx(codec, 0x05, 0x0700);
2841 /* DMIC control */
2842 alc_write_coef_idx(codec, 0x07, 0x0200);
2843 /* Analog clock */
2844 val = alc_read_coef_idx(codec, 0x06);
2845 alc_write_coef_idx(codec, 0x06, (val & ~0x00f0) | 0x0);
2846 /* JD */
2847 val = alc_read_coef_idx(codec, 0x08);
2848 alc_write_coef_idx(codec, 0x08, (val & ~0xfffc) | 0x0c2c);
2849 /* JD offset1 */
2850 alc_write_coef_idx(codec, 0x0a, 0xcccc);
2851 /* JD offset2 */
2852 alc_write_coef_idx(codec, 0x0b, 0xcccc);
2853 /* LDO1/2/3, DAC/ADC */
2854 alc_write_coef_idx(codec, 0x0e, 0x6e00);
2855 /* JD */
2856 val = alc_read_coef_idx(codec, 0x0f);
2857 alc_write_coef_idx(codec, 0x0f, (val & ~0xf800) | 0x1000);
2858 /* Capless */
2859 val = alc_read_coef_idx(codec, 0x10);
2860 alc_write_coef_idx(codec, 0x10, (val & ~0xfc00) | 0x0c00);
2861 /* Class D test 4 */
2862 alc_write_coef_idx(codec, 0x6f, 0x0);
2863 /* IO power down directly */
2864 val = alc_read_coef_idx(codec, 0x0c);
2865 alc_write_coef_idx(codec, 0x0c, (val & ~0xfe00) | 0x0);
2866 /* ANC */
2867 alc_write_coef_idx(codec, 0x34, 0xa0c0);
2868 /* AGC MUX */
2869 val = alc_read_coef_idx(codec, 0x16);
2870 alc_write_coef_idx(codec, 0x16, (val & ~0x0008) | 0x0);
2871 /* DAC simple content protection */
2872 val = alc_read_coef_idx(codec, 0x1d);
2873 alc_write_coef_idx(codec, 0x1d, (val & ~0x00e0) | 0x0);
2874 /* ADC simple content protection */
2875 val = alc_read_coef_idx(codec, 0x1f);
2876 alc_write_coef_idx(codec, 0x1f, (val & ~0x00e0) | 0x0);
2877 /* DAC ADC Zero Detection */
2878 alc_write_coef_idx(codec, 0x21, 0x8804);
2879 /* PLL */
2880 alc_write_coef_idx(codec, 0x63, 0x2902);
2881 /* capless control 2 */
2882 alc_write_coef_idx(codec, 0x68, 0xa080);
2883 /* capless control 3 */
2884 alc_write_coef_idx(codec, 0x69, 0x3400);
2885 /* capless control 4 */
2886 alc_write_coef_idx(codec, 0x6a, 0x2f3e);
2887 /* capless control 5 */
2888 alc_write_coef_idx(codec, 0x6b, 0x0);
2889 /* class D test 2 */
2890 val = alc_read_coef_idx(codec, 0x6d);
2891 alc_write_coef_idx(codec, 0x6d, (val & ~0x0fff) | 0x0900);
2892 /* class D test 3 */
2893 alc_write_coef_idx(codec, 0x6e, 0x110a);
2894 /* class D test 5 */
2895 val = alc_read_coef_idx(codec, 0x70);
2896 alc_write_coef_idx(codec, 0x70, (val & ~0x00f8) | 0x00d8);
2897 /* class D test 6 */
2898 alc_write_coef_idx(codec, 0x71, 0x0014);
2899 /* classD OCP */
2900 alc_write_coef_idx(codec, 0x72, 0xc2ba);
2901 /* classD pure DC test */
2902 val = alc_read_coef_idx(codec, 0x77);
2903 alc_write_coef_idx(codec, 0x77, (val & ~0x0f80) | 0x0);
2904 /* Class D amp control */
2905 alc_write_coef_idx(codec, 0x6c, 0xfc06);
2906}
2907
Kailang Yang7b5c7a02014-03-18 16:15:54 +08002908static void alc282_init(struct hda_codec *codec)
2909{
2910 struct alc_spec *spec = codec->spec;
2911 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
2912 bool hp_pin_sense;
2913 int coef78;
2914
Kailang Yangcb149cb2014-03-18 16:45:32 +08002915 alc282_restore_default_value(codec);
2916
Kailang Yang7b5c7a02014-03-18 16:15:54 +08002917 if (!hp_pin)
2918 return;
2919 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
2920 coef78 = alc_read_coef_idx(codec, 0x78);
2921
2922 /* Index 0x78 Direct Drive HP AMP LPM Control 1 */
2923 /* Headphone capless set to high power mode */
2924 alc_write_coef_idx(codec, 0x78, 0x9004);
2925
2926 if (hp_pin_sense)
2927 msleep(2);
2928
2929 snd_hda_codec_write(codec, hp_pin, 0,
2930 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
2931
2932 if (hp_pin_sense)
2933 msleep(85);
2934
2935 snd_hda_codec_write(codec, hp_pin, 0,
2936 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
2937
2938 if (hp_pin_sense)
2939 msleep(100);
2940
2941 /* Headphone capless set to normal mode */
2942 alc_write_coef_idx(codec, 0x78, coef78);
2943}
2944
2945static void alc282_shutup(struct hda_codec *codec)
2946{
2947 struct alc_spec *spec = codec->spec;
2948 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
2949 bool hp_pin_sense;
2950 int coef78;
2951
2952 if (!hp_pin) {
2953 alc269_shutup(codec);
2954 return;
2955 }
2956
2957 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
2958 coef78 = alc_read_coef_idx(codec, 0x78);
2959 alc_write_coef_idx(codec, 0x78, 0x9004);
2960
2961 if (hp_pin_sense)
2962 msleep(2);
2963
2964 snd_hda_codec_write(codec, hp_pin, 0,
2965 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
2966
2967 if (hp_pin_sense)
2968 msleep(85);
2969
2970 snd_hda_codec_write(codec, hp_pin, 0,
2971 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
2972
2973 if (hp_pin_sense)
2974 msleep(100);
2975
2976 alc_auto_setup_eapd(codec, false);
2977 snd_hda_shutup_pins(codec);
2978 alc_write_coef_idx(codec, 0x78, coef78);
2979}
2980
Kailang Yang6bd55b02014-03-17 13:51:27 +08002981static void alc283_restore_default_value(struct hda_codec *codec)
2982{
2983 int val;
2984
2985 /* Power Down Control */
2986 alc_write_coef_idx(codec, 0x03, 0x0002);
2987 /* FIFO and filter clock */
2988 alc_write_coef_idx(codec, 0x05, 0x0700);
2989 /* DMIC control */
2990 alc_write_coef_idx(codec, 0x07, 0x0200);
2991 /* Analog clock */
2992 val = alc_read_coef_idx(codec, 0x06);
2993 alc_write_coef_idx(codec, 0x06, (val & ~0x00f0) | 0x0);
2994 /* JD */
2995 val = alc_read_coef_idx(codec, 0x08);
2996 alc_write_coef_idx(codec, 0x08, (val & ~0xfffc) | 0x0c2c);
2997 /* JD offset1 */
2998 alc_write_coef_idx(codec, 0x0a, 0xcccc);
2999 /* JD offset2 */
3000 alc_write_coef_idx(codec, 0x0b, 0xcccc);
3001 /* LDO1/2/3, DAC/ADC */
3002 alc_write_coef_idx(codec, 0x0e, 0x6fc0);
3003 /* JD */
3004 val = alc_read_coef_idx(codec, 0x0f);
3005 alc_write_coef_idx(codec, 0x0f, (val & ~0xf800) | 0x1000);
3006 /* Capless */
3007 val = alc_read_coef_idx(codec, 0x10);
3008 alc_write_coef_idx(codec, 0x10, (val & ~0xfc00) | 0x0c00);
3009 /* Class D test 4 */
3010 alc_write_coef_idx(codec, 0x3a, 0x0);
3011 /* IO power down directly */
3012 val = alc_read_coef_idx(codec, 0x0c);
3013 alc_write_coef_idx(codec, 0x0c, (val & ~0xfe00) | 0x0);
3014 /* ANC */
3015 alc_write_coef_idx(codec, 0x22, 0xa0c0);
3016 /* AGC MUX */
3017 val = alc_read_coefex_idx(codec, 0x53, 0x01);
3018 alc_write_coefex_idx(codec, 0x53, 0x01, (val & ~0x000f) | 0x0008);
3019 /* DAC simple content protection */
3020 val = alc_read_coef_idx(codec, 0x1d);
3021 alc_write_coef_idx(codec, 0x1d, (val & ~0x00e0) | 0x0);
3022 /* ADC simple content protection */
3023 val = alc_read_coef_idx(codec, 0x1f);
3024 alc_write_coef_idx(codec, 0x1f, (val & ~0x00e0) | 0x0);
3025 /* DAC ADC Zero Detection */
3026 alc_write_coef_idx(codec, 0x21, 0x8804);
3027 /* PLL */
3028 alc_write_coef_idx(codec, 0x2e, 0x2902);
3029 /* capless control 2 */
3030 alc_write_coef_idx(codec, 0x33, 0xa080);
3031 /* capless control 3 */
3032 alc_write_coef_idx(codec, 0x34, 0x3400);
3033 /* capless control 4 */
3034 alc_write_coef_idx(codec, 0x35, 0x2f3e);
3035 /* capless control 5 */
3036 alc_write_coef_idx(codec, 0x36, 0x0);
3037 /* class D test 2 */
3038 val = alc_read_coef_idx(codec, 0x38);
3039 alc_write_coef_idx(codec, 0x38, (val & ~0x0fff) | 0x0900);
3040 /* class D test 3 */
3041 alc_write_coef_idx(codec, 0x39, 0x110a);
3042 /* class D test 5 */
3043 val = alc_read_coef_idx(codec, 0x3b);
3044 alc_write_coef_idx(codec, 0x3b, (val & ~0x00f8) | 0x00d8);
3045 /* class D test 6 */
3046 alc_write_coef_idx(codec, 0x3c, 0x0014);
3047 /* classD OCP */
3048 alc_write_coef_idx(codec, 0x3d, 0xc2ba);
3049 /* classD pure DC test */
3050 val = alc_read_coef_idx(codec, 0x42);
3051 alc_write_coef_idx(codec, 0x42, (val & ~0x0f80) | 0x0);
3052 /* test mode */
3053 alc_write_coef_idx(codec, 0x49, 0x0);
3054 /* Class D DC enable */
3055 val = alc_read_coef_idx(codec, 0x40);
3056 alc_write_coef_idx(codec, 0x40, (val & ~0xf800) | 0x9800);
3057 /* DC offset */
3058 val = alc_read_coef_idx(codec, 0x42);
3059 alc_write_coef_idx(codec, 0x42, (val & ~0xf000) | 0x2000);
3060 /* Class D amp control */
3061 alc_write_coef_idx(codec, 0x37, 0xfc06);
3062}
3063
Kailang Yang2af02be2013-08-22 10:03:50 +02003064static void alc283_init(struct hda_codec *codec)
3065{
3066 struct alc_spec *spec = codec->spec;
3067 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
3068 bool hp_pin_sense;
3069 int val;
3070
Kailang Yang8314f222014-04-03 17:28:39 +08003071 if (!spec->gen.autocfg.hp_outs) {
3072 if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
3073 hp_pin = spec->gen.autocfg.line_out_pins[0];
3074 }
3075
Kailang Yang6bd55b02014-03-17 13:51:27 +08003076 alc283_restore_default_value(codec);
3077
Kailang Yang2af02be2013-08-22 10:03:50 +02003078 if (!hp_pin)
3079 return;
3080 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
3081
3082 /* Index 0x43 Direct Drive HP AMP LPM Control 1 */
3083 /* Headphone capless set to high power mode */
3084 alc_write_coef_idx(codec, 0x43, 0x9004);
3085
3086 snd_hda_codec_write(codec, hp_pin, 0,
3087 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
3088
3089 if (hp_pin_sense)
3090 msleep(85);
3091
3092 snd_hda_codec_write(codec, hp_pin, 0,
3093 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
3094
3095 if (hp_pin_sense)
3096 msleep(85);
3097 /* Index 0x46 Combo jack auto switch control 2 */
3098 /* 3k pull low control for Headset jack. */
3099 val = alc_read_coef_idx(codec, 0x46);
3100 alc_write_coef_idx(codec, 0x46, val & ~(3 << 12));
3101 /* Headphone capless set to normal mode */
3102 alc_write_coef_idx(codec, 0x43, 0x9614);
3103}
3104
3105static void alc283_shutup(struct hda_codec *codec)
3106{
3107 struct alc_spec *spec = codec->spec;
3108 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
3109 bool hp_pin_sense;
3110 int val;
3111
Kailang Yang8314f222014-04-03 17:28:39 +08003112 if (!spec->gen.autocfg.hp_outs) {
3113 if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
3114 hp_pin = spec->gen.autocfg.line_out_pins[0];
3115 }
3116
Kailang Yang2af02be2013-08-22 10:03:50 +02003117 if (!hp_pin) {
3118 alc269_shutup(codec);
3119 return;
3120 }
3121
3122 hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
3123
3124 alc_write_coef_idx(codec, 0x43, 0x9004);
3125
3126 snd_hda_codec_write(codec, hp_pin, 0,
3127 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
3128
3129 if (hp_pin_sense)
Kailang Yang88011c092013-10-24 15:45:24 +02003130 msleep(100);
Kailang Yang2af02be2013-08-22 10:03:50 +02003131
3132 snd_hda_codec_write(codec, hp_pin, 0,
3133 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
3134
3135 val = alc_read_coef_idx(codec, 0x46);
3136 alc_write_coef_idx(codec, 0x46, val | (3 << 12));
3137
3138 if (hp_pin_sense)
Kailang Yang88011c092013-10-24 15:45:24 +02003139 msleep(100);
Kailang Yang0435b3f2014-04-08 17:14:14 +08003140 alc_auto_setup_eapd(codec, false);
Kailang Yang2af02be2013-08-22 10:03:50 +02003141 snd_hda_shutup_pins(codec);
3142 alc_write_coef_idx(codec, 0x43, 0x9614);
3143}
3144
Kailang Yangad60d502013-06-28 12:03:01 +02003145static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
3146 unsigned int val)
3147{
3148 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
3149 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val & 0xffff); /* LSB */
3150 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_PROC_COEF, val >> 16); /* MSB */
3151}
3152
3153static int alc5505_coef_get(struct hda_codec *codec, unsigned int index_reg)
3154{
3155 unsigned int val;
3156
3157 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_COEF_INDEX, index_reg >> 1);
3158 val = snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
3159 & 0xffff;
3160 val |= snd_hda_codec_read(codec, 0x51, 0, AC_VERB_GET_PROC_COEF, 0)
3161 << 16;
3162 return val;
3163}
3164
3165static void alc5505_dsp_halt(struct hda_codec *codec)
3166{
3167 unsigned int val;
3168
3169 alc5505_coef_set(codec, 0x3000, 0x000c); /* DSP CPU stop */
3170 alc5505_coef_set(codec, 0x880c, 0x0008); /* DDR enter self refresh */
3171 alc5505_coef_set(codec, 0x61c0, 0x11110080); /* Clock control for PLL and CPU */
3172 alc5505_coef_set(codec, 0x6230, 0xfc0d4011); /* Disable Input OP */
3173 alc5505_coef_set(codec, 0x61b4, 0x040a2b03); /* Stop PLL2 */
3174 alc5505_coef_set(codec, 0x61b0, 0x00005b17); /* Stop PLL1 */
3175 alc5505_coef_set(codec, 0x61b8, 0x04133303); /* Stop PLL3 */
3176 val = alc5505_coef_get(codec, 0x6220);
3177 alc5505_coef_set(codec, 0x6220, (val | 0x3000)); /* switch Ringbuffer clock to DBUS clock */
3178}
3179
3180static void alc5505_dsp_back_from_halt(struct hda_codec *codec)
3181{
3182 alc5505_coef_set(codec, 0x61b8, 0x04133302);
3183 alc5505_coef_set(codec, 0x61b0, 0x00005b16);
3184 alc5505_coef_set(codec, 0x61b4, 0x040a2b02);
3185 alc5505_coef_set(codec, 0x6230, 0xf80d4011);
3186 alc5505_coef_set(codec, 0x6220, 0x2002010f);
3187 alc5505_coef_set(codec, 0x880c, 0x00000004);
3188}
3189
3190static void alc5505_dsp_init(struct hda_codec *codec)
3191{
3192 unsigned int val;
3193
3194 alc5505_dsp_halt(codec);
3195 alc5505_dsp_back_from_halt(codec);
3196 alc5505_coef_set(codec, 0x61b0, 0x5b14); /* PLL1 control */
3197 alc5505_coef_set(codec, 0x61b0, 0x5b16);
3198 alc5505_coef_set(codec, 0x61b4, 0x04132b00); /* PLL2 control */
3199 alc5505_coef_set(codec, 0x61b4, 0x04132b02);
3200 alc5505_coef_set(codec, 0x61b8, 0x041f3300); /* PLL3 control*/
3201 alc5505_coef_set(codec, 0x61b8, 0x041f3302);
3202 snd_hda_codec_write(codec, 0x51, 0, AC_VERB_SET_CODEC_RESET, 0); /* Function reset */
3203 alc5505_coef_set(codec, 0x61b8, 0x041b3302);
3204 alc5505_coef_set(codec, 0x61b8, 0x04173302);
3205 alc5505_coef_set(codec, 0x61b8, 0x04163302);
3206 alc5505_coef_set(codec, 0x8800, 0x348b328b); /* DRAM control */
3207 alc5505_coef_set(codec, 0x8808, 0x00020022); /* DRAM control */
3208 alc5505_coef_set(codec, 0x8818, 0x00000400); /* DRAM control */
3209
3210 val = alc5505_coef_get(codec, 0x6200) >> 16; /* Read revision ID */
3211 if (val <= 3)
3212 alc5505_coef_set(codec, 0x6220, 0x2002010f); /* I/O PAD Configuration */
3213 else
3214 alc5505_coef_set(codec, 0x6220, 0x6002018f);
3215
3216 alc5505_coef_set(codec, 0x61ac, 0x055525f0); /**/
3217 alc5505_coef_set(codec, 0x61c0, 0x12230080); /* Clock control */
3218 alc5505_coef_set(codec, 0x61b4, 0x040e2b02); /* PLL2 control */
3219 alc5505_coef_set(codec, 0x61bc, 0x010234f8); /* OSC Control */
3220 alc5505_coef_set(codec, 0x880c, 0x00000004); /* DRAM Function control */
3221 alc5505_coef_set(codec, 0x880c, 0x00000003);
3222 alc5505_coef_set(codec, 0x880c, 0x00000010);
Takashi Iwaicd63a5f2013-07-05 12:13:59 +02003223
3224#ifdef HALT_REALTEK_ALC5505
3225 alc5505_dsp_halt(codec);
3226#endif
Kailang Yangad60d502013-06-28 12:03:01 +02003227}
3228
Takashi Iwaicd63a5f2013-07-05 12:13:59 +02003229#ifdef HALT_REALTEK_ALC5505
3230#define alc5505_dsp_suspend(codec) /* NOP */
3231#define alc5505_dsp_resume(codec) /* NOP */
3232#else
3233#define alc5505_dsp_suspend(codec) alc5505_dsp_halt(codec)
3234#define alc5505_dsp_resume(codec) alc5505_dsp_back_from_halt(codec)
3235#endif
3236
Takashi Iwai2a439522011-07-26 09:52:50 +02003237#ifdef CONFIG_PM
Kailang Yangad60d502013-06-28 12:03:01 +02003238static int alc269_suspend(struct hda_codec *codec)
3239{
3240 struct alc_spec *spec = codec->spec;
3241
3242 if (spec->has_alc5505_dsp)
Takashi Iwaicd63a5f2013-07-05 12:13:59 +02003243 alc5505_dsp_suspend(codec);
Kailang Yangad60d502013-06-28 12:03:01 +02003244 return alc_suspend(codec);
3245}
3246
Takashi Iwai1d045db2011-07-07 18:23:21 +02003247static int alc269_resume(struct hda_codec *codec)
3248{
Kailang Yangadcc70b2012-05-25 08:08:38 +02003249 struct alc_spec *spec = codec->spec;
3250
Kailang Yang1387e2d2012-11-08 10:23:18 +01003251 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
3252 alc269vb_toggle_power_output(codec, 0);
3253 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
Kailang Yangadcc70b2012-05-25 08:08:38 +02003254 (alc_get_coef0(codec) & 0x00ff) == 0x018) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003255 msleep(150);
3256 }
3257
3258 codec->patch_ops.init(codec);
3259
Kailang Yang1387e2d2012-11-08 10:23:18 +01003260 if (spec->codec_variant == ALC269_TYPE_ALC269VB)
3261 alc269vb_toggle_power_output(codec, 1);
3262 if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
Kailang Yangadcc70b2012-05-25 08:08:38 +02003263 (alc_get_coef0(codec) & 0x00ff) == 0x017) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02003264 msleep(200);
3265 }
3266
Takashi Iwai1d045db2011-07-07 18:23:21 +02003267 snd_hda_codec_resume_amp(codec);
3268 snd_hda_codec_resume_cache(codec);
Takashi Iwai0623a882013-06-25 09:28:40 +02003269 alc_inv_dmic_sync(codec, true);
Takashi Iwai1d045db2011-07-07 18:23:21 +02003270 hda_call_check_power_status(codec, 0x01);
Hui Wangf4753712014-08-19 12:07:03 +08003271
3272 /* on some machine, the BIOS will clear the codec gpio data when enter
3273 * suspend, and won't restore the data after resume, so we restore it
3274 * in the driver.
3275 */
3276 if (spec->gpio_led)
3277 snd_hda_codec_write(codec, codec->afg, 0, AC_VERB_SET_GPIO_DATA,
3278 spec->gpio_led);
3279
Kailang Yangad60d502013-06-28 12:03:01 +02003280 if (spec->has_alc5505_dsp)
Takashi Iwaicd63a5f2013-07-05 12:13:59 +02003281 alc5505_dsp_resume(codec);
Kailang Yangc5177c82013-07-24 14:39:49 +02003282
Takashi Iwai1d045db2011-07-07 18:23:21 +02003283 return 0;
3284}
Takashi Iwai2a439522011-07-26 09:52:50 +02003285#endif /* CONFIG_PM */
Takashi Iwai1d045db2011-07-07 18:23:21 +02003286
David Henningsson108cc102012-07-20 10:37:25 +02003287static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003288 const struct hda_fixup *fix, int action)
David Henningsson108cc102012-07-20 10:37:25 +02003289{
3290 struct alc_spec *spec = codec->spec;
3291
Takashi Iwai1727a772013-01-10 09:52:52 +01003292 if (action == HDA_FIXUP_ACT_PRE_PROBE)
David Henningsson108cc102012-07-20 10:37:25 +02003293 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
3294}
3295
Takashi Iwai1d045db2011-07-07 18:23:21 +02003296static void alc269_fixup_hweq(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003297 const struct hda_fixup *fix, int action)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003298{
3299 int coef;
3300
Takashi Iwai1727a772013-01-10 09:52:52 +01003301 if (action != HDA_FIXUP_ACT_INIT)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003302 return;
3303 coef = alc_read_coef_idx(codec, 0x1e);
3304 alc_write_coef_idx(codec, 0x1e, coef | 0x80);
3305}
3306
David Henningsson7c478f02013-10-11 10:18:46 +02003307static void alc269_fixup_headset_mic(struct hda_codec *codec,
3308 const struct hda_fixup *fix, int action)
3309{
3310 struct alc_spec *spec = codec->spec;
3311
3312 if (action == HDA_FIXUP_ACT_PRE_PROBE)
3313 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
3314}
3315
Takashi Iwai1d045db2011-07-07 18:23:21 +02003316static void alc271_fixup_dmic(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003317 const struct hda_fixup *fix, int action)
Takashi Iwai1d045db2011-07-07 18:23:21 +02003318{
3319 static const struct hda_verb verbs[] = {
3320 {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
3321 {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
3322 {}
3323 };
3324 unsigned int cfg;
3325
Dylan Reid42397002013-04-05 14:58:22 -07003326 if (strcmp(codec->chip_name, "ALC271X") &&
3327 strcmp(codec->chip_name, "ALC269VB"))
Takashi Iwai1d045db2011-07-07 18:23:21 +02003328 return;
3329 cfg = snd_hda_codec_get_pincfg(codec, 0x12);
3330 if (get_defcfg_connect(cfg) == AC_JACK_PORT_FIXED)
3331 snd_hda_sequence_write(codec, verbs);
3332}
3333
Takashi Iwai017f2a12011-07-09 14:42:25 +02003334static void alc269_fixup_pcm_44k(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003335 const struct hda_fixup *fix, int action)
Takashi Iwai017f2a12011-07-09 14:42:25 +02003336{
3337 struct alc_spec *spec = codec->spec;
3338
Takashi Iwai1727a772013-01-10 09:52:52 +01003339 if (action != HDA_FIXUP_ACT_PROBE)
Takashi Iwai017f2a12011-07-09 14:42:25 +02003340 return;
3341
3342 /* Due to a hardware problem on Lenovo Ideadpad, we need to
3343 * fix the sample rate of analog I/O to 44.1kHz
3344 */
Takashi Iwai08c189f2012-12-19 15:22:24 +01003345 spec->gen.stream_analog_playback = &alc269_44k_pcm_analog_playback;
3346 spec->gen.stream_analog_capture = &alc269_44k_pcm_analog_capture;
Takashi Iwai017f2a12011-07-09 14:42:25 +02003347}
3348
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02003349static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003350 const struct hda_fixup *fix, int action)
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02003351{
3352 int coef;
3353
Takashi Iwai1727a772013-01-10 09:52:52 +01003354 if (action != HDA_FIXUP_ACT_INIT)
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02003355 return;
3356 /* The digital-mic unit sends PDM (differential signal) instead of
3357 * the standard PCM, thus you can't record a valid mono stream as is.
3358 * Below is a workaround specific to ALC269 to control the dmic
3359 * signal source as mono.
3360 */
3361 coef = alc_read_coef_idx(codec, 0x07);
3362 alc_write_coef_idx(codec, 0x07, coef | 0x80);
3363}
3364
Takashi Iwai24519912011-08-16 15:08:49 +02003365static void alc269_quanta_automute(struct hda_codec *codec)
3366{
Takashi Iwai08c189f2012-12-19 15:22:24 +01003367 snd_hda_gen_update_outputs(codec);
Takashi Iwai24519912011-08-16 15:08:49 +02003368
3369 snd_hda_codec_write(codec, 0x20, 0,
3370 AC_VERB_SET_COEF_INDEX, 0x0c);
3371 snd_hda_codec_write(codec, 0x20, 0,
3372 AC_VERB_SET_PROC_COEF, 0x680);
3373
3374 snd_hda_codec_write(codec, 0x20, 0,
3375 AC_VERB_SET_COEF_INDEX, 0x0c);
3376 snd_hda_codec_write(codec, 0x20, 0,
3377 AC_VERB_SET_PROC_COEF, 0x480);
3378}
3379
3380static void alc269_fixup_quanta_mute(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01003381 const struct hda_fixup *fix, int action)
Takashi Iwai24519912011-08-16 15:08:49 +02003382{
3383 struct alc_spec *spec = codec->spec;
Takashi Iwai1727a772013-01-10 09:52:52 +01003384 if (action != HDA_FIXUP_ACT_PROBE)
Takashi Iwai24519912011-08-16 15:08:49 +02003385 return;
Takashi Iwai08c189f2012-12-19 15:22:24 +01003386 spec->gen.automute_hook = alc269_quanta_automute;
Takashi Iwai24519912011-08-16 15:08:49 +02003387}
3388
David Henningssond240d1d2013-04-15 12:50:02 +02003389static void alc269_x101_hp_automute_hook(struct hda_codec *codec,
3390 struct hda_jack_tbl *jack)
3391{
3392 struct alc_spec *spec = codec->spec;
3393 int vref;
3394 msleep(200);
3395 snd_hda_gen_hp_automute(codec, jack);
3396
3397 vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
3398 msleep(100);
3399 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3400 vref);
3401 msleep(500);
3402 snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3403 vref);
3404}
3405
3406static void alc269_fixup_x101_headset_mic(struct hda_codec *codec,
3407 const struct hda_fixup *fix, int action)
3408{
3409 struct alc_spec *spec = codec->spec;
3410 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3411 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
3412 spec->gen.hp_automute_hook = alc269_x101_hp_automute_hook;
3413 }
3414}
3415
3416
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003417/* update mute-LED according to the speaker mute state via mic VREF pin */
3418static void alc269_fixup_mic_mute_hook(void *private_data, int enabled)
David Henningsson6d3cd5d2013-01-07 12:03:47 +01003419{
3420 struct hda_codec *codec = private_data;
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003421 struct alc_spec *spec = codec->spec;
3422 unsigned int pinval;
3423
3424 if (spec->mute_led_polarity)
3425 enabled = !enabled;
Takashi Iwai415d5552014-04-03 11:51:21 +02003426 pinval = snd_hda_codec_get_pin_target(codec, spec->mute_led_nid);
3427 pinval &= ~AC_PINCTL_VREFEN;
3428 pinval |= enabled ? AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80;
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003429 if (spec->mute_led_nid)
3430 snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval);
David Henningsson6d3cd5d2013-01-07 12:03:47 +01003431}
3432
David Henningssond5b6b652013-11-06 10:50:44 +01003433/* Make sure the led works even in runtime suspend */
3434static unsigned int led_power_filter(struct hda_codec *codec,
3435 hda_nid_t nid,
3436 unsigned int power_state)
3437{
3438 struct alc_spec *spec = codec->spec;
3439
Hui Wang50dd9052014-07-08 17:56:15 +08003440 if (power_state != AC_PWRST_D3 || nid == 0 ||
3441 (nid != spec->mute_led_nid && nid != spec->cap_mute_led_nid))
David Henningssond5b6b652013-11-06 10:50:44 +01003442 return power_state;
3443
3444 /* Set pin ctl again, it might have just been set to 0 */
3445 snd_hda_set_pin_ctl(codec, nid,
3446 snd_hda_codec_get_pin_target(codec, nid));
3447
3448 return AC_PWRST_D0;
3449}
3450
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003451static void alc269_fixup_hp_mute_led(struct hda_codec *codec,
3452 const struct hda_fixup *fix, int action)
David Henningsson6d3cd5d2013-01-07 12:03:47 +01003453{
3454 struct alc_spec *spec = codec->spec;
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003455 const struct dmi_device *dev = NULL;
3456
3457 if (action != HDA_FIXUP_ACT_PRE_PROBE)
3458 return;
3459
3460 while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
3461 int pol, pin;
3462 if (sscanf(dev->name, "HP_Mute_LED_%d_%x", &pol, &pin) != 2)
3463 continue;
3464 if (pin < 0x0a || pin >= 0x10)
3465 break;
3466 spec->mute_led_polarity = pol;
3467 spec->mute_led_nid = pin - 0x0a + 0x18;
3468 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
Takashi Iwaifd25a972012-12-20 14:57:18 +01003469 spec->gen.vmaster_mute_enum = 1;
David Henningssond5b6b652013-11-06 10:50:44 +01003470 codec->power_filter = led_power_filter;
Takashi Iwai4e76a882014-02-25 12:21:03 +01003471 codec_dbg(codec,
3472 "Detected mute LED for %x:%d\n", spec->mute_led_nid,
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003473 spec->mute_led_polarity);
David Henningsson6d3cd5d2013-01-07 12:03:47 +01003474 break;
3475 }
3476}
3477
David Henningssond06ac142013-02-18 11:41:55 +01003478static void alc269_fixup_hp_mute_led_mic1(struct hda_codec *codec,
3479 const struct hda_fixup *fix, int action)
3480{
3481 struct alc_spec *spec = codec->spec;
3482 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3483 spec->mute_led_polarity = 0;
3484 spec->mute_led_nid = 0x18;
3485 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
3486 spec->gen.vmaster_mute_enum = 1;
David Henningssond5b6b652013-11-06 10:50:44 +01003487 codec->power_filter = led_power_filter;
David Henningssond06ac142013-02-18 11:41:55 +01003488 }
3489}
3490
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003491static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec,
3492 const struct hda_fixup *fix, int action)
Takashi Iwai420b0fe2012-03-12 12:35:27 +01003493{
3494 struct alc_spec *spec = codec->spec;
Takashi Iwai9bb1f062013-01-10 17:14:29 +01003495 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwai08fb0d02013-01-10 17:33:58 +01003496 spec->mute_led_polarity = 0;
3497 spec->mute_led_nid = 0x19;
3498 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
Takashi Iwaifd25a972012-12-20 14:57:18 +01003499 spec->gen.vmaster_mute_enum = 1;
David Henningssond5b6b652013-11-06 10:50:44 +01003500 codec->power_filter = led_power_filter;
Takashi Iwai420b0fe2012-03-12 12:35:27 +01003501 }
3502}
3503
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003504/* turn on/off mute LED per vmaster hook */
3505static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled)
3506{
3507 struct hda_codec *codec = private_data;
3508 struct alc_spec *spec = codec->spec;
3509 unsigned int oldval = spec->gpio_led;
3510
3511 if (enabled)
3512 spec->gpio_led &= ~0x08;
3513 else
3514 spec->gpio_led |= 0x08;
3515 if (spec->gpio_led != oldval)
3516 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3517 spec->gpio_led);
3518}
3519
3520/* turn on/off mic-mute LED per capture hook */
3521static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec,
Takashi Iwai7fe30712014-01-30 17:59:02 +01003522 struct snd_kcontrol *kcontrol,
3523 struct snd_ctl_elem_value *ucontrol)
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01003524{
3525 struct alc_spec *spec = codec->spec;
3526 unsigned int oldval = spec->gpio_led;
3527
3528 if (!ucontrol)
3529 return;
3530
3531 if (ucontrol->value.integer.value[0] ||
3532 ucontrol->value.integer.value[1])
3533 spec->gpio_led &= ~0x10;
3534 else
3535 spec->gpio_led |= 0x10;
3536 if (spec->gpio_led != oldval)
3537 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
3538 spec->gpio_led);
3539}
3540
3541static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
3542 const struct hda_fixup *fix, int action)
3543{
3544 struct alc_spec *spec = codec->spec;
3545 static const struct hda_verb gpio_init[] = {
3546 { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 },
3547 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 },
3548 {}
3549 };
3550
3551 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3552 spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
3553 spec->gen.cap_sync_hook = alc269_fixup_hp_gpio_mic_mute_hook;
3554 spec->gpio_led = 0;
3555 snd_hda_add_verbs(codec, gpio_init);
3556 }
3557}
3558
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08003559/* turn on/off mic-mute LED per capture hook */
3560static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec,
3561 struct snd_kcontrol *kcontrol,
3562 struct snd_ctl_elem_value *ucontrol)
3563{
3564 struct alc_spec *spec = codec->spec;
3565 unsigned int pinval, enable, disable;
3566
Hui Wangfc1fad92014-07-08 17:56:14 +08003567 pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid);
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08003568 pinval &= ~AC_PINCTL_VREFEN;
3569 enable = pinval | AC_PINCTL_VREF_80;
3570 disable = pinval | AC_PINCTL_VREF_HIZ;
3571
3572 if (!ucontrol)
3573 return;
3574
3575 if (ucontrol->value.integer.value[0] ||
3576 ucontrol->value.integer.value[1])
3577 pinval = disable;
3578 else
3579 pinval = enable;
3580
3581 if (spec->cap_mute_led_nid)
3582 snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
3583}
3584
3585static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
3586 const struct hda_fixup *fix, int action)
3587{
3588 struct alc_spec *spec = codec->spec;
3589 static const struct hda_verb gpio_init[] = {
3590 { 0x01, AC_VERB_SET_GPIO_MASK, 0x08 },
3591 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 },
3592 {}
3593 };
3594
3595 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3596 spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
3597 spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
3598 spec->gpio_led = 0;
3599 spec->cap_mute_led_nid = 0x18;
3600 snd_hda_add_verbs(codec, gpio_init);
Hui Wang50dd9052014-07-08 17:56:15 +08003601 codec->power_filter = led_power_filter;
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08003602 }
3603}
3604
3605static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
3606 const struct hda_fixup *fix, int action)
3607{
3608 struct alc_spec *spec = codec->spec;
3609
3610 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
3611 spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
3612 spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
3613 spec->mute_led_polarity = 0;
3614 spec->mute_led_nid = 0x1a;
3615 spec->cap_mute_led_nid = 0x18;
3616 spec->gen.vmaster_mute_enum = 1;
3617 codec->power_filter = led_power_filter;
3618 }
3619}
3620
David Henningsson73bdd592013-04-15 15:44:14 +02003621static void alc_headset_mode_unplugged(struct hda_codec *codec)
3622{
3623 int val;
3624
3625 switch (codec->vendor_id) {
Kailang Yang9a22a8f52013-11-08 15:54:49 +08003626 case 0x10ec0255:
3627 /* LDO and MISC control */
3628 alc_write_coef_idx(codec, 0x1b, 0x0c0b);
3629 /* UAJ function set to menual mode */
3630 alc_write_coef_idx(codec, 0x45, 0xd089);
3631 /* Direct Drive HP Amp control(Set to verb control)*/
3632 val = alc_read_coefex_idx(codec, 0x57, 0x05);
3633 alc_write_coefex_idx(codec, 0x57, 0x05, val & ~(1<<14));
3634 /* Set MIC2 Vref gate with HP */
3635 alc_write_coef_idx(codec, 0x06, 0x6104);
3636 /* Direct Drive HP Amp control */
3637 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6);
3638 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003639 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003640 case 0x10ec0283:
3641 alc_write_coef_idx(codec, 0x1b, 0x0c0b);
3642 alc_write_coef_idx(codec, 0x45, 0xc429);
3643 val = alc_read_coef_idx(codec, 0x35);
3644 alc_write_coef_idx(codec, 0x35, val & 0xbfff);
3645 alc_write_coef_idx(codec, 0x06, 0x2104);
3646 alc_write_coef_idx(codec, 0x1a, 0x0001);
3647 alc_write_coef_idx(codec, 0x26, 0x0004);
3648 alc_write_coef_idx(codec, 0x32, 0x42a3);
3649 break;
3650 case 0x10ec0292:
3651 alc_write_coef_idx(codec, 0x76, 0x000e);
3652 alc_write_coef_idx(codec, 0x6c, 0x2400);
3653 alc_write_coef_idx(codec, 0x18, 0x7308);
3654 alc_write_coef_idx(codec, 0x6b, 0xc429);
3655 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003656 case 0x10ec0293:
3657 /* SET Line1 JD to 0 */
3658 val = alc_read_coef_idx(codec, 0x10);
3659 alc_write_coef_idx(codec, 0x10, (val & ~(7<<8)) | 6<<8);
3660 /* SET charge pump by verb */
3661 val = alc_read_coefex_idx(codec, 0x57, 0x05);
3662 alc_write_coefex_idx(codec, 0x57, 0x05, (val & ~(1<<15|1<<13)) | 0x0);
3663 /* SET EN_OSW to 1 */
3664 val = alc_read_coefex_idx(codec, 0x57, 0x03);
3665 alc_write_coefex_idx(codec, 0x57, 0x03, (val & ~(1<<10)) | (1<<10) );
3666 /* Combo JD gating with LINE1-VREFO */
3667 val = alc_read_coef_idx(codec, 0x1a);
3668 alc_write_coef_idx(codec, 0x1a, (val & ~(1<<3)) | (1<<3));
3669 /* Set to TRS type */
3670 alc_write_coef_idx(codec, 0x45, 0xc429);
3671 /* Combo Jack auto detect */
3672 val = alc_read_coef_idx(codec, 0x4a);
3673 alc_write_coef_idx(codec, 0x4a, (val & 0xfff0) | 0x000e);
3674 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003675 case 0x10ec0668:
3676 alc_write_coef_idx(codec, 0x15, 0x0d40);
3677 alc_write_coef_idx(codec, 0xb7, 0x802b);
3678 break;
3679 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01003680 codec_dbg(codec, "Headset jack set to unplugged mode.\n");
David Henningsson73bdd592013-04-15 15:44:14 +02003681}
3682
3683
3684static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
3685 hda_nid_t mic_pin)
3686{
3687 int val;
3688
3689 switch (codec->vendor_id) {
Kailang Yang9a22a8f52013-11-08 15:54:49 +08003690 case 0x10ec0255:
3691 alc_write_coef_idx(codec, 0x45, 0xc489);
3692 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3693 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8aa6);
3694 /* Set MIC2 Vref gate to normal */
3695 alc_write_coef_idx(codec, 0x06, 0x6100);
3696 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3697 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003698 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003699 case 0x10ec0283:
3700 alc_write_coef_idx(codec, 0x45, 0xc429);
3701 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3702 val = alc_read_coef_idx(codec, 0x35);
3703 alc_write_coef_idx(codec, 0x35, val | 1<<14);
3704 alc_write_coef_idx(codec, 0x06, 0x2100);
3705 alc_write_coef_idx(codec, 0x1a, 0x0021);
3706 alc_write_coef_idx(codec, 0x26, 0x008c);
3707 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3708 break;
3709 case 0x10ec0292:
3710 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3711 alc_write_coef_idx(codec, 0x19, 0xa208);
3712 alc_write_coef_idx(codec, 0x2e, 0xacf0);
3713 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003714 case 0x10ec0293:
3715 /* Set to TRS mode */
3716 alc_write_coef_idx(codec, 0x45, 0xc429);
3717 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3718 /* SET charge pump by verb */
3719 val = alc_read_coefex_idx(codec, 0x57, 0x05);
3720 alc_write_coefex_idx(codec, 0x57, 0x05, (val & ~(1<<15|1<<13)) | (1<<15|1<<13));
3721 /* SET EN_OSW to 0 */
3722 val = alc_read_coefex_idx(codec, 0x57, 0x03);
3723 alc_write_coefex_idx(codec, 0x57, 0x03, (val & ~(1<<10)) | 0x0);
3724 /* Combo JD gating without LINE1-VREFO */
3725 val = alc_read_coef_idx(codec, 0x1a);
3726 alc_write_coef_idx(codec, 0x1a, (val & ~(1<<3)) | 0x0);
3727 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3728 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003729 case 0x10ec0668:
3730 alc_write_coef_idx(codec, 0x11, 0x0001);
3731 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
3732 alc_write_coef_idx(codec, 0xb7, 0x802b);
3733 alc_write_coef_idx(codec, 0xb5, 0x1040);
3734 val = alc_read_coef_idx(codec, 0xc3);
3735 alc_write_coef_idx(codec, 0xc3, val | 1<<12);
3736 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
3737 break;
3738 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01003739 codec_dbg(codec, "Headset jack set to mic-in mode.\n");
David Henningsson73bdd592013-04-15 15:44:14 +02003740}
3741
3742static void alc_headset_mode_default(struct hda_codec *codec)
3743{
Kailang Yanga22aa262014-04-23 17:34:28 +08003744 int val;
3745
David Henningsson73bdd592013-04-15 15:44:14 +02003746 switch (codec->vendor_id) {
Kailang Yang9a22a8f52013-11-08 15:54:49 +08003747 case 0x10ec0255:
3748 alc_write_coef_idx(codec, 0x45, 0xc089);
3749 alc_write_coef_idx(codec, 0x45, 0xc489);
3750 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
3751 alc_write_coef_idx(codec, 0x49, 0x0049);
3752 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003753 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003754 case 0x10ec0283:
3755 alc_write_coef_idx(codec, 0x06, 0x2100);
3756 alc_write_coef_idx(codec, 0x32, 0x4ea3);
3757 break;
3758 case 0x10ec0292:
3759 alc_write_coef_idx(codec, 0x76, 0x000e);
3760 alc_write_coef_idx(codec, 0x6c, 0x2400);
3761 alc_write_coef_idx(codec, 0x6b, 0xc429);
3762 alc_write_coef_idx(codec, 0x18, 0x7308);
3763 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003764 case 0x10ec0293:
3765 /* Combo Jack auto detect */
3766 val = alc_read_coef_idx(codec, 0x4a);
3767 alc_write_coef_idx(codec, 0x4a, (val & 0xfff0) | 0x000e);
3768 /* Set to TRS type */
3769 alc_write_coef_idx(codec, 0x45, 0xC429);
3770 /* Combo JD gating without LINE1-VREFO */
3771 val = alc_read_coef_idx(codec, 0x1a);
3772 alc_write_coef_idx(codec, 0x1a, (val & ~(1<<3)) | 0x0);
3773 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003774 case 0x10ec0668:
3775 alc_write_coef_idx(codec, 0x11, 0x0041);
3776 alc_write_coef_idx(codec, 0x15, 0x0d40);
3777 alc_write_coef_idx(codec, 0xb7, 0x802b);
3778 break;
3779 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01003780 codec_dbg(codec, "Headset jack set to headphone (default) mode.\n");
David Henningsson73bdd592013-04-15 15:44:14 +02003781}
3782
3783/* Iphone type */
3784static void alc_headset_mode_ctia(struct hda_codec *codec)
3785{
Kailang Yanga22aa262014-04-23 17:34:28 +08003786 int val;
3787
David Henningsson73bdd592013-04-15 15:44:14 +02003788 switch (codec->vendor_id) {
Kailang Yang9a22a8f52013-11-08 15:54:49 +08003789 case 0x10ec0255:
3790 /* Set to CTIA type */
3791 alc_write_coef_idx(codec, 0x45, 0xd489);
3792 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3793 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
3794 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003795 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003796 case 0x10ec0283:
3797 alc_write_coef_idx(codec, 0x45, 0xd429);
3798 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3799 alc_write_coef_idx(codec, 0x32, 0x4ea3);
3800 break;
3801 case 0x10ec0292:
3802 alc_write_coef_idx(codec, 0x6b, 0xd429);
3803 alc_write_coef_idx(codec, 0x76, 0x0008);
3804 alc_write_coef_idx(codec, 0x18, 0x7388);
3805 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003806 case 0x10ec0293:
3807 /* Set to ctia type */
3808 alc_write_coef_idx(codec, 0x45, 0xd429);
3809 /* SET Line1 JD to 1 */
3810 val = alc_read_coef_idx(codec, 0x10);
3811 alc_write_coef_idx(codec, 0x10, (val & ~(7<<8)) | 7<<8);
3812 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003813 case 0x10ec0668:
David Henningssond59915d2013-12-02 18:06:20 +08003814 alc_write_coef_idx(codec, 0x11, 0x0001);
David Henningsson73bdd592013-04-15 15:44:14 +02003815 alc_write_coef_idx(codec, 0x15, 0x0d60);
3816 alc_write_coef_idx(codec, 0xc3, 0x0000);
3817 break;
3818 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01003819 codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n");
David Henningsson73bdd592013-04-15 15:44:14 +02003820}
3821
3822/* Nokia type */
3823static void alc_headset_mode_omtp(struct hda_codec *codec)
3824{
Kailang Yanga22aa262014-04-23 17:34:28 +08003825 int val;
3826
David Henningsson73bdd592013-04-15 15:44:14 +02003827 switch (codec->vendor_id) {
Kailang Yang9a22a8f52013-11-08 15:54:49 +08003828 case 0x10ec0255:
3829 /* Set to OMTP Type */
3830 alc_write_coef_idx(codec, 0x45, 0xe489);
3831 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3832 alc_write_coefex_idx(codec, 0x57, 0x03, 0x8ea6);
3833 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003834 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003835 case 0x10ec0283:
3836 alc_write_coef_idx(codec, 0x45, 0xe429);
3837 alc_write_coef_idx(codec, 0x1b, 0x0c2b);
3838 alc_write_coef_idx(codec, 0x32, 0x4ea3);
3839 break;
3840 case 0x10ec0292:
3841 alc_write_coef_idx(codec, 0x6b, 0xe429);
3842 alc_write_coef_idx(codec, 0x76, 0x0008);
3843 alc_write_coef_idx(codec, 0x18, 0x7388);
3844 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003845 case 0x10ec0293:
3846 /* Set to omtp type */
3847 alc_write_coef_idx(codec, 0x45, 0xe429);
3848 /* SET Line1 JD to 1 */
3849 val = alc_read_coef_idx(codec, 0x10);
3850 alc_write_coef_idx(codec, 0x10, (val & ~(7<<8)) | 7<<8);
3851 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003852 case 0x10ec0668:
David Henningssond59915d2013-12-02 18:06:20 +08003853 alc_write_coef_idx(codec, 0x11, 0x0001);
David Henningsson73bdd592013-04-15 15:44:14 +02003854 alc_write_coef_idx(codec, 0x15, 0x0d50);
3855 alc_write_coef_idx(codec, 0xc3, 0x0000);
3856 break;
3857 }
Takashi Iwai4e76a882014-02-25 12:21:03 +01003858 codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n");
David Henningsson73bdd592013-04-15 15:44:14 +02003859}
3860
3861static void alc_determine_headset_type(struct hda_codec *codec)
3862{
3863 int val;
3864 bool is_ctia = false;
3865 struct alc_spec *spec = codec->spec;
3866
3867 switch (codec->vendor_id) {
Kailang Yang9a22a8f52013-11-08 15:54:49 +08003868 case 0x10ec0255:
3869 /* combo jack auto switch control(Check type)*/
3870 alc_write_coef_idx(codec, 0x45, 0xd089);
3871 /* combo jack auto switch control(Vref conteol) */
3872 alc_write_coef_idx(codec, 0x49, 0x0149);
3873 msleep(300);
3874 val = alc_read_coef_idx(codec, 0x46);
3875 is_ctia = (val & 0x0070) == 0x0070;
3876 break;
Kailang Yang13fd08a2014-05-21 16:49:48 +08003877 case 0x10ec0233:
David Henningsson73bdd592013-04-15 15:44:14 +02003878 case 0x10ec0283:
3879 alc_write_coef_idx(codec, 0x45, 0xd029);
3880 msleep(300);
3881 val = alc_read_coef_idx(codec, 0x46);
3882 is_ctia = (val & 0x0070) == 0x0070;
3883 break;
3884 case 0x10ec0292:
3885 alc_write_coef_idx(codec, 0x6b, 0xd429);
3886 msleep(300);
3887 val = alc_read_coef_idx(codec, 0x6c);
3888 is_ctia = (val & 0x001c) == 0x001c;
3889 break;
Kailang Yanga22aa262014-04-23 17:34:28 +08003890 case 0x10ec0293:
3891 /* Combo Jack auto detect */
3892 val = alc_read_coef_idx(codec, 0x4a);
3893 alc_write_coef_idx(codec, 0x4a, (val & 0xfff0) | 0x0008);
3894 /* Set to ctia type */
3895 alc_write_coef_idx(codec, 0x45, 0xD429);
3896 msleep(300);
3897 val = alc_read_coef_idx(codec, 0x46);
3898 is_ctia = (val & 0x0070) == 0x0070;
3899 break;
David Henningsson73bdd592013-04-15 15:44:14 +02003900 case 0x10ec0668:
3901 alc_write_coef_idx(codec, 0x11, 0x0001);
3902 alc_write_coef_idx(codec, 0xb7, 0x802b);
3903 alc_write_coef_idx(codec, 0x15, 0x0d60);
3904 alc_write_coef_idx(codec, 0xc3, 0x0c00);
3905 msleep(300);
3906 val = alc_read_coef_idx(codec, 0xbe);
3907 is_ctia = (val & 0x1c02) == 0x1c02;
3908 break;
3909 }
3910
Takashi Iwai4e76a882014-02-25 12:21:03 +01003911 codec_dbg(codec, "Headset jack detected iPhone-style headset: %s\n",
David Henningsson73bdd592013-04-15 15:44:14 +02003912 is_ctia ? "yes" : "no");
3913 spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP;
3914}
3915
3916static void alc_update_headset_mode(struct hda_codec *codec)
3917{
3918 struct alc_spec *spec = codec->spec;
3919
3920 hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
3921 hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
3922
3923 int new_headset_mode;
3924
3925 if (!snd_hda_jack_detect(codec, hp_pin))
3926 new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED;
3927 else if (mux_pin == spec->headset_mic_pin)
3928 new_headset_mode = ALC_HEADSET_MODE_HEADSET;
3929 else if (mux_pin == spec->headphone_mic_pin)
3930 new_headset_mode = ALC_HEADSET_MODE_MIC;
3931 else
3932 new_headset_mode = ALC_HEADSET_MODE_HEADPHONE;
3933
David Henningsson5959a6b2013-11-12 11:10:57 +01003934 if (new_headset_mode == spec->current_headset_mode) {
3935 snd_hda_gen_update_outputs(codec);
David Henningsson73bdd592013-04-15 15:44:14 +02003936 return;
David Henningsson5959a6b2013-11-12 11:10:57 +01003937 }
David Henningsson73bdd592013-04-15 15:44:14 +02003938
3939 switch (new_headset_mode) {
3940 case ALC_HEADSET_MODE_UNPLUGGED:
3941 alc_headset_mode_unplugged(codec);
3942 spec->gen.hp_jack_present = false;
3943 break;
3944 case ALC_HEADSET_MODE_HEADSET:
3945 if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)
3946 alc_determine_headset_type(codec);
3947 if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)
3948 alc_headset_mode_ctia(codec);
3949 else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP)
3950 alc_headset_mode_omtp(codec);
3951 spec->gen.hp_jack_present = true;
3952 break;
3953 case ALC_HEADSET_MODE_MIC:
3954 alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin);
3955 spec->gen.hp_jack_present = false;
3956 break;
3957 case ALC_HEADSET_MODE_HEADPHONE:
3958 alc_headset_mode_default(codec);
3959 spec->gen.hp_jack_present = true;
3960 break;
3961 }
3962 if (new_headset_mode != ALC_HEADSET_MODE_MIC) {
3963 snd_hda_set_pin_ctl_cache(codec, hp_pin,
3964 AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
3965 if (spec->headphone_mic_pin)
3966 snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin,
3967 PIN_VREFHIZ);
3968 }
3969 spec->current_headset_mode = new_headset_mode;
3970
3971 snd_hda_gen_update_outputs(codec);
3972}
3973
3974static void alc_update_headset_mode_hook(struct hda_codec *codec,
Takashi Iwai7fe30712014-01-30 17:59:02 +01003975 struct snd_kcontrol *kcontrol,
3976 struct snd_ctl_elem_value *ucontrol)
David Henningsson73bdd592013-04-15 15:44:14 +02003977{
3978 alc_update_headset_mode(codec);
3979}
3980
3981static void alc_update_headset_jack_cb(struct hda_codec *codec, struct hda_jack_tbl *jack)
3982{
3983 struct alc_spec *spec = codec->spec;
David Henningsson5db4d342013-11-22 12:17:06 +01003984 spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
David Henningsson73bdd592013-04-15 15:44:14 +02003985 snd_hda_gen_hp_automute(codec, jack);
3986}
3987
3988static void alc_probe_headset_mode(struct hda_codec *codec)
3989{
3990 int i;
3991 struct alc_spec *spec = codec->spec;
3992 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
3993
3994 /* Find mic pins */
3995 for (i = 0; i < cfg->num_inputs; i++) {
3996 if (cfg->inputs[i].is_headset_mic && !spec->headset_mic_pin)
3997 spec->headset_mic_pin = cfg->inputs[i].pin;
3998 if (cfg->inputs[i].is_headphone_mic && !spec->headphone_mic_pin)
3999 spec->headphone_mic_pin = cfg->inputs[i].pin;
4000 }
4001
4002 spec->gen.cap_sync_hook = alc_update_headset_mode_hook;
4003 spec->gen.automute_hook = alc_update_headset_mode;
4004 spec->gen.hp_automute_hook = alc_update_headset_jack_cb;
4005}
4006
4007static void alc_fixup_headset_mode(struct hda_codec *codec,
4008 const struct hda_fixup *fix, int action)
4009{
4010 struct alc_spec *spec = codec->spec;
4011
4012 switch (action) {
4013 case HDA_FIXUP_ACT_PRE_PROBE:
4014 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC | HDA_PINCFG_HEADPHONE_MIC;
4015 break;
4016 case HDA_FIXUP_ACT_PROBE:
4017 alc_probe_headset_mode(codec);
4018 break;
4019 case HDA_FIXUP_ACT_INIT:
4020 spec->current_headset_mode = 0;
4021 alc_update_headset_mode(codec);
4022 break;
4023 }
4024}
4025
4026static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
4027 const struct hda_fixup *fix, int action)
4028{
4029 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4030 struct alc_spec *spec = codec->spec;
4031 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
4032 }
4033 else
4034 alc_fixup_headset_mode(codec, fix, action);
4035}
4036
Kailang Yang31278992014-03-03 15:27:22 +08004037static void alc255_set_default_jack_type(struct hda_codec *codec)
4038{
4039 /* Set to iphone type */
4040 alc_write_coef_idx(codec, 0x1b, 0x880b);
4041 alc_write_coef_idx(codec, 0x45, 0xd089);
4042 alc_write_coef_idx(codec, 0x1b, 0x080b);
4043 alc_write_coef_idx(codec, 0x46, 0x0004);
4044 alc_write_coef_idx(codec, 0x1b, 0x0c0b);
4045 msleep(30);
4046}
4047
Kailang Yang9a22a8f52013-11-08 15:54:49 +08004048static void alc_fixup_headset_mode_alc255(struct hda_codec *codec,
4049 const struct hda_fixup *fix, int action)
4050{
4051 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Kailang Yang31278992014-03-03 15:27:22 +08004052 alc255_set_default_jack_type(codec);
Kailang Yang9a22a8f52013-11-08 15:54:49 +08004053 }
4054 alc_fixup_headset_mode(codec, fix, action);
4055}
4056
Kailang Yang31278992014-03-03 15:27:22 +08004057static void alc_fixup_headset_mode_alc255_no_hp_mic(struct hda_codec *codec,
4058 const struct hda_fixup *fix, int action)
4059{
4060 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4061 struct alc_spec *spec = codec->spec;
4062 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
4063 alc255_set_default_jack_type(codec);
4064 }
4065 else
4066 alc_fixup_headset_mode(codec, fix, action);
4067}
4068
Hui Wang493a52a2014-01-14 14:07:36 +08004069static void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
4070 const struct hda_fixup *fix, int action)
4071{
4072 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4073 struct alc_spec *spec = codec->spec;
4074 spec->gen.auto_mute_via_amp = 1;
4075 }
4076}
4077
Takashi Iwai9b745ab2014-03-07 08:37:19 +01004078static void alc_no_shutup(struct hda_codec *codec)
4079{
4080}
4081
4082static void alc_fixup_no_shutup(struct hda_codec *codec,
4083 const struct hda_fixup *fix, int action)
4084{
4085 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4086 struct alc_spec *spec = codec->spec;
4087 spec->shutup = alc_no_shutup;
4088 }
4089}
4090
Gabriele Mazzotta5e6db662014-05-20 18:58:26 +02004091static void alc_fixup_disable_aamix(struct hda_codec *codec,
4092 const struct hda_fixup *fix, int action)
4093{
4094 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4095 struct alc_spec *spec = codec->spec;
4096 /* Disable AA-loopback as it causes white noise */
4097 spec->gen.mixer_nid = 0;
4098 }
4099}
4100
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02004101static unsigned int alc_power_filter_xps13(struct hda_codec *codec,
4102 hda_nid_t nid,
4103 unsigned int power_state)
4104{
4105 struct alc_spec *spec = codec->spec;
4106
4107 /* Avoid pop noises when headphones are plugged in */
4108 if (spec->gen.hp_jack_present)
Gabriele Mazzottade3da4f2014-08-08 19:34:41 +02004109 if (nid == codec->afg || nid == 0x02 || nid == 0x15)
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02004110 return AC_PWRST_D0;
4111 return power_state;
4112}
4113
4114static void alc_fixup_dell_xps13(struct hda_codec *codec,
4115 const struct hda_fixup *fix, int action)
4116{
4117 if (action == HDA_FIXUP_ACT_PROBE) {
4118 struct alc_spec *spec = codec->spec;
Gabriele Mazzottaf38663a2014-08-08 19:34:40 +02004119 struct hda_input_mux *imux = &spec->gen.input_mux;
4120 int i;
4121
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02004122 spec->shutup = alc_no_shutup;
4123 codec->power_filter = alc_power_filter_xps13;
Gabriele Mazzottaf38663a2014-08-08 19:34:40 +02004124
4125 /* Make the internal mic the default input source. */
4126 for (i = 0; i < imux->num_items; i++) {
4127 if (spec->gen.imux_pins[i] == 0x12) {
4128 spec->gen.cur_mux[0] = i;
4129 break;
4130 }
4131 }
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02004132 }
4133}
4134
David Henningsson73bdd592013-04-15 15:44:14 +02004135static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
4136 const struct hda_fixup *fix, int action)
4137{
4138 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4139 int val;
4140 alc_write_coef_idx(codec, 0xc4, 0x8000);
4141 val = alc_read_coef_idx(codec, 0xc2);
4142 alc_write_coef_idx(codec, 0xc2, val & 0xfe);
4143 snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
4144 }
4145 alc_fixup_headset_mode(codec, fix, action);
4146}
4147
Chih-Chung Changbde7bc62013-08-05 16:38:42 +08004148/* Returns the nid of the external mic input pin, or 0 if it cannot be found. */
4149static int find_ext_mic_pin(struct hda_codec *codec)
4150{
4151 struct alc_spec *spec = codec->spec;
4152 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
4153 hda_nid_t nid;
4154 unsigned int defcfg;
4155 int i;
4156
4157 for (i = 0; i < cfg->num_inputs; i++) {
4158 if (cfg->inputs[i].type != AUTO_PIN_MIC)
4159 continue;
4160 nid = cfg->inputs[i].pin;
4161 defcfg = snd_hda_codec_get_pincfg(codec, nid);
4162 if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
4163 continue;
4164 return nid;
4165 }
4166
4167 return 0;
4168}
4169
Dylan Reid08a978d2012-11-18 22:56:40 -08004170static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01004171 const struct hda_fixup *fix,
Dylan Reid08a978d2012-11-18 22:56:40 -08004172 int action)
4173{
4174 struct alc_spec *spec = codec->spec;
4175
Takashi Iwai0db75792013-01-23 13:57:20 +01004176 if (action == HDA_FIXUP_ACT_PROBE) {
Chih-Chung Changbde7bc62013-08-05 16:38:42 +08004177 int mic_pin = find_ext_mic_pin(codec);
4178 int hp_pin = spec->gen.autocfg.hp_pins[0];
4179
4180 if (snd_BUG_ON(!mic_pin || !hp_pin))
Takashi Iwai0db75792013-01-23 13:57:20 +01004181 return;
Chih-Chung Changbde7bc62013-08-05 16:38:42 +08004182 snd_hda_jack_set_gating_jack(codec, mic_pin, hp_pin);
Takashi Iwai0db75792013-01-23 13:57:20 +01004183 }
Dylan Reid08a978d2012-11-18 22:56:40 -08004184}
David Henningsson693b6132012-06-22 19:12:10 +02004185
David Henningsson3e0d6112013-04-22 14:30:14 +02004186static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec,
4187 const struct hda_fixup *fix,
4188 int action)
4189{
4190 struct alc_spec *spec = codec->spec;
4191 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
4192 int i;
4193
4194 /* The mic boosts on level 2 and 3 are too noisy
4195 on the internal mic input.
4196 Therefore limit the boost to 0 or 1. */
4197
4198 if (action != HDA_FIXUP_ACT_PROBE)
4199 return;
4200
4201 for (i = 0; i < cfg->num_inputs; i++) {
4202 hda_nid_t nid = cfg->inputs[i].pin;
4203 unsigned int defcfg;
4204 if (cfg->inputs[i].type != AUTO_PIN_MIC)
4205 continue;
4206 defcfg = snd_hda_codec_get_pincfg(codec, nid);
4207 if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
4208 continue;
4209
4210 snd_hda_override_amp_caps(codec, nid, HDA_INPUT,
4211 (0x00 << AC_AMPCAP_OFFSET_SHIFT) |
4212 (0x01 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4213 (0x2f << AC_AMPCAP_STEP_SIZE_SHIFT) |
4214 (0 << AC_AMPCAP_MUTE_SHIFT));
4215 }
4216}
4217
Kailang Yangcd217a62013-08-22 10:15:24 +02004218static void alc283_hp_automute_hook(struct hda_codec *codec,
4219 struct hda_jack_tbl *jack)
4220{
4221 struct alc_spec *spec = codec->spec;
4222 int vref;
4223
4224 msleep(200);
4225 snd_hda_gen_hp_automute(codec, jack);
4226
4227 vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
4228
4229 msleep(600);
4230 snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
4231 vref);
4232}
4233
Kailang Yangcd217a62013-08-22 10:15:24 +02004234static void alc283_fixup_chromebook(struct hda_codec *codec,
4235 const struct hda_fixup *fix, int action)
4236{
4237 struct alc_spec *spec = codec->spec;
4238 int val;
4239
4240 switch (action) {
4241 case HDA_FIXUP_ACT_PRE_PROBE:
Kailang Yang0202e992013-12-02 15:20:15 +08004242 snd_hda_override_wcaps(codec, 0x03, 0);
Takashi Iwaid2e92702013-10-30 07:50:53 +01004243 /* Disable AA-loopback as it causes white noise */
4244 spec->gen.mixer_nid = 0;
Kailang Yang38070212013-11-01 15:57:35 +08004245 break;
4246 case HDA_FIXUP_ACT_INIT:
Kailang Yangde9481c2014-04-07 16:41:52 +08004247 /* MIC2-VREF control */
4248 /* Set to manual mode */
4249 val = alc_read_coef_idx(codec, 0x06);
4250 alc_write_coef_idx(codec, 0x06, val & ~0x000c);
Kailang Yang0202e992013-12-02 15:20:15 +08004251 /* Enable Line1 input control by verb */
4252 val = alc_read_coef_idx(codec, 0x1a);
4253 alc_write_coef_idx(codec, 0x1a, val | (1 << 4));
4254 break;
4255 }
4256}
4257
4258static void alc283_fixup_sense_combo_jack(struct hda_codec *codec,
4259 const struct hda_fixup *fix, int action)
4260{
4261 struct alc_spec *spec = codec->spec;
4262 int val;
4263
4264 switch (action) {
4265 case HDA_FIXUP_ACT_PRE_PROBE:
Kailang Yangcd217a62013-08-22 10:15:24 +02004266 spec->gen.hp_automute_hook = alc283_hp_automute_hook;
4267 break;
4268 case HDA_FIXUP_ACT_INIT:
4269 /* MIC2-VREF control */
4270 /* Set to manual mode */
Kailang Yang068fd3a2013-09-27 14:02:28 +02004271 val = alc_read_coef_idx(codec, 0x06);
4272 alc_write_coef_idx(codec, 0x06, val & ~0x000c);
Kailang Yangcd217a62013-08-22 10:15:24 +02004273 break;
4274 }
4275}
4276
Takashi Iwai7bba2152013-09-06 15:45:38 +02004277/* mute tablet speaker pin (0x14) via dock plugging in addition */
4278static void asus_tx300_automute(struct hda_codec *codec)
4279{
4280 struct alc_spec *spec = codec->spec;
4281 snd_hda_gen_update_outputs(codec);
4282 if (snd_hda_jack_detect(codec, 0x1b))
4283 spec->gen.mute_bits |= (1ULL << 0x14);
4284}
4285
4286static void alc282_fixup_asus_tx300(struct hda_codec *codec,
4287 const struct hda_fixup *fix, int action)
4288{
4289 struct alc_spec *spec = codec->spec;
4290 /* TX300 needs to set up GPIO2 for the speaker amp */
4291 static const struct hda_verb gpio2_verbs[] = {
4292 { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 },
4293 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 },
4294 { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 },
4295 {}
4296 };
4297 static const struct hda_pintbl dock_pins[] = {
4298 { 0x1b, 0x21114000 }, /* dock speaker pin */
4299 {}
4300 };
4301 struct snd_kcontrol *kctl;
4302
4303 switch (action) {
4304 case HDA_FIXUP_ACT_PRE_PROBE:
4305 snd_hda_add_verbs(codec, gpio2_verbs);
4306 snd_hda_apply_pincfgs(codec, dock_pins);
4307 spec->gen.auto_mute_via_amp = 1;
4308 spec->gen.automute_hook = asus_tx300_automute;
4309 snd_hda_jack_detect_enable_callback(codec, 0x1b,
4310 HDA_GEN_HP_EVENT,
4311 snd_hda_gen_hp_automute);
4312 break;
4313 case HDA_FIXUP_ACT_BUILD:
4314 /* this is a bit tricky; give more sane names for the main
4315 * (tablet) speaker and the dock speaker, respectively
4316 */
4317 kctl = snd_hda_find_mixer_ctl(codec, "Speaker Playback Switch");
4318 if (kctl)
4319 strcpy(kctl->id.name, "Dock Speaker Playback Switch");
4320 kctl = snd_hda_find_mixer_ctl(codec, "Bass Speaker Playback Switch");
4321 if (kctl)
4322 strcpy(kctl->id.name, "Speaker Playback Switch");
4323 break;
4324 }
4325}
4326
David Henningsson338cae52013-10-07 10:39:59 +02004327static void alc290_fixup_mono_speakers(struct hda_codec *codec,
4328 const struct hda_fixup *fix, int action)
4329{
David Henningsson0f4881d2013-12-20 16:08:13 +01004330 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
4331 /* DAC node 0x03 is giving mono output. We therefore want to
4332 make sure 0x14 (front speaker) and 0x15 (headphones) use the
4333 stereo DAC, while leaving 0x17 (bass speaker) for node 0x03. */
4334 hda_nid_t conn1[2] = { 0x0c };
4335 snd_hda_override_conn_list(codec, 0x14, 1, conn1);
4336 snd_hda_override_conn_list(codec, 0x15, 1, conn1);
4337 }
David Henningsson338cae52013-10-07 10:39:59 +02004338}
4339
Takashi Iwaib317b032014-01-08 11:44:21 +01004340/* for hda_fixup_thinkpad_acpi() */
4341#include "thinkpad_helper.c"
David Henningssonb67ae3f2013-11-05 13:11:37 +01004342
Hui Wang00ef9942014-07-31 11:52:38 +08004343/* for dell wmi mic mute led */
4344#include "dell_wmi_helper.c"
4345
Takashi Iwai1d045db2011-07-07 18:23:21 +02004346enum {
4347 ALC269_FIXUP_SONY_VAIO,
4348 ALC275_FIXUP_SONY_VAIO_GPIO2,
4349 ALC269_FIXUP_DELL_M101Z,
4350 ALC269_FIXUP_SKU_IGNORE,
4351 ALC269_FIXUP_ASUS_G73JW,
4352 ALC269_FIXUP_LENOVO_EAPD,
4353 ALC275_FIXUP_SONY_HWEQ,
Takashi Iwaie9bd7d52014-05-21 11:06:49 +02004354 ALC275_FIXUP_SONY_DISABLE_AAMIX,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004355 ALC271_FIXUP_DMIC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004356 ALC269_FIXUP_PCM_44K,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004357 ALC269_FIXUP_STEREO_DMIC,
David Henningsson7c478f02013-10-11 10:18:46 +02004358 ALC269_FIXUP_HEADSET_MIC,
Takashi Iwai24519912011-08-16 15:08:49 +02004359 ALC269_FIXUP_QUANTA_MUTE,
4360 ALC269_FIXUP_LIFEBOOK,
David Henningsson2041d562014-06-13 11:15:44 +02004361 ALC269_FIXUP_LIFEBOOK_EXTMIC,
Takashi Iwaia4297b52011-08-23 18:40:12 +02004362 ALC269_FIXUP_AMIC,
4363 ALC269_FIXUP_DMIC,
4364 ALC269VB_FIXUP_AMIC,
4365 ALC269VB_FIXUP_DMIC,
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004366 ALC269_FIXUP_HP_MUTE_LED,
David Henningssond06ac142013-02-18 11:41:55 +01004367 ALC269_FIXUP_HP_MUTE_LED_MIC1,
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004368 ALC269_FIXUP_HP_MUTE_LED_MIC2,
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01004369 ALC269_FIXUP_HP_GPIO_LED,
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08004370 ALC269_FIXUP_HP_GPIO_MIC1_LED,
4371 ALC269_FIXUP_HP_LINE1_MIC1_LED,
David Henningsson693b6132012-06-22 19:12:10 +02004372 ALC269_FIXUP_INV_DMIC,
David Henningsson108cc102012-07-20 10:37:25 +02004373 ALC269_FIXUP_LENOVO_DOCK,
Takashi Iwai9b745ab2014-03-07 08:37:19 +01004374 ALC269_FIXUP_NO_SHUTUP,
David Henningsson88cfcf82013-10-11 10:18:45 +02004375 ALC286_FIXUP_SONY_MIC_NO_PRESENCE,
David Henningsson108cc102012-07-20 10:37:25 +02004376 ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT,
David Henningsson73bdd592013-04-15 15:44:14 +02004377 ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
4378 ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
David Henningsson338cae52013-10-07 10:39:59 +02004379 ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
David Henningsson73bdd592013-04-15 15:44:14 +02004380 ALC269_FIXUP_HEADSET_MODE,
4381 ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC,
David Henningssond240d1d2013-04-15 12:50:02 +02004382 ALC269_FIXUP_ASUS_X101_FUNC,
4383 ALC269_FIXUP_ASUS_X101_VERB,
4384 ALC269_FIXUP_ASUS_X101,
Dylan Reid08a978d2012-11-18 22:56:40 -08004385 ALC271_FIXUP_AMIC_MIC2,
4386 ALC271_FIXUP_HP_GATE_MIC_JACK,
Oleksij Rempelb1e89722013-12-04 20:50:53 +01004387 ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572,
Dylan Reid42397002013-04-05 14:58:22 -07004388 ALC269_FIXUP_ACER_AC700,
David Henningsson3e0d6112013-04-22 14:30:14 +02004389 ALC269_FIXUP_LIMIT_INT_MIC_BOOST,
Oleksij Rempel2cede302013-11-27 17:12:03 +01004390 ALC269VB_FIXUP_ASUS_ZENBOOK,
Takashi Iwai23870832013-11-29 14:13:12 +01004391 ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A,
David Henningsson8e35cd42013-11-06 11:20:01 +01004392 ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED,
Anisse Astier02b504d2013-06-03 11:53:10 +02004393 ALC269VB_FIXUP_ORDISSIMO_EVE2,
Kailang Yangcd217a62013-08-22 10:15:24 +02004394 ALC283_FIXUP_CHROME_BOOK,
Kailang Yang0202e992013-12-02 15:20:15 +08004395 ALC283_FIXUP_SENSE_COMBO_JACK,
Takashi Iwai7bba2152013-09-06 15:45:38 +02004396 ALC282_FIXUP_ASUS_TX300,
Kailang Yang1bb3e062013-09-27 13:10:25 +02004397 ALC283_FIXUP_INT_MIC,
David Henningsson338cae52013-10-07 10:39:59 +02004398 ALC290_FIXUP_MONO_SPEAKERS,
David Henningsson0f4881d2013-12-20 16:08:13 +01004399 ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
4400 ALC290_FIXUP_SUBWOOFER,
4401 ALC290_FIXUP_SUBWOOFER_HSJACK,
David Henningssonb67ae3f2013-11-05 13:11:37 +01004402 ALC269_FIXUP_THINKPAD_ACPI,
Kailang Yang9a22a8f52013-11-08 15:54:49 +08004403 ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
Kailang Yang31278992014-03-03 15:27:22 +08004404 ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
Kailang Yang9a22a8f52013-11-08 15:54:49 +08004405 ALC255_FIXUP_HEADSET_MODE,
Kailang Yang31278992014-03-03 15:27:22 +08004406 ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
Kailang Yanga22aa262014-04-23 17:34:28 +08004407 ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
Takashi Iwai1c37c222014-05-06 17:34:42 +02004408 ALC292_FIXUP_TPT440_DOCK,
Daniel Drake9dc12862014-07-22 10:58:29 +01004409 ALC283_FIXUP_BXBT2807_MIC,
Hui Wang00ef9942014-07-31 11:52:38 +08004410 ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
Takashi Iwai1a22e772014-08-27 08:19:05 +02004411 ALC282_FIXUP_ASPIRE_V5_PINS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004412};
4413
Takashi Iwai1727a772013-01-10 09:52:52 +01004414static const struct hda_fixup alc269_fixups[] = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004415 [ALC269_FIXUP_SONY_VAIO] = {
Takashi Iwaifd108212013-01-10 10:18:14 +01004416 .type = HDA_FIXUP_PINCTLS,
4417 .v.pins = (const struct hda_pintbl[]) {
4418 {0x19, PIN_VREFGRD},
Takashi Iwai1d045db2011-07-07 18:23:21 +02004419 {}
4420 }
4421 },
4422 [ALC275_FIXUP_SONY_VAIO_GPIO2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004423 .type = HDA_FIXUP_VERBS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004424 .v.verbs = (const struct hda_verb[]) {
4425 {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
4426 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
4427 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
4428 { }
4429 },
4430 .chained = true,
4431 .chain_id = ALC269_FIXUP_SONY_VAIO
4432 },
4433 [ALC269_FIXUP_DELL_M101Z] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004434 .type = HDA_FIXUP_VERBS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004435 .v.verbs = (const struct hda_verb[]) {
4436 /* Enables internal speaker */
4437 {0x20, AC_VERB_SET_COEF_INDEX, 13},
4438 {0x20, AC_VERB_SET_PROC_COEF, 0x4040},
4439 {}
4440 }
4441 },
4442 [ALC269_FIXUP_SKU_IGNORE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004443 .type = HDA_FIXUP_FUNC,
Takashi Iwai23d30f22012-05-07 17:17:32 +02004444 .v.func = alc_fixup_sku_ignore,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004445 },
4446 [ALC269_FIXUP_ASUS_G73JW] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004447 .type = HDA_FIXUP_PINS,
4448 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02004449 { 0x17, 0x99130111 }, /* subwoofer */
4450 { }
4451 }
4452 },
4453 [ALC269_FIXUP_LENOVO_EAPD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004454 .type = HDA_FIXUP_VERBS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004455 .v.verbs = (const struct hda_verb[]) {
4456 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
4457 {}
4458 }
4459 },
4460 [ALC275_FIXUP_SONY_HWEQ] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004461 .type = HDA_FIXUP_FUNC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004462 .v.func = alc269_fixup_hweq,
4463 .chained = true,
4464 .chain_id = ALC275_FIXUP_SONY_VAIO_GPIO2
4465 },
Takashi Iwaie9bd7d52014-05-21 11:06:49 +02004466 [ALC275_FIXUP_SONY_DISABLE_AAMIX] = {
4467 .type = HDA_FIXUP_FUNC,
4468 .v.func = alc_fixup_disable_aamix,
4469 .chained = true,
4470 .chain_id = ALC269_FIXUP_SONY_VAIO
4471 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02004472 [ALC271_FIXUP_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004473 .type = HDA_FIXUP_FUNC,
Takashi Iwai1d045db2011-07-07 18:23:21 +02004474 .v.func = alc271_fixup_dmic,
4475 },
Takashi Iwai017f2a12011-07-09 14:42:25 +02004476 [ALC269_FIXUP_PCM_44K] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004477 .type = HDA_FIXUP_FUNC,
Takashi Iwai017f2a12011-07-09 14:42:25 +02004478 .v.func = alc269_fixup_pcm_44k,
David Henningsson012e7eb2012-08-08 08:43:37 +02004479 .chained = true,
4480 .chain_id = ALC269_FIXUP_QUANTA_MUTE
Takashi Iwai017f2a12011-07-09 14:42:25 +02004481 },
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004482 [ALC269_FIXUP_STEREO_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004483 .type = HDA_FIXUP_FUNC,
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02004484 .v.func = alc269_fixup_stereo_dmic,
4485 },
David Henningsson7c478f02013-10-11 10:18:46 +02004486 [ALC269_FIXUP_HEADSET_MIC] = {
4487 .type = HDA_FIXUP_FUNC,
4488 .v.func = alc269_fixup_headset_mic,
4489 },
Takashi Iwai24519912011-08-16 15:08:49 +02004490 [ALC269_FIXUP_QUANTA_MUTE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004491 .type = HDA_FIXUP_FUNC,
Takashi Iwai24519912011-08-16 15:08:49 +02004492 .v.func = alc269_fixup_quanta_mute,
4493 },
4494 [ALC269_FIXUP_LIFEBOOK] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004495 .type = HDA_FIXUP_PINS,
4496 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai24519912011-08-16 15:08:49 +02004497 { 0x1a, 0x2101103f }, /* dock line-out */
4498 { 0x1b, 0x23a11040 }, /* dock mic-in */
4499 { }
4500 },
4501 .chained = true,
4502 .chain_id = ALC269_FIXUP_QUANTA_MUTE
4503 },
David Henningsson2041d562014-06-13 11:15:44 +02004504 [ALC269_FIXUP_LIFEBOOK_EXTMIC] = {
4505 .type = HDA_FIXUP_PINS,
4506 .v.pins = (const struct hda_pintbl[]) {
4507 { 0x19, 0x01a1903c }, /* headset mic, with jack detect */
4508 { }
4509 },
4510 },
Takashi Iwaia4297b52011-08-23 18:40:12 +02004511 [ALC269_FIXUP_AMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004512 .type = HDA_FIXUP_PINS,
4513 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaia4297b52011-08-23 18:40:12 +02004514 { 0x14, 0x99130110 }, /* speaker */
4515 { 0x15, 0x0121401f }, /* HP out */
4516 { 0x18, 0x01a19c20 }, /* mic */
4517 { 0x19, 0x99a3092f }, /* int-mic */
4518 { }
4519 },
4520 },
4521 [ALC269_FIXUP_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004522 .type = HDA_FIXUP_PINS,
4523 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaia4297b52011-08-23 18:40:12 +02004524 { 0x12, 0x99a3092f }, /* int-mic */
4525 { 0x14, 0x99130110 }, /* speaker */
4526 { 0x15, 0x0121401f }, /* HP out */
4527 { 0x18, 0x01a19c20 }, /* mic */
4528 { }
4529 },
4530 },
4531 [ALC269VB_FIXUP_AMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004532 .type = HDA_FIXUP_PINS,
4533 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaia4297b52011-08-23 18:40:12 +02004534 { 0x14, 0x99130110 }, /* speaker */
4535 { 0x18, 0x01a19c20 }, /* mic */
4536 { 0x19, 0x99a3092f }, /* int-mic */
4537 { 0x21, 0x0121401f }, /* HP out */
4538 { }
4539 },
4540 },
David Henningsson2267ea92012-01-03 08:45:56 +01004541 [ALC269VB_FIXUP_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004542 .type = HDA_FIXUP_PINS,
4543 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaia4297b52011-08-23 18:40:12 +02004544 { 0x12, 0x99a3092f }, /* int-mic */
4545 { 0x14, 0x99130110 }, /* speaker */
4546 { 0x18, 0x01a19c20 }, /* mic */
4547 { 0x21, 0x0121401f }, /* HP out */
4548 { }
4549 },
4550 },
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004551 [ALC269_FIXUP_HP_MUTE_LED] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004552 .type = HDA_FIXUP_FUNC,
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004553 .v.func = alc269_fixup_hp_mute_led,
David Henningsson6d3cd5d2013-01-07 12:03:47 +01004554 },
David Henningssond06ac142013-02-18 11:41:55 +01004555 [ALC269_FIXUP_HP_MUTE_LED_MIC1] = {
4556 .type = HDA_FIXUP_FUNC,
4557 .v.func = alc269_fixup_hp_mute_led_mic1,
4558 },
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004559 [ALC269_FIXUP_HP_MUTE_LED_MIC2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004560 .type = HDA_FIXUP_FUNC,
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004561 .v.func = alc269_fixup_hp_mute_led_mic2,
Takashi Iwai420b0fe2012-03-12 12:35:27 +01004562 },
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01004563 [ALC269_FIXUP_HP_GPIO_LED] = {
4564 .type = HDA_FIXUP_FUNC,
4565 .v.func = alc269_fixup_hp_gpio_led,
4566 },
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08004567 [ALC269_FIXUP_HP_GPIO_MIC1_LED] = {
4568 .type = HDA_FIXUP_FUNC,
4569 .v.func = alc269_fixup_hp_gpio_mic1_led,
4570 },
4571 [ALC269_FIXUP_HP_LINE1_MIC1_LED] = {
4572 .type = HDA_FIXUP_FUNC,
4573 .v.func = alc269_fixup_hp_line1_mic1_led,
4574 },
David Henningsson693b6132012-06-22 19:12:10 +02004575 [ALC269_FIXUP_INV_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004576 .type = HDA_FIXUP_FUNC,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02004577 .v.func = alc_fixup_inv_dmic_0x12,
David Henningsson693b6132012-06-22 19:12:10 +02004578 },
Takashi Iwai9b745ab2014-03-07 08:37:19 +01004579 [ALC269_FIXUP_NO_SHUTUP] = {
4580 .type = HDA_FIXUP_FUNC,
4581 .v.func = alc_fixup_no_shutup,
4582 },
David Henningsson108cc102012-07-20 10:37:25 +02004583 [ALC269_FIXUP_LENOVO_DOCK] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004584 .type = HDA_FIXUP_PINS,
4585 .v.pins = (const struct hda_pintbl[]) {
David Henningsson108cc102012-07-20 10:37:25 +02004586 { 0x19, 0x23a11040 }, /* dock mic */
4587 { 0x1b, 0x2121103f }, /* dock headphone */
4588 { }
4589 },
4590 .chained = true,
4591 .chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT
4592 },
4593 [ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004594 .type = HDA_FIXUP_FUNC,
David Henningsson108cc102012-07-20 10:37:25 +02004595 .v.func = alc269_fixup_pincfg_no_hp_to_lineout,
David Henningsson52129002013-11-19 10:25:53 +01004596 .chained = true,
4597 .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
David Henningsson108cc102012-07-20 10:37:25 +02004598 },
David Henningsson73bdd592013-04-15 15:44:14 +02004599 [ALC269_FIXUP_DELL1_MIC_NO_PRESENCE] = {
4600 .type = HDA_FIXUP_PINS,
4601 .v.pins = (const struct hda_pintbl[]) {
4602 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4603 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
4604 { }
4605 },
4606 .chained = true,
4607 .chain_id = ALC269_FIXUP_HEADSET_MODE
4608 },
4609 [ALC269_FIXUP_DELL2_MIC_NO_PRESENCE] = {
4610 .type = HDA_FIXUP_PINS,
4611 .v.pins = (const struct hda_pintbl[]) {
4612 { 0x16, 0x21014020 }, /* dock line out */
4613 { 0x19, 0x21a19030 }, /* dock mic */
4614 { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4615 { }
4616 },
4617 .chained = true,
4618 .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
4619 },
David Henningsson338cae52013-10-07 10:39:59 +02004620 [ALC269_FIXUP_DELL3_MIC_NO_PRESENCE] = {
4621 .type = HDA_FIXUP_PINS,
4622 .v.pins = (const struct hda_pintbl[]) {
4623 { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4624 { }
4625 },
4626 .chained = true,
4627 .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
4628 },
David Henningsson73bdd592013-04-15 15:44:14 +02004629 [ALC269_FIXUP_HEADSET_MODE] = {
4630 .type = HDA_FIXUP_FUNC,
4631 .v.func = alc_fixup_headset_mode,
4632 },
4633 [ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
4634 .type = HDA_FIXUP_FUNC,
4635 .v.func = alc_fixup_headset_mode_no_hp_mic,
4636 },
David Henningsson88cfcf82013-10-11 10:18:45 +02004637 [ALC286_FIXUP_SONY_MIC_NO_PRESENCE] = {
4638 .type = HDA_FIXUP_PINS,
4639 .v.pins = (const struct hda_pintbl[]) {
4640 { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4641 { }
4642 },
David Henningssonfbc78ad2013-10-11 13:46:04 +02004643 .chained = true,
4644 .chain_id = ALC269_FIXUP_HEADSET_MIC
David Henningsson88cfcf82013-10-11 10:18:45 +02004645 },
David Henningssond240d1d2013-04-15 12:50:02 +02004646 [ALC269_FIXUP_ASUS_X101_FUNC] = {
4647 .type = HDA_FIXUP_FUNC,
4648 .v.func = alc269_fixup_x101_headset_mic,
4649 },
4650 [ALC269_FIXUP_ASUS_X101_VERB] = {
4651 .type = HDA_FIXUP_VERBS,
4652 .v.verbs = (const struct hda_verb[]) {
4653 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
4654 {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
4655 {0x20, AC_VERB_SET_PROC_COEF, 0x0310},
4656 { }
4657 },
4658 .chained = true,
4659 .chain_id = ALC269_FIXUP_ASUS_X101_FUNC
4660 },
4661 [ALC269_FIXUP_ASUS_X101] = {
4662 .type = HDA_FIXUP_PINS,
4663 .v.pins = (const struct hda_pintbl[]) {
4664 { 0x18, 0x04a1182c }, /* Headset mic */
4665 { }
4666 },
4667 .chained = true,
4668 .chain_id = ALC269_FIXUP_ASUS_X101_VERB
4669 },
Dylan Reid08a978d2012-11-18 22:56:40 -08004670 [ALC271_FIXUP_AMIC_MIC2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004671 .type = HDA_FIXUP_PINS,
4672 .v.pins = (const struct hda_pintbl[]) {
Dylan Reid08a978d2012-11-18 22:56:40 -08004673 { 0x14, 0x99130110 }, /* speaker */
4674 { 0x19, 0x01a19c20 }, /* mic */
4675 { 0x1b, 0x99a7012f }, /* int-mic */
4676 { 0x21, 0x0121401f }, /* HP out */
4677 { }
4678 },
4679 },
4680 [ALC271_FIXUP_HP_GATE_MIC_JACK] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01004681 .type = HDA_FIXUP_FUNC,
Dylan Reid08a978d2012-11-18 22:56:40 -08004682 .v.func = alc271_hp_gate_mic_jack,
4683 .chained = true,
4684 .chain_id = ALC271_FIXUP_AMIC_MIC2,
4685 },
Oleksij Rempelb1e89722013-12-04 20:50:53 +01004686 [ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572] = {
4687 .type = HDA_FIXUP_FUNC,
4688 .v.func = alc269_fixup_limit_int_mic_boost,
4689 .chained = true,
4690 .chain_id = ALC271_FIXUP_HP_GATE_MIC_JACK,
4691 },
Dylan Reid42397002013-04-05 14:58:22 -07004692 [ALC269_FIXUP_ACER_AC700] = {
4693 .type = HDA_FIXUP_PINS,
4694 .v.pins = (const struct hda_pintbl[]) {
4695 { 0x12, 0x99a3092f }, /* int-mic */
4696 { 0x14, 0x99130110 }, /* speaker */
4697 { 0x18, 0x03a11c20 }, /* mic */
4698 { 0x1e, 0x0346101e }, /* SPDIF1 */
4699 { 0x21, 0x0321101f }, /* HP out */
4700 { }
4701 },
4702 .chained = true,
4703 .chain_id = ALC271_FIXUP_DMIC,
4704 },
David Henningsson3e0d6112013-04-22 14:30:14 +02004705 [ALC269_FIXUP_LIMIT_INT_MIC_BOOST] = {
4706 .type = HDA_FIXUP_FUNC,
4707 .v.func = alc269_fixup_limit_int_mic_boost,
David Henningsson27937692013-11-18 11:51:47 +01004708 .chained = true,
4709 .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
David Henningsson3e0d6112013-04-22 14:30:14 +02004710 },
Oleksij Rempel2cede302013-11-27 17:12:03 +01004711 [ALC269VB_FIXUP_ASUS_ZENBOOK] = {
4712 .type = HDA_FIXUP_FUNC,
4713 .v.func = alc269_fixup_limit_int_mic_boost,
4714 .chained = true,
4715 .chain_id = ALC269VB_FIXUP_DMIC,
4716 },
Takashi Iwai23870832013-11-29 14:13:12 +01004717 [ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A] = {
4718 .type = HDA_FIXUP_VERBS,
4719 .v.verbs = (const struct hda_verb[]) {
4720 /* class-D output amp +5dB */
4721 { 0x20, AC_VERB_SET_COEF_INDEX, 0x12 },
4722 { 0x20, AC_VERB_SET_PROC_COEF, 0x2800 },
4723 {}
4724 },
4725 .chained = true,
4726 .chain_id = ALC269VB_FIXUP_ASUS_ZENBOOK,
4727 },
David Henningsson8e35cd42013-11-06 11:20:01 +01004728 [ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED] = {
4729 .type = HDA_FIXUP_FUNC,
4730 .v.func = alc269_fixup_limit_int_mic_boost,
4731 .chained = true,
4732 .chain_id = ALC269_FIXUP_HP_MUTE_LED_MIC1,
4733 },
Anisse Astier02b504d2013-06-03 11:53:10 +02004734 [ALC269VB_FIXUP_ORDISSIMO_EVE2] = {
4735 .type = HDA_FIXUP_PINS,
4736 .v.pins = (const struct hda_pintbl[]) {
4737 { 0x12, 0x99a3092f }, /* int-mic */
4738 { 0x18, 0x03a11d20 }, /* mic */
4739 { 0x19, 0x411111f0 }, /* Unused bogus pin */
4740 { }
4741 },
4742 },
Kailang Yangcd217a62013-08-22 10:15:24 +02004743 [ALC283_FIXUP_CHROME_BOOK] = {
4744 .type = HDA_FIXUP_FUNC,
4745 .v.func = alc283_fixup_chromebook,
4746 },
Kailang Yang0202e992013-12-02 15:20:15 +08004747 [ALC283_FIXUP_SENSE_COMBO_JACK] = {
4748 .type = HDA_FIXUP_FUNC,
4749 .v.func = alc283_fixup_sense_combo_jack,
4750 .chained = true,
4751 .chain_id = ALC283_FIXUP_CHROME_BOOK,
4752 },
Takashi Iwai7bba2152013-09-06 15:45:38 +02004753 [ALC282_FIXUP_ASUS_TX300] = {
4754 .type = HDA_FIXUP_FUNC,
4755 .v.func = alc282_fixup_asus_tx300,
4756 },
Kailang Yang1bb3e062013-09-27 13:10:25 +02004757 [ALC283_FIXUP_INT_MIC] = {
4758 .type = HDA_FIXUP_VERBS,
4759 .v.verbs = (const struct hda_verb[]) {
4760 {0x20, AC_VERB_SET_COEF_INDEX, 0x1a},
4761 {0x20, AC_VERB_SET_PROC_COEF, 0x0011},
4762 { }
4763 },
4764 .chained = true,
4765 .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
4766 },
David Henningsson0f4881d2013-12-20 16:08:13 +01004767 [ALC290_FIXUP_SUBWOOFER_HSJACK] = {
4768 .type = HDA_FIXUP_PINS,
4769 .v.pins = (const struct hda_pintbl[]) {
4770 { 0x17, 0x90170112 }, /* subwoofer */
4771 { }
4772 },
4773 .chained = true,
4774 .chain_id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK,
4775 },
4776 [ALC290_FIXUP_SUBWOOFER] = {
4777 .type = HDA_FIXUP_PINS,
4778 .v.pins = (const struct hda_pintbl[]) {
4779 { 0x17, 0x90170112 }, /* subwoofer */
4780 { }
4781 },
4782 .chained = true,
4783 .chain_id = ALC290_FIXUP_MONO_SPEAKERS,
4784 },
David Henningsson338cae52013-10-07 10:39:59 +02004785 [ALC290_FIXUP_MONO_SPEAKERS] = {
4786 .type = HDA_FIXUP_FUNC,
4787 .v.func = alc290_fixup_mono_speakers,
David Henningsson0f4881d2013-12-20 16:08:13 +01004788 },
4789 [ALC290_FIXUP_MONO_SPEAKERS_HSJACK] = {
4790 .type = HDA_FIXUP_FUNC,
4791 .v.func = alc290_fixup_mono_speakers,
David Henningsson338cae52013-10-07 10:39:59 +02004792 .chained = true,
4793 .chain_id = ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
4794 },
David Henningssonb67ae3f2013-11-05 13:11:37 +01004795 [ALC269_FIXUP_THINKPAD_ACPI] = {
4796 .type = HDA_FIXUP_FUNC,
Takashi Iwaib317b032014-01-08 11:44:21 +01004797 .v.func = hda_fixup_thinkpad_acpi,
David Henningssonb67ae3f2013-11-05 13:11:37 +01004798 },
Kailang Yang9a22a8f52013-11-08 15:54:49 +08004799 [ALC255_FIXUP_DELL1_MIC_NO_PRESENCE] = {
4800 .type = HDA_FIXUP_PINS,
4801 .v.pins = (const struct hda_pintbl[]) {
4802 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4803 { 0x1a, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
4804 { }
4805 },
4806 .chained = true,
4807 .chain_id = ALC255_FIXUP_HEADSET_MODE
4808 },
Kailang Yang31278992014-03-03 15:27:22 +08004809 [ALC255_FIXUP_DELL2_MIC_NO_PRESENCE] = {
4810 .type = HDA_FIXUP_PINS,
4811 .v.pins = (const struct hda_pintbl[]) {
4812 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4813 { }
4814 },
4815 .chained = true,
4816 .chain_id = ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC
4817 },
Kailang Yang9a22a8f52013-11-08 15:54:49 +08004818 [ALC255_FIXUP_HEADSET_MODE] = {
4819 .type = HDA_FIXUP_FUNC,
4820 .v.func = alc_fixup_headset_mode_alc255,
4821 },
Kailang Yang31278992014-03-03 15:27:22 +08004822 [ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC] = {
4823 .type = HDA_FIXUP_FUNC,
4824 .v.func = alc_fixup_headset_mode_alc255_no_hp_mic,
4825 },
Kailang Yanga22aa262014-04-23 17:34:28 +08004826 [ALC293_FIXUP_DELL1_MIC_NO_PRESENCE] = {
4827 .type = HDA_FIXUP_PINS,
4828 .v.pins = (const struct hda_pintbl[]) {
4829 { 0x18, 0x01a1913d }, /* use as headphone mic, without its own jack detect */
4830 { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
4831 { }
4832 },
4833 .chained = true,
4834 .chain_id = ALC269_FIXUP_HEADSET_MODE
4835 },
Takashi Iwai1c37c222014-05-06 17:34:42 +02004836 [ALC292_FIXUP_TPT440_DOCK] = {
4837 .type = HDA_FIXUP_PINS,
4838 .v.pins = (const struct hda_pintbl[]) {
4839 { 0x16, 0x21211010 }, /* dock headphone */
4840 { 0x19, 0x21a11010 }, /* dock mic */
4841 { }
4842 },
4843 .chained = true,
4844 .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
4845 },
Daniel Drake9dc12862014-07-22 10:58:29 +01004846 [ALC283_FIXUP_BXBT2807_MIC] = {
4847 .type = HDA_FIXUP_PINS,
4848 .v.pins = (const struct hda_pintbl[]) {
4849 { 0x19, 0x04a110f0 },
4850 { },
4851 },
4852 },
Hui Wang00ef9942014-07-31 11:52:38 +08004853 [ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = {
4854 .type = HDA_FIXUP_FUNC,
4855 .v.func = alc_fixup_dell_wmi,
4856 .chained_before = true,
4857 .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
4858 },
Takashi Iwai1a22e772014-08-27 08:19:05 +02004859 [ALC282_FIXUP_ASPIRE_V5_PINS] = {
4860 .type = HDA_FIXUP_PINS,
4861 .v.pins = (const struct hda_pintbl[]) {
4862 { 0x12, 0x90a60130 },
4863 { 0x14, 0x90170110 },
4864 { 0x17, 0x40000008 },
4865 { 0x18, 0x411111f0 },
4866 { 0x19, 0x411111f0 },
4867 { 0x1a, 0x411111f0 },
4868 { 0x1b, 0x411111f0 },
4869 { 0x1d, 0x40f89b2d },
4870 { 0x1e, 0x411111f0 },
4871 { 0x21, 0x0321101f },
4872 { },
4873 },
4874 },
Hui Wang00ef9942014-07-31 11:52:38 +08004875
Takashi Iwai1d045db2011-07-07 18:23:21 +02004876};
4877
4878static const struct snd_pci_quirk alc269_fixup_tbl[] = {
Marius Knausta6b92b62014-03-03 01:48:58 +01004879 SND_PCI_QUIRK(0x1025, 0x0283, "Acer TravelMate 8371", ALC269_FIXUP_INV_DMIC),
David Henningsson693b6132012-06-22 19:12:10 +02004880 SND_PCI_QUIRK(0x1025, 0x029b, "Acer 1810TZ", ALC269_FIXUP_INV_DMIC),
4881 SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
David Henningssonaaedfb42013-08-16 14:09:02 +02004882 SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
4883 SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
4884 SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
Oleksij Rempelb1e89722013-12-04 20:50:53 +01004885 SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
Takashi Iwai1a22e772014-08-27 08:19:05 +02004886 SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
David Henningssonaaedfb42013-08-16 14:09:02 +02004887 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
David Henningsson73bdd592013-04-15 15:44:14 +02004888 SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4889 SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4890 SND_PCI_QUIRK(0x1028, 0x05c4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4891 SND_PCI_QUIRK(0x1028, 0x05c5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4892 SND_PCI_QUIRK(0x1028, 0x05c6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4893 SND_PCI_QUIRK(0x1028, 0x05c7, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4894 SND_PCI_QUIRK(0x1028, 0x05c8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4895 SND_PCI_QUIRK(0x1028, 0x05c9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4896 SND_PCI_QUIRK(0x1028, 0x05ca, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4897 SND_PCI_QUIRK(0x1028, 0x05cb, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
Kailang Yang05843c02013-07-01 11:27:16 +02004898 SND_PCI_QUIRK(0x1028, 0x05cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4899 SND_PCI_QUIRK(0x1028, 0x05cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
David Henningsson0f4881d2013-12-20 16:08:13 +01004900 SND_PCI_QUIRK(0x1028, 0x05da, "Dell Vostro 5460", ALC290_FIXUP_SUBWOOFER),
David Henningsson436c4a02013-05-15 13:56:00 +02004901 SND_PCI_QUIRK(0x1028, 0x05de, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
David Henningssond81bf8c2013-06-11 11:06:48 +02004902 SND_PCI_QUIRK(0x1028, 0x05e0, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
David Henningsson73bdd592013-04-15 15:44:14 +02004903 SND_PCI_QUIRK(0x1028, 0x05e9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4904 SND_PCI_QUIRK(0x1028, 0x05ea, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4905 SND_PCI_QUIRK(0x1028, 0x05eb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4906 SND_PCI_QUIRK(0x1028, 0x05ec, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4907 SND_PCI_QUIRK(0x1028, 0x05ed, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4908 SND_PCI_QUIRK(0x1028, 0x05ee, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4909 SND_PCI_QUIRK(0x1028, 0x05f3, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4910 SND_PCI_QUIRK(0x1028, 0x05f4, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4911 SND_PCI_QUIRK(0x1028, 0x05f5, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4912 SND_PCI_QUIRK(0x1028, 0x05f6, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
David Henningsson3ee21022013-05-31 10:41:04 +02004913 SND_PCI_QUIRK(0x1028, 0x05f8, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
David Henningssoncd6fb6792013-06-28 11:09:56 +02004914 SND_PCI_QUIRK(0x1028, 0x05f9, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4915 SND_PCI_QUIRK(0x1028, 0x05fb, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
David Henningssond81bf8c2013-06-11 11:06:48 +02004916 SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
4917 SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
David Henningsson3ee21022013-05-31 10:41:04 +02004918 SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
Hui Wang00ef9942014-07-31 11:52:38 +08004919 SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
David Henningsson6c29d682013-06-28 08:53:34 +02004920 SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
David Henningssonb8362e72013-11-21 14:12:59 +01004921 SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
David Henningsson0f4881d2013-12-20 16:08:13 +01004922 SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
4923 SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
Hui Wang00ef9942014-07-31 11:52:38 +08004924 SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
David Henningsson0f4881d2013-12-20 16:08:13 +01004925 SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
Kailang Yang9a22a8f52013-11-08 15:54:49 +08004926 SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
Kailang Yanga22aa262014-04-23 17:34:28 +08004927 SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
4928 SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
Kailang Yang31278992014-03-03 15:27:22 +08004929 SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE),
4930 SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE),
Hui Wanga1f3b5f2014-05-09 11:12:58 +08004931 SND_PCI_QUIRK(0x1028, 0x0684, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
Kailang Yang05843c02013-07-01 11:27:16 +02004932 SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
4933 SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
Kailang Yanga22aa262014-04-23 17:34:28 +08004934 SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
4935 SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
Takashi Iwai08fb0d02013-01-10 17:33:58 +01004936 SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01004937 SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
David Henningssond06ac142013-02-18 11:41:55 +01004938 SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4939 SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
David Henningsson8e35cd42013-11-06 11:20:01 +01004940 SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
Kailang Yangc60666b2014-02-21 16:23:35 +08004941 /* ALC282 */
Hui Wang549d8782014-07-07 17:07:43 +08004942 SND_PCI_QUIRK(0x103c, 0x21f8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4943 SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang8a02b162014-06-13 17:16:31 +08004944 SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4945 SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08004946 SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang8a02b162014-06-13 17:16:31 +08004947 SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4948 SND_PCI_QUIRK(0x103c, 0x2211, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4949 SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08004950 SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang8a02b162014-06-13 17:16:31 +08004951 SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08004952 SND_PCI_QUIRK(0x103c, 0x2234, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4953 SND_PCI_QUIRK(0x103c, 0x2235, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4954 SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4955 SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4956 SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4957 SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4958 SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4959 SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4960 SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4961 SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4962 SND_PCI_QUIRK(0x103c, 0x224a, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4963 SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4964 SND_PCI_QUIRK(0x103c, 0x224c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
4965 SND_PCI_QUIRK(0x103c, 0x224d, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
Kailang Yangc60666b2014-02-21 16:23:35 +08004966 SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4967 SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4968 SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4969 SND_PCI_QUIRK(0x103c, 0x2269, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4970 SND_PCI_QUIRK(0x103c, 0x226a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4971 SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang8a02b162014-06-13 17:16:31 +08004972 SND_PCI_QUIRK(0x103c, 0x226c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4973 SND_PCI_QUIRK(0x103c, 0x226d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4974 SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4975 SND_PCI_QUIRK(0x103c, 0x226f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08004976 SND_PCI_QUIRK(0x103c, 0x227a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4977 SND_PCI_QUIRK(0x103c, 0x227b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4978 SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4979 SND_PCI_QUIRK(0x103c, 0x22a0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4980 SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4981 SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4982 SND_PCI_QUIRK(0x103c, 0x22bf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4983 SND_PCI_QUIRK(0x103c, 0x22c0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4984 SND_PCI_QUIRK(0x103c, 0x22c1, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4985 SND_PCI_QUIRK(0x103c, 0x22c2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4986 SND_PCI_QUIRK(0x103c, 0x22cd, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4987 SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4988 SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
4989 SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08004990 SND_PCI_QUIRK(0x103c, 0x22da, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4991 SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4992 SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4993 SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4994 SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yangc60666b2014-02-21 16:23:35 +08004995 /* ALC290 */
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08004996 SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Hui Wang549d8782014-07-07 17:07:43 +08004997 SND_PCI_QUIRK(0x103c, 0x221c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
4998 SND_PCI_QUIRK(0x103c, 0x221d, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08004999 SND_PCI_QUIRK(0x103c, 0x2220, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5000 SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5001 SND_PCI_QUIRK(0x103c, 0x2222, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5002 SND_PCI_QUIRK(0x103c, 0x2223, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5003 SND_PCI_QUIRK(0x103c, 0x2224, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5004 SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5005 SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5006 SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5007 SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5008 SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5009 SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5010 SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5011 SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5012 SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5013 SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5014 SND_PCI_QUIRK(0x103c, 0x2258, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5015 SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5016 SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yangc60666b2014-02-21 16:23:35 +08005017 SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5018 SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5019 SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5020 SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5021 SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5022 SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang9c5dc3b2014-06-19 16:11:36 +08005023 SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5024 SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5025 SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
5026 SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
Kailang Yangc60666b2014-02-21 16:23:35 +08005027 SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5028 SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5029 SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5030 SND_PCI_QUIRK(0x103c, 0x2280, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5031 SND_PCI_QUIRK(0x103c, 0x2281, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5032 SND_PCI_QUIRK(0x103c, 0x2282, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5033 SND_PCI_QUIRK(0x103c, 0x2289, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5034 SND_PCI_QUIRK(0x103c, 0x228a, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5035 SND_PCI_QUIRK(0x103c, 0x228b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5036 SND_PCI_QUIRK(0x103c, 0x228c, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangfce0a0c2014-02-26 15:23:19 +08005037 SND_PCI_QUIRK(0x103c, 0x228d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yangc60666b2014-02-21 16:23:35 +08005038 SND_PCI_QUIRK(0x103c, 0x228e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5039 SND_PCI_QUIRK(0x103c, 0x22c5, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5040 SND_PCI_QUIRK(0x103c, 0x22c6, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5041 SND_PCI_QUIRK(0x103c, 0x22c7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5042 SND_PCI_QUIRK(0x103c, 0x22c8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5043 SND_PCI_QUIRK(0x103c, 0x22c3, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5044 SND_PCI_QUIRK(0x103c, 0x22c4, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Kailang Yang8a02b162014-06-13 17:16:31 +08005045 SND_PCI_QUIRK(0x103c, 0x2334, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5046 SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5047 SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
5048 SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
Takashi Iwai7bba2152013-09-06 15:45:38 +02005049 SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
David Henningsson3e0d6112013-04-22 14:30:14 +02005050 SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
5051 SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
Oleksij Rempel2cede302013-11-27 17:12:03 +01005052 SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
Takashi Iwai23870832013-11-29 14:13:12 +01005053 SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
David Henningsson3e0d6112013-04-22 14:30:14 +02005054 SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
Takashi Iwai017f2a12011-07-09 14:42:25 +02005055 SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
David Henningsson693b6132012-06-22 19:12:10 +02005056 SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC),
David Henningsson3e0d6112013-04-22 14:30:14 +02005057 SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
Takashi Iwaiadabb3e2011-08-03 07:48:37 +02005058 SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
5059 SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
5060 SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
5061 SND_PCI_QUIRK(0x1043, 0x83ce, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
David Henningssond240d1d2013-04-15 12:50:02 +02005062 SND_PCI_QUIRK(0x1043, 0x8516, "ASUS X101CH", ALC269_FIXUP_ASUS_X101),
Takashi Iwaif88abaa2014-02-07 12:07:59 +01005063 SND_PCI_QUIRK(0x104d, 0x90b5, "Sony VAIO Pro 11", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
David Henningsson88cfcf82013-10-11 10:18:45 +02005064 SND_PCI_QUIRK(0x104d, 0x90b6, "Sony VAIO Pro 13", ALC286_FIXUP_SONY_MIC_NO_PRESENCE),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005065 SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
5066 SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
5067 SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
Takashi Iwaie9bd7d52014-05-21 11:06:49 +02005068 SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX),
Takashi Iwai24519912011-08-16 15:08:49 +02005069 SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
David Henningsson2041d562014-06-13 11:15:44 +02005070 SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
Daniel Drake9dc12862014-07-22 10:58:29 +01005071 SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005072 SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
5073 SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
5074 SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
5075 SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
5076 SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
Takashi Iwai707fba32012-08-02 09:04:39 +02005077 SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),
Felix Kaechelec8415a42012-08-06 23:02:01 +02005078 SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
Stefán Freyr84f98fd2012-10-19 22:46:00 +02005079 SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
Philipp A. Mohrenweiser4407be62012-08-06 13:14:18 +02005080 SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
David Henningsson108cc102012-07-20 10:37:25 +02005081 SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
David Henningssonaaedfb42013-08-16 14:09:02 +02005082 SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
Takashi Iwai1c37c222014-05-06 17:34:42 +02005083 SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440_DOCK),
5084 SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
Takashi Iwaia12137e2014-06-27 12:14:35 +02005085 SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
David Henningssoncd5302c2013-08-19 12:22:33 +02005086 SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
David Henningsson27937692013-11-18 11:51:47 +01005087 SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
David Henningssona4a9e082013-08-16 14:09:01 +02005088 SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
Takashi Iwai9b745ab2014-03-07 08:37:19 +01005089 SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
David Henningssona4a9e082013-08-16 14:09:01 +02005090 SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
Kailang Yang1bb3e062013-09-27 13:10:25 +02005091 SND_PCI_QUIRK(0x17aa, 0x501a, "Thinkpad", ALC283_FIXUP_INT_MIC),
David Henningssoncd5302c2013-08-19 12:22:33 +02005092 SND_PCI_QUIRK(0x17aa, 0x5026, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
5093 SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
David Henningsson012e7eb2012-08-08 08:43:37 +02005094 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005095 SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
Anisse Astier02b504d2013-06-03 11:53:10 +02005096 SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
Takashi Iwaia4297b52011-08-23 18:40:12 +02005097
Takashi Iwaia7f3eed2012-02-16 13:03:18 +01005098#if 0
Takashi Iwaia4297b52011-08-23 18:40:12 +02005099 /* Below is a quirk table taken from the old code.
5100 * Basically the device should work as is without the fixup table.
5101 * If BIOS doesn't give a proper info, enable the corresponding
5102 * fixup entry.
Jesper Juhl7d7eb9e2012-04-12 22:11:25 +02005103 */
Takashi Iwaia4297b52011-08-23 18:40:12 +02005104 SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
5105 ALC269_FIXUP_AMIC),
5106 SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
Takashi Iwaia4297b52011-08-23 18:40:12 +02005107 SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
5108 SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
5109 SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
5110 SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269_FIXUP_AMIC),
5111 SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269_FIXUP_AMIC),
5112 SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269_FIXUP_AMIC),
5113 SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_FIXUP_AMIC),
5114 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269_FIXUP_AMIC),
5115 SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_FIXUP_AMIC),
5116 SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_FIXUP_AMIC),
5117 SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_FIXUP_AMIC),
5118 SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_FIXUP_AMIC),
5119 SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_FIXUP_AMIC),
5120 SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_FIXUP_AMIC),
5121 SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_FIXUP_AMIC),
5122 SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_FIXUP_AMIC),
5123 SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_FIXUP_AMIC),
5124 SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_FIXUP_AMIC),
5125 SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_FIXUP_AMIC),
5126 SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_FIXUP_AMIC),
5127 SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_FIXUP_AMIC),
5128 SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_FIXUP_AMIC),
5129 SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_FIXUP_AMIC),
5130 SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_FIXUP_AMIC),
5131 SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_FIXUP_AMIC),
5132 SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_FIXUP_AMIC),
5133 SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_FIXUP_AMIC),
5134 SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_FIXUP_AMIC),
5135 SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_FIXUP_AMIC),
5136 SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_FIXUP_AMIC),
5137 SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_FIXUP_AMIC),
5138 SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_FIXUP_AMIC),
5139 SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_FIXUP_AMIC),
5140 SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_FIXUP_DMIC),
5141 SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_FIXUP_AMIC),
5142 SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_AMIC),
5143 SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_FIXUP_DMIC),
5144 SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_FIXUP_DMIC),
5145#endif
5146 {}
5147};
5148
David Henningsson214eef72014-07-22 14:09:35 +02005149static const struct snd_pci_quirk alc269_fixup_vendor_tbl[] = {
5150 SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
5151 SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
5152 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
5153 SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
5154 {}
5155};
5156
Takashi Iwai1727a772013-01-10 09:52:52 +01005157static const struct hda_model_fixup alc269_fixup_models[] = {
Takashi Iwaia4297b52011-08-23 18:40:12 +02005158 {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
5159 {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
Takashi Iwai6e72aa52012-06-25 10:52:25 +02005160 {.id = ALC269_FIXUP_STEREO_DMIC, .name = "alc269-dmic"},
5161 {.id = ALC271_FIXUP_DMIC, .name = "alc271-dmic"},
5162 {.id = ALC269_FIXUP_INV_DMIC, .name = "inv-dmic"},
David Henningsson7c478f02013-10-11 10:18:46 +02005163 {.id = ALC269_FIXUP_HEADSET_MIC, .name = "headset-mic"},
David Henningsson108cc102012-07-20 10:37:25 +02005164 {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"},
Takashi Iwai9f5c6fa2013-03-18 14:15:58 +01005165 {.id = ALC269_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"},
David Henningssone32aa852013-06-17 11:04:02 +02005166 {.id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
5167 {.id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "dell-headset-dock"},
Kailang Yangbe8ef162014-04-08 15:19:49 +08005168 {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"},
Kailang Yang0202e992013-12-02 15:20:15 +08005169 {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
Takashi Iwai1c37c222014-05-06 17:34:42 +02005170 {.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"},
Takashi Iwai1d045db2011-07-07 18:23:21 +02005171 {}
5172};
5173
Hui Wange1918932014-05-26 16:22:44 +08005174static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
David Henningsson76c21322014-06-24 14:46:54 +02005175 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5176 {0x12, 0x90a60140},
5177 {0x14, 0x90170110},
5178 {0x17, 0x40000000},
5179 {0x18, 0x411111f0},
5180 {0x19, 0x411111f0},
5181 {0x1a, 0x411111f0},
5182 {0x1b, 0x411111f0},
5183 {0x1d, 0x40700001},
5184 {0x1e, 0x411111f0},
5185 {0x21, 0x02211020}),
5186 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5187 {0x12, 0x90a60160},
5188 {0x14, 0x90170120},
5189 {0x17, 0x40000000},
5190 {0x18, 0x411111f0},
5191 {0x19, 0x411111f0},
5192 {0x1a, 0x411111f0},
5193 {0x1b, 0x411111f0},
5194 {0x1d, 0x40700001},
5195 {0x1e, 0x411111f0},
5196 {0x21, 0x02211030}),
5197 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5198 {0x12, 0x90a60160},
5199 {0x14, 0x90170120},
5200 {0x17, 0x90170140},
5201 {0x18, 0x40000000},
5202 {0x19, 0x411111f0},
5203 {0x1a, 0x411111f0},
5204 {0x1b, 0x411111f0},
5205 {0x1d, 0x41163b05},
5206 {0x1e, 0x411111f0},
5207 {0x21, 0x0321102f}),
5208 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5209 {0x12, 0x90a60160},
5210 {0x14, 0x90170130},
5211 {0x17, 0x40000000},
5212 {0x18, 0x411111f0},
5213 {0x19, 0x411111f0},
5214 {0x1a, 0x411111f0},
5215 {0x1b, 0x411111f0},
5216 {0x1d, 0x40700001},
5217 {0x1e, 0x411111f0},
5218 {0x21, 0x02211040}),
5219 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5220 {0x12, 0x90a60160},
5221 {0x14, 0x90170140},
5222 {0x17, 0x40000000},
5223 {0x18, 0x411111f0},
5224 {0x19, 0x411111f0},
5225 {0x1a, 0x411111f0},
5226 {0x1b, 0x411111f0},
5227 {0x1d, 0x40700001},
5228 {0x1e, 0x411111f0},
5229 {0x21, 0x02211050}),
5230 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5231 {0x12, 0x90a60170},
5232 {0x14, 0x90170120},
5233 {0x17, 0x40000000},
5234 {0x18, 0x411111f0},
5235 {0x19, 0x411111f0},
5236 {0x1a, 0x411111f0},
5237 {0x1b, 0x411111f0},
5238 {0x1d, 0x40700001},
5239 {0x1e, 0x411111f0},
5240 {0x21, 0x02211030}),
5241 SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
5242 {0x12, 0x90a60170},
5243 {0x14, 0x90170130},
5244 {0x17, 0x40000000},
5245 {0x18, 0x411111f0},
5246 {0x19, 0x411111f0},
5247 {0x1a, 0x411111f0},
5248 {0x1b, 0x411111f0},
5249 {0x1d, 0x40700001},
5250 {0x1e, 0x411111f0},
5251 {0x21, 0x02211040}),
David Henningsson42304472014-07-22 11:42:17 +02005252 SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1,
5253 {0x12, 0x99a30130},
5254 {0x14, 0x90170110},
5255 {0x17, 0x40000000},
5256 {0x18, 0x411111f0},
5257 {0x19, 0x03a11020},
5258 {0x1a, 0x411111f0},
5259 {0x1b, 0x411111f0},
5260 {0x1d, 0x40f41905},
5261 {0x1e, 0x411111f0},
5262 {0x21, 0x0321101f}),
David Henningsson76c21322014-06-24 14:46:54 +02005263 SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
5264 {0x12, 0x90a60130},
5265 {0x14, 0x90170110},
5266 {0x17, 0x40020008},
5267 {0x18, 0x411111f0},
5268 {0x19, 0x411111f0},
5269 {0x1a, 0x411111f0},
5270 {0x1b, 0x411111f0},
5271 {0x1d, 0x40e00001},
5272 {0x1e, 0x411111f0},
5273 {0x21, 0x0321101f}),
5274 SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
5275 {0x12, 0x90a60160},
5276 {0x14, 0x90170120},
5277 {0x17, 0x40000000},
5278 {0x18, 0x411111f0},
5279 {0x19, 0x411111f0},
5280 {0x1a, 0x411111f0},
5281 {0x1b, 0x411111f0},
5282 {0x1d, 0x40700001},
5283 {0x1e, 0x411111f0},
5284 {0x21, 0x02211030}),
5285 SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
5286 {0x12, 0x90a60140},
5287 {0x13, 0x411111f0},
5288 {0x14, 0x90170110},
5289 {0x15, 0x0221401f},
5290 {0x16, 0x411111f0},
5291 {0x18, 0x411111f0},
5292 {0x19, 0x411111f0},
5293 {0x1a, 0x411111f0},
5294 {0x1b, 0x411111f0},
5295 {0x1d, 0x40700001},
5296 {0x1e, 0x411111f0}),
5297 SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
5298 {0x12, 0x40000000},
5299 {0x13, 0x90a60140},
5300 {0x14, 0x90170110},
5301 {0x15, 0x0221401f},
5302 {0x16, 0x21014020},
5303 {0x18, 0x411111f0},
5304 {0x19, 0x21a19030},
5305 {0x1a, 0x411111f0},
5306 {0x1b, 0x411111f0},
5307 {0x1d, 0x40700001},
5308 {0x1e, 0x411111f0}),
David Henningssone03fdbd2014-06-27 08:41:59 +02005309 SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
5310 {0x12, 0x40000000},
5311 {0x13, 0x90a60140},
5312 {0x14, 0x90170110},
5313 {0x15, 0x0221401f},
5314 {0x16, 0x411111f0},
5315 {0x18, 0x411111f0},
5316 {0x19, 0x411111f0},
5317 {0x1a, 0x411111f0},
5318 {0x1b, 0x411111f0},
5319 {0x1d, 0x40700001},
5320 {0x1e, 0x411111f0}),
Hui Wange1918932014-05-26 16:22:44 +08005321 {}
5322};
Takashi Iwai1d045db2011-07-07 18:23:21 +02005323
Takashi Iwai546bb672012-03-07 08:37:19 +01005324static void alc269_fill_coef(struct hda_codec *codec)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005325{
Kailang Yang526af6e2012-03-07 08:25:20 +01005326 struct alc_spec *spec = codec->spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005327 int val;
5328
Kailang Yang526af6e2012-03-07 08:25:20 +01005329 if (spec->codec_variant != ALC269_TYPE_ALC269VB)
Takashi Iwai546bb672012-03-07 08:37:19 +01005330 return;
Kailang Yang526af6e2012-03-07 08:25:20 +01005331
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005332 if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005333 alc_write_coef_idx(codec, 0xf, 0x960b);
5334 alc_write_coef_idx(codec, 0xe, 0x8817);
5335 }
5336
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005337 if ((alc_get_coef0(codec) & 0x00ff) == 0x016) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005338 alc_write_coef_idx(codec, 0xf, 0x960b);
5339 alc_write_coef_idx(codec, 0xe, 0x8814);
5340 }
5341
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005342 if ((alc_get_coef0(codec) & 0x00ff) == 0x017) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005343 val = alc_read_coef_idx(codec, 0x04);
5344 /* Power up output pin */
Takashi Iwaif3ee07d2014-08-15 17:35:00 +02005345 if (val != -1)
5346 alc_write_coef_idx(codec, 0x04, val | (1<<11));
Takashi Iwai1d045db2011-07-07 18:23:21 +02005347 }
5348
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005349 if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005350 val = alc_read_coef_idx(codec, 0xd);
Takashi Iwaif3ee07d2014-08-15 17:35:00 +02005351 if (val != -1 && (val & 0x0c00) >> 10 != 0x1) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005352 /* Capless ramp up clock control */
5353 alc_write_coef_idx(codec, 0xd, val | (1<<10));
5354 }
5355 val = alc_read_coef_idx(codec, 0x17);
Takashi Iwaif3ee07d2014-08-15 17:35:00 +02005356 if (val != -1 && (val & 0x01c0) >> 6 != 0x4) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005357 /* Class D power on reset */
5358 alc_write_coef_idx(codec, 0x17, val | (1<<7));
5359 }
5360 }
5361
5362 val = alc_read_coef_idx(codec, 0xd); /* Class D */
Takashi Iwaif3ee07d2014-08-15 17:35:00 +02005363 if (val != -1)
5364 alc_write_coef_idx(codec, 0xd, val | (1<<14));
Takashi Iwai1d045db2011-07-07 18:23:21 +02005365
5366 val = alc_read_coef_idx(codec, 0x4); /* HP */
Takashi Iwaif3ee07d2014-08-15 17:35:00 +02005367 if (val != -1)
5368 alc_write_coef_idx(codec, 0x4, val | (1<<11));
Takashi Iwai1d045db2011-07-07 18:23:21 +02005369}
5370
5371/*
5372 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005373static int patch_alc269(struct hda_codec *codec)
5374{
5375 struct alc_spec *spec;
Takashi Iwai3de95172012-05-07 18:03:15 +02005376 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005377
Takashi Iwai3de95172012-05-07 18:03:15 +02005378 err = alc_alloc_spec(codec, 0x0b);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005379 if (err < 0)
Takashi Iwai3de95172012-05-07 18:03:15 +02005380 return err;
5381
5382 spec = codec->spec;
Takashi Iwai08c189f2012-12-19 15:22:24 +01005383 spec->gen.shared_mic_vref_pin = 0x18;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005384
Takashi Iwai1727a772013-01-10 09:52:52 +01005385 snd_hda_pick_fixup(codec, alc269_fixup_models,
Herton Ronaldo Krzesinski9f720bb92012-09-27 10:38:14 -03005386 alc269_fixup_tbl, alc269_fixups);
Hui Wange1918932014-05-26 16:22:44 +08005387 snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups);
David Henningsson214eef72014-07-22 14:09:35 +02005388 snd_hda_pick_fixup(codec, NULL, alc269_fixup_vendor_tbl,
5389 alc269_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01005390 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Herton Ronaldo Krzesinski9f720bb92012-09-27 10:38:14 -03005391
5392 alc_auto_parse_customize_define(codec);
5393
Takashi Iwai7504b6c2013-03-18 11:25:51 +01005394 if (has_cdefine_beep(codec))
5395 spec->gen.beep_nid = 0x01;
5396
Kailang Yang065380f2013-01-10 10:25:48 +01005397 switch (codec->vendor_id) {
5398 case 0x10ec0269:
Takashi Iwai1d045db2011-07-07 18:23:21 +02005399 spec->codec_variant = ALC269_TYPE_ALC269VA;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005400 switch (alc_get_coef0(codec) & 0x00f0) {
5401 case 0x0010:
Takashi Iwai5100cd02014-02-15 10:03:19 +01005402 if (codec->bus->pci &&
5403 codec->bus->pci->subsystem_vendor == 0x1025 &&
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005404 spec->cdefine.platform_type == 1)
Takashi Iwai20ca0c32011-10-17 16:00:35 +02005405 err = alc_codec_rename(codec, "ALC271X");
Takashi Iwai1d045db2011-07-07 18:23:21 +02005406 spec->codec_variant = ALC269_TYPE_ALC269VB;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005407 break;
5408 case 0x0020:
Takashi Iwai5100cd02014-02-15 10:03:19 +01005409 if (codec->bus->pci &&
5410 codec->bus->pci->subsystem_vendor == 0x17aa &&
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005411 codec->bus->pci->subsystem_device == 0x21f3)
Takashi Iwai20ca0c32011-10-17 16:00:35 +02005412 err = alc_codec_rename(codec, "ALC3202");
Takashi Iwai1d045db2011-07-07 18:23:21 +02005413 spec->codec_variant = ALC269_TYPE_ALC269VC;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005414 break;
Kailang Yangadcc70b2012-05-25 08:08:38 +02005415 case 0x0030:
5416 spec->codec_variant = ALC269_TYPE_ALC269VD;
5417 break;
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005418 default:
Takashi Iwai1d045db2011-07-07 18:23:21 +02005419 alc_fix_pll_init(codec, 0x20, 0x04, 15);
Takashi Iwai1bb7e432011-10-17 16:50:59 +02005420 }
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005421 if (err < 0)
5422 goto error;
Takashi Iwai546bb672012-03-07 08:37:19 +01005423 spec->init_hook = alc269_fill_coef;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005424 alc269_fill_coef(codec);
Kailang Yang065380f2013-01-10 10:25:48 +01005425 break;
5426
5427 case 0x10ec0280:
5428 case 0x10ec0290:
5429 spec->codec_variant = ALC269_TYPE_ALC280;
5430 break;
5431 case 0x10ec0282:
Kailang Yang065380f2013-01-10 10:25:48 +01005432 spec->codec_variant = ALC269_TYPE_ALC282;
Kailang Yang7b5c7a02014-03-18 16:15:54 +08005433 spec->shutup = alc282_shutup;
5434 spec->init_hook = alc282_init;
Kailang Yang065380f2013-01-10 10:25:48 +01005435 break;
Kailang Yang2af02be2013-08-22 10:03:50 +02005436 case 0x10ec0233:
5437 case 0x10ec0283:
5438 spec->codec_variant = ALC269_TYPE_ALC283;
5439 spec->shutup = alc283_shutup;
5440 spec->init_hook = alc283_init;
5441 break;
Kailang Yang065380f2013-01-10 10:25:48 +01005442 case 0x10ec0284:
5443 case 0x10ec0292:
5444 spec->codec_variant = ALC269_TYPE_ALC284;
5445 break;
Kailang Yang161ebf22013-10-24 11:36:33 +02005446 case 0x10ec0285:
5447 case 0x10ec0293:
5448 spec->codec_variant = ALC269_TYPE_ALC285;
5449 break;
Kailang Yang7fc7d042013-04-25 11:04:43 +02005450 case 0x10ec0286:
Kailang Yang7c665932014-04-14 15:09:44 +08005451 case 0x10ec0288:
Kailang Yang7fc7d042013-04-25 11:04:43 +02005452 spec->codec_variant = ALC269_TYPE_ALC286;
Kailang Yangf7ae9ba2014-06-30 16:10:37 +08005453 spec->shutup = alc286_shutup;
Kailang Yang7fc7d042013-04-25 11:04:43 +02005454 break;
Kailang Yang1d04c9d2013-10-24 11:35:18 +02005455 case 0x10ec0255:
5456 spec->codec_variant = ALC269_TYPE_ALC255;
5457 break;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005458 }
5459
Kailang Yangad60d502013-06-28 12:03:01 +02005460 if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
Kailang Yang97a26572013-11-29 00:35:26 -05005461 spec->has_alc5505_dsp = 1;
Kailang Yangad60d502013-06-28 12:03:01 +02005462 spec->init_hook = alc5505_dsp_init;
5463 }
5464
Takashi Iwaia4297b52011-08-23 18:40:12 +02005465 /* automatic parse from the BIOS config */
5466 err = alc269_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005467 if (err < 0)
5468 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005469
Takashi Iwai7504b6c2013-03-18 11:25:51 +01005470 if (!spec->gen.no_analog && spec->gen.beep_nid)
Takashi Iwai1d045db2011-07-07 18:23:21 +02005471 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
5472
Takashi Iwai1d045db2011-07-07 18:23:21 +02005473 codec->patch_ops = alc_patch_ops;
Takashi Iwai2a439522011-07-26 09:52:50 +02005474#ifdef CONFIG_PM
Kailang Yangad60d502013-06-28 12:03:01 +02005475 codec->patch_ops.suspend = alc269_suspend;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005476 codec->patch_ops.resume = alc269_resume;
5477#endif
Kailang Yangc5177c82013-07-24 14:39:49 +02005478 if (!spec->shutup)
5479 spec->shutup = alc269_shutup;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005480
Takashi Iwai1727a772013-01-10 09:52:52 +01005481 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01005482
Takashi Iwai1d045db2011-07-07 18:23:21 +02005483 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005484
5485 error:
5486 alc_free(codec);
5487 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005488}
5489
5490/*
5491 * ALC861
5492 */
5493
Takashi Iwai1d045db2011-07-07 18:23:21 +02005494static int alc861_parse_auto_config(struct hda_codec *codec)
5495{
Takashi Iwai1d045db2011-07-07 18:23:21 +02005496 static const hda_nid_t alc861_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005497 static const hda_nid_t alc861_ssids[] = { 0x0e, 0x0f, 0x0b, 0 };
5498 return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005499}
5500
Takashi Iwai1d045db2011-07-07 18:23:21 +02005501/* Pin config fixes */
5502enum {
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005503 ALC861_FIXUP_FSC_AMILO_PI1505,
5504 ALC861_FIXUP_AMP_VREF_0F,
5505 ALC861_FIXUP_NO_JACK_DETECT,
5506 ALC861_FIXUP_ASUS_A6RP,
Takashi Iwai6ddf0fd2013-11-29 12:47:34 +01005507 ALC660_FIXUP_ASUS_W7J,
Takashi Iwai1d045db2011-07-07 18:23:21 +02005508};
5509
Takashi Iwai31150f22012-01-30 10:54:08 +01005510/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
5511static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01005512 const struct hda_fixup *fix, int action)
Takashi Iwai31150f22012-01-30 10:54:08 +01005513{
5514 struct alc_spec *spec = codec->spec;
5515 unsigned int val;
5516
Takashi Iwai1727a772013-01-10 09:52:52 +01005517 if (action != HDA_FIXUP_ACT_INIT)
Takashi Iwai31150f22012-01-30 10:54:08 +01005518 return;
Takashi Iwaid3f02d62013-01-10 10:12:22 +01005519 val = snd_hda_codec_get_pin_target(codec, 0x0f);
Takashi Iwai31150f22012-01-30 10:54:08 +01005520 if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
5521 val |= AC_PINCTL_IN_EN;
5522 val |= AC_PINCTL_VREF_50;
Takashi Iwaicdd03ce2012-04-20 12:34:50 +02005523 snd_hda_set_pin_ctl(codec, 0x0f, val);
Takashi Iwai08c189f2012-12-19 15:22:24 +01005524 spec->gen.keep_vref_in_automute = 1;
Takashi Iwai31150f22012-01-30 10:54:08 +01005525}
5526
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005527/* suppress the jack-detection */
5528static void alc_fixup_no_jack_detect(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01005529 const struct hda_fixup *fix, int action)
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005530{
Takashi Iwai1727a772013-01-10 09:52:52 +01005531 if (action == HDA_FIXUP_ACT_PRE_PROBE)
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005532 codec->no_jack_detect = 1;
Jesper Juhl7d7eb9e2012-04-12 22:11:25 +02005533}
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005534
Takashi Iwai1727a772013-01-10 09:52:52 +01005535static const struct hda_fixup alc861_fixups[] = {
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005536 [ALC861_FIXUP_FSC_AMILO_PI1505] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005537 .type = HDA_FIXUP_PINS,
5538 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005539 { 0x0b, 0x0221101f }, /* HP */
5540 { 0x0f, 0x90170310 }, /* speaker */
5541 { }
5542 }
5543 },
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005544 [ALC861_FIXUP_AMP_VREF_0F] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005545 .type = HDA_FIXUP_FUNC,
Takashi Iwai31150f22012-01-30 10:54:08 +01005546 .v.func = alc861_fixup_asus_amp_vref_0f,
Takashi Iwai3b25eb62012-01-25 09:55:46 +01005547 },
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005548 [ALC861_FIXUP_NO_JACK_DETECT] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005549 .type = HDA_FIXUP_FUNC,
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005550 .v.func = alc_fixup_no_jack_detect,
5551 },
5552 [ALC861_FIXUP_ASUS_A6RP] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005553 .type = HDA_FIXUP_FUNC,
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005554 .v.func = alc861_fixup_asus_amp_vref_0f,
5555 .chained = true,
5556 .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
Takashi Iwai6ddf0fd2013-11-29 12:47:34 +01005557 },
5558 [ALC660_FIXUP_ASUS_W7J] = {
5559 .type = HDA_FIXUP_VERBS,
5560 .v.verbs = (const struct hda_verb[]) {
5561 /* ASUS W7J needs a magic pin setup on unused NID 0x10
5562 * for enabling outputs
5563 */
5564 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
5565 { }
5566 },
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005567 }
Takashi Iwai1d045db2011-07-07 18:23:21 +02005568};
5569
5570static const struct snd_pci_quirk alc861_fixup_tbl[] = {
Takashi Iwai6ddf0fd2013-11-29 12:47:34 +01005571 SND_PCI_QUIRK(0x1043, 0x1253, "ASUS W7J", ALC660_FIXUP_ASUS_W7J),
Takashi Iwaie7ca2372013-12-02 15:27:19 +01005572 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS Z35HL", ALC660_FIXUP_ASUS_W7J),
Takashi Iwaie652f4c2012-02-13 11:56:25 +01005573 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
5574 SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
5575 SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
5576 SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F),
5577 SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F),
5578 SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005579 {}
5580};
5581
5582/*
5583 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005584static int patch_alc861(struct hda_codec *codec)
5585{
5586 struct alc_spec *spec;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005587 int err;
5588
Takashi Iwai3de95172012-05-07 18:03:15 +02005589 err = alc_alloc_spec(codec, 0x15);
5590 if (err < 0)
5591 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005592
Takashi Iwai3de95172012-05-07 18:03:15 +02005593 spec = codec->spec;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01005594 spec->gen.beep_nid = 0x23;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005595
Takashi Iwai1727a772013-01-10 09:52:52 +01005596 snd_hda_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
5597 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005598
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005599 /* automatic parse from the BIOS config */
5600 err = alc861_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005601 if (err < 0)
5602 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005603
Takashi Iwai7504b6c2013-03-18 11:25:51 +01005604 if (!spec->gen.no_analog)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005605 set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005606
Takashi Iwai1d045db2011-07-07 18:23:21 +02005607 codec->patch_ops = alc_patch_ops;
Takashi Iwai83012a72012-08-24 18:38:08 +02005608#ifdef CONFIG_PM
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005609 spec->power_hook = alc_power_eapd;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005610#endif
5611
Takashi Iwai1727a772013-01-10 09:52:52 +01005612 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01005613
Takashi Iwai1d045db2011-07-07 18:23:21 +02005614 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005615
5616 error:
5617 alc_free(codec);
5618 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005619}
5620
5621/*
5622 * ALC861-VD support
5623 *
5624 * Based on ALC882
5625 *
5626 * In addition, an independent DAC
5627 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005628static int alc861vd_parse_auto_config(struct hda_codec *codec)
5629{
Takashi Iwai1d045db2011-07-07 18:23:21 +02005630 static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005631 static const hda_nid_t alc861vd_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5632 return alc_parse_auto_config(codec, alc861vd_ignore, alc861vd_ssids);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005633}
5634
Takashi Iwai1d045db2011-07-07 18:23:21 +02005635enum {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005636 ALC660VD_FIX_ASUS_GPIO1,
5637 ALC861VD_FIX_DALLAS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02005638};
5639
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005640/* exclude VREF80 */
5641static void alc861vd_fixup_dallas(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01005642 const struct hda_fixup *fix, int action)
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005643{
Takashi Iwai1727a772013-01-10 09:52:52 +01005644 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
Takashi Iwaib78562b2012-12-17 20:06:49 +01005645 snd_hda_override_pin_caps(codec, 0x18, 0x00000734);
5646 snd_hda_override_pin_caps(codec, 0x19, 0x0000073c);
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005647 }
5648}
5649
Takashi Iwai1727a772013-01-10 09:52:52 +01005650static const struct hda_fixup alc861vd_fixups[] = {
Takashi Iwai1d045db2011-07-07 18:23:21 +02005651 [ALC660VD_FIX_ASUS_GPIO1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005652 .type = HDA_FIXUP_VERBS,
Takashi Iwai1d045db2011-07-07 18:23:21 +02005653 .v.verbs = (const struct hda_verb[]) {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005654 /* reset GPIO1 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005655 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
5656 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
5657 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
5658 { }
5659 }
5660 },
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005661 [ALC861VD_FIX_DALLAS] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005662 .type = HDA_FIXUP_FUNC,
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005663 .v.func = alc861vd_fixup_dallas,
5664 },
Takashi Iwai1d045db2011-07-07 18:23:21 +02005665};
5666
5667static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005668 SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005669 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
Takashi Iwai8fdcb6f2011-08-23 17:28:55 +02005670 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS),
Takashi Iwai1d045db2011-07-07 18:23:21 +02005671 {}
5672};
5673
Takashi Iwai1d045db2011-07-07 18:23:21 +02005674/*
5675 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005676static int patch_alc861vd(struct hda_codec *codec)
5677{
5678 struct alc_spec *spec;
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005679 int err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005680
Takashi Iwai3de95172012-05-07 18:03:15 +02005681 err = alc_alloc_spec(codec, 0x0b);
5682 if (err < 0)
5683 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005684
Takashi Iwai3de95172012-05-07 18:03:15 +02005685 spec = codec->spec;
Takashi Iwai7504b6c2013-03-18 11:25:51 +01005686 spec->gen.beep_nid = 0x23;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005687
Takashi Iwai1727a772013-01-10 09:52:52 +01005688 snd_hda_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
5689 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005690
Takashi Iwaicb4e4822011-08-23 17:34:25 +02005691 /* automatic parse from the BIOS config */
5692 err = alc861vd_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005693 if (err < 0)
5694 goto error;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005695
Takashi Iwai7504b6c2013-03-18 11:25:51 +01005696 if (!spec->gen.no_analog)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005697 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
Takashi Iwai1d045db2011-07-07 18:23:21 +02005698
Takashi Iwai1d045db2011-07-07 18:23:21 +02005699 codec->patch_ops = alc_patch_ops;
5700
Takashi Iwai1d045db2011-07-07 18:23:21 +02005701 spec->shutup = alc_eapd_shutup;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005702
Takashi Iwai1727a772013-01-10 09:52:52 +01005703 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01005704
Takashi Iwai1d045db2011-07-07 18:23:21 +02005705 return 0;
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02005706
5707 error:
5708 alc_free(codec);
5709 return err;
Takashi Iwai1d045db2011-07-07 18:23:21 +02005710}
5711
5712/*
5713 * ALC662 support
5714 *
5715 * ALC662 is almost identical with ALC880 but has cleaner and more flexible
5716 * configuration. Each pin widget can choose any input DACs and a mixer.
5717 * Each ADC is connected from a mixer of all inputs. This makes possible
5718 * 6-channel independent captures.
5719 *
5720 * In addition, an independent DAC for the multi-playback (not used in this
5721 * driver yet).
5722 */
Takashi Iwai1d045db2011-07-07 18:23:21 +02005723
5724/*
5725 * BIOS auto configuration
5726 */
5727
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005728static int alc662_parse_auto_config(struct hda_codec *codec)
5729{
Takashi Iwai4c6d72d2011-05-02 11:30:18 +02005730 static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005731 static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
5732 static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
5733 const hda_nid_t *ssids;
Takashi Iwaiee979a142008-09-02 15:42:20 +02005734
Kailang Yang6227cdc2010-02-25 08:36:52 +01005735 if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
Rainer Koenig1d87caa2013-04-04 08:40:38 +02005736 codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670 ||
5737 codec->vendor_id == 0x10ec0671)
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005738 ssids = alc663_ssids;
Kailang Yang6227cdc2010-02-25 08:36:52 +01005739 else
Takashi Iwai3e6179b2011-07-08 16:55:13 +02005740 ssids = alc662_ssids;
5741 return alc_parse_auto_config(codec, alc662_ignore, ssids);
Kailang Yangbc9f98a2007-04-12 13:06:07 +02005742}
5743
Todd Broch6be79482010-12-07 16:51:05 -08005744static void alc272_fixup_mario(struct hda_codec *codec,
Takashi Iwai1727a772013-01-10 09:52:52 +01005745 const struct hda_fixup *fix, int action)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005746{
Takashi Iwai9bb1f062013-01-10 17:14:29 +01005747 if (action != HDA_FIXUP_ACT_PRE_PROBE)
Takashi Iwai6fc398c2011-01-13 14:36:37 +01005748 return;
Todd Broch6be79482010-12-07 16:51:05 -08005749 if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
5750 (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
5751 (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
5752 (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
5753 (0 << AC_AMPCAP_MUTE_SHIFT)))
Takashi Iwai4e76a882014-02-25 12:21:03 +01005754 codec_warn(codec, "failed to override amp caps for NID 0x2\n");
Todd Broch6be79482010-12-07 16:51:05 -08005755}
5756
Takashi Iwai8e383952013-10-30 17:41:12 +01005757static const struct snd_pcm_chmap_elem asus_pcm_2_1_chmaps[] = {
5758 { .channels = 2,
5759 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
5760 { .channels = 4,
5761 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
5762 SNDRV_CHMAP_NA, SNDRV_CHMAP_LFE } }, /* LFE only on right */
5763 { }
5764};
5765
5766/* override the 2.1 chmap */
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01005767static void alc_fixup_bass_chmap(struct hda_codec *codec,
Takashi Iwai8e383952013-10-30 17:41:12 +01005768 const struct hda_fixup *fix, int action)
5769{
5770 if (action == HDA_FIXUP_ACT_BUILD) {
5771 struct alc_spec *spec = codec->spec;
5772 spec->gen.pcm_rec[0].stream[0].chmap = asus_pcm_2_1_chmaps;
5773 }
5774}
5775
Takashi Iwai3e887f32014-01-10 17:50:58 +01005776/* turn on/off mute LED per vmaster hook */
5777static void alc662_led_gpio1_mute_hook(void *private_data, int enabled)
5778{
5779 struct hda_codec *codec = private_data;
5780 struct alc_spec *spec = codec->spec;
5781 unsigned int oldval = spec->gpio_led;
5782
5783 if (enabled)
5784 spec->gpio_led &= ~0x01;
5785 else
5786 spec->gpio_led |= 0x01;
5787 if (spec->gpio_led != oldval)
5788 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
5789 spec->gpio_led);
5790}
5791
Takashi Iwaibf686652014-01-13 16:18:25 +01005792/* avoid D3 for keeping GPIO up */
5793static unsigned int gpio_led_power_filter(struct hda_codec *codec,
5794 hda_nid_t nid,
5795 unsigned int power_state)
5796{
5797 struct alc_spec *spec = codec->spec;
5798 if (nid == codec->afg && power_state == AC_PWRST_D3 && spec->gpio_led)
5799 return AC_PWRST_D0;
5800 return power_state;
5801}
5802
Takashi Iwai3e887f32014-01-10 17:50:58 +01005803static void alc662_fixup_led_gpio1(struct hda_codec *codec,
5804 const struct hda_fixup *fix, int action)
5805{
5806 struct alc_spec *spec = codec->spec;
5807 static const struct hda_verb gpio_init[] = {
5808 { 0x01, AC_VERB_SET_GPIO_MASK, 0x01 },
5809 { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01 },
5810 {}
5811 };
5812
5813 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
5814 spec->gen.vmaster_mute.hook = alc662_led_gpio1_mute_hook;
5815 spec->gpio_led = 0;
5816 snd_hda_add_verbs(codec, gpio_init);
Takashi Iwaibf686652014-01-13 16:18:25 +01005817 codec->power_filter = gpio_led_power_filter;
Takashi Iwai3e887f32014-01-10 17:50:58 +01005818 }
5819}
5820
David Henningsson6cb3b702010-09-09 08:51:44 +02005821enum {
Daniel T Chen2df03512010-10-10 22:39:28 -04005822 ALC662_FIXUP_ASPIRE,
Takashi Iwai3e887f32014-01-10 17:50:58 +01005823 ALC662_FIXUP_LED_GPIO1,
David Henningsson6cb3b702010-09-09 08:51:44 +02005824 ALC662_FIXUP_IDEAPAD,
Todd Broch6be79482010-12-07 16:51:05 -08005825 ALC272_FIXUP_MARIO,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005826 ALC662_FIXUP_CZC_P10T,
David Henningsson94024cd2011-04-29 14:10:55 +02005827 ALC662_FIXUP_SKU_IGNORE,
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005828 ALC662_FIXUP_HP_RP5800,
Takashi Iwai53c334a2011-08-23 18:27:14 +02005829 ALC662_FIXUP_ASUS_MODE1,
5830 ALC662_FIXUP_ASUS_MODE2,
5831 ALC662_FIXUP_ASUS_MODE3,
5832 ALC662_FIXUP_ASUS_MODE4,
5833 ALC662_FIXUP_ASUS_MODE5,
5834 ALC662_FIXUP_ASUS_MODE6,
5835 ALC662_FIXUP_ASUS_MODE7,
5836 ALC662_FIXUP_ASUS_MODE8,
Takashi Iwai1565cc32012-02-13 12:03:25 +01005837 ALC662_FIXUP_NO_JACK_DETECT,
David Henningssonedfe3bf2012-06-12 13:15:12 +02005838 ALC662_FIXUP_ZOTAC_Z68,
Takashi Iwai125821a2012-06-22 14:30:29 +02005839 ALC662_FIXUP_INV_DMIC,
David Henningsson73bdd592013-04-15 15:44:14 +02005840 ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
5841 ALC668_FIXUP_HEADSET_MODE,
David Henningsson8e54b4a2014-02-07 09:31:07 +01005842 ALC662_FIXUP_BASS_MODE4_CHMAP,
David Henningsson61a75f12014-02-07 09:31:08 +01005843 ALC662_FIXUP_BASS_16,
Takashi Iwaia30c9aa2013-11-21 08:00:20 +01005844 ALC662_FIXUP_BASS_1A,
David Henningsson8e54b4a2014-02-07 09:31:07 +01005845 ALC662_FIXUP_BASS_CHMAP,
Hui Wang493a52a2014-01-14 14:07:36 +08005846 ALC668_FIXUP_AUTO_MUTE,
Gabriele Mazzotta5e6db662014-05-20 18:58:26 +02005847 ALC668_FIXUP_DELL_DISABLE_AAMIX,
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02005848 ALC668_FIXUP_DELL_XPS13,
David Henningsson6cb3b702010-09-09 08:51:44 +02005849};
5850
Takashi Iwai1727a772013-01-10 09:52:52 +01005851static const struct hda_fixup alc662_fixups[] = {
Daniel T Chen2df03512010-10-10 22:39:28 -04005852 [ALC662_FIXUP_ASPIRE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005853 .type = HDA_FIXUP_PINS,
5854 .v.pins = (const struct hda_pintbl[]) {
Daniel T Chen2df03512010-10-10 22:39:28 -04005855 { 0x15, 0x99130112 }, /* subwoofer */
5856 { }
5857 }
5858 },
Takashi Iwai3e887f32014-01-10 17:50:58 +01005859 [ALC662_FIXUP_LED_GPIO1] = {
5860 .type = HDA_FIXUP_FUNC,
5861 .v.func = alc662_fixup_led_gpio1,
5862 },
David Henningsson6cb3b702010-09-09 08:51:44 +02005863 [ALC662_FIXUP_IDEAPAD] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005864 .type = HDA_FIXUP_PINS,
5865 .v.pins = (const struct hda_pintbl[]) {
David Henningsson6cb3b702010-09-09 08:51:44 +02005866 { 0x17, 0x99130112 }, /* subwoofer */
5867 { }
Takashi Iwai3e887f32014-01-10 17:50:58 +01005868 },
5869 .chained = true,
5870 .chain_id = ALC662_FIXUP_LED_GPIO1,
David Henningsson6cb3b702010-09-09 08:51:44 +02005871 },
Todd Broch6be79482010-12-07 16:51:05 -08005872 [ALC272_FIXUP_MARIO] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005873 .type = HDA_FIXUP_FUNC,
Takashi Iwaib5bfbc62011-01-13 14:22:32 +01005874 .v.func = alc272_fixup_mario,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005875 },
5876 [ALC662_FIXUP_CZC_P10T] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005877 .type = HDA_FIXUP_VERBS,
Anisse Astierd2ebd472011-01-20 12:36:21 +01005878 .v.verbs = (const struct hda_verb[]) {
5879 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
5880 {}
5881 }
5882 },
David Henningsson94024cd2011-04-29 14:10:55 +02005883 [ALC662_FIXUP_SKU_IGNORE] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005884 .type = HDA_FIXUP_FUNC,
Takashi Iwai23d30f22012-05-07 17:17:32 +02005885 .v.func = alc_fixup_sku_ignore,
Takashi Iwaic6b35872011-03-28 12:05:31 +02005886 },
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005887 [ALC662_FIXUP_HP_RP5800] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005888 .type = HDA_FIXUP_PINS,
5889 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02005890 { 0x14, 0x0221201f }, /* HP out */
5891 { }
5892 },
5893 .chained = true,
5894 .chain_id = ALC662_FIXUP_SKU_IGNORE
5895 },
Takashi Iwai53c334a2011-08-23 18:27:14 +02005896 [ALC662_FIXUP_ASUS_MODE1] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005897 .type = HDA_FIXUP_PINS,
5898 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02005899 { 0x14, 0x99130110 }, /* speaker */
5900 { 0x18, 0x01a19c20 }, /* mic */
5901 { 0x19, 0x99a3092f }, /* int-mic */
5902 { 0x21, 0x0121401f }, /* HP out */
5903 { }
5904 },
5905 .chained = true,
5906 .chain_id = ALC662_FIXUP_SKU_IGNORE
5907 },
5908 [ALC662_FIXUP_ASUS_MODE2] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005909 .type = HDA_FIXUP_PINS,
5910 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005911 { 0x14, 0x99130110 }, /* speaker */
5912 { 0x18, 0x01a19820 }, /* mic */
5913 { 0x19, 0x99a3092f }, /* int-mic */
5914 { 0x1b, 0x0121401f }, /* HP out */
5915 { }
5916 },
Takashi Iwai53c334a2011-08-23 18:27:14 +02005917 .chained = true,
5918 .chain_id = ALC662_FIXUP_SKU_IGNORE
5919 },
5920 [ALC662_FIXUP_ASUS_MODE3] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005921 .type = HDA_FIXUP_PINS,
5922 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02005923 { 0x14, 0x99130110 }, /* speaker */
5924 { 0x15, 0x0121441f }, /* HP */
5925 { 0x18, 0x01a19840 }, /* mic */
5926 { 0x19, 0x99a3094f }, /* int-mic */
5927 { 0x21, 0x01211420 }, /* HP2 */
5928 { }
5929 },
5930 .chained = true,
5931 .chain_id = ALC662_FIXUP_SKU_IGNORE
5932 },
5933 [ALC662_FIXUP_ASUS_MODE4] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005934 .type = HDA_FIXUP_PINS,
5935 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02005936 { 0x14, 0x99130110 }, /* speaker */
5937 { 0x16, 0x99130111 }, /* speaker */
5938 { 0x18, 0x01a19840 }, /* mic */
5939 { 0x19, 0x99a3094f }, /* int-mic */
5940 { 0x21, 0x0121441f }, /* HP */
5941 { }
5942 },
5943 .chained = true,
5944 .chain_id = ALC662_FIXUP_SKU_IGNORE
5945 },
5946 [ALC662_FIXUP_ASUS_MODE5] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005947 .type = HDA_FIXUP_PINS,
5948 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02005949 { 0x14, 0x99130110 }, /* speaker */
5950 { 0x15, 0x0121441f }, /* HP */
5951 { 0x16, 0x99130111 }, /* speaker */
5952 { 0x18, 0x01a19840 }, /* mic */
5953 { 0x19, 0x99a3094f }, /* int-mic */
5954 { }
5955 },
5956 .chained = true,
5957 .chain_id = ALC662_FIXUP_SKU_IGNORE
5958 },
5959 [ALC662_FIXUP_ASUS_MODE6] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005960 .type = HDA_FIXUP_PINS,
5961 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02005962 { 0x14, 0x99130110 }, /* speaker */
5963 { 0x15, 0x01211420 }, /* HP2 */
5964 { 0x18, 0x01a19840 }, /* mic */
5965 { 0x19, 0x99a3094f }, /* int-mic */
5966 { 0x1b, 0x0121441f }, /* HP */
5967 { }
5968 },
5969 .chained = true,
5970 .chain_id = ALC662_FIXUP_SKU_IGNORE
5971 },
5972 [ALC662_FIXUP_ASUS_MODE7] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005973 .type = HDA_FIXUP_PINS,
5974 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02005975 { 0x14, 0x99130110 }, /* speaker */
5976 { 0x17, 0x99130111 }, /* speaker */
5977 { 0x18, 0x01a19840 }, /* mic */
5978 { 0x19, 0x99a3094f }, /* int-mic */
5979 { 0x1b, 0x01214020 }, /* HP */
5980 { 0x21, 0x0121401f }, /* HP */
5981 { }
5982 },
5983 .chained = true,
5984 .chain_id = ALC662_FIXUP_SKU_IGNORE
5985 },
5986 [ALC662_FIXUP_ASUS_MODE8] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01005987 .type = HDA_FIXUP_PINS,
5988 .v.pins = (const struct hda_pintbl[]) {
Takashi Iwai53c334a2011-08-23 18:27:14 +02005989 { 0x14, 0x99130110 }, /* speaker */
5990 { 0x12, 0x99a30970 }, /* int-mic */
5991 { 0x15, 0x01214020 }, /* HP */
5992 { 0x17, 0x99130111 }, /* speaker */
5993 { 0x18, 0x01a19840 }, /* mic */
5994 { 0x21, 0x0121401f }, /* HP */
5995 { }
5996 },
5997 .chained = true,
5998 .chain_id = ALC662_FIXUP_SKU_IGNORE
Takashi Iwai2996bdb2011-08-18 16:02:24 +02005999 },
Takashi Iwai1565cc32012-02-13 12:03:25 +01006000 [ALC662_FIXUP_NO_JACK_DETECT] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006001 .type = HDA_FIXUP_FUNC,
Takashi Iwai1565cc32012-02-13 12:03:25 +01006002 .v.func = alc_fixup_no_jack_detect,
6003 },
David Henningssonedfe3bf2012-06-12 13:15:12 +02006004 [ALC662_FIXUP_ZOTAC_Z68] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006005 .type = HDA_FIXUP_PINS,
6006 .v.pins = (const struct hda_pintbl[]) {
David Henningssonedfe3bf2012-06-12 13:15:12 +02006007 { 0x1b, 0x02214020 }, /* Front HP */
6008 { }
6009 }
6010 },
Takashi Iwai125821a2012-06-22 14:30:29 +02006011 [ALC662_FIXUP_INV_DMIC] = {
Takashi Iwai1727a772013-01-10 09:52:52 +01006012 .type = HDA_FIXUP_FUNC,
Takashi Iwai6e72aa52012-06-25 10:52:25 +02006013 .v.func = alc_fixup_inv_dmic_0x12,
Takashi Iwai125821a2012-06-22 14:30:29 +02006014 },
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02006015 [ALC668_FIXUP_DELL_XPS13] = {
6016 .type = HDA_FIXUP_FUNC,
6017 .v.func = alc_fixup_dell_xps13,
6018 .chained = true,
6019 .chain_id = ALC668_FIXUP_DELL_DISABLE_AAMIX
6020 },
Gabriele Mazzotta5e6db662014-05-20 18:58:26 +02006021 [ALC668_FIXUP_DELL_DISABLE_AAMIX] = {
6022 .type = HDA_FIXUP_FUNC,
6023 .v.func = alc_fixup_disable_aamix,
6024 .chained = true,
6025 .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
6026 },
Hui Wang493a52a2014-01-14 14:07:36 +08006027 [ALC668_FIXUP_AUTO_MUTE] = {
6028 .type = HDA_FIXUP_FUNC,
6029 .v.func = alc_fixup_auto_mute_via_amp,
6030 .chained = true,
6031 .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
6032 },
David Henningsson73bdd592013-04-15 15:44:14 +02006033 [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
6034 .type = HDA_FIXUP_PINS,
6035 .v.pins = (const struct hda_pintbl[]) {
6036 { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
6037 { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
6038 { }
6039 },
6040 .chained = true,
6041 .chain_id = ALC668_FIXUP_HEADSET_MODE
6042 },
6043 [ALC668_FIXUP_HEADSET_MODE] = {
6044 .type = HDA_FIXUP_FUNC,
6045 .v.func = alc_fixup_headset_mode_alc668,
6046 },
David Henningsson8e54b4a2014-02-07 09:31:07 +01006047 [ALC662_FIXUP_BASS_MODE4_CHMAP] = {
Takashi Iwai8e383952013-10-30 17:41:12 +01006048 .type = HDA_FIXUP_FUNC,
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01006049 .v.func = alc_fixup_bass_chmap,
Takashi Iwai8e383952013-10-30 17:41:12 +01006050 .chained = true,
6051 .chain_id = ALC662_FIXUP_ASUS_MODE4
6052 },
David Henningsson61a75f12014-02-07 09:31:08 +01006053 [ALC662_FIXUP_BASS_16] = {
6054 .type = HDA_FIXUP_PINS,
6055 .v.pins = (const struct hda_pintbl[]) {
6056 {0x16, 0x80106111}, /* bass speaker */
6057 {}
6058 },
6059 .chained = true,
6060 .chain_id = ALC662_FIXUP_BASS_CHMAP,
6061 },
Takashi Iwaia30c9aa2013-11-21 08:00:20 +01006062 [ALC662_FIXUP_BASS_1A] = {
6063 .type = HDA_FIXUP_PINS,
6064 .v.pins = (const struct hda_pintbl[]) {
6065 {0x1a, 0x80106111}, /* bass speaker */
6066 {}
6067 },
David Henningsson8e54b4a2014-02-07 09:31:07 +01006068 .chained = true,
6069 .chain_id = ALC662_FIXUP_BASS_CHMAP,
Takashi Iwaia30c9aa2013-11-21 08:00:20 +01006070 },
David Henningsson8e54b4a2014-02-07 09:31:07 +01006071 [ALC662_FIXUP_BASS_CHMAP] = {
Takashi Iwaia30c9aa2013-11-21 08:00:20 +01006072 .type = HDA_FIXUP_FUNC,
Takashi Iwaieb9ca3a2013-11-28 15:24:34 +01006073 .v.func = alc_fixup_bass_chmap,
Takashi Iwaia30c9aa2013-11-21 08:00:20 +01006074 },
David Henningsson6cb3b702010-09-09 08:51:44 +02006075};
6076
Takashi Iwaia9111322011-05-02 11:30:18 +02006077static const struct snd_pci_quirk alc662_fixup_tbl[] = {
Takashi Iwai53c334a2011-08-23 18:27:14 +02006078 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
Takashi Iwaid3d38352013-08-19 20:05:50 +02006079 SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
David Henningssona6c47a82011-02-10 15:39:19 +01006080 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
David Henningsson94024cd2011-04-29 14:10:55 +02006081 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
Takashi Iwai125821a2012-06-22 14:30:29 +02006082 SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
Takashi Iwai18019282013-08-16 08:17:05 +02006083 SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
Daniel T Chen2df03512010-10-10 22:39:28 -04006084 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
David Henningsson73bdd592013-04-15 15:44:14 +02006085 SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
6086 SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
Takashi Iwaic5d019c2014-07-22 17:33:32 +02006087 SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13),
Gabriele Mazzotta033b0a72014-05-26 17:11:46 +02006088 SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13),
David Henningsson09d20142013-11-20 11:43:30 +01006089 SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
David Henningssonad8ff992013-11-07 09:28:59 +01006090 SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
Kailang Yang8dc9abb2014-04-16 15:53:12 +08006091 SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
6092 SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
Takashi Iwaie59ea3e2011-06-29 17:21:00 +02006093 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
David Henningsson8e54b4a2014-02-07 09:31:07 +01006094 SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A),
6095 SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
David Henningsson61a75f12014-02-07 09:31:08 +01006096 SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
6097 SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
David Henningsson8e54b4a2014-02-07 09:31:07 +01006098 SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
Takashi Iwai1565cc32012-02-13 12:03:25 +01006099 SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
Takashi Iwai53c334a2011-08-23 18:27:14 +02006100 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
Daniel T Chena0e90ac2010-11-20 10:20:35 -05006101 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
Valentine Sinitsynd4118582010-10-01 22:24:08 +06006102 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
David Henningsson6cb3b702010-09-09 08:51:44 +02006103 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
David Henningssonedfe3bf2012-06-12 13:15:12 +02006104 SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68),
Anisse Astierd2ebd472011-01-20 12:36:21 +01006105 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
Takashi Iwai53c334a2011-08-23 18:27:14 +02006106
6107#if 0
6108 /* Below is a quirk table taken from the old code.
6109 * Basically the device should work as is without the fixup table.
6110 * If BIOS doesn't give a proper info, enable the corresponding
6111 * fixup entry.
Jesper Juhl7d7eb9e2012-04-12 22:11:25 +02006112 */
Takashi Iwai53c334a2011-08-23 18:27:14 +02006113 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
6114 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
6115 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
6116 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
6117 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6118 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6119 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6120 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
6121 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
6122 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6123 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
6124 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
6125 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
6126 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
6127 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
6128 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6129 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
6130 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
6131 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6132 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
6133 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
6134 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6135 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
6136 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
6137 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
6138 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6139 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
6140 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
6141 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6142 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
6143 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6144 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6145 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
6146 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
6147 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
6148 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
6149 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
6150 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
6151 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
6152 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
6153 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
6154 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
6155 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6156 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
6157 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
6158 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
6159 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
6160 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
6161 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
6162 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
6163#endif
David Henningsson6cb3b702010-09-09 08:51:44 +02006164 {}
6165};
6166
Takashi Iwai1727a772013-01-10 09:52:52 +01006167static const struct hda_model_fixup alc662_fixup_models[] = {
Todd Broch6be79482010-12-07 16:51:05 -08006168 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
Takashi Iwai53c334a2011-08-23 18:27:14 +02006169 {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
6170 {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
6171 {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
6172 {.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
6173 {.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
6174 {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
6175 {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
6176 {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
Takashi Iwai6e72aa52012-06-25 10:52:25 +02006177 {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
David Henningssone32aa852013-06-17 11:04:02 +02006178 {.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
Todd Broch6be79482010-12-07 16:51:05 -08006179 {}
6180};
David Henningsson6cb3b702010-09-09 08:51:44 +02006181
Hui Wang532895c2014-05-29 15:59:19 +08006182static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = {
David Henningsson76c21322014-06-24 14:46:54 +02006183 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
6184 {0x12, 0x99a30130},
6185 {0x14, 0x90170110},
6186 {0x15, 0x0321101f},
6187 {0x16, 0x03011020},
6188 {0x18, 0x40000008},
6189 {0x19, 0x411111f0},
6190 {0x1a, 0x411111f0},
6191 {0x1b, 0x411111f0},
6192 {0x1d, 0x41000001},
6193 {0x1e, 0x411111f0},
6194 {0x1f, 0x411111f0}),
6195 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
6196 {0x12, 0x99a30140},
6197 {0x14, 0x90170110},
6198 {0x15, 0x0321101f},
6199 {0x16, 0x03011020},
6200 {0x18, 0x40000008},
6201 {0x19, 0x411111f0},
6202 {0x1a, 0x411111f0},
6203 {0x1b, 0x411111f0},
6204 {0x1d, 0x41000001},
6205 {0x1e, 0x411111f0},
6206 {0x1f, 0x411111f0}),
6207 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
6208 {0x12, 0x99a30150},
6209 {0x14, 0x90170110},
6210 {0x15, 0x0321101f},
6211 {0x16, 0x03011020},
6212 {0x18, 0x40000008},
6213 {0x19, 0x411111f0},
6214 {0x1a, 0x411111f0},
6215 {0x1b, 0x411111f0},
6216 {0x1d, 0x41000001},
6217 {0x1e, 0x411111f0},
6218 {0x1f, 0x411111f0}),
6219 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
6220 {0x12, 0x411111f0},
6221 {0x14, 0x90170110},
6222 {0x15, 0x0321101f},
6223 {0x16, 0x03011020},
6224 {0x18, 0x40000008},
6225 {0x19, 0x411111f0},
6226 {0x1a, 0x411111f0},
6227 {0x1b, 0x411111f0},
6228 {0x1d, 0x41000001},
6229 {0x1e, 0x411111f0},
6230 {0x1f, 0x411111f0}),
6231 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell XPS 15", ALC668_FIXUP_AUTO_MUTE,
6232 {0x12, 0x90a60130},
6233 {0x14, 0x90170110},
6234 {0x15, 0x0321101f},
6235 {0x16, 0x40000000},
6236 {0x18, 0x411111f0},
6237 {0x19, 0x411111f0},
6238 {0x1a, 0x411111f0},
6239 {0x1b, 0x411111f0},
6240 {0x1d, 0x40d6832d},
6241 {0x1e, 0x411111f0},
6242 {0x1f, 0x411111f0}),
Hui Wang532895c2014-05-29 15:59:19 +08006243 {}
6244};
6245
Kailang Yang8663ff72012-06-29 09:35:52 +02006246static void alc662_fill_coef(struct hda_codec *codec)
6247{
6248 int val, coef;
6249
6250 coef = alc_get_coef0(codec);
6251
6252 switch (codec->vendor_id) {
6253 case 0x10ec0662:
6254 if ((coef & 0x00f0) == 0x0030) {
6255 val = alc_read_coef_idx(codec, 0x4); /* EAPD Ctrl */
6256 alc_write_coef_idx(codec, 0x4, val & ~(1<<10));
6257 }
6258 break;
6259 case 0x10ec0272:
6260 case 0x10ec0273:
6261 case 0x10ec0663:
6262 case 0x10ec0665:
6263 case 0x10ec0670:
6264 case 0x10ec0671:
6265 case 0x10ec0672:
6266 val = alc_read_coef_idx(codec, 0xd); /* EAPD Ctrl */
6267 alc_write_coef_idx(codec, 0xd, val | (1<<14));
6268 break;
6269 }
6270}
David Henningsson6cb3b702010-09-09 08:51:44 +02006271
Takashi Iwai1d045db2011-07-07 18:23:21 +02006272/*
6273 */
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006274static int patch_alc662(struct hda_codec *codec)
6275{
6276 struct alc_spec *spec;
Takashi Iwai3de95172012-05-07 18:03:15 +02006277 int err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006278
Takashi Iwai3de95172012-05-07 18:03:15 +02006279 err = alc_alloc_spec(codec, 0x0b);
6280 if (err < 0)
6281 return err;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006282
Takashi Iwai3de95172012-05-07 18:03:15 +02006283 spec = codec->spec;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02006284
Takashi Iwai53c334a2011-08-23 18:27:14 +02006285 /* handle multiple HPs as is */
6286 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
6287
Takashi Iwai2c3bf9a2008-06-04 12:39:38 +02006288 alc_fix_pll_init(codec, 0x20, 0x04, 15);
6289
Kailang Yang8663ff72012-06-29 09:35:52 +02006290 spec->init_hook = alc662_fill_coef;
6291 alc662_fill_coef(codec);
6292
Takashi Iwai1727a772013-01-10 09:52:52 +01006293 snd_hda_pick_fixup(codec, alc662_fixup_models,
Takashi Iwai8e5a0502012-06-21 15:49:33 +02006294 alc662_fixup_tbl, alc662_fixups);
Hui Wang532895c2014-05-29 15:59:19 +08006295 snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups);
Takashi Iwai1727a772013-01-10 09:52:52 +01006296 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
Takashi Iwai8e5a0502012-06-21 15:49:33 +02006297
6298 alc_auto_parse_customize_define(codec);
6299
Takashi Iwai7504b6c2013-03-18 11:25:51 +01006300 if (has_cdefine_beep(codec))
6301 spec->gen.beep_nid = 0x01;
6302
Takashi Iwai1bb7e432011-10-17 16:50:59 +02006303 if ((alc_get_coef0(codec) & (1 << 14)) &&
Takashi Iwai5100cd02014-02-15 10:03:19 +01006304 codec->bus->pci && codec->bus->pci->subsystem_vendor == 0x1025 &&
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006305 spec->cdefine.platform_type == 1) {
Wei Yongjun6134b1a2013-04-18 11:12:59 +08006306 err = alc_codec_rename(codec, "ALC272X");
6307 if (err < 0)
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006308 goto error;
Takashi Iwai20ca0c32011-10-17 16:00:35 +02006309 }
Kailang Yang274693f2009-12-03 10:07:50 +01006310
Takashi Iwaib9c51062011-08-24 18:08:07 +02006311 /* automatic parse from the BIOS config */
6312 err = alc662_parse_auto_config(codec);
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006313 if (err < 0)
6314 goto error;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006315
Takashi Iwai7504b6c2013-03-18 11:25:51 +01006316 if (!spec->gen.no_analog && spec->gen.beep_nid) {
Kailang Yangda00c242010-03-19 11:23:45 +01006317 switch (codec->vendor_id) {
6318 case 0x10ec0662:
6319 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
6320 break;
6321 case 0x10ec0272:
6322 case 0x10ec0663:
6323 case 0x10ec0665:
Kailang Yang9ad54542013-11-26 15:41:40 +08006324 case 0x10ec0668:
Kailang Yangda00c242010-03-19 11:23:45 +01006325 set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
6326 break;
6327 case 0x10ec0273:
6328 set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
6329 break;
6330 }
Kailang Yangcec27c82010-02-04 14:18:18 +01006331 }
Takashi Iwai2134ea42008-01-10 16:53:55 +01006332
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006333 codec->patch_ops = alc_patch_ops;
Takashi Iwai1c7161532011-04-07 10:37:16 +02006334 spec->shutup = alc_eapd_shutup;
David Henningsson6cb3b702010-09-09 08:51:44 +02006335
Takashi Iwai1727a772013-01-10 09:52:52 +01006336 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Takashi Iwai589876e2012-02-20 15:47:55 +01006337
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006338 return 0;
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006339
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006340 error:
6341 alc_free(codec);
6342 return err;
Kailang Yangb478b992011-05-18 11:51:15 +02006343}
6344
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006345/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006346 * ALC680 support
6347 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006348
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006349static int alc680_parse_auto_config(struct hda_codec *codec)
6350{
Takashi Iwai3e6179b2011-07-08 16:55:13 +02006351 return alc_parse_auto_config(codec, NULL, NULL);
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006352}
6353
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006354/*
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006355 */
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006356static int patch_alc680(struct hda_codec *codec)
6357{
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006358 int err;
6359
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02006360 /* ALC680 has no aa-loopback mixer */
Takashi Iwai3de95172012-05-07 18:03:15 +02006361 err = alc_alloc_spec(codec, 0);
6362 if (err < 0)
6363 return err;
Takashi Iwai1f0f4b82011-06-27 10:52:59 +02006364
Takashi Iwai1ebec5f2011-08-15 13:21:48 +02006365 /* automatic parse from the BIOS config */
6366 err = alc680_parse_auto_config(codec);
6367 if (err < 0) {
6368 alc_free(codec);
6369 return err;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006370 }
6371
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006372 codec->patch_ops = alc_patch_ops;
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006373
6374 return 0;
6375}
6376
6377/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006378 * patch entries
6379 */
Takashi Iwaia9111322011-05-02 11:30:18 +02006380static const struct hda_codec_preset snd_hda_preset_realtek[] = {
Kailang Yang296f0332011-05-18 11:52:36 +02006381 { .id = 0x10ec0221, .name = "ALC221", .patch = patch_alc269 },
Kailang Yangba4c4d02013-11-26 15:17:50 +08006382 { .id = 0x10ec0231, .name = "ALC231", .patch = patch_alc269 },
Kailang Yang84dfd0a2013-03-07 09:19:38 +01006383 { .id = 0x10ec0233, .name = "ALC233", .patch = patch_alc269 },
Kailang Yang92f974d2014-06-06 17:05:33 +08006384 { .id = 0x10ec0235, .name = "ALC233", .patch = patch_alc269 },
Kailang Yang1d04c9d2013-10-24 11:35:18 +02006385 { .id = 0x10ec0255, .name = "ALC255", .patch = patch_alc269 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006386 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
Kailang Yangdf694da2005-12-05 19:42:22 +01006387 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
Kailang Yangf6a92242007-12-13 16:52:54 +01006388 { .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
Kailang Yanga361d842007-06-05 12:30:55 +02006389 { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 },
Kailang Yangf6a92242007-12-13 16:52:54 +01006390 { .id = 0x10ec0269, .name = "ALC269", .patch = patch_alc269 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01006391 { .id = 0x10ec0270, .name = "ALC270", .patch = patch_alc269 },
Kailang Yang01afd412008-10-15 11:22:09 +02006392 { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 },
Kailang Yangebb83ee2009-12-17 12:23:00 +01006393 { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 },
Kailang Yang296f0332011-05-18 11:52:36 +02006394 { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 },
David Henningssonbefae822012-06-25 19:49:28 +02006395 { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 },
David Henningsson4e01ec62012-07-18 07:38:46 +02006396 { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
Kailang Yang7ff34ad2012-10-06 17:02:30 +02006397 { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
Kailang Yang065380f2013-01-10 10:25:48 +01006398 { .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 },
Kailang Yang161ebf22013-10-24 11:36:33 +02006399 { .id = 0x10ec0285, .name = "ALC285", .patch = patch_alc269 },
Kailang Yang7fc7d042013-04-25 11:04:43 +02006400 { .id = 0x10ec0286, .name = "ALC286", .patch = patch_alc269 },
Kailang Yang7c665932014-04-14 15:09:44 +08006401 { .id = 0x10ec0288, .name = "ALC288", .patch = patch_alc269 },
Kailang Yang7ff34ad2012-10-06 17:02:30 +02006402 { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
David Henningssonaf02dde2012-11-21 08:57:58 +01006403 { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
Kailang Yang161ebf22013-10-24 11:36:33 +02006404 { .id = 0x10ec0293, .name = "ALC293", .patch = patch_alc269 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01006405 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006406 .patch = patch_alc861 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01006407 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
6408 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
6409 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006410 { .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
Takashi Iwai4953550a2009-06-30 15:28:30 +02006411 .patch = patch_alc882 },
Kailang Yangbc9f98a2007-04-12 13:06:07 +02006412 { .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
6413 .patch = patch_alc662 },
David Henningssoncc667a72011-10-18 14:07:51 +02006414 { .id = 0x10ec0662, .rev = 0x100300, .name = "ALC662 rev3",
6415 .patch = patch_alc662 },
Kailang Yang6dda9f42008-05-27 12:05:31 +02006416 { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
Kailang Yangcec27c82010-02-04 14:18:18 +01006417 { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
Kailang Yang72009432014-06-06 16:51:18 +08006418 { .id = 0x10ec0667, .name = "ALC667", .patch = patch_alc662 },
Kailang Yang19a62822012-11-08 10:25:37 +01006419 { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
Kailang Yang6227cdc2010-02-25 08:36:52 +01006420 { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
Rainer Koenig1d87caa2013-04-04 08:40:38 +02006421 { .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 },
Kailang Yangd1eb57f2010-06-23 16:25:26 +02006422 { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
Kailang Yangb6c5fba2014-06-05 11:13:44 +08006423 { .id = 0x10ec0867, .name = "ALC891", .patch = patch_alc882 },
Jakub Schmidtkef32610e2007-02-02 18:17:27 +01006424 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006425 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02006426 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
Clive Messer669faba2008-09-30 15:49:13 +02006427 { .id = 0x10ec0885, .rev = 0x100101, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +02006428 .patch = patch_alc882 },
Takashi Iwaicb308f92008-04-16 14:13:29 +02006429 { .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
Takashi Iwai4953550a2009-06-30 15:28:30 +02006430 .patch = patch_alc882 },
Kailang Yangdf694da2005-12-05 19:42:22 +01006431 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006432 { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
Kailang Yang44426082008-10-15 11:18:05 +02006433 { .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
Takashi Iwai4953550a2009-06-30 15:28:30 +02006434 .patch = patch_alc882 },
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006435 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc882 },
Takashi Iwai4953550a2009-06-30 15:28:30 +02006436 { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
Kailang Yang274693f2009-12-03 10:07:50 +01006437 { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
Takashi Iwaie16fb6d2011-10-17 16:39:09 +02006438 { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 },
Kailang Yang19a62822012-11-08 10:25:37 +01006439 { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07006440 {} /* terminator */
6441};
Takashi Iwai1289e9e2008-11-27 15:47:11 +01006442
6443MODULE_ALIAS("snd-hda-codec-id:10ec*");
6444
6445MODULE_LICENSE("GPL");
6446MODULE_DESCRIPTION("Realtek HD-audio codec");
6447
6448static struct hda_codec_preset_list realtek_list = {
6449 .preset = snd_hda_preset_realtek,
6450 .owner = THIS_MODULE,
6451};
6452
6453static int __init patch_realtek_init(void)
6454{
6455 return snd_hda_add_codec_preset(&realtek_list);
6456}
6457
6458static void __exit patch_realtek_exit(void)
6459{
6460 snd_hda_delete_codec_preset(&realtek_list);
6461}
6462
6463module_init(patch_realtek_init)
6464module_exit(patch_realtek_exit)