xref: /freebsd/sys/dev/sound/pci/hda/hdaa_patches.c (revision 89a8fedd7774fbb840ebda33ddb418ea4eb3bfc4)
17c6b05d2SAlexander Motin /*-
27c6b05d2SAlexander Motin  * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
37c6b05d2SAlexander Motin  * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
47c6b05d2SAlexander Motin  * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
57c6b05d2SAlexander Motin  * All rights reserved.
67c6b05d2SAlexander Motin  *
77c6b05d2SAlexander Motin  * Redistribution and use in source and binary forms, with or without
87c6b05d2SAlexander Motin  * modification, are permitted provided that the following conditions
97c6b05d2SAlexander Motin  * are met:
107c6b05d2SAlexander Motin  * 1. Redistributions of source code must retain the above copyright
117c6b05d2SAlexander Motin  *    notice, this list of conditions and the following disclaimer.
127c6b05d2SAlexander Motin  * 2. Redistributions in binary form must reproduce the above copyright
137c6b05d2SAlexander Motin  *    notice, this list of conditions and the following disclaimer in the
147c6b05d2SAlexander Motin  *    documentation and/or other materials provided with the distribution.
157c6b05d2SAlexander Motin  *
167c6b05d2SAlexander Motin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
177c6b05d2SAlexander Motin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
187c6b05d2SAlexander Motin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
197c6b05d2SAlexander Motin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
207c6b05d2SAlexander Motin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
217c6b05d2SAlexander Motin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
227c6b05d2SAlexander Motin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
237c6b05d2SAlexander Motin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
247c6b05d2SAlexander Motin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
257c6b05d2SAlexander Motin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
267c6b05d2SAlexander Motin  * SUCH DAMAGE.
277c6b05d2SAlexander Motin  */
287c6b05d2SAlexander Motin 
297c6b05d2SAlexander Motin /*
307c6b05d2SAlexander Motin  * Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
317c6b05d2SAlexander Motin  */
327c6b05d2SAlexander Motin 
337c6b05d2SAlexander Motin #ifdef HAVE_KERNEL_OPTION_HEADERS
347c6b05d2SAlexander Motin #include "opt_snd.h"
357c6b05d2SAlexander Motin #endif
367c6b05d2SAlexander Motin 
377c6b05d2SAlexander Motin #include <dev/sound/pcm/sound.h>
387c6b05d2SAlexander Motin 
397c6b05d2SAlexander Motin #include <sys/ctype.h>
407c6b05d2SAlexander Motin 
417c6b05d2SAlexander Motin #include <dev/sound/pci/hda/hdac.h>
427c6b05d2SAlexander Motin #include <dev/sound/pci/hda/hdaa.h>
437c6b05d2SAlexander Motin #include <dev/sound/pci/hda/hda_reg.h>
447c6b05d2SAlexander Motin 
457c6b05d2SAlexander Motin SND_DECLARE_FILE("$FreeBSD$");
467c6b05d2SAlexander Motin 
477c6b05d2SAlexander Motin static const struct {
487c6b05d2SAlexander Motin 	uint32_t model;
497c6b05d2SAlexander Motin 	uint32_t id;
507c6b05d2SAlexander Motin 	uint32_t set, unset;
517c6b05d2SAlexander Motin 	uint32_t gpio;
527c6b05d2SAlexander Motin } hdac_quirks[] = {
537c6b05d2SAlexander Motin 	/*
547c6b05d2SAlexander Motin 	 * XXX Force stereo quirk. Monoural recording / playback
557c6b05d2SAlexander Motin 	 *     on few codecs (especially ALC880) seems broken or
567c6b05d2SAlexander Motin 	 *     perhaps unsupported.
577c6b05d2SAlexander Motin 	 */
587c6b05d2SAlexander Motin 	{ HDA_MATCH_ALL, HDA_MATCH_ALL,
597c6b05d2SAlexander Motin 	    HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
607c6b05d2SAlexander Motin 	    0 },
617c6b05d2SAlexander Motin 	{ ACER_ALL_SUBVENDOR, HDA_MATCH_ALL,
627c6b05d2SAlexander Motin 	    0, 0,
637c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
647c6b05d2SAlexander Motin 	{ ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660,
657c6b05d2SAlexander Motin 	    0, 0,
667c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
677c6b05d2SAlexander Motin 	{ ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880,
687c6b05d2SAlexander Motin 	    0, 0,
697c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
707c6b05d2SAlexander Motin 	{ ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880,
717c6b05d2SAlexander Motin 	    0, 0,
727c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
737c6b05d2SAlexander Motin 	{ ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882,
747c6b05d2SAlexander Motin 	    0, 0,
757c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
767c6b05d2SAlexander Motin 	{ ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882,
777c6b05d2SAlexander Motin 	    0, 0,
787c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
797c6b05d2SAlexander Motin 	{ ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A,
807c6b05d2SAlexander Motin 	    HDAA_QUIRK_EAPDINV, 0,
817c6b05d2SAlexander Motin 	    0 },
827c6b05d2SAlexander Motin 	{ ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A,
837c6b05d2SAlexander Motin 	    HDAA_QUIRK_EAPDINV, 0,
847c6b05d2SAlexander Motin 	    0 },
857c6b05d2SAlexander Motin 	{ ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861,
867c6b05d2SAlexander Motin 	    HDAA_QUIRK_OVREF, 0,
877c6b05d2SAlexander Motin 	    0 },
887c6b05d2SAlexander Motin 	{ UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861,
897c6b05d2SAlexander Motin 	    HDAA_QUIRK_OVREF, 0,
907c6b05d2SAlexander Motin 	    0 },
917c6b05d2SAlexander Motin 	/*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988,
927c6b05d2SAlexander Motin 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
937c6b05d2SAlexander Motin 	    0 },*/
947c6b05d2SAlexander Motin 	{ MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880,
957c6b05d2SAlexander Motin 	    0, 0,
967c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(1) },
977c6b05d2SAlexander Motin 	{ LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A,
987c6b05d2SAlexander Motin 	    HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
997c6b05d2SAlexander Motin 	    0 },
1007c6b05d2SAlexander Motin 	{ SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A,
1017c6b05d2SAlexander Motin 	    HDAA_QUIRK_EAPDINV, 0,
1027c6b05d2SAlexander Motin 	    0 },
1037c6b05d2SAlexander Motin 	{ APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885,
1047c6b05d2SAlexander Motin 	    HDAA_QUIRK_OVREF50, 0,
1057c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
1067c6b05d2SAlexander Motin 	{ APPLE_INTEL_MAC, HDA_CODEC_STAC9221,
1077c6b05d2SAlexander Motin 	    0, 0,
1087c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
1097c6b05d2SAlexander Motin 	{ APPLE_MACBOOKPRO55, HDA_CODEC_CS4206,
1107c6b05d2SAlexander Motin 	    0, 0,
1117c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
1127c6b05d2SAlexander Motin 	{ DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X,
1137c6b05d2SAlexander Motin 	    0, 0,
1147c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
1157c6b05d2SAlexander Motin 	{ DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X,
1167c6b05d2SAlexander Motin 	    0, 0,
1177c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(2) },
1187c6b05d2SAlexander Motin 	{ DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X,
1197c6b05d2SAlexander Motin 	    0, 0,
1207c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
1217c6b05d2SAlexander Motin 	{ HDA_MATCH_ALL, HDA_CODEC_AD1988,
1227c6b05d2SAlexander Motin 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
1237c6b05d2SAlexander Motin 	    0 },
1247c6b05d2SAlexander Motin 	{ HDA_MATCH_ALL, HDA_CODEC_AD1988B,
1257c6b05d2SAlexander Motin 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
1267c6b05d2SAlexander Motin 	    0 },
1277c6b05d2SAlexander Motin 	{ HDA_MATCH_ALL, HDA_CODEC_CX20549,
1287c6b05d2SAlexander Motin 	    0, HDAA_QUIRK_FORCESTEREO,
1297c6b05d2SAlexander Motin 	    0 }
1307c6b05d2SAlexander Motin };
1317c6b05d2SAlexander Motin #define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0]))
1327c6b05d2SAlexander Motin 
1337c6b05d2SAlexander Motin static void
1347c6b05d2SAlexander Motin hdac_pin_patch(struct hdaa_widget *w)
1357c6b05d2SAlexander Motin {
1367c6b05d2SAlexander Motin 	const char *patch = NULL;
1377c6b05d2SAlexander Motin 	uint32_t config, orig, id, subid;
1387c6b05d2SAlexander Motin 	nid_t nid = w->nid;
1397c6b05d2SAlexander Motin 
1407c6b05d2SAlexander Motin 	config = orig = w->wclass.pin.config;
1417c6b05d2SAlexander Motin 	id = hdaa_codec_id(w->devinfo);
1427c6b05d2SAlexander Motin 	subid = hdaa_subvendor_id(w->devinfo);
1437c6b05d2SAlexander Motin 
1447c6b05d2SAlexander Motin 	/* XXX: Old patches require complete review.
1457c6b05d2SAlexander Motin 	 * Now they may create more problem then solve due to
1467c6b05d2SAlexander Motin 	 * incorrect associations.
1477c6b05d2SAlexander Motin 	 */
1487c6b05d2SAlexander Motin 	if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) {
1497c6b05d2SAlexander Motin 		switch (nid) {
1507c6b05d2SAlexander Motin 		case 26:
1517c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
1527c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
1537c6b05d2SAlexander Motin 			break;
1547c6b05d2SAlexander Motin 		case 27:
1557c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
1567c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT;
1577c6b05d2SAlexander Motin 			break;
1587c6b05d2SAlexander Motin 		default:
1597c6b05d2SAlexander Motin 			break;
1607c6b05d2SAlexander Motin 		}
1617c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_ALC880 &&
1627c6b05d2SAlexander Motin 	    (subid == CLEVO_D900T_SUBVENDOR ||
1637c6b05d2SAlexander Motin 	    subid == ASUS_M5200_SUBVENDOR)) {
1647c6b05d2SAlexander Motin 		/*
1657c6b05d2SAlexander Motin 		 * Super broken BIOS
1667c6b05d2SAlexander Motin 		 */
1677c6b05d2SAlexander Motin 		switch (nid) {
1687c6b05d2SAlexander Motin 		case 24:	/* MIC1 */
1697c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
1707c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
1717c6b05d2SAlexander Motin 			break;
1727c6b05d2SAlexander Motin 		case 25:	/* XXX MIC2 */
1737c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
1747c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
1757c6b05d2SAlexander Motin 			break;
1767c6b05d2SAlexander Motin 		case 26:	/* LINE1 */
1777c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
1787c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
1797c6b05d2SAlexander Motin 			break;
1807c6b05d2SAlexander Motin 		case 27:	/* XXX LINE2 */
1817c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
1827c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
1837c6b05d2SAlexander Motin 			break;
1847c6b05d2SAlexander Motin 		case 28:	/* CD */
1857c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
1867c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD;
1877c6b05d2SAlexander Motin 			break;
1887c6b05d2SAlexander Motin 		}
1897c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_ALC883 &&
1907c6b05d2SAlexander Motin 	    (subid == MSI_MS034A_SUBVENDOR ||
1917c6b05d2SAlexander Motin 	    HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) {
1927c6b05d2SAlexander Motin 		switch (nid) {
1937c6b05d2SAlexander Motin 		case 25:
1947c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
1957c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
1967c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
1977c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
1987c6b05d2SAlexander Motin 			break;
1997c6b05d2SAlexander Motin 		case 28:
2007c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
2017c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
2027c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
2037c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
2047c6b05d2SAlexander Motin 			break;
2057c6b05d2SAlexander Motin 		}
2067c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_CX20549 && subid ==
2077c6b05d2SAlexander Motin 	    HP_V3000_SUBVENDOR) {
2087c6b05d2SAlexander Motin 		switch (nid) {
2097c6b05d2SAlexander Motin 		case 18:
2107c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
2117c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
2127c6b05d2SAlexander Motin 			break;
2137c6b05d2SAlexander Motin 		case 20:
2147c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
2157c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
2167c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
2177c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
2187c6b05d2SAlexander Motin 			break;
2197c6b05d2SAlexander Motin 		case 21:
2207c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
2217c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
2227c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
2237c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
2247c6b05d2SAlexander Motin 			break;
2257c6b05d2SAlexander Motin 		}
2267c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_CX20551 && subid ==
2277c6b05d2SAlexander Motin 	    HP_DV5000_SUBVENDOR) {
2287c6b05d2SAlexander Motin 		switch (nid) {
2297c6b05d2SAlexander Motin 		case 20:
2307c6b05d2SAlexander Motin 		case 21:
2317c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
2327c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
2337c6b05d2SAlexander Motin 			break;
2347c6b05d2SAlexander Motin 		}
2357c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_ALC861 && subid ==
2367c6b05d2SAlexander Motin 	    ASUS_W6F_SUBVENDOR) {
2377c6b05d2SAlexander Motin 		switch (nid) {
2387c6b05d2SAlexander Motin 		case 11:
2397c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
2407c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
2417c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
2427c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
2437c6b05d2SAlexander Motin 			break;
2447c6b05d2SAlexander Motin 		case 12:
2457c6b05d2SAlexander Motin 		case 14:
2467c6b05d2SAlexander Motin 		case 16:
2477c6b05d2SAlexander Motin 		case 31:
2487c6b05d2SAlexander Motin 		case 32:
2497c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
2507c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
2517c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
2527c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
2537c6b05d2SAlexander Motin 			break;
2547c6b05d2SAlexander Motin 		case 15:
2557c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
2567c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
2577c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
2587c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
2597c6b05d2SAlexander Motin 			break;
2607c6b05d2SAlexander Motin 		}
2617c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_ALC861 && subid ==
2627c6b05d2SAlexander Motin 	    UNIWILL_9075_SUBVENDOR) {
2637c6b05d2SAlexander Motin 		switch (nid) {
2647c6b05d2SAlexander Motin 		case 15:
2657c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
2667c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
2677c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
2687c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
2697c6b05d2SAlexander Motin 			break;
2707c6b05d2SAlexander Motin 		}
2717c6b05d2SAlexander Motin 	}
2727c6b05d2SAlexander Motin 
2737c6b05d2SAlexander Motin 	/* New patches */
2747c6b05d2SAlexander Motin 	if (id == HDA_CODEC_AD1986A &&
2757c6b05d2SAlexander Motin 	    (subid == ASUS_M2NPVMX_SUBVENDOR ||
2767c6b05d2SAlexander Motin 	    subid == ASUS_A8NVMCSM_SUBVENDOR ||
2777c6b05d2SAlexander Motin 	    subid == ASUS_P5PL2_SUBVENDOR)) {
2787c6b05d2SAlexander Motin 		switch (nid) {
2797c6b05d2SAlexander Motin 		case 26: /* Headphones with redirection */
2807c6b05d2SAlexander Motin 			patch = "as=1 seq=15";
2817c6b05d2SAlexander Motin 			break;
2827c6b05d2SAlexander Motin 		case 28: /* 5.1 out => 2.0 out + 1 input */
2837c6b05d2SAlexander Motin 			patch = "device=Line-in as=8 seq=1";
2847c6b05d2SAlexander Motin 			break;
2857c6b05d2SAlexander Motin 		case 29: /* Can't use this as input, as the only available mic
2867c6b05d2SAlexander Motin 			  * preamplifier is busy by front panel mic (nid 31).
2877c6b05d2SAlexander Motin 			  * If you want to use this rear connector as mic input,
2887c6b05d2SAlexander Motin 			  * you have to disable the front panel one. */
2897c6b05d2SAlexander Motin 			patch = "as=0";
2907c6b05d2SAlexander Motin 			break;
2917c6b05d2SAlexander Motin 		case 31: /* Lot of inputs configured with as=15 and unusable */
2927c6b05d2SAlexander Motin 			patch = "as=8 seq=3";
2937c6b05d2SAlexander Motin 			break;
2947c6b05d2SAlexander Motin 		case 32:
2957c6b05d2SAlexander Motin 			patch = "as=8 seq=4";
2967c6b05d2SAlexander Motin 			break;
2977c6b05d2SAlexander Motin 		case 34:
2987c6b05d2SAlexander Motin 			patch = "as=8 seq=5";
2997c6b05d2SAlexander Motin 			break;
3007c6b05d2SAlexander Motin 		case 36:
3017c6b05d2SAlexander Motin 			patch = "as=8 seq=6";
3027c6b05d2SAlexander Motin 			break;
3037c6b05d2SAlexander Motin 		}
3047c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_ALC260 &&
3057c6b05d2SAlexander Motin 	    HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
3067c6b05d2SAlexander Motin 		switch (nid) {
3077c6b05d2SAlexander Motin 		case 16:
3087c6b05d2SAlexander Motin 			patch = "seq=15 device=Headphones";
3097c6b05d2SAlexander Motin 			break;
3107c6b05d2SAlexander Motin 		}
3117c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_ALC268) {
3127c6b05d2SAlexander Motin 	    if (subid == ACER_T5320_SUBVENDOR) {
3137c6b05d2SAlexander Motin 		switch (nid) {
3147c6b05d2SAlexander Motin 		case 20: /* Headphones Jack */
3157c6b05d2SAlexander Motin 			patch = "as=1 seq=15";
3167c6b05d2SAlexander Motin 			break;
3177c6b05d2SAlexander Motin 		}
3187c6b05d2SAlexander Motin 	    }
3197c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_CX20561 &&
3207c6b05d2SAlexander Motin 	    subid == LENOVO_B450_SUBVENDOR) {
3217c6b05d2SAlexander Motin 		switch (nid) {
3227c6b05d2SAlexander Motin 		case 22:
3237c6b05d2SAlexander Motin 			patch = "as=1 seq=15";
3247c6b05d2SAlexander Motin 			break;
3257c6b05d2SAlexander Motin 		}
3267c6b05d2SAlexander Motin 	}
3277c6b05d2SAlexander Motin 
3287c6b05d2SAlexander Motin 	if (patch != NULL)
3297c6b05d2SAlexander Motin 		config = hdaa_widget_pin_patch(config, patch);
3307c6b05d2SAlexander Motin 	HDA_BOOTVERBOSE(
3317c6b05d2SAlexander Motin 		if (config != orig)
3327c6b05d2SAlexander Motin 			device_printf(w->devinfo->dev,
3337c6b05d2SAlexander Motin 			    "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
3347c6b05d2SAlexander Motin 			    nid, orig, config);
3357c6b05d2SAlexander Motin 	);
3367c6b05d2SAlexander Motin 	w->wclass.pin.config = config;
3377c6b05d2SAlexander Motin }
3387c6b05d2SAlexander Motin 
3397c6b05d2SAlexander Motin static void
3407c6b05d2SAlexander Motin hdaa_widget_patch(struct hdaa_widget *w)
3417c6b05d2SAlexander Motin {
3427c6b05d2SAlexander Motin 	struct hdaa_devinfo *devinfo = w->devinfo;
3437c6b05d2SAlexander Motin 	uint32_t orig;
3447c6b05d2SAlexander Motin 	nid_t beeper = -1;
3457c6b05d2SAlexander Motin 
3467c6b05d2SAlexander Motin 	orig = w->param.widget_cap;
3477c6b05d2SAlexander Motin 	/* On some codecs beeper is an input pin, but it is not recordable
3487c6b05d2SAlexander Motin 	   alone. Also most of BIOSes does not declare beeper pin.
3497c6b05d2SAlexander Motin 	   Change beeper pin node type to beeper to help parser. */
3507c6b05d2SAlexander Motin 	switch (hdaa_codec_id(devinfo)) {
3517c6b05d2SAlexander Motin 	case HDA_CODEC_AD1882:
3527c6b05d2SAlexander Motin 	case HDA_CODEC_AD1883:
3537c6b05d2SAlexander Motin 	case HDA_CODEC_AD1984:
3547c6b05d2SAlexander Motin 	case HDA_CODEC_AD1984A:
3557c6b05d2SAlexander Motin 	case HDA_CODEC_AD1984B:
3567c6b05d2SAlexander Motin 	case HDA_CODEC_AD1987:
3577c6b05d2SAlexander Motin 	case HDA_CODEC_AD1988:
3587c6b05d2SAlexander Motin 	case HDA_CODEC_AD1988B:
3597c6b05d2SAlexander Motin 	case HDA_CODEC_AD1989B:
3607c6b05d2SAlexander Motin 		beeper = 26;
3617c6b05d2SAlexander Motin 		break;
3627c6b05d2SAlexander Motin 	case HDA_CODEC_ALC260:
3637c6b05d2SAlexander Motin 		beeper = 23;
3647c6b05d2SAlexander Motin 		break;
3657c6b05d2SAlexander Motin 	}
3667c6b05d2SAlexander Motin 	if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
3677c6b05d2SAlexander Motin 	    hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
3687c6b05d2SAlexander Motin 		beeper = 29;
3697c6b05d2SAlexander Motin 	if (w->nid == beeper) {
3707c6b05d2SAlexander Motin 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
3717c6b05d2SAlexander Motin 		w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
3727c6b05d2SAlexander Motin 		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
3737c6b05d2SAlexander Motin 		w->waspin = 1;
3747c6b05d2SAlexander Motin 	}
3757c6b05d2SAlexander Motin 	HDA_BOOTVERBOSE(
3767c6b05d2SAlexander Motin 		if (w->param.widget_cap != orig) {
3777c6b05d2SAlexander Motin 			device_printf(w->devinfo->dev,
3787c6b05d2SAlexander Motin 			    "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
3797c6b05d2SAlexander Motin 			    w->nid, orig, w->param.widget_cap);
3807c6b05d2SAlexander Motin 		}
3817c6b05d2SAlexander Motin 	);
3827c6b05d2SAlexander Motin 
3837c6b05d2SAlexander Motin 	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
3847c6b05d2SAlexander Motin 		hdac_pin_patch(w);
3857c6b05d2SAlexander Motin }
3867c6b05d2SAlexander Motin 
3877c6b05d2SAlexander Motin void
3887c6b05d2SAlexander Motin hdaa_patch(struct hdaa_devinfo *devinfo)
3897c6b05d2SAlexander Motin {
3907c6b05d2SAlexander Motin 	struct hdaa_widget *w;
3917c6b05d2SAlexander Motin 	uint32_t id, subid;
3927c6b05d2SAlexander Motin 	int i;
3937c6b05d2SAlexander Motin 
3947c6b05d2SAlexander Motin 	id = hdaa_codec_id(devinfo);
3957c6b05d2SAlexander Motin 	subid = hdaa_subvendor_id(devinfo);
3967c6b05d2SAlexander Motin 
3977c6b05d2SAlexander Motin 	/*
3987c6b05d2SAlexander Motin 	 * Quirks
3997c6b05d2SAlexander Motin 	 */
4007c6b05d2SAlexander Motin 	for (i = 0; i < HDAC_QUIRKS_LEN; i++) {
4017c6b05d2SAlexander Motin 		if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
4027c6b05d2SAlexander Motin 		    HDA_DEV_MATCH(hdac_quirks[i].id, id)))
4037c6b05d2SAlexander Motin 			continue;
4047c6b05d2SAlexander Motin 		if (hdac_quirks[i].set != 0)
4057c6b05d2SAlexander Motin 			devinfo->quirks |=
4067c6b05d2SAlexander Motin 			    hdac_quirks[i].set;
4077c6b05d2SAlexander Motin 		if (hdac_quirks[i].unset != 0)
4087c6b05d2SAlexander Motin 			devinfo->quirks &=
4097c6b05d2SAlexander Motin 			    ~(hdac_quirks[i].unset);
4107c6b05d2SAlexander Motin 	}
4117c6b05d2SAlexander Motin 
4127c6b05d2SAlexander Motin 	/* Apply per-widget patch. */
4137c6b05d2SAlexander Motin 	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
4147c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, i);
4157c6b05d2SAlexander Motin 		if (w == NULL)
4167c6b05d2SAlexander Motin 			continue;
4177c6b05d2SAlexander Motin 		hdaa_widget_patch(w);
4187c6b05d2SAlexander Motin 	}
4197c6b05d2SAlexander Motin 
4207c6b05d2SAlexander Motin 	switch (id) {
4217c6b05d2SAlexander Motin 	case HDA_CODEC_AD1983:
4227c6b05d2SAlexander Motin 		/*
4237c6b05d2SAlexander Motin 		 * This CODEC has several possible usages, but none
4247c6b05d2SAlexander Motin 		 * fit the parser best. Help parser to choose better.
4257c6b05d2SAlexander Motin 		 */
4267c6b05d2SAlexander Motin 		/* Disable direct unmixed playback to get pcm volume. */
4277c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 5);
4287c6b05d2SAlexander Motin 		if (w != NULL)
4297c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
4307c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 6);
4317c6b05d2SAlexander Motin 		if (w != NULL)
4327c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
4337c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 11);
4347c6b05d2SAlexander Motin 		if (w != NULL)
4357c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
4367c6b05d2SAlexander Motin 		/* Disable mic and line selectors. */
4377c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 12);
4387c6b05d2SAlexander Motin 		if (w != NULL)
4397c6b05d2SAlexander Motin 			w->connsenable[1] = 0;
4407c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 13);
4417c6b05d2SAlexander Motin 		if (w != NULL)
4427c6b05d2SAlexander Motin 			w->connsenable[1] = 0;
4437c6b05d2SAlexander Motin 		/* Disable recording from mono playback mix. */
4447c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 20);
4457c6b05d2SAlexander Motin 		if (w != NULL)
4467c6b05d2SAlexander Motin 			w->connsenable[3] = 0;
4477c6b05d2SAlexander Motin 		break;
4487c6b05d2SAlexander Motin 	case HDA_CODEC_AD1986A:
4497c6b05d2SAlexander Motin 		/*
4507c6b05d2SAlexander Motin 		 * This CODEC has overcomplicated input mixing.
4517c6b05d2SAlexander Motin 		 * Make some cleaning there.
4527c6b05d2SAlexander Motin 		 */
4537c6b05d2SAlexander Motin 		/* Disable input mono mixer. Not needed and not supported. */
4547c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 43);
4557c6b05d2SAlexander Motin 		if (w != NULL)
4567c6b05d2SAlexander Motin 			w->enable = 0;
4577c6b05d2SAlexander Motin 		/* Disable any with any input mixing mesh. Use separately. */
4587c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 39);
4597c6b05d2SAlexander Motin 		if (w != NULL)
4607c6b05d2SAlexander Motin 			w->enable = 0;
4617c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 40);
4627c6b05d2SAlexander Motin 		if (w != NULL)
4637c6b05d2SAlexander Motin 			w->enable = 0;
4647c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 41);
4657c6b05d2SAlexander Motin 		if (w != NULL)
4667c6b05d2SAlexander Motin 			w->enable = 0;
4677c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 42);
4687c6b05d2SAlexander Motin 		if (w != NULL)
4697c6b05d2SAlexander Motin 			w->enable = 0;
4707c6b05d2SAlexander Motin 		/* Disable duplicate mixer node connector. */
4717c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 15);
4727c6b05d2SAlexander Motin 		if (w != NULL)
4737c6b05d2SAlexander Motin 			w->connsenable[3] = 0;
4747c6b05d2SAlexander Motin 		/* There is only one mic preamplifier, use it effectively. */
4757c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 31);
4767c6b05d2SAlexander Motin 		if (w != NULL) {
4777c6b05d2SAlexander Motin 			if ((w->wclass.pin.config &
4787c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
4797c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
4807c6b05d2SAlexander Motin 				w = hdaa_widget_get(devinfo, 16);
4817c6b05d2SAlexander Motin 				if (w != NULL)
4827c6b05d2SAlexander Motin 				    w->connsenable[2] = 0;
4837c6b05d2SAlexander Motin 			} else {
4847c6b05d2SAlexander Motin 				w = hdaa_widget_get(devinfo, 15);
4857c6b05d2SAlexander Motin 				if (w != NULL)
4867c6b05d2SAlexander Motin 				    w->connsenable[0] = 0;
4877c6b05d2SAlexander Motin 			}
4887c6b05d2SAlexander Motin 		}
4897c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 32);
4907c6b05d2SAlexander Motin 		if (w != NULL) {
4917c6b05d2SAlexander Motin 			if ((w->wclass.pin.config &
4927c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
4937c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
4947c6b05d2SAlexander Motin 				w = hdaa_widget_get(devinfo, 16);
4957c6b05d2SAlexander Motin 				if (w != NULL)
4967c6b05d2SAlexander Motin 				    w->connsenable[0] = 0;
4977c6b05d2SAlexander Motin 			} else {
4987c6b05d2SAlexander Motin 				w = hdaa_widget_get(devinfo, 15);
4997c6b05d2SAlexander Motin 				if (w != NULL)
5007c6b05d2SAlexander Motin 				    w->connsenable[1] = 0;
5017c6b05d2SAlexander Motin 			}
5027c6b05d2SAlexander Motin 		}
5037c6b05d2SAlexander Motin 
5047c6b05d2SAlexander Motin 		if (subid == ASUS_A8X_SUBVENDOR) {
5057c6b05d2SAlexander Motin 			/*
5067c6b05d2SAlexander Motin 			 * This is just plain ridiculous.. There
5077c6b05d2SAlexander Motin 			 * are several A8 series that share the same
5087c6b05d2SAlexander Motin 			 * pci id but works differently (EAPD).
5097c6b05d2SAlexander Motin 			 */
5107c6b05d2SAlexander Motin 			w = hdaa_widget_get(devinfo, 26);
5117c6b05d2SAlexander Motin 			if (w != NULL && w->type ==
5127c6b05d2SAlexander Motin 			    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
5137c6b05d2SAlexander Motin 			    (w->wclass.pin.config &
5147c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
5157c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
5167c6b05d2SAlexander Motin 				devinfo->quirks &=
5177c6b05d2SAlexander Motin 				    ~HDAA_QUIRK_EAPDINV;
5187c6b05d2SAlexander Motin 		}
5197c6b05d2SAlexander Motin 		break;
5207c6b05d2SAlexander Motin 	case HDA_CODEC_AD1981HD:
5217c6b05d2SAlexander Motin 		/*
5227c6b05d2SAlexander Motin 		 * This CODEC has very unusual design with several
5237c6b05d2SAlexander Motin 		 * points inappropriate for the present parser.
5247c6b05d2SAlexander Motin 		 */
5257c6b05d2SAlexander Motin 		/* Disable recording from mono playback mix. */
5267c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 21);
5277c6b05d2SAlexander Motin 		if (w != NULL)
5287c6b05d2SAlexander Motin 			w->connsenable[3] = 0;
5297c6b05d2SAlexander Motin 		/* Disable rear to front mic mixer, use separately. */
5307c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 31);
5317c6b05d2SAlexander Motin 		if (w != NULL)
5327c6b05d2SAlexander Motin 			w->enable = 0;
5337c6b05d2SAlexander Motin 		/* Disable direct playback, use mixer. */
5347c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 5);
5357c6b05d2SAlexander Motin 		if (w != NULL)
5367c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
5377c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 6);
5387c6b05d2SAlexander Motin 		if (w != NULL)
5397c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
5407c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 9);
5417c6b05d2SAlexander Motin 		if (w != NULL)
5427c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
5437c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 24);
5447c6b05d2SAlexander Motin 		if (w != NULL)
5457c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
5467c6b05d2SAlexander Motin 		break;
5477c6b05d2SAlexander Motin 	case HDA_CODEC_CX20582:
5487c6b05d2SAlexander Motin 	case HDA_CODEC_CX20583:
5497c6b05d2SAlexander Motin 	case HDA_CODEC_CX20584:
5507c6b05d2SAlexander Motin 	case HDA_CODEC_CX20585:
5517c6b05d2SAlexander Motin 	case HDA_CODEC_CX20590:
5527c6b05d2SAlexander Motin 		/*
5537c6b05d2SAlexander Motin 		 * These codecs have extra connectivity on record side
5547c6b05d2SAlexander Motin 		 * too reach for the present parser.
5557c6b05d2SAlexander Motin 		 */
5567c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 20);
5577c6b05d2SAlexander Motin 		if (w != NULL)
5587c6b05d2SAlexander Motin 			w->connsenable[1] = 0;
5597c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 21);
5607c6b05d2SAlexander Motin 		if (w != NULL)
5617c6b05d2SAlexander Motin 			w->connsenable[1] = 0;
5627c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 22);
5637c6b05d2SAlexander Motin 		if (w != NULL)
5647c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
5657c6b05d2SAlexander Motin 		break;
5667c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_0:
5677c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_1:
5687c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_2:
5697c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_3:
5707c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_4:
5717c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_5:
5727c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_6:
5737c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_7:
5747c6b05d2SAlexander Motin 		/*
5757c6b05d2SAlexander Motin 		 * These codecs have hidden mic boost controls.
5767c6b05d2SAlexander Motin 		 */
5777c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 26);
5787c6b05d2SAlexander Motin 		if (w != NULL)
5797c6b05d2SAlexander Motin 			w->param.inamp_cap =
5807c6b05d2SAlexander Motin 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
5817c6b05d2SAlexander Motin 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
5827c6b05d2SAlexander Motin 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
5837c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 30);
5847c6b05d2SAlexander Motin 		if (w != NULL)
5857c6b05d2SAlexander Motin 			w->param.inamp_cap =
5867c6b05d2SAlexander Motin 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
5877c6b05d2SAlexander Motin 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
5887c6b05d2SAlexander Motin 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
5897c6b05d2SAlexander Motin 		break;
5907c6b05d2SAlexander Motin 	}
5917c6b05d2SAlexander Motin }
5927c6b05d2SAlexander Motin 
5937c6b05d2SAlexander Motin void
5947c6b05d2SAlexander Motin hdaa_patch_direct(struct hdaa_devinfo *devinfo)
5957c6b05d2SAlexander Motin {
5967c6b05d2SAlexander Motin 	device_t dev = devinfo->dev;
5977c6b05d2SAlexander Motin 	uint32_t id, subid, val;
5987c6b05d2SAlexander Motin 
5997c6b05d2SAlexander Motin 	id = hdaa_codec_id(devinfo);
6007c6b05d2SAlexander Motin 	subid = hdaa_subvendor_id(devinfo);
6017c6b05d2SAlexander Motin 
6027c6b05d2SAlexander Motin 	switch (id) {
6037c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_0:
6047c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_1:
6057c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_2:
6067c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_3:
6077c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_4:
6087c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_5:
6097c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_6:
6107c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_7:
6117c6b05d2SAlexander Motin 		/* Enable Mic Boost Volume controls. */
6127c6b05d2SAlexander Motin 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
6137c6b05d2SAlexander Motin 		    0xf98, 0x01));
6147c6b05d2SAlexander Motin 		/* Don't bypass mixer. */
6157c6b05d2SAlexander Motin 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
6167c6b05d2SAlexander Motin 		    0xf88, 0xc0));
6177c6b05d2SAlexander Motin 		break;
6187c6b05d2SAlexander Motin 	}
6197c6b05d2SAlexander Motin 	if (subid == APPLE_INTEL_MAC)
6207c6b05d2SAlexander Motin 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
6217c6b05d2SAlexander Motin 		    0x7e7, 0));
6227c6b05d2SAlexander Motin 	if (id == HDA_CODEC_ALC269) {
623*89a8feddSAlexander Motin 		if (subid == 0x16e31043 || subid == 0x831a1043 ||
624*89a8feddSAlexander Motin 		    subid == 0x834a1043 || subid == 0x83981043 ||
625*89a8feddSAlexander Motin 		    subid == 0x83ce1043) {
6267c6b05d2SAlexander Motin 			/*
6277c6b05d2SAlexander Motin 			 * The ditital mics on some Asus laptops produce
6287c6b05d2SAlexander Motin 			 * differential signals instead of expected stereo.
6297c6b05d2SAlexander Motin 			 * That results in silence if downmix it to mono.
6307c6b05d2SAlexander Motin 			 * To workaround, make codec to handle signal as mono.
6317c6b05d2SAlexander Motin 			 */
6327c6b05d2SAlexander Motin 			hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
6337c6b05d2SAlexander Motin 			val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20));
6347c6b05d2SAlexander Motin 			hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
6357c6b05d2SAlexander Motin 			hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80));
6367c6b05d2SAlexander Motin 		}
6377c6b05d2SAlexander Motin 	}
6387c6b05d2SAlexander Motin }
639