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