xref: /freebsd/sys/dev/sound/pci/hda/hdaa_patches.c (revision 53120fbb68952b7d620c2c0e1cf05c5017fc1b27)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
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 #include "pin_patch.h"
48 #include "pin_patch_realtek.h"
49 
50 static const struct {
51 	uint32_t model;
52 	uint32_t id;
53 	uint32_t subsystemid;
54 	uint32_t set, unset;
55 	uint32_t gpio;
56 } hdac_quirks[] = {
57 	/*
58 	 * XXX Force stereo quirk. Monoural recording / playback
59 	 *     on few codecs (especially ALC880) seems broken or
60 	 *     perhaps unsupported.
61 	 */
62 	{ HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_MATCH_ALL,
63 	    HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
64 	    0 },
65 	{ ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, HDA_MATCH_ALL,
66 	    0, 0,
67 	    HDAA_GPIO_SET(0) },
68 	{ ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, HDA_MATCH_ALL,
69 	    0, 0,
70 	    HDAA_GPIO_SET(0) },
71 	{ ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
72 	    0, 0,
73 	    HDAA_GPIO_SET(0) },
74 	{ ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
75 	    0, 0,
76 	    HDAA_GPIO_SET(0) },
77 	{ ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
78 	    0, 0,
79 	    HDAA_GPIO_SET(0) },
80 	{ ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
81 	    0, 0,
82 	    HDAA_GPIO_SET(0) },
83 	{ ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
84 	    HDAA_QUIRK_EAPDINV, 0,
85 	    0 },
86 	{ ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
87 	    HDAA_QUIRK_EAPDINV, 0,
88 	    0 },
89 	{ ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
90 	    HDAA_QUIRK_OVREF, 0,
91 	    0 },
92 	{ UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
93 	    HDAA_QUIRK_OVREF, 0,
94 	    0 },
95 	/*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, HDA_MATCH_ALL,
96 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
97 	    0 },*/
98 	{ MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
99 	    0, 0,
100 	    HDAA_GPIO_SET(1) },
101 	{ LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
102 	    HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
103 	    0 },
104 	{ SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
105 	    HDAA_QUIRK_EAPDINV, 0,
106 	    0 },
107 	{ APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDA_MATCH_ALL,
108 	    HDAA_QUIRK_OVREF50, 0,
109 	    HDAA_GPIO_SET(0) },
110 	{ APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDA_MATCH_ALL,
111 	    0, 0,
112 	    HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
113 	{ APPLE_MACBOOKAIR31, HDA_CODEC_CS4206, HDA_MATCH_ALL,
114 	    0, 0,
115 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
116 	{ APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
117 	    0, 0,
118 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
119 	{ APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL,
120 	    0, 0,
121 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
122 	{ HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL,
123 	    0, 0,
124 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
125 	{ DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
126 	    0, 0,
127 	    HDAA_GPIO_SET(0) },
128 	{ DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
129 	    0, 0,
130 	    HDAA_GPIO_SET(2) },
131 	{ DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
132 	    0, 0,
133 	    HDAA_GPIO_SET(0) },
134 	{ HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
135 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
136 	    0 },
137 	{ HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
138 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
139 	    0 },
140 	{ HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
141 	    0, HDAA_QUIRK_FORCESTEREO,
142 	    0 },
143 	/* Mac Pro 1,1 requires ovref for proper volume level. */
144 	{ 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
145 	    0, HDAA_QUIRK_OVREF,
146 	    0 }
147 };
148 
149 static struct pin_patch_t *
150 match_pin_patches(int vendor_id, int vendor_subid)
151 {
152 	for (int ci = 0; ci < nitems(realtek_model_pin_patches); ci++) {
153 		struct hdaa_model_pin_patch_t *p = &realtek_model_pin_patches[ci];
154 		if (vendor_id != p->id)
155 			continue;
156 		for (struct model_pin_patch_t *pp =  p->patches; pp->models; pp++) {
157 			for (struct pin_machine_model_t *model = pp->models; model->id != 0; model++) {
158 				if (HDA_DEV_MATCH(model->id, vendor_subid))
159 					return (pp->pin_patches);
160 			}
161 		}
162 	}
163 
164 	return (0);
165 }
166 
167 static void
168 hdac_pin_patch(struct hdaa_widget *w)
169 {
170 	const char *patch_str = NULL;
171 	uint32_t config, orig, id, subid;
172 	nid_t nid = w->nid;
173 
174 	config = orig = w->wclass.pin.config;
175 	id = hdaa_codec_id(w->devinfo);
176 	subid = hdaa_card_id(w->devinfo);
177 
178 	if (id == HDA_CODEC_ALC883 && HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid)) {
179 		switch (nid) {
180 		case 25:
181 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
182 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
183 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
184 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
185 			break;
186 		case 28:
187 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
188 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
189 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
190 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
191 			break;
192 		}
193 	} else if (id == HDA_CODEC_CX20549 && subid ==
194 	    HP_V3000_SUBVENDOR) {
195 		switch (nid) {
196 		case 18:
197 			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
198 			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
199 			break;
200 		case 20:
201 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
202 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
203 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
204 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
205 			break;
206 		case 21:
207 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
208 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
209 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
210 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
211 			break;
212 		}
213 	} else if (id == HDA_CODEC_CX20551 && subid ==
214 	    HP_DV5000_SUBVENDOR) {
215 		switch (nid) {
216 		case 20:
217 		case 21:
218 			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
219 			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
220 			break;
221 		}
222 	}
223 
224 	/* New patches */
225 	if (id == HDA_CODEC_AD1984A &&
226 	    subid == LENOVO_X300_SUBVENDOR) {
227 		switch (nid) {
228 		case 17: /* Headphones with redirection */
229 			patch_str = "as=1 seq=15";
230 			break;
231 		case 20: /* Two mics together */
232 			patch_str = "as=2 seq=15";
233 			break;
234 		}
235 	} else if (id == HDA_CODEC_AD1986A &&
236 	    (subid == ASUS_M2NPVMX_SUBVENDOR ||
237 	    subid == ASUS_A8NVMCSM_SUBVENDOR ||
238 	    subid == ASUS_P5PL2_SUBVENDOR)) {
239 		switch (nid) {
240 		case 26: /* Headphones with redirection */
241 			patch_str = "as=1 seq=15";
242 			break;
243 		case 28: /* 5.1 out => 2.0 out + 1 input */
244 			patch_str = "device=Line-in as=8 seq=1";
245 			break;
246 		case 29: /* Can't use this as input, as the only available mic
247 			  * preamplifier is busy by front panel mic (nid 31).
248 			  * If you want to use this rear connector as mic input,
249 			  * you have to disable the front panel one. */
250 			patch_str = "as=0";
251 			break;
252 		case 31: /* Lot of inputs configured with as=15 and unusable */
253 			patch_str = "as=8 seq=3";
254 			break;
255 		case 32:
256 			patch_str = "as=8 seq=4";
257 			break;
258 		case 34:
259 			patch_str = "as=8 seq=5";
260 			break;
261 		case 36:
262 			patch_str = "as=8 seq=6";
263 			break;
264 		}
265 	} else if (id == HDA_CODEC_CX20561 &&
266 	    subid == LENOVO_B450_SUBVENDOR) {
267 		switch (nid) {
268 		case 22:
269 			patch_str = "as=1 seq=15";
270 			break;
271 		}
272 	} else if (id == HDA_CODEC_CX20561 &&
273 	    subid == LENOVO_T400_SUBVENDOR) {
274 		switch (nid) {
275 		case 22:
276 			patch_str = "as=1 seq=15";
277 			break;
278 		case 26:
279 			patch_str = "as=1 seq=0";
280 			break;
281 		}
282 	} else if (id == HDA_CODEC_CX20590 &&
283 	    (subid == LENOVO_X1_SUBVENDOR ||
284 	    subid == LENOVO_X220_SUBVENDOR ||
285 	    subid == LENOVO_T420_SUBVENDOR ||
286 	    subid == LENOVO_T520_SUBVENDOR ||
287 	    subid == LENOVO_G580_SUBVENDOR)) {
288 		switch (nid) {
289 		case 25:
290 			patch_str = "as=1 seq=15";
291 			break;
292 		/*
293 		 * Group onboard mic and headphone mic
294 		 * together.  Fixes onboard mic.
295 		 */
296 		case 27:
297 			patch_str = "as=2 seq=15";
298 			break;
299 		case 35:
300 			patch_str = "as=2";
301 			break;
302 		}
303 	} else if (id == HDA_CODEC_ALC235 && subid == ASUS_GL553VE_SUBVENDOR) {
304 		switch (nid) {
305 		case 33:
306 			patch_str = "as=1 seq=15";
307 			break;
308 		}
309 	} else if (id == HDA_CODEC_ALC256 && (subid == DELL_I7577_SUBVENDOR ||
310 	    subid == DELL_L7480_SUBVENDOR)) {
311 		switch (nid) {
312 		case 20:
313 			patch_str = "as=1 seq=0";
314 			break;
315 		case 33:
316 			patch_str = "as=1 seq=15";
317 			break;
318 		}
319 	} else if (id == HDA_CODEC_ALC257 &&
320 	    (subid == LENOVO_L5AMD_SUBVENDOR ||
321 	    subid == LENOVO_L5INTEL_SUBVENDOR ||
322 	    subid == LENOVO_IDEAPAD3_SUBVENDOR)) {
323 		switch (nid) {
324 		case 20:
325 			patch_str = "as=1 seq=0";
326 			break;
327 		case 33:
328 			patch_str = "as=1 seq=15";
329 			break;
330 		}
331 	} else if (id == HDA_CODEC_IDT92HD95B &&
332 	    (subid == FRAMEWORK_LAPTOP_0001_SUBVENDOR ||
333 	    subid == FRAMEWORK_LAPTOP_0002_SUBVENDOR)) {
334 		switch (nid) {
335 		case 10:
336 			patch_str = "as=1 seq=15 color=Black loc=Left";
337 			break;
338 		case 11:
339 			patch_str = "as=3 seq=15 color=Black loc=Left";
340 			break;
341 		}
342 	} else if (id == HDA_CODEC_ALC230 &&
343 	    subid == LENOVO_IDEAPAD330_SUBVENDOR) {
344 		switch (nid) {
345 		case 20:
346 			patch_str = "as=1 seq=0 device=Speaker";
347 			break;
348 		case 33:
349 			patch_str = "as=1 seq=15 device=Headphones";
350 			break;
351 		}
352 	} else if (id == HDA_CODEC_ALC269 &&
353 	    subid == LENOVO_X230_SUBVENDOR) {
354 		switch (nid) {
355 		case 21:
356 			patch_str = "as=1 seq=15";
357 			break;
358 		case 24:
359 			patch_str = "as=4 seq=15";
360 			break;
361 		}
362 	} else {
363 		/*
364 		 * loop over hdaa_model_pin_patch
365 		 */
366 		struct pin_patch_t *pin_patches = NULL;
367 
368 		pin_patches = match_pin_patches(id, subid);
369 
370 		if (pin_patches != NULL) {
371 			for (struct pin_patch_t *patch = pin_patches; patch->type; patch++) {
372 				if (nid == patch->nid) {
373 					switch (patch->type) {
374 					case PIN_PATCH_TYPE_STRING:
375 						patch_str = patch->patch.string;
376 						break;
377 					case PIN_PATCH_TYPE_MASK:
378 						config &= ~patch->patch.mask[0];
379 						config |= patch->patch.mask[1];
380 						break;
381 					case PIN_PATCH_TYPE_OVERRIDE:
382 						config = patch->patch.override;
383 						break;
384 					default:
385 						/* should panic hard */
386 						break;
387 					}
388 					break;
389 				}
390 			}
391 		}
392 	}
393 
394 	if (patch_str != NULL)
395 		config = hdaa_widget_pin_patch(config, patch_str);
396 	HDA_BOOTVERBOSE(
397 		if (config != orig)
398 			device_printf(w->devinfo->dev,
399 			    "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
400 			    nid, orig, config);
401 	);
402 	w->wclass.pin.config = config;
403 }
404 
405 static void
406 hdaa_widget_patch(struct hdaa_widget *w)
407 {
408 	struct hdaa_devinfo *devinfo = w->devinfo;
409 	uint32_t orig;
410 	nid_t beeper = -1;
411 
412 	orig = w->param.widget_cap;
413 	/* On some codecs beeper is an input pin, but it is not recordable
414 	   alone. Also most of BIOSes does not declare beeper pin.
415 	   Change beeper pin node type to beeper to help parser. */
416 	switch (hdaa_codec_id(devinfo)) {
417 	case HDA_CODEC_AD1882:
418 	case HDA_CODEC_AD1883:
419 	case HDA_CODEC_AD1984:
420 	case HDA_CODEC_AD1984A:
421 	case HDA_CODEC_AD1984B:
422 	case HDA_CODEC_AD1987:
423 	case HDA_CODEC_AD1988:
424 	case HDA_CODEC_AD1988B:
425 	case HDA_CODEC_AD1989B:
426 		beeper = 26;
427 		break;
428 	case HDA_CODEC_ALC260:
429 		beeper = 23;
430 		break;
431 	}
432 	if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
433 	    hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
434 		beeper = 29;
435 	if (w->nid == beeper) {
436 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
437 		w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
438 		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
439 		w->waspin = 1;
440 	}
441 	/*
442 	 * Clear "digital" flag from digital mic input, as its signal then goes
443 	 * to "analog" mixer and this separation just limits functionaity.
444 	 */
445 	if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
446 	    w->nid == 23)
447 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
448 	HDA_BOOTVERBOSE(
449 		if (w->param.widget_cap != orig) {
450 			device_printf(w->devinfo->dev,
451 			    "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
452 			    w->nid, orig, w->param.widget_cap);
453 		}
454 	);
455 
456 	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
457 		hdac_pin_patch(w);
458 }
459 
460 void
461 hdaa_patch(struct hdaa_devinfo *devinfo)
462 {
463 	struct hdaa_widget *w;
464 	uint32_t id, subid, subsystemid;
465 	int i;
466 
467 	id = hdaa_codec_id(devinfo);
468 	subid = hdaa_card_id(devinfo);
469 	subsystemid = hda_get_subsystem_id(devinfo->dev);
470 
471 	/*
472 	 * Quirks
473 	 */
474 	for (i = 0; i < nitems(hdac_quirks); i++) {
475 		if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
476 		    HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
477 		    HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
478 			continue;
479 		devinfo->quirks |= hdac_quirks[i].set;
480 		devinfo->quirks &= ~(hdac_quirks[i].unset);
481 		devinfo->gpio = hdac_quirks[i].gpio;
482 	}
483 
484 	/* Apply per-widget patch. */
485 	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
486 		w = hdaa_widget_get(devinfo, i);
487 		if (w == NULL)
488 			continue;
489 		hdaa_widget_patch(w);
490 	}
491 
492 	switch (id) {
493 	case HDA_CODEC_AD1983:
494 		/*
495 		 * This CODEC has several possible usages, but none
496 		 * fit the parser best. Help parser to choose better.
497 		 */
498 		/* Disable direct unmixed playback to get pcm volume. */
499 		w = hdaa_widget_get(devinfo, 5);
500 		if (w != NULL)
501 			w->connsenable[0] = 0;
502 		w = hdaa_widget_get(devinfo, 6);
503 		if (w != NULL)
504 			w->connsenable[0] = 0;
505 		w = hdaa_widget_get(devinfo, 11);
506 		if (w != NULL)
507 			w->connsenable[0] = 0;
508 		/* Disable mic and line selectors. */
509 		w = hdaa_widget_get(devinfo, 12);
510 		if (w != NULL)
511 			w->connsenable[1] = 0;
512 		w = hdaa_widget_get(devinfo, 13);
513 		if (w != NULL)
514 			w->connsenable[1] = 0;
515 		/* Disable recording from mono playback mix. */
516 		w = hdaa_widget_get(devinfo, 20);
517 		if (w != NULL)
518 			w->connsenable[3] = 0;
519 		break;
520 	case HDA_CODEC_AD1986A:
521 		/*
522 		 * This CODEC has overcomplicated input mixing.
523 		 * Make some cleaning there.
524 		 */
525 		/* Disable input mono mixer. Not needed and not supported. */
526 		w = hdaa_widget_get(devinfo, 43);
527 		if (w != NULL)
528 			w->enable = 0;
529 		/* Disable any with any input mixing mesh. Use separately. */
530 		w = hdaa_widget_get(devinfo, 39);
531 		if (w != NULL)
532 			w->enable = 0;
533 		w = hdaa_widget_get(devinfo, 40);
534 		if (w != NULL)
535 			w->enable = 0;
536 		w = hdaa_widget_get(devinfo, 41);
537 		if (w != NULL)
538 			w->enable = 0;
539 		w = hdaa_widget_get(devinfo, 42);
540 		if (w != NULL)
541 			w->enable = 0;
542 		/* Disable duplicate mixer node connector. */
543 		w = hdaa_widget_get(devinfo, 15);
544 		if (w != NULL)
545 			w->connsenable[3] = 0;
546 		/* There is only one mic preamplifier, use it effectively. */
547 		w = hdaa_widget_get(devinfo, 31);
548 		if (w != NULL) {
549 			if ((w->wclass.pin.config &
550 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
551 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
552 				w = hdaa_widget_get(devinfo, 16);
553 				if (w != NULL)
554 				    w->connsenable[2] = 0;
555 			} else {
556 				w = hdaa_widget_get(devinfo, 15);
557 				if (w != NULL)
558 				    w->connsenable[0] = 0;
559 			}
560 		}
561 		w = hdaa_widget_get(devinfo, 32);
562 		if (w != NULL) {
563 			if ((w->wclass.pin.config &
564 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
565 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
566 				w = hdaa_widget_get(devinfo, 16);
567 				if (w != NULL)
568 				    w->connsenable[0] = 0;
569 			} else {
570 				w = hdaa_widget_get(devinfo, 15);
571 				if (w != NULL)
572 				    w->connsenable[1] = 0;
573 			}
574 		}
575 
576 		if (subid == ASUS_A8X_SUBVENDOR) {
577 			/*
578 			 * This is just plain ridiculous.. There
579 			 * are several A8 series that share the same
580 			 * pci id but works differently (EAPD).
581 			 */
582 			w = hdaa_widget_get(devinfo, 26);
583 			if (w != NULL && w->type ==
584 			    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
585 			    (w->wclass.pin.config &
586 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
587 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
588 				devinfo->quirks &=
589 				    ~HDAA_QUIRK_EAPDINV;
590 		}
591 		break;
592 	case HDA_CODEC_AD1981HD:
593 		/*
594 		 * This CODEC has very unusual design with several
595 		 * points inappropriate for the present parser.
596 		 */
597 		/* Disable recording from mono playback mix. */
598 		w = hdaa_widget_get(devinfo, 21);
599 		if (w != NULL)
600 			w->connsenable[3] = 0;
601 		/* Disable rear to front mic mixer, use separately. */
602 		w = hdaa_widget_get(devinfo, 31);
603 		if (w != NULL)
604 			w->enable = 0;
605 		/* Disable direct playback, use mixer. */
606 		w = hdaa_widget_get(devinfo, 5);
607 		if (w != NULL)
608 			w->connsenable[0] = 0;
609 		w = hdaa_widget_get(devinfo, 6);
610 		if (w != NULL)
611 			w->connsenable[0] = 0;
612 		w = hdaa_widget_get(devinfo, 9);
613 		if (w != NULL)
614 			w->connsenable[0] = 0;
615 		w = hdaa_widget_get(devinfo, 24);
616 		if (w != NULL)
617 			w->connsenable[0] = 0;
618 		break;
619 	case HDA_CODEC_ALC269:
620 		/*
621 		 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
622 		 * that mutes speaker if unused mixer at NID 15 is muted.
623 		 * Probably CODEC incorrectly reports internal connections.
624 		 * Hide that muter from the driver.  There are several CODECs
625 		 * sharing this ID and I have not enough information about
626 		 * them to implement more universal solution.
627 		 */
628 		if (subid == 0x84371043) {
629 			w = hdaa_widget_get(devinfo, 15);
630 			if (w != NULL)
631 				w->param.inamp_cap = 0;
632 		}
633 		break;
634 	case HDA_CODEC_CX20582:
635 	case HDA_CODEC_CX20583:
636 	case HDA_CODEC_CX20584:
637 	case HDA_CODEC_CX20585:
638 	case HDA_CODEC_CX20590:
639 		/*
640 		 * These codecs have extra connectivity on record side
641 		 * too reach for the present parser.
642 		 */
643 		w = hdaa_widget_get(devinfo, 20);
644 		if (w != NULL)
645 			w->connsenable[1] = 0;
646 		w = hdaa_widget_get(devinfo, 21);
647 		if (w != NULL)
648 			w->connsenable[1] = 0;
649 		w = hdaa_widget_get(devinfo, 22);
650 		if (w != NULL)
651 			w->connsenable[0] = 0;
652 		break;
653 	case HDA_CODEC_VT1708S_0:
654 	case HDA_CODEC_VT1708S_1:
655 	case HDA_CODEC_VT1708S_2:
656 	case HDA_CODEC_VT1708S_3:
657 	case HDA_CODEC_VT1708S_4:
658 	case HDA_CODEC_VT1708S_5:
659 	case HDA_CODEC_VT1708S_6:
660 	case HDA_CODEC_VT1708S_7:
661 		/*
662 		 * These codecs have hidden mic boost controls.
663 		 */
664 		w = hdaa_widget_get(devinfo, 26);
665 		if (w != NULL)
666 			w->param.inamp_cap =
667 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
668 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
669 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
670 		w = hdaa_widget_get(devinfo, 30);
671 		if (w != NULL)
672 			w->param.inamp_cap =
673 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
674 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
675 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
676 		break;
677 	}
678 }
679 
680 static uint32_t
681 hdaa_read_coef(device_t dev, nid_t nid, uint16_t idx)
682 {
683 
684 	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
685 	return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid)));
686 }
687 
688 static uint32_t
689 hdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val)
690 {
691 
692 	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
693 	return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val)));
694 }
695 
696 void
697 hdaa_patch_direct(struct hdaa_devinfo *devinfo)
698 {
699 	device_t dev = devinfo->dev;
700 	uint32_t id, subid, val;
701 
702 	id = hdaa_codec_id(devinfo);
703 	subid = hdaa_card_id(devinfo);
704 
705 	switch (id) {
706 	case HDA_CODEC_VT1708S_0:
707 	case HDA_CODEC_VT1708S_1:
708 	case HDA_CODEC_VT1708S_2:
709 	case HDA_CODEC_VT1708S_3:
710 	case HDA_CODEC_VT1708S_4:
711 	case HDA_CODEC_VT1708S_5:
712 	case HDA_CODEC_VT1708S_6:
713 	case HDA_CODEC_VT1708S_7:
714 		/* Enable Mic Boost Volume controls. */
715 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
716 		    0xf98, 0x01));
717 		/* Fall though */
718 	case HDA_CODEC_VT1818S:
719 		/* Don't bypass mixer. */
720 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
721 		    0xf88, 0xc0));
722 		break;
723 	case HDA_CODEC_ALC1150:
724 		if (subid == 0xd9781462) {
725 			/* Too low volume on MSI H170 GAMING M3. */
726 			hdaa_write_coef(dev, 0x20, 0x07, 0x7cb);
727 		}
728 		break;
729 	}
730 	if (id == HDA_CODEC_ALC255 || id == HDA_CODEC_ALC256) {
731 		val = hdaa_read_coef(dev, 0x20, 0x46);
732 		hdaa_write_coef(dev, 0x20, 0x46, val|0x3000);
733 	}
734 	if (subid == APPLE_INTEL_MAC)
735 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
736 		    0x7e7, 0));
737 	if (id == HDA_CODEC_ALC269) {
738 		if (subid == 0x16e31043 || subid == 0x831a1043 ||
739 		    subid == 0x834a1043 || subid == 0x83981043 ||
740 		    subid == 0x83ce1043) {
741 			/*
742 			 * The digital mics on some Asus laptops produce
743 			 * differential signals instead of expected stereo.
744 			 * That results in silence if downmixing to mono.
745 			 * To workaround, make codec handle the signal as mono.
746 			 */
747 			val = hdaa_read_coef(dev, 0x20, 0x07);
748 			hdaa_write_coef(dev, 0x20, 0x07, val|0x80);
749 		}
750 		if (subid == 0x15171043) {
751 			/* Increase output amp on ASUS UX31A by +5dB. */
752 			hdaa_write_coef(dev, 0x20, 0x12, 0x2800);
753 		}
754 	}
755 }
756