hdaa_patches.c revision 232798
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/9/sys/dev/sound/pci/hda/hdaa_patches.c 232798 2012-03-10 21:58:08Z mav $");
46
47static const struct {
48	uint32_t model;
49	uint32_t id;
50	uint32_t set, unset;
51	uint32_t gpio;
52} hdac_quirks[] = {
53	/*
54	 * XXX Force stereo quirk. Monoural recording / playback
55	 *     on few codecs (especially ALC880) seems broken or
56	 *     perhaps unsupported.
57	 */
58	{ HDA_MATCH_ALL, HDA_MATCH_ALL,
59	    HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
60	    0 },
61	{ ACER_ALL_SUBVENDOR, HDA_MATCH_ALL,
62	    0, 0,
63	    HDAA_GPIO_SET(0) },
64	{ ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660,
65	    0, 0,
66	    HDAA_GPIO_SET(0) },
67	{ ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880,
68	    0, 0,
69	    HDAA_GPIO_SET(0) },
70	{ ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880,
71	    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_subvendor_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_AD1986A &&
275	    (subid == ASUS_M2NPVMX_SUBVENDOR ||
276	    subid == ASUS_A8NVMCSM_SUBVENDOR ||
277	    subid == ASUS_P5PL2_SUBVENDOR)) {
278		switch (nid) {
279		case 26: /* Headphones with redirection */
280			patch = "as=1 seq=15";
281			break;
282		case 28: /* 5.1 out => 2.0 out + 1 input */
283			patch = "device=Line-in as=8 seq=1";
284			break;
285		case 29: /* Can't use this as input, as the only available mic
286			  * preamplifier is busy by front panel mic (nid 31).
287			  * If you want to use this rear connector as mic input,
288			  * you have to disable the front panel one. */
289			patch = "as=0";
290			break;
291		case 31: /* Lot of inputs configured with as=15 and unusable */
292			patch = "as=8 seq=3";
293			break;
294		case 32:
295			patch = "as=8 seq=4";
296			break;
297		case 34:
298			patch = "as=8 seq=5";
299			break;
300		case 36:
301			patch = "as=8 seq=6";
302			break;
303		}
304	} else if (id == HDA_CODEC_ALC260 &&
305	    HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
306		switch (nid) {
307		case 16:
308			patch = "seq=15 device=Headphones";
309			break;
310		}
311	} else if (id == HDA_CODEC_ALC268) {
312	    if (subid == ACER_T5320_SUBVENDOR) {
313		switch (nid) {
314		case 20: /* Headphones Jack */
315			patch = "as=1 seq=15";
316			break;
317		}
318	    }
319	} else if (id == HDA_CODEC_CX20561 &&
320	    subid == LENOVO_B450_SUBVENDOR) {
321		switch (nid) {
322		case 22:
323			patch = "as=1 seq=15";
324			break;
325		}
326	}
327
328	if (patch != NULL)
329		config = hdaa_widget_pin_patch(config, patch);
330	HDA_BOOTVERBOSE(
331		if (config != orig)
332			device_printf(w->devinfo->dev,
333			    "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
334			    nid, orig, config);
335	);
336	w->wclass.pin.config = config;
337}
338
339static void
340hdaa_widget_patch(struct hdaa_widget *w)
341{
342	struct hdaa_devinfo *devinfo = w->devinfo;
343	uint32_t orig;
344	nid_t beeper = -1;
345
346	orig = w->param.widget_cap;
347	/* On some codecs beeper is an input pin, but it is not recordable
348	   alone. Also most of BIOSes does not declare beeper pin.
349	   Change beeper pin node type to beeper to help parser. */
350	switch (hdaa_codec_id(devinfo)) {
351	case HDA_CODEC_AD1882:
352	case HDA_CODEC_AD1883:
353	case HDA_CODEC_AD1984:
354	case HDA_CODEC_AD1984A:
355	case HDA_CODEC_AD1984B:
356	case HDA_CODEC_AD1987:
357	case HDA_CODEC_AD1988:
358	case HDA_CODEC_AD1988B:
359	case HDA_CODEC_AD1989B:
360		beeper = 26;
361		break;
362	case HDA_CODEC_ALC260:
363		beeper = 23;
364		break;
365	}
366	if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
367	    hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
368		beeper = 29;
369	if (w->nid == beeper) {
370		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
371		w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
372		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
373		w->waspin = 1;
374	}
375	HDA_BOOTVERBOSE(
376		if (w->param.widget_cap != orig) {
377			device_printf(w->devinfo->dev,
378			    "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
379			    w->nid, orig, w->param.widget_cap);
380		}
381	);
382
383	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
384		hdac_pin_patch(w);
385}
386
387void
388hdaa_patch(struct hdaa_devinfo *devinfo)
389{
390	struct hdaa_widget *w;
391	uint32_t id, subid;
392	int i;
393
394	id = hdaa_codec_id(devinfo);
395	subid = hdaa_subvendor_id(devinfo);
396
397	/*
398	 * Quirks
399	 */
400	for (i = 0; i < HDAC_QUIRKS_LEN; i++) {
401		if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
402		    HDA_DEV_MATCH(hdac_quirks[i].id, id)))
403			continue;
404		if (hdac_quirks[i].set != 0)
405			devinfo->quirks |=
406			    hdac_quirks[i].set;
407		if (hdac_quirks[i].unset != 0)
408			devinfo->quirks &=
409			    ~(hdac_quirks[i].unset);
410	}
411
412	/* Apply per-widget patch. */
413	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
414		w = hdaa_widget_get(devinfo, i);
415		if (w == NULL)
416			continue;
417		hdaa_widget_patch(w);
418	}
419
420	switch (id) {
421	case HDA_CODEC_AD1983:
422		/*
423		 * This CODEC has several possible usages, but none
424		 * fit the parser best. Help parser to choose better.
425		 */
426		/* Disable direct unmixed playback to get pcm volume. */
427		w = hdaa_widget_get(devinfo, 5);
428		if (w != NULL)
429			w->connsenable[0] = 0;
430		w = hdaa_widget_get(devinfo, 6);
431		if (w != NULL)
432			w->connsenable[0] = 0;
433		w = hdaa_widget_get(devinfo, 11);
434		if (w != NULL)
435			w->connsenable[0] = 0;
436		/* Disable mic and line selectors. */
437		w = hdaa_widget_get(devinfo, 12);
438		if (w != NULL)
439			w->connsenable[1] = 0;
440		w = hdaa_widget_get(devinfo, 13);
441		if (w != NULL)
442			w->connsenable[1] = 0;
443		/* Disable recording from mono playback mix. */
444		w = hdaa_widget_get(devinfo, 20);
445		if (w != NULL)
446			w->connsenable[3] = 0;
447		break;
448	case HDA_CODEC_AD1986A:
449		/*
450		 * This CODEC has overcomplicated input mixing.
451		 * Make some cleaning there.
452		 */
453		/* Disable input mono mixer. Not needed and not supported. */
454		w = hdaa_widget_get(devinfo, 43);
455		if (w != NULL)
456			w->enable = 0;
457		/* Disable any with any input mixing mesh. Use separately. */
458		w = hdaa_widget_get(devinfo, 39);
459		if (w != NULL)
460			w->enable = 0;
461		w = hdaa_widget_get(devinfo, 40);
462		if (w != NULL)
463			w->enable = 0;
464		w = hdaa_widget_get(devinfo, 41);
465		if (w != NULL)
466			w->enable = 0;
467		w = hdaa_widget_get(devinfo, 42);
468		if (w != NULL)
469			w->enable = 0;
470		/* Disable duplicate mixer node connector. */
471		w = hdaa_widget_get(devinfo, 15);
472		if (w != NULL)
473			w->connsenable[3] = 0;
474		/* There is only one mic preamplifier, use it effectively. */
475		w = hdaa_widget_get(devinfo, 31);
476		if (w != NULL) {
477			if ((w->wclass.pin.config &
478			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
479			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
480				w = hdaa_widget_get(devinfo, 16);
481				if (w != NULL)
482				    w->connsenable[2] = 0;
483			} else {
484				w = hdaa_widget_get(devinfo, 15);
485				if (w != NULL)
486				    w->connsenable[0] = 0;
487			}
488		}
489		w = hdaa_widget_get(devinfo, 32);
490		if (w != NULL) {
491			if ((w->wclass.pin.config &
492			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
493			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
494				w = hdaa_widget_get(devinfo, 16);
495				if (w != NULL)
496				    w->connsenable[0] = 0;
497			} else {
498				w = hdaa_widget_get(devinfo, 15);
499				if (w != NULL)
500				    w->connsenable[1] = 0;
501			}
502		}
503
504		if (subid == ASUS_A8X_SUBVENDOR) {
505			/*
506			 * This is just plain ridiculous.. There
507			 * are several A8 series that share the same
508			 * pci id but works differently (EAPD).
509			 */
510			w = hdaa_widget_get(devinfo, 26);
511			if (w != NULL && w->type ==
512			    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
513			    (w->wclass.pin.config &
514			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
515			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
516				devinfo->quirks &=
517				    ~HDAA_QUIRK_EAPDINV;
518		}
519		break;
520	case HDA_CODEC_AD1981HD:
521		/*
522		 * This CODEC has very unusual design with several
523		 * points inappropriate for the present parser.
524		 */
525		/* Disable recording from mono playback mix. */
526		w = hdaa_widget_get(devinfo, 21);
527		if (w != NULL)
528			w->connsenable[3] = 0;
529		/* Disable rear to front mic mixer, use separately. */
530		w = hdaa_widget_get(devinfo, 31);
531		if (w != NULL)
532			w->enable = 0;
533		/* Disable direct playback, use mixer. */
534		w = hdaa_widget_get(devinfo, 5);
535		if (w != NULL)
536			w->connsenable[0] = 0;
537		w = hdaa_widget_get(devinfo, 6);
538		if (w != NULL)
539			w->connsenable[0] = 0;
540		w = hdaa_widget_get(devinfo, 9);
541		if (w != NULL)
542			w->connsenable[0] = 0;
543		w = hdaa_widget_get(devinfo, 24);
544		if (w != NULL)
545			w->connsenable[0] = 0;
546		break;
547	case HDA_CODEC_CX20582:
548	case HDA_CODEC_CX20583:
549	case HDA_CODEC_CX20584:
550	case HDA_CODEC_CX20585:
551	case HDA_CODEC_CX20590:
552		/*
553		 * These codecs have extra connectivity on record side
554		 * too reach for the present parser.
555		 */
556		w = hdaa_widget_get(devinfo, 20);
557		if (w != NULL)
558			w->connsenable[1] = 0;
559		w = hdaa_widget_get(devinfo, 21);
560		if (w != NULL)
561			w->connsenable[1] = 0;
562		w = hdaa_widget_get(devinfo, 22);
563		if (w != NULL)
564			w->connsenable[0] = 0;
565		break;
566	case HDA_CODEC_VT1708S_0:
567	case HDA_CODEC_VT1708S_1:
568	case HDA_CODEC_VT1708S_2:
569	case HDA_CODEC_VT1708S_3:
570	case HDA_CODEC_VT1708S_4:
571	case HDA_CODEC_VT1708S_5:
572	case HDA_CODEC_VT1708S_6:
573	case HDA_CODEC_VT1708S_7:
574		/*
575		 * These codecs have hidden mic boost controls.
576		 */
577		w = hdaa_widget_get(devinfo, 26);
578		if (w != NULL)
579			w->param.inamp_cap =
580			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
581			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
582			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
583		w = hdaa_widget_get(devinfo, 30);
584		if (w != NULL)
585			w->param.inamp_cap =
586			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
587			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
588			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
589		break;
590	}
591}
592
593void
594hdaa_patch_direct(struct hdaa_devinfo *devinfo)
595{
596	device_t dev = devinfo->dev;
597	uint32_t id, subid, val;
598
599	id = hdaa_codec_id(devinfo);
600	subid = hdaa_subvendor_id(devinfo);
601
602	switch (id) {
603	case HDA_CODEC_VT1708S_0:
604	case HDA_CODEC_VT1708S_1:
605	case HDA_CODEC_VT1708S_2:
606	case HDA_CODEC_VT1708S_3:
607	case HDA_CODEC_VT1708S_4:
608	case HDA_CODEC_VT1708S_5:
609	case HDA_CODEC_VT1708S_6:
610	case HDA_CODEC_VT1708S_7:
611		/* Enable Mic Boost Volume controls. */
612		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
613		    0xf98, 0x01));
614		/* Don't bypass mixer. */
615		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
616		    0xf88, 0xc0));
617		break;
618	}
619	if (subid == APPLE_INTEL_MAC)
620		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
621		    0x7e7, 0));
622	if (id == HDA_CODEC_ALC269) {
623		if (subid == 0x16e31043 || subid == 0x831a1043 ||
624		    subid == 0x834a1043 || subid == 0x83981043 ||
625		    subid == 0x83ce1043) {
626			/*
627			 * The ditital mics on some Asus laptops produce
628			 * differential signals instead of expected stereo.
629			 * That results in silence if downmix it to mono.
630			 * To workaround, make codec to handle signal as mono.
631			 */
632			hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
633			val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20));
634			hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
635			hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80));
636		}
637	}
638}
639