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