xref: /linux/sound/hda/codecs/realtek/alc662.c (revision ce76a36223b853dcb6e76da6f1c4f745c3f3f7ba)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 //
3 // Realtek ALC662 and compatible codecs
4 //
5 
6 #include <linux/init.h>
7 #include <linux/module.h>
8 #include "realtek.h"
9 
10 /*
11  * ALC662 support
12  *
13  * ALC662 is almost identical with ALC880 but has cleaner and more flexible
14  * configuration.  Each pin widget can choose any input DACs and a mixer.
15  * Each ADC is connected from a mixer of all inputs.  This makes possible
16  * 6-channel independent captures.
17  *
18  * In addition, an independent DAC for the multi-playback (not used in this
19  * driver yet).
20  */
21 
22 /*
23  * BIOS auto configuration
24  */
25 
alc662_parse_auto_config(struct hda_codec * codec)26 static int alc662_parse_auto_config(struct hda_codec *codec)
27 {
28 	static const hda_nid_t alc662_ignore[] = { 0x1d, 0 };
29 	static const hda_nid_t alc663_ssids[] = { 0x15, 0x1b, 0x14, 0x21 };
30 	static const hda_nid_t alc662_ssids[] = { 0x15, 0x1b, 0x14, 0 };
31 	const hda_nid_t *ssids;
32 
33 	if (codec->core.vendor_id == 0x10ec0272 || codec->core.vendor_id == 0x10ec0663 ||
34 	    codec->core.vendor_id == 0x10ec0665 || codec->core.vendor_id == 0x10ec0670 ||
35 	    codec->core.vendor_id == 0x10ec0671)
36 		ssids = alc663_ssids;
37 	else
38 		ssids = alc662_ssids;
39 	return alc_parse_auto_config(codec, alc662_ignore, ssids);
40 }
41 
alc272_fixup_mario(struct hda_codec * codec,const struct hda_fixup * fix,int action)42 static void alc272_fixup_mario(struct hda_codec *codec,
43 			       const struct hda_fixup *fix, int action)
44 {
45 	if (action != HDA_FIXUP_ACT_PRE_PROBE)
46 		return;
47 	if (snd_hda_override_amp_caps(codec, 0x2, HDA_OUTPUT,
48 				      (0x3b << AC_AMPCAP_OFFSET_SHIFT) |
49 				      (0x3b << AC_AMPCAP_NUM_STEPS_SHIFT) |
50 				      (0x03 << AC_AMPCAP_STEP_SIZE_SHIFT) |
51 				      (0 << AC_AMPCAP_MUTE_SHIFT)))
52 		codec_warn(codec, "failed to override amp caps for NID 0x2\n");
53 }
54 
55 /* avoid D3 for keeping GPIO up */
gpio_led_power_filter(struct hda_codec * codec,hda_nid_t nid,unsigned int power_state)56 static unsigned int gpio_led_power_filter(struct hda_codec *codec,
57 					  hda_nid_t nid,
58 					  unsigned int power_state)
59 {
60 	struct alc_spec *spec = codec->spec;
61 	if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_data)
62 		return AC_PWRST_D0;
63 	return power_state;
64 }
65 
alc662_fixup_led_gpio1(struct hda_codec * codec,const struct hda_fixup * fix,int action)66 static void alc662_fixup_led_gpio1(struct hda_codec *codec,
67 				   const struct hda_fixup *fix, int action)
68 {
69 	struct alc_spec *spec = codec->spec;
70 
71 	alc_fixup_hp_gpio_led(codec, action, 0x01, 0);
72 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
73 		spec->mute_led_polarity = 1;
74 		codec->power_filter = gpio_led_power_filter;
75 	}
76 }
77 
alc662_usi_automute_hook(struct hda_codec * codec,struct hda_jack_callback * jack)78 static void alc662_usi_automute_hook(struct hda_codec *codec,
79 					 struct hda_jack_callback *jack)
80 {
81 	struct alc_spec *spec = codec->spec;
82 	int vref;
83 	msleep(200);
84 	snd_hda_gen_hp_automute(codec, jack);
85 
86 	vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
87 	msleep(100);
88 	snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
89 			    vref);
90 }
91 
alc662_fixup_usi_headset_mic(struct hda_codec * codec,const struct hda_fixup * fix,int action)92 static void alc662_fixup_usi_headset_mic(struct hda_codec *codec,
93 				     const struct hda_fixup *fix, int action)
94 {
95 	struct alc_spec *spec = codec->spec;
96 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
97 		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
98 		spec->gen.hp_automute_hook = alc662_usi_automute_hook;
99 	}
100 }
101 
alc662_aspire_ethos_mute_speakers(struct hda_codec * codec,struct hda_jack_callback * cb)102 static void alc662_aspire_ethos_mute_speakers(struct hda_codec *codec,
103 					struct hda_jack_callback *cb)
104 {
105 	/* surround speakers at 0x1b already get muted automatically when
106 	 * headphones are plugged in, but we have to mute/unmute the remaining
107 	 * channels manually:
108 	 * 0x15 - front left/front right
109 	 * 0x18 - front center/ LFE
110 	 */
111 	if (snd_hda_jack_detect_state(codec, 0x1b) == HDA_JACK_PRESENT) {
112 		snd_hda_set_pin_ctl_cache(codec, 0x15, 0);
113 		snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
114 	} else {
115 		snd_hda_set_pin_ctl_cache(codec, 0x15, PIN_OUT);
116 		snd_hda_set_pin_ctl_cache(codec, 0x18, PIN_OUT);
117 	}
118 }
119 
alc662_fixup_aspire_ethos_hp(struct hda_codec * codec,const struct hda_fixup * fix,int action)120 static void alc662_fixup_aspire_ethos_hp(struct hda_codec *codec,
121 					const struct hda_fixup *fix, int action)
122 {
123     /* Pin 0x1b: shared headphones jack and surround speakers */
124 	if (!is_jack_detectable(codec, 0x1b))
125 		return;
126 
127 	switch (action) {
128 	case HDA_FIXUP_ACT_PRE_PROBE:
129 		snd_hda_jack_detect_enable_callback(codec, 0x1b,
130 				alc662_aspire_ethos_mute_speakers);
131 		/* subwoofer needs an extra GPIO setting to become audible */
132 		alc_setup_gpio(codec, 0x02);
133 		break;
134 	case HDA_FIXUP_ACT_INIT:
135 		/* Make sure to start in a correct state, i.e. if
136 		 * headphones have been plugged in before powering up the system
137 		 */
138 		alc662_aspire_ethos_mute_speakers(codec, NULL);
139 		break;
140 	}
141 }
142 
alc671_fixup_hp_headset_mic2(struct hda_codec * codec,const struct hda_fixup * fix,int action)143 static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec,
144 					     const struct hda_fixup *fix, int action)
145 {
146 	struct alc_spec *spec = codec->spec;
147 
148 	static const struct hda_pintbl pincfgs[] = {
149 		{ 0x19, 0x02a11040 }, /* use as headset mic, with its own jack detect */
150 		{ 0x1b, 0x0181304f },
151 		{ }
152 	};
153 
154 	switch (action) {
155 	case HDA_FIXUP_ACT_PRE_PROBE:
156 		spec->gen.mixer_nid = 0;
157 		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
158 		snd_hda_apply_pincfgs(codec, pincfgs);
159 		break;
160 	case HDA_FIXUP_ACT_INIT:
161 		alc_write_coef_idx(codec, 0x19, 0xa054);
162 		break;
163 	}
164 }
165 
alc897_hp_automute_hook(struct hda_codec * codec,struct hda_jack_callback * jack)166 static void alc897_hp_automute_hook(struct hda_codec *codec,
167 					 struct hda_jack_callback *jack)
168 {
169 	struct alc_spec *spec = codec->spec;
170 	int vref;
171 
172 	snd_hda_gen_hp_automute(codec, jack);
173 	vref = spec->gen.hp_jack_present ? (PIN_HP | AC_PINCTL_VREF_100) : PIN_HP;
174 	snd_hda_set_pin_ctl(codec, 0x1b, vref);
175 }
176 
alc897_fixup_lenovo_headset_mic(struct hda_codec * codec,const struct hda_fixup * fix,int action)177 static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec,
178 				     const struct hda_fixup *fix, int action)
179 {
180 	struct alc_spec *spec = codec->spec;
181 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
182 		spec->gen.hp_automute_hook = alc897_hp_automute_hook;
183 		spec->no_shutup_pins = 1;
184 	}
185 	if (action == HDA_FIXUP_ACT_PROBE) {
186 		snd_hda_set_pin_ctl_cache(codec, 0x1a, PIN_IN | AC_PINCTL_VREF_100);
187 	}
188 }
189 
alc897_fixup_lenovo_headset_mode(struct hda_codec * codec,const struct hda_fixup * fix,int action)190 static void alc897_fixup_lenovo_headset_mode(struct hda_codec *codec,
191 				     const struct hda_fixup *fix, int action)
192 {
193 	struct alc_spec *spec = codec->spec;
194 
195 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
196 		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
197 		spec->gen.hp_automute_hook = alc897_hp_automute_hook;
198 	}
199 }
200 
201 static const struct coef_fw alc668_coefs[] = {
202 	WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03,    0x0),
203 	WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06,    0x0), WRITE_COEF(0x07, 0x0f80),
204 	WRITE_COEF(0x08, 0x0031), WRITE_COEF(0x0a, 0x0060), WRITE_COEF(0x0b,    0x0),
205 	WRITE_COEF(0x0c, 0x7cf7), WRITE_COEF(0x0d, 0x1080), WRITE_COEF(0x0e, 0x7f7f),
206 	WRITE_COEF(0x0f, 0xcccc), WRITE_COEF(0x10, 0xddcc), WRITE_COEF(0x11, 0x0001),
207 	WRITE_COEF(0x13,    0x0), WRITE_COEF(0x14, 0x2aa0), WRITE_COEF(0x17, 0xa940),
208 	WRITE_COEF(0x19,    0x0), WRITE_COEF(0x1a,    0x0), WRITE_COEF(0x1b,    0x0),
209 	WRITE_COEF(0x1c,    0x0), WRITE_COEF(0x1d,    0x0), WRITE_COEF(0x1e, 0x7418),
210 	WRITE_COEF(0x1f, 0x0804), WRITE_COEF(0x20, 0x4200), WRITE_COEF(0x21, 0x0468),
211 	WRITE_COEF(0x22, 0x8ccc), WRITE_COEF(0x23, 0x0250), WRITE_COEF(0x24, 0x7418),
212 	WRITE_COEF(0x27,    0x0), WRITE_COEF(0x28, 0x8ccc), WRITE_COEF(0x2a, 0xff00),
213 	WRITE_COEF(0x2b, 0x8000), WRITE_COEF(0xa7, 0xff00), WRITE_COEF(0xa8, 0x8000),
214 	WRITE_COEF(0xaa, 0x2e17), WRITE_COEF(0xab, 0xa0c0), WRITE_COEF(0xac,    0x0),
215 	WRITE_COEF(0xad,    0x0), WRITE_COEF(0xae, 0x2ac6), WRITE_COEF(0xaf, 0xa480),
216 	WRITE_COEF(0xb0,    0x0), WRITE_COEF(0xb1,    0x0), WRITE_COEF(0xb2,    0x0),
217 	WRITE_COEF(0xb3,    0x0), WRITE_COEF(0xb4,    0x0), WRITE_COEF(0xb5, 0x1040),
218 	WRITE_COEF(0xb6, 0xd697), WRITE_COEF(0xb7, 0x902b), WRITE_COEF(0xb8, 0xd697),
219 	WRITE_COEF(0xb9, 0x902b), WRITE_COEF(0xba, 0xb8ba), WRITE_COEF(0xbb, 0xaaab),
220 	WRITE_COEF(0xbc, 0xaaaf), WRITE_COEF(0xbd, 0x6aaa), WRITE_COEF(0xbe, 0x1c02),
221 	WRITE_COEF(0xc0, 0x00ff), WRITE_COEF(0xc1, 0x0fa6),
222 	{}
223 };
224 
alc668_restore_default_value(struct hda_codec * codec)225 static void alc668_restore_default_value(struct hda_codec *codec)
226 {
227 	alc_process_coef_fw(codec, alc668_coefs);
228 }
229 
alc_fixup_headset_mode_alc662(struct hda_codec * codec,const struct hda_fixup * fix,int action)230 static void alc_fixup_headset_mode_alc662(struct hda_codec *codec,
231 				const struct hda_fixup *fix, int action)
232 {
233 	struct alc_spec *spec = codec->spec;
234 
235 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
236 		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
237 		spec->gen.hp_mic = 1; /* Mic-in is same pin as headphone */
238 
239 		/* Disable boost for mic-in permanently. (This code is only called
240 		   from quirks that guarantee that the headphone is at NID 0x1b.) */
241 		snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000);
242 		snd_hda_override_wcaps(codec, 0x1b, get_wcaps(codec, 0x1b) & ~AC_WCAP_IN_AMP);
243 	} else
244 		alc_fixup_headset_mode(codec, fix, action);
245 }
246 
alc_fixup_headset_mode_alc668(struct hda_codec * codec,const struct hda_fixup * fix,int action)247 static void alc_fixup_headset_mode_alc668(struct hda_codec *codec,
248 				const struct hda_fixup *fix, int action)
249 {
250 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
251 		alc_write_coef_idx(codec, 0xc4, 0x8000);
252 		alc_update_coef_idx(codec, 0xc2, ~0xfe, 0);
253 		snd_hda_set_pin_ctl_cache(codec, 0x18, 0);
254 	}
255 	alc_fixup_headset_mode(codec, fix, action);
256 }
257 
alc662_fixup_csl_amp(struct hda_codec * codec,const struct hda_fixup * fix,int action)258 static void alc662_fixup_csl_amp(struct hda_codec *codec,
259 				 const struct hda_fixup *fix, int action)
260 {
261 	if (action == HDA_FIXUP_ACT_INIT) {
262 		/* need to toggle GPIO to enable the amp */
263 		snd_hda_codec_set_gpio(codec, 0x03, 0x03, 0x03, 0);
264 		msleep(100);
265 		snd_hda_codec_set_gpio(codec, 0x03, 0x03, 0x00, 0);
266 	}
267 }
268 
269 enum {
270 	ALC662_FIXUP_ASPIRE,
271 	ALC662_FIXUP_LED_GPIO1,
272 	ALC662_FIXUP_IDEAPAD,
273 	ALC272_FIXUP_MARIO,
274 	ALC662_FIXUP_CZC_ET26,
275 	ALC662_FIXUP_CZC_P10T,
276 	ALC662_FIXUP_SKU_IGNORE,
277 	ALC662_FIXUP_HP_RP5800,
278 	ALC662_FIXUP_ASUS_MODE1,
279 	ALC662_FIXUP_ASUS_MODE2,
280 	ALC662_FIXUP_ASUS_MODE3,
281 	ALC662_FIXUP_ASUS_MODE4,
282 	ALC662_FIXUP_ASUS_MODE5,
283 	ALC662_FIXUP_ASUS_MODE6,
284 	ALC662_FIXUP_ASUS_MODE7,
285 	ALC662_FIXUP_ASUS_MODE8,
286 	ALC662_FIXUP_NO_JACK_DETECT,
287 	ALC662_FIXUP_ZOTAC_Z68,
288 	ALC662_FIXUP_INV_DMIC,
289 	ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
290 	ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
291 	ALC662_FIXUP_HEADSET_MODE,
292 	ALC668_FIXUP_HEADSET_MODE,
293 	ALC662_FIXUP_BASS_MODE4_CHMAP,
294 	ALC662_FIXUP_BASS_16,
295 	ALC662_FIXUP_BASS_1A,
296 	ALC662_FIXUP_BASS_CHMAP,
297 	ALC668_FIXUP_AUTO_MUTE,
298 	ALC668_FIXUP_DELL_DISABLE_AAMIX,
299 	ALC668_FIXUP_DELL_XPS13,
300 	ALC662_FIXUP_ASUS_Nx50,
301 	ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE,
302 	ALC668_FIXUP_ASUS_Nx51,
303 	ALC668_FIXUP_MIC_COEF,
304 	ALC668_FIXUP_ASUS_G751,
305 	ALC891_FIXUP_HEADSET_MODE,
306 	ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
307 	ALC662_FIXUP_ACER_VERITON,
308 	ALC892_FIXUP_ASROCK_MOBO,
309 	ALC662_FIXUP_USI_FUNC,
310 	ALC662_FIXUP_USI_HEADSET_MODE,
311 	ALC662_FIXUP_LENOVO_MULTI_CODECS,
312 	ALC669_FIXUP_ACER_ASPIRE_ETHOS,
313 	ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET,
314 	ALC671_FIXUP_HP_HEADSET_MIC2,
315 	ALC662_FIXUP_ACER_X2660G_HEADSET_MODE,
316 	ALC662_FIXUP_ACER_NITRO_HEADSET_MODE,
317 	ALC668_FIXUP_ASUS_NO_HEADSET_MIC,
318 	ALC668_FIXUP_HEADSET_MIC,
319 	ALC668_FIXUP_MIC_DET_COEF,
320 	ALC897_FIXUP_LENOVO_HEADSET_MIC,
321 	ALC897_FIXUP_HEADSET_MIC_PIN,
322 	ALC897_FIXUP_HP_HSMIC_VERB,
323 	ALC897_FIXUP_LENOVO_HEADSET_MODE,
324 	ALC897_FIXUP_HEADSET_MIC_PIN2,
325 	ALC897_FIXUP_UNIS_H3C_X500S,
326 	ALC897_FIXUP_HEADSET_MIC_PIN3,
327 	ALC662_FIXUP_CSL_GPIO,
328 };
329 
330 static const struct hda_fixup alc662_fixups[] = {
331 	[ALC662_FIXUP_ASPIRE] = {
332 		.type = HDA_FIXUP_PINS,
333 		.v.pins = (const struct hda_pintbl[]) {
334 			{ 0x15, 0x99130112 }, /* subwoofer */
335 			{ }
336 		}
337 	},
338 	[ALC662_FIXUP_LED_GPIO1] = {
339 		.type = HDA_FIXUP_FUNC,
340 		.v.func = alc662_fixup_led_gpio1,
341 	},
342 	[ALC662_FIXUP_IDEAPAD] = {
343 		.type = HDA_FIXUP_PINS,
344 		.v.pins = (const struct hda_pintbl[]) {
345 			{ 0x17, 0x99130112 }, /* subwoofer */
346 			{ }
347 		},
348 		.chained = true,
349 		.chain_id = ALC662_FIXUP_LED_GPIO1,
350 	},
351 	[ALC272_FIXUP_MARIO] = {
352 		.type = HDA_FIXUP_FUNC,
353 		.v.func = alc272_fixup_mario,
354 	},
355 	[ALC662_FIXUP_CZC_ET26] = {
356 		.type = HDA_FIXUP_PINS,
357 		.v.pins = (const struct hda_pintbl[]) {
358 			{0x12, 0x403cc000},
359 			{0x14, 0x90170110}, /* speaker */
360 			{0x15, 0x411111f0},
361 			{0x16, 0x411111f0},
362 			{0x18, 0x01a19030}, /* mic */
363 			{0x19, 0x90a7013f}, /* int-mic */
364 			{0x1a, 0x01014020},
365 			{0x1b, 0x0121401f},
366 			{0x1c, 0x411111f0},
367 			{0x1d, 0x411111f0},
368 			{0x1e, 0x40478e35},
369 			{}
370 		},
371 		.chained = true,
372 		.chain_id = ALC662_FIXUP_SKU_IGNORE
373 	},
374 	[ALC662_FIXUP_CZC_P10T] = {
375 		.type = HDA_FIXUP_VERBS,
376 		.v.verbs = (const struct hda_verb[]) {
377 			{0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
378 			{}
379 		}
380 	},
381 	[ALC662_FIXUP_SKU_IGNORE] = {
382 		.type = HDA_FIXUP_FUNC,
383 		.v.func = alc_fixup_sku_ignore,
384 	},
385 	[ALC662_FIXUP_HP_RP5800] = {
386 		.type = HDA_FIXUP_PINS,
387 		.v.pins = (const struct hda_pintbl[]) {
388 			{ 0x14, 0x0221201f }, /* HP out */
389 			{ }
390 		},
391 		.chained = true,
392 		.chain_id = ALC662_FIXUP_SKU_IGNORE
393 	},
394 	[ALC662_FIXUP_ASUS_MODE1] = {
395 		.type = HDA_FIXUP_PINS,
396 		.v.pins = (const struct hda_pintbl[]) {
397 			{ 0x14, 0x99130110 }, /* speaker */
398 			{ 0x18, 0x01a19c20 }, /* mic */
399 			{ 0x19, 0x99a3092f }, /* int-mic */
400 			{ 0x21, 0x0121401f }, /* HP out */
401 			{ }
402 		},
403 		.chained = true,
404 		.chain_id = ALC662_FIXUP_SKU_IGNORE
405 	},
406 	[ALC662_FIXUP_ASUS_MODE2] = {
407 		.type = HDA_FIXUP_PINS,
408 		.v.pins = (const struct hda_pintbl[]) {
409 			{ 0x14, 0x99130110 }, /* speaker */
410 			{ 0x18, 0x01a19820 }, /* mic */
411 			{ 0x19, 0x99a3092f }, /* int-mic */
412 			{ 0x1b, 0x0121401f }, /* HP out */
413 			{ }
414 		},
415 		.chained = true,
416 		.chain_id = ALC662_FIXUP_SKU_IGNORE
417 	},
418 	[ALC662_FIXUP_ASUS_MODE3] = {
419 		.type = HDA_FIXUP_PINS,
420 		.v.pins = (const struct hda_pintbl[]) {
421 			{ 0x14, 0x99130110 }, /* speaker */
422 			{ 0x15, 0x0121441f }, /* HP */
423 			{ 0x18, 0x01a19840 }, /* mic */
424 			{ 0x19, 0x99a3094f }, /* int-mic */
425 			{ 0x21, 0x01211420 }, /* HP2 */
426 			{ }
427 		},
428 		.chained = true,
429 		.chain_id = ALC662_FIXUP_SKU_IGNORE
430 	},
431 	[ALC662_FIXUP_ASUS_MODE4] = {
432 		.type = HDA_FIXUP_PINS,
433 		.v.pins = (const struct hda_pintbl[]) {
434 			{ 0x14, 0x99130110 }, /* speaker */
435 			{ 0x16, 0x99130111 }, /* speaker */
436 			{ 0x18, 0x01a19840 }, /* mic */
437 			{ 0x19, 0x99a3094f }, /* int-mic */
438 			{ 0x21, 0x0121441f }, /* HP */
439 			{ }
440 		},
441 		.chained = true,
442 		.chain_id = ALC662_FIXUP_SKU_IGNORE
443 	},
444 	[ALC662_FIXUP_ASUS_MODE5] = {
445 		.type = HDA_FIXUP_PINS,
446 		.v.pins = (const struct hda_pintbl[]) {
447 			{ 0x14, 0x99130110 }, /* speaker */
448 			{ 0x15, 0x0121441f }, /* HP */
449 			{ 0x16, 0x99130111 }, /* speaker */
450 			{ 0x18, 0x01a19840 }, /* mic */
451 			{ 0x19, 0x99a3094f }, /* int-mic */
452 			{ }
453 		},
454 		.chained = true,
455 		.chain_id = ALC662_FIXUP_SKU_IGNORE
456 	},
457 	[ALC662_FIXUP_ASUS_MODE6] = {
458 		.type = HDA_FIXUP_PINS,
459 		.v.pins = (const struct hda_pintbl[]) {
460 			{ 0x14, 0x99130110 }, /* speaker */
461 			{ 0x15, 0x01211420 }, /* HP2 */
462 			{ 0x18, 0x01a19840 }, /* mic */
463 			{ 0x19, 0x99a3094f }, /* int-mic */
464 			{ 0x1b, 0x0121441f }, /* HP */
465 			{ }
466 		},
467 		.chained = true,
468 		.chain_id = ALC662_FIXUP_SKU_IGNORE
469 	},
470 	[ALC662_FIXUP_ASUS_MODE7] = {
471 		.type = HDA_FIXUP_PINS,
472 		.v.pins = (const struct hda_pintbl[]) {
473 			{ 0x14, 0x99130110 }, /* speaker */
474 			{ 0x17, 0x99130111 }, /* speaker */
475 			{ 0x18, 0x01a19840 }, /* mic */
476 			{ 0x19, 0x99a3094f }, /* int-mic */
477 			{ 0x1b, 0x01214020 }, /* HP */
478 			{ 0x21, 0x0121401f }, /* HP */
479 			{ }
480 		},
481 		.chained = true,
482 		.chain_id = ALC662_FIXUP_SKU_IGNORE
483 	},
484 	[ALC662_FIXUP_ASUS_MODE8] = {
485 		.type = HDA_FIXUP_PINS,
486 		.v.pins = (const struct hda_pintbl[]) {
487 			{ 0x14, 0x99130110 }, /* speaker */
488 			{ 0x12, 0x99a30970 }, /* int-mic */
489 			{ 0x15, 0x01214020 }, /* HP */
490 			{ 0x17, 0x99130111 }, /* speaker */
491 			{ 0x18, 0x01a19840 }, /* mic */
492 			{ 0x21, 0x0121401f }, /* HP */
493 			{ }
494 		},
495 		.chained = true,
496 		.chain_id = ALC662_FIXUP_SKU_IGNORE
497 	},
498 	[ALC662_FIXUP_NO_JACK_DETECT] = {
499 		.type = HDA_FIXUP_FUNC,
500 		.v.func = alc_fixup_no_jack_detect,
501 	},
502 	[ALC662_FIXUP_ZOTAC_Z68] = {
503 		.type = HDA_FIXUP_PINS,
504 		.v.pins = (const struct hda_pintbl[]) {
505 			{ 0x1b, 0x02214020 }, /* Front HP */
506 			{ }
507 		}
508 	},
509 	[ALC662_FIXUP_INV_DMIC] = {
510 		.type = HDA_FIXUP_FUNC,
511 		.v.func = alc_fixup_inv_dmic,
512 	},
513 	[ALC668_FIXUP_DELL_XPS13] = {
514 		.type = HDA_FIXUP_FUNC,
515 		.v.func = alc_fixup_dell_xps13,
516 		.chained = true,
517 		.chain_id = ALC668_FIXUP_DELL_DISABLE_AAMIX
518 	},
519 	[ALC668_FIXUP_DELL_DISABLE_AAMIX] = {
520 		.type = HDA_FIXUP_FUNC,
521 		.v.func = alc_fixup_disable_aamix,
522 		.chained = true,
523 		.chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
524 	},
525 	[ALC668_FIXUP_AUTO_MUTE] = {
526 		.type = HDA_FIXUP_FUNC,
527 		.v.func = alc_fixup_auto_mute_via_amp,
528 		.chained = true,
529 		.chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
530 	},
531 	[ALC662_FIXUP_DELL_MIC_NO_PRESENCE] = {
532 		.type = HDA_FIXUP_PINS,
533 		.v.pins = (const struct hda_pintbl[]) {
534 			{ 0x19, 0x03a1113c }, /* use as headset mic, without its own jack detect */
535 			/* headphone mic by setting pin control of 0x1b (headphone out) to in + vref_50 */
536 			{ }
537 		},
538 		.chained = true,
539 		.chain_id = ALC662_FIXUP_HEADSET_MODE
540 	},
541 	[ALC662_FIXUP_HEADSET_MODE] = {
542 		.type = HDA_FIXUP_FUNC,
543 		.v.func = alc_fixup_headset_mode_alc662,
544 	},
545 	[ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
546 		.type = HDA_FIXUP_PINS,
547 		.v.pins = (const struct hda_pintbl[]) {
548 			{ 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
549 			{ 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
550 			{ }
551 		},
552 		.chained = true,
553 		.chain_id = ALC668_FIXUP_HEADSET_MODE
554 	},
555 	[ALC668_FIXUP_HEADSET_MODE] = {
556 		.type = HDA_FIXUP_FUNC,
557 		.v.func = alc_fixup_headset_mode_alc668,
558 	},
559 	[ALC662_FIXUP_BASS_MODE4_CHMAP] = {
560 		.type = HDA_FIXUP_FUNC,
561 		.v.func = alc_fixup_bass_chmap,
562 		.chained = true,
563 		.chain_id = ALC662_FIXUP_ASUS_MODE4
564 	},
565 	[ALC662_FIXUP_BASS_16] = {
566 		.type = HDA_FIXUP_PINS,
567 		.v.pins = (const struct hda_pintbl[]) {
568 			{0x16, 0x80106111}, /* bass speaker */
569 			{}
570 		},
571 		.chained = true,
572 		.chain_id = ALC662_FIXUP_BASS_CHMAP,
573 	},
574 	[ALC662_FIXUP_BASS_1A] = {
575 		.type = HDA_FIXUP_PINS,
576 		.v.pins = (const struct hda_pintbl[]) {
577 			{0x1a, 0x80106111}, /* bass speaker */
578 			{}
579 		},
580 		.chained = true,
581 		.chain_id = ALC662_FIXUP_BASS_CHMAP,
582 	},
583 	[ALC662_FIXUP_BASS_CHMAP] = {
584 		.type = HDA_FIXUP_FUNC,
585 		.v.func = alc_fixup_bass_chmap,
586 	},
587 	[ALC662_FIXUP_ASUS_Nx50] = {
588 		.type = HDA_FIXUP_FUNC,
589 		.v.func = alc_fixup_auto_mute_via_amp,
590 		.chained = true,
591 		.chain_id = ALC662_FIXUP_BASS_1A
592 	},
593 	[ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE] = {
594 		.type = HDA_FIXUP_FUNC,
595 		.v.func = alc_fixup_headset_mode_alc668,
596 		.chain_id = ALC662_FIXUP_BASS_CHMAP
597 	},
598 	[ALC668_FIXUP_ASUS_Nx51] = {
599 		.type = HDA_FIXUP_PINS,
600 		.v.pins = (const struct hda_pintbl[]) {
601 			{ 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
602 			{ 0x1a, 0x90170151 }, /* bass speaker */
603 			{ 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
604 			{}
605 		},
606 		.chained = true,
607 		.chain_id = ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE,
608 	},
609 	[ALC668_FIXUP_MIC_COEF] = {
610 		.type = HDA_FIXUP_VERBS,
611 		.v.verbs = (const struct hda_verb[]) {
612 			{ 0x20, AC_VERB_SET_COEF_INDEX, 0xc3 },
613 			{ 0x20, AC_VERB_SET_PROC_COEF, 0x4000 },
614 			{}
615 		},
616 	},
617 	[ALC668_FIXUP_ASUS_G751] = {
618 		.type = HDA_FIXUP_PINS,
619 		.v.pins = (const struct hda_pintbl[]) {
620 			{ 0x16, 0x0421101f }, /* HP */
621 			{}
622 		},
623 		.chained = true,
624 		.chain_id = ALC668_FIXUP_MIC_COEF
625 	},
626 	[ALC891_FIXUP_HEADSET_MODE] = {
627 		.type = HDA_FIXUP_FUNC,
628 		.v.func = alc_fixup_headset_mode,
629 	},
630 	[ALC891_FIXUP_DELL_MIC_NO_PRESENCE] = {
631 		.type = HDA_FIXUP_PINS,
632 		.v.pins = (const struct hda_pintbl[]) {
633 			{ 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
634 			{ 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
635 			{ }
636 		},
637 		.chained = true,
638 		.chain_id = ALC891_FIXUP_HEADSET_MODE
639 	},
640 	[ALC662_FIXUP_ACER_VERITON] = {
641 		.type = HDA_FIXUP_PINS,
642 		.v.pins = (const struct hda_pintbl[]) {
643 			{ 0x15, 0x50170120 }, /* no internal speaker */
644 			{ }
645 		}
646 	},
647 	[ALC892_FIXUP_ASROCK_MOBO] = {
648 		.type = HDA_FIXUP_PINS,
649 		.v.pins = (const struct hda_pintbl[]) {
650 			{ 0x15, 0x40f000f0 }, /* disabled */
651 			{ 0x16, 0x40f000f0 }, /* disabled */
652 			{ }
653 		}
654 	},
655 	[ALC662_FIXUP_USI_FUNC] = {
656 		.type = HDA_FIXUP_FUNC,
657 		.v.func = alc662_fixup_usi_headset_mic,
658 	},
659 	[ALC662_FIXUP_USI_HEADSET_MODE] = {
660 		.type = HDA_FIXUP_PINS,
661 		.v.pins = (const struct hda_pintbl[]) {
662 			{ 0x19, 0x02a1913c }, /* use as headset mic, without its own jack detect */
663 			{ 0x18, 0x01a1903d },
664 			{ }
665 		},
666 		.chained = true,
667 		.chain_id = ALC662_FIXUP_USI_FUNC
668 	},
669 	[ALC662_FIXUP_LENOVO_MULTI_CODECS] = {
670 		.type = HDA_FIXUP_FUNC,
671 		.v.func = alc233_alc662_fixup_lenovo_dual_codecs,
672 	},
673 	[ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET] = {
674 		.type = HDA_FIXUP_FUNC,
675 		.v.func = alc662_fixup_aspire_ethos_hp,
676 	},
677 	[ALC669_FIXUP_ACER_ASPIRE_ETHOS] = {
678 		.type = HDA_FIXUP_PINS,
679 		.v.pins = (const struct hda_pintbl[]) {
680 			{ 0x15, 0x92130110 }, /* front speakers */
681 			{ 0x18, 0x99130111 }, /* center/subwoofer */
682 			{ 0x1b, 0x11130012 }, /* surround plus jack for HP */
683 			{ }
684 		},
685 		.chained = true,
686 		.chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET
687 	},
688 	[ALC671_FIXUP_HP_HEADSET_MIC2] = {
689 		.type = HDA_FIXUP_FUNC,
690 		.v.func = alc671_fixup_hp_headset_mic2,
691 	},
692 	[ALC662_FIXUP_ACER_X2660G_HEADSET_MODE] = {
693 		.type = HDA_FIXUP_PINS,
694 		.v.pins = (const struct hda_pintbl[]) {
695 			{ 0x1a, 0x02a1113c }, /* use as headset mic, without its own jack detect */
696 			{ }
697 		},
698 		.chained = true,
699 		.chain_id = ALC662_FIXUP_USI_FUNC
700 	},
701 	[ALC662_FIXUP_ACER_NITRO_HEADSET_MODE] = {
702 		.type = HDA_FIXUP_PINS,
703 		.v.pins = (const struct hda_pintbl[]) {
704 			{ 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */
705 			{ 0x1b, 0x0221144f },
706 			{ }
707 		},
708 		.chained = true,
709 		.chain_id = ALC662_FIXUP_USI_FUNC
710 	},
711 	[ALC668_FIXUP_ASUS_NO_HEADSET_MIC] = {
712 		.type = HDA_FIXUP_PINS,
713 		.v.pins = (const struct hda_pintbl[]) {
714 			{ 0x1b, 0x04a1112c },
715 			{ }
716 		},
717 		.chained = true,
718 		.chain_id = ALC668_FIXUP_HEADSET_MIC
719 	},
720 	[ALC668_FIXUP_HEADSET_MIC] = {
721 		.type = HDA_FIXUP_FUNC,
722 		.v.func = alc_fixup_headset_mic,
723 		.chained = true,
724 		.chain_id = ALC668_FIXUP_MIC_DET_COEF
725 	},
726 	[ALC668_FIXUP_MIC_DET_COEF] = {
727 		.type = HDA_FIXUP_VERBS,
728 		.v.verbs = (const struct hda_verb[]) {
729 			{ 0x20, AC_VERB_SET_COEF_INDEX, 0x15 },
730 			{ 0x20, AC_VERB_SET_PROC_COEF, 0x0d60 },
731 			{}
732 		},
733 	},
734 	[ALC897_FIXUP_LENOVO_HEADSET_MIC] = {
735 		.type = HDA_FIXUP_FUNC,
736 		.v.func = alc897_fixup_lenovo_headset_mic,
737 	},
738 	[ALC897_FIXUP_HEADSET_MIC_PIN] = {
739 		.type = HDA_FIXUP_PINS,
740 		.v.pins = (const struct hda_pintbl[]) {
741 			{ 0x1a, 0x03a11050 },
742 			{ }
743 		},
744 		.chained = true,
745 		.chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC
746 	},
747 	[ALC897_FIXUP_HP_HSMIC_VERB] = {
748 		.type = HDA_FIXUP_PINS,
749 		.v.pins = (const struct hda_pintbl[]) {
750 			{ 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
751 			{ }
752 		},
753 	},
754 	[ALC897_FIXUP_LENOVO_HEADSET_MODE] = {
755 		.type = HDA_FIXUP_FUNC,
756 		.v.func = alc897_fixup_lenovo_headset_mode,
757 	},
758 	[ALC897_FIXUP_HEADSET_MIC_PIN2] = {
759 		.type = HDA_FIXUP_PINS,
760 		.v.pins = (const struct hda_pintbl[]) {
761 			{ 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */
762 			{ }
763 		},
764 		.chained = true,
765 		.chain_id = ALC897_FIXUP_LENOVO_HEADSET_MODE
766 	},
767 	[ALC897_FIXUP_UNIS_H3C_X500S] = {
768 		.type = HDA_FIXUP_VERBS,
769 		.v.verbs = (const struct hda_verb[]) {
770 			{ 0x14, AC_VERB_SET_EAPD_BTLENABLE, 0 },
771 			{}
772 		},
773 	},
774 	[ALC897_FIXUP_HEADSET_MIC_PIN3] = {
775 		.type = HDA_FIXUP_PINS,
776 		.v.pins = (const struct hda_pintbl[]) {
777 			{ 0x19, 0x03a11050 }, /* use as headset mic */
778 			{ }
779 		},
780 	},
781 	[ALC662_FIXUP_CSL_GPIO] = {
782 		.type = HDA_FIXUP_FUNC,
783 		.v.func = alc662_fixup_csl_amp,
784 	},
785 };
786 
787 static const struct hda_quirk alc662_fixup_tbl[] = {
788 	SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
789 	SND_PCI_QUIRK(0x1019, 0x9859, "JP-IK LEAP W502", ALC897_FIXUP_HEADSET_MIC_PIN3),
790 	SND_PCI_QUIRK(0x1022, 0xc950, "CSL Unity BF24B", ALC662_FIXUP_CSL_GPIO),
791 	SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
792 	SND_PCI_QUIRK(0x1025, 0x0241, "Packard Bell DOTS", ALC662_FIXUP_INV_DMIC),
793 	SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
794 	SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
795 	SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
796 	SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
797 	SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
798 	SND_PCI_QUIRK(0x1025, 0x0566, "Acer Aspire Ethos 8951G", ALC669_FIXUP_ACER_ASPIRE_ETHOS),
799 	SND_PCI_QUIRK(0x1025, 0x123c, "Acer Nitro N50-600", ALC662_FIXUP_ACER_NITRO_HEADSET_MODE),
800 	SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE),
801 	SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
802 	SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
803 	SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13),
804 	SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13),
805 	SND_PCI_QUIRK(0x1028, 0x060d, "Dell M3800", ALC668_FIXUP_DELL_XPS13),
806 	SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
807 	SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
808 	SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
809 	SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
810 	SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
811 	SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
812 	SND_PCI_QUIRK(0x103c, 0x870c, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
813 	SND_PCI_QUIRK(0x103c, 0x8719, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
814 	SND_PCI_QUIRK(0x103c, 0x872b, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
815 	SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2),
816 	SND_PCI_QUIRK(0x103c, 0x8768, "HP Slim Desktop S01", ALC671_FIXUP_HP_HEADSET_MIC2),
817 	SND_PCI_QUIRK(0x103c, 0x877e, "HP 288 Pro G6", ALC671_FIXUP_HP_HEADSET_MIC2),
818 	SND_PCI_QUIRK(0x103c, 0x885f, "HP 288 Pro G8", ALC671_FIXUP_HP_HEADSET_MIC2),
819 	SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE),
820 	SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50),
821 	SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50),
822 	SND_PCI_QUIRK(0x1043, 0x12ff, "ASUS G751", ALC668_FIXUP_ASUS_G751),
823 	SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A),
824 	SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
825 	SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
826 	SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51),
827 	SND_PCI_QUIRK(0x1043, 0x17bd, "ASUS N751", ALC668_FIXUP_ASUS_Nx51),
828 	SND_PCI_QUIRK(0x1043, 0x185d, "ASUS G551JW", ALC668_FIXUP_ASUS_NO_HEADSET_MIC),
829 	SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71SL", ALC662_FIXUP_ASUS_MODE8),
830 	SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
831 	SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
832 	SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
833 	SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
834 	SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
835 	SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE),
836 	SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS),
837 	SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN),
838 	SND_PCI_QUIRK(0x17aa, 0x1064, "Lenovo P3 Tower", ALC897_FIXUP_HEADSET_MIC_PIN),
839 	SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN),
840 	SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
841 	SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
842 	SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
843 	SND_PCI_QUIRK(0x17aa, 0x3321, "Lenovo ThinkCentre M70 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
844 	SND_PCI_QUIRK(0x17aa, 0x331b, "Lenovo ThinkCentre M90 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
845 	SND_PCI_QUIRK(0x17aa, 0x3364, "Lenovo ThinkCentre M90 Gen5", ALC897_FIXUP_HEADSET_MIC_PIN),
846 	SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2),
847 	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
848 	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
849 	SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),
850 	SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68),
851 	SND_PCI_QUIRK(0x1b0a, 0x01b8, "ACER Veriton", ALC662_FIXUP_ACER_VERITON),
852 	SND_PCI_QUIRK(0x1b35, 0x1234, "CZC ET26", ALC662_FIXUP_CZC_ET26),
853 	SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
854 	SND_PCI_QUIRK(0x1c6c, 0x1239, "Compaq N14JP6-V2", ALC897_FIXUP_HP_HSMIC_VERB),
855 
856 #if 0
857 	/* Below is a quirk table taken from the old code.
858 	 * Basically the device should work as is without the fixup table.
859 	 * If BIOS doesn't give a proper info, enable the corresponding
860 	 * fixup entry.
861 	 */
862 	SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
863 	SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
864 	SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
865 	SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
866 	SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
867 	SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
868 	SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
869 	SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
870 	SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
871 	SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
872 	SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
873 	SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
874 	SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
875 	SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
876 	SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
877 	SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
878 	SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
879 	SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
880 	SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
881 	SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
882 	SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
883 	SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
884 	SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
885 	SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
886 	SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
887 	SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
888 	SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
889 	SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
890 	SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
891 	SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
892 	SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
893 	SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
894 	SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
895 	SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
896 	SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
897 	SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
898 	SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
899 	SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
900 	SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
901 	SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
902 	SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
903 	SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
904 	SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
905 	SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
906 	SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
907 	SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
908 	SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
909 	SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
910 	SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
911 	SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
912 #endif
913 	{}
914 };
915 
916 static const struct hda_model_fixup alc662_fixup_models[] = {
917 	{.id = ALC662_FIXUP_ASPIRE, .name = "aspire"},
918 	{.id = ALC662_FIXUP_IDEAPAD, .name = "ideapad"},
919 	{.id = ALC272_FIXUP_MARIO, .name = "mario"},
920 	{.id = ALC662_FIXUP_HP_RP5800, .name = "hp-rp5800"},
921 	{.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
922 	{.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
923 	{.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
924 	{.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
925 	{.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
926 	{.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
927 	{.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
928 	{.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
929 	{.id = ALC662_FIXUP_ZOTAC_Z68, .name = "zotac-z68"},
930 	{.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
931 	{.id = ALC662_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc662-headset-multi"},
932 	{.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
933 	{.id = ALC662_FIXUP_HEADSET_MODE, .name = "alc662-headset"},
934 	{.id = ALC668_FIXUP_HEADSET_MODE, .name = "alc668-headset"},
935 	{.id = ALC662_FIXUP_BASS_16, .name = "bass16"},
936 	{.id = ALC662_FIXUP_BASS_1A, .name = "bass1a"},
937 	{.id = ALC668_FIXUP_AUTO_MUTE, .name = "automute"},
938 	{.id = ALC668_FIXUP_DELL_XPS13, .name = "dell-xps13"},
939 	{.id = ALC662_FIXUP_ASUS_Nx50, .name = "asus-nx50"},
940 	{.id = ALC668_FIXUP_ASUS_Nx51, .name = "asus-nx51"},
941 	{.id = ALC668_FIXUP_ASUS_G751, .name = "asus-g751"},
942 	{.id = ALC891_FIXUP_HEADSET_MODE, .name = "alc891-headset"},
943 	{.id = ALC891_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc891-headset-multi"},
944 	{.id = ALC662_FIXUP_ACER_VERITON, .name = "acer-veriton"},
945 	{.id = ALC892_FIXUP_ASROCK_MOBO, .name = "asrock-mobo"},
946 	{.id = ALC662_FIXUP_USI_HEADSET_MODE, .name = "usi-headset"},
947 	{.id = ALC662_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"},
948 	{.id = ALC669_FIXUP_ACER_ASPIRE_ETHOS, .name = "aspire-ethos"},
949 	{.id = ALC897_FIXUP_UNIS_H3C_X500S, .name = "unis-h3c-x500s"},
950 	{}
951 };
952 
953 static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = {
954 	SND_HDA_PIN_QUIRK(0x10ec0867, 0x1028, "Dell", ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
955 		{0x17, 0x02211010},
956 		{0x18, 0x01a19030},
957 		{0x1a, 0x01813040},
958 		{0x21, 0x01014020}),
959 	SND_HDA_PIN_QUIRK(0x10ec0867, 0x1028, "Dell", ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
960 		{0x16, 0x01813030},
961 		{0x17, 0x02211010},
962 		{0x18, 0x01a19040},
963 		{0x21, 0x01014020}),
964 	SND_HDA_PIN_QUIRK(0x10ec0662, 0x1028, "Dell", ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
965 		{0x14, 0x01014010},
966 		{0x18, 0x01a19020},
967 		{0x1a, 0x0181302f},
968 		{0x1b, 0x0221401f}),
969 	SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
970 		{0x12, 0x99a30130},
971 		{0x14, 0x90170110},
972 		{0x15, 0x0321101f},
973 		{0x16, 0x03011020}),
974 	SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
975 		{0x12, 0x99a30140},
976 		{0x14, 0x90170110},
977 		{0x15, 0x0321101f},
978 		{0x16, 0x03011020}),
979 	SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
980 		{0x12, 0x99a30150},
981 		{0x14, 0x90170110},
982 		{0x15, 0x0321101f},
983 		{0x16, 0x03011020}),
984 	SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
985 		{0x14, 0x90170110},
986 		{0x15, 0x0321101f},
987 		{0x16, 0x03011020}),
988 	SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell XPS 15", ALC668_FIXUP_AUTO_MUTE,
989 		{0x12, 0x90a60130},
990 		{0x14, 0x90170110},
991 		{0x15, 0x0321101f}),
992 	SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
993 		{0x14, 0x01014010},
994 		{0x17, 0x90170150},
995 		{0x19, 0x02a11060},
996 		{0x1b, 0x01813030},
997 		{0x21, 0x02211020}),
998 	SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
999 		{0x14, 0x01014010},
1000 		{0x18, 0x01a19040},
1001 		{0x1b, 0x01813030},
1002 		{0x21, 0x02211020}),
1003 	SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
1004 		{0x14, 0x01014020},
1005 		{0x17, 0x90170110},
1006 		{0x18, 0x01a19050},
1007 		{0x1b, 0x01813040},
1008 		{0x21, 0x02211030}),
1009 	{}
1010 };
1011 
1012 /*
1013  */
alc662_probe(struct hda_codec * codec,const struct hda_device_id * id)1014 static int alc662_probe(struct hda_codec *codec, const struct hda_device_id *id)
1015 {
1016 	struct alc_spec *spec;
1017 	int err;
1018 
1019 	err = alc_alloc_spec(codec, 0x0b);
1020 	if (err < 0)
1021 		return err;
1022 
1023 	spec = codec->spec;
1024 
1025 	spec->shutup = alc_eapd_shutup;
1026 
1027 	/* handle multiple HPs as is */
1028 	spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
1029 
1030 	alc_fix_pll_init(codec, 0x20, 0x04, 15);
1031 
1032 	switch (codec->core.vendor_id) {
1033 	case 0x10ec0668:
1034 		spec->init_hook = alc668_restore_default_value;
1035 		break;
1036 	}
1037 
1038 	alc_pre_init(codec);
1039 
1040 	snd_hda_pick_fixup(codec, alc662_fixup_models,
1041 		       alc662_fixup_tbl, alc662_fixups);
1042 	snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups, true);
1043 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1044 
1045 	alc_auto_parse_customize_define(codec);
1046 
1047 	if (has_cdefine_beep(codec))
1048 		spec->gen.beep_nid = 0x01;
1049 
1050 	if ((alc_get_coef0(codec) & (1 << 14)) &&
1051 	    codec->bus->pci && codec->bus->pci->subsystem_vendor == 0x1025 &&
1052 	    spec->cdefine.platform_type == 1) {
1053 		err = alc_codec_rename(codec, "ALC272X");
1054 		if (err < 0)
1055 			goto error;
1056 	}
1057 
1058 	/* automatic parse from the BIOS config */
1059 	err = alc662_parse_auto_config(codec);
1060 	if (err < 0)
1061 		goto error;
1062 
1063 	if (!spec->gen.no_analog && spec->gen.beep_nid) {
1064 		switch (codec->core.vendor_id) {
1065 		case 0x10ec0662:
1066 			err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
1067 			break;
1068 		case 0x10ec0272:
1069 		case 0x10ec0663:
1070 		case 0x10ec0665:
1071 		case 0x10ec0668:
1072 			err = set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
1073 			break;
1074 		case 0x10ec0273:
1075 			err = set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
1076 			break;
1077 		}
1078 		if (err < 0)
1079 			goto error;
1080 	}
1081 
1082 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
1083 
1084 	return 0;
1085 
1086  error:
1087 	snd_hda_gen_remove(codec);
1088 	return err;
1089 }
1090 
1091 static const struct hda_codec_ops alc662_codec_ops = {
1092 	.probe = alc662_probe,
1093 	.remove = snd_hda_gen_remove,
1094 	.build_controls = alc_build_controls,
1095 	.build_pcms = snd_hda_gen_build_pcms,
1096 	.init = alc_init,
1097 	.unsol_event = snd_hda_jack_unsol_event,
1098 	.resume = alc_resume,
1099 	.suspend = alc_suspend,
1100 	.check_power_status = snd_hda_gen_check_power_status,
1101 	.stream_pm = snd_hda_gen_stream_pm,
1102 };
1103 
1104 /*
1105  * driver entries
1106  */
1107 static const struct hda_device_id snd_hda_id_alc662[] = {
1108 	HDA_CODEC_ID(0x10ec0272, "ALC272"),
1109 	HDA_CODEC_ID_REV(0x10ec0662, 0x100101, "ALC662 rev1"),
1110 	HDA_CODEC_ID_REV(0x10ec0662, 0x100300, "ALC662 rev3"),
1111 	HDA_CODEC_ID(0x10ec0663, "ALC663"),
1112 	HDA_CODEC_ID(0x10ec0665, "ALC665"),
1113 	HDA_CODEC_ID(0x10ec0667, "ALC667"),
1114 	HDA_CODEC_ID(0x10ec0668, "ALC668"),
1115 	HDA_CODEC_ID(0x10ec0670, "ALC670"),
1116 	HDA_CODEC_ID(0x10ec0671, "ALC671"),
1117 	HDA_CODEC_ID(0x10ec0867, "ALC891"),
1118 	HDA_CODEC_ID(0x10ec0892, "ALC892"),
1119 	HDA_CODEC_ID(0x10ec0897, "ALC897"),
1120 	{} /* terminator */
1121 };
1122 MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc662);
1123 
1124 MODULE_LICENSE("GPL");
1125 MODULE_DESCRIPTION("Realtek ALC662 and compatible HD-audio codec");
1126 MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
1127 
1128 static struct hda_codec_driver alc662_driver = {
1129 	.id = snd_hda_id_alc662,
1130 	.ops = &alc662_codec_ops,
1131 };
1132 
1133 module_hda_codec_driver(alc662_driver);
1134