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 * 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 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 { 363 /* 364 * loop over hdaa_model_pin_patch 365 */ 366 struct pin_patch_t *pin_patches = NULL; 367 368 pin_patches = match_pin_patches(id, subid); 369 370 if (pin_patches != NULL) { 371 for (struct pin_patch_t *patch = pin_patches; patch->type; patch++) { 372 if (nid == patch->nid) { 373 switch (patch->type) { 374 case PIN_PATCH_TYPE_STRING: 375 patch_str = patch->patch.string; 376 break; 377 case PIN_PATCH_TYPE_MASK: 378 config &= ~patch->patch.mask[0]; 379 config |= patch->patch.mask[1]; 380 break; 381 case PIN_PATCH_TYPE_OVERRIDE: 382 config = patch->patch.override; 383 break; 384 default: 385 /* should panic hard */ 386 break; 387 } 388 break; 389 } 390 } 391 } 392 } 393 394 if (patch_str != NULL) 395 config = hdaa_widget_pin_patch(config, patch_str); 396 HDA_BOOTVERBOSE( 397 if (config != orig) 398 device_printf(w->devinfo->dev, 399 "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 400 nid, orig, config); 401 ); 402 w->wclass.pin.config = config; 403 } 404 405 static void 406 hdaa_widget_patch(struct hdaa_widget *w) 407 { 408 struct hdaa_devinfo *devinfo = w->devinfo; 409 uint32_t orig; 410 nid_t beeper = -1; 411 412 orig = w->param.widget_cap; 413 /* On some codecs beeper is an input pin, but it is not recordable 414 alone. Also most of BIOSes does not declare beeper pin. 415 Change beeper pin node type to beeper to help parser. */ 416 switch (hdaa_codec_id(devinfo)) { 417 case HDA_CODEC_AD1882: 418 case HDA_CODEC_AD1883: 419 case HDA_CODEC_AD1984: 420 case HDA_CODEC_AD1984A: 421 case HDA_CODEC_AD1984B: 422 case HDA_CODEC_AD1987: 423 case HDA_CODEC_AD1988: 424 case HDA_CODEC_AD1988B: 425 case HDA_CODEC_AD1989B: 426 beeper = 26; 427 break; 428 case HDA_CODEC_ALC260: 429 beeper = 23; 430 break; 431 } 432 if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID && 433 hdaa_codec_id(devinfo) != HDA_CODEC_ALC260) 434 beeper = 29; 435 if (w->nid == beeper) { 436 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 437 w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 438 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 439 w->waspin = 1; 440 } 441 /* 442 * Clear "digital" flag from digital mic input, as its signal then goes 443 * to "analog" mixer and this separation just limits functionaity. 444 */ 445 if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A && 446 w->nid == 23) 447 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK; 448 HDA_BOOTVERBOSE( 449 if (w->param.widget_cap != orig) { 450 device_printf(w->devinfo->dev, 451 "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 452 w->nid, orig, w->param.widget_cap); 453 } 454 ); 455 456 if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 457 hdac_pin_patch(w); 458 } 459 460 void 461 hdaa_patch(struct hdaa_devinfo *devinfo) 462 { 463 struct hdaa_widget *w; 464 uint32_t id, subid, subsystemid; 465 int i; 466 467 id = hdaa_codec_id(devinfo); 468 subid = hdaa_card_id(devinfo); 469 subsystemid = hda_get_subsystem_id(devinfo->dev); 470 471 /* 472 * Quirks 473 */ 474 for (i = 0; i < nitems(hdac_quirks); i++) { 475 if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) && 476 HDA_DEV_MATCH(hdac_quirks[i].id, id) && 477 HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid))) 478 continue; 479 devinfo->quirks |= hdac_quirks[i].set; 480 devinfo->quirks &= ~(hdac_quirks[i].unset); 481 devinfo->gpio = hdac_quirks[i].gpio; 482 } 483 484 /* Apply per-widget patch. */ 485 for (i = devinfo->startnode; i < devinfo->endnode; i++) { 486 w = hdaa_widget_get(devinfo, i); 487 if (w == NULL) 488 continue; 489 hdaa_widget_patch(w); 490 } 491 492 switch (id) { 493 case HDA_CODEC_AD1983: 494 /* 495 * This CODEC has several possible usages, but none 496 * fit the parser best. Help parser to choose better. 497 */ 498 /* Disable direct unmixed playback to get pcm volume. */ 499 w = hdaa_widget_get(devinfo, 5); 500 if (w != NULL) 501 w->connsenable[0] = 0; 502 w = hdaa_widget_get(devinfo, 6); 503 if (w != NULL) 504 w->connsenable[0] = 0; 505 w = hdaa_widget_get(devinfo, 11); 506 if (w != NULL) 507 w->connsenable[0] = 0; 508 /* Disable mic and line selectors. */ 509 w = hdaa_widget_get(devinfo, 12); 510 if (w != NULL) 511 w->connsenable[1] = 0; 512 w = hdaa_widget_get(devinfo, 13); 513 if (w != NULL) 514 w->connsenable[1] = 0; 515 /* Disable recording from mono playback mix. */ 516 w = hdaa_widget_get(devinfo, 20); 517 if (w != NULL) 518 w->connsenable[3] = 0; 519 break; 520 case HDA_CODEC_AD1986A: 521 /* 522 * This CODEC has overcomplicated input mixing. 523 * Make some cleaning there. 524 */ 525 /* Disable input mono mixer. Not needed and not supported. */ 526 w = hdaa_widget_get(devinfo, 43); 527 if (w != NULL) 528 w->enable = 0; 529 /* Disable any with any input mixing mesh. Use separately. */ 530 w = hdaa_widget_get(devinfo, 39); 531 if (w != NULL) 532 w->enable = 0; 533 w = hdaa_widget_get(devinfo, 40); 534 if (w != NULL) 535 w->enable = 0; 536 w = hdaa_widget_get(devinfo, 41); 537 if (w != NULL) 538 w->enable = 0; 539 w = hdaa_widget_get(devinfo, 42); 540 if (w != NULL) 541 w->enable = 0; 542 /* Disable duplicate mixer node connector. */ 543 w = hdaa_widget_get(devinfo, 15); 544 if (w != NULL) 545 w->connsenable[3] = 0; 546 /* There is only one mic preamplifier, use it effectively. */ 547 w = hdaa_widget_get(devinfo, 31); 548 if (w != NULL) { 549 if ((w->wclass.pin.config & 550 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 551 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 552 w = hdaa_widget_get(devinfo, 16); 553 if (w != NULL) 554 w->connsenable[2] = 0; 555 } else { 556 w = hdaa_widget_get(devinfo, 15); 557 if (w != NULL) 558 w->connsenable[0] = 0; 559 } 560 } 561 w = hdaa_widget_get(devinfo, 32); 562 if (w != NULL) { 563 if ((w->wclass.pin.config & 564 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 565 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 566 w = hdaa_widget_get(devinfo, 16); 567 if (w != NULL) 568 w->connsenable[0] = 0; 569 } else { 570 w = hdaa_widget_get(devinfo, 15); 571 if (w != NULL) 572 w->connsenable[1] = 0; 573 } 574 } 575 576 if (subid == ASUS_A8X_SUBVENDOR) { 577 /* 578 * This is just plain ridiculous.. There 579 * are several A8 series that share the same 580 * pci id but works differently (EAPD). 581 */ 582 w = hdaa_widget_get(devinfo, 26); 583 if (w != NULL && w->type == 584 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 585 (w->wclass.pin.config & 586 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 587 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 588 devinfo->quirks &= 589 ~HDAA_QUIRK_EAPDINV; 590 } 591 break; 592 case HDA_CODEC_AD1981HD: 593 /* 594 * This CODEC has very unusual design with several 595 * points inappropriate for the present parser. 596 */ 597 /* Disable recording from mono playback mix. */ 598 w = hdaa_widget_get(devinfo, 21); 599 if (w != NULL) 600 w->connsenable[3] = 0; 601 /* Disable rear to front mic mixer, use separately. */ 602 w = hdaa_widget_get(devinfo, 31); 603 if (w != NULL) 604 w->enable = 0; 605 /* Disable direct playback, use mixer. */ 606 w = hdaa_widget_get(devinfo, 5); 607 if (w != NULL) 608 w->connsenable[0] = 0; 609 w = hdaa_widget_get(devinfo, 6); 610 if (w != NULL) 611 w->connsenable[0] = 0; 612 w = hdaa_widget_get(devinfo, 9); 613 if (w != NULL) 614 w->connsenable[0] = 0; 615 w = hdaa_widget_get(devinfo, 24); 616 if (w != NULL) 617 w->connsenable[0] = 0; 618 break; 619 case HDA_CODEC_ALC269: 620 /* 621 * ASUS EeePC 1001px has strange variant of ALC269 CODEC, 622 * that mutes speaker if unused mixer at NID 15 is muted. 623 * Probably CODEC incorrectly reports internal connections. 624 * Hide that muter from the driver. There are several CODECs 625 * sharing this ID and I have not enough information about 626 * them to implement more universal solution. 627 */ 628 if (subid == 0x84371043) { 629 w = hdaa_widget_get(devinfo, 15); 630 if (w != NULL) 631 w->param.inamp_cap = 0; 632 } 633 break; 634 case HDA_CODEC_CX20582: 635 case HDA_CODEC_CX20583: 636 case HDA_CODEC_CX20584: 637 case HDA_CODEC_CX20585: 638 case HDA_CODEC_CX20590: 639 /* 640 * These codecs have extra connectivity on record side 641 * too reach for the present parser. 642 */ 643 w = hdaa_widget_get(devinfo, 20); 644 if (w != NULL) 645 w->connsenable[1] = 0; 646 w = hdaa_widget_get(devinfo, 21); 647 if (w != NULL) 648 w->connsenable[1] = 0; 649 w = hdaa_widget_get(devinfo, 22); 650 if (w != NULL) 651 w->connsenable[0] = 0; 652 break; 653 case HDA_CODEC_VT1708S_0: 654 case HDA_CODEC_VT1708S_1: 655 case HDA_CODEC_VT1708S_2: 656 case HDA_CODEC_VT1708S_3: 657 case HDA_CODEC_VT1708S_4: 658 case HDA_CODEC_VT1708S_5: 659 case HDA_CODEC_VT1708S_6: 660 case HDA_CODEC_VT1708S_7: 661 /* 662 * These codecs have hidden mic boost controls. 663 */ 664 w = hdaa_widget_get(devinfo, 26); 665 if (w != NULL) 666 w->param.inamp_cap = 667 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 668 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 669 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 670 w = hdaa_widget_get(devinfo, 30); 671 if (w != NULL) 672 w->param.inamp_cap = 673 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 674 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 675 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 676 break; 677 } 678 } 679 680 static uint32_t 681 hdaa_read_coef(device_t dev, nid_t nid, uint16_t idx) 682 { 683 684 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx)); 685 return (hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, nid))); 686 } 687 688 static uint32_t 689 hdaa_write_coef(device_t dev, nid_t nid, uint16_t idx, uint16_t val) 690 { 691 692 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, nid, idx)); 693 return (hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, nid, val))); 694 } 695 696 void 697 hdaa_patch_direct(struct hdaa_devinfo *devinfo) 698 { 699 device_t dev = devinfo->dev; 700 uint32_t id, subid, val; 701 702 id = hdaa_codec_id(devinfo); 703 subid = hdaa_card_id(devinfo); 704 705 switch (id) { 706 case HDA_CODEC_VT1708S_0: 707 case HDA_CODEC_VT1708S_1: 708 case HDA_CODEC_VT1708S_2: 709 case HDA_CODEC_VT1708S_3: 710 case HDA_CODEC_VT1708S_4: 711 case HDA_CODEC_VT1708S_5: 712 case HDA_CODEC_VT1708S_6: 713 case HDA_CODEC_VT1708S_7: 714 /* Enable Mic Boost Volume controls. */ 715 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 716 0xf98, 0x01)); 717 /* Fall though */ 718 case HDA_CODEC_VT1818S: 719 /* Don't bypass mixer. */ 720 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 721 0xf88, 0xc0)); 722 break; 723 case HDA_CODEC_ALC1150: 724 if (subid == 0xd9781462) { 725 /* Too low volume on MSI H170 GAMING M3. */ 726 hdaa_write_coef(dev, 0x20, 0x07, 0x7cb); 727 } 728 break; 729 } 730 if (id == HDA_CODEC_ALC255 || id == HDA_CODEC_ALC256) { 731 val = hdaa_read_coef(dev, 0x20, 0x46); 732 hdaa_write_coef(dev, 0x20, 0x46, val|0x3000); 733 } 734 if (subid == APPLE_INTEL_MAC) 735 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 736 0x7e7, 0)); 737 if (id == HDA_CODEC_ALC269) { 738 if (subid == 0x16e31043 || subid == 0x831a1043 || 739 subid == 0x834a1043 || subid == 0x83981043 || 740 subid == 0x83ce1043) { 741 /* 742 * The digital mics on some Asus laptops produce 743 * differential signals instead of expected stereo. 744 * That results in silence if downmixing to mono. 745 * To workaround, make codec handle the signal as mono. 746 */ 747 val = hdaa_read_coef(dev, 0x20, 0x07); 748 hdaa_write_coef(dev, 0x20, 0x07, val|0x80); 749 } 750 if (subid == 0x15171043) { 751 /* Increase output amp on ASUS UX31A by +5dB. */ 752 hdaa_write_coef(dev, 0x20, 0x12, 0x2800); 753 } 754 } 755 } 756