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