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