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