hdaa_patches.c revision 247911
151766Scg/*-
251766Scg * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
351766Scg * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
451766Scg * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
551766Scg * All rights reserved.
651766Scg *
751766Scg * Redistribution and use in source and binary forms, with or without
851766Scg * modification, are permitted provided that the following conditions
951766Scg * are met:
1051766Scg * 1. Redistributions of source code must retain the above copyright
1151766Scg *    notice, this list of conditions and the following disclaimer.
1251766Scg * 2. Redistributions in binary form must reproduce the above copyright
1351766Scg *    notice, this list of conditions and the following disclaimer in the
1451766Scg *    documentation and/or other materials provided with the distribution.
1551766Scg *
1651766Scg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1751766Scg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1851766Scg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1951766Scg * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2051766Scg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2151766Scg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2251766Scg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2351766Scg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2451766Scg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2551766Scg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2651766Scg * SUCH DAMAGE.
2751766Scg */
2851766Scg
2951766Scg/*
3051766Scg * Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
3151766Scg */
3251766Scg
3351766Scg#ifdef HAVE_KERNEL_OPTION_HEADERS
3451766Scg#include "opt_snd.h"
3551766Scg#endif
3651766Scg
3751766Scg#include <dev/sound/pcm/sound.h>
3851766Scg
3951766Scg#include <sys/ctype.h>
4051766Scg
4151766Scg#include <dev/sound/pci/hda/hdac.h>
4251766Scg#include <dev/sound/pci/hda/hdaa.h>
4351766Scg#include <dev/sound/pci/hda/hda_reg.h>
4451766Scg
4551766ScgSND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa_patches.c 247911 2013-03-07 08:00:04Z glebius $");
4651766Scg
4751766Scgstatic const struct {
4851766Scg	uint32_t model;
4951766Scg	uint32_t id;
5051766Scg	uint32_t set, unset;
5151766Scg	uint32_t gpio;
5251766Scg} hdac_quirks[] = {
5351766Scg	/*
5451766Scg	 * XXX Force stereo quirk. Monoural recording / playback
5551766Scg	 *     on few codecs (especially ALC880) seems broken or
5651766Scg	 *     perhaps unsupported.
5751766Scg	 */
5851766Scg	{ HDA_MATCH_ALL, HDA_MATCH_ALL,
5951766Scg	    HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
6051766Scg	    0 },
6151766Scg	{ ACER_ALL_SUBVENDOR, HDA_MATCH_ALL,
6251766Scg	    0, 0,
6351766Scg	    HDAA_GPIO_SET(0) },
6451766Scg	{ ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660,
6551766Scg	    0, 0,
6651766Scg	    HDAA_GPIO_SET(0) },
6751766Scg	{ ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880,
6851766Scg	    0, 0,
6951766Scg	    HDAA_GPIO_SET(0) },
7051766Scg	{ ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880,
7151766Scg	    0, 0,
72	    HDAA_GPIO_SET(0) },
73	{ ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882,
74	    0, 0,
75	    HDAA_GPIO_SET(0) },
76	{ ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882,
77	    0, 0,
78	    HDAA_GPIO_SET(0) },
79	{ ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A,
80	    HDAA_QUIRK_EAPDINV, 0,
81	    0 },
82	{ ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A,
83	    HDAA_QUIRK_EAPDINV, 0,
84	    0 },
85	{ ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861,
86	    HDAA_QUIRK_OVREF, 0,
87	    0 },
88	{ UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861,
89	    HDAA_QUIRK_OVREF, 0,
90	    0 },
91	/*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988,
92	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
93	    0 },*/
94	{ MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880,
95	    0, 0,
96	    HDAA_GPIO_SET(1) },
97	{ LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A,
98	    HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
99	    0 },
100	{ SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A,
101	    HDAA_QUIRK_EAPDINV, 0,
102	    0 },
103	{ APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885,
104	    HDAA_QUIRK_OVREF50, 0,
105	    HDAA_GPIO_SET(0) },
106	{ APPLE_INTEL_MAC, HDA_CODEC_STAC9221,
107	    0, 0,
108	    HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
109	{ APPLE_MACBOOKPRO55, HDA_CODEC_CS4206,
110	    0, 0,
111	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
112	{ DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X,
113	    0, 0,
114	    HDAA_GPIO_SET(0) },
115	{ DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X,
116	    0, 0,
117	    HDAA_GPIO_SET(2) },
118	{ DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X,
119	    0, 0,
120	    HDAA_GPIO_SET(0) },
121	{ HDA_MATCH_ALL, HDA_CODEC_AD1988,
122	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
123	    0 },
124	{ HDA_MATCH_ALL, HDA_CODEC_AD1988B,
125	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
126	    0 },
127	{ HDA_MATCH_ALL, HDA_CODEC_CX20549,
128	    0, HDAA_QUIRK_FORCESTEREO,
129	    0 }
130};
131#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0]))
132
133static void
134hdac_pin_patch(struct hdaa_widget *w)
135{
136	const char *patch = NULL;
137	uint32_t config, orig, id, subid;
138	nid_t nid = w->nid;
139
140	config = orig = w->wclass.pin.config;
141	id = hdaa_codec_id(w->devinfo);
142	subid = hdaa_card_id(w->devinfo);
143
144	/* XXX: Old patches require complete review.
145	 * Now they may create more problem then solve due to
146	 * incorrect associations.
147	 */
148	if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) {
149		switch (nid) {
150		case 26:
151			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
152			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
153			break;
154		case 27:
155			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
156			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT;
157			break;
158		default:
159			break;
160		}
161	} else if (id == HDA_CODEC_ALC880 &&
162	    (subid == CLEVO_D900T_SUBVENDOR ||
163	    subid == ASUS_M5200_SUBVENDOR)) {
164		/*
165		 * Super broken BIOS
166		 */
167		switch (nid) {
168		case 24:	/* MIC1 */
169			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
170			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
171			break;
172		case 25:	/* XXX MIC2 */
173			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
174			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
175			break;
176		case 26:	/* LINE1 */
177			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
178			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
179			break;
180		case 27:	/* XXX LINE2 */
181			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
182			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
183			break;
184		case 28:	/* CD */
185			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
186			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD;
187			break;
188		}
189	} else if (id == HDA_CODEC_ALC883 &&
190	    (subid == MSI_MS034A_SUBVENDOR ||
191	    HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) {
192		switch (nid) {
193		case 25:
194			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
195			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
196			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
197			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
198			break;
199		case 28:
200			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
201			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
202			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
203			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
204			break;
205		}
206	} else if (id == HDA_CODEC_CX20549 && subid ==
207	    HP_V3000_SUBVENDOR) {
208		switch (nid) {
209		case 18:
210			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
211			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
212			break;
213		case 20:
214			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
215			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
216			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
217			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
218			break;
219		case 21:
220			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
221			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
222			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
223			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
224			break;
225		}
226	} else if (id == HDA_CODEC_CX20551 && subid ==
227	    HP_DV5000_SUBVENDOR) {
228		switch (nid) {
229		case 20:
230		case 21:
231			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
232			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
233			break;
234		}
235	} else if (id == HDA_CODEC_ALC861 && subid ==
236	    ASUS_W6F_SUBVENDOR) {
237		switch (nid) {
238		case 11:
239			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
240			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
241			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
242			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
243			break;
244		case 12:
245		case 14:
246		case 16:
247		case 31:
248		case 32:
249			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
250			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
251			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
252			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
253			break;
254		case 15:
255			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
256			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
257			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
258			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
259			break;
260		}
261	} else if (id == HDA_CODEC_ALC861 && subid ==
262	    UNIWILL_9075_SUBVENDOR) {
263		switch (nid) {
264		case 15:
265			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
266			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
267			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
268			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
269			break;
270		}
271	}
272
273	/* New patches */
274	if (id == HDA_CODEC_AD1984A &&
275	    subid == LENOVO_X300_SUBVENDOR) {
276		switch (nid) {
277		case 17: /* Headphones with redirection */
278			patch = "as=1 seq=15";
279			break;
280		case 20: /* Two mics together */
281			patch = "as=2 seq=15";
282			break;
283		}
284	} else if (id == HDA_CODEC_AD1986A &&
285	    (subid == ASUS_M2NPVMX_SUBVENDOR ||
286	    subid == ASUS_A8NVMCSM_SUBVENDOR ||
287	    subid == ASUS_P5PL2_SUBVENDOR)) {
288		switch (nid) {
289		case 26: /* Headphones with redirection */
290			patch = "as=1 seq=15";
291			break;
292		case 28: /* 5.1 out => 2.0 out + 1 input */
293			patch = "device=Line-in as=8 seq=1";
294			break;
295		case 29: /* Can't use this as input, as the only available mic
296			  * preamplifier is busy by front panel mic (nid 31).
297			  * If you want to use this rear connector as mic input,
298			  * you have to disable the front panel one. */
299			patch = "as=0";
300			break;
301		case 31: /* Lot of inputs configured with as=15 and unusable */
302			patch = "as=8 seq=3";
303			break;
304		case 32:
305			patch = "as=8 seq=4";
306			break;
307		case 34:
308			patch = "as=8 seq=5";
309			break;
310		case 36:
311			patch = "as=8 seq=6";
312			break;
313		}
314	} else if (id == HDA_CODEC_ALC260 &&
315	    HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
316		switch (nid) {
317		case 16:
318			patch = "seq=15 device=Headphones";
319			break;
320		}
321	} else if (id == HDA_CODEC_ALC268) {
322	    if (subid == ACER_T5320_SUBVENDOR) {
323		switch (nid) {
324		case 20: /* Headphones Jack */
325			patch = "as=1 seq=15";
326			break;
327		}
328	    }
329	} else if (id == HDA_CODEC_CX20561 &&
330	    subid == LENOVO_B450_SUBVENDOR) {
331		switch (nid) {
332		case 22:
333			patch = "as=1 seq=15";
334			break;
335		}
336	} else if (id == HDA_CODEC_CX20590 &&
337	    (subid == LENOVO_X1_SUBVENDOR ||
338	    subid == LENOVO_X220_SUBVENDOR ||
339	    subid == LENOVO_T420_SUBVENDOR ||
340	    subid == LENOVO_T520_SUBVENDOR)) {
341		switch (nid) {
342		case 25:
343			patch = "as=1 seq=15";
344			break;
345		}
346	} else if (id == HDA_CODEC_ALC269 &&
347	    subid == LENOVO_X1CRBN_SUBVENDOR) {
348		switch (nid) {
349		case 21:
350			patch = "as=1 seq=15";
351			break;
352		}
353	}
354
355	if (patch != NULL)
356		config = hdaa_widget_pin_patch(config, patch);
357	HDA_BOOTVERBOSE(
358		if (config != orig)
359			device_printf(w->devinfo->dev,
360			    "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
361			    nid, orig, config);
362	);
363	w->wclass.pin.config = config;
364}
365
366static void
367hdaa_widget_patch(struct hdaa_widget *w)
368{
369	struct hdaa_devinfo *devinfo = w->devinfo;
370	uint32_t orig;
371	nid_t beeper = -1;
372
373	orig = w->param.widget_cap;
374	/* On some codecs beeper is an input pin, but it is not recordable
375	   alone. Also most of BIOSes does not declare beeper pin.
376	   Change beeper pin node type to beeper to help parser. */
377	switch (hdaa_codec_id(devinfo)) {
378	case HDA_CODEC_AD1882:
379	case HDA_CODEC_AD1883:
380	case HDA_CODEC_AD1984:
381	case HDA_CODEC_AD1984A:
382	case HDA_CODEC_AD1984B:
383	case HDA_CODEC_AD1987:
384	case HDA_CODEC_AD1988:
385	case HDA_CODEC_AD1988B:
386	case HDA_CODEC_AD1989B:
387		beeper = 26;
388		break;
389	case HDA_CODEC_ALC260:
390		beeper = 23;
391		break;
392	}
393	if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
394	    hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
395		beeper = 29;
396	if (w->nid == beeper) {
397		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
398		w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
399		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
400		w->waspin = 1;
401	}
402	/*
403	 * Clear "digital" flag from digital mic input, as its signal then goes
404	 * to "analog" mixer and this separation just limits functionaity.
405	 */
406	if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
407	    w->nid == 23)
408		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
409	HDA_BOOTVERBOSE(
410		if (w->param.widget_cap != orig) {
411			device_printf(w->devinfo->dev,
412			    "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
413			    w->nid, orig, w->param.widget_cap);
414		}
415	);
416
417	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
418		hdac_pin_patch(w);
419}
420
421void
422hdaa_patch(struct hdaa_devinfo *devinfo)
423{
424	struct hdaa_widget *w;
425	uint32_t id, subid;
426	int i;
427
428	id = hdaa_codec_id(devinfo);
429	subid = hdaa_card_id(devinfo);
430
431	/*
432	 * Quirks
433	 */
434	for (i = 0; i < HDAC_QUIRKS_LEN; i++) {
435		if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
436		    HDA_DEV_MATCH(hdac_quirks[i].id, id)))
437			continue;
438		devinfo->quirks |= hdac_quirks[i].set;
439		devinfo->quirks &= ~(hdac_quirks[i].unset);
440		devinfo->gpio = hdac_quirks[i].gpio;
441	}
442
443	/* Apply per-widget patch. */
444	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
445		w = hdaa_widget_get(devinfo, i);
446		if (w == NULL)
447			continue;
448		hdaa_widget_patch(w);
449	}
450
451	switch (id) {
452	case HDA_CODEC_AD1983:
453		/*
454		 * This CODEC has several possible usages, but none
455		 * fit the parser best. Help parser to choose better.
456		 */
457		/* Disable direct unmixed playback to get pcm volume. */
458		w = hdaa_widget_get(devinfo, 5);
459		if (w != NULL)
460			w->connsenable[0] = 0;
461		w = hdaa_widget_get(devinfo, 6);
462		if (w != NULL)
463			w->connsenable[0] = 0;
464		w = hdaa_widget_get(devinfo, 11);
465		if (w != NULL)
466			w->connsenable[0] = 0;
467		/* Disable mic and line selectors. */
468		w = hdaa_widget_get(devinfo, 12);
469		if (w != NULL)
470			w->connsenable[1] = 0;
471		w = hdaa_widget_get(devinfo, 13);
472		if (w != NULL)
473			w->connsenable[1] = 0;
474		/* Disable recording from mono playback mix. */
475		w = hdaa_widget_get(devinfo, 20);
476		if (w != NULL)
477			w->connsenable[3] = 0;
478		break;
479	case HDA_CODEC_AD1986A:
480		/*
481		 * This CODEC has overcomplicated input mixing.
482		 * Make some cleaning there.
483		 */
484		/* Disable input mono mixer. Not needed and not supported. */
485		w = hdaa_widget_get(devinfo, 43);
486		if (w != NULL)
487			w->enable = 0;
488		/* Disable any with any input mixing mesh. Use separately. */
489		w = hdaa_widget_get(devinfo, 39);
490		if (w != NULL)
491			w->enable = 0;
492		w = hdaa_widget_get(devinfo, 40);
493		if (w != NULL)
494			w->enable = 0;
495		w = hdaa_widget_get(devinfo, 41);
496		if (w != NULL)
497			w->enable = 0;
498		w = hdaa_widget_get(devinfo, 42);
499		if (w != NULL)
500			w->enable = 0;
501		/* Disable duplicate mixer node connector. */
502		w = hdaa_widget_get(devinfo, 15);
503		if (w != NULL)
504			w->connsenable[3] = 0;
505		/* There is only one mic preamplifier, use it effectively. */
506		w = hdaa_widget_get(devinfo, 31);
507		if (w != NULL) {
508			if ((w->wclass.pin.config &
509			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
510			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
511				w = hdaa_widget_get(devinfo, 16);
512				if (w != NULL)
513				    w->connsenable[2] = 0;
514			} else {
515				w = hdaa_widget_get(devinfo, 15);
516				if (w != NULL)
517				    w->connsenable[0] = 0;
518			}
519		}
520		w = hdaa_widget_get(devinfo, 32);
521		if (w != NULL) {
522			if ((w->wclass.pin.config &
523			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
524			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
525				w = hdaa_widget_get(devinfo, 16);
526				if (w != NULL)
527				    w->connsenable[0] = 0;
528			} else {
529				w = hdaa_widget_get(devinfo, 15);
530				if (w != NULL)
531				    w->connsenable[1] = 0;
532			}
533		}
534
535		if (subid == ASUS_A8X_SUBVENDOR) {
536			/*
537			 * This is just plain ridiculous.. There
538			 * are several A8 series that share the same
539			 * pci id but works differently (EAPD).
540			 */
541			w = hdaa_widget_get(devinfo, 26);
542			if (w != NULL && w->type ==
543			    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
544			    (w->wclass.pin.config &
545			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
546			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
547				devinfo->quirks &=
548				    ~HDAA_QUIRK_EAPDINV;
549		}
550		break;
551	case HDA_CODEC_AD1981HD:
552		/*
553		 * This CODEC has very unusual design with several
554		 * points inappropriate for the present parser.
555		 */
556		/* Disable recording from mono playback mix. */
557		w = hdaa_widget_get(devinfo, 21);
558		if (w != NULL)
559			w->connsenable[3] = 0;
560		/* Disable rear to front mic mixer, use separately. */
561		w = hdaa_widget_get(devinfo, 31);
562		if (w != NULL)
563			w->enable = 0;
564		/* Disable direct playback, use mixer. */
565		w = hdaa_widget_get(devinfo, 5);
566		if (w != NULL)
567			w->connsenable[0] = 0;
568		w = hdaa_widget_get(devinfo, 6);
569		if (w != NULL)
570			w->connsenable[0] = 0;
571		w = hdaa_widget_get(devinfo, 9);
572		if (w != NULL)
573			w->connsenable[0] = 0;
574		w = hdaa_widget_get(devinfo, 24);
575		if (w != NULL)
576			w->connsenable[0] = 0;
577		break;
578	case HDA_CODEC_ALC269:
579		/*
580		 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
581		 * that mutes speaker if unused mixer at NID 15 is muted.
582		 * Probably CODEC incorrectly reports internal connections.
583		 * Hide that muter from the driver.  There are several CODECs
584		 * sharing this ID and I have not enough information about
585		 * them to implement more universal solution.
586		 */
587		if (subid == 0x84371043) {
588			w = hdaa_widget_get(devinfo, 15);
589			if (w != NULL)
590				w->param.inamp_cap = 0;
591		}
592		break;
593	case HDA_CODEC_CX20582:
594	case HDA_CODEC_CX20583:
595	case HDA_CODEC_CX20584:
596	case HDA_CODEC_CX20585:
597	case HDA_CODEC_CX20590:
598		/*
599		 * These codecs have extra connectivity on record side
600		 * too reach for the present parser.
601		 */
602		w = hdaa_widget_get(devinfo, 20);
603		if (w != NULL)
604			w->connsenable[1] = 0;
605		w = hdaa_widget_get(devinfo, 21);
606		if (w != NULL)
607			w->connsenable[1] = 0;
608		w = hdaa_widget_get(devinfo, 22);
609		if (w != NULL)
610			w->connsenable[0] = 0;
611		break;
612	case HDA_CODEC_VT1708S_0:
613	case HDA_CODEC_VT1708S_1:
614	case HDA_CODEC_VT1708S_2:
615	case HDA_CODEC_VT1708S_3:
616	case HDA_CODEC_VT1708S_4:
617	case HDA_CODEC_VT1708S_5:
618	case HDA_CODEC_VT1708S_6:
619	case HDA_CODEC_VT1708S_7:
620		/*
621		 * These codecs have hidden mic boost controls.
622		 */
623		w = hdaa_widget_get(devinfo, 26);
624		if (w != NULL)
625			w->param.inamp_cap =
626			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
627			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
628			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
629		w = hdaa_widget_get(devinfo, 30);
630		if (w != NULL)
631			w->param.inamp_cap =
632			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
633			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
634			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
635		break;
636	}
637}
638
639void
640hdaa_patch_direct(struct hdaa_devinfo *devinfo)
641{
642	device_t dev = devinfo->dev;
643	uint32_t id, subid, val;
644
645	id = hdaa_codec_id(devinfo);
646	subid = hdaa_card_id(devinfo);
647
648	switch (id) {
649	case HDA_CODEC_VT1708S_0:
650	case HDA_CODEC_VT1708S_1:
651	case HDA_CODEC_VT1708S_2:
652	case HDA_CODEC_VT1708S_3:
653	case HDA_CODEC_VT1708S_4:
654	case HDA_CODEC_VT1708S_5:
655	case HDA_CODEC_VT1708S_6:
656	case HDA_CODEC_VT1708S_7:
657		/* Enable Mic Boost Volume controls. */
658		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
659		    0xf98, 0x01));
660		/* Fall though */
661	case HDA_CODEC_VT1818S:
662		/* Don't bypass mixer. */
663		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
664		    0xf88, 0xc0));
665		break;
666	}
667	if (subid == APPLE_INTEL_MAC)
668		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
669		    0x7e7, 0));
670	if (id == HDA_CODEC_ALC269) {
671		if (subid == 0x16e31043 || subid == 0x831a1043 ||
672		    subid == 0x834a1043 || subid == 0x83981043 ||
673		    subid == 0x83ce1043) {
674			/*
675			 * The ditital mics on some Asus laptops produce
676			 * differential signals instead of expected stereo.
677			 * That results in silence if downmix it to mono.
678			 * To workaround, make codec to handle signal as mono.
679			 */
680			hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
681			val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20));
682			hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
683			hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80));
684		}
685	}
686}
687