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
258 enum {
259 ALC662_FIXUP_ASPIRE,
260 ALC662_FIXUP_LED_GPIO1,
261 ALC662_FIXUP_IDEAPAD,
262 ALC272_FIXUP_MARIO,
263 ALC662_FIXUP_CZC_ET26,
264 ALC662_FIXUP_CZC_P10T,
265 ALC662_FIXUP_SKU_IGNORE,
266 ALC662_FIXUP_HP_RP5800,
267 ALC662_FIXUP_ASUS_MODE1,
268 ALC662_FIXUP_ASUS_MODE2,
269 ALC662_FIXUP_ASUS_MODE3,
270 ALC662_FIXUP_ASUS_MODE4,
271 ALC662_FIXUP_ASUS_MODE5,
272 ALC662_FIXUP_ASUS_MODE6,
273 ALC662_FIXUP_ASUS_MODE7,
274 ALC662_FIXUP_ASUS_MODE8,
275 ALC662_FIXUP_NO_JACK_DETECT,
276 ALC662_FIXUP_ZOTAC_Z68,
277 ALC662_FIXUP_INV_DMIC,
278 ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
279 ALC668_FIXUP_DELL_MIC_NO_PRESENCE,
280 ALC662_FIXUP_HEADSET_MODE,
281 ALC668_FIXUP_HEADSET_MODE,
282 ALC662_FIXUP_BASS_MODE4_CHMAP,
283 ALC662_FIXUP_BASS_16,
284 ALC662_FIXUP_BASS_1A,
285 ALC662_FIXUP_BASS_CHMAP,
286 ALC668_FIXUP_AUTO_MUTE,
287 ALC668_FIXUP_DELL_DISABLE_AAMIX,
288 ALC668_FIXUP_DELL_XPS13,
289 ALC662_FIXUP_ASUS_Nx50,
290 ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE,
291 ALC668_FIXUP_ASUS_Nx51,
292 ALC668_FIXUP_MIC_COEF,
293 ALC668_FIXUP_ASUS_G751,
294 ALC891_FIXUP_HEADSET_MODE,
295 ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
296 ALC662_FIXUP_ACER_VERITON,
297 ALC892_FIXUP_ASROCK_MOBO,
298 ALC662_FIXUP_USI_FUNC,
299 ALC662_FIXUP_USI_HEADSET_MODE,
300 ALC662_FIXUP_LENOVO_MULTI_CODECS,
301 ALC669_FIXUP_ACER_ASPIRE_ETHOS,
302 ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET,
303 ALC671_FIXUP_HP_HEADSET_MIC2,
304 ALC662_FIXUP_ACER_X2660G_HEADSET_MODE,
305 ALC662_FIXUP_ACER_NITRO_HEADSET_MODE,
306 ALC668_FIXUP_ASUS_NO_HEADSET_MIC,
307 ALC668_FIXUP_HEADSET_MIC,
308 ALC668_FIXUP_MIC_DET_COEF,
309 ALC897_FIXUP_LENOVO_HEADSET_MIC,
310 ALC897_FIXUP_HEADSET_MIC_PIN,
311 ALC897_FIXUP_HP_HSMIC_VERB,
312 ALC897_FIXUP_LENOVO_HEADSET_MODE,
313 ALC897_FIXUP_HEADSET_MIC_PIN2,
314 ALC897_FIXUP_UNIS_H3C_X500S,
315 ALC897_FIXUP_HEADSET_MIC_PIN3,
316 };
317
318 static const struct hda_fixup alc662_fixups[] = {
319 [ALC662_FIXUP_ASPIRE] = {
320 .type = HDA_FIXUP_PINS,
321 .v.pins = (const struct hda_pintbl[]) {
322 { 0x15, 0x99130112 }, /* subwoofer */
323 { }
324 }
325 },
326 [ALC662_FIXUP_LED_GPIO1] = {
327 .type = HDA_FIXUP_FUNC,
328 .v.func = alc662_fixup_led_gpio1,
329 },
330 [ALC662_FIXUP_IDEAPAD] = {
331 .type = HDA_FIXUP_PINS,
332 .v.pins = (const struct hda_pintbl[]) {
333 { 0x17, 0x99130112 }, /* subwoofer */
334 { }
335 },
336 .chained = true,
337 .chain_id = ALC662_FIXUP_LED_GPIO1,
338 },
339 [ALC272_FIXUP_MARIO] = {
340 .type = HDA_FIXUP_FUNC,
341 .v.func = alc272_fixup_mario,
342 },
343 [ALC662_FIXUP_CZC_ET26] = {
344 .type = HDA_FIXUP_PINS,
345 .v.pins = (const struct hda_pintbl[]) {
346 {0x12, 0x403cc000},
347 {0x14, 0x90170110}, /* speaker */
348 {0x15, 0x411111f0},
349 {0x16, 0x411111f0},
350 {0x18, 0x01a19030}, /* mic */
351 {0x19, 0x90a7013f}, /* int-mic */
352 {0x1a, 0x01014020},
353 {0x1b, 0x0121401f},
354 {0x1c, 0x411111f0},
355 {0x1d, 0x411111f0},
356 {0x1e, 0x40478e35},
357 {}
358 },
359 .chained = true,
360 .chain_id = ALC662_FIXUP_SKU_IGNORE
361 },
362 [ALC662_FIXUP_CZC_P10T] = {
363 .type = HDA_FIXUP_VERBS,
364 .v.verbs = (const struct hda_verb[]) {
365 {0x14, AC_VERB_SET_EAPD_BTLENABLE, 0},
366 {}
367 }
368 },
369 [ALC662_FIXUP_SKU_IGNORE] = {
370 .type = HDA_FIXUP_FUNC,
371 .v.func = alc_fixup_sku_ignore,
372 },
373 [ALC662_FIXUP_HP_RP5800] = {
374 .type = HDA_FIXUP_PINS,
375 .v.pins = (const struct hda_pintbl[]) {
376 { 0x14, 0x0221201f }, /* HP out */
377 { }
378 },
379 .chained = true,
380 .chain_id = ALC662_FIXUP_SKU_IGNORE
381 },
382 [ALC662_FIXUP_ASUS_MODE1] = {
383 .type = HDA_FIXUP_PINS,
384 .v.pins = (const struct hda_pintbl[]) {
385 { 0x14, 0x99130110 }, /* speaker */
386 { 0x18, 0x01a19c20 }, /* mic */
387 { 0x19, 0x99a3092f }, /* int-mic */
388 { 0x21, 0x0121401f }, /* HP out */
389 { }
390 },
391 .chained = true,
392 .chain_id = ALC662_FIXUP_SKU_IGNORE
393 },
394 [ALC662_FIXUP_ASUS_MODE2] = {
395 .type = HDA_FIXUP_PINS,
396 .v.pins = (const struct hda_pintbl[]) {
397 { 0x14, 0x99130110 }, /* speaker */
398 { 0x18, 0x01a19820 }, /* mic */
399 { 0x19, 0x99a3092f }, /* int-mic */
400 { 0x1b, 0x0121401f }, /* HP out */
401 { }
402 },
403 .chained = true,
404 .chain_id = ALC662_FIXUP_SKU_IGNORE
405 },
406 [ALC662_FIXUP_ASUS_MODE3] = {
407 .type = HDA_FIXUP_PINS,
408 .v.pins = (const struct hda_pintbl[]) {
409 { 0x14, 0x99130110 }, /* speaker */
410 { 0x15, 0x0121441f }, /* HP */
411 { 0x18, 0x01a19840 }, /* mic */
412 { 0x19, 0x99a3094f }, /* int-mic */
413 { 0x21, 0x01211420 }, /* HP2 */
414 { }
415 },
416 .chained = true,
417 .chain_id = ALC662_FIXUP_SKU_IGNORE
418 },
419 [ALC662_FIXUP_ASUS_MODE4] = {
420 .type = HDA_FIXUP_PINS,
421 .v.pins = (const struct hda_pintbl[]) {
422 { 0x14, 0x99130110 }, /* speaker */
423 { 0x16, 0x99130111 }, /* speaker */
424 { 0x18, 0x01a19840 }, /* mic */
425 { 0x19, 0x99a3094f }, /* int-mic */
426 { 0x21, 0x0121441f }, /* HP */
427 { }
428 },
429 .chained = true,
430 .chain_id = ALC662_FIXUP_SKU_IGNORE
431 },
432 [ALC662_FIXUP_ASUS_MODE5] = {
433 .type = HDA_FIXUP_PINS,
434 .v.pins = (const struct hda_pintbl[]) {
435 { 0x14, 0x99130110 }, /* speaker */
436 { 0x15, 0x0121441f }, /* HP */
437 { 0x16, 0x99130111 }, /* speaker */
438 { 0x18, 0x01a19840 }, /* mic */
439 { 0x19, 0x99a3094f }, /* int-mic */
440 { }
441 },
442 .chained = true,
443 .chain_id = ALC662_FIXUP_SKU_IGNORE
444 },
445 [ALC662_FIXUP_ASUS_MODE6] = {
446 .type = HDA_FIXUP_PINS,
447 .v.pins = (const struct hda_pintbl[]) {
448 { 0x14, 0x99130110 }, /* speaker */
449 { 0x15, 0x01211420 }, /* HP2 */
450 { 0x18, 0x01a19840 }, /* mic */
451 { 0x19, 0x99a3094f }, /* int-mic */
452 { 0x1b, 0x0121441f }, /* HP */
453 { }
454 },
455 .chained = true,
456 .chain_id = ALC662_FIXUP_SKU_IGNORE
457 },
458 [ALC662_FIXUP_ASUS_MODE7] = {
459 .type = HDA_FIXUP_PINS,
460 .v.pins = (const struct hda_pintbl[]) {
461 { 0x14, 0x99130110 }, /* speaker */
462 { 0x17, 0x99130111 }, /* speaker */
463 { 0x18, 0x01a19840 }, /* mic */
464 { 0x19, 0x99a3094f }, /* int-mic */
465 { 0x1b, 0x01214020 }, /* HP */
466 { 0x21, 0x0121401f }, /* HP */
467 { }
468 },
469 .chained = true,
470 .chain_id = ALC662_FIXUP_SKU_IGNORE
471 },
472 [ALC662_FIXUP_ASUS_MODE8] = {
473 .type = HDA_FIXUP_PINS,
474 .v.pins = (const struct hda_pintbl[]) {
475 { 0x14, 0x99130110 }, /* speaker */
476 { 0x12, 0x99a30970 }, /* int-mic */
477 { 0x15, 0x01214020 }, /* HP */
478 { 0x17, 0x99130111 }, /* speaker */
479 { 0x18, 0x01a19840 }, /* mic */
480 { 0x21, 0x0121401f }, /* HP */
481 { }
482 },
483 .chained = true,
484 .chain_id = ALC662_FIXUP_SKU_IGNORE
485 },
486 [ALC662_FIXUP_NO_JACK_DETECT] = {
487 .type = HDA_FIXUP_FUNC,
488 .v.func = alc_fixup_no_jack_detect,
489 },
490 [ALC662_FIXUP_ZOTAC_Z68] = {
491 .type = HDA_FIXUP_PINS,
492 .v.pins = (const struct hda_pintbl[]) {
493 { 0x1b, 0x02214020 }, /* Front HP */
494 { }
495 }
496 },
497 [ALC662_FIXUP_INV_DMIC] = {
498 .type = HDA_FIXUP_FUNC,
499 .v.func = alc_fixup_inv_dmic,
500 },
501 [ALC668_FIXUP_DELL_XPS13] = {
502 .type = HDA_FIXUP_FUNC,
503 .v.func = alc_fixup_dell_xps13,
504 .chained = true,
505 .chain_id = ALC668_FIXUP_DELL_DISABLE_AAMIX
506 },
507 [ALC668_FIXUP_DELL_DISABLE_AAMIX] = {
508 .type = HDA_FIXUP_FUNC,
509 .v.func = alc_fixup_disable_aamix,
510 .chained = true,
511 .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
512 },
513 [ALC668_FIXUP_AUTO_MUTE] = {
514 .type = HDA_FIXUP_FUNC,
515 .v.func = alc_fixup_auto_mute_via_amp,
516 .chained = true,
517 .chain_id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE
518 },
519 [ALC662_FIXUP_DELL_MIC_NO_PRESENCE] = {
520 .type = HDA_FIXUP_PINS,
521 .v.pins = (const struct hda_pintbl[]) {
522 { 0x19, 0x03a1113c }, /* use as headset mic, without its own jack detect */
523 /* headphone mic by setting pin control of 0x1b (headphone out) to in + vref_50 */
524 { }
525 },
526 .chained = true,
527 .chain_id = ALC662_FIXUP_HEADSET_MODE
528 },
529 [ALC662_FIXUP_HEADSET_MODE] = {
530 .type = HDA_FIXUP_FUNC,
531 .v.func = alc_fixup_headset_mode_alc662,
532 },
533 [ALC668_FIXUP_DELL_MIC_NO_PRESENCE] = {
534 .type = HDA_FIXUP_PINS,
535 .v.pins = (const struct hda_pintbl[]) {
536 { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
537 { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
538 { }
539 },
540 .chained = true,
541 .chain_id = ALC668_FIXUP_HEADSET_MODE
542 },
543 [ALC668_FIXUP_HEADSET_MODE] = {
544 .type = HDA_FIXUP_FUNC,
545 .v.func = alc_fixup_headset_mode_alc668,
546 },
547 [ALC662_FIXUP_BASS_MODE4_CHMAP] = {
548 .type = HDA_FIXUP_FUNC,
549 .v.func = alc_fixup_bass_chmap,
550 .chained = true,
551 .chain_id = ALC662_FIXUP_ASUS_MODE4
552 },
553 [ALC662_FIXUP_BASS_16] = {
554 .type = HDA_FIXUP_PINS,
555 .v.pins = (const struct hda_pintbl[]) {
556 {0x16, 0x80106111}, /* bass speaker */
557 {}
558 },
559 .chained = true,
560 .chain_id = ALC662_FIXUP_BASS_CHMAP,
561 },
562 [ALC662_FIXUP_BASS_1A] = {
563 .type = HDA_FIXUP_PINS,
564 .v.pins = (const struct hda_pintbl[]) {
565 {0x1a, 0x80106111}, /* bass speaker */
566 {}
567 },
568 .chained = true,
569 .chain_id = ALC662_FIXUP_BASS_CHMAP,
570 },
571 [ALC662_FIXUP_BASS_CHMAP] = {
572 .type = HDA_FIXUP_FUNC,
573 .v.func = alc_fixup_bass_chmap,
574 },
575 [ALC662_FIXUP_ASUS_Nx50] = {
576 .type = HDA_FIXUP_FUNC,
577 .v.func = alc_fixup_auto_mute_via_amp,
578 .chained = true,
579 .chain_id = ALC662_FIXUP_BASS_1A
580 },
581 [ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE] = {
582 .type = HDA_FIXUP_FUNC,
583 .v.func = alc_fixup_headset_mode_alc668,
584 .chain_id = ALC662_FIXUP_BASS_CHMAP
585 },
586 [ALC668_FIXUP_ASUS_Nx51] = {
587 .type = HDA_FIXUP_PINS,
588 .v.pins = (const struct hda_pintbl[]) {
589 { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
590 { 0x1a, 0x90170151 }, /* bass speaker */
591 { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
592 {}
593 },
594 .chained = true,
595 .chain_id = ALC668_FIXUP_ASUS_Nx51_HEADSET_MODE,
596 },
597 [ALC668_FIXUP_MIC_COEF] = {
598 .type = HDA_FIXUP_VERBS,
599 .v.verbs = (const struct hda_verb[]) {
600 { 0x20, AC_VERB_SET_COEF_INDEX, 0xc3 },
601 { 0x20, AC_VERB_SET_PROC_COEF, 0x4000 },
602 {}
603 },
604 },
605 [ALC668_FIXUP_ASUS_G751] = {
606 .type = HDA_FIXUP_PINS,
607 .v.pins = (const struct hda_pintbl[]) {
608 { 0x16, 0x0421101f }, /* HP */
609 {}
610 },
611 .chained = true,
612 .chain_id = ALC668_FIXUP_MIC_COEF
613 },
614 [ALC891_FIXUP_HEADSET_MODE] = {
615 .type = HDA_FIXUP_FUNC,
616 .v.func = alc_fixup_headset_mode,
617 },
618 [ALC891_FIXUP_DELL_MIC_NO_PRESENCE] = {
619 .type = HDA_FIXUP_PINS,
620 .v.pins = (const struct hda_pintbl[]) {
621 { 0x19, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
622 { 0x1b, 0x03a1113c }, /* use as headset mic, without its own jack detect */
623 { }
624 },
625 .chained = true,
626 .chain_id = ALC891_FIXUP_HEADSET_MODE
627 },
628 [ALC662_FIXUP_ACER_VERITON] = {
629 .type = HDA_FIXUP_PINS,
630 .v.pins = (const struct hda_pintbl[]) {
631 { 0x15, 0x50170120 }, /* no internal speaker */
632 { }
633 }
634 },
635 [ALC892_FIXUP_ASROCK_MOBO] = {
636 .type = HDA_FIXUP_PINS,
637 .v.pins = (const struct hda_pintbl[]) {
638 { 0x15, 0x40f000f0 }, /* disabled */
639 { 0x16, 0x40f000f0 }, /* disabled */
640 { }
641 }
642 },
643 [ALC662_FIXUP_USI_FUNC] = {
644 .type = HDA_FIXUP_FUNC,
645 .v.func = alc662_fixup_usi_headset_mic,
646 },
647 [ALC662_FIXUP_USI_HEADSET_MODE] = {
648 .type = HDA_FIXUP_PINS,
649 .v.pins = (const struct hda_pintbl[]) {
650 { 0x19, 0x02a1913c }, /* use as headset mic, without its own jack detect */
651 { 0x18, 0x01a1903d },
652 { }
653 },
654 .chained = true,
655 .chain_id = ALC662_FIXUP_USI_FUNC
656 },
657 [ALC662_FIXUP_LENOVO_MULTI_CODECS] = {
658 .type = HDA_FIXUP_FUNC,
659 .v.func = alc233_alc662_fixup_lenovo_dual_codecs,
660 },
661 [ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET] = {
662 .type = HDA_FIXUP_FUNC,
663 .v.func = alc662_fixup_aspire_ethos_hp,
664 },
665 [ALC669_FIXUP_ACER_ASPIRE_ETHOS] = {
666 .type = HDA_FIXUP_PINS,
667 .v.pins = (const struct hda_pintbl[]) {
668 { 0x15, 0x92130110 }, /* front speakers */
669 { 0x18, 0x99130111 }, /* center/subwoofer */
670 { 0x1b, 0x11130012 }, /* surround plus jack for HP */
671 { }
672 },
673 .chained = true,
674 .chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET
675 },
676 [ALC671_FIXUP_HP_HEADSET_MIC2] = {
677 .type = HDA_FIXUP_FUNC,
678 .v.func = alc671_fixup_hp_headset_mic2,
679 },
680 [ALC662_FIXUP_ACER_X2660G_HEADSET_MODE] = {
681 .type = HDA_FIXUP_PINS,
682 .v.pins = (const struct hda_pintbl[]) {
683 { 0x1a, 0x02a1113c }, /* use as headset mic, without its own jack detect */
684 { }
685 },
686 .chained = true,
687 .chain_id = ALC662_FIXUP_USI_FUNC
688 },
689 [ALC662_FIXUP_ACER_NITRO_HEADSET_MODE] = {
690 .type = HDA_FIXUP_PINS,
691 .v.pins = (const struct hda_pintbl[]) {
692 { 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */
693 { 0x1b, 0x0221144f },
694 { }
695 },
696 .chained = true,
697 .chain_id = ALC662_FIXUP_USI_FUNC
698 },
699 [ALC668_FIXUP_ASUS_NO_HEADSET_MIC] = {
700 .type = HDA_FIXUP_PINS,
701 .v.pins = (const struct hda_pintbl[]) {
702 { 0x1b, 0x04a1112c },
703 { }
704 },
705 .chained = true,
706 .chain_id = ALC668_FIXUP_HEADSET_MIC
707 },
708 [ALC668_FIXUP_HEADSET_MIC] = {
709 .type = HDA_FIXUP_FUNC,
710 .v.func = alc_fixup_headset_mic,
711 .chained = true,
712 .chain_id = ALC668_FIXUP_MIC_DET_COEF
713 },
714 [ALC668_FIXUP_MIC_DET_COEF] = {
715 .type = HDA_FIXUP_VERBS,
716 .v.verbs = (const struct hda_verb[]) {
717 { 0x20, AC_VERB_SET_COEF_INDEX, 0x15 },
718 { 0x20, AC_VERB_SET_PROC_COEF, 0x0d60 },
719 {}
720 },
721 },
722 [ALC897_FIXUP_LENOVO_HEADSET_MIC] = {
723 .type = HDA_FIXUP_FUNC,
724 .v.func = alc897_fixup_lenovo_headset_mic,
725 },
726 [ALC897_FIXUP_HEADSET_MIC_PIN] = {
727 .type = HDA_FIXUP_PINS,
728 .v.pins = (const struct hda_pintbl[]) {
729 { 0x1a, 0x03a11050 },
730 { }
731 },
732 .chained = true,
733 .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC
734 },
735 [ALC897_FIXUP_HP_HSMIC_VERB] = {
736 .type = HDA_FIXUP_PINS,
737 .v.pins = (const struct hda_pintbl[]) {
738 { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
739 { }
740 },
741 },
742 [ALC897_FIXUP_LENOVO_HEADSET_MODE] = {
743 .type = HDA_FIXUP_FUNC,
744 .v.func = alc897_fixup_lenovo_headset_mode,
745 },
746 [ALC897_FIXUP_HEADSET_MIC_PIN2] = {
747 .type = HDA_FIXUP_PINS,
748 .v.pins = (const struct hda_pintbl[]) {
749 { 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */
750 { }
751 },
752 .chained = true,
753 .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MODE
754 },
755 [ALC897_FIXUP_UNIS_H3C_X500S] = {
756 .type = HDA_FIXUP_VERBS,
757 .v.verbs = (const struct hda_verb[]) {
758 { 0x14, AC_VERB_SET_EAPD_BTLENABLE, 0 },
759 {}
760 },
761 },
762 [ALC897_FIXUP_HEADSET_MIC_PIN3] = {
763 .type = HDA_FIXUP_PINS,
764 .v.pins = (const struct hda_pintbl[]) {
765 { 0x19, 0x03a11050 }, /* use as headset mic */
766 { }
767 },
768 },
769 };
770
771 static const struct hda_quirk alc662_fixup_tbl[] = {
772 SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
773 SND_PCI_QUIRK(0x1019, 0x9859, "JP-IK LEAP W502", ALC897_FIXUP_HEADSET_MIC_PIN3),
774 SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
775 SND_PCI_QUIRK(0x1025, 0x0241, "Packard Bell DOTS", ALC662_FIXUP_INV_DMIC),
776 SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
777 SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
778 SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
779 SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC),
780 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
781 SND_PCI_QUIRK(0x1025, 0x0566, "Acer Aspire Ethos 8951G", ALC669_FIXUP_ACER_ASPIRE_ETHOS),
782 SND_PCI_QUIRK(0x1025, 0x123c, "Acer Nitro N50-600", ALC662_FIXUP_ACER_NITRO_HEADSET_MODE),
783 SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE),
784 SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
785 SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
786 SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13),
787 SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13),
788 SND_PCI_QUIRK(0x1028, 0x060d, "Dell M3800", ALC668_FIXUP_DELL_XPS13),
789 SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
790 SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
791 SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
792 SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
793 SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
794 SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
795 SND_PCI_QUIRK(0x103c, 0x870c, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
796 SND_PCI_QUIRK(0x103c, 0x8719, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
797 SND_PCI_QUIRK(0x103c, 0x872b, "HP", ALC897_FIXUP_HP_HSMIC_VERB),
798 SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2),
799 SND_PCI_QUIRK(0x103c, 0x8768, "HP Slim Desktop S01", ALC671_FIXUP_HP_HEADSET_MIC2),
800 SND_PCI_QUIRK(0x103c, 0x877e, "HP 288 Pro G6", ALC671_FIXUP_HP_HEADSET_MIC2),
801 SND_PCI_QUIRK(0x103c, 0x885f, "HP 288 Pro G8", ALC671_FIXUP_HP_HEADSET_MIC2),
802 SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE),
803 SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50),
804 SND_PCI_QUIRK(0x1043, 0x129d, "Asus N750", ALC662_FIXUP_ASUS_Nx50),
805 SND_PCI_QUIRK(0x1043, 0x12ff, "ASUS G751", ALC668_FIXUP_ASUS_G751),
806 SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A),
807 SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
808 SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16),
809 SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51),
810 SND_PCI_QUIRK(0x1043, 0x17bd, "ASUS N751", ALC668_FIXUP_ASUS_Nx51),
811 SND_PCI_QUIRK(0x1043, 0x185d, "ASUS G551JW", ALC668_FIXUP_ASUS_NO_HEADSET_MIC),
812 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71SL", ALC662_FIXUP_ASUS_MODE8),
813 SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16),
814 SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP),
815 SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
816 SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
817 SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
818 SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE),
819 SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS),
820 SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN),
821 SND_PCI_QUIRK(0x17aa, 0x1064, "Lenovo P3 Tower", ALC897_FIXUP_HEADSET_MIC_PIN),
822 SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN),
823 SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN),
824 SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN),
825 SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN),
826 SND_PCI_QUIRK(0x17aa, 0x3321, "Lenovo ThinkCentre M70 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
827 SND_PCI_QUIRK(0x17aa, 0x331b, "Lenovo ThinkCentre M90 Gen4", ALC897_FIXUP_HEADSET_MIC_PIN),
828 SND_PCI_QUIRK(0x17aa, 0x3364, "Lenovo ThinkCentre M90 Gen5", ALC897_FIXUP_HEADSET_MIC_PIN),
829 SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2),
830 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
831 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
832 SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO),
833 SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68),
834 SND_PCI_QUIRK(0x1b0a, 0x01b8, "ACER Veriton", ALC662_FIXUP_ACER_VERITON),
835 SND_PCI_QUIRK(0x1b35, 0x1234, "CZC ET26", ALC662_FIXUP_CZC_ET26),
836 SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
837 SND_PCI_QUIRK(0x1c6c, 0x1239, "Compaq N14JP6-V2", ALC897_FIXUP_HP_HSMIC_VERB),
838
839 #if 0
840 /* Below is a quirk table taken from the old code.
841 * Basically the device should work as is without the fixup table.
842 * If BIOS doesn't give a proper info, enable the corresponding
843 * fixup entry.
844 */
845 SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
846 SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
847 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
848 SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
849 SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
850 SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
851 SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
852 SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
853 SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
854 SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
855 SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
856 SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
857 SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
858 SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
859 SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
860 SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
861 SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
862 SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
863 SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
864 SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
865 SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
866 SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
867 SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
868 SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
869 SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
870 SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
871 SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
872 SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
873 SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
874 SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
875 SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
876 SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
877 SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
878 SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
879 SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
880 SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
881 SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
882 SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
883 SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
884 SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
885 SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
886 SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
887 SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
888 SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
889 SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
890 SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
891 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
892 SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
893 SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
894 SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
895 #endif
896 {}
897 };
898
899 static const struct hda_model_fixup alc662_fixup_models[] = {
900 {.id = ALC662_FIXUP_ASPIRE, .name = "aspire"},
901 {.id = ALC662_FIXUP_IDEAPAD, .name = "ideapad"},
902 {.id = ALC272_FIXUP_MARIO, .name = "mario"},
903 {.id = ALC662_FIXUP_HP_RP5800, .name = "hp-rp5800"},
904 {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
905 {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
906 {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
907 {.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
908 {.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
909 {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
910 {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
911 {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
912 {.id = ALC662_FIXUP_ZOTAC_Z68, .name = "zotac-z68"},
913 {.id = ALC662_FIXUP_INV_DMIC, .name = "inv-dmic"},
914 {.id = ALC662_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc662-headset-multi"},
915 {.id = ALC668_FIXUP_DELL_MIC_NO_PRESENCE, .name = "dell-headset-multi"},
916 {.id = ALC662_FIXUP_HEADSET_MODE, .name = "alc662-headset"},
917 {.id = ALC668_FIXUP_HEADSET_MODE, .name = "alc668-headset"},
918 {.id = ALC662_FIXUP_BASS_16, .name = "bass16"},
919 {.id = ALC662_FIXUP_BASS_1A, .name = "bass1a"},
920 {.id = ALC668_FIXUP_AUTO_MUTE, .name = "automute"},
921 {.id = ALC668_FIXUP_DELL_XPS13, .name = "dell-xps13"},
922 {.id = ALC662_FIXUP_ASUS_Nx50, .name = "asus-nx50"},
923 {.id = ALC668_FIXUP_ASUS_Nx51, .name = "asus-nx51"},
924 {.id = ALC668_FIXUP_ASUS_G751, .name = "asus-g751"},
925 {.id = ALC891_FIXUP_HEADSET_MODE, .name = "alc891-headset"},
926 {.id = ALC891_FIXUP_DELL_MIC_NO_PRESENCE, .name = "alc891-headset-multi"},
927 {.id = ALC662_FIXUP_ACER_VERITON, .name = "acer-veriton"},
928 {.id = ALC892_FIXUP_ASROCK_MOBO, .name = "asrock-mobo"},
929 {.id = ALC662_FIXUP_USI_HEADSET_MODE, .name = "usi-headset"},
930 {.id = ALC662_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"},
931 {.id = ALC669_FIXUP_ACER_ASPIRE_ETHOS, .name = "aspire-ethos"},
932 {.id = ALC897_FIXUP_UNIS_H3C_X500S, .name = "unis-h3c-x500s"},
933 {}
934 };
935
936 static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = {
937 SND_HDA_PIN_QUIRK(0x10ec0867, 0x1028, "Dell", ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
938 {0x17, 0x02211010},
939 {0x18, 0x01a19030},
940 {0x1a, 0x01813040},
941 {0x21, 0x01014020}),
942 SND_HDA_PIN_QUIRK(0x10ec0867, 0x1028, "Dell", ALC891_FIXUP_DELL_MIC_NO_PRESENCE,
943 {0x16, 0x01813030},
944 {0x17, 0x02211010},
945 {0x18, 0x01a19040},
946 {0x21, 0x01014020}),
947 SND_HDA_PIN_QUIRK(0x10ec0662, 0x1028, "Dell", ALC662_FIXUP_DELL_MIC_NO_PRESENCE,
948 {0x14, 0x01014010},
949 {0x18, 0x01a19020},
950 {0x1a, 0x0181302f},
951 {0x1b, 0x0221401f}),
952 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
953 {0x12, 0x99a30130},
954 {0x14, 0x90170110},
955 {0x15, 0x0321101f},
956 {0x16, 0x03011020}),
957 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
958 {0x12, 0x99a30140},
959 {0x14, 0x90170110},
960 {0x15, 0x0321101f},
961 {0x16, 0x03011020}),
962 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
963 {0x12, 0x99a30150},
964 {0x14, 0x90170110},
965 {0x15, 0x0321101f},
966 {0x16, 0x03011020}),
967 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell", ALC668_FIXUP_AUTO_MUTE,
968 {0x14, 0x90170110},
969 {0x15, 0x0321101f},
970 {0x16, 0x03011020}),
971 SND_HDA_PIN_QUIRK(0x10ec0668, 0x1028, "Dell XPS 15", ALC668_FIXUP_AUTO_MUTE,
972 {0x12, 0x90a60130},
973 {0x14, 0x90170110},
974 {0x15, 0x0321101f}),
975 SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
976 {0x14, 0x01014010},
977 {0x17, 0x90170150},
978 {0x19, 0x02a11060},
979 {0x1b, 0x01813030},
980 {0x21, 0x02211020}),
981 SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
982 {0x14, 0x01014010},
983 {0x18, 0x01a19040},
984 {0x1b, 0x01813030},
985 {0x21, 0x02211020}),
986 SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
987 {0x14, 0x01014020},
988 {0x17, 0x90170110},
989 {0x18, 0x01a19050},
990 {0x1b, 0x01813040},
991 {0x21, 0x02211030}),
992 {}
993 };
994
995 /*
996 */
alc662_probe(struct hda_codec * codec,const struct hda_device_id * id)997 static int alc662_probe(struct hda_codec *codec, const struct hda_device_id *id)
998 {
999 struct alc_spec *spec;
1000 int err;
1001
1002 err = alc_alloc_spec(codec, 0x0b);
1003 if (err < 0)
1004 return err;
1005
1006 spec = codec->spec;
1007
1008 spec->shutup = alc_eapd_shutup;
1009
1010 /* handle multiple HPs as is */
1011 spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
1012
1013 alc_fix_pll_init(codec, 0x20, 0x04, 15);
1014
1015 switch (codec->core.vendor_id) {
1016 case 0x10ec0668:
1017 spec->init_hook = alc668_restore_default_value;
1018 break;
1019 }
1020
1021 alc_pre_init(codec);
1022
1023 snd_hda_pick_fixup(codec, alc662_fixup_models,
1024 alc662_fixup_tbl, alc662_fixups);
1025 snd_hda_pick_pin_fixup(codec, alc662_pin_fixup_tbl, alc662_fixups, true);
1026 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
1027
1028 alc_auto_parse_customize_define(codec);
1029
1030 if (has_cdefine_beep(codec))
1031 spec->gen.beep_nid = 0x01;
1032
1033 if ((alc_get_coef0(codec) & (1 << 14)) &&
1034 codec->bus->pci && codec->bus->pci->subsystem_vendor == 0x1025 &&
1035 spec->cdefine.platform_type == 1) {
1036 err = alc_codec_rename(codec, "ALC272X");
1037 if (err < 0)
1038 goto error;
1039 }
1040
1041 /* automatic parse from the BIOS config */
1042 err = alc662_parse_auto_config(codec);
1043 if (err < 0)
1044 goto error;
1045
1046 if (!spec->gen.no_analog && spec->gen.beep_nid) {
1047 switch (codec->core.vendor_id) {
1048 case 0x10ec0662:
1049 err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
1050 break;
1051 case 0x10ec0272:
1052 case 0x10ec0663:
1053 case 0x10ec0665:
1054 case 0x10ec0668:
1055 err = set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
1056 break;
1057 case 0x10ec0273:
1058 err = set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT);
1059 break;
1060 }
1061 if (err < 0)
1062 goto error;
1063 }
1064
1065 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
1066
1067 return 0;
1068
1069 error:
1070 snd_hda_gen_remove(codec);
1071 return err;
1072 }
1073
1074 static const struct hda_codec_ops alc662_codec_ops = {
1075 .probe = alc662_probe,
1076 .remove = snd_hda_gen_remove,
1077 .build_controls = alc_build_controls,
1078 .build_pcms = snd_hda_gen_build_pcms,
1079 .init = alc_init,
1080 .unsol_event = snd_hda_jack_unsol_event,
1081 .resume = alc_resume,
1082 .suspend = alc_suspend,
1083 .check_power_status = snd_hda_gen_check_power_status,
1084 .stream_pm = snd_hda_gen_stream_pm,
1085 };
1086
1087 /*
1088 * driver entries
1089 */
1090 static const struct hda_device_id snd_hda_id_alc662[] = {
1091 HDA_CODEC_ID(0x10ec0272, "ALC272"),
1092 HDA_CODEC_ID_REV(0x10ec0662, 0x100101, "ALC662 rev1"),
1093 HDA_CODEC_ID_REV(0x10ec0662, 0x100300, "ALC662 rev3"),
1094 HDA_CODEC_ID(0x10ec0663, "ALC663"),
1095 HDA_CODEC_ID(0x10ec0665, "ALC665"),
1096 HDA_CODEC_ID(0x10ec0667, "ALC667"),
1097 HDA_CODEC_ID(0x10ec0668, "ALC668"),
1098 HDA_CODEC_ID(0x10ec0670, "ALC670"),
1099 HDA_CODEC_ID(0x10ec0671, "ALC671"),
1100 HDA_CODEC_ID(0x10ec0867, "ALC891"),
1101 HDA_CODEC_ID(0x10ec0892, "ALC892"),
1102 HDA_CODEC_ID(0x10ec0897, "ALC897"),
1103 {} /* terminator */
1104 };
1105 MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_alc662);
1106
1107 MODULE_LICENSE("GPL");
1108 MODULE_DESCRIPTION("Realtek ALC662 and compatible HD-audio codec");
1109 MODULE_IMPORT_NS("SND_HDA_CODEC_REALTEK");
1110
1111 static struct hda_codec_driver alc662_driver = {
1112 .id = snd_hda_id_alc662,
1113 .ops = &alc662_codec_ops,
1114 };
1115
1116 module_hda_codec_driver(alc662_driver);
1117