xref: /dragonfly/sys/dev/sound/pci/hda/hdaa_patches.c (revision e6d22e9b)
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 				       subid == ACER_C720_SUBVENDOR2)) {
290 		switch (nid) {
291 		case 20:
292 			patch = "as=2 seq=0";
293 			break;
294 		case 25:
295 			patch = "as=1 seq=0";
296 			break;
297 		case 27:
298 			/*
299 			patch = "device=Headphones conn=Fixed as=2 seq=15";
300 			w->enable = 1;
301 			*/
302 			break;
303 		case 33:
304 			break;
305 		}
306 	} else
307 	if (id == HDA_CODEC_AD1984A &&
308 	    subid == LENOVO_X300_SUBVENDOR) {
309 		switch (nid) {
310 		case 17: /* Headphones with redirection */
311 			patch = "as=1 seq=15";
312 			break;
313 		case 20: /* Two mics together */
314 			patch = "as=2 seq=15";
315 			break;
316 		}
317 	} else if (id == HDA_CODEC_AD1986A &&
318 	    (subid == ASUS_M2NPVMX_SUBVENDOR ||
319 	    subid == ASUS_A8NVMCSM_SUBVENDOR ||
320 	    subid == ASUS_P5PL2_SUBVENDOR)) {
321 		switch (nid) {
322 		case 26: /* Headphones with redirection */
323 			patch = "as=1 seq=15";
324 			break;
325 		case 28: /* 5.1 out => 2.0 out + 1 input */
326 			patch = "device=Line-in as=8 seq=1";
327 			break;
328 		case 29: /* Can't use this as input, as the only available mic
329 			  * preamplifier is busy by front panel mic (nid 31).
330 			  * If you want to use this rear connector as mic input,
331 			  * you have to disable the front panel one. */
332 			patch = "as=0";
333 			break;
334 		case 31: /* Lot of inputs configured with as=15 and unusable */
335 			patch = "as=8 seq=3";
336 			break;
337 		case 32:
338 			patch = "as=8 seq=4";
339 			break;
340 		case 34:
341 			patch = "as=8 seq=5";
342 			break;
343 		case 36:
344 			patch = "as=8 seq=6";
345 			break;
346 		}
347 	} else if (id == HDA_CODEC_ALC260 &&
348 	    HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
349 		switch (nid) {
350 		case 16:
351 			patch = "seq=15 device=Headphones";
352 			break;
353 		}
354 	} else if (id == HDA_CODEC_ALC268) {
355 	    if (subid == ACER_T5320_SUBVENDOR) {
356 		switch (nid) {
357 		case 20: /* Headphones Jack */
358 			patch = "as=1 seq=15";
359 			break;
360 		}
361 	    }
362 	} else if (id == HDA_CODEC_CX20561 &&
363 	    subid == LENOVO_B450_SUBVENDOR) {
364 		switch (nid) {
365 		case 22:
366 			patch = "as=1 seq=15";
367 			break;
368 		}
369 	} else if (id == HDA_CODEC_CX20561 &&
370 	    subid == LENOVO_T400_SUBVENDOR) {
371 		switch (nid) {
372 		case 22:
373 			patch = "as=1 seq=15";
374 			break;
375 		case 26:
376 			patch = "as=1 seq=0";
377 			break;
378 		}
379 	} else if (id == HDA_CODEC_CX20590 &&
380 	    (subid == LENOVO_X1_SUBVENDOR ||
381 	    subid == LENOVO_X220_SUBVENDOR ||
382 	    subid == LENOVO_T420_SUBVENDOR ||
383 	    subid == LENOVO_T520_SUBVENDOR ||
384 	    subid == LENOVO_G580_SUBVENDOR)) {
385 		switch (nid) {
386 		case 25:
387 			patch = "as=1 seq=15";
388 			break;
389 		/*
390 		 * Group onboard mic and headphone mic
391 		 * together.  Fixes onboard mic.
392 		 */
393 		case 27:
394 			patch = "as=2 seq=15";
395 			break;
396 		case 35:
397 			patch = "as=2";
398 			break;
399 		}
400 	} else if (id == HDA_CODEC_ALC269 &&
401 	    (subid == LENOVO_X1CRBN_SUBVENDOR ||
402 	    subid == LENOVO_T430_SUBVENDOR ||
403 	    subid == LENOVO_T430S_SUBVENDOR ||
404 	    subid == LENOVO_T530_SUBVENDOR)) {
405 		switch (nid) {
406 		case 21:
407 			patch = "as=1 seq=15";
408 			break;
409 		}
410 	} else if (id == HDA_CODEC_ALC269 &&
411 	    subid == ASUS_UX31A_SUBVENDOR) {
412 		switch (nid) {
413 		case 33:
414 			patch = "as=1 seq=15";
415 			break;
416 		}
417 	} else if (id == HDA_CODEC_ALC892 &&
418 	    subid == INTEL_DH87RL_SUBVENDOR) {
419 		switch (nid) {
420 		case 27:
421 			patch = "as=1 seq=15";
422 			break;
423 		}
424 	}
425 
426 	if (patch != NULL)
427 		config = hdaa_widget_pin_patch(config, patch);
428 	HDA_BOOTVERBOSE(
429 		if (config != orig)
430 			device_printf(w->devinfo->dev,
431 			    "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
432 			    nid, orig, config);
433 	);
434 	w->wclass.pin.config = config;
435 }
436 
437 static void
438 hdaa_widget_patch(struct hdaa_widget *w)
439 {
440 	struct hdaa_devinfo *devinfo = w->devinfo;
441 	uint32_t orig;
442 	nid_t beeper = -1;
443 	uint32_t id, subid;
444 
445 	id = hdaa_codec_id(devinfo);
446 	subid = hdaa_card_id(devinfo);
447 
448 	orig = w->param.widget_cap;
449 	/* On some codecs beeper is an input pin, but it is not recordable
450 	   alone. Also most of BIOSes does not declare beeper pin.
451 	   Change beeper pin node type to beeper to help parser. */
452 	switch (hdaa_codec_id(devinfo)) {
453 	case HDA_CODEC_AD1882:
454 	case HDA_CODEC_AD1883:
455 	case HDA_CODEC_AD1984:
456 	case HDA_CODEC_AD1984A:
457 	case HDA_CODEC_AD1984B:
458 	case HDA_CODEC_AD1987:
459 	case HDA_CODEC_AD1988:
460 	case HDA_CODEC_AD1988B:
461 	case HDA_CODEC_AD1989B:
462 		beeper = 26;
463 		break;
464 	case HDA_CODEC_ALC260:
465 		beeper = 23;
466 		break;
467 	}
468 	if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
469 	    hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
470 		beeper = 29;
471 	if (w->nid == beeper) {
472 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
473 		w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
474 		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
475 		w->waspin = 1;
476 	}
477 	/*
478 	 * Clear "digital" flag from digital mic input, as its signal then goes
479 	 * to "analog" mixer and this separation just limits functionaity.
480 	 */
481 	if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
482 	    w->nid == 23)
483 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
484 	HDA_BOOTVERBOSE(
485 		if (w->param.widget_cap != orig) {
486 			device_printf(w->devinfo->dev,
487 			    "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
488 			    w->nid, orig, w->param.widget_cap);
489 		}
490 	);
491 
492 #if 1
493 	/*
494 	 * Redirect the headphone plug sense (NID 33 -> redir to 12).
495 	 *
496 	 * Disable the remixer (NID 11).  There was a comment in the linux
497 	 * driver that disabling the remixer removes low level whitenoise.
498 	 * this makes sense since the mixer's unconnected inputs might have
499 	 * noise on them that leaks through.
500 	 */
501 	if (id == HDA_CODEC_ALC283 && (subid == ACER_C720_SUBVENDOR ||
502 				       subid == ACER_C720_SUBVENDOR2)) {
503 		if (w->nid == 33)
504 			w->senseredir = 12;
505 		if (w->nid == 11)
506 			w->enable = 0;
507 	}
508 #endif
509 
510 	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
511 		hdac_pin_patch(w);
512 }
513 
514 void
515 hdaa_patch(struct hdaa_devinfo *devinfo)
516 {
517 	struct hdaa_widget *w;
518 	uint32_t id, subid, subsystemid;
519 	uint32_t val;
520 	int i;
521 
522 	id = hdaa_codec_id(devinfo);
523 	subid = hdaa_card_id(devinfo);
524 	subsystemid = hda_get_subsystem_id(devinfo->dev);
525 
526 	/*
527 	 * Quirks
528 	 */
529 	for (i = 0; i < nitems(hdac_quirks); i++) {
530 		if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
531 		    HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
532 		    HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
533 			continue;
534 		devinfo->quirks |= hdac_quirks[i].set;
535 		devinfo->quirks &= ~(hdac_quirks[i].unset);
536 		devinfo->gpio = hdac_quirks[i].gpio;
537 	}
538 
539 	/* Apply per-widget patch. */
540 	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
541 		w = hdaa_widget_get(devinfo, i);
542 		if (w == NULL)
543 			continue;
544 		hdaa_widget_patch(w);
545 	}
546 
547 	switch (id) {
548 	case HDA_CODEC_AD1983:
549 		/*
550 		 * This CODEC has several possible usages, but none
551 		 * fit the parser best. Help parser to choose better.
552 		 */
553 		/* Disable direct unmixed playback to get pcm volume. */
554 		w = hdaa_widget_get(devinfo, 5);
555 		if (w != NULL)
556 			w->connsenable[0] = 0;
557 		w = hdaa_widget_get(devinfo, 6);
558 		if (w != NULL)
559 			w->connsenable[0] = 0;
560 		w = hdaa_widget_get(devinfo, 11);
561 		if (w != NULL)
562 			w->connsenable[0] = 0;
563 		/* Disable mic and line selectors. */
564 		w = hdaa_widget_get(devinfo, 12);
565 		if (w != NULL)
566 			w->connsenable[1] = 0;
567 		w = hdaa_widget_get(devinfo, 13);
568 		if (w != NULL)
569 			w->connsenable[1] = 0;
570 		/* Disable recording from mono playback mix. */
571 		w = hdaa_widget_get(devinfo, 20);
572 		if (w != NULL)
573 			w->connsenable[3] = 0;
574 		break;
575 	case HDA_CODEC_AD1986A:
576 		/*
577 		 * This CODEC has overcomplicated input mixing.
578 		 * Make some cleaning there.
579 		 */
580 		/* Disable input mono mixer. Not needed and not supported. */
581 		w = hdaa_widget_get(devinfo, 43);
582 		if (w != NULL)
583 			w->enable = 0;
584 		/* Disable any with any input mixing mesh. Use separately. */
585 		w = hdaa_widget_get(devinfo, 39);
586 		if (w != NULL)
587 			w->enable = 0;
588 		w = hdaa_widget_get(devinfo, 40);
589 		if (w != NULL)
590 			w->enable = 0;
591 		w = hdaa_widget_get(devinfo, 41);
592 		if (w != NULL)
593 			w->enable = 0;
594 		w = hdaa_widget_get(devinfo, 42);
595 		if (w != NULL)
596 			w->enable = 0;
597 		/* Disable duplicate mixer node connector. */
598 		w = hdaa_widget_get(devinfo, 15);
599 		if (w != NULL)
600 			w->connsenable[3] = 0;
601 		/* There is only one mic preamplifier, use it effectively. */
602 		w = hdaa_widget_get(devinfo, 31);
603 		if (w != NULL) {
604 			if ((w->wclass.pin.config &
605 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
606 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
607 				w = hdaa_widget_get(devinfo, 16);
608 				if (w != NULL)
609 				    w->connsenable[2] = 0;
610 			} else {
611 				w = hdaa_widget_get(devinfo, 15);
612 				if (w != NULL)
613 				    w->connsenable[0] = 0;
614 			}
615 		}
616 		w = hdaa_widget_get(devinfo, 32);
617 		if (w != NULL) {
618 			if ((w->wclass.pin.config &
619 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
620 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
621 				w = hdaa_widget_get(devinfo, 16);
622 				if (w != NULL)
623 				    w->connsenable[0] = 0;
624 			} else {
625 				w = hdaa_widget_get(devinfo, 15);
626 				if (w != NULL)
627 				    w->connsenable[1] = 0;
628 			}
629 		}
630 
631 		if (subid == ASUS_A8X_SUBVENDOR) {
632 			/*
633 			 * This is just plain ridiculous.. There
634 			 * are several A8 series that share the same
635 			 * pci id but works differently (EAPD).
636 			 */
637 			w = hdaa_widget_get(devinfo, 26);
638 			if (w != NULL && w->type ==
639 			    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
640 			    (w->wclass.pin.config &
641 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
642 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
643 				devinfo->quirks &=
644 				    ~HDAA_QUIRK_EAPDINV;
645 		}
646 		break;
647 	case HDA_CODEC_AD1981HD:
648 		/*
649 		 * This CODEC has very unusual design with several
650 		 * points inappropriate for the present parser.
651 		 */
652 		/* Disable recording from mono playback mix. */
653 		w = hdaa_widget_get(devinfo, 21);
654 		if (w != NULL)
655 			w->connsenable[3] = 0;
656 		/* Disable rear to front mic mixer, use separately. */
657 		w = hdaa_widget_get(devinfo, 31);
658 		if (w != NULL)
659 			w->enable = 0;
660 		/* Disable direct playback, use mixer. */
661 		w = hdaa_widget_get(devinfo, 5);
662 		if (w != NULL)
663 			w->connsenable[0] = 0;
664 		w = hdaa_widget_get(devinfo, 6);
665 		if (w != NULL)
666 			w->connsenable[0] = 0;
667 		w = hdaa_widget_get(devinfo, 9);
668 		if (w != NULL)
669 			w->connsenable[0] = 0;
670 		w = hdaa_widget_get(devinfo, 24);
671 		if (w != NULL)
672 			w->connsenable[0] = 0;
673 		break;
674 	case HDA_CODEC_ALC256:
675 		val = hda_read_coef_idx(devinfo->dev, 0x20, 0x46);
676 		hda_write_coef_idx(devinfo->dev, 0x20, 0x46, val|0x3000);
677 		break;
678 	case HDA_CODEC_ALC269:
679 		/*
680 		 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
681 		 * that mutes speaker if unused mixer at NID 15 is muted.
682 		 * Probably CODEC incorrectly reports internal connections.
683 		 * Hide that muter from the driver.  There are several CODECs
684 		 * sharing this ID and I have not enough information about
685 		 * them to implement more universal solution.
686 		 */
687 		if (subid == 0x84371043) {
688 			w = hdaa_widget_get(devinfo, 15);
689 			if (w != NULL)
690 				w->param.inamp_cap = 0;
691 		}
692 		break;
693 	case HDA_CODEC_CX20582:
694 	case HDA_CODEC_CX20583:
695 	case HDA_CODEC_CX20584:
696 	case HDA_CODEC_CX20585:
697 	case HDA_CODEC_CX20590:
698 		/*
699 		 * These codecs have extra connectivity on record side
700 		 * too reach for the present parser.
701 		 */
702 		w = hdaa_widget_get(devinfo, 20);
703 		if (w != NULL)
704 			w->connsenable[1] = 0;
705 		w = hdaa_widget_get(devinfo, 21);
706 		if (w != NULL)
707 			w->connsenable[1] = 0;
708 		w = hdaa_widget_get(devinfo, 22);
709 		if (w != NULL)
710 			w->connsenable[0] = 0;
711 		break;
712 	case HDA_CODEC_VT1708S_0:
713 	case HDA_CODEC_VT1708S_1:
714 	case HDA_CODEC_VT1708S_2:
715 	case HDA_CODEC_VT1708S_3:
716 	case HDA_CODEC_VT1708S_4:
717 	case HDA_CODEC_VT1708S_5:
718 	case HDA_CODEC_VT1708S_6:
719 	case HDA_CODEC_VT1708S_7:
720 		/*
721 		 * These codecs have hidden mic boost controls.
722 		 */
723 		w = hdaa_widget_get(devinfo, 26);
724 		if (w != NULL)
725 			w->param.inamp_cap =
726 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
727 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
728 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
729 		w = hdaa_widget_get(devinfo, 30);
730 		if (w != NULL)
731 			w->param.inamp_cap =
732 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
733 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
734 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
735 		break;
736 	}
737 }
738 
739 void
740 hdaa_patch_direct(struct hdaa_devinfo *devinfo)
741 {
742 	device_t dev = devinfo->dev;
743 	uint32_t id, subid, val;
744 
745 	id = hdaa_codec_id(devinfo);
746 	subid = hdaa_card_id(devinfo);
747 
748 	switch (id) {
749 	case HDA_CODEC_VT1708S_0:
750 	case HDA_CODEC_VT1708S_1:
751 	case HDA_CODEC_VT1708S_2:
752 	case HDA_CODEC_VT1708S_3:
753 	case HDA_CODEC_VT1708S_4:
754 	case HDA_CODEC_VT1708S_5:
755 	case HDA_CODEC_VT1708S_6:
756 	case HDA_CODEC_VT1708S_7:
757 		/* Enable Mic Boost Volume controls. */
758 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
759 		    0xf98, 0x01));
760 		/* Fall though */
761 	case HDA_CODEC_VT1818S:
762 		/* Don't bypass mixer. */
763 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
764 		    0xf88, 0xc0));
765 		break;
766 	}
767 	if (subid == APPLE_INTEL_MAC)
768 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
769 		    0x7e7, 0));
770 	if (id == HDA_CODEC_ALC269) {
771 		if (subid == 0x16e31043 || subid == 0x831a1043 ||
772 		    subid == 0x834a1043 || subid == 0x83981043 ||
773 		    subid == 0x83ce1043) {
774 			/*
775 			 * The ditital mics on some Asus laptops produce
776 			 * differential signals instead of expected stereo.
777 			 * That results in silence if downmix it to mono.
778 			 * To workaround, make codec to handle signal as mono.
779 			 */
780 			hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
781 			val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20));
782 			hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
783 			hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80));
784 		}
785 	}
786 	if (id == HDA_CODEC_ALC283) {
787 		if (subid == ACER_C720_SUBVENDOR ||
788 		    subid == ACER_C720_SUBVENDOR2)
789 			hdaa_patch_direct_acer_c720(devinfo);
790 	}
791 }
792 
793 /* XXX move me to a better place */
794 uint32_t
795 hda_read_coef_idx(device_t dev, nid_t nid, unsigned int coef_idx)
796 {
797 	uint32_t val;
798 
799 	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, coef_idx));
800 	val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid));
801 	return val;
802 }
803 
804 void
805 hda_write_coef_idx(device_t dev, nid_t nid, unsigned int coef_idx,
806 		   unsigned coef_val)
807 {
808 	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, coef_idx));
809 	hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, coef_val));
810 }
811