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