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