1230130Smav/*-
2230130Smav * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
3230130Smav * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
4230130Smav * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
5230130Smav * All rights reserved.
6230130Smav *
7230130Smav * Redistribution and use in source and binary forms, with or without
8230130Smav * modification, are permitted provided that the following conditions
9230130Smav * are met:
10230130Smav * 1. Redistributions of source code must retain the above copyright
11230130Smav *    notice, this list of conditions and the following disclaimer.
12230130Smav * 2. Redistributions in binary form must reproduce the above copyright
13230130Smav *    notice, this list of conditions and the following disclaimer in the
14230130Smav *    documentation and/or other materials provided with the distribution.
15230130Smav *
16230130Smav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17230130Smav * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18230130Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19230130Smav * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20230130Smav * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21230130Smav * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22230130Smav * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23230130Smav * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24230130Smav * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25230130Smav * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26230130Smav * SUCH DAMAGE.
27230130Smav */
28230130Smav
29230130Smav/*
30230130Smav * Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
31230130Smav */
32230130Smav
33230130Smav#ifdef HAVE_KERNEL_OPTION_HEADERS
34230130Smav#include "opt_snd.h"
35230130Smav#endif
36230130Smav
37230130Smav#include <dev/sound/pcm/sound.h>
38230130Smav
39230130Smav#include <sys/ctype.h>
40230130Smav
41230130Smav#include <dev/sound/pci/hda/hdac.h>
42230130Smav#include <dev/sound/pci/hda/hdaa.h>
43230130Smav#include <dev/sound/pci/hda/hda_reg.h>
44230130Smav
45230130SmavSND_DECLARE_FILE("$FreeBSD: stable/11/sys/dev/sound/pci/hda/hdaa_patches.c 351814 2019-09-04 14:05:04Z jkim $");
46230130Smav
47230130Smavstatic const struct {
48230130Smav	uint32_t model;
49230130Smav	uint32_t id;
50248786Smav	uint32_t subsystemid;
51230130Smav	uint32_t set, unset;
52230130Smav	uint32_t gpio;
53230130Smav} hdac_quirks[] = {
54230130Smav	/*
55230130Smav	 * XXX Force stereo quirk. Monoural recording / playback
56230130Smav	 *     on few codecs (especially ALC880) seems broken or
57230130Smav	 *     perhaps unsupported.
58230130Smav	 */
59248786Smav	{ HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_MATCH_ALL,
60230130Smav	    HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
61230130Smav	    0 },
62248786Smav	{ ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, HDA_MATCH_ALL,
63230130Smav	    0, 0,
64230130Smav	    HDAA_GPIO_SET(0) },
65248786Smav	{ ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, HDA_MATCH_ALL,
66230130Smav	    0, 0,
67230130Smav	    HDAA_GPIO_SET(0) },
68248786Smav	{ ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
69230130Smav	    0, 0,
70230130Smav	    HDAA_GPIO_SET(0) },
71248786Smav	{ ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
72230130Smav	    0, 0,
73230130Smav	    HDAA_GPIO_SET(0) },
74248786Smav	{ ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
75230130Smav	    0, 0,
76230130Smav	    HDAA_GPIO_SET(0) },
77248786Smav	{ ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
78230130Smav	    0, 0,
79230130Smav	    HDAA_GPIO_SET(0) },
80248786Smav	{ ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
81230130Smav	    HDAA_QUIRK_EAPDINV, 0,
82230130Smav	    0 },
83248786Smav	{ ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
84230130Smav	    HDAA_QUIRK_EAPDINV, 0,
85230130Smav	    0 },
86248786Smav	{ ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
87230130Smav	    HDAA_QUIRK_OVREF, 0,
88230130Smav	    0 },
89248786Smav	{ UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
90230130Smav	    HDAA_QUIRK_OVREF, 0,
91230130Smav	    0 },
92248786Smav	/*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, HDA_MATCH_ALL,
93230130Smav	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
94230130Smav	    0 },*/
95248786Smav	{ MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
96230130Smav	    0, 0,
97230130Smav	    HDAA_GPIO_SET(1) },
98248786Smav	{ LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
99230130Smav	    HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
100230130Smav	    0 },
101248786Smav	{ SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
102230130Smav	    HDAA_QUIRK_EAPDINV, 0,
103230130Smav	    0 },
104248786Smav	{ APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDA_MATCH_ALL,
105230130Smav	    HDAA_QUIRK_OVREF50, 0,
106230130Smav	    HDAA_GPIO_SET(0) },
107248786Smav	{ APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDA_MATCH_ALL,
108230130Smav	    0, 0,
109230130Smav	    HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
110261507Shselasky	{ APPLE_MACBOOKAIR31, HDA_CODEC_CS4206, HDA_MATCH_ALL,
111261507Shselasky	    0, 0,
112261507Shselasky	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
113248786Smav	{ APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
114230130Smav	    0, 0,
115230130Smav	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
116261507Shselasky	{ APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL,
117261507Shselasky	    0, 0,
118261507Shselasky	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
119261507Shselasky	{ HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL,
120261507Shselasky	    0, 0,
121261507Shselasky	    HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
122248786Smav	{ DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
123230130Smav	    0, 0,
124230130Smav	    HDAA_GPIO_SET(0) },
125248786Smav	{ DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
126230130Smav	    0, 0,
127230130Smav	    HDAA_GPIO_SET(2) },
128248786Smav	{ DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
129230130Smav	    0, 0,
130230130Smav	    HDAA_GPIO_SET(0) },
131248786Smav	{ HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
132230130Smav	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
133230130Smav	    0 },
134248786Smav	{ HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
135230130Smav	    HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
136230130Smav	    0 },
137248786Smav	{ HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
138230130Smav	    0, HDAA_QUIRK_FORCESTEREO,
139248786Smav	    0 },
140248786Smav	/* Mac Pro 1,1 requires ovref for proper volume level. */
141248786Smav	{ 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
142248786Smav	    0, HDAA_QUIRK_OVREF,
143230130Smav	    0 }
144230130Smav};
145230130Smav
146230130Smavstatic void
147230130Smavhdac_pin_patch(struct hdaa_widget *w)
148230130Smav{
149230130Smav	const char *patch = NULL;
150230130Smav	uint32_t config, orig, id, subid;
151230130Smav	nid_t nid = w->nid;
152230130Smav
153230130Smav	config = orig = w->wclass.pin.config;
154230130Smav	id = hdaa_codec_id(w->devinfo);
155242352Smav	subid = hdaa_card_id(w->devinfo);
156230130Smav
157230130Smav	/* XXX: Old patches require complete review.
158230130Smav	 * Now they may create more problem then solve due to
159230130Smav	 * incorrect associations.
160230130Smav	 */
161230130Smav	if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) {
162230130Smav		switch (nid) {
163230130Smav		case 26:
164230130Smav			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
165230130Smav			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
166230130Smav			break;
167230130Smav		case 27:
168230130Smav			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
169230130Smav			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT;
170230130Smav			break;
171230130Smav		default:
172230130Smav			break;
173230130Smav		}
174230130Smav	} else if (id == HDA_CODEC_ALC880 &&
175230130Smav	    (subid == CLEVO_D900T_SUBVENDOR ||
176230130Smav	    subid == ASUS_M5200_SUBVENDOR)) {
177230130Smav		/*
178230130Smav		 * Super broken BIOS
179230130Smav		 */
180230130Smav		switch (nid) {
181230130Smav		case 24:	/* MIC1 */
182230130Smav			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
183230130Smav			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
184230130Smav			break;
185230130Smav		case 25:	/* XXX MIC2 */
186230130Smav			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
187230130Smav			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
188230130Smav			break;
189230130Smav		case 26:	/* LINE1 */
190230130Smav			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
191230130Smav			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
192230130Smav			break;
193230130Smav		case 27:	/* XXX LINE2 */
194230130Smav			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
195230130Smav			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
196230130Smav			break;
197230130Smav		case 28:	/* CD */
198230130Smav			config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
199230130Smav			config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD;
200230130Smav			break;
201230130Smav		}
202230130Smav	} else if (id == HDA_CODEC_ALC883 &&
203230130Smav	    (subid == MSI_MS034A_SUBVENDOR ||
204230130Smav	    HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) {
205230130Smav		switch (nid) {
206230130Smav		case 25:
207230130Smav			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
208230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
209230130Smav			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
210230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
211230130Smav			break;
212230130Smav		case 28:
213230130Smav			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
214230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
215230130Smav			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
216230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
217230130Smav			break;
218230130Smav		}
219230130Smav	} else if (id == HDA_CODEC_CX20549 && subid ==
220230130Smav	    HP_V3000_SUBVENDOR) {
221230130Smav		switch (nid) {
222230130Smav		case 18:
223230130Smav			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
224230130Smav			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
225230130Smav			break;
226230130Smav		case 20:
227230130Smav			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
228230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
229230130Smav			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
230230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
231230130Smav			break;
232230130Smav		case 21:
233230130Smav			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
234230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
235230130Smav			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
236230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
237230130Smav			break;
238230130Smav		}
239230130Smav	} else if (id == HDA_CODEC_CX20551 && subid ==
240230130Smav	    HP_DV5000_SUBVENDOR) {
241230130Smav		switch (nid) {
242230130Smav		case 20:
243230130Smav		case 21:
244230130Smav			config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
245230130Smav			config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
246230130Smav			break;
247230130Smav		}
248230130Smav	} else if (id == HDA_CODEC_ALC861 && subid ==
249230130Smav	    ASUS_W6F_SUBVENDOR) {
250230130Smav		switch (nid) {
251230130Smav		case 11:
252230130Smav			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
253230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
254230130Smav			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
255230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
256230130Smav			break;
257230130Smav		case 12:
258230130Smav		case 14:
259230130Smav		case 16:
260230130Smav		case 31:
261230130Smav		case 32:
262230130Smav			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
263230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
264230130Smav			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
265230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
266230130Smav			break;
267230130Smav		case 15:
268230130Smav			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
269230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
270230130Smav			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
271230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
272230130Smav			break;
273230130Smav		}
274230130Smav	} else if (id == HDA_CODEC_ALC861 && subid ==
275230130Smav	    UNIWILL_9075_SUBVENDOR) {
276230130Smav		switch (nid) {
277230130Smav		case 15:
278230130Smav			config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
279230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
280230130Smav			config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
281230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
282230130Smav			break;
283230130Smav		}
284230130Smav	}
285230130Smav
286230130Smav	/* New patches */
287244145Smav	if (id == HDA_CODEC_AD1984A &&
288244145Smav	    subid == LENOVO_X300_SUBVENDOR) {
289244145Smav		switch (nid) {
290244145Smav		case 17: /* Headphones with redirection */
291244145Smav			patch = "as=1 seq=15";
292244145Smav			break;
293244145Smav		case 20: /* Two mics together */
294244145Smav			patch = "as=2 seq=15";
295244145Smav			break;
296244145Smav		}
297244145Smav	} else if (id == HDA_CODEC_AD1986A &&
298230130Smav	    (subid == ASUS_M2NPVMX_SUBVENDOR ||
299230130Smav	    subid == ASUS_A8NVMCSM_SUBVENDOR ||
300230130Smav	    subid == ASUS_P5PL2_SUBVENDOR)) {
301230130Smav		switch (nid) {
302230130Smav		case 26: /* Headphones with redirection */
303230130Smav			patch = "as=1 seq=15";
304230130Smav			break;
305230130Smav		case 28: /* 5.1 out => 2.0 out + 1 input */
306230130Smav			patch = "device=Line-in as=8 seq=1";
307230130Smav			break;
308230130Smav		case 29: /* Can't use this as input, as the only available mic
309230130Smav			  * preamplifier is busy by front panel mic (nid 31).
310230130Smav			  * If you want to use this rear connector as mic input,
311230130Smav			  * you have to disable the front panel one. */
312230130Smav			patch = "as=0";
313230130Smav			break;
314230130Smav		case 31: /* Lot of inputs configured with as=15 and unusable */
315230130Smav			patch = "as=8 seq=3";
316230130Smav			break;
317230130Smav		case 32:
318230130Smav			patch = "as=8 seq=4";
319230130Smav			break;
320230130Smav		case 34:
321230130Smav			patch = "as=8 seq=5";
322230130Smav			break;
323230130Smav		case 36:
324230130Smav			patch = "as=8 seq=6";
325230130Smav			break;
326230130Smav		}
327230130Smav	} else if (id == HDA_CODEC_ALC260 &&
328230130Smav	    HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
329230130Smav		switch (nid) {
330230130Smav		case 16:
331230130Smav			patch = "seq=15 device=Headphones";
332230130Smav			break;
333230130Smav		}
334230130Smav	} else if (id == HDA_CODEC_ALC268) {
335230130Smav	    if (subid == ACER_T5320_SUBVENDOR) {
336230130Smav		switch (nid) {
337230130Smav		case 20: /* Headphones Jack */
338230130Smav			patch = "as=1 seq=15";
339230130Smav			break;
340230130Smav		}
341230130Smav	    }
342230130Smav	} else if (id == HDA_CODEC_CX20561 &&
343230130Smav	    subid == LENOVO_B450_SUBVENDOR) {
344230130Smav		switch (nid) {
345230130Smav		case 22:
346230130Smav			patch = "as=1 seq=15";
347230130Smav			break;
348230130Smav		}
349269152Sadrian	} else if (id == HDA_CODEC_CX20561 &&
350269152Sadrian	    subid == LENOVO_T400_SUBVENDOR) {
351269152Sadrian		switch (nid) {
352269152Sadrian		case 22:
353269152Sadrian			patch = "as=1 seq=15";
354269152Sadrian			break;
355269152Sadrian		case 26:
356269152Sadrian			patch = "as=1 seq=0";
357269152Sadrian			break;
358269152Sadrian		}
359247815Smav	} else if (id == HDA_CODEC_CX20590 &&
360247911Sglebius	    (subid == LENOVO_X1_SUBVENDOR ||
361247911Sglebius	    subid == LENOVO_X220_SUBVENDOR ||
362247911Sglebius	    subid == LENOVO_T420_SUBVENDOR ||
363268584Smarkj	    subid == LENOVO_T520_SUBVENDOR ||
364268584Smarkj	    subid == LENOVO_G580_SUBVENDOR)) {
365247815Smav		switch (nid) {
366247815Smav		case 25:
367247815Smav			patch = "as=1 seq=15";
368247815Smav			break;
369264831Smarius		/*
370250797Ssbruno		 * Group onboard mic and headphone mic
371250797Ssbruno		 * together.  Fixes onboard mic.
372250797Ssbruno		 */
373250797Ssbruno		case 27:
374250797Ssbruno			patch = "as=2 seq=15";
375250797Ssbruno			break;
376250797Ssbruno		case 35:
377250797Ssbruno			patch = "as=2";
378250797Ssbruno			break;
379247815Smav		}
380247911Sglebius	} else if (id == HDA_CODEC_ALC269 &&
381248187Sglebius	    (subid == LENOVO_X1CRBN_SUBVENDOR ||
382248187Sglebius	    subid == LENOVO_T430_SUBVENDOR ||
383248254Sdelphij	    subid == LENOVO_T430S_SUBVENDOR ||
384248254Sdelphij	    subid == LENOVO_T530_SUBVENDOR)) {
385247911Sglebius		switch (nid) {
386247911Sglebius		case 21:
387247911Sglebius			patch = "as=1 seq=15";
388247911Sglebius			break;
389247911Sglebius		}
390351814Sjkim	} else if (id == HDA_CODEC_ALC285 &&
391351814Sjkim	    subid == LENOVO_X120KH_SUBVENDOR) {
392351814Sjkim		switch (nid) {
393351814Sjkim		case 33:
394351814Sjkim			patch = "as=1 seq=15";
395351814Sjkim			break;
396351814Sjkim		}
397253036Smav	} else if (id == HDA_CODEC_ALC269 &&
398253036Smav	    subid == ASUS_UX31A_SUBVENDOR) {
399253036Smav		switch (nid) {
400253036Smav		case 33:
401253036Smav			patch = "as=1 seq=15";
402253036Smav			break;
403253036Smav		}
404264831Smarius	} else if (id == HDA_CODEC_ALC892 &&
405264831Smarius	    subid == INTEL_DH87RL_SUBVENDOR) {
406264831Smarius		switch (nid) {
407264831Smarius		case 27:
408264831Smarius			patch = "as=1 seq=15";
409264831Smarius			break;
410264831Smarius		}
411281544Srpaulo	} else if (id == HDA_CODEC_ALC292 &&
412281544Srpaulo	    subid == LENOVO_X120BS_SUBVENDOR) {
413281544Srpaulo		switch (nid) {
414281544Srpaulo		case 21:
415281544Srpaulo			patch = "as=1 seq=15";
416281544Srpaulo			break;
417281544Srpaulo		}
418230130Smav	}
419230130Smav
420230130Smav	if (patch != NULL)
421230130Smav		config = hdaa_widget_pin_patch(config, patch);
422230130Smav	HDA_BOOTVERBOSE(
423230130Smav		if (config != orig)
424230130Smav			device_printf(w->devinfo->dev,
425230130Smav			    "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
426230130Smav			    nid, orig, config);
427230130Smav	);
428230130Smav	w->wclass.pin.config = config;
429230130Smav}
430230130Smav
431230130Smavstatic void
432230130Smavhdaa_widget_patch(struct hdaa_widget *w)
433230130Smav{
434230130Smav	struct hdaa_devinfo *devinfo = w->devinfo;
435230130Smav	uint32_t orig;
436230130Smav	nid_t beeper = -1;
437230130Smav
438230130Smav	orig = w->param.widget_cap;
439230130Smav	/* On some codecs beeper is an input pin, but it is not recordable
440230130Smav	   alone. Also most of BIOSes does not declare beeper pin.
441230130Smav	   Change beeper pin node type to beeper to help parser. */
442230130Smav	switch (hdaa_codec_id(devinfo)) {
443230130Smav	case HDA_CODEC_AD1882:
444230130Smav	case HDA_CODEC_AD1883:
445230130Smav	case HDA_CODEC_AD1984:
446230130Smav	case HDA_CODEC_AD1984A:
447230130Smav	case HDA_CODEC_AD1984B:
448230130Smav	case HDA_CODEC_AD1987:
449230130Smav	case HDA_CODEC_AD1988:
450230130Smav	case HDA_CODEC_AD1988B:
451230130Smav	case HDA_CODEC_AD1989B:
452230130Smav		beeper = 26;
453230130Smav		break;
454230130Smav	case HDA_CODEC_ALC260:
455230130Smav		beeper = 23;
456230130Smav		break;
457230130Smav	}
458230130Smav	if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
459230130Smav	    hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
460230130Smav		beeper = 29;
461230130Smav	if (w->nid == beeper) {
462230130Smav		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
463230130Smav		w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
464230130Smav		    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
465230130Smav		w->waspin = 1;
466230130Smav	}
467244145Smav	/*
468244145Smav	 * Clear "digital" flag from digital mic input, as its signal then goes
469244145Smav	 * to "analog" mixer and this separation just limits functionaity.
470244145Smav	 */
471244145Smav	if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
472244145Smav	    w->nid == 23)
473244145Smav		w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
474230130Smav	HDA_BOOTVERBOSE(
475230130Smav		if (w->param.widget_cap != orig) {
476230130Smav			device_printf(w->devinfo->dev,
477230130Smav			    "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
478230130Smav			    w->nid, orig, w->param.widget_cap);
479230130Smav		}
480230130Smav	);
481230130Smav
482230130Smav	if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
483230130Smav		hdac_pin_patch(w);
484230130Smav}
485230130Smav
486230130Smavvoid
487230130Smavhdaa_patch(struct hdaa_devinfo *devinfo)
488230130Smav{
489230130Smav	struct hdaa_widget *w;
490248786Smav	uint32_t id, subid, subsystemid;
491230130Smav	int i;
492230130Smav
493230130Smav	id = hdaa_codec_id(devinfo);
494242352Smav	subid = hdaa_card_id(devinfo);
495248786Smav	subsystemid = hda_get_subsystem_id(devinfo->dev);
496230130Smav
497230130Smav	/*
498230130Smav	 * Quirks
499230130Smav	 */
500261508Shselasky	for (i = 0; i < nitems(hdac_quirks); i++) {
501230130Smav		if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
502248786Smav		    HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
503248786Smav		    HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
504230130Smav			continue;
505238011Smav		devinfo->quirks |= hdac_quirks[i].set;
506238011Smav		devinfo->quirks &= ~(hdac_quirks[i].unset);
507238011Smav		devinfo->gpio = hdac_quirks[i].gpio;
508230130Smav	}
509230130Smav
510230130Smav	/* Apply per-widget patch. */
511230130Smav	for (i = devinfo->startnode; i < devinfo->endnode; i++) {
512230130Smav		w = hdaa_widget_get(devinfo, i);
513230130Smav		if (w == NULL)
514230130Smav			continue;
515230130Smav		hdaa_widget_patch(w);
516230130Smav	}
517230130Smav
518230130Smav	switch (id) {
519230130Smav	case HDA_CODEC_AD1983:
520230130Smav		/*
521230130Smav		 * This CODEC has several possible usages, but none
522230130Smav		 * fit the parser best. Help parser to choose better.
523230130Smav		 */
524230130Smav		/* Disable direct unmixed playback to get pcm volume. */
525230130Smav		w = hdaa_widget_get(devinfo, 5);
526230130Smav		if (w != NULL)
527230130Smav			w->connsenable[0] = 0;
528230130Smav		w = hdaa_widget_get(devinfo, 6);
529230130Smav		if (w != NULL)
530230130Smav			w->connsenable[0] = 0;
531230130Smav		w = hdaa_widget_get(devinfo, 11);
532230130Smav		if (w != NULL)
533230130Smav			w->connsenable[0] = 0;
534230130Smav		/* Disable mic and line selectors. */
535230130Smav		w = hdaa_widget_get(devinfo, 12);
536230130Smav		if (w != NULL)
537230130Smav			w->connsenable[1] = 0;
538230130Smav		w = hdaa_widget_get(devinfo, 13);
539230130Smav		if (w != NULL)
540230130Smav			w->connsenable[1] = 0;
541230130Smav		/* Disable recording from mono playback mix. */
542230130Smav		w = hdaa_widget_get(devinfo, 20);
543230130Smav		if (w != NULL)
544230130Smav			w->connsenable[3] = 0;
545230130Smav		break;
546230130Smav	case HDA_CODEC_AD1986A:
547230130Smav		/*
548230130Smav		 * This CODEC has overcomplicated input mixing.
549230130Smav		 * Make some cleaning there.
550230130Smav		 */
551230130Smav		/* Disable input mono mixer. Not needed and not supported. */
552230130Smav		w = hdaa_widget_get(devinfo, 43);
553230130Smav		if (w != NULL)
554230130Smav			w->enable = 0;
555230130Smav		/* Disable any with any input mixing mesh. Use separately. */
556230130Smav		w = hdaa_widget_get(devinfo, 39);
557230130Smav		if (w != NULL)
558230130Smav			w->enable = 0;
559230130Smav		w = hdaa_widget_get(devinfo, 40);
560230130Smav		if (w != NULL)
561230130Smav			w->enable = 0;
562230130Smav		w = hdaa_widget_get(devinfo, 41);
563230130Smav		if (w != NULL)
564230130Smav			w->enable = 0;
565230130Smav		w = hdaa_widget_get(devinfo, 42);
566230130Smav		if (w != NULL)
567230130Smav			w->enable = 0;
568230130Smav		/* Disable duplicate mixer node connector. */
569230130Smav		w = hdaa_widget_get(devinfo, 15);
570230130Smav		if (w != NULL)
571230130Smav			w->connsenable[3] = 0;
572230130Smav		/* There is only one mic preamplifier, use it effectively. */
573230130Smav		w = hdaa_widget_get(devinfo, 31);
574230130Smav		if (w != NULL) {
575230130Smav			if ((w->wclass.pin.config &
576230130Smav			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
577230130Smav			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
578230130Smav				w = hdaa_widget_get(devinfo, 16);
579230130Smav				if (w != NULL)
580230130Smav				    w->connsenable[2] = 0;
581230130Smav			} else {
582230130Smav				w = hdaa_widget_get(devinfo, 15);
583230130Smav				if (w != NULL)
584230130Smav				    w->connsenable[0] = 0;
585230130Smav			}
586230130Smav		}
587230130Smav		w = hdaa_widget_get(devinfo, 32);
588230130Smav		if (w != NULL) {
589230130Smav			if ((w->wclass.pin.config &
590230130Smav			    HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
591230130Smav			    HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
592230130Smav				w = hdaa_widget_get(devinfo, 16);
593230130Smav				if (w != NULL)
594230130Smav				    w->connsenable[0] = 0;
595230130Smav			} else {
596230130Smav				w = hdaa_widget_get(devinfo, 15);
597230130Smav				if (w != NULL)
598230130Smav				    w->connsenable[1] = 0;
599230130Smav			}
600230130Smav		}
601230130Smav
602230130Smav		if (subid == ASUS_A8X_SUBVENDOR) {
603230130Smav			/*
604230130Smav			 * This is just plain ridiculous.. There
605230130Smav			 * are several A8 series that share the same
606230130Smav			 * pci id but works differently (EAPD).
607230130Smav			 */
608230130Smav			w = hdaa_widget_get(devinfo, 26);
609230130Smav			if (w != NULL && w->type ==
610230130Smav			    HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
611230130Smav			    (w->wclass.pin.config &
612230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
613230130Smav			    HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
614230130Smav				devinfo->quirks &=
615230130Smav				    ~HDAA_QUIRK_EAPDINV;
616230130Smav		}
617230130Smav		break;
618230130Smav	case HDA_CODEC_AD1981HD:
619230130Smav		/*
620230130Smav		 * This CODEC has very unusual design with several
621230130Smav		 * points inappropriate for the present parser.
622230130Smav		 */
623230130Smav		/* Disable recording from mono playback mix. */
624230130Smav		w = hdaa_widget_get(devinfo, 21);
625230130Smav		if (w != NULL)
626230130Smav			w->connsenable[3] = 0;
627230130Smav		/* Disable rear to front mic mixer, use separately. */
628230130Smav		w = hdaa_widget_get(devinfo, 31);
629230130Smav		if (w != NULL)
630230130Smav			w->enable = 0;
631230130Smav		/* Disable direct playback, use mixer. */
632230130Smav		w = hdaa_widget_get(devinfo, 5);
633230130Smav		if (w != NULL)
634230130Smav			w->connsenable[0] = 0;
635230130Smav		w = hdaa_widget_get(devinfo, 6);
636230130Smav		if (w != NULL)
637230130Smav			w->connsenable[0] = 0;
638230130Smav		w = hdaa_widget_get(devinfo, 9);
639230130Smav		if (w != NULL)
640230130Smav			w->connsenable[0] = 0;
641230130Smav		w = hdaa_widget_get(devinfo, 24);
642230130Smav		if (w != NULL)
643230130Smav			w->connsenable[0] = 0;
644230130Smav		break;
645242417Smav	case HDA_CODEC_ALC269:
646242417Smav		/*
647242417Smav		 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
648242417Smav		 * that mutes speaker if unused mixer at NID 15 is muted.
649242417Smav		 * Probably CODEC incorrectly reports internal connections.
650242417Smav		 * Hide that muter from the driver.  There are several CODECs
651242417Smav		 * sharing this ID and I have not enough information about
652242417Smav		 * them to implement more universal solution.
653242417Smav		 */
654242417Smav		if (subid == 0x84371043) {
655242417Smav			w = hdaa_widget_get(devinfo, 15);
656242417Smav			if (w != NULL)
657242417Smav				w->param.inamp_cap = 0;
658242417Smav		}
659242417Smav		break;
660230130Smav	case HDA_CODEC_CX20582:
661230130Smav	case HDA_CODEC_CX20583:
662230130Smav	case HDA_CODEC_CX20584:
663230130Smav	case HDA_CODEC_CX20585:
664230130Smav	case HDA_CODEC_CX20590:
665230130Smav		/*
666230130Smav		 * These codecs have extra connectivity on record side
667230130Smav		 * too reach for the present parser.
668230130Smav		 */
669230130Smav		w = hdaa_widget_get(devinfo, 20);
670230130Smav		if (w != NULL)
671230130Smav			w->connsenable[1] = 0;
672230130Smav		w = hdaa_widget_get(devinfo, 21);
673230130Smav		if (w != NULL)
674230130Smav			w->connsenable[1] = 0;
675230130Smav		w = hdaa_widget_get(devinfo, 22);
676230130Smav		if (w != NULL)
677230130Smav			w->connsenable[0] = 0;
678230130Smav		break;
679230130Smav	case HDA_CODEC_VT1708S_0:
680230130Smav	case HDA_CODEC_VT1708S_1:
681230130Smav	case HDA_CODEC_VT1708S_2:
682230130Smav	case HDA_CODEC_VT1708S_3:
683230130Smav	case HDA_CODEC_VT1708S_4:
684230130Smav	case HDA_CODEC_VT1708S_5:
685230130Smav	case HDA_CODEC_VT1708S_6:
686230130Smav	case HDA_CODEC_VT1708S_7:
687230130Smav		/*
688230130Smav		 * These codecs have hidden mic boost controls.
689230130Smav		 */
690230130Smav		w = hdaa_widget_get(devinfo, 26);
691230130Smav		if (w != NULL)
692230130Smav			w->param.inamp_cap =
693230130Smav			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
694230130Smav			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
695230130Smav			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
696230130Smav		w = hdaa_widget_get(devinfo, 30);
697230130Smav		if (w != NULL)
698230130Smav			w->param.inamp_cap =
699230130Smav			    (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
700230130Smav			    (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
701230130Smav			    (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
702230130Smav		break;
703230130Smav	}
704230130Smav}
705230130Smav
706285723Smavstatic uint32_t
707285723Smavhdaa_read_coef(device_t dev, nid_t nid, uint16_t idx)
708285723Smav{
709285723Smav
710285723Smav	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
711285723Smav	return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid)));
712285723Smav}
713285723Smav
714285723Smavstatic uint32_t
715285723Smavhdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val)
716285723Smav{
717285723Smav
718285723Smav	hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
719285723Smav	return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val)));
720285723Smav}
721285723Smav
722230130Smavvoid
723230130Smavhdaa_patch_direct(struct hdaa_devinfo *devinfo)
724230130Smav{
725230130Smav	device_t dev = devinfo->dev;
726230130Smav	uint32_t id, subid, val;
727230130Smav
728230130Smav	id = hdaa_codec_id(devinfo);
729242352Smav	subid = hdaa_card_id(devinfo);
730230130Smav
731230130Smav	switch (id) {
732230130Smav	case HDA_CODEC_VT1708S_0:
733230130Smav	case HDA_CODEC_VT1708S_1:
734230130Smav	case HDA_CODEC_VT1708S_2:
735230130Smav	case HDA_CODEC_VT1708S_3:
736230130Smav	case HDA_CODEC_VT1708S_4:
737230130Smav	case HDA_CODEC_VT1708S_5:
738230130Smav	case HDA_CODEC_VT1708S_6:
739230130Smav	case HDA_CODEC_VT1708S_7:
740230130Smav		/* Enable Mic Boost Volume controls. */
741230130Smav		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
742230130Smav		    0xf98, 0x01));
743241375Smav		/* Fall though */
744241375Smav	case HDA_CODEC_VT1818S:
745230130Smav		/* Don't bypass mixer. */
746230130Smav		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
747230130Smav		    0xf88, 0xc0));
748230130Smav		break;
749312366Syongari	case HDA_CODEC_ALC1150:
750312366Syongari		if (subid == 0xd9781462) {
751312366Syongari			/* Too low volume on MSI H170 GAMING M3. */
752312366Syongari			hdaa_write_coef(dev, 0x20, 0x07, 0x7cb);
753312366Syongari		}
754312366Syongari		break;
755230130Smav	}
756230130Smav	if (subid == APPLE_INTEL_MAC)
757230130Smav		hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
758230130Smav		    0x7e7, 0));
759230130Smav	if (id == HDA_CODEC_ALC269) {
760230532Smav		if (subid == 0x16e31043 || subid == 0x831a1043 ||
761230532Smav		    subid == 0x834a1043 || subid == 0x83981043 ||
762230532Smav		    subid == 0x83ce1043) {
763230130Smav			/*
764230130Smav			 * The ditital mics on some Asus laptops produce
765230130Smav			 * differential signals instead of expected stereo.
766230130Smav			 * That results in silence if downmix it to mono.
767230130Smav			 * To workaround, make codec to handle signal as mono.
768230130Smav			 */
769285723Smav			val = hdaa_read_coef(dev, 0x20, 0x07);
770285723Smav			hdaa_write_coef(dev, 0x20, 0x07, val|0x80);
771230130Smav		}
772285723Smav		if (subid == 0x15171043) {
773285723Smav			/* Increase output amp on ASUS UX31A by +5dB. */
774285723Smav			hdaa_write_coef(dev, 0x20, 0x12, 0x2800);
775285723Smav		}
776230130Smav	}
777230130Smav}
778