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