1 // SPDX-License-Identifier: GPL-2.0-or-later
2 //
3 // Realtek HD-audio codec support code
4 //
5
6 #include <linux/init.h>
7 #include <linux/module.h>
8 #include "realtek.h"
9
__alc_read_coefex_idx(struct hda_codec * codec,hda_nid_t nid,unsigned int coef_idx)10 static int __alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
11 unsigned int coef_idx)
12 {
13 unsigned int val;
14
15 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx);
16 val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF, 0);
17 return val;
18 }
19
alc_read_coefex_idx(struct hda_codec * codec,hda_nid_t nid,unsigned int coef_idx)20 int alc_read_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
21 unsigned int coef_idx)
22 {
23 guard(coef_mutex)(codec);
24 return __alc_read_coefex_idx(codec, nid, coef_idx);
25 }
26 EXPORT_SYMBOL_NS_GPL(alc_read_coefex_idx, "SND_HDA_CODEC_REALTEK");
27
__alc_write_coefex_idx(struct hda_codec * codec,hda_nid_t nid,unsigned int coef_idx,unsigned int coef_val)28 static void __alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
29 unsigned int coef_idx, unsigned int coef_val)
30 {
31 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_COEF_INDEX, coef_idx);
32 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PROC_COEF, coef_val);
33 }
34
alc_write_coefex_idx(struct hda_codec * codec,hda_nid_t nid,unsigned int coef_idx,unsigned int coef_val)35 void alc_write_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
36 unsigned int coef_idx, unsigned int coef_val)
37 {
38 guard(coef_mutex)(codec);
39 __alc_write_coefex_idx(codec, nid, coef_idx, coef_val);
40 }
41 EXPORT_SYMBOL_NS_GPL(alc_write_coefex_idx, "SND_HDA_CODEC_REALTEK");
42
__alc_update_coefex_idx(struct hda_codec * codec,hda_nid_t nid,unsigned int coef_idx,unsigned int mask,unsigned int bits_set)43 static void __alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
44 unsigned int coef_idx, unsigned int mask,
45 unsigned int bits_set)
46 {
47 unsigned int val = __alc_read_coefex_idx(codec, nid, coef_idx);
48
49 if (val != -1)
50 __alc_write_coefex_idx(codec, nid, coef_idx,
51 (val & ~mask) | bits_set);
52 }
53
alc_update_coefex_idx(struct hda_codec * codec,hda_nid_t nid,unsigned int coef_idx,unsigned int mask,unsigned int bits_set)54 void alc_update_coefex_idx(struct hda_codec *codec, hda_nid_t nid,
55 unsigned int coef_idx, unsigned int mask,
56 unsigned int bits_set)
57 {
58 guard(coef_mutex)(codec);
59 __alc_update_coefex_idx(codec, nid, coef_idx, mask, bits_set);
60 }
61 EXPORT_SYMBOL_NS_GPL(alc_update_coefex_idx, "SND_HDA_CODEC_REALTEK");
62
63 /* a special bypass for COEF 0; read the cached value at the second time */
alc_get_coef0(struct hda_codec * codec)64 unsigned int alc_get_coef0(struct hda_codec *codec)
65 {
66 struct alc_spec *spec = codec->spec;
67
68 if (!spec->coef0)
69 spec->coef0 = alc_read_coef_idx(codec, 0);
70 return spec->coef0;
71 }
72 EXPORT_SYMBOL_NS_GPL(alc_get_coef0, "SND_HDA_CODEC_REALTEK");
73
alc_process_coef_fw(struct hda_codec * codec,const struct coef_fw * fw)74 void alc_process_coef_fw(struct hda_codec *codec, const struct coef_fw *fw)
75 {
76 guard(coef_mutex)(codec);
77 for (; fw->nid; fw++) {
78 if (fw->mask == (unsigned short)-1)
79 __alc_write_coefex_idx(codec, fw->nid, fw->idx, fw->val);
80 else
81 __alc_update_coefex_idx(codec, fw->nid, fw->idx,
82 fw->mask, fw->val);
83 }
84 }
85 EXPORT_SYMBOL_NS_GPL(alc_process_coef_fw, "SND_HDA_CODEC_REALTEK");
86
87 /*
88 * GPIO setup tables, used in initialization
89 */
90
91 /* Enable GPIO mask and set output */
alc_setup_gpio(struct hda_codec * codec,unsigned int mask)92 void alc_setup_gpio(struct hda_codec *codec, unsigned int mask)
93 {
94 struct alc_spec *spec = codec->spec;
95
96 spec->gpio_mask |= mask;
97 spec->gpio_dir |= mask;
98 spec->gpio_data |= mask;
99 }
100 EXPORT_SYMBOL_NS_GPL(alc_setup_gpio, "SND_HDA_CODEC_REALTEK");
101
alc_update_gpio_data(struct hda_codec * codec,unsigned int mask,bool on)102 void alc_update_gpio_data(struct hda_codec *codec, unsigned int mask,
103 bool on)
104 {
105 struct alc_spec *spec = codec->spec;
106 unsigned int oldval = spec->gpio_data;
107
108 if (on)
109 spec->gpio_data |= mask;
110 else
111 spec->gpio_data &= ~mask;
112 if (oldval != spec->gpio_data)
113 snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
114 spec->gpio_data);
115 }
116 EXPORT_SYMBOL_NS_GPL(alc_update_gpio_data, "SND_HDA_CODEC_REALTEK");
117
alc_write_gpio(struct hda_codec * codec)118 static void alc_write_gpio(struct hda_codec *codec)
119 {
120 struct alc_spec *spec = codec->spec;
121
122 if (!spec->gpio_mask)
123 return;
124
125 snd_hda_codec_set_gpio(codec, spec->gpio_mask, spec->gpio_dir,
126 spec->gpio_data,
127 spec->gpio_write_delay ? 1 : 0);
128 }
129
alc_fixup_gpio(struct hda_codec * codec,int action,unsigned int mask)130 void alc_fixup_gpio(struct hda_codec *codec, int action, unsigned int mask)
131 {
132 if (action == HDA_FIXUP_ACT_PRE_PROBE)
133 alc_setup_gpio(codec, mask);
134 }
135 EXPORT_SYMBOL_NS_GPL(alc_fixup_gpio, "SND_HDA_CODEC_REALTEK");
136
alc_fixup_gpio1(struct hda_codec * codec,const struct hda_fixup * fix,int action)137 void alc_fixup_gpio1(struct hda_codec *codec,
138 const struct hda_fixup *fix, int action)
139 {
140 alc_fixup_gpio(codec, action, 0x01);
141 }
142 EXPORT_SYMBOL_NS_GPL(alc_fixup_gpio1, "SND_HDA_CODEC_REALTEK");
143
alc_fixup_gpio2(struct hda_codec * codec,const struct hda_fixup * fix,int action)144 void alc_fixup_gpio2(struct hda_codec *codec,
145 const struct hda_fixup *fix, int action)
146 {
147 alc_fixup_gpio(codec, action, 0x02);
148 }
149 EXPORT_SYMBOL_NS_GPL(alc_fixup_gpio2, "SND_HDA_CODEC_REALTEK");
150
alc_fixup_gpio3(struct hda_codec * codec,const struct hda_fixup * fix,int action)151 void alc_fixup_gpio3(struct hda_codec *codec,
152 const struct hda_fixup *fix, int action)
153 {
154 alc_fixup_gpio(codec, action, 0x03);
155 }
156 EXPORT_SYMBOL_NS_GPL(alc_fixup_gpio3, "SND_HDA_CODEC_REALTEK");
157
alc_fixup_gpio4(struct hda_codec * codec,const struct hda_fixup * fix,int action)158 void alc_fixup_gpio4(struct hda_codec *codec,
159 const struct hda_fixup *fix, int action)
160 {
161 alc_fixup_gpio(codec, action, 0x04);
162 }
163 EXPORT_SYMBOL_NS_GPL(alc_fixup_gpio4, "SND_HDA_CODEC_REALTEK");
164
alc_fixup_micmute_led(struct hda_codec * codec,const struct hda_fixup * fix,int action)165 void alc_fixup_micmute_led(struct hda_codec *codec,
166 const struct hda_fixup *fix, int action)
167 {
168 if (action == HDA_FIXUP_ACT_PRE_PROBE)
169 snd_hda_gen_add_micmute_led_cdev(codec, NULL);
170 }
171 EXPORT_SYMBOL_NS_GPL(alc_fixup_micmute_led, "SND_HDA_CODEC_REALTEK");
172
173 /*
174 * Fix hardware PLL issue
175 * On some codecs, the analog PLL gating control must be off while
176 * the default value is 1.
177 */
alc_fix_pll(struct hda_codec * codec)178 void alc_fix_pll(struct hda_codec *codec)
179 {
180 struct alc_spec *spec = codec->spec;
181
182 if (spec->pll_nid)
183 alc_update_coefex_idx(codec, spec->pll_nid, spec->pll_coef_idx,
184 1 << spec->pll_coef_bit, 0);
185 }
186 EXPORT_SYMBOL_NS_GPL(alc_fix_pll, "SND_HDA_CODEC_REALTEK");
187
alc_fix_pll_init(struct hda_codec * codec,hda_nid_t nid,unsigned int coef_idx,unsigned int coef_bit)188 void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
189 unsigned int coef_idx, unsigned int coef_bit)
190 {
191 struct alc_spec *spec = codec->spec;
192 spec->pll_nid = nid;
193 spec->pll_coef_idx = coef_idx;
194 spec->pll_coef_bit = coef_bit;
195 alc_fix_pll(codec);
196 }
197 EXPORT_SYMBOL_NS_GPL(alc_fix_pll_init, "SND_HDA_CODEC_REALTEK");
198
199 /* update the master volume per volume-knob's unsol event */
alc_update_knob_master(struct hda_codec * codec,struct hda_jack_callback * jack)200 void alc_update_knob_master(struct hda_codec *codec,
201 struct hda_jack_callback *jack)
202 {
203 unsigned int val;
204 struct snd_kcontrol *kctl;
205
206 kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
207 if (!kctl)
208 return;
209
210 struct snd_ctl_elem_value *uctl __free(kfree) =
211 kzalloc_obj(*uctl);
212 if (!uctl)
213 return;
214 val = snd_hda_codec_read(codec, jack->nid, 0,
215 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
216 val &= HDA_AMP_VOLMASK;
217 uctl->value.integer.value[0] = val;
218 uctl->value.integer.value[1] = val;
219 kctl->put(kctl, uctl);
220 }
221 EXPORT_SYMBOL_NS_GPL(alc_update_knob_master, "SND_HDA_CODEC_REALTEK");
222
223 /* Change EAPD to verb control */
alc_fill_eapd_coef(struct hda_codec * codec)224 void alc_fill_eapd_coef(struct hda_codec *codec)
225 {
226 int coef;
227
228 coef = alc_get_coef0(codec);
229
230 switch (codec->core.vendor_id) {
231 case 0x10ec0262:
232 alc_update_coef_idx(codec, 0x7, 0, 1<<5);
233 break;
234 case 0x10ec0267:
235 case 0x10ec0268:
236 alc_update_coef_idx(codec, 0x7, 0, 1<<13);
237 break;
238 case 0x10ec0269:
239 if ((coef & 0x00f0) == 0x0010)
240 alc_update_coef_idx(codec, 0xd, 0, 1<<14);
241 if ((coef & 0x00f0) == 0x0020)
242 alc_update_coef_idx(codec, 0x4, 1<<15, 0);
243 if ((coef & 0x00f0) == 0x0030)
244 alc_update_coef_idx(codec, 0x10, 1<<9, 0);
245 break;
246 case 0x10ec0280:
247 case 0x10ec0284:
248 case 0x10ec0290:
249 case 0x10ec0292:
250 alc_update_coef_idx(codec, 0x4, 1<<15, 0);
251 break;
252 case 0x10ec0225:
253 case 0x10ec0295:
254 case 0x10ec0299:
255 alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
256 fallthrough;
257 case 0x10ec0215:
258 case 0x10ec0236:
259 case 0x10ec0245:
260 case 0x10ec0256:
261 case 0x10ec0257:
262 case 0x10ec0285:
263 case 0x10ec0289:
264 alc_update_coef_idx(codec, 0x36, 1<<13, 0);
265 fallthrough;
266 case 0x10ec0230:
267 case 0x10ec0233:
268 case 0x10ec0235:
269 case 0x10ec0255:
270 case 0x19e58326:
271 case 0x10ec0282:
272 case 0x10ec0283:
273 case 0x10ec0286:
274 case 0x10ec0288:
275 case 0x10ec0298:
276 case 0x10ec0300:
277 alc_update_coef_idx(codec, 0x10, 1<<9, 0);
278 break;
279 case 0x10ec0275:
280 alc_update_coef_idx(codec, 0xe, 0, 1<<0);
281 break;
282 case 0x10ec0287:
283 alc_update_coef_idx(codec, 0x10, 1<<9, 0);
284 alc_write_coef_idx(codec, 0x8, 0x4ab7);
285 break;
286 case 0x10ec0293:
287 alc_update_coef_idx(codec, 0xa, 1<<13, 0);
288 break;
289 case 0x10ec0234:
290 case 0x10ec0274:
291 alc_write_coef_idx(codec, 0x6e, 0x0c25);
292 fallthrough;
293 case 0x10ec0294:
294 case 0x10ec0700:
295 case 0x10ec0701:
296 case 0x10ec0703:
297 case 0x10ec0711:
298 alc_update_coef_idx(codec, 0x10, 1<<15, 0);
299 break;
300 case 0x10ec0662:
301 if ((coef & 0x00f0) == 0x0030)
302 alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */
303 break;
304 case 0x10ec0272:
305 case 0x10ec0273:
306 case 0x10ec0663:
307 case 0x10ec0665:
308 case 0x10ec0670:
309 case 0x10ec0671:
310 case 0x10ec0672:
311 alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
312 break;
313 case 0x10ec0222:
314 case 0x10ec0623:
315 alc_update_coef_idx(codec, 0x19, 1<<13, 0);
316 break;
317 case 0x10ec0668:
318 alc_update_coef_idx(codec, 0x7, 3<<13, 0);
319 break;
320 case 0x10ec0867:
321 alc_update_coef_idx(codec, 0x4, 1<<10, 0);
322 break;
323 case 0x10ec0888:
324 if ((coef & 0x00f0) == 0x0020 || (coef & 0x00f0) == 0x0030)
325 alc_update_coef_idx(codec, 0x7, 1<<5, 0);
326 break;
327 case 0x10ec0892:
328 case 0x10ec0897:
329 alc_update_coef_idx(codec, 0x7, 1<<5, 0);
330 break;
331 case 0x10ec0899:
332 case 0x10ec0900:
333 case 0x10ec0b00:
334 case 0x10ec1168:
335 case 0x10ec1220:
336 alc_update_coef_idx(codec, 0x7, 1<<1, 0);
337 break;
338 }
339 }
340 EXPORT_SYMBOL_NS_GPL(alc_fill_eapd_coef, "SND_HDA_CODEC_REALTEK");
341
342 /* turn on/off EAPD control (only if available) */
set_eapd(struct hda_codec * codec,hda_nid_t nid,int on)343 static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
344 {
345 if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
346 return;
347 if (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD)
348 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
349 on ? 2 : 0);
350 }
351
352 /* turn on/off EAPD controls of the codec */
alc_auto_setup_eapd(struct hda_codec * codec,bool on)353 void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
354 {
355 /* We currently only handle front, HP */
356 static const hda_nid_t pins[] = {
357 0x0f, 0x10, 0x14, 0x15, 0x17, 0
358 };
359 const hda_nid_t *p;
360 for (p = pins; *p; p++)
361 set_eapd(codec, *p, on);
362 }
363 EXPORT_SYMBOL_NS_GPL(alc_auto_setup_eapd, "SND_HDA_CODEC_REALTEK");
364
365 /* Returns the nid of the external mic input pin, or 0 if it cannot be found. */
alc_find_ext_mic_pin(struct hda_codec * codec)366 int alc_find_ext_mic_pin(struct hda_codec *codec)
367 {
368 struct alc_spec *spec = codec->spec;
369 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
370 hda_nid_t nid;
371 unsigned int defcfg;
372 int i;
373
374 for (i = 0; i < cfg->num_inputs; i++) {
375 if (cfg->inputs[i].type != AUTO_PIN_MIC)
376 continue;
377 nid = cfg->inputs[i].pin;
378 defcfg = snd_hda_codec_get_pincfg(codec, nid);
379 if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
380 continue;
381 return nid;
382 }
383
384 return 0;
385 }
386 EXPORT_SYMBOL_NS_GPL(alc_find_ext_mic_pin, "SND_HDA_CODEC_REALTEK");
387
alc_headset_mic_no_shutup(struct hda_codec * codec)388 void alc_headset_mic_no_shutup(struct hda_codec *codec)
389 {
390 const struct hda_pincfg *pin;
391 int mic_pin = alc_find_ext_mic_pin(codec);
392 int i;
393
394 /* don't shut up pins when unloading the driver; otherwise it breaks
395 * the default pin setup at the next load of the driver
396 */
397 if (codec->bus->shutdown)
398 return;
399
400 snd_array_for_each(&codec->init_pins, i, pin) {
401 if (pin->nid != mic_pin)
402 snd_hda_codec_write_sync(codec, pin->nid, 0,
403 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
404 }
405
406 codec->pins_shutup = 1;
407 }
408 EXPORT_SYMBOL_NS_GPL(alc_headset_mic_no_shutup, "SND_HDA_CODEC_REALTEK");
409
alc_shutup_pins(struct hda_codec * codec)410 void alc_shutup_pins(struct hda_codec *codec)
411 {
412 struct alc_spec *spec = codec->spec;
413
414 if (spec->no_shutup_pins)
415 return;
416
417 switch (codec->core.vendor_id) {
418 case 0x10ec0236:
419 case 0x10ec0256:
420 case 0x10ec0257:
421 case 0x19e58326:
422 case 0x10ec0283:
423 case 0x10ec0285:
424 case 0x10ec0286:
425 case 0x10ec0287:
426 case 0x10ec0288:
427 case 0x10ec0295:
428 case 0x10ec0298:
429 alc_headset_mic_no_shutup(codec);
430 break;
431 default:
432 snd_hda_shutup_pins(codec);
433 break;
434 }
435 }
436 EXPORT_SYMBOL_NS_GPL(alc_shutup_pins, "SND_HDA_CODEC_REALTEK");
437
438 /* generic shutup callback;
439 * just turning off EAPD and a little pause for avoiding pop-noise
440 */
alc_eapd_shutup(struct hda_codec * codec)441 void alc_eapd_shutup(struct hda_codec *codec)
442 {
443 struct alc_spec *spec = codec->spec;
444
445 alc_auto_setup_eapd(codec, false);
446 if (!spec->no_depop_delay)
447 msleep(200);
448 alc_shutup_pins(codec);
449 }
450 EXPORT_SYMBOL_NS_GPL(alc_eapd_shutup, "SND_HDA_CODEC_REALTEK");
451
452 /* additional initialization for ALC888 variants */
alc888_coef_init(struct hda_codec * codec)453 static void alc888_coef_init(struct hda_codec *codec)
454 {
455 switch (alc_get_coef0(codec) & 0x00f0) {
456 /* alc888-VA */
457 case 0x00:
458 /* alc888-VB */
459 case 0x10:
460 alc_update_coef_idx(codec, 7, 0, 0x2030); /* Turn EAPD to High */
461 break;
462 }
463 }
464
465 /* generic EAPD initialization */
alc_auto_init_amp(struct hda_codec * codec,int type)466 void alc_auto_init_amp(struct hda_codec *codec, int type)
467 {
468 alc_auto_setup_eapd(codec, true);
469 alc_write_gpio(codec);
470 switch (type) {
471 case ALC_INIT_DEFAULT:
472 switch (codec->core.vendor_id) {
473 case 0x10ec0260:
474 alc_update_coefex_idx(codec, 0x1a, 7, 0, 0x2010);
475 break;
476 case 0x10ec0880:
477 case 0x10ec0882:
478 case 0x10ec0883:
479 case 0x10ec0885:
480 alc_update_coef_idx(codec, 7, 0, 0x2030);
481 break;
482 case 0x10ec0888:
483 alc888_coef_init(codec);
484 break;
485 }
486 break;
487 }
488 }
489 EXPORT_SYMBOL_NS_GPL(alc_auto_init_amp, "SND_HDA_CODEC_REALTEK");
490
491 /* get a primary headphone pin if available */
alc_get_hp_pin(struct alc_spec * spec)492 hda_nid_t alc_get_hp_pin(struct alc_spec *spec)
493 {
494 if (spec->gen.autocfg.hp_pins[0])
495 return spec->gen.autocfg.hp_pins[0];
496 if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
497 return spec->gen.autocfg.line_out_pins[0];
498 return 0;
499 }
500 EXPORT_SYMBOL_NS_GPL(alc_get_hp_pin, "SND_HDA_CODEC_REALTEK");
501
502 /*
503 * Realtek SSID verification
504 */
505
506 /* Could be any non-zero and even value. When used as fixup, tells
507 * the driver to ignore any present sku defines.
508 */
509 #define ALC_FIXUP_SKU_IGNORE (2)
510
alc_fixup_sku_ignore(struct hda_codec * codec,const struct hda_fixup * fix,int action)511 void alc_fixup_sku_ignore(struct hda_codec *codec,
512 const struct hda_fixup *fix, int action)
513 {
514 struct alc_spec *spec = codec->spec;
515 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
516 spec->cdefine.fixup = 1;
517 spec->cdefine.sku_cfg = ALC_FIXUP_SKU_IGNORE;
518 }
519 }
520 EXPORT_SYMBOL_NS_GPL(alc_fixup_sku_ignore, "SND_HDA_CODEC_REALTEK");
521
alc_fixup_no_depop_delay(struct hda_codec * codec,const struct hda_fixup * fix,int action)522 void alc_fixup_no_depop_delay(struct hda_codec *codec,
523 const struct hda_fixup *fix, int action)
524 {
525 struct alc_spec *spec = codec->spec;
526
527 if (action == HDA_FIXUP_ACT_PROBE) {
528 spec->no_depop_delay = 1;
529 codec->depop_delay = 0;
530 }
531 }
532 EXPORT_SYMBOL_NS_GPL(alc_fixup_no_depop_delay, "SND_HDA_CODEC_REALTEK");
533
alc_auto_parse_customize_define(struct hda_codec * codec)534 int alc_auto_parse_customize_define(struct hda_codec *codec)
535 {
536 unsigned int ass, tmp, i;
537 unsigned nid = 0;
538 struct alc_spec *spec = codec->spec;
539
540 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
541
542 if (spec->cdefine.fixup) {
543 ass = spec->cdefine.sku_cfg;
544 if (ass == ALC_FIXUP_SKU_IGNORE)
545 return -1;
546 goto do_sku;
547 }
548
549 if (!codec->bus->pci)
550 return -1;
551 ass = codec->core.subsystem_id & 0xffff;
552 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
553 goto do_sku;
554
555 nid = 0x1d;
556 if (codec->core.vendor_id == 0x10ec0260)
557 nid = 0x17;
558 ass = snd_hda_codec_get_pincfg(codec, nid);
559
560 if (!(ass & 1)) {
561 codec_info(codec, "%s: SKU not ready 0x%08x\n",
562 codec->core.chip_name, ass);
563 return -1;
564 }
565
566 /* check sum */
567 tmp = 0;
568 for (i = 1; i < 16; i++) {
569 if ((ass >> i) & 1)
570 tmp++;
571 }
572 if (((ass >> 16) & 0xf) != tmp)
573 return -1;
574
575 spec->cdefine.port_connectivity = ass >> 30;
576 spec->cdefine.enable_pcbeep = (ass & 0x100000) >> 20;
577 spec->cdefine.check_sum = (ass >> 16) & 0xf;
578 spec->cdefine.customization = ass >> 8;
579 do_sku:
580 spec->cdefine.sku_cfg = ass;
581 spec->cdefine.external_amp = (ass & 0x38) >> 3;
582 spec->cdefine.platform_type = (ass & 0x4) >> 2;
583 spec->cdefine.swap = (ass & 0x2) >> 1;
584 spec->cdefine.override = ass & 0x1;
585
586 codec_dbg(codec, "SKU: Nid=0x%x sku_cfg=0x%08x\n",
587 nid, spec->cdefine.sku_cfg);
588 codec_dbg(codec, "SKU: port_connectivity=0x%x\n",
589 spec->cdefine.port_connectivity);
590 codec_dbg(codec, "SKU: enable_pcbeep=0x%x\n", spec->cdefine.enable_pcbeep);
591 codec_dbg(codec, "SKU: check_sum=0x%08x\n", spec->cdefine.check_sum);
592 codec_dbg(codec, "SKU: customization=0x%08x\n", spec->cdefine.customization);
593 codec_dbg(codec, "SKU: external_amp=0x%x\n", spec->cdefine.external_amp);
594 codec_dbg(codec, "SKU: platform_type=0x%x\n", spec->cdefine.platform_type);
595 codec_dbg(codec, "SKU: swap=0x%x\n", spec->cdefine.swap);
596 codec_dbg(codec, "SKU: override=0x%x\n", spec->cdefine.override);
597
598 return 0;
599 }
600 EXPORT_SYMBOL_NS_GPL(alc_auto_parse_customize_define, "SND_HDA_CODEC_REALTEK");
601
602 /* return the position of NID in the list, or -1 if not found */
find_idx_in_nid_list(hda_nid_t nid,const hda_nid_t * list,int nums)603 static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
604 {
605 int i;
606 for (i = 0; i < nums; i++)
607 if (list[i] == nid)
608 return i;
609 return -1;
610 }
611 /* return true if the given NID is found in the list */
found_in_nid_list(hda_nid_t nid,const hda_nid_t * list,int nums)612 static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
613 {
614 return find_idx_in_nid_list(nid, list, nums) >= 0;
615 }
616
617 /* check subsystem ID and set up device-specific initialization;
618 * return 1 if initialized, 0 if invalid SSID
619 */
620 /* 32-bit subsystem ID for BIOS loading in HD Audio codec.
621 * 31 ~ 16 : Manufacture ID
622 * 15 ~ 8 : SKU ID
623 * 7 ~ 0 : Assembly ID
624 * port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
625 */
alc_subsystem_id(struct hda_codec * codec,const hda_nid_t * ports)626 int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports)
627 {
628 unsigned int ass, tmp, i;
629 unsigned nid;
630 struct alc_spec *spec = codec->spec;
631
632 if (spec->cdefine.fixup) {
633 ass = spec->cdefine.sku_cfg;
634 if (ass == ALC_FIXUP_SKU_IGNORE)
635 return 0;
636 goto do_sku;
637 }
638
639 ass = codec->core.subsystem_id & 0xffff;
640 if (codec->bus->pci &&
641 ass != codec->bus->pci->subsystem_device && (ass & 1))
642 goto do_sku;
643
644 /* invalid SSID, check the special NID pin defcfg instead */
645 /*
646 * 31~30 : port connectivity
647 * 29~21 : reserve
648 * 20 : PCBEEP input
649 * 19~16 : Check sum (15:1)
650 * 15~1 : Custom
651 * 0 : override
652 */
653 nid = 0x1d;
654 if (codec->core.vendor_id == 0x10ec0260)
655 nid = 0x17;
656 ass = snd_hda_codec_get_pincfg(codec, nid);
657 codec_dbg(codec,
658 "realtek: No valid SSID, checking pincfg 0x%08x for NID 0x%x\n",
659 ass, nid);
660 if (!(ass & 1))
661 return 0;
662 if ((ass >> 30) != 1) /* no physical connection */
663 return 0;
664
665 /* check sum */
666 tmp = 0;
667 for (i = 1; i < 16; i++) {
668 if ((ass >> i) & 1)
669 tmp++;
670 }
671 if (((ass >> 16) & 0xf) != tmp)
672 return 0;
673 do_sku:
674 codec_dbg(codec, "realtek: Enabling init ASM_ID=0x%04x CODEC_ID=%08x\n",
675 ass & 0xffff, codec->core.vendor_id);
676 /*
677 * 0 : override
678 * 1 : Swap Jack
679 * 2 : 0 --> Desktop, 1 --> Laptop
680 * 3~5 : External Amplifier control
681 * 7~6 : Reserved
682 */
683 tmp = (ass & 0x38) >> 3; /* external Amp control */
684 if (spec->init_amp == ALC_INIT_UNDEFINED) {
685 switch (tmp) {
686 case 1:
687 alc_setup_gpio(codec, 0x01);
688 break;
689 case 3:
690 alc_setup_gpio(codec, 0x02);
691 break;
692 case 7:
693 alc_setup_gpio(codec, 0x04);
694 break;
695 case 5:
696 default:
697 spec->init_amp = ALC_INIT_DEFAULT;
698 break;
699 }
700 }
701
702 /* is laptop or Desktop and enable the function "Mute internal speaker
703 * when the external headphone out jack is plugged"
704 */
705 if (!(ass & 0x8000))
706 return 1;
707 /*
708 * 10~8 : Jack location
709 * 12~11: Headphone out -> 00: PortA, 01: PortE, 02: PortD, 03: Resvered
710 * 14~13: Resvered
711 * 15 : 1 --> enable the function "Mute internal speaker
712 * when the external headphone out jack is plugged"
713 */
714 if (!alc_get_hp_pin(spec)) {
715 hda_nid_t nid;
716 tmp = (ass >> 11) & 0x3; /* HP to chassis */
717 nid = ports[tmp];
718 if (found_in_nid_list(nid, spec->gen.autocfg.line_out_pins,
719 spec->gen.autocfg.line_outs))
720 return 1;
721 spec->gen.autocfg.hp_pins[0] = nid;
722 }
723 return 1;
724 }
725 EXPORT_SYMBOL_NS_GPL(alc_subsystem_id, "SND_HDA_CODEC_REALTEK");
726
727 /* Check the validity of ALC subsystem-id
728 * ports contains an array of 4 pin NIDs for port-A, E, D and I */
alc_ssid_check(struct hda_codec * codec,const hda_nid_t * ports)729 void alc_ssid_check(struct hda_codec *codec, const hda_nid_t *ports)
730 {
731 if (!alc_subsystem_id(codec, ports)) {
732 struct alc_spec *spec = codec->spec;
733 if (spec->init_amp == ALC_INIT_UNDEFINED) {
734 codec_dbg(codec,
735 "realtek: Enable default setup for auto mode as fallback\n");
736 spec->init_amp = ALC_INIT_DEFAULT;
737 }
738 }
739 }
740 EXPORT_SYMBOL_NS_GPL(alc_ssid_check, "SND_HDA_CODEC_REALTEK");
741
742 /* inverted digital-mic */
alc_fixup_inv_dmic(struct hda_codec * codec,const struct hda_fixup * fix,int action)743 void alc_fixup_inv_dmic(struct hda_codec *codec,
744 const struct hda_fixup *fix, int action)
745 {
746 struct alc_spec *spec = codec->spec;
747
748 spec->gen.inv_dmic_split = 1;
749 }
750 EXPORT_SYMBOL_NS_GPL(alc_fixup_inv_dmic, "SND_HDA_CODEC_REALTEK");
751
alc_build_controls(struct hda_codec * codec)752 int alc_build_controls(struct hda_codec *codec)
753 {
754 int err;
755
756 err = snd_hda_gen_build_controls(codec);
757 if (err < 0)
758 return err;
759
760 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD);
761 return 0;
762 }
763 EXPORT_SYMBOL_NS_GPL(alc_build_controls, "SND_HDA_CODEC_REALTEK");
764
alc_init(struct hda_codec * codec)765 int alc_init(struct hda_codec *codec)
766 {
767 struct alc_spec *spec = codec->spec;
768
769 /* hibernation resume needs the full chip initialization */
770 if (is_s4_resume(codec))
771 alc_pre_init(codec);
772
773 if (spec->init_hook)
774 spec->init_hook(codec);
775
776 spec->gen.skip_verbs = 1; /* applied in below */
777 snd_hda_gen_init(codec);
778 alc_fix_pll(codec);
779 alc_auto_init_amp(codec, spec->init_amp);
780 snd_hda_apply_verbs(codec); /* apply verbs here after own init */
781
782 snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
783
784 return 0;
785 }
786 EXPORT_SYMBOL_NS_GPL(alc_init, "SND_HDA_CODEC_REALTEK");
787
alc_shutup(struct hda_codec * codec)788 void alc_shutup(struct hda_codec *codec)
789 {
790 struct alc_spec *spec = codec->spec;
791
792 if (!snd_hda_get_bool_hint(codec, "shutup"))
793 return; /* disabled explicitly by hints */
794
795 if (spec && spec->shutup)
796 spec->shutup(codec);
797 else
798 alc_shutup_pins(codec);
799 }
800 EXPORT_SYMBOL_NS_GPL(alc_shutup, "SND_HDA_CODEC_REALTEK");
801
alc_power_eapd(struct hda_codec * codec)802 void alc_power_eapd(struct hda_codec *codec)
803 {
804 alc_auto_setup_eapd(codec, false);
805 }
806 EXPORT_SYMBOL_NS_GPL(alc_power_eapd, "SND_HDA_CODEC_REALTEK");
807
alc_suspend(struct hda_codec * codec)808 int alc_suspend(struct hda_codec *codec)
809 {
810 struct alc_spec *spec = codec->spec;
811 alc_shutup(codec);
812 if (spec && spec->power_hook)
813 spec->power_hook(codec);
814 return 0;
815 }
816 EXPORT_SYMBOL_NS_GPL(alc_suspend, "SND_HDA_CODEC_REALTEK");
817
alc_resume(struct hda_codec * codec)818 int alc_resume(struct hda_codec *codec)
819 {
820 struct alc_spec *spec = codec->spec;
821
822 if (!spec->no_depop_delay)
823 msleep(150); /* to avoid pop noise */
824 snd_hda_codec_init(codec);
825 snd_hda_regmap_sync(codec);
826 hda_call_check_power_status(codec, 0x01);
827 return 0;
828 }
829 EXPORT_SYMBOL_NS_GPL(alc_resume, "SND_HDA_CODEC_REALTEK");
830
831 /*
832 * Rename codecs appropriately from COEF value or subvendor id
833 */
834 struct alc_codec_rename_table {
835 unsigned int vendor_id;
836 unsigned short coef_mask;
837 unsigned short coef_bits;
838 const char *name;
839 };
840
841 struct alc_codec_rename_pci_table {
842 unsigned int codec_vendor_id;
843 unsigned short pci_subvendor;
844 unsigned short pci_subdevice;
845 const char *name;
846 };
847
848 static const struct alc_codec_rename_table rename_tbl[] = {
849 { 0x10ec0221, 0xf00f, 0x1003, "ALC231" },
850 { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
851 { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
852 { 0x10ec0269, 0xf0f0, 0x3010, "ALC258" },
853 { 0x10ec0269, 0x00f0, 0x0010, "ALC269VB" },
854 { 0x10ec0269, 0xffff, 0xa023, "ALC259" },
855 { 0x10ec0269, 0xffff, 0x6023, "ALC281X" },
856 { 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" },
857 { 0x10ec0269, 0x00f0, 0x0030, "ALC269VD" },
858 { 0x10ec0662, 0xffff, 0x4020, "ALC656" },
859 { 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" },
860 { 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" },
861 { 0x10ec0888, 0xf0f0, 0x3020, "ALC886" },
862 { 0x10ec0899, 0x2000, 0x2000, "ALC899" },
863 { 0x10ec0892, 0xffff, 0x8020, "ALC661" },
864 { 0x10ec0892, 0xffff, 0x8011, "ALC661" },
865 { 0x10ec0892, 0xffff, 0x4011, "ALC656" },
866 { } /* terminator */
867 };
868
869 static const struct alc_codec_rename_pci_table rename_pci_tbl[] = {
870 { 0x10ec0280, 0x1028, 0, "ALC3220" },
871 { 0x10ec0282, 0x1028, 0, "ALC3221" },
872 { 0x10ec0283, 0x1028, 0, "ALC3223" },
873 { 0x10ec0288, 0x1028, 0, "ALC3263" },
874 { 0x10ec0292, 0x1028, 0, "ALC3226" },
875 { 0x10ec0293, 0x1028, 0, "ALC3235" },
876 { 0x10ec0255, 0x1028, 0, "ALC3234" },
877 { 0x10ec0668, 0x1028, 0, "ALC3661" },
878 { 0x10ec0275, 0x1028, 0, "ALC3260" },
879 { 0x10ec0899, 0x1028, 0, "ALC3861" },
880 { 0x10ec0298, 0x1028, 0, "ALC3266" },
881 { 0x10ec0236, 0x1028, 0, "ALC3204" },
882 { 0x10ec0256, 0x1028, 0, "ALC3246" },
883 { 0x10ec0225, 0x1028, 0, "ALC3253" },
884 { 0x10ec0295, 0x1028, 0, "ALC3254" },
885 { 0x10ec0299, 0x1028, 0, "ALC3271" },
886 { 0x10ec0670, 0x1025, 0, "ALC669X" },
887 { 0x10ec0676, 0x1025, 0, "ALC679X" },
888 { 0x10ec0282, 0x1043, 0, "ALC3229" },
889 { 0x10ec0233, 0x1043, 0, "ALC3236" },
890 { 0x10ec0280, 0x103c, 0, "ALC3228" },
891 { 0x10ec0282, 0x103c, 0, "ALC3227" },
892 { 0x10ec0286, 0x103c, 0, "ALC3242" },
893 { 0x10ec0290, 0x103c, 0, "ALC3241" },
894 { 0x10ec0668, 0x103c, 0, "ALC3662" },
895 { 0x10ec0283, 0x17aa, 0, "ALC3239" },
896 { 0x10ec0292, 0x17aa, 0, "ALC3232" },
897 { 0x10ec0257, 0x12f0, 0, "ALC3328" },
898 { } /* terminator */
899 };
900
alc_codec_rename_from_preset(struct hda_codec * codec)901 static int alc_codec_rename_from_preset(struct hda_codec *codec)
902 {
903 const struct alc_codec_rename_table *p;
904 const struct alc_codec_rename_pci_table *q;
905
906 for (p = rename_tbl; p->vendor_id; p++) {
907 if (p->vendor_id != codec->core.vendor_id)
908 continue;
909 if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
910 return alc_codec_rename(codec, p->name);
911 }
912
913 if (!codec->bus->pci)
914 return 0;
915 for (q = rename_pci_tbl; q->codec_vendor_id; q++) {
916 if (q->codec_vendor_id != codec->core.vendor_id)
917 continue;
918 if (q->pci_subvendor != codec->bus->pci->subsystem_vendor)
919 continue;
920 if (!q->pci_subdevice ||
921 q->pci_subdevice == codec->bus->pci->subsystem_device)
922 return alc_codec_rename(codec, q->name);
923 }
924
925 return 0;
926 }
927
928 /*
929 * Digital-beep handlers
930 */
931 #ifdef CONFIG_SND_HDA_INPUT_BEEP
932
933 /* additional beep mixers; private_value will be overwritten */
934 static const struct snd_kcontrol_new alc_beep_mixer[] = {
935 HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT),
936 HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT),
937 };
938
939 /* set up and create beep controls */
alc_set_beep_amp(struct alc_spec * spec,hda_nid_t nid,int idx,int dir)940 int alc_set_beep_amp(struct alc_spec *spec, hda_nid_t nid, int idx, int dir)
941 {
942 struct snd_kcontrol_new *knew;
943 unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
944 int i;
945
946 for (i = 0; i < ARRAY_SIZE(alc_beep_mixer); i++) {
947 knew = snd_hda_gen_add_kctl(&spec->gen, NULL,
948 &alc_beep_mixer[i]);
949 if (!knew)
950 return -ENOMEM;
951 knew->private_value = beep_amp;
952 }
953 return 0;
954 }
955 EXPORT_SYMBOL_NS_GPL(alc_set_beep_amp, "SND_HDA_CODEC_REALTEK");
956
957 static const struct snd_pci_quirk beep_allow_list[] = {
958 SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1),
959 SND_PCI_QUIRK(0x1043, 0x115d, "ASUS", 1),
960 SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
961 SND_PCI_QUIRK(0x1043, 0x8376, "EeePC", 1),
962 SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
963 SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
964 SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
965 SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1),
966 SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
967 /* denylist -- no beep available */
968 SND_PCI_QUIRK(0x17aa, 0x309e, "Lenovo ThinkCentre M73", 0),
969 SND_PCI_QUIRK(0x17aa, 0x30a3, "Lenovo ThinkCentre M93", 0),
970 {}
971 };
972
alc_has_cdefine_beep(struct hda_codec * codec)973 int alc_has_cdefine_beep(struct hda_codec *codec)
974 {
975 struct alc_spec *spec = codec->spec;
976 const struct snd_pci_quirk *q;
977 q = snd_pci_quirk_lookup(codec->bus->pci, beep_allow_list);
978 if (q)
979 return q->value;
980 return spec->cdefine.enable_pcbeep;
981 }
982 EXPORT_SYMBOL_NS_GPL(alc_has_cdefine_beep, "SND_HDA_CODEC_REALTEK");
983
984 #endif /* CONFIG_SND_HDA_INPUT_BEEP */
985
986 /* parse the BIOS configuration and set up the alc_spec */
987 /* return 1 if successful, 0 if the proper config is not found,
988 * or a negative error code
989 */
alc_parse_auto_config(struct hda_codec * codec,const hda_nid_t * ignore_nids,const hda_nid_t * ssid_nids)990 int alc_parse_auto_config(struct hda_codec *codec,
991 const hda_nid_t *ignore_nids,
992 const hda_nid_t *ssid_nids)
993 {
994 struct alc_spec *spec = codec->spec;
995 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
996 int err;
997
998 err = snd_hda_parse_pin_defcfg(codec, cfg, ignore_nids,
999 spec->parse_flags);
1000 if (err < 0)
1001 return err;
1002
1003 if (ssid_nids)
1004 alc_ssid_check(codec, ssid_nids);
1005
1006 err = snd_hda_gen_parse_auto_config(codec, cfg);
1007 if (err < 0)
1008 return err;
1009
1010 return 1;
1011 }
1012 EXPORT_SYMBOL_NS_GPL(alc_parse_auto_config, "SND_HDA_CODEC_REALTEK");
1013
1014 /* common preparation job for alc_spec */
alc_alloc_spec(struct hda_codec * codec,hda_nid_t mixer_nid)1015 int alc_alloc_spec(struct hda_codec *codec, hda_nid_t mixer_nid)
1016 {
1017 struct alc_spec *spec = kzalloc_obj(*spec);
1018 int err;
1019
1020 if (!spec)
1021 return -ENOMEM;
1022 codec->spec = spec;
1023 snd_hda_gen_spec_init(&spec->gen);
1024 spec->gen.mixer_nid = mixer_nid;
1025 spec->gen.own_eapd_ctl = 1;
1026 codec->single_adc_amp = 1;
1027 /* FIXME: do we need this for all Realtek codec models? */
1028 codec->spdif_status_reset = 1;
1029 codec->forced_resume = 1;
1030 mutex_init(&spec->coef_mutex);
1031
1032 err = alc_codec_rename_from_preset(codec);
1033 if (err < 0) {
1034 kfree(spec);
1035 return err;
1036 }
1037 return 0;
1038 }
1039 EXPORT_SYMBOL_NS_GPL(alc_alloc_spec, "SND_HDA_CODEC_REALTEK");
1040
1041 /* For dual-codec configuration, we need to disable some features to avoid
1042 * conflicts of kctls and PCM streams
1043 */
alc_fixup_dual_codecs(struct hda_codec * codec,const struct hda_fixup * fix,int action)1044 void alc_fixup_dual_codecs(struct hda_codec *codec,
1045 const struct hda_fixup *fix, int action)
1046 {
1047 struct alc_spec *spec = codec->spec;
1048
1049 if (action != HDA_FIXUP_ACT_PRE_PROBE)
1050 return;
1051 /* disable vmaster */
1052 spec->gen.suppress_vmaster = 1;
1053 /* auto-mute and auto-mic switch don't work with multiple codecs */
1054 spec->gen.suppress_auto_mute = 1;
1055 spec->gen.suppress_auto_mic = 1;
1056 /* disable aamix as well */
1057 spec->gen.mixer_nid = 0;
1058 /* add location prefix to avoid conflicts */
1059 codec->force_pin_prefix = 1;
1060 }
1061 EXPORT_SYMBOL_NS_GPL(alc_fixup_dual_codecs, "SND_HDA_CODEC_REALTEK");
1062
1063 static const struct snd_pcm_chmap_elem asus_pcm_2_1_chmaps[] = {
1064 { .channels = 2,
1065 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },
1066 { .channels = 4,
1067 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR,
1068 SNDRV_CHMAP_NA, SNDRV_CHMAP_LFE } }, /* LFE only on right */
1069 { }
1070 };
1071
1072 /* override the 2.1 chmap */
alc_fixup_bass_chmap(struct hda_codec * codec,const struct hda_fixup * fix,int action)1073 void alc_fixup_bass_chmap(struct hda_codec *codec,
1074 const struct hda_fixup *fix, int action)
1075 {
1076 if (action == HDA_FIXUP_ACT_BUILD) {
1077 struct alc_spec *spec = codec->spec;
1078 spec->gen.pcm_rec[0]->stream[0].chmap = asus_pcm_2_1_chmaps;
1079 }
1080 }
1081 EXPORT_SYMBOL_NS_GPL(alc_fixup_bass_chmap, "SND_HDA_CODEC_REALTEK");
1082
1083 /* exported as it's used by multiple codecs */
alc1220_fixup_gb_dual_codecs(struct hda_codec * codec,const struct hda_fixup * fix,int action)1084 void alc1220_fixup_gb_dual_codecs(struct hda_codec *codec,
1085 const struct hda_fixup *fix,
1086 int action)
1087 {
1088 alc_fixup_dual_codecs(codec, fix, action);
1089 switch (action) {
1090 case HDA_FIXUP_ACT_PRE_PROBE:
1091 /* override card longname to provide a unique UCM profile */
1092 strscpy(codec->card->longname, "HDAudio-Gigabyte-ALC1220DualCodecs");
1093 break;
1094 case HDA_FIXUP_ACT_BUILD:
1095 /* rename Capture controls depending on the codec */
1096 rename_ctl(codec, "Capture Volume",
1097 codec->addr == 0 ?
1098 "Rear-Panel Capture Volume" :
1099 "Front-Panel Capture Volume");
1100 rename_ctl(codec, "Capture Switch",
1101 codec->addr == 0 ?
1102 "Rear-Panel Capture Switch" :
1103 "Front-Panel Capture Switch");
1104 break;
1105 }
1106 }
1107 EXPORT_SYMBOL_NS_GPL(alc1220_fixup_gb_dual_codecs, "SND_HDA_CODEC_REALTEK");
1108
alc233_alc662_fixup_lenovo_dual_codecs(struct hda_codec * codec,const struct hda_fixup * fix,int action)1109 void alc233_alc662_fixup_lenovo_dual_codecs(struct hda_codec *codec,
1110 const struct hda_fixup *fix,
1111 int action)
1112 {
1113 alc_fixup_dual_codecs(codec, fix, action);
1114 switch (action) {
1115 case HDA_FIXUP_ACT_PRE_PROBE:
1116 /* override card longname to provide a unique UCM profile */
1117 strscpy(codec->card->longname, "HDAudio-Lenovo-DualCodecs");
1118 break;
1119 case HDA_FIXUP_ACT_BUILD:
1120 /* rename Capture controls depending on the codec */
1121 rename_ctl(codec, "Capture Volume",
1122 codec->addr == 0 ?
1123 "Rear-Panel Capture Volume" :
1124 "Front-Panel Capture Volume");
1125 rename_ctl(codec, "Capture Switch",
1126 codec->addr == 0 ?
1127 "Rear-Panel Capture Switch" :
1128 "Front-Panel Capture Switch");
1129 break;
1130 }
1131 }
1132 EXPORT_SYMBOL_NS_GPL(alc233_alc662_fixup_lenovo_dual_codecs, "SND_HDA_CODEC_REALTEK");
1133
alc_shutup_dell_xps13(struct hda_codec * codec)1134 static void alc_shutup_dell_xps13(struct hda_codec *codec)
1135 {
1136 struct alc_spec *spec = codec->spec;
1137 int hp_pin = alc_get_hp_pin(spec);
1138
1139 /* Prevent pop noises when headphones are plugged in */
1140 snd_hda_codec_write(codec, hp_pin, 0,
1141 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
1142 msleep(20);
1143 }
1144
alc_fixup_dell_xps13(struct hda_codec * codec,const struct hda_fixup * fix,int action)1145 void alc_fixup_dell_xps13(struct hda_codec *codec,
1146 const struct hda_fixup *fix, int action)
1147 {
1148 struct alc_spec *spec = codec->spec;
1149 struct hda_input_mux *imux = &spec->gen.input_mux;
1150 int i;
1151
1152 switch (action) {
1153 case HDA_FIXUP_ACT_PRE_PROBE:
1154 /* mic pin 0x19 must be initialized with Vref Hi-Z, otherwise
1155 * it causes a click noise at start up
1156 */
1157 snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
1158 spec->shutup = alc_shutup_dell_xps13;
1159 break;
1160 case HDA_FIXUP_ACT_PROBE:
1161 /* Make the internal mic the default input source. */
1162 for (i = 0; i < imux->num_items; i++) {
1163 if (spec->gen.imux_pins[i] == 0x12) {
1164 spec->gen.cur_mux[0] = i;
1165 break;
1166 }
1167 }
1168 break;
1169 }
1170 }
1171 EXPORT_SYMBOL_NS_GPL(alc_fixup_dell_xps13, "SND_HDA_CODEC_REALTEK");
1172
1173 /*
1174 * headset handling
1175 */
1176
alc_hp_mute_disable(struct hda_codec * codec,unsigned int delay)1177 static void alc_hp_mute_disable(struct hda_codec *codec, unsigned int delay)
1178 {
1179 if (delay <= 0)
1180 delay = 75;
1181 snd_hda_codec_write(codec, 0x21, 0,
1182 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
1183 msleep(delay);
1184 snd_hda_codec_write(codec, 0x21, 0,
1185 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
1186 msleep(delay);
1187 }
1188
alc_hp_enable_unmute(struct hda_codec * codec,unsigned int delay)1189 static void alc_hp_enable_unmute(struct hda_codec *codec, unsigned int delay)
1190 {
1191 if (delay <= 0)
1192 delay = 75;
1193 snd_hda_codec_write(codec, 0x21, 0,
1194 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
1195 msleep(delay);
1196 snd_hda_codec_write(codec, 0x21, 0,
1197 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
1198 msleep(delay);
1199 }
1200
1201 static const struct coef_fw alc225_pre_hsmode[] = {
1202 UPDATE_COEF(0x4a, 1<<8, 0),
1203 UPDATE_COEFEX(0x57, 0x05, 1<<14, 0),
1204 UPDATE_COEF(0x63, 3<<14, 3<<14),
1205 UPDATE_COEF(0x4a, 3<<4, 2<<4),
1206 UPDATE_COEF(0x4a, 3<<10, 3<<10),
1207 UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10),
1208 UPDATE_COEF(0x4a, 3<<10, 0),
1209 {}
1210 };
1211
alc_headset_mode_unplugged(struct hda_codec * codec)1212 static void alc_headset_mode_unplugged(struct hda_codec *codec)
1213 {
1214 struct alc_spec *spec = codec->spec;
1215 static const struct coef_fw coef0255[] = {
1216 WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
1217 WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
1218 UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
1219 WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
1220 WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */
1221 {}
1222 };
1223 static const struct coef_fw coef0256[] = {
1224 WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */
1225 WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
1226 WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
1227 WRITE_COEFEX(0x57, 0x03, 0x09a3), /* Direct Drive HP Amp control */
1228 UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
1229 {}
1230 };
1231 static const struct coef_fw coef0233[] = {
1232 WRITE_COEF(0x1b, 0x0c0b),
1233 WRITE_COEF(0x45, 0xc429),
1234 UPDATE_COEF(0x35, 0x4000, 0),
1235 WRITE_COEF(0x06, 0x2104),
1236 WRITE_COEF(0x1a, 0x0001),
1237 WRITE_COEF(0x26, 0x0004),
1238 WRITE_COEF(0x32, 0x42a3),
1239 {}
1240 };
1241 static const struct coef_fw coef0288[] = {
1242 UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
1243 UPDATE_COEF(0x50, 0x2000, 0x2000),
1244 UPDATE_COEF(0x56, 0x0006, 0x0006),
1245 UPDATE_COEF(0x66, 0x0008, 0),
1246 UPDATE_COEF(0x67, 0x2000, 0),
1247 {}
1248 };
1249 static const struct coef_fw coef0298[] = {
1250 UPDATE_COEF(0x19, 0x1300, 0x0300),
1251 {}
1252 };
1253 static const struct coef_fw coef0292[] = {
1254 WRITE_COEF(0x76, 0x000e),
1255 WRITE_COEF(0x6c, 0x2400),
1256 WRITE_COEF(0x18, 0x7308),
1257 WRITE_COEF(0x6b, 0xc429),
1258 {}
1259 };
1260 static const struct coef_fw coef0293[] = {
1261 UPDATE_COEF(0x10, 7<<8, 6<<8), /* SET Line1 JD to 0 */
1262 UPDATE_COEFEX(0x57, 0x05, 1<<15|1<<13, 0x0), /* SET charge pump by verb */
1263 UPDATE_COEFEX(0x57, 0x03, 1<<10, 1<<10), /* SET EN_OSW to 1 */
1264 UPDATE_COEF(0x1a, 1<<3, 1<<3), /* Combo JD gating with LINE1-VREFO */
1265 WRITE_COEF(0x45, 0xc429), /* Set to TRS type */
1266 UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */
1267 {}
1268 };
1269 static const struct coef_fw coef0668[] = {
1270 WRITE_COEF(0x15, 0x0d40),
1271 WRITE_COEF(0xb7, 0x802b),
1272 {}
1273 };
1274 static const struct coef_fw coef0225[] = {
1275 UPDATE_COEF(0x63, 3<<14, 0),
1276 {}
1277 };
1278 static const struct coef_fw coef0274[] = {
1279 UPDATE_COEF(0x4a, 0x0100, 0),
1280 UPDATE_COEFEX(0x57, 0x05, 0x4000, 0),
1281 UPDATE_COEF(0x6b, 0xf000, 0x5000),
1282 UPDATE_COEF(0x4a, 0x0010, 0),
1283 UPDATE_COEF(0x4a, 0x0c00, 0x0c00),
1284 WRITE_COEF(0x45, 0x5289),
1285 UPDATE_COEF(0x4a, 0x0c00, 0),
1286 {}
1287 };
1288
1289 if (spec->no_internal_mic_pin) {
1290 alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
1291 return;
1292 }
1293
1294 switch (codec->core.vendor_id) {
1295 case 0x10ec0235:
1296 case 0x10ec0255:
1297 alc_process_coef_fw(codec, coef0255);
1298 break;
1299 case 0x10ec0230:
1300 case 0x10ec0236:
1301 case 0x10ec0256:
1302 case 0x19e58326:
1303 alc_hp_mute_disable(codec, 75);
1304 alc_process_coef_fw(codec, coef0256);
1305 break;
1306 case 0x10ec0234:
1307 case 0x10ec0274:
1308 case 0x10ec0294:
1309 alc_process_coef_fw(codec, coef0274);
1310 break;
1311 case 0x10ec0233:
1312 case 0x10ec0283:
1313 alc_process_coef_fw(codec, coef0233);
1314 break;
1315 case 0x10ec0286:
1316 case 0x10ec0288:
1317 alc_process_coef_fw(codec, coef0288);
1318 break;
1319 case 0x10ec0298:
1320 alc_process_coef_fw(codec, coef0298);
1321 alc_process_coef_fw(codec, coef0288);
1322 break;
1323 case 0x10ec0292:
1324 alc_process_coef_fw(codec, coef0292);
1325 break;
1326 case 0x10ec0293:
1327 alc_process_coef_fw(codec, coef0293);
1328 break;
1329 case 0x10ec0668:
1330 alc_process_coef_fw(codec, coef0668);
1331 break;
1332 case 0x10ec0215:
1333 case 0x10ec0225:
1334 case 0x10ec0285:
1335 case 0x10ec0295:
1336 case 0x10ec0289:
1337 case 0x10ec0299:
1338 alc_hp_mute_disable(codec, 75);
1339 alc_process_coef_fw(codec, alc225_pre_hsmode);
1340 alc_process_coef_fw(codec, coef0225);
1341 break;
1342 case 0x10ec0867:
1343 alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
1344 break;
1345 }
1346 codec_dbg(codec, "Headset jack set to unplugged mode.\n");
1347 }
1348
1349
alc_headset_mode_mic_in(struct hda_codec * codec,hda_nid_t hp_pin,hda_nid_t mic_pin)1350 static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
1351 hda_nid_t mic_pin)
1352 {
1353 static const struct coef_fw coef0255[] = {
1354 WRITE_COEFEX(0x57, 0x03, 0x8aa6),
1355 WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */
1356 {}
1357 };
1358 static const struct coef_fw coef0256[] = {
1359 UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14), /* Direct Drive HP Amp control(Set to verb control)*/
1360 WRITE_COEFEX(0x57, 0x03, 0x09a3),
1361 WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */
1362 {}
1363 };
1364 static const struct coef_fw coef0233[] = {
1365 UPDATE_COEF(0x35, 0, 1<<14),
1366 WRITE_COEF(0x06, 0x2100),
1367 WRITE_COEF(0x1a, 0x0021),
1368 WRITE_COEF(0x26, 0x008c),
1369 {}
1370 };
1371 static const struct coef_fw coef0288[] = {
1372 UPDATE_COEF(0x4f, 0x00c0, 0),
1373 UPDATE_COEF(0x50, 0x2000, 0),
1374 UPDATE_COEF(0x56, 0x0006, 0),
1375 UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
1376 UPDATE_COEF(0x66, 0x0008, 0x0008),
1377 UPDATE_COEF(0x67, 0x2000, 0x2000),
1378 {}
1379 };
1380 static const struct coef_fw coef0292[] = {
1381 WRITE_COEF(0x19, 0xa208),
1382 WRITE_COEF(0x2e, 0xacf0),
1383 {}
1384 };
1385 static const struct coef_fw coef0293[] = {
1386 UPDATE_COEFEX(0x57, 0x05, 0, 1<<15|1<<13), /* SET charge pump by verb */
1387 UPDATE_COEFEX(0x57, 0x03, 1<<10, 0), /* SET EN_OSW to 0 */
1388 UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */
1389 {}
1390 };
1391 static const struct coef_fw coef0688[] = {
1392 WRITE_COEF(0xb7, 0x802b),
1393 WRITE_COEF(0xb5, 0x1040),
1394 UPDATE_COEF(0xc3, 0, 1<<12),
1395 {}
1396 };
1397 static const struct coef_fw coef0225[] = {
1398 UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14),
1399 UPDATE_COEF(0x4a, 3<<4, 2<<4),
1400 UPDATE_COEF(0x63, 3<<14, 0),
1401 {}
1402 };
1403 static const struct coef_fw coef0274[] = {
1404 UPDATE_COEFEX(0x57, 0x05, 0x4000, 0x4000),
1405 UPDATE_COEF(0x4a, 0x0010, 0),
1406 UPDATE_COEF(0x6b, 0xf000, 0),
1407 {}
1408 };
1409
1410 switch (codec->core.vendor_id) {
1411 case 0x10ec0235:
1412 case 0x10ec0255:
1413 alc_write_coef_idx(codec, 0x45, 0xc489);
1414 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1415 alc_process_coef_fw(codec, coef0255);
1416 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1417 break;
1418 case 0x10ec0230:
1419 case 0x10ec0236:
1420 case 0x10ec0256:
1421 case 0x19e58326:
1422 alc_write_coef_idx(codec, 0x45, 0xc489);
1423 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1424 alc_process_coef_fw(codec, coef0256);
1425 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1426 break;
1427 case 0x10ec0234:
1428 case 0x10ec0274:
1429 case 0x10ec0294:
1430 alc_write_coef_idx(codec, 0x45, 0x4689);
1431 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1432 alc_process_coef_fw(codec, coef0274);
1433 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1434 break;
1435 case 0x10ec0233:
1436 case 0x10ec0283:
1437 alc_write_coef_idx(codec, 0x45, 0xc429);
1438 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1439 alc_process_coef_fw(codec, coef0233);
1440 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1441 break;
1442 case 0x10ec0286:
1443 case 0x10ec0288:
1444 case 0x10ec0298:
1445 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1446 alc_process_coef_fw(codec, coef0288);
1447 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1448 break;
1449 case 0x10ec0292:
1450 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1451 alc_process_coef_fw(codec, coef0292);
1452 break;
1453 case 0x10ec0293:
1454 /* Set to TRS mode */
1455 alc_write_coef_idx(codec, 0x45, 0xc429);
1456 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1457 alc_process_coef_fw(codec, coef0293);
1458 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1459 break;
1460 case 0x10ec0867:
1461 alc_update_coefex_idx(codec, 0x57, 0x5, 0, 1<<14);
1462 fallthrough;
1463 case 0x10ec0221:
1464 case 0x10ec0662:
1465 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1466 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1467 break;
1468 case 0x10ec0668:
1469 alc_write_coef_idx(codec, 0x11, 0x0001);
1470 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1471 alc_process_coef_fw(codec, coef0688);
1472 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1473 break;
1474 case 0x10ec0215:
1475 case 0x10ec0225:
1476 case 0x10ec0285:
1477 case 0x10ec0295:
1478 case 0x10ec0289:
1479 case 0x10ec0299:
1480 alc_process_coef_fw(codec, alc225_pre_hsmode);
1481 alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10);
1482 snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
1483 alc_process_coef_fw(codec, coef0225);
1484 snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
1485 break;
1486 }
1487 codec_dbg(codec, "Headset jack set to mic-in mode.\n");
1488 }
1489
alc_headset_mode_default(struct hda_codec * codec)1490 static void alc_headset_mode_default(struct hda_codec *codec)
1491 {
1492 static const struct coef_fw coef0225[] = {
1493 UPDATE_COEF(0x45, 0x3f<<10, 0x30<<10),
1494 UPDATE_COEF(0x45, 0x3f<<10, 0x31<<10),
1495 UPDATE_COEF(0x49, 3<<8, 0<<8),
1496 UPDATE_COEF(0x4a, 3<<4, 3<<4),
1497 UPDATE_COEF(0x63, 3<<14, 0),
1498 UPDATE_COEF(0x67, 0xf000, 0x3000),
1499 {}
1500 };
1501 static const struct coef_fw coef0255[] = {
1502 WRITE_COEF(0x45, 0xc089),
1503 WRITE_COEF(0x45, 0xc489),
1504 WRITE_COEFEX(0x57, 0x03, 0x8ea6),
1505 WRITE_COEF(0x49, 0x0049),
1506 {}
1507 };
1508 static const struct coef_fw coef0256[] = {
1509 WRITE_COEF(0x45, 0xc489),
1510 WRITE_COEFEX(0x57, 0x03, 0x0da3),
1511 WRITE_COEF(0x49, 0x0049),
1512 UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
1513 WRITE_COEF(0x06, 0x6100),
1514 {}
1515 };
1516 static const struct coef_fw coef0233[] = {
1517 WRITE_COEF(0x06, 0x2100),
1518 WRITE_COEF(0x32, 0x4ea3),
1519 {}
1520 };
1521 static const struct coef_fw coef0288[] = {
1522 UPDATE_COEF(0x4f, 0xfcc0, 0xc400), /* Set to TRS type */
1523 UPDATE_COEF(0x50, 0x2000, 0x2000),
1524 UPDATE_COEF(0x56, 0x0006, 0x0006),
1525 UPDATE_COEF(0x66, 0x0008, 0),
1526 UPDATE_COEF(0x67, 0x2000, 0),
1527 {}
1528 };
1529 static const struct coef_fw coef0292[] = {
1530 WRITE_COEF(0x76, 0x000e),
1531 WRITE_COEF(0x6c, 0x2400),
1532 WRITE_COEF(0x6b, 0xc429),
1533 WRITE_COEF(0x18, 0x7308),
1534 {}
1535 };
1536 static const struct coef_fw coef0293[] = {
1537 UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */
1538 WRITE_COEF(0x45, 0xC429), /* Set to TRS type */
1539 UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */
1540 {}
1541 };
1542 static const struct coef_fw coef0688[] = {
1543 WRITE_COEF(0x11, 0x0041),
1544 WRITE_COEF(0x15, 0x0d40),
1545 WRITE_COEF(0xb7, 0x802b),
1546 {}
1547 };
1548 static const struct coef_fw coef0274[] = {
1549 WRITE_COEF(0x45, 0x4289),
1550 UPDATE_COEF(0x4a, 0x0010, 0x0010),
1551 UPDATE_COEF(0x6b, 0x0f00, 0),
1552 UPDATE_COEF(0x49, 0x0300, 0x0300),
1553 {}
1554 };
1555
1556 switch (codec->core.vendor_id) {
1557 case 0x10ec0215:
1558 case 0x10ec0225:
1559 case 0x10ec0285:
1560 case 0x10ec0295:
1561 case 0x10ec0289:
1562 case 0x10ec0299:
1563 alc_process_coef_fw(codec, alc225_pre_hsmode);
1564 alc_process_coef_fw(codec, coef0225);
1565 alc_hp_enable_unmute(codec, 75);
1566 break;
1567 case 0x10ec0235:
1568 case 0x10ec0255:
1569 alc_process_coef_fw(codec, coef0255);
1570 break;
1571 case 0x10ec0230:
1572 case 0x10ec0236:
1573 case 0x10ec0256:
1574 case 0x19e58326:
1575 alc_write_coef_idx(codec, 0x1b, 0x0e4b);
1576 alc_write_coef_idx(codec, 0x45, 0xc089);
1577 msleep(50);
1578 alc_process_coef_fw(codec, coef0256);
1579 alc_hp_enable_unmute(codec, 75);
1580 break;
1581 case 0x10ec0234:
1582 case 0x10ec0274:
1583 case 0x10ec0294:
1584 alc_process_coef_fw(codec, coef0274);
1585 break;
1586 case 0x10ec0233:
1587 case 0x10ec0283:
1588 alc_process_coef_fw(codec, coef0233);
1589 break;
1590 case 0x10ec0286:
1591 case 0x10ec0288:
1592 case 0x10ec0298:
1593 alc_process_coef_fw(codec, coef0288);
1594 break;
1595 case 0x10ec0292:
1596 alc_process_coef_fw(codec, coef0292);
1597 break;
1598 case 0x10ec0293:
1599 alc_process_coef_fw(codec, coef0293);
1600 break;
1601 case 0x10ec0668:
1602 alc_process_coef_fw(codec, coef0688);
1603 break;
1604 case 0x10ec0867:
1605 alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
1606 break;
1607 }
1608 codec_dbg(codec, "Headset jack set to headphone (default) mode.\n");
1609 }
1610
1611 /* Iphone type */
alc_headset_mode_ctia(struct hda_codec * codec)1612 static void alc_headset_mode_ctia(struct hda_codec *codec)
1613 {
1614 int val;
1615
1616 static const struct coef_fw coef0255[] = {
1617 WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
1618 WRITE_COEF(0x1b, 0x0c2b),
1619 WRITE_COEFEX(0x57, 0x03, 0x8ea6),
1620 {}
1621 };
1622 static const struct coef_fw coef0256[] = {
1623 WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
1624 WRITE_COEF(0x1b, 0x0e6b),
1625 {}
1626 };
1627 static const struct coef_fw coef0233[] = {
1628 WRITE_COEF(0x45, 0xd429),
1629 WRITE_COEF(0x1b, 0x0c2b),
1630 WRITE_COEF(0x32, 0x4ea3),
1631 {}
1632 };
1633 static const struct coef_fw coef0288[] = {
1634 UPDATE_COEF(0x50, 0x2000, 0x2000),
1635 UPDATE_COEF(0x56, 0x0006, 0x0006),
1636 UPDATE_COEF(0x66, 0x0008, 0),
1637 UPDATE_COEF(0x67, 0x2000, 0),
1638 {}
1639 };
1640 static const struct coef_fw coef0292[] = {
1641 WRITE_COEF(0x6b, 0xd429),
1642 WRITE_COEF(0x76, 0x0008),
1643 WRITE_COEF(0x18, 0x7388),
1644 {}
1645 };
1646 static const struct coef_fw coef0293[] = {
1647 WRITE_COEF(0x45, 0xd429), /* Set to ctia type */
1648 UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */
1649 {}
1650 };
1651 static const struct coef_fw coef0688[] = {
1652 WRITE_COEF(0x11, 0x0001),
1653 WRITE_COEF(0x15, 0x0d60),
1654 WRITE_COEF(0xc3, 0x0000),
1655 {}
1656 };
1657 static const struct coef_fw coef0225_1[] = {
1658 UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10),
1659 UPDATE_COEF(0x63, 3<<14, 2<<14),
1660 {}
1661 };
1662 static const struct coef_fw coef0225_2[] = {
1663 UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10),
1664 UPDATE_COEF(0x63, 3<<14, 1<<14),
1665 {}
1666 };
1667
1668 switch (codec->core.vendor_id) {
1669 case 0x10ec0235:
1670 case 0x10ec0255:
1671 alc_process_coef_fw(codec, coef0255);
1672 break;
1673 case 0x10ec0230:
1674 case 0x10ec0236:
1675 case 0x10ec0256:
1676 case 0x19e58326:
1677 alc_process_coef_fw(codec, coef0256);
1678 alc_hp_enable_unmute(codec, 75);
1679 break;
1680 case 0x10ec0234:
1681 case 0x10ec0274:
1682 case 0x10ec0294:
1683 alc_write_coef_idx(codec, 0x45, 0xd689);
1684 break;
1685 case 0x10ec0233:
1686 case 0x10ec0283:
1687 alc_process_coef_fw(codec, coef0233);
1688 break;
1689 case 0x10ec0298:
1690 val = alc_read_coef_idx(codec, 0x50);
1691 if (val & (1 << 12)) {
1692 alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020);
1693 alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
1694 msleep(300);
1695 } else {
1696 alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);
1697 alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
1698 msleep(300);
1699 }
1700 break;
1701 case 0x10ec0286:
1702 case 0x10ec0288:
1703 alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xd400);
1704 msleep(300);
1705 alc_process_coef_fw(codec, coef0288);
1706 break;
1707 case 0x10ec0292:
1708 alc_process_coef_fw(codec, coef0292);
1709 break;
1710 case 0x10ec0293:
1711 alc_process_coef_fw(codec, coef0293);
1712 break;
1713 case 0x10ec0668:
1714 alc_process_coef_fw(codec, coef0688);
1715 break;
1716 case 0x10ec0215:
1717 case 0x10ec0225:
1718 case 0x10ec0285:
1719 case 0x10ec0295:
1720 case 0x10ec0289:
1721 case 0x10ec0299:
1722 val = alc_read_coef_idx(codec, 0x45);
1723 if (val & (1 << 9))
1724 alc_process_coef_fw(codec, coef0225_2);
1725 else
1726 alc_process_coef_fw(codec, coef0225_1);
1727 alc_hp_enable_unmute(codec, 75);
1728 break;
1729 case 0x10ec0867:
1730 alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
1731 break;
1732 }
1733 codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n");
1734 }
1735
1736 /* Nokia type */
alc_headset_mode_omtp(struct hda_codec * codec)1737 static void alc_headset_mode_omtp(struct hda_codec *codec)
1738 {
1739 static const struct coef_fw coef0255[] = {
1740 WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
1741 WRITE_COEF(0x1b, 0x0c2b),
1742 WRITE_COEFEX(0x57, 0x03, 0x8ea6),
1743 {}
1744 };
1745 static const struct coef_fw coef0256[] = {
1746 WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
1747 WRITE_COEF(0x1b, 0x0e6b),
1748 {}
1749 };
1750 static const struct coef_fw coef0233[] = {
1751 WRITE_COEF(0x45, 0xe429),
1752 WRITE_COEF(0x1b, 0x0c2b),
1753 WRITE_COEF(0x32, 0x4ea3),
1754 {}
1755 };
1756 static const struct coef_fw coef0288[] = {
1757 UPDATE_COEF(0x50, 0x2000, 0x2000),
1758 UPDATE_COEF(0x56, 0x0006, 0x0006),
1759 UPDATE_COEF(0x66, 0x0008, 0),
1760 UPDATE_COEF(0x67, 0x2000, 0),
1761 {}
1762 };
1763 static const struct coef_fw coef0292[] = {
1764 WRITE_COEF(0x6b, 0xe429),
1765 WRITE_COEF(0x76, 0x0008),
1766 WRITE_COEF(0x18, 0x7388),
1767 {}
1768 };
1769 static const struct coef_fw coef0293[] = {
1770 WRITE_COEF(0x45, 0xe429), /* Set to omtp type */
1771 UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */
1772 {}
1773 };
1774 static const struct coef_fw coef0688[] = {
1775 WRITE_COEF(0x11, 0x0001),
1776 WRITE_COEF(0x15, 0x0d50),
1777 WRITE_COEF(0xc3, 0x0000),
1778 {}
1779 };
1780 static const struct coef_fw coef0225[] = {
1781 UPDATE_COEF(0x45, 0x3f<<10, 0x39<<10),
1782 UPDATE_COEF(0x63, 3<<14, 2<<14),
1783 {}
1784 };
1785
1786 switch (codec->core.vendor_id) {
1787 case 0x10ec0235:
1788 case 0x10ec0255:
1789 alc_process_coef_fw(codec, coef0255);
1790 break;
1791 case 0x10ec0230:
1792 case 0x10ec0236:
1793 case 0x10ec0256:
1794 case 0x19e58326:
1795 alc_process_coef_fw(codec, coef0256);
1796 alc_hp_enable_unmute(codec, 75);
1797 break;
1798 case 0x10ec0234:
1799 case 0x10ec0274:
1800 case 0x10ec0294:
1801 alc_write_coef_idx(codec, 0x45, 0xe689);
1802 break;
1803 case 0x10ec0233:
1804 case 0x10ec0283:
1805 alc_process_coef_fw(codec, coef0233);
1806 break;
1807 case 0x10ec0298:
1808 alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);/* Headset output enable */
1809 alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400);
1810 msleep(300);
1811 break;
1812 case 0x10ec0286:
1813 case 0x10ec0288:
1814 alc_update_coef_idx(codec, 0x4f, 0xfcc0, 0xe400);
1815 msleep(300);
1816 alc_process_coef_fw(codec, coef0288);
1817 break;
1818 case 0x10ec0292:
1819 alc_process_coef_fw(codec, coef0292);
1820 break;
1821 case 0x10ec0293:
1822 alc_process_coef_fw(codec, coef0293);
1823 break;
1824 case 0x10ec0668:
1825 alc_process_coef_fw(codec, coef0688);
1826 break;
1827 case 0x10ec0215:
1828 case 0x10ec0225:
1829 case 0x10ec0285:
1830 case 0x10ec0295:
1831 case 0x10ec0289:
1832 case 0x10ec0299:
1833 alc_process_coef_fw(codec, coef0225);
1834 alc_hp_enable_unmute(codec, 75);
1835 break;
1836 }
1837 codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n");
1838 }
1839
alc_determine_headset_type(struct hda_codec * codec)1840 static void alc_determine_headset_type(struct hda_codec *codec)
1841 {
1842 int val;
1843 bool is_ctia = false;
1844 struct alc_spec *spec = codec->spec;
1845 static const struct coef_fw coef0255[] = {
1846 WRITE_COEF(0x45, 0xd089), /* combo jack auto switch control(Check type)*/
1847 WRITE_COEF(0x49, 0x0149), /* combo jack auto switch control(Vref
1848 conteol) */
1849 {}
1850 };
1851 static const struct coef_fw coef0288[] = {
1852 UPDATE_COEF(0x4f, 0xfcc0, 0xd400), /* Check Type */
1853 {}
1854 };
1855 static const struct coef_fw coef0298[] = {
1856 UPDATE_COEF(0x50, 0x2000, 0x2000),
1857 UPDATE_COEF(0x56, 0x0006, 0x0006),
1858 UPDATE_COEF(0x66, 0x0008, 0),
1859 UPDATE_COEF(0x67, 0x2000, 0),
1860 UPDATE_COEF(0x19, 0x1300, 0x1300),
1861 {}
1862 };
1863 static const struct coef_fw coef0293[] = {
1864 UPDATE_COEF(0x4a, 0x000f, 0x0008), /* Combo Jack auto detect */
1865 WRITE_COEF(0x45, 0xD429), /* Set to ctia type */
1866 {}
1867 };
1868 static const struct coef_fw coef0688[] = {
1869 WRITE_COEF(0x11, 0x0001),
1870 WRITE_COEF(0xb7, 0x802b),
1871 WRITE_COEF(0x15, 0x0d60),
1872 WRITE_COEF(0xc3, 0x0c00),
1873 {}
1874 };
1875 static const struct coef_fw coef0274[] = {
1876 UPDATE_COEF(0x4a, 0x0010, 0),
1877 UPDATE_COEF(0x4a, 0x8000, 0),
1878 WRITE_COEF(0x45, 0xd289),
1879 UPDATE_COEF(0x49, 0x0300, 0x0300),
1880 {}
1881 };
1882
1883 if (spec->no_internal_mic_pin) {
1884 alc_update_coef_idx(codec, 0x45, 0xf<<12 | 1<<10, 5<<12);
1885 return;
1886 }
1887
1888 switch (codec->core.vendor_id) {
1889 case 0x10ec0235:
1890 case 0x10ec0255:
1891 alc_process_coef_fw(codec, coef0255);
1892 msleep(300);
1893 val = alc_read_coef_idx(codec, 0x46);
1894 is_ctia = (val & 0x0070) == 0x0070;
1895 break;
1896 case 0x10ec0230:
1897 case 0x10ec0236:
1898 case 0x10ec0256:
1899 case 0x19e58326:
1900 alc_write_coef_idx(codec, 0x1b, 0x0e4b);
1901 alc_write_coef_idx(codec, 0x06, 0x6104);
1902 alc_write_coefex_idx(codec, 0x57, 0x3, 0x09a3);
1903
1904 alc_process_coef_fw(codec, coef0255);
1905 msleep(300);
1906 val = alc_read_coef_idx(codec, 0x46);
1907 is_ctia = (val & 0x0070) == 0x0070;
1908 if (!is_ctia) {
1909 alc_write_coef_idx(codec, 0x45, 0xe089);
1910 msleep(100);
1911 val = alc_read_coef_idx(codec, 0x46);
1912 if ((val & 0x0070) == 0x0070)
1913 is_ctia = false;
1914 else
1915 is_ctia = true;
1916 }
1917 alc_write_coefex_idx(codec, 0x57, 0x3, 0x0da3);
1918 alc_update_coefex_idx(codec, 0x57, 0x5, 1<<14, 0);
1919 break;
1920 case 0x10ec0234:
1921 case 0x10ec0274:
1922 case 0x10ec0294:
1923 alc_process_coef_fw(codec, coef0274);
1924 msleep(850);
1925 val = alc_read_coef_idx(codec, 0x46);
1926 is_ctia = (val & 0x00f0) == 0x00f0;
1927 break;
1928 case 0x10ec0233:
1929 case 0x10ec0283:
1930 alc_write_coef_idx(codec, 0x45, 0xd029);
1931 msleep(300);
1932 val = alc_read_coef_idx(codec, 0x46);
1933 is_ctia = (val & 0x0070) == 0x0070;
1934 break;
1935 case 0x10ec0298:
1936 snd_hda_codec_write(codec, 0x21, 0,
1937 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
1938 msleep(100);
1939 snd_hda_codec_write(codec, 0x21, 0,
1940 AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
1941 msleep(200);
1942
1943 val = alc_read_coef_idx(codec, 0x50);
1944 if (val & (1 << 12)) {
1945 alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0020);
1946 alc_process_coef_fw(codec, coef0288);
1947 msleep(350);
1948 val = alc_read_coef_idx(codec, 0x50);
1949 is_ctia = (val & 0x0070) == 0x0070;
1950 } else {
1951 alc_update_coef_idx(codec, 0x8e, 0x0070, 0x0010);
1952 alc_process_coef_fw(codec, coef0288);
1953 msleep(350);
1954 val = alc_read_coef_idx(codec, 0x50);
1955 is_ctia = (val & 0x0070) == 0x0070;
1956 }
1957 alc_process_coef_fw(codec, coef0298);
1958 snd_hda_codec_write(codec, 0x21, 0,
1959 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
1960 msleep(75);
1961 snd_hda_codec_write(codec, 0x21, 0,
1962 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
1963 break;
1964 case 0x10ec0286:
1965 case 0x10ec0288:
1966 alc_process_coef_fw(codec, coef0288);
1967 msleep(350);
1968 val = alc_read_coef_idx(codec, 0x50);
1969 is_ctia = (val & 0x0070) == 0x0070;
1970 break;
1971 case 0x10ec0292:
1972 alc_write_coef_idx(codec, 0x6b, 0xd429);
1973 msleep(300);
1974 val = alc_read_coef_idx(codec, 0x6c);
1975 is_ctia = (val & 0x001c) == 0x001c;
1976 break;
1977 case 0x10ec0293:
1978 alc_process_coef_fw(codec, coef0293);
1979 msleep(300);
1980 val = alc_read_coef_idx(codec, 0x46);
1981 is_ctia = (val & 0x0070) == 0x0070;
1982 break;
1983 case 0x10ec0668:
1984 alc_process_coef_fw(codec, coef0688);
1985 msleep(300);
1986 val = alc_read_coef_idx(codec, 0xbe);
1987 is_ctia = (val & 0x1c02) == 0x1c02;
1988 break;
1989 case 0x10ec0215:
1990 case 0x10ec0225:
1991 case 0x10ec0285:
1992 case 0x10ec0295:
1993 case 0x10ec0289:
1994 case 0x10ec0299:
1995 alc_process_coef_fw(codec, alc225_pre_hsmode);
1996 alc_update_coef_idx(codec, 0x67, 0xf000, 0x1000);
1997 val = alc_read_coef_idx(codec, 0x45);
1998 if (val & (1 << 9)) {
1999 alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x34<<10);
2000 alc_update_coef_idx(codec, 0x49, 3<<8, 2<<8);
2001 msleep(800);
2002 val = alc_read_coef_idx(codec, 0x46);
2003 is_ctia = (val & 0x00f0) == 0x00f0;
2004 } else {
2005 alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x34<<10);
2006 alc_update_coef_idx(codec, 0x49, 3<<8, 1<<8);
2007 msleep(800);
2008 val = alc_read_coef_idx(codec, 0x46);
2009 is_ctia = (val & 0x00f0) == 0x00f0;
2010 }
2011 if (!is_ctia) {
2012 alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x38<<10);
2013 alc_update_coef_idx(codec, 0x49, 3<<8, 1<<8);
2014 msleep(100);
2015 val = alc_read_coef_idx(codec, 0x46);
2016 if ((val & 0x00f0) == 0x00f0)
2017 is_ctia = false;
2018 else
2019 is_ctia = true;
2020 }
2021 alc_update_coef_idx(codec, 0x4a, 7<<6, 7<<6);
2022 alc_update_coef_idx(codec, 0x4a, 3<<4, 3<<4);
2023 alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000);
2024 break;
2025 case 0x10ec0867:
2026 is_ctia = true;
2027 break;
2028 }
2029
2030 codec_dbg(codec, "Headset jack detected iPhone-style headset: %s\n",
2031 str_yes_no(is_ctia));
2032 spec->current_headset_type = is_ctia ? ALC_HEADSET_TYPE_CTIA : ALC_HEADSET_TYPE_OMTP;
2033 }
2034
alc_update_headset_mode(struct hda_codec * codec)2035 static void alc_update_headset_mode(struct hda_codec *codec)
2036 {
2037 struct alc_spec *spec = codec->spec;
2038
2039 hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
2040 hda_nid_t hp_pin = alc_get_hp_pin(spec);
2041
2042 int new_headset_mode;
2043
2044 if (!snd_hda_jack_detect(codec, hp_pin))
2045 new_headset_mode = ALC_HEADSET_MODE_UNPLUGGED;
2046 else if (mux_pin == spec->headset_mic_pin)
2047 new_headset_mode = ALC_HEADSET_MODE_HEADSET;
2048 else if (mux_pin == spec->headphone_mic_pin)
2049 new_headset_mode = ALC_HEADSET_MODE_MIC;
2050 else
2051 new_headset_mode = ALC_HEADSET_MODE_HEADPHONE;
2052
2053 if (new_headset_mode == spec->current_headset_mode) {
2054 snd_hda_gen_update_outputs(codec);
2055 return;
2056 }
2057
2058 switch (new_headset_mode) {
2059 case ALC_HEADSET_MODE_UNPLUGGED:
2060 alc_headset_mode_unplugged(codec);
2061 spec->current_headset_mode = ALC_HEADSET_MODE_UNKNOWN;
2062 spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
2063 spec->gen.hp_jack_present = false;
2064 break;
2065 case ALC_HEADSET_MODE_HEADSET:
2066 if (spec->current_headset_type == ALC_HEADSET_TYPE_UNKNOWN)
2067 alc_determine_headset_type(codec);
2068 if (spec->current_headset_type == ALC_HEADSET_TYPE_CTIA)
2069 alc_headset_mode_ctia(codec);
2070 else if (spec->current_headset_type == ALC_HEADSET_TYPE_OMTP)
2071 alc_headset_mode_omtp(codec);
2072 spec->gen.hp_jack_present = true;
2073 break;
2074 case ALC_HEADSET_MODE_MIC:
2075 alc_headset_mode_mic_in(codec, hp_pin, spec->headphone_mic_pin);
2076 spec->gen.hp_jack_present = false;
2077 break;
2078 case ALC_HEADSET_MODE_HEADPHONE:
2079 alc_headset_mode_default(codec);
2080 spec->gen.hp_jack_present = true;
2081 break;
2082 }
2083 if (new_headset_mode != ALC_HEADSET_MODE_MIC) {
2084 snd_hda_set_pin_ctl_cache(codec, hp_pin,
2085 AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
2086 if (spec->headphone_mic_pin && spec->headphone_mic_pin != hp_pin)
2087 snd_hda_set_pin_ctl_cache(codec, spec->headphone_mic_pin,
2088 PIN_VREFHIZ);
2089 }
2090 spec->current_headset_mode = new_headset_mode;
2091
2092 snd_hda_gen_update_outputs(codec);
2093 }
2094
alc_update_headset_mode_hook(struct hda_codec * codec,struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2095 static void alc_update_headset_mode_hook(struct hda_codec *codec,
2096 struct snd_kcontrol *kcontrol,
2097 struct snd_ctl_elem_value *ucontrol)
2098 {
2099 alc_update_headset_mode(codec);
2100 }
2101
alc_update_headset_jack_cb(struct hda_codec * codec,struct hda_jack_callback * jack)2102 void alc_update_headset_jack_cb(struct hda_codec *codec,
2103 struct hda_jack_callback *jack)
2104 {
2105 snd_hda_gen_hp_automute(codec, jack);
2106 alc_update_headset_mode(codec);
2107 }
2108 EXPORT_SYMBOL_NS_GPL(alc_update_headset_jack_cb, "SND_HDA_CODEC_REALTEK");
2109
alc_probe_headset_mode(struct hda_codec * codec)2110 static void alc_probe_headset_mode(struct hda_codec *codec)
2111 {
2112 int i;
2113 struct alc_spec *spec = codec->spec;
2114 struct auto_pin_cfg *cfg = &spec->gen.autocfg;
2115
2116 /* Find mic pins */
2117 for (i = 0; i < cfg->num_inputs; i++) {
2118 if (cfg->inputs[i].is_headset_mic && !spec->headset_mic_pin)
2119 spec->headset_mic_pin = cfg->inputs[i].pin;
2120 if (cfg->inputs[i].is_headphone_mic && !spec->headphone_mic_pin)
2121 spec->headphone_mic_pin = cfg->inputs[i].pin;
2122 }
2123
2124 WARN_ON(spec->gen.cap_sync_hook);
2125 spec->gen.cap_sync_hook = alc_update_headset_mode_hook;
2126 spec->gen.automute_hook = alc_update_headset_mode;
2127 spec->gen.hp_automute_hook = alc_update_headset_jack_cb;
2128 }
2129
alc_fixup_headset_mode(struct hda_codec * codec,const struct hda_fixup * fix,int action)2130 void alc_fixup_headset_mode(struct hda_codec *codec,
2131 const struct hda_fixup *fix, int action)
2132 {
2133 struct alc_spec *spec = codec->spec;
2134
2135 switch (action) {
2136 case HDA_FIXUP_ACT_PRE_PROBE:
2137 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC | HDA_PINCFG_HEADPHONE_MIC;
2138 break;
2139 case HDA_FIXUP_ACT_PROBE:
2140 alc_probe_headset_mode(codec);
2141 break;
2142 case HDA_FIXUP_ACT_INIT:
2143 if (is_s3_resume(codec) || is_s4_resume(codec)) {
2144 spec->current_headset_mode = ALC_HEADSET_MODE_UNKNOWN;
2145 spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN;
2146 }
2147 alc_update_headset_mode(codec);
2148 break;
2149 }
2150 }
2151 EXPORT_SYMBOL_NS_GPL(alc_fixup_headset_mode, "SND_HDA_CODEC_REALTEK");
2152
alc_fixup_headset_mode_no_hp_mic(struct hda_codec * codec,const struct hda_fixup * fix,int action)2153 void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
2154 const struct hda_fixup *fix, int action)
2155 {
2156 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
2157 struct alc_spec *spec = codec->spec;
2158 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
2159 } else
2160 alc_fixup_headset_mode(codec, fix, action);
2161 }
2162 EXPORT_SYMBOL_NS_GPL(alc_fixup_headset_mode_no_hp_mic, "SND_HDA_CODEC_REALTEK");
2163
alc_fixup_headset_mic(struct hda_codec * codec,const struct hda_fixup * fix,int action)2164 void alc_fixup_headset_mic(struct hda_codec *codec,
2165 const struct hda_fixup *fix, int action)
2166 {
2167 struct alc_spec *spec = codec->spec;
2168
2169 if (action == HDA_FIXUP_ACT_PRE_PROBE)
2170 spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
2171 }
2172 EXPORT_SYMBOL_NS_GPL(alc_fixup_headset_mic, "SND_HDA_CODEC_REALTEK");
2173
2174 /* update LED status via GPIO */
alc_update_gpio_led(struct hda_codec * codec,unsigned int mask,int polarity,bool enabled)2175 void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask,
2176 int polarity, bool enabled)
2177 {
2178 if (polarity)
2179 enabled = !enabled;
2180 alc_update_gpio_data(codec, mask, !enabled); /* muted -> LED on */
2181 }
2182 EXPORT_SYMBOL_NS_GPL(alc_update_gpio_led, "SND_HDA_CODEC_REALTEK");
2183
2184 /* turn on/off mic-mute LED via GPIO per capture hook */
micmute_led_set(struct led_classdev * led_cdev,enum led_brightness brightness)2185 static int micmute_led_set(struct led_classdev *led_cdev,
2186 enum led_brightness brightness)
2187 {
2188 struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
2189 struct alc_spec *spec = codec->spec;
2190
2191 alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
2192 spec->micmute_led_polarity, !brightness);
2193 return 0;
2194 }
2195
2196 /* turn on/off mute LED via GPIO per vmaster hook */
gpio_mute_led_set(struct led_classdev * led_cdev,enum led_brightness brightness)2197 static int gpio_mute_led_set(struct led_classdev *led_cdev,
2198 enum led_brightness brightness)
2199 {
2200 struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
2201 struct alc_spec *spec = codec->spec;
2202
2203 alc_update_gpio_led(codec, spec->gpio_mute_led_mask,
2204 spec->mute_led_polarity, !brightness);
2205 return 0;
2206 }
2207
2208 /* setup mute and mic-mute GPIO bits, add hooks appropriately */
alc_fixup_hp_gpio_led(struct hda_codec * codec,int action,unsigned int mute_mask,unsigned int micmute_mask)2209 void alc_fixup_hp_gpio_led(struct hda_codec *codec,
2210 int action,
2211 unsigned int mute_mask,
2212 unsigned int micmute_mask)
2213 {
2214 struct alc_spec *spec = codec->spec;
2215
2216 alc_fixup_gpio(codec, action, mute_mask | micmute_mask);
2217
2218 if (action != HDA_FIXUP_ACT_PRE_PROBE)
2219 return;
2220 if (mute_mask) {
2221 spec->gpio_mute_led_mask = mute_mask;
2222 snd_hda_gen_add_mute_led_cdev(codec, gpio_mute_led_set);
2223 }
2224 if (micmute_mask) {
2225 spec->gpio_mic_led_mask = micmute_mask;
2226 snd_hda_gen_add_micmute_led_cdev(codec, micmute_led_set);
2227 }
2228 }
2229 EXPORT_SYMBOL_NS_GPL(alc_fixup_hp_gpio_led, "SND_HDA_CODEC_REALTEK");
2230
2231 /* suppress the jack-detection */
alc_fixup_no_jack_detect(struct hda_codec * codec,const struct hda_fixup * fix,int action)2232 void alc_fixup_no_jack_detect(struct hda_codec *codec,
2233 const struct hda_fixup *fix, int action)
2234 {
2235 if (action == HDA_FIXUP_ACT_PRE_PROBE)
2236 codec->no_jack_detect = 1;
2237 }
2238 EXPORT_SYMBOL_NS_GPL(alc_fixup_no_jack_detect, "SND_HDA_CODEC_REALTEK");
2239
alc_fixup_disable_aamix(struct hda_codec * codec,const struct hda_fixup * fix,int action)2240 void alc_fixup_disable_aamix(struct hda_codec *codec,
2241 const struct hda_fixup *fix, int action)
2242 {
2243 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
2244 struct alc_spec *spec = codec->spec;
2245 /* Disable AA-loopback as it causes white noise */
2246 spec->gen.mixer_nid = 0;
2247 }
2248 }
2249 EXPORT_SYMBOL_NS_GPL(alc_fixup_disable_aamix, "SND_HDA_CODEC_REALTEK");
2250
alc_fixup_auto_mute_via_amp(struct hda_codec * codec,const struct hda_fixup * fix,int action)2251 void alc_fixup_auto_mute_via_amp(struct hda_codec *codec,
2252 const struct hda_fixup *fix, int action)
2253 {
2254 if (action == HDA_FIXUP_ACT_PRE_PROBE) {
2255 struct alc_spec *spec = codec->spec;
2256 spec->gen.auto_mute_via_amp = 1;
2257 }
2258 }
2259 EXPORT_SYMBOL_NS_GPL(alc_fixup_auto_mute_via_amp, "SND_HDA_CODEC_REALTEK");
2260
2261 MODULE_IMPORT_NS("SND_HDA_SCODEC_COMPONENT");
2262 MODULE_LICENSE("GPL");
2263 MODULE_DESCRIPTION("Realtek HD-audio codec helper");
2264