Deleted Added
full compact
hdaa_patches.c (268584) hdaa_patches.c (269152)
1/*-
2 * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
3 * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
4 * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29/*
30 * Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
31 */
32
33#ifdef HAVE_KERNEL_OPTION_HEADERS
34#include "opt_snd.h"
35#endif
36
37#include <dev/sound/pcm/sound.h>
38
39#include <sys/ctype.h>
40
41#include <dev/sound/pci/hda/hdac.h>
42#include <dev/sound/pci/hda/hdaa.h>
43#include <dev/sound/pci/hda/hda_reg.h>
44
1/*-
2 * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
3 * Copyright (c) 2006 Ariff Abdullah <ariff@FreeBSD.org>
4 * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29/*
30 * Intel High Definition Audio (Audio function quirks) driver for FreeBSD.
31 */
32
33#ifdef HAVE_KERNEL_OPTION_HEADERS
34#include "opt_snd.h"
35#endif
36
37#include <dev/sound/pcm/sound.h>
38
39#include <sys/ctype.h>
40
41#include <dev/sound/pci/hda/hdac.h>
42#include <dev/sound/pci/hda/hdaa.h>
43#include <dev/sound/pci/hda/hda_reg.h>
44
45SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa_patches.c 268584 2014-07-13 10:31:29Z markj $");
45SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa_patches.c 269152 2014-07-27 08:44:15Z adrian $");
46
47static const struct {
48 uint32_t model;
49 uint32_t id;
50 uint32_t subsystemid;
51 uint32_t set, unset;
52 uint32_t gpio;
53} hdac_quirks[] = {
54 /*
55 * XXX Force stereo quirk. Monoural recording / playback
56 * on few codecs (especially ALC880) seems broken or
57 * perhaps unsupported.
58 */
59 { HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_MATCH_ALL,
60 HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
61 0 },
62 { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, HDA_MATCH_ALL,
63 0, 0,
64 HDAA_GPIO_SET(0) },
65 { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, HDA_MATCH_ALL,
66 0, 0,
67 HDAA_GPIO_SET(0) },
68 { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
69 0, 0,
70 HDAA_GPIO_SET(0) },
71 { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
72 0, 0,
73 HDAA_GPIO_SET(0) },
74 { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
75 0, 0,
76 HDAA_GPIO_SET(0) },
77 { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
78 0, 0,
79 HDAA_GPIO_SET(0) },
80 { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
81 HDAA_QUIRK_EAPDINV, 0,
82 0 },
83 { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
84 HDAA_QUIRK_EAPDINV, 0,
85 0 },
86 { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
87 HDAA_QUIRK_OVREF, 0,
88 0 },
89 { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
90 HDAA_QUIRK_OVREF, 0,
91 0 },
92 /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, HDA_MATCH_ALL,
93 HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
94 0 },*/
95 { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
96 0, 0,
97 HDAA_GPIO_SET(1) },
98 { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
99 HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
100 0 },
101 { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
102 HDAA_QUIRK_EAPDINV, 0,
103 0 },
104 { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDA_MATCH_ALL,
105 HDAA_QUIRK_OVREF50, 0,
106 HDAA_GPIO_SET(0) },
107 { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDA_MATCH_ALL,
108 0, 0,
109 HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
110 { APPLE_MACBOOKAIR31, HDA_CODEC_CS4206, HDA_MATCH_ALL,
111 0, 0,
112 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
113 { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
114 0, 0,
115 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
116 { APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL,
117 0, 0,
118 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
119 { HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL,
120 0, 0,
121 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
122 { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
123 0, 0,
124 HDAA_GPIO_SET(0) },
125 { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
126 0, 0,
127 HDAA_GPIO_SET(2) },
128 { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
129 0, 0,
130 HDAA_GPIO_SET(0) },
131 { HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
132 HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
133 0 },
134 { HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
135 HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
136 0 },
137 { HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
138 0, HDAA_QUIRK_FORCESTEREO,
139 0 },
140 /* Mac Pro 1,1 requires ovref for proper volume level. */
141 { 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
142 0, HDAA_QUIRK_OVREF,
143 0 }
144};
145
146static void
147hdac_pin_patch(struct hdaa_widget *w)
148{
149 const char *patch = NULL;
150 uint32_t config, orig, id, subid;
151 nid_t nid = w->nid;
152
153 config = orig = w->wclass.pin.config;
154 id = hdaa_codec_id(w->devinfo);
155 subid = hdaa_card_id(w->devinfo);
156
157 /* XXX: Old patches require complete review.
158 * Now they may create more problem then solve due to
159 * incorrect associations.
160 */
161 if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) {
162 switch (nid) {
163 case 26:
164 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
165 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
166 break;
167 case 27:
168 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
169 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT;
170 break;
171 default:
172 break;
173 }
174 } else if (id == HDA_CODEC_ALC880 &&
175 (subid == CLEVO_D900T_SUBVENDOR ||
176 subid == ASUS_M5200_SUBVENDOR)) {
177 /*
178 * Super broken BIOS
179 */
180 switch (nid) {
181 case 24: /* MIC1 */
182 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
183 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
184 break;
185 case 25: /* XXX MIC2 */
186 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
187 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
188 break;
189 case 26: /* LINE1 */
190 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
191 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
192 break;
193 case 27: /* XXX LINE2 */
194 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
195 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
196 break;
197 case 28: /* CD */
198 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
199 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD;
200 break;
201 }
202 } else if (id == HDA_CODEC_ALC883 &&
203 (subid == MSI_MS034A_SUBVENDOR ||
204 HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) {
205 switch (nid) {
206 case 25:
207 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
208 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
209 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
210 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
211 break;
212 case 28:
213 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
214 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
215 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
216 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
217 break;
218 }
219 } else if (id == HDA_CODEC_CX20549 && subid ==
220 HP_V3000_SUBVENDOR) {
221 switch (nid) {
222 case 18:
223 config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
224 config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
225 break;
226 case 20:
227 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
228 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
229 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
230 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
231 break;
232 case 21:
233 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
234 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
235 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
236 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
237 break;
238 }
239 } else if (id == HDA_CODEC_CX20551 && subid ==
240 HP_DV5000_SUBVENDOR) {
241 switch (nid) {
242 case 20:
243 case 21:
244 config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
245 config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
246 break;
247 }
248 } else if (id == HDA_CODEC_ALC861 && subid ==
249 ASUS_W6F_SUBVENDOR) {
250 switch (nid) {
251 case 11:
252 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
253 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
254 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
255 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
256 break;
257 case 12:
258 case 14:
259 case 16:
260 case 31:
261 case 32:
262 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
263 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
264 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
265 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
266 break;
267 case 15:
268 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
269 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
270 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
271 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
272 break;
273 }
274 } else if (id == HDA_CODEC_ALC861 && subid ==
275 UNIWILL_9075_SUBVENDOR) {
276 switch (nid) {
277 case 15:
278 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
279 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
280 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
281 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
282 break;
283 }
284 }
285
286 /* New patches */
287 if (id == HDA_CODEC_AD1984A &&
288 subid == LENOVO_X300_SUBVENDOR) {
289 switch (nid) {
290 case 17: /* Headphones with redirection */
291 patch = "as=1 seq=15";
292 break;
293 case 20: /* Two mics together */
294 patch = "as=2 seq=15";
295 break;
296 }
297 } else if (id == HDA_CODEC_AD1986A &&
298 (subid == ASUS_M2NPVMX_SUBVENDOR ||
299 subid == ASUS_A8NVMCSM_SUBVENDOR ||
300 subid == ASUS_P5PL2_SUBVENDOR)) {
301 switch (nid) {
302 case 26: /* Headphones with redirection */
303 patch = "as=1 seq=15";
304 break;
305 case 28: /* 5.1 out => 2.0 out + 1 input */
306 patch = "device=Line-in as=8 seq=1";
307 break;
308 case 29: /* Can't use this as input, as the only available mic
309 * preamplifier is busy by front panel mic (nid 31).
310 * If you want to use this rear connector as mic input,
311 * you have to disable the front panel one. */
312 patch = "as=0";
313 break;
314 case 31: /* Lot of inputs configured with as=15 and unusable */
315 patch = "as=8 seq=3";
316 break;
317 case 32:
318 patch = "as=8 seq=4";
319 break;
320 case 34:
321 patch = "as=8 seq=5";
322 break;
323 case 36:
324 patch = "as=8 seq=6";
325 break;
326 }
327 } else if (id == HDA_CODEC_ALC260 &&
328 HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
329 switch (nid) {
330 case 16:
331 patch = "seq=15 device=Headphones";
332 break;
333 }
334 } else if (id == HDA_CODEC_ALC268) {
335 if (subid == ACER_T5320_SUBVENDOR) {
336 switch (nid) {
337 case 20: /* Headphones Jack */
338 patch = "as=1 seq=15";
339 break;
340 }
341 }
342 } else if (id == HDA_CODEC_CX20561 &&
343 subid == LENOVO_B450_SUBVENDOR) {
344 switch (nid) {
345 case 22:
346 patch = "as=1 seq=15";
347 break;
348 }
46
47static const struct {
48 uint32_t model;
49 uint32_t id;
50 uint32_t subsystemid;
51 uint32_t set, unset;
52 uint32_t gpio;
53} hdac_quirks[] = {
54 /*
55 * XXX Force stereo quirk. Monoural recording / playback
56 * on few codecs (especially ALC880) seems broken or
57 * perhaps unsupported.
58 */
59 { HDA_MATCH_ALL, HDA_MATCH_ALL, HDA_MATCH_ALL,
60 HDAA_QUIRK_FORCESTEREO | HDAA_QUIRK_IVREF, 0,
61 0 },
62 { ACER_ALL_SUBVENDOR, HDA_MATCH_ALL, HDA_MATCH_ALL,
63 0, 0,
64 HDAA_GPIO_SET(0) },
65 { ASUS_G2K_SUBVENDOR, HDA_CODEC_ALC660, HDA_MATCH_ALL,
66 0, 0,
67 HDAA_GPIO_SET(0) },
68 { ASUS_M5200_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
69 0, 0,
70 HDAA_GPIO_SET(0) },
71 { ASUS_A7M_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
72 0, 0,
73 HDAA_GPIO_SET(0) },
74 { ASUS_A7T_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
75 0, 0,
76 HDAA_GPIO_SET(0) },
77 { ASUS_W2J_SUBVENDOR, HDA_CODEC_ALC882, HDA_MATCH_ALL,
78 0, 0,
79 HDAA_GPIO_SET(0) },
80 { ASUS_U5F_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
81 HDAA_QUIRK_EAPDINV, 0,
82 0 },
83 { ASUS_A8X_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
84 HDAA_QUIRK_EAPDINV, 0,
85 0 },
86 { ASUS_F3JC_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
87 HDAA_QUIRK_OVREF, 0,
88 0 },
89 { UNIWILL_9075_SUBVENDOR, HDA_CODEC_ALC861, HDA_MATCH_ALL,
90 HDAA_QUIRK_OVREF, 0,
91 0 },
92 /*{ ASUS_M2N_SUBVENDOR, HDA_CODEC_AD1988, HDA_MATCH_ALL,
93 HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
94 0 },*/
95 { MEDION_MD95257_SUBVENDOR, HDA_CODEC_ALC880, HDA_MATCH_ALL,
96 0, 0,
97 HDAA_GPIO_SET(1) },
98 { LENOVO_3KN100_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
99 HDAA_QUIRK_EAPDINV | HDAA_QUIRK_SENSEINV, 0,
100 0 },
101 { SAMSUNG_Q1_SUBVENDOR, HDA_CODEC_AD1986A, HDA_MATCH_ALL,
102 HDAA_QUIRK_EAPDINV, 0,
103 0 },
104 { APPLE_MB3_SUBVENDOR, HDA_CODEC_ALC885, HDA_MATCH_ALL,
105 HDAA_QUIRK_OVREF50, 0,
106 HDAA_GPIO_SET(0) },
107 { APPLE_INTEL_MAC, HDA_CODEC_STAC9221, HDA_MATCH_ALL,
108 0, 0,
109 HDAA_GPIO_SET(0) | HDAA_GPIO_SET(1) },
110 { APPLE_MACBOOKAIR31, HDA_CODEC_CS4206, HDA_MATCH_ALL,
111 0, 0,
112 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
113 { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
114 0, 0,
115 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
116 { APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL,
117 0, 0,
118 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
119 { HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL,
120 0, 0,
121 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
122 { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
123 0, 0,
124 HDAA_GPIO_SET(0) },
125 { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
126 0, 0,
127 HDAA_GPIO_SET(2) },
128 { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
129 0, 0,
130 HDAA_GPIO_SET(0) },
131 { HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
132 HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
133 0 },
134 { HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
135 HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
136 0 },
137 { HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
138 0, HDAA_QUIRK_FORCESTEREO,
139 0 },
140 /* Mac Pro 1,1 requires ovref for proper volume level. */
141 { 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
142 0, HDAA_QUIRK_OVREF,
143 0 }
144};
145
146static void
147hdac_pin_patch(struct hdaa_widget *w)
148{
149 const char *patch = NULL;
150 uint32_t config, orig, id, subid;
151 nid_t nid = w->nid;
152
153 config = orig = w->wclass.pin.config;
154 id = hdaa_codec_id(w->devinfo);
155 subid = hdaa_card_id(w->devinfo);
156
157 /* XXX: Old patches require complete review.
158 * Now they may create more problem then solve due to
159 * incorrect associations.
160 */
161 if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) {
162 switch (nid) {
163 case 26:
164 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
165 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
166 break;
167 case 27:
168 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
169 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT;
170 break;
171 default:
172 break;
173 }
174 } else if (id == HDA_CODEC_ALC880 &&
175 (subid == CLEVO_D900T_SUBVENDOR ||
176 subid == ASUS_M5200_SUBVENDOR)) {
177 /*
178 * Super broken BIOS
179 */
180 switch (nid) {
181 case 24: /* MIC1 */
182 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
183 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
184 break;
185 case 25: /* XXX MIC2 */
186 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
187 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN;
188 break;
189 case 26: /* LINE1 */
190 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
191 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
192 break;
193 case 27: /* XXX LINE2 */
194 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
195 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN;
196 break;
197 case 28: /* CD */
198 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK;
199 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD;
200 break;
201 }
202 } else if (id == HDA_CODEC_ALC883 &&
203 (subid == MSI_MS034A_SUBVENDOR ||
204 HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) {
205 switch (nid) {
206 case 25:
207 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
208 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
209 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
210 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
211 break;
212 case 28:
213 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
214 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
215 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
216 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
217 break;
218 }
219 } else if (id == HDA_CODEC_CX20549 && subid ==
220 HP_V3000_SUBVENDOR) {
221 switch (nid) {
222 case 18:
223 config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
224 config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
225 break;
226 case 20:
227 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
228 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
229 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
230 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
231 break;
232 case 21:
233 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
234 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
235 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
236 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
237 break;
238 }
239 } else if (id == HDA_CODEC_CX20551 && subid ==
240 HP_DV5000_SUBVENDOR) {
241 switch (nid) {
242 case 20:
243 case 21:
244 config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
245 config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
246 break;
247 }
248 } else if (id == HDA_CODEC_ALC861 && subid ==
249 ASUS_W6F_SUBVENDOR) {
250 switch (nid) {
251 case 11:
252 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
253 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
254 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT |
255 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
256 break;
257 case 12:
258 case 14:
259 case 16:
260 case 31:
261 case 32:
262 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
263 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
264 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
265 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
266 break;
267 case 15:
268 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
269 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
270 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
271 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
272 break;
273 }
274 } else if (id == HDA_CODEC_ALC861 && subid ==
275 UNIWILL_9075_SUBVENDOR) {
276 switch (nid) {
277 case 15:
278 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
279 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
280 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT |
281 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK);
282 break;
283 }
284 }
285
286 /* New patches */
287 if (id == HDA_CODEC_AD1984A &&
288 subid == LENOVO_X300_SUBVENDOR) {
289 switch (nid) {
290 case 17: /* Headphones with redirection */
291 patch = "as=1 seq=15";
292 break;
293 case 20: /* Two mics together */
294 patch = "as=2 seq=15";
295 break;
296 }
297 } else if (id == HDA_CODEC_AD1986A &&
298 (subid == ASUS_M2NPVMX_SUBVENDOR ||
299 subid == ASUS_A8NVMCSM_SUBVENDOR ||
300 subid == ASUS_P5PL2_SUBVENDOR)) {
301 switch (nid) {
302 case 26: /* Headphones with redirection */
303 patch = "as=1 seq=15";
304 break;
305 case 28: /* 5.1 out => 2.0 out + 1 input */
306 patch = "device=Line-in as=8 seq=1";
307 break;
308 case 29: /* Can't use this as input, as the only available mic
309 * preamplifier is busy by front panel mic (nid 31).
310 * If you want to use this rear connector as mic input,
311 * you have to disable the front panel one. */
312 patch = "as=0";
313 break;
314 case 31: /* Lot of inputs configured with as=15 and unusable */
315 patch = "as=8 seq=3";
316 break;
317 case 32:
318 patch = "as=8 seq=4";
319 break;
320 case 34:
321 patch = "as=8 seq=5";
322 break;
323 case 36:
324 patch = "as=8 seq=6";
325 break;
326 }
327 } else if (id == HDA_CODEC_ALC260 &&
328 HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) {
329 switch (nid) {
330 case 16:
331 patch = "seq=15 device=Headphones";
332 break;
333 }
334 } else if (id == HDA_CODEC_ALC268) {
335 if (subid == ACER_T5320_SUBVENDOR) {
336 switch (nid) {
337 case 20: /* Headphones Jack */
338 patch = "as=1 seq=15";
339 break;
340 }
341 }
342 } else if (id == HDA_CODEC_CX20561 &&
343 subid == LENOVO_B450_SUBVENDOR) {
344 switch (nid) {
345 case 22:
346 patch = "as=1 seq=15";
347 break;
348 }
349 } else if (id == HDA_CODEC_CX20561 &&
350 subid == LENOVO_T400_SUBVENDOR) {
351 switch (nid) {
352 case 22:
353 patch = "as=1 seq=15";
354 break;
355 case 24:
356 patch = "as=2 seq=14";
357 break;
358 case 26:
359 patch = "as=1 seq=0";
360 break;
361 case 29:
362 patch = "as=2 seq=0";
363 break;
364 }
349 } else if (id == HDA_CODEC_CX20590 &&
350 (subid == LENOVO_X1_SUBVENDOR ||
351 subid == LENOVO_X220_SUBVENDOR ||
352 subid == LENOVO_T420_SUBVENDOR ||
353 subid == LENOVO_T520_SUBVENDOR ||
354 subid == LENOVO_G580_SUBVENDOR)) {
355 switch (nid) {
356 case 25:
357 patch = "as=1 seq=15";
358 break;
359 /*
360 * Group onboard mic and headphone mic
361 * together. Fixes onboard mic.
362 */
363 case 27:
364 patch = "as=2 seq=15";
365 break;
366 case 35:
367 patch = "as=2";
368 break;
369 }
370 } else if (id == HDA_CODEC_ALC269 &&
371 (subid == LENOVO_X1CRBN_SUBVENDOR ||
372 subid == LENOVO_T430_SUBVENDOR ||
373 subid == LENOVO_T430S_SUBVENDOR ||
374 subid == LENOVO_T530_SUBVENDOR)) {
375 switch (nid) {
376 case 21:
377 patch = "as=1 seq=15";
378 break;
379 }
380 } else if (id == HDA_CODEC_ALC269 &&
381 subid == ASUS_UX31A_SUBVENDOR) {
382 switch (nid) {
383 case 33:
384 patch = "as=1 seq=15";
385 break;
386 }
387 } else if (id == HDA_CODEC_ALC892 &&
388 subid == INTEL_DH87RL_SUBVENDOR) {
389 switch (nid) {
390 case 27:
391 patch = "as=1 seq=15";
392 break;
393 }
394 }
395
396 if (patch != NULL)
397 config = hdaa_widget_pin_patch(config, patch);
398 HDA_BOOTVERBOSE(
399 if (config != orig)
400 device_printf(w->devinfo->dev,
401 "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
402 nid, orig, config);
403 );
404 w->wclass.pin.config = config;
405}
406
407static void
408hdaa_widget_patch(struct hdaa_widget *w)
409{
410 struct hdaa_devinfo *devinfo = w->devinfo;
411 uint32_t orig;
412 nid_t beeper = -1;
413
414 orig = w->param.widget_cap;
415 /* On some codecs beeper is an input pin, but it is not recordable
416 alone. Also most of BIOSes does not declare beeper pin.
417 Change beeper pin node type to beeper to help parser. */
418 switch (hdaa_codec_id(devinfo)) {
419 case HDA_CODEC_AD1882:
420 case HDA_CODEC_AD1883:
421 case HDA_CODEC_AD1984:
422 case HDA_CODEC_AD1984A:
423 case HDA_CODEC_AD1984B:
424 case HDA_CODEC_AD1987:
425 case HDA_CODEC_AD1988:
426 case HDA_CODEC_AD1988B:
427 case HDA_CODEC_AD1989B:
428 beeper = 26;
429 break;
430 case HDA_CODEC_ALC260:
431 beeper = 23;
432 break;
433 }
434 if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
435 hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
436 beeper = 29;
437 if (w->nid == beeper) {
438 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
439 w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
440 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
441 w->waspin = 1;
442 }
443 /*
444 * Clear "digital" flag from digital mic input, as its signal then goes
445 * to "analog" mixer and this separation just limits functionaity.
446 */
447 if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
448 w->nid == 23)
449 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
450 HDA_BOOTVERBOSE(
451 if (w->param.widget_cap != orig) {
452 device_printf(w->devinfo->dev,
453 "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
454 w->nid, orig, w->param.widget_cap);
455 }
456 );
457
458 if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
459 hdac_pin_patch(w);
460}
461
462void
463hdaa_patch(struct hdaa_devinfo *devinfo)
464{
465 struct hdaa_widget *w;
466 uint32_t id, subid, subsystemid;
467 int i;
468
469 id = hdaa_codec_id(devinfo);
470 subid = hdaa_card_id(devinfo);
471 subsystemid = hda_get_subsystem_id(devinfo->dev);
472
473 /*
474 * Quirks
475 */
476 for (i = 0; i < nitems(hdac_quirks); i++) {
477 if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
478 HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
479 HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
480 continue;
481 devinfo->quirks |= hdac_quirks[i].set;
482 devinfo->quirks &= ~(hdac_quirks[i].unset);
483 devinfo->gpio = hdac_quirks[i].gpio;
484 }
485
486 /* Apply per-widget patch. */
487 for (i = devinfo->startnode; i < devinfo->endnode; i++) {
488 w = hdaa_widget_get(devinfo, i);
489 if (w == NULL)
490 continue;
491 hdaa_widget_patch(w);
492 }
493
494 switch (id) {
495 case HDA_CODEC_AD1983:
496 /*
497 * This CODEC has several possible usages, but none
498 * fit the parser best. Help parser to choose better.
499 */
500 /* Disable direct unmixed playback to get pcm volume. */
501 w = hdaa_widget_get(devinfo, 5);
502 if (w != NULL)
503 w->connsenable[0] = 0;
504 w = hdaa_widget_get(devinfo, 6);
505 if (w != NULL)
506 w->connsenable[0] = 0;
507 w = hdaa_widget_get(devinfo, 11);
508 if (w != NULL)
509 w->connsenable[0] = 0;
510 /* Disable mic and line selectors. */
511 w = hdaa_widget_get(devinfo, 12);
512 if (w != NULL)
513 w->connsenable[1] = 0;
514 w = hdaa_widget_get(devinfo, 13);
515 if (w != NULL)
516 w->connsenable[1] = 0;
517 /* Disable recording from mono playback mix. */
518 w = hdaa_widget_get(devinfo, 20);
519 if (w != NULL)
520 w->connsenable[3] = 0;
521 break;
522 case HDA_CODEC_AD1986A:
523 /*
524 * This CODEC has overcomplicated input mixing.
525 * Make some cleaning there.
526 */
527 /* Disable input mono mixer. Not needed and not supported. */
528 w = hdaa_widget_get(devinfo, 43);
529 if (w != NULL)
530 w->enable = 0;
531 /* Disable any with any input mixing mesh. Use separately. */
532 w = hdaa_widget_get(devinfo, 39);
533 if (w != NULL)
534 w->enable = 0;
535 w = hdaa_widget_get(devinfo, 40);
536 if (w != NULL)
537 w->enable = 0;
538 w = hdaa_widget_get(devinfo, 41);
539 if (w != NULL)
540 w->enable = 0;
541 w = hdaa_widget_get(devinfo, 42);
542 if (w != NULL)
543 w->enable = 0;
544 /* Disable duplicate mixer node connector. */
545 w = hdaa_widget_get(devinfo, 15);
546 if (w != NULL)
547 w->connsenable[3] = 0;
548 /* There is only one mic preamplifier, use it effectively. */
549 w = hdaa_widget_get(devinfo, 31);
550 if (w != NULL) {
551 if ((w->wclass.pin.config &
552 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
553 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
554 w = hdaa_widget_get(devinfo, 16);
555 if (w != NULL)
556 w->connsenable[2] = 0;
557 } else {
558 w = hdaa_widget_get(devinfo, 15);
559 if (w != NULL)
560 w->connsenable[0] = 0;
561 }
562 }
563 w = hdaa_widget_get(devinfo, 32);
564 if (w != NULL) {
565 if ((w->wclass.pin.config &
566 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
567 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
568 w = hdaa_widget_get(devinfo, 16);
569 if (w != NULL)
570 w->connsenable[0] = 0;
571 } else {
572 w = hdaa_widget_get(devinfo, 15);
573 if (w != NULL)
574 w->connsenable[1] = 0;
575 }
576 }
577
578 if (subid == ASUS_A8X_SUBVENDOR) {
579 /*
580 * This is just plain ridiculous.. There
581 * are several A8 series that share the same
582 * pci id but works differently (EAPD).
583 */
584 w = hdaa_widget_get(devinfo, 26);
585 if (w != NULL && w->type ==
586 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
587 (w->wclass.pin.config &
588 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
589 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
590 devinfo->quirks &=
591 ~HDAA_QUIRK_EAPDINV;
592 }
593 break;
594 case HDA_CODEC_AD1981HD:
595 /*
596 * This CODEC has very unusual design with several
597 * points inappropriate for the present parser.
598 */
599 /* Disable recording from mono playback mix. */
600 w = hdaa_widget_get(devinfo, 21);
601 if (w != NULL)
602 w->connsenable[3] = 0;
603 /* Disable rear to front mic mixer, use separately. */
604 w = hdaa_widget_get(devinfo, 31);
605 if (w != NULL)
606 w->enable = 0;
607 /* Disable direct playback, use mixer. */
608 w = hdaa_widget_get(devinfo, 5);
609 if (w != NULL)
610 w->connsenable[0] = 0;
611 w = hdaa_widget_get(devinfo, 6);
612 if (w != NULL)
613 w->connsenable[0] = 0;
614 w = hdaa_widget_get(devinfo, 9);
615 if (w != NULL)
616 w->connsenable[0] = 0;
617 w = hdaa_widget_get(devinfo, 24);
618 if (w != NULL)
619 w->connsenable[0] = 0;
620 break;
621 case HDA_CODEC_ALC269:
622 /*
623 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
624 * that mutes speaker if unused mixer at NID 15 is muted.
625 * Probably CODEC incorrectly reports internal connections.
626 * Hide that muter from the driver. There are several CODECs
627 * sharing this ID and I have not enough information about
628 * them to implement more universal solution.
629 */
630 if (subid == 0x84371043) {
631 w = hdaa_widget_get(devinfo, 15);
632 if (w != NULL)
633 w->param.inamp_cap = 0;
634 }
635 break;
636 case HDA_CODEC_CX20582:
637 case HDA_CODEC_CX20583:
638 case HDA_CODEC_CX20584:
639 case HDA_CODEC_CX20585:
640 case HDA_CODEC_CX20590:
641 /*
642 * These codecs have extra connectivity on record side
643 * too reach for the present parser.
644 */
645 w = hdaa_widget_get(devinfo, 20);
646 if (w != NULL)
647 w->connsenable[1] = 0;
648 w = hdaa_widget_get(devinfo, 21);
649 if (w != NULL)
650 w->connsenable[1] = 0;
651 w = hdaa_widget_get(devinfo, 22);
652 if (w != NULL)
653 w->connsenable[0] = 0;
654 break;
655 case HDA_CODEC_VT1708S_0:
656 case HDA_CODEC_VT1708S_1:
657 case HDA_CODEC_VT1708S_2:
658 case HDA_CODEC_VT1708S_3:
659 case HDA_CODEC_VT1708S_4:
660 case HDA_CODEC_VT1708S_5:
661 case HDA_CODEC_VT1708S_6:
662 case HDA_CODEC_VT1708S_7:
663 /*
664 * These codecs have hidden mic boost controls.
665 */
666 w = hdaa_widget_get(devinfo, 26);
667 if (w != NULL)
668 w->param.inamp_cap =
669 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
670 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
671 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
672 w = hdaa_widget_get(devinfo, 30);
673 if (w != NULL)
674 w->param.inamp_cap =
675 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
676 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
677 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
678 break;
679 }
680}
681
682void
683hdaa_patch_direct(struct hdaa_devinfo *devinfo)
684{
685 device_t dev = devinfo->dev;
686 uint32_t id, subid, val;
687
688 id = hdaa_codec_id(devinfo);
689 subid = hdaa_card_id(devinfo);
690
691 switch (id) {
692 case HDA_CODEC_VT1708S_0:
693 case HDA_CODEC_VT1708S_1:
694 case HDA_CODEC_VT1708S_2:
695 case HDA_CODEC_VT1708S_3:
696 case HDA_CODEC_VT1708S_4:
697 case HDA_CODEC_VT1708S_5:
698 case HDA_CODEC_VT1708S_6:
699 case HDA_CODEC_VT1708S_7:
700 /* Enable Mic Boost Volume controls. */
701 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
702 0xf98, 0x01));
703 /* Fall though */
704 case HDA_CODEC_VT1818S:
705 /* Don't bypass mixer. */
706 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
707 0xf88, 0xc0));
708 break;
709 }
710 if (subid == APPLE_INTEL_MAC)
711 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
712 0x7e7, 0));
713 if (id == HDA_CODEC_ALC269) {
714 if (subid == 0x16e31043 || subid == 0x831a1043 ||
715 subid == 0x834a1043 || subid == 0x83981043 ||
716 subid == 0x83ce1043) {
717 /*
718 * The ditital mics on some Asus laptops produce
719 * differential signals instead of expected stereo.
720 * That results in silence if downmix it to mono.
721 * To workaround, make codec to handle signal as mono.
722 */
723 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
724 val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20));
725 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
726 hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80));
727 }
728 }
729}
365 } else if (id == HDA_CODEC_CX20590 &&
366 (subid == LENOVO_X1_SUBVENDOR ||
367 subid == LENOVO_X220_SUBVENDOR ||
368 subid == LENOVO_T420_SUBVENDOR ||
369 subid == LENOVO_T520_SUBVENDOR ||
370 subid == LENOVO_G580_SUBVENDOR)) {
371 switch (nid) {
372 case 25:
373 patch = "as=1 seq=15";
374 break;
375 /*
376 * Group onboard mic and headphone mic
377 * together. Fixes onboard mic.
378 */
379 case 27:
380 patch = "as=2 seq=15";
381 break;
382 case 35:
383 patch = "as=2";
384 break;
385 }
386 } else if (id == HDA_CODEC_ALC269 &&
387 (subid == LENOVO_X1CRBN_SUBVENDOR ||
388 subid == LENOVO_T430_SUBVENDOR ||
389 subid == LENOVO_T430S_SUBVENDOR ||
390 subid == LENOVO_T530_SUBVENDOR)) {
391 switch (nid) {
392 case 21:
393 patch = "as=1 seq=15";
394 break;
395 }
396 } else if (id == HDA_CODEC_ALC269 &&
397 subid == ASUS_UX31A_SUBVENDOR) {
398 switch (nid) {
399 case 33:
400 patch = "as=1 seq=15";
401 break;
402 }
403 } else if (id == HDA_CODEC_ALC892 &&
404 subid == INTEL_DH87RL_SUBVENDOR) {
405 switch (nid) {
406 case 27:
407 patch = "as=1 seq=15";
408 break;
409 }
410 }
411
412 if (patch != NULL)
413 config = hdaa_widget_pin_patch(config, patch);
414 HDA_BOOTVERBOSE(
415 if (config != orig)
416 device_printf(w->devinfo->dev,
417 "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
418 nid, orig, config);
419 );
420 w->wclass.pin.config = config;
421}
422
423static void
424hdaa_widget_patch(struct hdaa_widget *w)
425{
426 struct hdaa_devinfo *devinfo = w->devinfo;
427 uint32_t orig;
428 nid_t beeper = -1;
429
430 orig = w->param.widget_cap;
431 /* On some codecs beeper is an input pin, but it is not recordable
432 alone. Also most of BIOSes does not declare beeper pin.
433 Change beeper pin node type to beeper to help parser. */
434 switch (hdaa_codec_id(devinfo)) {
435 case HDA_CODEC_AD1882:
436 case HDA_CODEC_AD1883:
437 case HDA_CODEC_AD1984:
438 case HDA_CODEC_AD1984A:
439 case HDA_CODEC_AD1984B:
440 case HDA_CODEC_AD1987:
441 case HDA_CODEC_AD1988:
442 case HDA_CODEC_AD1988B:
443 case HDA_CODEC_AD1989B:
444 beeper = 26;
445 break;
446 case HDA_CODEC_ALC260:
447 beeper = 23;
448 break;
449 }
450 if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
451 hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
452 beeper = 29;
453 if (w->nid == beeper) {
454 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
455 w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
456 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
457 w->waspin = 1;
458 }
459 /*
460 * Clear "digital" flag from digital mic input, as its signal then goes
461 * to "analog" mixer and this separation just limits functionaity.
462 */
463 if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
464 w->nid == 23)
465 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
466 HDA_BOOTVERBOSE(
467 if (w->param.widget_cap != orig) {
468 device_printf(w->devinfo->dev,
469 "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
470 w->nid, orig, w->param.widget_cap);
471 }
472 );
473
474 if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
475 hdac_pin_patch(w);
476}
477
478void
479hdaa_patch(struct hdaa_devinfo *devinfo)
480{
481 struct hdaa_widget *w;
482 uint32_t id, subid, subsystemid;
483 int i;
484
485 id = hdaa_codec_id(devinfo);
486 subid = hdaa_card_id(devinfo);
487 subsystemid = hda_get_subsystem_id(devinfo->dev);
488
489 /*
490 * Quirks
491 */
492 for (i = 0; i < nitems(hdac_quirks); i++) {
493 if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
494 HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
495 HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
496 continue;
497 devinfo->quirks |= hdac_quirks[i].set;
498 devinfo->quirks &= ~(hdac_quirks[i].unset);
499 devinfo->gpio = hdac_quirks[i].gpio;
500 }
501
502 /* Apply per-widget patch. */
503 for (i = devinfo->startnode; i < devinfo->endnode; i++) {
504 w = hdaa_widget_get(devinfo, i);
505 if (w == NULL)
506 continue;
507 hdaa_widget_patch(w);
508 }
509
510 switch (id) {
511 case HDA_CODEC_AD1983:
512 /*
513 * This CODEC has several possible usages, but none
514 * fit the parser best. Help parser to choose better.
515 */
516 /* Disable direct unmixed playback to get pcm volume. */
517 w = hdaa_widget_get(devinfo, 5);
518 if (w != NULL)
519 w->connsenable[0] = 0;
520 w = hdaa_widget_get(devinfo, 6);
521 if (w != NULL)
522 w->connsenable[0] = 0;
523 w = hdaa_widget_get(devinfo, 11);
524 if (w != NULL)
525 w->connsenable[0] = 0;
526 /* Disable mic and line selectors. */
527 w = hdaa_widget_get(devinfo, 12);
528 if (w != NULL)
529 w->connsenable[1] = 0;
530 w = hdaa_widget_get(devinfo, 13);
531 if (w != NULL)
532 w->connsenable[1] = 0;
533 /* Disable recording from mono playback mix. */
534 w = hdaa_widget_get(devinfo, 20);
535 if (w != NULL)
536 w->connsenable[3] = 0;
537 break;
538 case HDA_CODEC_AD1986A:
539 /*
540 * This CODEC has overcomplicated input mixing.
541 * Make some cleaning there.
542 */
543 /* Disable input mono mixer. Not needed and not supported. */
544 w = hdaa_widget_get(devinfo, 43);
545 if (w != NULL)
546 w->enable = 0;
547 /* Disable any with any input mixing mesh. Use separately. */
548 w = hdaa_widget_get(devinfo, 39);
549 if (w != NULL)
550 w->enable = 0;
551 w = hdaa_widget_get(devinfo, 40);
552 if (w != NULL)
553 w->enable = 0;
554 w = hdaa_widget_get(devinfo, 41);
555 if (w != NULL)
556 w->enable = 0;
557 w = hdaa_widget_get(devinfo, 42);
558 if (w != NULL)
559 w->enable = 0;
560 /* Disable duplicate mixer node connector. */
561 w = hdaa_widget_get(devinfo, 15);
562 if (w != NULL)
563 w->connsenable[3] = 0;
564 /* There is only one mic preamplifier, use it effectively. */
565 w = hdaa_widget_get(devinfo, 31);
566 if (w != NULL) {
567 if ((w->wclass.pin.config &
568 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
569 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
570 w = hdaa_widget_get(devinfo, 16);
571 if (w != NULL)
572 w->connsenable[2] = 0;
573 } else {
574 w = hdaa_widget_get(devinfo, 15);
575 if (w != NULL)
576 w->connsenable[0] = 0;
577 }
578 }
579 w = hdaa_widget_get(devinfo, 32);
580 if (w != NULL) {
581 if ((w->wclass.pin.config &
582 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
583 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
584 w = hdaa_widget_get(devinfo, 16);
585 if (w != NULL)
586 w->connsenable[0] = 0;
587 } else {
588 w = hdaa_widget_get(devinfo, 15);
589 if (w != NULL)
590 w->connsenable[1] = 0;
591 }
592 }
593
594 if (subid == ASUS_A8X_SUBVENDOR) {
595 /*
596 * This is just plain ridiculous.. There
597 * are several A8 series that share the same
598 * pci id but works differently (EAPD).
599 */
600 w = hdaa_widget_get(devinfo, 26);
601 if (w != NULL && w->type ==
602 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
603 (w->wclass.pin.config &
604 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
605 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
606 devinfo->quirks &=
607 ~HDAA_QUIRK_EAPDINV;
608 }
609 break;
610 case HDA_CODEC_AD1981HD:
611 /*
612 * This CODEC has very unusual design with several
613 * points inappropriate for the present parser.
614 */
615 /* Disable recording from mono playback mix. */
616 w = hdaa_widget_get(devinfo, 21);
617 if (w != NULL)
618 w->connsenable[3] = 0;
619 /* Disable rear to front mic mixer, use separately. */
620 w = hdaa_widget_get(devinfo, 31);
621 if (w != NULL)
622 w->enable = 0;
623 /* Disable direct playback, use mixer. */
624 w = hdaa_widget_get(devinfo, 5);
625 if (w != NULL)
626 w->connsenable[0] = 0;
627 w = hdaa_widget_get(devinfo, 6);
628 if (w != NULL)
629 w->connsenable[0] = 0;
630 w = hdaa_widget_get(devinfo, 9);
631 if (w != NULL)
632 w->connsenable[0] = 0;
633 w = hdaa_widget_get(devinfo, 24);
634 if (w != NULL)
635 w->connsenable[0] = 0;
636 break;
637 case HDA_CODEC_ALC269:
638 /*
639 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
640 * that mutes speaker if unused mixer at NID 15 is muted.
641 * Probably CODEC incorrectly reports internal connections.
642 * Hide that muter from the driver. There are several CODECs
643 * sharing this ID and I have not enough information about
644 * them to implement more universal solution.
645 */
646 if (subid == 0x84371043) {
647 w = hdaa_widget_get(devinfo, 15);
648 if (w != NULL)
649 w->param.inamp_cap = 0;
650 }
651 break;
652 case HDA_CODEC_CX20582:
653 case HDA_CODEC_CX20583:
654 case HDA_CODEC_CX20584:
655 case HDA_CODEC_CX20585:
656 case HDA_CODEC_CX20590:
657 /*
658 * These codecs have extra connectivity on record side
659 * too reach for the present parser.
660 */
661 w = hdaa_widget_get(devinfo, 20);
662 if (w != NULL)
663 w->connsenable[1] = 0;
664 w = hdaa_widget_get(devinfo, 21);
665 if (w != NULL)
666 w->connsenable[1] = 0;
667 w = hdaa_widget_get(devinfo, 22);
668 if (w != NULL)
669 w->connsenable[0] = 0;
670 break;
671 case HDA_CODEC_VT1708S_0:
672 case HDA_CODEC_VT1708S_1:
673 case HDA_CODEC_VT1708S_2:
674 case HDA_CODEC_VT1708S_3:
675 case HDA_CODEC_VT1708S_4:
676 case HDA_CODEC_VT1708S_5:
677 case HDA_CODEC_VT1708S_6:
678 case HDA_CODEC_VT1708S_7:
679 /*
680 * These codecs have hidden mic boost controls.
681 */
682 w = hdaa_widget_get(devinfo, 26);
683 if (w != NULL)
684 w->param.inamp_cap =
685 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
686 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
687 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
688 w = hdaa_widget_get(devinfo, 30);
689 if (w != NULL)
690 w->param.inamp_cap =
691 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
692 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
693 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
694 break;
695 }
696}
697
698void
699hdaa_patch_direct(struct hdaa_devinfo *devinfo)
700{
701 device_t dev = devinfo->dev;
702 uint32_t id, subid, val;
703
704 id = hdaa_codec_id(devinfo);
705 subid = hdaa_card_id(devinfo);
706
707 switch (id) {
708 case HDA_CODEC_VT1708S_0:
709 case HDA_CODEC_VT1708S_1:
710 case HDA_CODEC_VT1708S_2:
711 case HDA_CODEC_VT1708S_3:
712 case HDA_CODEC_VT1708S_4:
713 case HDA_CODEC_VT1708S_5:
714 case HDA_CODEC_VT1708S_6:
715 case HDA_CODEC_VT1708S_7:
716 /* Enable Mic Boost Volume controls. */
717 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
718 0xf98, 0x01));
719 /* Fall though */
720 case HDA_CODEC_VT1818S:
721 /* Don't bypass mixer. */
722 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
723 0xf88, 0xc0));
724 break;
725 }
726 if (subid == APPLE_INTEL_MAC)
727 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
728 0x7e7, 0));
729 if (id == HDA_CODEC_ALC269) {
730 if (subid == 0x16e31043 || subid == 0x831a1043 ||
731 subid == 0x834a1043 || subid == 0x83981043 ||
732 subid == 0x83ce1043) {
733 /*
734 * The ditital mics on some Asus laptops produce
735 * differential signals instead of expected stereo.
736 * That results in silence if downmix it to mono.
737 * To workaround, make codec to handle signal as mono.
738 */
739 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
740 val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20));
741 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07));
742 hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80));
743 }
744 }
745}