xref: /freebsd/sys/dev/sound/pci/hda/hdaa_patches.c (revision 4e8d558c)
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 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 	    subid == LENOVO_L5INTEL_SUBVENDOR)) {
324 		switch (nid) {
325 		case 20:
326 			patch_str = "as=1 seq=0";
327 			break;
328 		case 33:
329 			patch_str = "as=1 seq=15";
330 			break;
331 		}
332 	} else if (id == HDA_CODEC_IDT92HD95B &&
333 	    (subid == FRAMEWORK_LAPTOP_0001_SUBVENDOR ||
334 	    subid == FRAMEWORK_LAPTOP_0002_SUBVENDOR)) {
335 		switch (nid) {
336 		case 10:
337 			patch_str = "as=1 seq=15 color=Black loc=Left";
338 			break;
339 		case 11:
340 			patch_str = "as=3 seq=15 color=Black loc=Left";
341 			break;
342 		}
343 	} else {
344 		/*
345 		 * loop over hdaa_model_pin_patch
346 		 */
347 		struct pin_patch_t *pin_patches = NULL;
348 
349 		pin_patches = match_pin_patches(id, subid);
350 
351 		if (pin_patches != NULL) {
352 			for (struct pin_patch_t *patch = pin_patches; patch->type; patch++) {
353 				if (nid == patch->nid) {
354 					switch (patch->type) {
355 					case PIN_PATCH_TYPE_STRING:
356 						patch_str = patch->patch.string;
357 						break;
358 					case PIN_PATCH_TYPE_MASK:
359 						config &= ~patch->patch.mask[0];
360 						config |= patch->patch.mask[1];
361 						break;
362 					case PIN_PATCH_TYPE_OVERRIDE:
363 						config = patch->patch.override;
364 						break;
365 					default:
366 						/* should panic hard */
367 						break;
368 					}
369 					break;
370 				}
371 			}
372 		}
373 	}
374 
375 	if (patch_str != NULL)
376 		config = hdaa_widget_pin_patch(config, patch_str);
377 	HDA_BOOTVERBOSE(
378 		if (config != orig)
379 			device_printf(w->devinfo->dev,
380 			    "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
381 			    nid, orig, config);
382 	);
383 	w->wclass.pin.config = config;
384 }
385 
386 static void
387 hdaa_widget_patch(struct hdaa_widget *w)
388 {
389 	struct hdaa_devinfo *devinfo = w->devinfo;
390 	uint32_t orig;
391 	nid_t beeper = -1;
392 
393 	orig = w->param.widget_cap;
394 	/* On some codecs beeper is an input pin, but it is not recordable
395 	   alone. Also most of BIOSes does not declare beeper pin.
396 	   Change beeper pin node type to beeper to help parser. */
397 	switch (hdaa_codec_id(devinfo)) {
398 	case HDA_CODEC_AD1882:
399 	case HDA_CODEC_AD1883:
400 	case HDA_CODEC_AD1984:
401 	case HDA_CODEC_AD1984A:
402 	case HDA_CODEC_AD1984B:
403 	case HDA_CODEC_AD1987:
404 	case HDA_CODEC_AD1988:
405 	case HDA_CODEC_AD1988B:
406 	case HDA_CODEC_AD1989B:
407 		beeper = 26;
408 		break;
409 	case HDA_CODEC_ALC260:
410 		beeper = 23;
411 		break;
412 	}
413 	if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
414 	    hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
415 		beeper = 29;
416 	if (w->nid == beeper) {
417 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
418 		w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
419 		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
420 		w->waspin = 1;
421 	}
422 	/*
423 	 * Clear "digital" flag from digital mic input, as its signal then goes
424 	 * to "analog" mixer and this separation just limits functionaity.
425 	 */
426 	if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
427 	    w->nid == 23)
428 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
429 	HDA_BOOTVERBOSE(
430 		if (w->param.widget_cap != orig) {
431 			device_printf(w->devinfo->dev,
432 			    "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
433 			    w->nid, orig, w->param.widget_cap);
434 		}
435 	);
436 
437 	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
438 		hdac_pin_patch(w);
439 }
440 
441 void
442 hdaa_patch(struct hdaa_devinfo *devinfo)
443 {
444 	struct hdaa_widget *w;
445 	uint32_t id, subid, subsystemid;
446 	int i;
447 
448 	id = hdaa_codec_id(devinfo);
449 	subid = hdaa_card_id(devinfo);
450 	subsystemid = hda_get_subsystem_id(devinfo->dev);
451 
452 	/*
453 	 * Quirks
454 	 */
455 	for (i = 0; i < nitems(hdac_quirks); i++) {
456 		if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
457 		    HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
458 		    HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
459 			continue;
460 		devinfo->quirks |= hdac_quirks[i].set;
461 		devinfo->quirks &= ~(hdac_quirks[i].unset);
462 		devinfo->gpio = hdac_quirks[i].gpio;
463 	}
464 
465 	/* Apply per-widget patch. */
466 	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
467 		w = hdaa_widget_get(devinfo, i);
468 		if (w == NULL)
469 			continue;
470 		hdaa_widget_patch(w);
471 	}
472 
473 	switch (id) {
474 	case HDA_CODEC_AD1983:
475 		/*
476 		 * This CODEC has several possible usages, but none
477 		 * fit the parser best. Help parser to choose better.
478 		 */
479 		/* Disable direct unmixed playback to get pcm volume. */
480 		w = hdaa_widget_get(devinfo, 5);
481 		if (w != NULL)
482 			w->connsenable[0] = 0;
483 		w = hdaa_widget_get(devinfo, 6);
484 		if (w != NULL)
485 			w->connsenable[0] = 0;
486 		w = hdaa_widget_get(devinfo, 11);
487 		if (w != NULL)
488 			w->connsenable[0] = 0;
489 		/* Disable mic and line selectors. */
490 		w = hdaa_widget_get(devinfo, 12);
491 		if (w != NULL)
492 			w->connsenable[1] = 0;
493 		w = hdaa_widget_get(devinfo, 13);
494 		if (w != NULL)
495 			w->connsenable[1] = 0;
496 		/* Disable recording from mono playback mix. */
497 		w = hdaa_widget_get(devinfo, 20);
498 		if (w != NULL)
499 			w->connsenable[3] = 0;
500 		break;
501 	case HDA_CODEC_AD1986A:
502 		/*
503 		 * This CODEC has overcomplicated input mixing.
504 		 * Make some cleaning there.
505 		 */
506 		/* Disable input mono mixer. Not needed and not supported. */
507 		w = hdaa_widget_get(devinfo, 43);
508 		if (w != NULL)
509 			w->enable = 0;
510 		/* Disable any with any input mixing mesh. Use separately. */
511 		w = hdaa_widget_get(devinfo, 39);
512 		if (w != NULL)
513 			w->enable = 0;
514 		w = hdaa_widget_get(devinfo, 40);
515 		if (w != NULL)
516 			w->enable = 0;
517 		w = hdaa_widget_get(devinfo, 41);
518 		if (w != NULL)
519 			w->enable = 0;
520 		w = hdaa_widget_get(devinfo, 42);
521 		if (w != NULL)
522 			w->enable = 0;
523 		/* Disable duplicate mixer node connector. */
524 		w = hdaa_widget_get(devinfo, 15);
525 		if (w != NULL)
526 			w->connsenable[3] = 0;
527 		/* There is only one mic preamplifier, use it effectively. */
528 		w = hdaa_widget_get(devinfo, 31);
529 		if (w != NULL) {
530 			if ((w->wclass.pin.config &
531 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
532 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
533 				w = hdaa_widget_get(devinfo, 16);
534 				if (w != NULL)
535 				    w->connsenable[2] = 0;
536 			} else {
537 				w = hdaa_widget_get(devinfo, 15);
538 				if (w != NULL)
539 				    w->connsenable[0] = 0;
540 			}
541 		}
542 		w = hdaa_widget_get(devinfo, 32);
543 		if (w != NULL) {
544 			if ((w->wclass.pin.config &
545 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
546 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
547 				w = hdaa_widget_get(devinfo, 16);
548 				if (w != NULL)
549 				    w->connsenable[0] = 0;
550 			} else {
551 				w = hdaa_widget_get(devinfo, 15);
552 				if (w != NULL)
553 				    w->connsenable[1] = 0;
554 			}
555 		}
556 
557 		if (subid == ASUS_A8X_SUBVENDOR) {
558 			/*
559 			 * This is just plain ridiculous.. There
560 			 * are several A8 series that share the same
561 			 * pci id but works differently (EAPD).
562 			 */
563 			w = hdaa_widget_get(devinfo, 26);
564 			if (w != NULL && w->type ==
565 			    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
566 			    (w->wclass.pin.config &
567 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
568 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
569 				devinfo->quirks &=
570 				    ~HDAA_QUIRK_EAPDINV;
571 		}
572 		break;
573 	case HDA_CODEC_AD1981HD:
574 		/*
575 		 * This CODEC has very unusual design with several
576 		 * points inappropriate for the present parser.
577 		 */
578 		/* Disable recording from mono playback mix. */
579 		w = hdaa_widget_get(devinfo, 21);
580 		if (w != NULL)
581 			w->connsenable[3] = 0;
582 		/* Disable rear to front mic mixer, use separately. */
583 		w = hdaa_widget_get(devinfo, 31);
584 		if (w != NULL)
585 			w->enable = 0;
586 		/* Disable direct playback, use mixer. */
587 		w = hdaa_widget_get(devinfo, 5);
588 		if (w != NULL)
589 			w->connsenable[0] = 0;
590 		w = hdaa_widget_get(devinfo, 6);
591 		if (w != NULL)
592 			w->connsenable[0] = 0;
593 		w = hdaa_widget_get(devinfo, 9);
594 		if (w != NULL)
595 			w->connsenable[0] = 0;
596 		w = hdaa_widget_get(devinfo, 24);
597 		if (w != NULL)
598 			w->connsenable[0] = 0;
599 		break;
600 	case HDA_CODEC_ALC269:
601 		/*
602 		 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
603 		 * that mutes speaker if unused mixer at NID 15 is muted.
604 		 * Probably CODEC incorrectly reports internal connections.
605 		 * Hide that muter from the driver.  There are several CODECs
606 		 * sharing this ID and I have not enough information about
607 		 * them to implement more universal solution.
608 		 */
609 		if (subid == 0x84371043) {
610 			w = hdaa_widget_get(devinfo, 15);
611 			if (w != NULL)
612 				w->param.inamp_cap = 0;
613 		}
614 		break;
615 	case HDA_CODEC_CX20582:
616 	case HDA_CODEC_CX20583:
617 	case HDA_CODEC_CX20584:
618 	case HDA_CODEC_CX20585:
619 	case HDA_CODEC_CX20590:
620 		/*
621 		 * These codecs have extra connectivity on record side
622 		 * too reach for the present parser.
623 		 */
624 		w = hdaa_widget_get(devinfo, 20);
625 		if (w != NULL)
626 			w->connsenable[1] = 0;
627 		w = hdaa_widget_get(devinfo, 21);
628 		if (w != NULL)
629 			w->connsenable[1] = 0;
630 		w = hdaa_widget_get(devinfo, 22);
631 		if (w != NULL)
632 			w->connsenable[0] = 0;
633 		break;
634 	case HDA_CODEC_VT1708S_0:
635 	case HDA_CODEC_VT1708S_1:
636 	case HDA_CODEC_VT1708S_2:
637 	case HDA_CODEC_VT1708S_3:
638 	case HDA_CODEC_VT1708S_4:
639 	case HDA_CODEC_VT1708S_5:
640 	case HDA_CODEC_VT1708S_6:
641 	case HDA_CODEC_VT1708S_7:
642 		/*
643 		 * These codecs have hidden mic boost controls.
644 		 */
645 		w = hdaa_widget_get(devinfo, 26);
646 		if (w != NULL)
647 			w->param.inamp_cap =
648 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
649 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
650 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
651 		w = hdaa_widget_get(devinfo, 30);
652 		if (w != NULL)
653 			w->param.inamp_cap =
654 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
655 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
656 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
657 		break;
658 	}
659 }
660 
661 static uint32_t
662 hdaa_read_coef(device_t dev, nid_t nid, uint16_t idx)
663 {
664 
665 	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
666 	return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid)));
667 }
668 
669 static uint32_t
670 hdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val)
671 {
672 
673 	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
674 	return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val)));
675 }
676 
677 void
678 hdaa_patch_direct(struct hdaa_devinfo *devinfo)
679 {
680 	device_t dev = devinfo->dev;
681 	uint32_t id, subid, val;
682 
683 	id = hdaa_codec_id(devinfo);
684 	subid = hdaa_card_id(devinfo);
685 
686 	switch (id) {
687 	case HDA_CODEC_VT1708S_0:
688 	case HDA_CODEC_VT1708S_1:
689 	case HDA_CODEC_VT1708S_2:
690 	case HDA_CODEC_VT1708S_3:
691 	case HDA_CODEC_VT1708S_4:
692 	case HDA_CODEC_VT1708S_5:
693 	case HDA_CODEC_VT1708S_6:
694 	case HDA_CODEC_VT1708S_7:
695 		/* Enable Mic Boost Volume controls. */
696 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
697 		    0xf98, 0x01));
698 		/* Fall though */
699 	case HDA_CODEC_VT1818S:
700 		/* Don't bypass mixer. */
701 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
702 		    0xf88, 0xc0));
703 		break;
704 	case HDA_CODEC_ALC1150:
705 		if (subid == 0xd9781462) {
706 			/* Too low volume on MSI H170 GAMING M3. */
707 			hdaa_write_coef(dev, 0x20, 0x07, 0x7cb);
708 		}
709 		break;
710 	}
711 	if (id == HDA_CODEC_ALC255 || id == HDA_CODEC_ALC256) {
712 		val = hdaa_read_coef(dev, 0x20, 0x46);
713 		hdaa_write_coef(dev, 0x20, 0x46, val|0x3000);
714 	}
715 	if (subid == APPLE_INTEL_MAC)
716 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
717 		    0x7e7, 0));
718 	if (id == HDA_CODEC_ALC269) {
719 		if (subid == 0x16e31043 || subid == 0x831a1043 ||
720 		    subid == 0x834a1043 || subid == 0x83981043 ||
721 		    subid == 0x83ce1043) {
722 			/*
723 			 * The digital mics on some Asus laptops produce
724 			 * differential signals instead of expected stereo.
725 			 * That results in silence if downmixing to mono.
726 			 * To workaround, make codec handle the signal as mono.
727 			 */
728 			val = hdaa_read_coef(dev, 0x20, 0x07);
729 			hdaa_write_coef(dev, 0x20, 0x07, val|0x80);
730 		}
731 		if (subid == 0x15171043) {
732 			/* Increase output amp on ASUS UX31A by +5dB. */
733 			hdaa_write_coef(dev, 0x20, 0x12, 0x2800);
734 		}
735 	}
736 }
737