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