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