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