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