hdaa_patches.c revision 269158
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 269158 2014-07-27 20:14:22Z adrian $");
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_CX20561 &&
350	    subid == LENOVO_T400_SUBVENDOR) {
351		switch (nid) {
352		case 22:
353			patch = "as=1 seq=15";
354			break;
355		case 26:
356			patch = "as=1 seq=0";
357			break;
358		}
359	} else if (id == HDA_CODEC_CX20590 &&
360	    (subid == LENOVO_X1_SUBVENDOR ||
361	    subid == LENOVO_X220_SUBVENDOR ||
362	    subid == LENOVO_T420_SUBVENDOR ||
363	    subid == LENOVO_T520_SUBVENDOR ||
364	    subid == LENOVO_G580_SUBVENDOR)) {
365		switch (nid) {
366		case 25:
367			patch = "as=1 seq=15";
368			break;
369		/*
370		 * Group onboard mic and headphone mic
371		 * together.  Fixes onboard mic.
372		 */
373		case 27:
374			patch = "as=2 seq=15";
375			break;
376		case 35:
377			patch = "as=2";
378			break;
379		}
380	} else if (id == HDA_CODEC_ALC269 &&
381	    (subid == LENOVO_X1CRBN_SUBVENDOR ||
382	    subid == LENOVO_T430_SUBVENDOR ||
383	    subid == LENOVO_T430S_SUBVENDOR ||
384	    subid == LENOVO_T530_SUBVENDOR)) {
385		switch (nid) {
386		case 21:
387			patch = "as=1 seq=15";
388			break;
389		}
390	} else if (id == HDA_CODEC_ALC269 &&
391	    subid == ASUS_UX31A_SUBVENDOR) {
392		switch (nid) {
393		case 33:
394			patch = "as=1 seq=15";
395			break;
396		}
397	} else if (id == HDA_CODEC_ALC892 &&
398	    subid == INTEL_DH87RL_SUBVENDOR) {
399		switch (nid) {
400		case 27:
401			patch = "as=1 seq=15";
402			break;
403		}
404	}
405
406	if (patch != NULL)
407		config = hdaa_widget_pin_patch(config, patch);
408	HDA_BOOTVERBOSE(
409		if (config != orig)
410			device_printf(w->devinfo->dev,
411			    "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
412			    nid, orig, config);
413	);
414	w->wclass.pin.config = config;
415}
416
417static void
418hdaa_widget_patch(struct hdaa_widget *w)
419{
420	struct hdaa_devinfo *devinfo = w->devinfo;
421	uint32_t orig;
422	nid_t beeper = -1;
423
424	orig = w->param.widget_cap;
425	/* On some codecs beeper is an input pin, but it is not recordable
426	   alone. Also most of BIOSes does not declare beeper pin.
427	   Change beeper pin node type to beeper to help parser. */
428	switch (hdaa_codec_id(devinfo)) {
429	case HDA_CODEC_AD1882:
430	case HDA_CODEC_AD1883:
431	case HDA_CODEC_AD1984:
432	case HDA_CODEC_AD1984A:
433	case HDA_CODEC_AD1984B:
434	case HDA_CODEC_AD1987:
435	case HDA_CODEC_AD1988:
436	case HDA_CODEC_AD1988B:
437	case HDA_CODEC_AD1989B:
438		beeper = 26;
439		break;
440	case HDA_CODEC_ALC260:
441		beeper = 23;
442		break;
443	}
444	if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
445	    hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
446		beeper = 29;
447	if (w->nid == beeper) {
448		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
449		w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
450		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
451		w->waspin = 1;
452	}
453	/*
454	 * Clear "digital" flag from digital mic input, as its signal then goes
455	 * to "analog" mixer and this separation just limits functionaity.
456	 */
457	if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
458	    w->nid == 23)
459		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
460	HDA_BOOTVERBOSE(
461		if (w->param.widget_cap != orig) {
462			device_printf(w->devinfo->dev,
463			    "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
464			    w->nid, orig, w->param.widget_cap);
465		}
466	);
467
468	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
469		hdac_pin_patch(w);
470}
471
472void
473hdaa_patch(struct hdaa_devinfo *devinfo)
474{
475	struct hdaa_widget *w;
476	uint32_t id, subid, subsystemid;
477	int i;
478
479	id = hdaa_codec_id(devinfo);
480	subid = hdaa_card_id(devinfo);
481	subsystemid = hda_get_subsystem_id(devinfo->dev);
482
483	/*
484	 * Quirks
485	 */
486	for (i = 0; i < nitems(hdac_quirks); i++) {
487		if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
488		    HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
489		    HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
490			continue;
491		devinfo->quirks |= hdac_quirks[i].set;
492		devinfo->quirks &= ~(hdac_quirks[i].unset);
493		devinfo->gpio = hdac_quirks[i].gpio;
494	}
495
496	/* Apply per-widget patch. */
497	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
498		w = hdaa_widget_get(devinfo, i);
499		if (w == NULL)
500			continue;
501		hdaa_widget_patch(w);
502	}
503
504	switch (id) {
505	case HDA_CODEC_AD1983:
506		/*
507		 * This CODEC has several possible usages, but none
508		 * fit the parser best. Help parser to choose better.
509		 */
510		/* Disable direct unmixed playback to get pcm volume. */
511		w = hdaa_widget_get(devinfo, 5);
512		if (w != NULL)
513			w->connsenable[0] = 0;
514		w = hdaa_widget_get(devinfo, 6);
515		if (w != NULL)
516			w->connsenable[0] = 0;
517		w = hdaa_widget_get(devinfo, 11);
518		if (w != NULL)
519			w->connsenable[0] = 0;
520		/* Disable mic and line selectors. */
521		w = hdaa_widget_get(devinfo, 12);
522		if (w != NULL)
523			w->connsenable[1] = 0;
524		w = hdaa_widget_get(devinfo, 13);
525		if (w != NULL)
526			w->connsenable[1] = 0;
527		/* Disable recording from mono playback mix. */
528		w = hdaa_widget_get(devinfo, 20);
529		if (w != NULL)
530			w->connsenable[3] = 0;
531		break;
532	case HDA_CODEC_AD1986A:
533		/*
534		 * This CODEC has overcomplicated input mixing.
535		 * Make some cleaning there.
536		 */
537		/* Disable input mono mixer. Not needed and not supported. */
538		w = hdaa_widget_get(devinfo, 43);
539		if (w != NULL)
540			w->enable = 0;
541		/* Disable any with any input mixing mesh. Use separately. */
542		w = hdaa_widget_get(devinfo, 39);
543		if (w != NULL)
544			w->enable = 0;
545		w = hdaa_widget_get(devinfo, 40);
546		if (w != NULL)
547			w->enable = 0;
548		w = hdaa_widget_get(devinfo, 41);
549		if (w != NULL)
550			w->enable = 0;
551		w = hdaa_widget_get(devinfo, 42);
552		if (w != NULL)
553			w->enable = 0;
554		/* Disable duplicate mixer node connector. */
555		w = hdaa_widget_get(devinfo, 15);
556		if (w != NULL)
557			w->connsenable[3] = 0;
558		/* There is only one mic preamplifier, use it effectively. */
559		w = hdaa_widget_get(devinfo, 31);
560		if (w != NULL) {
561			if ((w->wclass.pin.config &
562			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
563			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
564				w = hdaa_widget_get(devinfo, 16);
565				if (w != NULL)
566				    w->connsenable[2] = 0;
567			} else {
568				w = hdaa_widget_get(devinfo, 15);
569				if (w != NULL)
570				    w->connsenable[0] = 0;
571			}
572		}
573		w = hdaa_widget_get(devinfo, 32);
574		if (w != NULL) {
575			if ((w->wclass.pin.config &
576			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
577			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
578				w = hdaa_widget_get(devinfo, 16);
579				if (w != NULL)
580				    w->connsenable[0] = 0;
581			} else {
582				w = hdaa_widget_get(devinfo, 15);
583				if (w != NULL)
584				    w->connsenable[1] = 0;
585			}
586		}
587
588		if (subid == ASUS_A8X_SUBVENDOR) {
589			/*
590			 * This is just plain ridiculous.. There
591			 * are several A8 series that share the same
592			 * pci id but works differently (EAPD).
593			 */
594			w = hdaa_widget_get(devinfo, 26);
595			if (w != NULL && w->type ==
596			    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
597			    (w->wclass.pin.config &
598			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
599			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
600				devinfo->quirks &=
601				    ~HDAA_QUIRK_EAPDINV;
602		}
603		break;
604	case HDA_CODEC_AD1981HD:
605		/*
606		 * This CODEC has very unusual design with several
607		 * points inappropriate for the present parser.
608		 */
609		/* Disable recording from mono playback mix. */
610		w = hdaa_widget_get(devinfo, 21);
611		if (w != NULL)
612			w->connsenable[3] = 0;
613		/* Disable rear to front mic mixer, use separately. */
614		w = hdaa_widget_get(devinfo, 31);
615		if (w != NULL)
616			w->enable = 0;
617		/* Disable direct playback, use mixer. */
618		w = hdaa_widget_get(devinfo, 5);
619		if (w != NULL)
620			w->connsenable[0] = 0;
621		w = hdaa_widget_get(devinfo, 6);
622		if (w != NULL)
623			w->connsenable[0] = 0;
624		w = hdaa_widget_get(devinfo, 9);
625		if (w != NULL)
626			w->connsenable[0] = 0;
627		w = hdaa_widget_get(devinfo, 24);
628		if (w != NULL)
629			w->connsenable[0] = 0;
630		break;
631	case HDA_CODEC_ALC269:
632		/*
633		 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
634		 * that mutes speaker if unused mixer at NID 15 is muted.
635		 * Probably CODEC incorrectly reports internal connections.
636		 * Hide that muter from the driver.  There are several CODECs
637		 * sharing this ID and I have not enough information about
638		 * them to implement more universal solution.
639		 */
640		if (subid == 0x84371043) {
641			w = hdaa_widget_get(devinfo, 15);
642			if (w != NULL)
643				w->param.inamp_cap = 0;
644		}
645		break;
646	case HDA_CODEC_CX20582:
647	case HDA_CODEC_CX20583:
648	case HDA_CODEC_CX20584:
649	case HDA_CODEC_CX20585:
650	case HDA_CODEC_CX20590:
651		/*
652		 * These codecs have extra connectivity on record side
653		 * too reach for the present parser.
654		 */
655		w = hdaa_widget_get(devinfo, 20);
656		if (w != NULL)
657			w->connsenable[1] = 0;
658		w = hdaa_widget_get(devinfo, 21);
659		if (w != NULL)
660			w->connsenable[1] = 0;
661		w = hdaa_widget_get(devinfo, 22);
662		if (w != NULL)
663			w->connsenable[0] = 0;
664		break;
665	case HDA_CODEC_VT1708S_0:
666	case HDA_CODEC_VT1708S_1:
667	case HDA_CODEC_VT1708S_2:
668	case HDA_CODEC_VT1708S_3:
669	case HDA_CODEC_VT1708S_4:
670	case HDA_CODEC_VT1708S_5:
671	case HDA_CODEC_VT1708S_6:
672	case HDA_CODEC_VT1708S_7:
673		/*
674		 * These codecs have hidden mic boost controls.
675		 */
676		w = hdaa_widget_get(devinfo, 26);
677		if (w != NULL)
678			w->param.inamp_cap =
679			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
680			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
681			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
682		w = hdaa_widget_get(devinfo, 30);
683		if (w != NULL)
684			w->param.inamp_cap =
685			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
686			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
687			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
688		break;
689	}
690}
691
692void
693hdaa_patch_direct(struct hdaa_devinfo *devinfo)
694{
695	device_t dev = devinfo->dev;
696	uint32_t id, subid, val;
697
698	id = hdaa_codec_id(devinfo);
699	subid = hdaa_card_id(devinfo);
700
701	switch (id) {
702	case HDA_CODEC_VT1708S_0:
703	case HDA_CODEC_VT1708S_1:
704	case HDA_CODEC_VT1708S_2:
705	case HDA_CODEC_VT1708S_3:
706	case HDA_CODEC_VT1708S_4:
707	case HDA_CODEC_VT1708S_5:
708	case HDA_CODEC_VT1708S_6:
709	case HDA_CODEC_VT1708S_7:
710		/* Enable Mic Boost Volume controls. */
711		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
712		    0xf98, 0x01));
713		/* Fall though */
714	case HDA_CODEC_VT1818S:
715		/* Don't bypass mixer. */
716		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
717		    0xf88, 0xc0));
718		break;
719	}
720	if (subid == APPLE_INTEL_MAC)
721		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
722		    0x7e7, 0));
723	if (id == HDA_CODEC_ALC269) {
724		if (subid == 0x16e31043 || subid == 0x831a1043 ||
725		    subid == 0x834a1043 || subid == 0x83981043 ||
726		    subid == 0x83ce1043) {
727			/*
728			 * The ditital mics on some Asus laptops produce
729			 * differential signals instead of expected stereo.
730			 * That results in silence if downmix it to mono.
731			 * To workaround, make codec to handle signal as mono.
732			 */
733			hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
734			val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20));
735			hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
736			hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80));
737		}
738	}
739}
740