xref: /freebsd/sys/dev/sound/pci/hda/hdaa_patches.c (revision 93ad59a251897431627345c287390ae134925a95)
17c6b05d2SAlexander Motin /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
47c6b05d2SAlexander Motin  * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
57c6b05d2SAlexander Motin  * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
67c6b05d2SAlexander Motin  * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
77c6b05d2SAlexander Motin  * All rights reserved.
87c6b05d2SAlexander Motin  *
97c6b05d2SAlexander Motin  * Redistribution and use in source and binary forms, with or without
107c6b05d2SAlexander Motin  * modification, are permitted provided that the following conditions
117c6b05d2SAlexander Motin  * are met:
127c6b05d2SAlexander Motin  * 1. Redistributions of source code must retain the above copyright
137c6b05d2SAlexander Motin  *    notice, this list of conditions and the following disclaimer.
147c6b05d2SAlexander Motin  * 2. Redistributions in binary form must reproduce the above copyright
157c6b05d2SAlexander Motin  *    notice, this list of conditions and the following disclaimer in the
167c6b05d2SAlexander Motin  *    documentation and/or other materials provided with the distribution.
177c6b05d2SAlexander Motin  *
187c6b05d2SAlexander Motin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
197c6b05d2SAlexander Motin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
207c6b05d2SAlexander Motin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
217c6b05d2SAlexander Motin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
227c6b05d2SAlexander Motin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
237c6b05d2SAlexander Motin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
247c6b05d2SAlexander Motin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
257c6b05d2SAlexander Motin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
267c6b05d2SAlexander Motin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
277c6b05d2SAlexander Motin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
287c6b05d2SAlexander Motin  * SUCH DAMAGE.
297c6b05d2SAlexander Motin  */
307c6b05d2SAlexander Motin 
317c6b05d2SAlexander Motin /*
327c6b05d2SAlexander Motin  * Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
337c6b05d2SAlexander Motin  */
347c6b05d2SAlexander Motin 
357c6b05d2SAlexander Motin #ifdef HAVE_KERNEL_OPTION_HEADERS
367c6b05d2SAlexander Motin #include "opt_snd.h"
377c6b05d2SAlexander Motin #endif
387c6b05d2SAlexander Motin 
397c6b05d2SAlexander Motin #include <dev/sound/pcm/sound.h>
407c6b05d2SAlexander Motin 
417c6b05d2SAlexander Motin #include <sys/ctype.h>
427c6b05d2SAlexander Motin 
437c6b05d2SAlexander Motin #include <dev/sound/pci/hda/hdac.h>
447c6b05d2SAlexander Motin #include <dev/sound/pci/hda/hdaa.h>
457c6b05d2SAlexander Motin #include <dev/sound/pci/hda/hda_reg.h>
467c6b05d2SAlexander Motin 
47ef790cc7SK Staring #include "pin_patch.h"
48ef790cc7SK Staring #include "pin_patch_realtek.h"
49ef790cc7SK Staring 
507c6b05d2SAlexander Motin static const struct {
517c6b05d2SAlexander Motin 	uint32_t model;
527c6b05d2SAlexander Motin 	uint32_t id;
537019329cSAlexander Motin 	uint32_t subsystemid;
547c6b05d2SAlexander Motin 	uint32_t set, unset;
557c6b05d2SAlexander Motin 	uint32_t gpio;
567c6b05d2SAlexander Motin } hdac_quirks[] = {
577c6b05d2SAlexander Motin 	/*
587c6b05d2SAlexander Motin 	 * XXX Force stereo quirk. Monoural recording / playback
597c6b05d2SAlexander Motin 	 *     on few codecs (especially ALC880) seems broken or
607c6b05d2SAlexander Motin 	 *     perhaps unsupported.
617c6b05d2SAlexander Motin 	 */
627019329cSAlexander Motin 	{ HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_MATCH_ALL,
637c6b05d2SAlexander Motin 	    HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
647c6b05d2SAlexander Motin 	    0 },
657019329cSAlexander Motin 	{ ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, HDA_MATCH_ALL,
667c6b05d2SAlexander Motin 	    0, 0,
677c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
687019329cSAlexander Motin 	{ ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, HDA_MATCH_ALL,
697c6b05d2SAlexander Motin 	    0, 0,
707c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
717019329cSAlexander Motin 	{ ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
727c6b05d2SAlexander Motin 	    0, 0,
737c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
747019329cSAlexander Motin 	{ ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
757c6b05d2SAlexander Motin 	    0, 0,
767c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
777019329cSAlexander Motin 	{ ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
787c6b05d2SAlexander Motin 	    0, 0,
797c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
807019329cSAlexander Motin 	{ ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
817c6b05d2SAlexander Motin 	    0, 0,
827c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
837019329cSAlexander Motin 	{ ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
847c6b05d2SAlexander Motin 	    HDAA_QUIRK_EAPDINV, 0,
857c6b05d2SAlexander Motin 	    0 },
867019329cSAlexander Motin 	{ ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
877c6b05d2SAlexander Motin 	    HDAA_QUIRK_EAPDINV, 0,
887c6b05d2SAlexander Motin 	    0 },
897019329cSAlexander Motin 	{ ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
907c6b05d2SAlexander Motin 	    HDAA_QUIRK_OVREF, 0,
917c6b05d2SAlexander Motin 	    0 },
927019329cSAlexander Motin 	{ UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
937c6b05d2SAlexander Motin 	    HDAA_QUIRK_OVREF, 0,
947c6b05d2SAlexander Motin 	    0 },
957019329cSAlexander Motin 	/*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, HDA_MATCH_ALL,
967c6b05d2SAlexander Motin 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
977c6b05d2SAlexander Motin 	    0 },*/
987019329cSAlexander Motin 	{ MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
997c6b05d2SAlexander Motin 	    0, 0,
1007c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(1) },
1017019329cSAlexander Motin 	{ LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
1027c6b05d2SAlexander Motin 	    HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
1037c6b05d2SAlexander Motin 	    0 },
1047019329cSAlexander Motin 	{ SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
1057c6b05d2SAlexander Motin 	    HDAA_QUIRK_EAPDINV, 0,
1067c6b05d2SAlexander Motin 	    0 },
1077019329cSAlexander Motin 	{ APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDA_MATCH_ALL,
1087c6b05d2SAlexander Motin 	    HDAA_QUIRK_OVREF50, 0,
1097c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
1107019329cSAlexander Motin 	{ APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDA_MATCH_ALL,
1117c6b05d2SAlexander Motin 	    0, 0,
1127c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
1136b97b1b3SHans Petter Selasky 	{ APPLE_MACBOOKAIR31, HDA_CODEC_CS4206, HDA_MATCH_ALL,
1146b97b1b3SHans Petter Selasky 	    0, 0,
1156b97b1b3SHans Petter Selasky 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
1167019329cSAlexander Motin 	{ APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
1177c6b05d2SAlexander Motin 	    0, 0,
1187c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
1196b97b1b3SHans Petter Selasky 	{ APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL,
1206b97b1b3SHans Petter Selasky 	    0, 0,
1216b97b1b3SHans Petter Selasky 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
1226b97b1b3SHans Petter Selasky 	{ HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL,
1236b97b1b3SHans Petter Selasky 	    0, 0,
1246b97b1b3SHans Petter Selasky 	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
1257019329cSAlexander Motin 	{ DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
1267c6b05d2SAlexander Motin 	    0, 0,
1277c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
1287019329cSAlexander Motin 	{ DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
1297c6b05d2SAlexander Motin 	    0, 0,
1307c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(2) },
1317019329cSAlexander Motin 	{ DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
1327c6b05d2SAlexander Motin 	    0, 0,
1337c6b05d2SAlexander Motin 	    HDAA_GPIO_SET(0) },
1347019329cSAlexander Motin 	{ HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
1357c6b05d2SAlexander Motin 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
1367c6b05d2SAlexander Motin 	    0 },
1377019329cSAlexander Motin 	{ HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
1387c6b05d2SAlexander Motin 	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
1397c6b05d2SAlexander Motin 	    0 },
1407019329cSAlexander Motin 	{ HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
1417c6b05d2SAlexander Motin 	    0, HDAA_QUIRK_FORCESTEREO,
1427019329cSAlexander Motin 	    0 },
1437019329cSAlexander Motin 	/* Mac Pro 1,1 requires ovref for proper volume level. */
1447019329cSAlexander Motin 	{ 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
1457019329cSAlexander Motin 	    0, HDAA_QUIRK_OVREF,
1467c6b05d2SAlexander Motin 	    0 }
1477c6b05d2SAlexander Motin };
1487c6b05d2SAlexander Motin 
149ef790cc7SK Staring static struct pin_patch_t *
match_pin_patches(int vendor_id,int vendor_subid)150ef790cc7SK Staring match_pin_patches(int vendor_id, int vendor_subid)
151ef790cc7SK Staring {
152ef790cc7SK Staring 	for (int ci = 0; ci < nitems(realtek_model_pin_patches); ci++) {
153ef790cc7SK Staring 		struct hdaa_model_pin_patch_t *p = &realtek_model_pin_patches[ci];
154ef790cc7SK Staring 		if (vendor_id != p->id)
155ef790cc7SK Staring 			continue;
156ef790cc7SK Staring 		for (struct model_pin_patch_t *pp =  p->patches; pp->models; pp++) {
157ef790cc7SK Staring 			for (struct pin_machine_model_t *model = pp->models; model->id != 0; model++) {
158c43bf3f5SXin LI 				if (HDA_DEV_MATCH(model->id, vendor_subid))
159ef790cc7SK Staring 					return (pp->pin_patches);
160ef790cc7SK Staring 			}
161ef790cc7SK Staring 		}
162ef790cc7SK Staring 	}
163ef790cc7SK Staring 
164ef790cc7SK Staring 	return (0);
165ef790cc7SK Staring }
166ef790cc7SK Staring 
1677c6b05d2SAlexander Motin static void
hdac_pin_patch(struct hdaa_widget * w)1687c6b05d2SAlexander Motin hdac_pin_patch(struct hdaa_widget *w)
1697c6b05d2SAlexander Motin {
170ef790cc7SK Staring 	const char *patch_str = NULL;
1717c6b05d2SAlexander Motin 	uint32_t config, orig, id, subid;
1727c6b05d2SAlexander Motin 	nid_t nid = w->nid;
1737c6b05d2SAlexander Motin 
1747c6b05d2SAlexander Motin 	config = orig = w->wclass.pin.config;
1757c6b05d2SAlexander Motin 	id = hdaa_codec_id(w->devinfo);
176ed228e40SAlexander Motin 	subid = hdaa_card_id(w->devinfo);
1777c6b05d2SAlexander Motin 
178ef790cc7SK Staring 	if (id == HDA_CODEC_ALC883 && HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid)) {
1797c6b05d2SAlexander Motin 		switch (nid) {
1807c6b05d2SAlexander Motin 		case 25:
1817c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
1827c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
1837c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
1847c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
1857c6b05d2SAlexander Motin 			break;
1867c6b05d2SAlexander Motin 		case 28:
1877c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
1887c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
1897c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
1907c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
1917c6b05d2SAlexander Motin 			break;
1927c6b05d2SAlexander Motin 		}
1937c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_CX20549 && subid ==
1947c6b05d2SAlexander Motin 	    HP_V3000_SUBVENDOR) {
1957c6b05d2SAlexander Motin 		switch (nid) {
1967c6b05d2SAlexander Motin 		case 18:
1977c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
1987c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
1997c6b05d2SAlexander Motin 			break;
2007c6b05d2SAlexander Motin 		case 20:
2017c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
2027c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
2037c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
2047c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
2057c6b05d2SAlexander Motin 			break;
2067c6b05d2SAlexander Motin 		case 21:
2077c6b05d2SAlexander Motin 			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
2087c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
2097c6b05d2SAlexander Motin 			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
2107c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
2117c6b05d2SAlexander Motin 			break;
2127c6b05d2SAlexander Motin 		}
2137c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_CX20551 && subid ==
2147c6b05d2SAlexander Motin 	    HP_DV5000_SUBVENDOR) {
2157c6b05d2SAlexander Motin 		switch (nid) {
2167c6b05d2SAlexander Motin 		case 20:
2177c6b05d2SAlexander Motin 		case 21:
2187c6b05d2SAlexander Motin 			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
2197c6b05d2SAlexander Motin 			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
2207c6b05d2SAlexander Motin 			break;
2217c6b05d2SAlexander Motin 		}
2227c6b05d2SAlexander Motin 	}
2237c6b05d2SAlexander Motin 
2247c6b05d2SAlexander Motin 	/* New patches */
225ae84f236SAlexander Motin 	if (id == HDA_CODEC_AD1984A &&
226ae84f236SAlexander Motin 	    subid == LENOVO_X300_SUBVENDOR) {
227ae84f236SAlexander Motin 		switch (nid) {
228ae84f236SAlexander Motin 		case 17: /* Headphones with redirection */
229ef790cc7SK Staring 			patch_str = "as=1 seq=15";
230ae84f236SAlexander Motin 			break;
231ae84f236SAlexander Motin 		case 20: /* Two mics together */
232ef790cc7SK Staring 			patch_str = "as=2 seq=15";
233ae84f236SAlexander Motin 			break;
234ae84f236SAlexander Motin 		}
235ae84f236SAlexander Motin 	} else if (id == HDA_CODEC_AD1986A &&
2367c6b05d2SAlexander Motin 	    (subid == ASUS_M2NPVMX_SUBVENDOR ||
2377c6b05d2SAlexander Motin 	    subid == ASUS_A8NVMCSM_SUBVENDOR ||
2387c6b05d2SAlexander Motin 	    subid == ASUS_P5PL2_SUBVENDOR)) {
2397c6b05d2SAlexander Motin 		switch (nid) {
2407c6b05d2SAlexander Motin 		case 26: /* Headphones with redirection */
241ef790cc7SK Staring 			patch_str = "as=1 seq=15";
2427c6b05d2SAlexander Motin 			break;
2437c6b05d2SAlexander Motin 		case 28: /* 5.1 out => 2.0 out + 1 input */
244ef790cc7SK Staring 			patch_str = "device=Line-in as=8 seq=1";
2457c6b05d2SAlexander Motin 			break;
2467c6b05d2SAlexander Motin 		case 29: /* Can't use this as input, as the only available mic
2477c6b05d2SAlexander Motin 			  * preamplifier is busy by front panel mic (nid 31).
2487c6b05d2SAlexander Motin 			  * If you want to use this rear connector as mic input,
2497c6b05d2SAlexander Motin 			  * you have to disable the front panel one. */
250ef790cc7SK Staring 			patch_str = "as=0";
2517c6b05d2SAlexander Motin 			break;
2527c6b05d2SAlexander Motin 		case 31: /* Lot of inputs configured with as=15 and unusable */
253ef790cc7SK Staring 			patch_str = "as=8 seq=3";
2547c6b05d2SAlexander Motin 			break;
2557c6b05d2SAlexander Motin 		case 32:
256ef790cc7SK Staring 			patch_str = "as=8 seq=4";
2577c6b05d2SAlexander Motin 			break;
2587c6b05d2SAlexander Motin 		case 34:
259ef790cc7SK Staring 			patch_str = "as=8 seq=5";
2607c6b05d2SAlexander Motin 			break;
2617c6b05d2SAlexander Motin 		case 36:
262ef790cc7SK Staring 			patch_str = "as=8 seq=6";
2637c6b05d2SAlexander Motin 			break;
2647c6b05d2SAlexander Motin 		}
2657c6b05d2SAlexander Motin 	} else if (id == HDA_CODEC_CX20561 &&
2667c6b05d2SAlexander Motin 	    subid == LENOVO_B450_SUBVENDOR) {
2677c6b05d2SAlexander Motin 		switch (nid) {
2687c6b05d2SAlexander Motin 		case 22:
269ef790cc7SK Staring 			patch_str = "as=1 seq=15";
2707c6b05d2SAlexander Motin 			break;
2717c6b05d2SAlexander Motin 		}
272dcd85063SAdrian Chadd 	} else if (id == HDA_CODEC_CX20561 &&
273dcd85063SAdrian Chadd 	    subid == LENOVO_T400_SUBVENDOR) {
274dcd85063SAdrian Chadd 		switch (nid) {
275dcd85063SAdrian Chadd 		case 22:
276ef790cc7SK Staring 			patch_str = "as=1 seq=15";
277dcd85063SAdrian Chadd 			break;
278dcd85063SAdrian Chadd 		case 26:
279ef790cc7SK Staring 			patch_str = "as=1 seq=0";
280dcd85063SAdrian Chadd 			break;
281dcd85063SAdrian Chadd 		}
28232ea29e2SAlexander Motin 	} else if (id == HDA_CODEC_CX20590 &&
2832112695cSGleb Smirnoff 	    (subid == LENOVO_X1_SUBVENDOR ||
2842112695cSGleb Smirnoff 	    subid == LENOVO_X220_SUBVENDOR ||
2852112695cSGleb Smirnoff 	    subid == LENOVO_T420_SUBVENDOR ||
28605929f8bSMark Johnston 	    subid == LENOVO_T520_SUBVENDOR ||
28705929f8bSMark Johnston 	    subid == LENOVO_G580_SUBVENDOR)) {
28832ea29e2SAlexander Motin 		switch (nid) {
28932ea29e2SAlexander Motin 		case 25:
290ef790cc7SK Staring 			patch_str = "as=1 seq=15";
29132ea29e2SAlexander Motin 			break;
292156860b2SSean Bruno 		/*
293156860b2SSean Bruno 		 * Group onboard mic and headphone mic
294156860b2SSean Bruno 		 * together.  Fixes onboard mic.
295156860b2SSean Bruno 		 */
296156860b2SSean Bruno 		case 27:
297ef790cc7SK Staring 			patch_str = "as=2 seq=15";
298156860b2SSean Bruno 			break;
299156860b2SSean Bruno 		case 35:
300ef790cc7SK Staring 			patch_str = "as=2";
30149de5ec3SSean Bruno 			break;
30249de5ec3SSean Bruno 		}
3035abe1789SGleb Popov 	} else if (id == HDA_CODEC_ALC235 && subid == ASUS_GL553VE_SUBVENDOR) {
3045abe1789SGleb Popov 		switch (nid) {
3055abe1789SGleb Popov 		case 33:
3065abe1789SGleb Popov 			patch_str = "as=1 seq=15";
3075abe1789SGleb Popov 			break;
3085abe1789SGleb Popov 		}
309d3eca31eSMark Johnston 	} else if (id == HDA_CODEC_ALC256 && (subid == DELL_I7577_SUBVENDOR ||
310d3eca31eSMark Johnston 	    subid == DELL_L7480_SUBVENDOR)) {
311145b1792SMarcelo Araujo 		switch (nid) {
312145b1792SMarcelo Araujo 		case 20:
313ef790cc7SK Staring 			patch_str = "as=1 seq=0";
314145b1792SMarcelo Araujo 			break;
315145b1792SMarcelo Araujo 		case 33:
316ef790cc7SK Staring 			patch_str = "as=1 seq=15";
317145b1792SMarcelo Araujo 			break;
318145b1792SMarcelo Araujo 		}
31945f0e571SPhilippe Michaud-Boudreault 	} else if (id == HDA_CODEC_ALC257 &&
320b44869cbSNuno Teixeira 	    (subid == LENOVO_L5AMD_SUBVENDOR ||
32154cc353fSChristos Margiolis 	    subid == LENOVO_L5INTEL_SUBVENDOR ||
32227895336SChristos Margiolis 	    subid == LENOVO_IDEAPAD3_SUBVENDOR)) {
32345f0e571SPhilippe Michaud-Boudreault 		switch (nid) {
32445f0e571SPhilippe Michaud-Boudreault 		case 20:
32545f0e571SPhilippe Michaud-Boudreault 			patch_str = "as=1 seq=0";
32645f0e571SPhilippe Michaud-Boudreault 			break;
32745f0e571SPhilippe Michaud-Boudreault 		case 33:
32845f0e571SPhilippe Michaud-Boudreault 			patch_str = "as=1 seq=15";
32945f0e571SPhilippe Michaud-Boudreault 			break;
33045f0e571SPhilippe Michaud-Boudreault 		}
33106731139SEd Maste 	} else if (id == HDA_CODEC_IDT92HD95B &&
332d88dc1b0SPavel Timofeev 	    (subid == FRAMEWORK_LAPTOP_0001_SUBVENDOR ||
333d88dc1b0SPavel Timofeev 	    subid == FRAMEWORK_LAPTOP_0002_SUBVENDOR)) {
33406731139SEd Maste 		switch (nid) {
33506731139SEd Maste 		case 10:
33606731139SEd Maste 			patch_str = "as=1 seq=15 color=Black loc=Left";
33706731139SEd Maste 			break;
338d88dc1b0SPavel Timofeev 		case 11:
339d88dc1b0SPavel Timofeev 			patch_str = "as=3 seq=15 color=Black loc=Left";
340d88dc1b0SPavel Timofeev 			break;
34106731139SEd Maste 		}
3425968e477SDmitry Lukhtionov 	} else if (id == HDA_CODEC_ALC230 &&
34327895336SChristos Margiolis 	    subid == LENOVO_IDEAPAD330_SUBVENDOR) {
3445968e477SDmitry Lukhtionov 		switch (nid) {
3455968e477SDmitry Lukhtionov 		case 20:
3465968e477SDmitry Lukhtionov 			patch_str = "as=1 seq=0 device=Speaker";
3475968e477SDmitry Lukhtionov 			break;
3485968e477SDmitry Lukhtionov 		case 33:
3495968e477SDmitry Lukhtionov 			patch_str = "as=1 seq=15 device=Headphones";
3505968e477SDmitry Lukhtionov 			break;
3515968e477SDmitry Lukhtionov 		}
3525968e477SDmitry Lukhtionov 	} else if (id == HDA_CODEC_ALC269 &&
3535968e477SDmitry Lukhtionov 	    subid == LENOVO_X230_SUBVENDOR) {
3545968e477SDmitry Lukhtionov 		switch (nid) {
3555968e477SDmitry Lukhtionov 		case 21:
3565968e477SDmitry Lukhtionov 			patch_str = "as=1 seq=15";
3575968e477SDmitry Lukhtionov 			break;
3585968e477SDmitry Lukhtionov 		case 24:
3595968e477SDmitry Lukhtionov 			patch_str = "as=4 seq=15";
3605968e477SDmitry Lukhtionov 			break;
3615968e477SDmitry Lukhtionov 		}
362*93ad59a2SLutz Bichler 	} else if (id == HDA_CODEC_ALC294 &&
363*93ad59a2SLutz Bichler 	    subid == ASUS_UX331_SUBVENDOR) {
364*93ad59a2SLutz Bichler 		switch (nid) {
365*93ad59a2SLutz Bichler 		case 25:
366*93ad59a2SLutz Bichler 			/* XXX You are not expected to understand this. */
367*93ad59a2SLutz Bichler 			config = 0x01a1103c;
368*93ad59a2SLutz Bichler 			break;
369*93ad59a2SLutz Bichler 		case 33:
370*93ad59a2SLutz Bichler 			patch_str = "as=1 seq=15";
371*93ad59a2SLutz Bichler 			break;
372*93ad59a2SLutz Bichler 		}
373ef790cc7SK Staring 	} else {
374ef790cc7SK Staring 		/*
375ef790cc7SK Staring 		 * loop over hdaa_model_pin_patch
376ef790cc7SK Staring 		 */
377ef790cc7SK Staring 		struct pin_patch_t *pin_patches = NULL;
378ef790cc7SK Staring 
379ef790cc7SK Staring 		pin_patches = match_pin_patches(id, subid);
380ef790cc7SK Staring 
381ef790cc7SK Staring 		if (pin_patches != NULL) {
382ef790cc7SK Staring 			for (struct pin_patch_t *patch = pin_patches; patch->type; patch++) {
383ef790cc7SK Staring 				if (nid == patch->nid) {
384ef790cc7SK Staring 					switch (patch->type) {
385ef790cc7SK Staring 					case PIN_PATCH_TYPE_STRING:
386ef790cc7SK Staring 						patch_str = patch->patch.string;
38729b4fa78SGleb Smirnoff 						break;
388ef790cc7SK Staring 					case PIN_PATCH_TYPE_MASK:
389ef790cc7SK Staring 						config &= ~patch->patch.mask[0];
390ef790cc7SK Staring 						config |= patch->patch.mask[1];
391ef790cc7SK Staring 						break;
392ef790cc7SK Staring 					case PIN_PATCH_TYPE_OVERRIDE:
393ef790cc7SK Staring 						config = patch->patch.override;
394ef790cc7SK Staring 						break;
395ef790cc7SK Staring 					default:
396ef790cc7SK Staring 						/* should panic hard */
397ef790cc7SK Staring 						break;
398ef790cc7SK Staring 					}
399ef790cc7SK Staring 					break;
400ef790cc7SK Staring 				}
401ef790cc7SK Staring 			}
402ef790cc7SK Staring 		}
4037c6b05d2SAlexander Motin 	}
4047c6b05d2SAlexander Motin 
405ef790cc7SK Staring 	if (patch_str != NULL)
406ef790cc7SK Staring 		config = hdaa_widget_pin_patch(config, patch_str);
4077c6b05d2SAlexander Motin 	HDA_BOOTVERBOSE(
4087c6b05d2SAlexander Motin 		if (config != orig)
4097c6b05d2SAlexander Motin 			device_printf(w->devinfo->dev,
4107c6b05d2SAlexander Motin 			    "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
4117c6b05d2SAlexander Motin 			    nid, orig, config);
4127c6b05d2SAlexander Motin 	);
4137c6b05d2SAlexander Motin 	w->wclass.pin.config = config;
4147c6b05d2SAlexander Motin }
4157c6b05d2SAlexander Motin 
4167c6b05d2SAlexander Motin static void
hdaa_widget_patch(struct hdaa_widget * w)4177c6b05d2SAlexander Motin hdaa_widget_patch(struct hdaa_widget *w)
4187c6b05d2SAlexander Motin {
4197c6b05d2SAlexander Motin 	struct hdaa_devinfo *devinfo = w->devinfo;
4207c6b05d2SAlexander Motin 	uint32_t orig;
4217c6b05d2SAlexander Motin 	nid_t beeper = -1;
4227c6b05d2SAlexander Motin 
4237c6b05d2SAlexander Motin 	orig = w->param.widget_cap;
4247c6b05d2SAlexander Motin 	/* On some codecs beeper is an input pin, but it is not recordable
4257c6b05d2SAlexander Motin 	   alone. Also most of BIOSes does not declare beeper pin.
4267c6b05d2SAlexander Motin 	   Change beeper pin node type to beeper to help parser. */
4277c6b05d2SAlexander Motin 	switch (hdaa_codec_id(devinfo)) {
4287c6b05d2SAlexander Motin 	case HDA_CODEC_AD1882:
4297c6b05d2SAlexander Motin 	case HDA_CODEC_AD1883:
4307c6b05d2SAlexander Motin 	case HDA_CODEC_AD1984:
4317c6b05d2SAlexander Motin 	case HDA_CODEC_AD1984A:
4327c6b05d2SAlexander Motin 	case HDA_CODEC_AD1984B:
4337c6b05d2SAlexander Motin 	case HDA_CODEC_AD1987:
4347c6b05d2SAlexander Motin 	case HDA_CODEC_AD1988:
4357c6b05d2SAlexander Motin 	case HDA_CODEC_AD1988B:
4367c6b05d2SAlexander Motin 	case HDA_CODEC_AD1989B:
4377c6b05d2SAlexander Motin 		beeper = 26;
4387c6b05d2SAlexander Motin 		break;
4397c6b05d2SAlexander Motin 	case HDA_CODEC_ALC260:
4407c6b05d2SAlexander Motin 		beeper = 23;
4417c6b05d2SAlexander Motin 		break;
4427c6b05d2SAlexander Motin 	}
4437c6b05d2SAlexander Motin 	if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
4447c6b05d2SAlexander Motin 	    hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
4457c6b05d2SAlexander Motin 		beeper = 29;
4467c6b05d2SAlexander Motin 	if (w->nid == beeper) {
4477c6b05d2SAlexander Motin 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
4487c6b05d2SAlexander Motin 		w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
4497c6b05d2SAlexander Motin 		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
4507c6b05d2SAlexander Motin 		w->waspin = 1;
4517c6b05d2SAlexander Motin 	}
452ae84f236SAlexander Motin 	/*
453ae84f236SAlexander Motin 	 * Clear "digital" flag from digital mic input, as its signal then goes
454ae84f236SAlexander Motin 	 * to "analog" mixer and this separation just limits functionaity.
455ae84f236SAlexander Motin 	 */
456ae84f236SAlexander Motin 	if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
457ae84f236SAlexander Motin 	    w->nid == 23)
458ae84f236SAlexander Motin 		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
4597c6b05d2SAlexander Motin 	HDA_BOOTVERBOSE(
4607c6b05d2SAlexander Motin 		if (w->param.widget_cap != orig) {
4617c6b05d2SAlexander Motin 			device_printf(w->devinfo->dev,
4627c6b05d2SAlexander Motin 			    "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
4637c6b05d2SAlexander Motin 			    w->nid, orig, w->param.widget_cap);
4647c6b05d2SAlexander Motin 		}
4657c6b05d2SAlexander Motin 	);
4667c6b05d2SAlexander Motin 
4677c6b05d2SAlexander Motin 	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
4687c6b05d2SAlexander Motin 		hdac_pin_patch(w);
4697c6b05d2SAlexander Motin }
4707c6b05d2SAlexander Motin 
4717c6b05d2SAlexander Motin void
hdaa_patch(struct hdaa_devinfo * devinfo)4727c6b05d2SAlexander Motin hdaa_patch(struct hdaa_devinfo *devinfo)
4737c6b05d2SAlexander Motin {
4747c6b05d2SAlexander Motin 	struct hdaa_widget *w;
4757019329cSAlexander Motin 	uint32_t id, subid, subsystemid;
4767c6b05d2SAlexander Motin 	int i;
4777c6b05d2SAlexander Motin 
4787c6b05d2SAlexander Motin 	id = hdaa_codec_id(devinfo);
479ed228e40SAlexander Motin 	subid = hdaa_card_id(devinfo);
4807019329cSAlexander Motin 	subsystemid = hda_get_subsystem_id(devinfo->dev);
4817c6b05d2SAlexander Motin 
4827c6b05d2SAlexander Motin 	/*
4837c6b05d2SAlexander Motin 	 * Quirks
4847c6b05d2SAlexander Motin 	 */
48542cb359eSHans Petter Selasky 	for (i = 0; i < nitems(hdac_quirks); i++) {
4867c6b05d2SAlexander Motin 		if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
4877019329cSAlexander Motin 		    HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
4887019329cSAlexander Motin 		    HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
4897c6b05d2SAlexander Motin 			continue;
4903c461fd0SAlexander Motin 		devinfo->quirks |= hdac_quirks[i].set;
4913c461fd0SAlexander Motin 		devinfo->quirks &= ~(hdac_quirks[i].unset);
4923c461fd0SAlexander Motin 		devinfo->gpio = hdac_quirks[i].gpio;
4937c6b05d2SAlexander Motin 	}
4947c6b05d2SAlexander Motin 
4957c6b05d2SAlexander Motin 	/* Apply per-widget patch. */
4967c6b05d2SAlexander Motin 	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
4977c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, i);
4987c6b05d2SAlexander Motin 		if (w == NULL)
4997c6b05d2SAlexander Motin 			continue;
5007c6b05d2SAlexander Motin 		hdaa_widget_patch(w);
5017c6b05d2SAlexander Motin 	}
5027c6b05d2SAlexander Motin 
5037c6b05d2SAlexander Motin 	switch (id) {
5047c6b05d2SAlexander Motin 	case HDA_CODEC_AD1983:
5057c6b05d2SAlexander Motin 		/*
5067c6b05d2SAlexander Motin 		 * This CODEC has several possible usages, but none
5077c6b05d2SAlexander Motin 		 * fit the parser best. Help parser to choose better.
5087c6b05d2SAlexander Motin 		 */
5097c6b05d2SAlexander Motin 		/* Disable direct unmixed playback to get pcm volume. */
5107c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 5);
5117c6b05d2SAlexander Motin 		if (w != NULL)
5127c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
5137c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 6);
5147c6b05d2SAlexander Motin 		if (w != NULL)
5157c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
5167c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 11);
5177c6b05d2SAlexander Motin 		if (w != NULL)
5187c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
5197c6b05d2SAlexander Motin 		/* Disable mic and line selectors. */
5207c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 12);
5217c6b05d2SAlexander Motin 		if (w != NULL)
5227c6b05d2SAlexander Motin 			w->connsenable[1] = 0;
5237c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 13);
5247c6b05d2SAlexander Motin 		if (w != NULL)
5257c6b05d2SAlexander Motin 			w->connsenable[1] = 0;
5267c6b05d2SAlexander Motin 		/* Disable recording from mono playback mix. */
5277c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 20);
5287c6b05d2SAlexander Motin 		if (w != NULL)
5297c6b05d2SAlexander Motin 			w->connsenable[3] = 0;
5307c6b05d2SAlexander Motin 		break;
5317c6b05d2SAlexander Motin 	case HDA_CODEC_AD1986A:
5327c6b05d2SAlexander Motin 		/*
5337c6b05d2SAlexander Motin 		 * This CODEC has overcomplicated input mixing.
5347c6b05d2SAlexander Motin 		 * Make some cleaning there.
5357c6b05d2SAlexander Motin 		 */
5367c6b05d2SAlexander Motin 		/* Disable input mono mixer. Not needed and not supported. */
5377c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 43);
5387c6b05d2SAlexander Motin 		if (w != NULL)
5397c6b05d2SAlexander Motin 			w->enable = 0;
5407c6b05d2SAlexander Motin 		/* Disable any with any input mixing mesh. Use separately. */
5417c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 39);
5427c6b05d2SAlexander Motin 		if (w != NULL)
5437c6b05d2SAlexander Motin 			w->enable = 0;
5447c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 40);
5457c6b05d2SAlexander Motin 		if (w != NULL)
5467c6b05d2SAlexander Motin 			w->enable = 0;
5477c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 41);
5487c6b05d2SAlexander Motin 		if (w != NULL)
5497c6b05d2SAlexander Motin 			w->enable = 0;
5507c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 42);
5517c6b05d2SAlexander Motin 		if (w != NULL)
5527c6b05d2SAlexander Motin 			w->enable = 0;
5537c6b05d2SAlexander Motin 		/* Disable duplicate mixer node connector. */
5547c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 15);
5557c6b05d2SAlexander Motin 		if (w != NULL)
5567c6b05d2SAlexander Motin 			w->connsenable[3] = 0;
5577c6b05d2SAlexander Motin 		/* There is only one mic preamplifier, use it effectively. */
5587c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 31);
5597c6b05d2SAlexander Motin 		if (w != NULL) {
5607c6b05d2SAlexander Motin 			if ((w->wclass.pin.config &
5617c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
5627c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
5637c6b05d2SAlexander Motin 				w = hdaa_widget_get(devinfo, 16);
5647c6b05d2SAlexander Motin 				if (w != NULL)
5657c6b05d2SAlexander Motin 				    w->connsenable[2] = 0;
5667c6b05d2SAlexander Motin 			} else {
5677c6b05d2SAlexander Motin 				w = hdaa_widget_get(devinfo, 15);
5687c6b05d2SAlexander Motin 				if (w != NULL)
5697c6b05d2SAlexander Motin 				    w->connsenable[0] = 0;
5707c6b05d2SAlexander Motin 			}
5717c6b05d2SAlexander Motin 		}
5727c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 32);
5737c6b05d2SAlexander Motin 		if (w != NULL) {
5747c6b05d2SAlexander Motin 			if ((w->wclass.pin.config &
5757c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
5767c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
5777c6b05d2SAlexander Motin 				w = hdaa_widget_get(devinfo, 16);
5787c6b05d2SAlexander Motin 				if (w != NULL)
5797c6b05d2SAlexander Motin 				    w->connsenable[0] = 0;
5807c6b05d2SAlexander Motin 			} else {
5817c6b05d2SAlexander Motin 				w = hdaa_widget_get(devinfo, 15);
5827c6b05d2SAlexander Motin 				if (w != NULL)
5837c6b05d2SAlexander Motin 				    w->connsenable[1] = 0;
5847c6b05d2SAlexander Motin 			}
5857c6b05d2SAlexander Motin 		}
5867c6b05d2SAlexander Motin 
5877c6b05d2SAlexander Motin 		if (subid == ASUS_A8X_SUBVENDOR) {
5887c6b05d2SAlexander Motin 			/*
5897c6b05d2SAlexander Motin 			 * This is just plain ridiculous.. There
5907c6b05d2SAlexander Motin 			 * are several A8 series that share the same
5917c6b05d2SAlexander Motin 			 * pci id but works differently (EAPD).
5927c6b05d2SAlexander Motin 			 */
5937c6b05d2SAlexander Motin 			w = hdaa_widget_get(devinfo, 26);
5947c6b05d2SAlexander Motin 			if (w != NULL && w->type ==
5957c6b05d2SAlexander Motin 			    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
5967c6b05d2SAlexander Motin 			    (w->wclass.pin.config &
5977c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
5987c6b05d2SAlexander Motin 			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
5997c6b05d2SAlexander Motin 				devinfo->quirks &=
6007c6b05d2SAlexander Motin 				    ~HDAA_QUIRK_EAPDINV;
6017c6b05d2SAlexander Motin 		}
6027c6b05d2SAlexander Motin 		break;
6037c6b05d2SAlexander Motin 	case HDA_CODEC_AD1981HD:
6047c6b05d2SAlexander Motin 		/*
6057c6b05d2SAlexander Motin 		 * This CODEC has very unusual design with several
6067c6b05d2SAlexander Motin 		 * points inappropriate for the present parser.
6077c6b05d2SAlexander Motin 		 */
6087c6b05d2SAlexander Motin 		/* Disable recording from mono playback mix. */
6097c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 21);
6107c6b05d2SAlexander Motin 		if (w != NULL)
6117c6b05d2SAlexander Motin 			w->connsenable[3] = 0;
6127c6b05d2SAlexander Motin 		/* Disable rear to front mic mixer, use separately. */
6137c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 31);
6147c6b05d2SAlexander Motin 		if (w != NULL)
6157c6b05d2SAlexander Motin 			w->enable = 0;
6167c6b05d2SAlexander Motin 		/* Disable direct playback, use mixer. */
6177c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 5);
6187c6b05d2SAlexander Motin 		if (w != NULL)
6197c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
6207c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 6);
6217c6b05d2SAlexander Motin 		if (w != NULL)
6227c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
6237c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 9);
6247c6b05d2SAlexander Motin 		if (w != NULL)
6257c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
6267c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 24);
6277c6b05d2SAlexander Motin 		if (w != NULL)
6287c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
6297c6b05d2SAlexander Motin 		break;
63030495557SAlexander Motin 	case HDA_CODEC_ALC269:
63130495557SAlexander Motin 		/*
63230495557SAlexander Motin 		 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
63330495557SAlexander Motin 		 * that mutes speaker if unused mixer at NID 15 is muted.
63430495557SAlexander Motin 		 * Probably CODEC incorrectly reports internal connections.
63530495557SAlexander Motin 		 * Hide that muter from the driver.  There are several CODECs
63630495557SAlexander Motin 		 * sharing this ID and I have not enough information about
63730495557SAlexander Motin 		 * them to implement more universal solution.
63830495557SAlexander Motin 		 */
63930495557SAlexander Motin 		if (subid == 0x84371043) {
64030495557SAlexander Motin 			w = hdaa_widget_get(devinfo, 15);
64130495557SAlexander Motin 			if (w != NULL)
64230495557SAlexander Motin 				w->param.inamp_cap = 0;
64330495557SAlexander Motin 		}
64430495557SAlexander Motin 		break;
6457c6b05d2SAlexander Motin 	case HDA_CODEC_CX20582:
6467c6b05d2SAlexander Motin 	case HDA_CODEC_CX20583:
6477c6b05d2SAlexander Motin 	case HDA_CODEC_CX20584:
6487c6b05d2SAlexander Motin 	case HDA_CODEC_CX20585:
6497c6b05d2SAlexander Motin 	case HDA_CODEC_CX20590:
6507c6b05d2SAlexander Motin 		/*
6517c6b05d2SAlexander Motin 		 * These codecs have extra connectivity on record side
6527c6b05d2SAlexander Motin 		 * too reach for the present parser.
6537c6b05d2SAlexander Motin 		 */
6547c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 20);
6557c6b05d2SAlexander Motin 		if (w != NULL)
6567c6b05d2SAlexander Motin 			w->connsenable[1] = 0;
6577c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 21);
6587c6b05d2SAlexander Motin 		if (w != NULL)
6597c6b05d2SAlexander Motin 			w->connsenable[1] = 0;
6607c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 22);
6617c6b05d2SAlexander Motin 		if (w != NULL)
6627c6b05d2SAlexander Motin 			w->connsenable[0] = 0;
6637c6b05d2SAlexander Motin 		break;
6647c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_0:
6657c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_1:
6667c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_2:
6677c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_3:
6687c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_4:
6697c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_5:
6707c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_6:
6717c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_7:
6727c6b05d2SAlexander Motin 		/*
6737c6b05d2SAlexander Motin 		 * These codecs have hidden mic boost controls.
6747c6b05d2SAlexander Motin 		 */
6757c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 26);
6767c6b05d2SAlexander Motin 		if (w != NULL)
6777c6b05d2SAlexander Motin 			w->param.inamp_cap =
6787c6b05d2SAlexander Motin 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
6797c6b05d2SAlexander Motin 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
6807c6b05d2SAlexander Motin 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
6817c6b05d2SAlexander Motin 		w = hdaa_widget_get(devinfo, 30);
6827c6b05d2SAlexander Motin 		if (w != NULL)
6837c6b05d2SAlexander Motin 			w->param.inamp_cap =
6847c6b05d2SAlexander Motin 			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
6857c6b05d2SAlexander Motin 			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
6867c6b05d2SAlexander Motin 			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
6877c6b05d2SAlexander Motin 		break;
6887c6b05d2SAlexander Motin 	}
6897c6b05d2SAlexander Motin }
6907c6b05d2SAlexander Motin 
691d575325bSAlexander Motin static uint32_t
hdaa_read_coef(device_t dev,nid_t nid,uint16_t idx)692d575325bSAlexander Motin hdaa_read_coef(device_t dev, nid_t nid, uint16_t idx)
693d575325bSAlexander Motin {
694d575325bSAlexander Motin 
695d575325bSAlexander Motin 	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
696d575325bSAlexander Motin 	return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid)));
697d575325bSAlexander Motin }
698d575325bSAlexander Motin 
699d575325bSAlexander Motin static uint32_t
hdaa_write_coef(device_t dev,nid_t nid,uint16_t idx,uint16_t val)700d575325bSAlexander Motin hdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val)
701d575325bSAlexander Motin {
702d575325bSAlexander Motin 
703d575325bSAlexander Motin 	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
704d575325bSAlexander Motin 	return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val)));
705d575325bSAlexander Motin }
706d575325bSAlexander Motin 
7077c6b05d2SAlexander Motin void
hdaa_patch_direct(struct hdaa_devinfo * devinfo)7087c6b05d2SAlexander Motin hdaa_patch_direct(struct hdaa_devinfo *devinfo)
7097c6b05d2SAlexander Motin {
7107c6b05d2SAlexander Motin 	device_t dev = devinfo->dev;
7117c6b05d2SAlexander Motin 	uint32_t id, subid, val;
7127c6b05d2SAlexander Motin 
7137c6b05d2SAlexander Motin 	id = hdaa_codec_id(devinfo);
714ed228e40SAlexander Motin 	subid = hdaa_card_id(devinfo);
7157c6b05d2SAlexander Motin 
7167c6b05d2SAlexander Motin 	switch (id) {
7177c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_0:
7187c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_1:
7197c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_2:
7207c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_3:
7217c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_4:
7227c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_5:
7237c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_6:
7247c6b05d2SAlexander Motin 	case HDA_CODEC_VT1708S_7:
7257c6b05d2SAlexander Motin 		/* Enable Mic Boost Volume controls. */
7267c6b05d2SAlexander Motin 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
7277c6b05d2SAlexander Motin 		    0xf98, 0x01));
728675dce07SAlexander Motin 		/* Fall though */
729675dce07SAlexander Motin 	case HDA_CODEC_VT1818S:
7307c6b05d2SAlexander Motin 		/* Don't bypass mixer. */
7317c6b05d2SAlexander Motin 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
7327c6b05d2SAlexander Motin 		    0xf88, 0xc0));
7337c6b05d2SAlexander Motin 		break;
7346861837cSPyun YongHyeon 	case HDA_CODEC_ALC1150:
7356861837cSPyun YongHyeon 		if (subid == 0xd9781462) {
7366861837cSPyun YongHyeon 			/* Too low volume on MSI H170 GAMING M3. */
7376861837cSPyun YongHyeon 			hdaa_write_coef(dev, 0x20, 0x07, 0x7cb);
7386861837cSPyun YongHyeon 		}
7396861837cSPyun YongHyeon 		break;
7407c6b05d2SAlexander Motin 	}
7418a323852SJung-uk Kim 	if (id == HDA_CODEC_ALC255 || id == HDA_CODEC_ALC256) {
7428a323852SJung-uk Kim 		val = hdaa_read_coef(dev, 0x20, 0x46);
7438a323852SJung-uk Kim 		hdaa_write_coef(dev, 0x20, 0x46, val|0x3000);
7448a323852SJung-uk Kim 	}
7457c6b05d2SAlexander Motin 	if (subid == APPLE_INTEL_MAC)
7467c6b05d2SAlexander Motin 		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
7477c6b05d2SAlexander Motin 		    0x7e7, 0));
7487c6b05d2SAlexander Motin 	if (id == HDA_CODEC_ALC269) {
74989a8feddSAlexander Motin 		if (subid == 0x16e31043 || subid == 0x831a1043 ||
75089a8feddSAlexander Motin 		    subid == 0x834a1043 || subid == 0x83981043 ||
75189a8feddSAlexander Motin 		    subid == 0x83ce1043) {
7527c6b05d2SAlexander Motin 			/*
7535d698386SPhilippe Michaud-Boudreault 			 * The digital mics on some Asus laptops produce
7547c6b05d2SAlexander Motin 			 * differential signals instead of expected stereo.
7555d698386SPhilippe Michaud-Boudreault 			 * That results in silence if downmixing to mono.
7565d698386SPhilippe Michaud-Boudreault 			 * To workaround, make codec handle the signal as mono.
7577c6b05d2SAlexander Motin 			 */
758d575325bSAlexander Motin 			val = hdaa_read_coef(dev, 0x20, 0x07);
759d575325bSAlexander Motin 			hdaa_write_coef(dev, 0x20, 0x07, val|0x80);
760d575325bSAlexander Motin 		}
761d575325bSAlexander Motin 		if (subid == 0x15171043) {
762d575325bSAlexander Motin 			/* Increase output amp on ASUS UX31A by +5dB. */
763d575325bSAlexander Motin 			hdaa_write_coef(dev, 0x20, 0x12, 0x2800);
7647c6b05d2SAlexander Motin 		}
7657c6b05d2SAlexander Motin 	}
7667c6b05d2SAlexander Motin }
767