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