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