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