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 { HDA_MATCH_ALL, HDA_CODEC_CS4208, APPLE_MACBOOKAIR61,
117 0, 0,
118 HDAA_GPIO_SET(0) },
119 { HDA_MATCH_ALL, HDA_CODEC_CS4208, APPLE_MACBOOKAIR62,
120 0, 0,
121 HDAA_GPIO_SET(0) },
122 { APPLE_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL,
123 0, 0,
124 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
125 { APPLE_MACBOOKPRO71, HDA_CODEC_CS4206, HDA_MATCH_ALL,
126 0, 0,
127 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
128 { HDA_INTEL_MACBOOKPRO92, HDA_CODEC_CS4206, HDA_MATCH_ALL,
129 0, 0,
130 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) },
131 { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
132 0, 0,
133 HDAA_GPIO_SET(0) },
134 { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL,
135 0, 0,
136 HDAA_GPIO_SET(2) },
137 { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL,
138 0, 0,
139 HDAA_GPIO_SET(0) },
140 { HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL,
141 HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
142 0 },
143 { HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL,
144 HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100,
145 0 },
146 { HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL,
147 0, HDAA_QUIRK_FORCESTEREO,
148 0 },
149 /* Mac Pro 1,1 requires ovref for proper volume level. */
150 { 0x00000000, HDA_CODEC_ALC885, 0x106b0c00,
151 0, HDAA_QUIRK_OVREF,
152 0 }
153 };
154
155 static struct pin_patch_t *
match_pin_patches(int vendor_id,int vendor_subid)156 match_pin_patches(int vendor_id, int vendor_subid)
157 {
158 for (int ci = 0; ci < nitems(realtek_model_pin_patches); ci++) {
159 struct hdaa_model_pin_patch_t *p = &realtek_model_pin_patches[ci];
160 if (vendor_id != p->id)
161 continue;
162 for (struct model_pin_patch_t *pp = p->patches; pp->models; pp++) {
163 for (struct pin_machine_model_t *model = pp->models; model->id != 0; model++) {
164 if (HDA_DEV_MATCH(model->id, vendor_subid))
165 return (pp->pin_patches);
166 }
167 }
168 }
169
170 return (0);
171 }
172
173 static void
hdac_pin_patch(struct hdaa_widget * w)174 hdac_pin_patch(struct hdaa_widget *w)
175 {
176 const char *patch_str = NULL;
177 uint32_t config, orig, id, subid;
178 nid_t nid = w->nid;
179
180 config = orig = w->wclass.pin.config;
181 id = hdaa_codec_id(w->devinfo);
182 subid = hdaa_card_id(w->devinfo);
183
184 if (id == HDA_CODEC_ALC883 && HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid)) {
185 switch (nid) {
186 case 25:
187 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
188 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
189 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN |
190 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
191 break;
192 case 28:
193 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK |
194 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK);
195 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD |
196 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED);
197 break;
198 }
199 } else if (id == HDA_CODEC_CX20549 && subid ==
200 HP_V3000_SUBVENDOR) {
201 switch (nid) {
202 case 18:
203 config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
204 config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
205 break;
206 case 20:
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 21:
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_CX20551 && subid ==
220 HP_DV5000_SUBVENDOR) {
221 switch (nid) {
222 case 20:
223 case 21:
224 config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK;
225 config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE;
226 break;
227 }
228 }
229
230 /* New patches */
231 if (id == HDA_CODEC_AD1984A &&
232 subid == LENOVO_X300_SUBVENDOR) {
233 switch (nid) {
234 case 17: /* Headphones with redirection */
235 patch_str = "as=1 seq=15";
236 break;
237 case 20: /* Two mics together */
238 patch_str = "as=2 seq=15";
239 break;
240 }
241 } else if (id == HDA_CODEC_AD1986A &&
242 (subid == ASUS_M2NPVMX_SUBVENDOR ||
243 subid == ASUS_A8NVMCSM_SUBVENDOR ||
244 subid == ASUS_P5PL2_SUBVENDOR)) {
245 switch (nid) {
246 case 26: /* Headphones with redirection */
247 patch_str = "as=1 seq=15";
248 break;
249 case 28: /* 5.1 out => 2.0 out + 1 input */
250 patch_str = "device=Line-in as=8 seq=1";
251 break;
252 case 29: /* Can't use this as input, as the only available mic
253 * preamplifier is busy by front panel mic (nid 31).
254 * If you want to use this rear connector as mic input,
255 * you have to disable the front panel one. */
256 patch_str = "as=0";
257 break;
258 case 31: /* Lot of inputs configured with as=15 and unusable */
259 patch_str = "as=8 seq=3";
260 break;
261 case 32:
262 patch_str = "as=8 seq=4";
263 break;
264 case 34:
265 patch_str = "as=8 seq=5";
266 break;
267 case 36:
268 patch_str = "as=8 seq=6";
269 break;
270 }
271 } else if (id == HDA_CODEC_CX20561 &&
272 subid == LENOVO_B450_SUBVENDOR) {
273 switch (nid) {
274 case 22:
275 patch_str = "as=1 seq=15";
276 break;
277 }
278 } else if (id == HDA_CODEC_CX20561 &&
279 subid == LENOVO_T400_SUBVENDOR) {
280 switch (nid) {
281 case 22:
282 patch_str = "as=1 seq=15";
283 break;
284 case 26:
285 patch_str = "as=1 seq=0";
286 break;
287 }
288 } else if (id == HDA_CODEC_CX20590 &&
289 (subid == LENOVO_X1_SUBVENDOR ||
290 subid == LENOVO_X220_SUBVENDOR ||
291 subid == LENOVO_T420_SUBVENDOR ||
292 subid == LENOVO_T520_SUBVENDOR ||
293 subid == LENOVO_G580_SUBVENDOR)) {
294 switch (nid) {
295 case 25:
296 patch_str = "as=1 seq=15";
297 break;
298 /*
299 * Group onboard mic and headphone mic
300 * together. Fixes onboard mic.
301 */
302 case 27:
303 patch_str = "as=2 seq=15";
304 break;
305 case 35:
306 patch_str = "as=2";
307 break;
308 }
309 } else if (id == HDA_CODEC_ALC235 && subid == ASUS_GL553VE_SUBVENDOR) {
310 switch (nid) {
311 case 33:
312 patch_str = "as=1 seq=15";
313 break;
314 }
315 } else if (id == HDA_CODEC_ALC256 && (subid == DELL_I7577_SUBVENDOR ||
316 subid == DELL_L7480_SUBVENDOR)) {
317 switch (nid) {
318 case 20:
319 patch_str = "as=1 seq=0";
320 break;
321 case 33:
322 patch_str = "as=1 seq=15";
323 break;
324 }
325 } else if (id == HDA_CODEC_ALC257 &&
326 (subid == LENOVO_L5AMD_SUBVENDOR ||
327 subid == LENOVO_L5INTEL_SUBVENDOR ||
328 subid == LENOVO_IDEAPAD3_SUBVENDOR)) {
329 switch (nid) {
330 case 20:
331 patch_str = "as=1 seq=0";
332 break;
333 case 33:
334 patch_str = "as=1 seq=15";
335 break;
336 }
337 } else if (id == HDA_CODEC_IDT92HD95B &&
338 (subid == FRAMEWORK_LAPTOP_0001_SUBVENDOR ||
339 subid == FRAMEWORK_LAPTOP_0002_SUBVENDOR ||
340 subid == FRAMEWORK_LAPTOP_0003_SUBVENDOR)) {
341 switch (nid) {
342 case 10:
343 patch_str = "as=1 seq=15 color=Black loc=Left";
344 break;
345 case 11:
346 patch_str = "as=3 seq=15 color=Black loc=Left";
347 break;
348 }
349 } else if (id == HDA_CODEC_ALC295 &&
350 subid == FRAMEWORK_LAPTOP_0005_SUBVENDOR) {
351 switch (nid) {
352 case 20:
353 /*
354 * This pin is a duplicate of pin 23 (both as=1 seq=0),
355 * which ends up in the driver disabling the
356 * association altogether. Since sound quality from pin
357 * 23 seems to be better, configure this one as a back
358 * speaker.
359 */
360 patch_str = "as=1 seq=2";
361 break;
362 }
363 } else if (id == HDA_CODEC_ALC295 &&
364 subid == FRAMEWORK_LAPTOP_0006_SUBVENDOR) {
365 switch (nid) {
366 case 33:
367 patch_str = "as=1 seq=15 color=Black loc=Left";
368 break;
369 }
370 } else if (id == HDA_CODEC_ALC230 &&
371 subid == LENOVO_IDEAPAD330_SUBVENDOR) {
372 switch (nid) {
373 case 20:
374 patch_str = "as=1 seq=0 device=Speaker";
375 break;
376 case 33:
377 patch_str = "as=1 seq=15 device=Headphones";
378 break;
379 }
380 } else if (id == HDA_CODEC_ALC269 &&
381 subid == LENOVO_X230_SUBVENDOR) {
382 switch (nid) {
383 case 21:
384 patch_str = "as=1 seq=15";
385 break;
386 case 24:
387 patch_str = "as=4 seq=15";
388 break;
389 }
390 } else if (id == HDA_CODEC_ALC294 &&
391 subid == ASUS_UX331_SUBVENDOR) {
392 switch (nid) {
393 case 25:
394 /* XXX You are not expected to understand this. */
395 config = 0x01a1103c;
396 break;
397 case 33:
398 patch_str = "as=1 seq=15";
399 break;
400 }
401 } else {
402 /*
403 * loop over hdaa_model_pin_patch
404 */
405 struct pin_patch_t *pin_patches = NULL;
406
407 pin_patches = match_pin_patches(id, subid);
408
409 if (pin_patches != NULL) {
410 for (struct pin_patch_t *patch = pin_patches; patch->type; patch++) {
411 if (nid == patch->nid) {
412 switch (patch->type) {
413 case PIN_PATCH_TYPE_STRING:
414 patch_str = patch->patch.string;
415 break;
416 case PIN_PATCH_TYPE_MASK:
417 config &= ~patch->patch.mask[0];
418 config |= patch->patch.mask[1];
419 break;
420 case PIN_PATCH_TYPE_OVERRIDE:
421 config = patch->patch.override;
422 break;
423 default:
424 /* should panic hard */
425 break;
426 }
427 break;
428 }
429 }
430 }
431 }
432
433 if (patch_str != NULL)
434 config = hdaa_widget_pin_patch(config, patch_str);
435 HDA_BOOTVERBOSE(
436 if (config != orig)
437 device_printf(w->devinfo->dev,
438 "Patching pin config nid=%u 0x%08x -> 0x%08x\n",
439 nid, orig, config);
440 );
441 w->wclass.pin.config = config;
442 }
443
444 static void
hdaa_widget_patch(struct hdaa_widget * w)445 hdaa_widget_patch(struct hdaa_widget *w)
446 {
447 struct hdaa_devinfo *devinfo = w->devinfo;
448 uint32_t orig;
449 nid_t beeper = -1;
450
451 orig = w->param.widget_cap;
452 /* On some codecs beeper is an input pin, but it is not recordable
453 alone. Also most of BIOSes does not declare beeper pin.
454 Change beeper pin node type to beeper to help parser. */
455 switch (hdaa_codec_id(devinfo)) {
456 case HDA_CODEC_AD1882:
457 case HDA_CODEC_AD1883:
458 case HDA_CODEC_AD1984:
459 case HDA_CODEC_AD1984A:
460 case HDA_CODEC_AD1984B:
461 case HDA_CODEC_AD1987:
462 case HDA_CODEC_AD1988:
463 case HDA_CODEC_AD1988B:
464 case HDA_CODEC_AD1989B:
465 beeper = 26;
466 break;
467 case HDA_CODEC_ALC260:
468 beeper = 23;
469 break;
470 }
471 if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID &&
472 hdaa_codec_id(devinfo) != HDA_CODEC_ALC260)
473 beeper = 29;
474 if (w->nid == beeper) {
475 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK;
476 w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET <<
477 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT;
478 w->waspin = 1;
479 }
480 /*
481 * Clear "digital" flag from digital mic input, as its signal then goes
482 * to "analog" mixer and this separation just limits functionaity.
483 */
484 if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A &&
485 w->nid == 23)
486 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK;
487 HDA_BOOTVERBOSE(
488 if (w->param.widget_cap != orig) {
489 device_printf(w->devinfo->dev,
490 "Patching widget caps nid=%u 0x%08x -> 0x%08x\n",
491 w->nid, orig, w->param.widget_cap);
492 }
493 );
494
495 if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX)
496 hdac_pin_patch(w);
497 }
498
499 void
hdaa_patch(struct hdaa_devinfo * devinfo)500 hdaa_patch(struct hdaa_devinfo *devinfo)
501 {
502 struct hdaa_widget *w;
503 uint32_t id, subid, subsystemid;
504 int i;
505
506 id = hdaa_codec_id(devinfo);
507 subid = hdaa_card_id(devinfo);
508 subsystemid = hda_get_subsystem_id(devinfo->dev);
509
510 /*
511 * Quirks
512 */
513 for (i = 0; i < nitems(hdac_quirks); i++) {
514 if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) &&
515 HDA_DEV_MATCH(hdac_quirks[i].id, id) &&
516 HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid)))
517 continue;
518 devinfo->quirks |= hdac_quirks[i].set;
519 devinfo->quirks &= ~(hdac_quirks[i].unset);
520 devinfo->gpio = hdac_quirks[i].gpio;
521 }
522
523 /* Apply per-widget patch. */
524 for (i = devinfo->startnode; i < devinfo->endnode; i++) {
525 w = hdaa_widget_get(devinfo, i);
526 if (w == NULL)
527 continue;
528 hdaa_widget_patch(w);
529 }
530
531 switch (id) {
532 case HDA_CODEC_AD1983:
533 /*
534 * This CODEC has several possible usages, but none
535 * fit the parser best. Help parser to choose better.
536 */
537 /* Disable direct unmixed playback to get pcm volume. */
538 w = hdaa_widget_get(devinfo, 5);
539 if (w != NULL)
540 w->connsenable[0] = 0;
541 w = hdaa_widget_get(devinfo, 6);
542 if (w != NULL)
543 w->connsenable[0] = 0;
544 w = hdaa_widget_get(devinfo, 11);
545 if (w != NULL)
546 w->connsenable[0] = 0;
547 /* Disable mic and line selectors. */
548 w = hdaa_widget_get(devinfo, 12);
549 if (w != NULL)
550 w->connsenable[1] = 0;
551 w = hdaa_widget_get(devinfo, 13);
552 if (w != NULL)
553 w->connsenable[1] = 0;
554 /* Disable recording from mono playback mix. */
555 w = hdaa_widget_get(devinfo, 20);
556 if (w != NULL)
557 w->connsenable[3] = 0;
558 break;
559 case HDA_CODEC_AD1986A:
560 /*
561 * This CODEC has overcomplicated input mixing.
562 * Make some cleaning there.
563 */
564 /* Disable input mono mixer. Not needed and not supported. */
565 w = hdaa_widget_get(devinfo, 43);
566 if (w != NULL)
567 w->enable = 0;
568 /* Disable any with any input mixing mesh. Use separately. */
569 w = hdaa_widget_get(devinfo, 39);
570 if (w != NULL)
571 w->enable = 0;
572 w = hdaa_widget_get(devinfo, 40);
573 if (w != NULL)
574 w->enable = 0;
575 w = hdaa_widget_get(devinfo, 41);
576 if (w != NULL)
577 w->enable = 0;
578 w = hdaa_widget_get(devinfo, 42);
579 if (w != NULL)
580 w->enable = 0;
581 /* Disable duplicate mixer node connector. */
582 w = hdaa_widget_get(devinfo, 15);
583 if (w != NULL)
584 w->connsenable[3] = 0;
585 /* There is only one mic preamplifier, use it effectively. */
586 w = hdaa_widget_get(devinfo, 31);
587 if (w != NULL) {
588 if ((w->wclass.pin.config &
589 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
590 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
591 w = hdaa_widget_get(devinfo, 16);
592 if (w != NULL)
593 w->connsenable[2] = 0;
594 } else {
595 w = hdaa_widget_get(devinfo, 15);
596 if (w != NULL)
597 w->connsenable[0] = 0;
598 }
599 }
600 w = hdaa_widget_get(devinfo, 32);
601 if (w != NULL) {
602 if ((w->wclass.pin.config &
603 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
604 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
605 w = hdaa_widget_get(devinfo, 16);
606 if (w != NULL)
607 w->connsenable[0] = 0;
608 } else {
609 w = hdaa_widget_get(devinfo, 15);
610 if (w != NULL)
611 w->connsenable[1] = 0;
612 }
613 }
614
615 if (subid == ASUS_A8X_SUBVENDOR) {
616 /*
617 * This is just plain ridiculous.. There
618 * are several A8 series that share the same
619 * pci id but works differently (EAPD).
620 */
621 w = hdaa_widget_get(devinfo, 26);
622 if (w != NULL && w->type ==
623 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX &&
624 (w->wclass.pin.config &
625 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) !=
626 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE)
627 devinfo->quirks &=
628 ~HDAA_QUIRK_EAPDINV;
629 }
630 break;
631 case HDA_CODEC_AD1981HD:
632 /*
633 * This CODEC has very unusual design with several
634 * points inappropriate for the present parser.
635 */
636 /* Disable recording from mono playback mix. */
637 w = hdaa_widget_get(devinfo, 21);
638 if (w != NULL)
639 w->connsenable[3] = 0;
640 /* Disable rear to front mic mixer, use separately. */
641 w = hdaa_widget_get(devinfo, 31);
642 if (w != NULL)
643 w->enable = 0;
644 /* Disable direct playback, use mixer. */
645 w = hdaa_widget_get(devinfo, 5);
646 if (w != NULL)
647 w->connsenable[0] = 0;
648 w = hdaa_widget_get(devinfo, 6);
649 if (w != NULL)
650 w->connsenable[0] = 0;
651 w = hdaa_widget_get(devinfo, 9);
652 if (w != NULL)
653 w->connsenable[0] = 0;
654 w = hdaa_widget_get(devinfo, 24);
655 if (w != NULL)
656 w->connsenable[0] = 0;
657 break;
658 case HDA_CODEC_ALC269:
659 /*
660 * ASUS EeePC 1001px has strange variant of ALC269 CODEC,
661 * that mutes speaker if unused mixer at NID 15 is muted.
662 * Probably CODEC incorrectly reports internal connections.
663 * Hide that muter from the driver. There are several CODECs
664 * sharing this ID and I have not enough information about
665 * them to implement more universal solution.
666 */
667 if (subid == 0x84371043) {
668 w = hdaa_widget_get(devinfo, 15);
669 if (w != NULL)
670 w->param.inamp_cap = 0;
671 }
672 break;
673 case HDA_CODEC_CX20582:
674 case HDA_CODEC_CX20583:
675 case HDA_CODEC_CX20584:
676 case HDA_CODEC_CX20585:
677 case HDA_CODEC_CX20590:
678 /*
679 * These codecs have extra connectivity on record side
680 * too reach for the present parser.
681 */
682 w = hdaa_widget_get(devinfo, 20);
683 if (w != NULL)
684 w->connsenable[1] = 0;
685 w = hdaa_widget_get(devinfo, 21);
686 if (w != NULL)
687 w->connsenable[1] = 0;
688 w = hdaa_widget_get(devinfo, 22);
689 if (w != NULL)
690 w->connsenable[0] = 0;
691 break;
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 /*
701 * These codecs have hidden mic boost controls.
702 */
703 w = hdaa_widget_get(devinfo, 26);
704 if (w != NULL)
705 w->param.inamp_cap =
706 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
707 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
708 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
709 w = hdaa_widget_get(devinfo, 30);
710 if (w != NULL)
711 w->param.inamp_cap =
712 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) |
713 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) |
714 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT);
715 break;
716 }
717 }
718
719 static uint32_t
hdaa_read_coef(device_t dev,nid_t nid,uint16_t idx)720 hdaa_read_coef(device_t dev, nid_t nid, uint16_t idx)
721 {
722
723 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
724 return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid)));
725 }
726
727 static uint32_t
hdaa_write_coef(device_t dev,nid_t nid,uint16_t idx,uint16_t val)728 hdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val)
729 {
730
731 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx));
732 return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val)));
733 }
734
735 void
hdaa_patch_direct(struct hdaa_devinfo * devinfo)736 hdaa_patch_direct(struct hdaa_devinfo *devinfo)
737 {
738 device_t dev = devinfo->dev;
739 uint32_t id, subid, val;
740
741 id = hdaa_codec_id(devinfo);
742 subid = hdaa_card_id(devinfo);
743
744 switch (id) {
745 case HDA_CODEC_VT1708S_0:
746 case HDA_CODEC_VT1708S_1:
747 case HDA_CODEC_VT1708S_2:
748 case HDA_CODEC_VT1708S_3:
749 case HDA_CODEC_VT1708S_4:
750 case HDA_CODEC_VT1708S_5:
751 case HDA_CODEC_VT1708S_6:
752 case HDA_CODEC_VT1708S_7:
753 /* Enable Mic Boost Volume controls. */
754 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
755 0xf98, 0x01));
756 /* Fall though */
757 case HDA_CODEC_VT1818S:
758 /* Don't bypass mixer. */
759 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
760 0xf88, 0xc0));
761 break;
762 case HDA_CODEC_ALC1150:
763 if (subid == 0xd9781462) {
764 /* Too low volume on MSI H170 GAMING M3. */
765 hdaa_write_coef(dev, 0x20, 0x07, 0x7cb);
766 }
767 break;
768 }
769 if (id == HDA_CODEC_ALC255 || id == HDA_CODEC_ALC256) {
770 val = hdaa_read_coef(dev, 0x20, 0x46);
771 hdaa_write_coef(dev, 0x20, 0x46, val|0x3000);
772 }
773 if (subid == APPLE_INTEL_MAC)
774 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid,
775 0x7e7, 0));
776 if (id == HDA_CODEC_ALC269) {
777 if (subid == 0x16e31043 || subid == 0x831a1043 ||
778 subid == 0x834a1043 || subid == 0x83981043 ||
779 subid == 0x83ce1043) {
780 /*
781 * The digital mics on some Asus laptops produce
782 * differential signals instead of expected stereo.
783 * That results in silence if downmixing to mono.
784 * To workaround, make codec handle the signal as mono.
785 */
786 val = hdaa_read_coef(dev, 0x20, 0x07);
787 hdaa_write_coef(dev, 0x20, 0x07, val|0x80);
788 }
789 if (subid == 0x15171043) {
790 /* Increase output amp on ASUS UX31A by +5dB. */
791 hdaa_write_coef(dev, 0x20, 0x12, 0x2800);
792 }
793 }
794 }
795