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