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