xref: /freebsd/sys/dev/sound/pci/hda/hdaa_patches.c (revision 32100375a661c1e16588ddfa7b90ca8d26cb9786)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
5  * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
6  * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 /*
32  * Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
33  */
34 
35 #ifdef HAVE_KERNEL_OPTION_HEADERS
36 #include "opt_snd.h"
37 #endif
38 
39 #include <dev/sound/pcm/sound.h>
40 
41 #include <sys/ctype.h>
42 
43 #include <dev/sound/pci/hda/hdac.h>
44 #include <dev/sound/pci/hda/hdaa.h>
45 #include <dev/sound/pci/hda/hda_reg.h>
46 
47 SND_DECLARE_FILE("$FreeBSD$");
48 
49 static const struct {
50 	uint32_t model;
51 	uint32_t id;
52 	uint32_t subsystemid;
53 	uint32_t set, unset;
54 	uint32_t gpio;
55 } hdac_quirks[] = {
56 	/*
57 	 * XXX Force stereo quirk. Monoural recording / playback
58 	 *     on few codecs (especially ALC880) seems broken or
59 	 *     perhaps unsupported.
60 	 */
61 	{ HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_MATCH_ALL,
62 	    HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
63 	    0 },
64 	{ ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, HDA_MATCH_ALL,
65 	    0, 0,
66 	    HDAA_GPIO_SET(0) },
67 	{ ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, HDA_MATCH_ALL,
68 	    0, 0,
69 	    HDAA_GPIO_SET(0) },
70 	{ ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
71 	    0, 0,
72 	    HDAA_GPIO_SET(0) },
73 	{ ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
74 	    0, 0,
75 	    HDAA_GPIO_SET(0) },
76 	{ ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
77 	    0, 0,
78 	    HDAA_GPIO_SET(0) },
79 	{ ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
80 	    0, 0,
81 	    HDAA_GPIO_SET(0) },
82 	{ ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
83 	    HDAA_QUIRK_EAPDINV, 0,
84 	    0 },
85 	{ ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
86 	    HDAA_QUIRK_EAPDINV, 0,
87 	    0 },
88 	{ ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
89 	    HDAA_QUIRK_OVREF, 0,
90 	    0 },
91 	{ UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
92 	    HDAA_QUIRK_OVREF, 0,
93 	    0 },
94 	/*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, HDA_MATCH_ALL,
95 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
96 	    0 },*/
97 	{ MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
98 	    0, 0,
99 	    HDAA_GPIO_SET(1) },
100 	{ LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
101 	    HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
102 	    0 },
103 	{ SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
104 	    HDAA_QUIRK_EAPDINV, 0,
105 	    0 },
106 	{ APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDA_MATCH_ALL,
107 	    HDAA_QUIRK_OVREF50, 0,
108 	    HDAA_GPIO_SET(0) },
109 	{ APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDA_MATCH_ALL,
110 	    0, 0,
111 	    HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
112 	{ APPLE_MACBOOKAIR31, HDA_CODEC_CS4206, HDA_MATCH_ALL,
113 	    0, 0,
114 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
115 	{ APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
116 	    0, 0,
117 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
118 	{ APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL,
119 	    0, 0,
120 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
121 	{ HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL,
122 	    0, 0,
123 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
124 	{ DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
125 	    0, 0,
126 	    HDAA_GPIO_SET(0) },
127 	{ DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
128 	    0, 0,
129 	    HDAA_GPIO_SET(2) },
130 	{ DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
131 	    0, 0,
132 	    HDAA_GPIO_SET(0) },
133 	{ HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
134 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
135 	    0 },
136 	{ HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
137 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
138 	    0 },
139 	{ HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
140 	    0, HDAA_QUIRK_FORCESTEREO,
141 	    0 },
142 	/* Mac Pro 1,1 requires ovref for proper volume level. */
143 	{ 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
144 	    0, HDAA_QUIRK_OVREF,
145 	    0 }
146 };
147 
148 static void
149 hdac_pin_patch(struct hdaa_widget *w)
150 {
151 	const char *patch = NULL;
152 	uint32_t config, orig, id, subid;
153 	nid_t nid = w->nid;
154 
155 	config = orig = w->wclass.pin.config;
156 	id = hdaa_codec_id(w->devinfo);
157 	subid = hdaa_card_id(w->devinfo);
158 
159 	/* XXX: Old patches require complete review.
160 	 * Now they may create more problem then solve due to
161 	 * incorrect associations.
162 	 */
163 	if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) {
164 		switch (nid) {
165 		case 26:
166 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
167 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
168 			break;
169 		case 27:
170 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
171 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT;
172 			break;
173 		default:
174 			break;
175 		}
176 	} else if (id == HDA_CODEC_ALC880 &&
177 	    (subid == CLEVO_D900T_SUBVENDOR ||
178 	    subid == ASUS_M5200_SUBVENDOR)) {
179 		/*
180 		 * Super broken BIOS
181 		 */
182 		switch (nid) {
183 		case 24:	/* MIC1 */
184 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
185 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
186 			break;
187 		case 25:	/* XXX MIC2 */
188 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
189 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
190 			break;
191 		case 26:	/* LINE1 */
192 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
193 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
194 			break;
195 		case 27:	/* XXX LINE2 */
196 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
197 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
198 			break;
199 		case 28:	/* CD */
200 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
201 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD;
202 			break;
203 		}
204 	} else if (id == HDA_CODEC_ALC883 &&
205 	    (subid == MSI_MS034A_SUBVENDOR ||
206 	    HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) {
207 		switch (nid) {
208 		case 25:
209 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
210 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
211 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
212 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
213 			break;
214 		case 28:
215 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
216 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
217 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
218 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
219 			break;
220 		}
221 	} else if (id == HDA_CODEC_CX20549 && subid ==
222 	    HP_V3000_SUBVENDOR) {
223 		switch (nid) {
224 		case 18:
225 			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
226 			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
227 			break;
228 		case 20:
229 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
230 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
231 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
232 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
233 			break;
234 		case 21:
235 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
236 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
237 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
238 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
239 			break;
240 		}
241 	} else if (id == HDA_CODEC_CX20551 && subid ==
242 	    HP_DV5000_SUBVENDOR) {
243 		switch (nid) {
244 		case 20:
245 		case 21:
246 			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
247 			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
248 			break;
249 		}
250 	} else if (id == HDA_CODEC_ALC861 && subid ==
251 	    ASUS_W6F_SUBVENDOR) {
252 		switch (nid) {
253 		case 11:
254 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
255 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
256 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
257 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
258 			break;
259 		case 12:
260 		case 14:
261 		case 16:
262 		case 31:
263 		case 32:
264 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
265 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
266 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
267 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
268 			break;
269 		case 15:
270 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
271 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
272 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
273 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
274 			break;
275 		}
276 	} else if (id == HDA_CODEC_ALC861 && subid ==
277 	    UNIWILL_9075_SUBVENDOR) {
278 		switch (nid) {
279 		case 15:
280 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
281 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
282 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
283 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
284 			break;
285 		}
286 	}
287 
288 	/* New patches */
289 	if (id == HDA_CODEC_AD1984A &&
290 	    subid == LENOVO_X300_SUBVENDOR) {
291 		switch (nid) {
292 		case 17: /* Headphones with redirection */
293 			patch = "as=1 seq=15";
294 			break;
295 		case 20: /* Two mics together */
296 			patch = "as=2 seq=15";
297 			break;
298 		}
299 	} else if (id == HDA_CODEC_AD1986A &&
300 	    (subid == ASUS_M2NPVMX_SUBVENDOR ||
301 	    subid == ASUS_A8NVMCSM_SUBVENDOR ||
302 	    subid == ASUS_P5PL2_SUBVENDOR)) {
303 		switch (nid) {
304 		case 26: /* Headphones with redirection */
305 			patch = "as=1 seq=15";
306 			break;
307 		case 28: /* 5.1 out => 2.0 out + 1 input */
308 			patch = "device=Line-in as=8 seq=1";
309 			break;
310 		case 29: /* Can't use this as input, as the only available mic
311 			  * preamplifier is busy by front panel mic (nid 31).
312 			  * If you want to use this rear connector as mic input,
313 			  * you have to disable the front panel one. */
314 			patch = "as=0";
315 			break;
316 		case 31: /* Lot of inputs configured with as=15 and unusable */
317 			patch = "as=8 seq=3";
318 			break;
319 		case 32:
320 			patch = "as=8 seq=4";
321 			break;
322 		case 34:
323 			patch = "as=8 seq=5";
324 			break;
325 		case 36:
326 			patch = "as=8 seq=6";
327 			break;
328 		}
329 	} else if (id == HDA_CODEC_ALC260 &&
330 	    HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
331 		switch (nid) {
332 		case 16:
333 			patch = "seq=15 device=Headphones";
334 			break;
335 		}
336 	} else if (id == HDA_CODEC_ALC268) {
337 	    if (subid == ACER_T5320_SUBVENDOR) {
338 		switch (nid) {
339 		case 20: /* Headphones Jack */
340 			patch = "as=1 seq=15";
341 			break;
342 		}
343 	    }
344 	} else if (id == HDA_CODEC_CX20561 &&
345 	    subid == LENOVO_B450_SUBVENDOR) {
346 		switch (nid) {
347 		case 22:
348 			patch = "as=1 seq=15";
349 			break;
350 		}
351 	} else if (id == HDA_CODEC_CX20561 &&
352 	    subid == LENOVO_T400_SUBVENDOR) {
353 		switch (nid) {
354 		case 22:
355 			patch = "as=1 seq=15";
356 			break;
357 		case 26:
358 			patch = "as=1 seq=0";
359 			break;
360 		}
361 	} else if (id == HDA_CODEC_CX20590 &&
362 	    (subid == LENOVO_X1_SUBVENDOR ||
363 	    subid == LENOVO_X220_SUBVENDOR ||
364 	    subid == LENOVO_T420_SUBVENDOR ||
365 	    subid == LENOVO_T520_SUBVENDOR ||
366 	    subid == LENOVO_G580_SUBVENDOR)) {
367 		switch (nid) {
368 		case 25:
369 			patch = "as=1 seq=15";
370 			break;
371 		/*
372 		 * Group onboard mic and headphone mic
373 		 * together.  Fixes onboard mic.
374 		 */
375 		case 27:
376 			patch = "as=2 seq=15";
377 			break;
378 		case 35:
379 			patch = "as=2";
380 			break;
381 		}
382 	} else if (id == HDA_CODEC_ALC269 &&
383 	    (subid == LENOVO_X1CRBN_SUBVENDOR ||
384 	    subid == LENOVO_T430_SUBVENDOR ||
385 	    subid == LENOVO_T430S_SUBVENDOR ||
386 	    subid == LENOVO_T530_SUBVENDOR)) {
387 		switch (nid) {
388 		case 21:
389 			patch = "as=1 seq=15";
390 			break;
391 		}
392 	} else if (id == HDA_CODEC_ALC285 &&
393 	    (subid == LENOVO_X120KH_SUBVENDOR ||
394 	    subid == LENOVO_X120QD_SUBVENDOR)) {
395 		switch (nid) {
396 		case 33:
397 			patch = "as=1 seq=15";
398 			break;
399 		}
400 	} else if (id == HDA_CODEC_ALC269 &&
401 	    subid == ASUS_UX31A_SUBVENDOR) {
402 		switch (nid) {
403 		case 33:
404 			patch = "as=1 seq=15";
405 			break;
406 		}
407 	} else if (id == HDA_CODEC_ALC892 &&
408 	    subid == INTEL_DH87RL_SUBVENDOR) {
409 		switch (nid) {
410 		case 27:
411 			patch = "as=1 seq=15";
412 			break;
413 		}
414 	} else if (id == HDA_CODEC_ALC292 &&
415 	    subid == LENOVO_X120BS_SUBVENDOR) {
416 		switch (nid) {
417 		case 21:
418 			patch = "as=1 seq=15";
419 			break;
420 		}
421 	} else if (id == HDA_CODEC_ALC295 && subid == HP_AF006UR_SUBVENDOR) {
422 		switch (nid) {
423 		case 18:
424 			patch = "as=2";
425 			break;
426 		case 25:
427 			patch = "as=2 seq=15";
428 			break;
429 		case 33:
430 			patch = "as=1 seq=15";
431 			break;
432 		}
433 	} else if (id == HDA_CODEC_ALC298 && HDA_DEV_MATCH(LENOVO_ALL_SUBVENDOR, subid)) {
434 		switch (nid) {
435 		case 23:
436 			config = 0x03a1103f;
437 			break;
438 		case 33:
439 			config = 0x2121101f;
440 			break;
441 		}
442 	} else if (id == HDA_CODEC_ALC298 && subid == DELL_XPS9560_SUBVENDOR) {
443 		switch (nid) {
444 		case 24:
445 			config = 0x01a1913c;
446 			break;
447 		case 26:
448 			config = 0x01a1913d;
449 			break;
450 		}
451 	} else if (id == HDA_CODEC_ALC256 && (subid == DELL_I7577_SUBVENDOR ||
452 	    subid == DELL_L7480_SUBVENDOR)) {
453 		switch (nid) {
454 		case 20:
455 			patch = "as=1 seq=0";
456 			break;
457 		case 33:
458 			patch = "as=1 seq=15";
459 			break;
460 		}
461 	}
462 
463 	if (patch != NULL)
464 		config = hdaa_widget_pin_patch(config, patch);
465 	HDA_BOOTVERBOSE(
466 		if (config != orig)
467 			device_printf(w->devinfo->dev,
468 			    "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
469 			    nid, orig, config);
470 	);
471 	w->wclass.pin.config = config;
472 }
473 
474 static void
475 hdaa_widget_patch(struct hdaa_widget *w)
476 {
477 	struct hdaa_devinfo *devinfo = w->devinfo;
478 	uint32_t orig;
479 	nid_t beeper = -1;
480 
481 	orig = w->param.widget_cap;
482 	/* On some codecs beeper is an input pin, but it is not recordable
483 	   alone. Also most of BIOSes does not declare beeper pin.
484 	   Change beeper pin node type to beeper to help parser. */
485 	switch (hdaa_codec_id(devinfo)) {
486 	case HDA_CODEC_AD1882:
487 	case HDA_CODEC_AD1883:
488 	case HDA_CODEC_AD1984:
489 	case HDA_CODEC_AD1984A:
490 	case HDA_CODEC_AD1984B:
491 	case HDA_CODEC_AD1987:
492 	case HDA_CODEC_AD1988:
493 	case HDA_CODEC_AD1988B:
494 	case HDA_CODEC_AD1989B:
495 		beeper = 26;
496 		break;
497 	case HDA_CODEC_ALC260:
498 		beeper = 23;
499 		break;
500 	}
501 	if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
502 	    hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
503 		beeper = 29;
504 	if (w->nid == beeper) {
505 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
506 		w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
507 		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
508 		w->waspin = 1;
509 	}
510 	/*
511 	 * Clear "digital" flag from digital mic input, as its signal then goes
512 	 * to "analog" mixer and this separation just limits functionaity.
513 	 */
514 	if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
515 	    w->nid == 23)
516 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
517 	HDA_BOOTVERBOSE(
518 		if (w->param.widget_cap != orig) {
519 			device_printf(w->devinfo->dev,
520 			    "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
521 			    w->nid, orig, w->param.widget_cap);
522 		}
523 	);
524 
525 	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
526 		hdac_pin_patch(w);
527 }
528 
529 void
530 hdaa_patch(struct hdaa_devinfo *devinfo)
531 {
532 	struct hdaa_widget *w;
533 	uint32_t id, subid, subsystemid;
534 	int i;
535 
536 	id = hdaa_codec_id(devinfo);
537 	subid = hdaa_card_id(devinfo);
538 	subsystemid = hda_get_subsystem_id(devinfo->dev);
539 
540 	/*
541 	 * Quirks
542 	 */
543 	for (i = 0; i < nitems(hdac_quirks); i++) {
544 		if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
545 		    HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
546 		    HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
547 			continue;
548 		devinfo->quirks |= hdac_quirks[i].set;
549 		devinfo->quirks &= ~(hdac_quirks[i].unset);
550 		devinfo->gpio = hdac_quirks[i].gpio;
551 	}
552 
553 	/* Apply per-widget patch. */
554 	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
555 		w = hdaa_widget_get(devinfo, i);
556 		if (w == NULL)
557 			continue;
558 		hdaa_widget_patch(w);
559 	}
560 
561 	switch (id) {
562 	case HDA_CODEC_AD1983:
563 		/*
564 		 * This CODEC has several possible usages, but none
565 		 * fit the parser best. Help parser to choose better.
566 		 */
567 		/* Disable direct unmixed playback to get pcm volume. */
568 		w = hdaa_widget_get(devinfo, 5);
569 		if (w != NULL)
570 			w->connsenable[0] = 0;
571 		w = hdaa_widget_get(devinfo, 6);
572 		if (w != NULL)
573 			w->connsenable[0] = 0;
574 		w = hdaa_widget_get(devinfo, 11);
575 		if (w != NULL)
576 			w->connsenable[0] = 0;
577 		/* Disable mic and line selectors. */
578 		w = hdaa_widget_get(devinfo, 12);
579 		if (w != NULL)
580 			w->connsenable[1] = 0;
581 		w = hdaa_widget_get(devinfo, 13);
582 		if (w != NULL)
583 			w->connsenable[1] = 0;
584 		/* Disable recording from mono playback mix. */
585 		w = hdaa_widget_get(devinfo, 20);
586 		if (w != NULL)
587 			w->connsenable[3] = 0;
588 		break;
589 	case HDA_CODEC_AD1986A:
590 		/*
591 		 * This CODEC has overcomplicated input mixing.
592 		 * Make some cleaning there.
593 		 */
594 		/* Disable input mono mixer. Not needed and not supported. */
595 		w = hdaa_widget_get(devinfo, 43);
596 		if (w != NULL)
597 			w->enable = 0;
598 		/* Disable any with any input mixing mesh. Use separately. */
599 		w = hdaa_widget_get(devinfo, 39);
600 		if (w != NULL)
601 			w->enable = 0;
602 		w = hdaa_widget_get(devinfo, 40);
603 		if (w != NULL)
604 			w->enable = 0;
605 		w = hdaa_widget_get(devinfo, 41);
606 		if (w != NULL)
607 			w->enable = 0;
608 		w = hdaa_widget_get(devinfo, 42);
609 		if (w != NULL)
610 			w->enable = 0;
611 		/* Disable duplicate mixer node connector. */
612 		w = hdaa_widget_get(devinfo, 15);
613 		if (w != NULL)
614 			w->connsenable[3] = 0;
615 		/* There is only one mic preamplifier, use it effectively. */
616 		w = hdaa_widget_get(devinfo, 31);
617 		if (w != NULL) {
618 			if ((w->wclass.pin.config &
619 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
620 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
621 				w = hdaa_widget_get(devinfo, 16);
622 				if (w != NULL)
623 				    w->connsenable[2] = 0;
624 			} else {
625 				w = hdaa_widget_get(devinfo, 15);
626 				if (w != NULL)
627 				    w->connsenable[0] = 0;
628 			}
629 		}
630 		w = hdaa_widget_get(devinfo, 32);
631 		if (w != NULL) {
632 			if ((w->wclass.pin.config &
633 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
634 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
635 				w = hdaa_widget_get(devinfo, 16);
636 				if (w != NULL)
637 				    w->connsenable[0] = 0;
638 			} else {
639 				w = hdaa_widget_get(devinfo, 15);
640 				if (w != NULL)
641 				    w->connsenable[1] = 0;
642 			}
643 		}
644 
645 		if (subid == ASUS_A8X_SUBVENDOR) {
646 			/*
647 			 * This is just plain ridiculous.. There
648 			 * are several A8 series that share the same
649 			 * pci id but works differently (EAPD).
650 			 */
651 			w = hdaa_widget_get(devinfo, 26);
652 			if (w != NULL && w->type ==
653 			    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
654 			    (w->wclass.pin.config &
655 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
656 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
657 				devinfo->quirks &=
658 				    ~HDAA_QUIRK_EAPDINV;
659 		}
660 		break;
661 	case HDA_CODEC_AD1981HD:
662 		/*
663 		 * This CODEC has very unusual design with several
664 		 * points inappropriate for the present parser.
665 		 */
666 		/* Disable recording from mono playback mix. */
667 		w = hdaa_widget_get(devinfo, 21);
668 		if (w != NULL)
669 			w->connsenable[3] = 0;
670 		/* Disable rear to front mic mixer, use separately. */
671 		w = hdaa_widget_get(devinfo, 31);
672 		if (w != NULL)
673 			w->enable = 0;
674 		/* Disable direct playback, use mixer. */
675 		w = hdaa_widget_get(devinfo, 5);
676 		if (w != NULL)
677 			w->connsenable[0] = 0;
678 		w = hdaa_widget_get(devinfo, 6);
679 		if (w != NULL)
680 			w->connsenable[0] = 0;
681 		w = hdaa_widget_get(devinfo, 9);
682 		if (w != NULL)
683 			w->connsenable[0] = 0;
684 		w = hdaa_widget_get(devinfo, 24);
685 		if (w != NULL)
686 			w->connsenable[0] = 0;
687 		break;
688 	case HDA_CODEC_ALC269:
689 		/*
690 		 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
691 		 * that mutes speaker if unused mixer at NID 15 is muted.
692 		 * Probably CODEC incorrectly reports internal connections.
693 		 * Hide that muter from the driver.  There are several CODECs
694 		 * sharing this ID and I have not enough information about
695 		 * them to implement more universal solution.
696 		 */
697 		if (subid == 0x84371043) {
698 			w = hdaa_widget_get(devinfo, 15);
699 			if (w != NULL)
700 				w->param.inamp_cap = 0;
701 		}
702 		break;
703 	case HDA_CODEC_CX20582:
704 	case HDA_CODEC_CX20583:
705 	case HDA_CODEC_CX20584:
706 	case HDA_CODEC_CX20585:
707 	case HDA_CODEC_CX20590:
708 		/*
709 		 * These codecs have extra connectivity on record side
710 		 * too reach for the present parser.
711 		 */
712 		w = hdaa_widget_get(devinfo, 20);
713 		if (w != NULL)
714 			w->connsenable[1] = 0;
715 		w = hdaa_widget_get(devinfo, 21);
716 		if (w != NULL)
717 			w->connsenable[1] = 0;
718 		w = hdaa_widget_get(devinfo, 22);
719 		if (w != NULL)
720 			w->connsenable[0] = 0;
721 		break;
722 	case HDA_CODEC_VT1708S_0:
723 	case HDA_CODEC_VT1708S_1:
724 	case HDA_CODEC_VT1708S_2:
725 	case HDA_CODEC_VT1708S_3:
726 	case HDA_CODEC_VT1708S_4:
727 	case HDA_CODEC_VT1708S_5:
728 	case HDA_CODEC_VT1708S_6:
729 	case HDA_CODEC_VT1708S_7:
730 		/*
731 		 * These codecs have hidden mic boost controls.
732 		 */
733 		w = hdaa_widget_get(devinfo, 26);
734 		if (w != NULL)
735 			w->param.inamp_cap =
736 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
737 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
738 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
739 		w = hdaa_widget_get(devinfo, 30);
740 		if (w != NULL)
741 			w->param.inamp_cap =
742 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
743 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
744 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
745 		break;
746 	}
747 }
748 
749 static uint32_t
750 hdaa_read_coef(device_t dev, nid_t nid, uint16_t idx)
751 {
752 
753 	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
754 	return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid)));
755 }
756 
757 static uint32_t
758 hdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val)
759 {
760 
761 	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
762 	return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val)));
763 }
764 
765 void
766 hdaa_patch_direct(struct hdaa_devinfo *devinfo)
767 {
768 	device_t dev = devinfo->dev;
769 	uint32_t id, subid, val;
770 
771 	id = hdaa_codec_id(devinfo);
772 	subid = hdaa_card_id(devinfo);
773 
774 	switch (id) {
775 	case HDA_CODEC_VT1708S_0:
776 	case HDA_CODEC_VT1708S_1:
777 	case HDA_CODEC_VT1708S_2:
778 	case HDA_CODEC_VT1708S_3:
779 	case HDA_CODEC_VT1708S_4:
780 	case HDA_CODEC_VT1708S_5:
781 	case HDA_CODEC_VT1708S_6:
782 	case HDA_CODEC_VT1708S_7:
783 		/* Enable Mic Boost Volume controls. */
784 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
785 		    0xf98, 0x01));
786 		/* Fall though */
787 	case HDA_CODEC_VT1818S:
788 		/* Don't bypass mixer. */
789 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
790 		    0xf88, 0xc0));
791 		break;
792 	case HDA_CODEC_ALC1150:
793 		if (subid == 0xd9781462) {
794 			/* Too low volume on MSI H170 GAMING M3. */
795 			hdaa_write_coef(dev, 0x20, 0x07, 0x7cb);
796 		}
797 		break;
798 	}
799 	if (id == HDA_CODEC_ALC255 || id == HDA_CODEC_ALC256) {
800 		val = hdaa_read_coef(dev, 0x20, 0x46);
801 		hdaa_write_coef(dev, 0x20, 0x46, val|0x3000);
802 	}
803 	if (subid == APPLE_INTEL_MAC)
804 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
805 		    0x7e7, 0));
806 	if (id == HDA_CODEC_ALC269) {
807 		if (subid == 0x16e31043 || subid == 0x831a1043 ||
808 		    subid == 0x834a1043 || subid == 0x83981043 ||
809 		    subid == 0x83ce1043) {
810 			/*
811 			 * The ditital mics on some Asus laptops produce
812 			 * differential signals instead of expected stereo.
813 			 * That results in silence if downmix it to mono.
814 			 * To workaround, make codec to handle signal as mono.
815 			 */
816 			val = hdaa_read_coef(dev, 0x20, 0x07);
817 			hdaa_write_coef(dev, 0x20, 0x07, val|0x80);
818 		}
819 		if (subid == 0x15171043) {
820 			/* Increase output amp on ASUS UX31A by +5dB. */
821 			hdaa_write_coef(dev, 0x20, 0x12, 0x2800);
822 		}
823 	}
824 }
825