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