hdaa_patches.c revision 248786
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 248786 2013-03-27 07:30:08Z mav $"); 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_MACBOOKPRO55, HDA_CODEC_CS4206, HDA_MATCH_ALL, 111 0, 0, 112 HDAA_GPIO_SET(1) | HDAA_GPIO_SET(3) }, 113 { DELL_D630_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL, 114 0, 0, 115 HDAA_GPIO_SET(0) }, 116 { DELL_V1400_SUBVENDOR, HDA_CODEC_STAC9228X, HDA_MATCH_ALL, 117 0, 0, 118 HDAA_GPIO_SET(2) }, 119 { DELL_V1500_SUBVENDOR, HDA_CODEC_STAC9205X, HDA_MATCH_ALL, 120 0, 0, 121 HDAA_GPIO_SET(0) }, 122 { HDA_MATCH_ALL, HDA_CODEC_AD1988, HDA_MATCH_ALL, 123 HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100, 124 0 }, 125 { HDA_MATCH_ALL, HDA_CODEC_AD1988B, HDA_MATCH_ALL, 126 HDAA_QUIRK_IVREF80, HDAA_QUIRK_IVREF50 | HDAA_QUIRK_IVREF100, 127 0 }, 128 { HDA_MATCH_ALL, HDA_CODEC_CX20549, HDA_MATCH_ALL, 129 0, HDAA_QUIRK_FORCESTEREO, 130 0 }, 131 /* Mac Pro 1,1 requires ovref for proper volume level. */ 132 { 0x00000000, HDA_CODEC_ALC885, 0x106b0c00, 133 0, HDAA_QUIRK_OVREF, 134 0 } 135}; 136#define HDAC_QUIRKS_LEN (sizeof(hdac_quirks) / sizeof(hdac_quirks[0])) 137 138static void 139hdac_pin_patch(struct hdaa_widget *w) 140{ 141 const char *patch = NULL; 142 uint32_t config, orig, id, subid; 143 nid_t nid = w->nid; 144 145 config = orig = w->wclass.pin.config; 146 id = hdaa_codec_id(w->devinfo); 147 subid = hdaa_card_id(w->devinfo); 148 149 /* XXX: Old patches require complete review. 150 * Now they may create more problem then solve due to 151 * incorrect associations. 152 */ 153 if (id == HDA_CODEC_ALC880 && subid == LG_LW20_SUBVENDOR) { 154 switch (nid) { 155 case 26: 156 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 157 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 158 break; 159 case 27: 160 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 161 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT; 162 break; 163 default: 164 break; 165 } 166 } else if (id == HDA_CODEC_ALC880 && 167 (subid == CLEVO_D900T_SUBVENDOR || 168 subid == ASUS_M5200_SUBVENDOR)) { 169 /* 170 * Super broken BIOS 171 */ 172 switch (nid) { 173 case 24: /* MIC1 */ 174 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 175 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 176 break; 177 case 25: /* XXX MIC2 */ 178 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 179 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN; 180 break; 181 case 26: /* LINE1 */ 182 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 183 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 184 break; 185 case 27: /* XXX LINE2 */ 186 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 187 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_IN; 188 break; 189 case 28: /* CD */ 190 config &= ~HDA_CONFIG_DEFAULTCONF_DEVICE_MASK; 191 config |= HDA_CONFIG_DEFAULTCONF_DEVICE_CD; 192 break; 193 } 194 } else if (id == HDA_CODEC_ALC883 && 195 (subid == MSI_MS034A_SUBVENDOR || 196 HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, subid))) { 197 switch (nid) { 198 case 25: 199 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 200 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 201 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 202 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 203 break; 204 case 28: 205 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 206 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 207 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 208 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 209 break; 210 } 211 } else if (id == HDA_CODEC_CX20549 && subid == 212 HP_V3000_SUBVENDOR) { 213 switch (nid) { 214 case 18: 215 config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 216 config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 217 break; 218 case 20: 219 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 220 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 221 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 222 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 223 break; 224 case 21: 225 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 226 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 227 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_CD | 228 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 229 break; 230 } 231 } else if (id == HDA_CODEC_CX20551 && subid == 232 HP_DV5000_SUBVENDOR) { 233 switch (nid) { 234 case 20: 235 case 21: 236 config &= ~HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK; 237 config |= HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE; 238 break; 239 } 240 } else if (id == HDA_CODEC_ALC861 && subid == 241 ASUS_W6F_SUBVENDOR) { 242 switch (nid) { 243 case 11: 244 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 245 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 246 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_LINE_OUT | 247 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 248 break; 249 case 12: 250 case 14: 251 case 16: 252 case 31: 253 case 32: 254 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 255 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 256 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN | 257 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_FIXED); 258 break; 259 case 15: 260 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 261 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 262 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 263 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 264 break; 265 } 266 } else if (id == HDA_CODEC_ALC861 && subid == 267 UNIWILL_9075_SUBVENDOR) { 268 switch (nid) { 269 case 15: 270 config &= ~(HDA_CONFIG_DEFAULTCONF_DEVICE_MASK | 271 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK); 272 config |= (HDA_CONFIG_DEFAULTCONF_DEVICE_HP_OUT | 273 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_JACK); 274 break; 275 } 276 } 277 278 /* New patches */ 279 if (id == HDA_CODEC_AD1984A && 280 subid == LENOVO_X300_SUBVENDOR) { 281 switch (nid) { 282 case 17: /* Headphones with redirection */ 283 patch = "as=1 seq=15"; 284 break; 285 case 20: /* Two mics together */ 286 patch = "as=2 seq=15"; 287 break; 288 } 289 } else if (id == HDA_CODEC_AD1986A && 290 (subid == ASUS_M2NPVMX_SUBVENDOR || 291 subid == ASUS_A8NVMCSM_SUBVENDOR || 292 subid == ASUS_P5PL2_SUBVENDOR)) { 293 switch (nid) { 294 case 26: /* Headphones with redirection */ 295 patch = "as=1 seq=15"; 296 break; 297 case 28: /* 5.1 out => 2.0 out + 1 input */ 298 patch = "device=Line-in as=8 seq=1"; 299 break; 300 case 29: /* Can't use this as input, as the only available mic 301 * preamplifier is busy by front panel mic (nid 31). 302 * If you want to use this rear connector as mic input, 303 * you have to disable the front panel one. */ 304 patch = "as=0"; 305 break; 306 case 31: /* Lot of inputs configured with as=15 and unusable */ 307 patch = "as=8 seq=3"; 308 break; 309 case 32: 310 patch = "as=8 seq=4"; 311 break; 312 case 34: 313 patch = "as=8 seq=5"; 314 break; 315 case 36: 316 patch = "as=8 seq=6"; 317 break; 318 } 319 } else if (id == HDA_CODEC_ALC260 && 320 HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) { 321 switch (nid) { 322 case 16: 323 patch = "seq=15 device=Headphones"; 324 break; 325 } 326 } else if (id == HDA_CODEC_ALC268) { 327 if (subid == ACER_T5320_SUBVENDOR) { 328 switch (nid) { 329 case 20: /* Headphones Jack */ 330 patch = "as=1 seq=15"; 331 break; 332 } 333 } 334 } else if (id == HDA_CODEC_CX20561 && 335 subid == LENOVO_B450_SUBVENDOR) { 336 switch (nid) { 337 case 22: 338 patch = "as=1 seq=15"; 339 break; 340 } 341 } else if (id == HDA_CODEC_CX20590 && 342 (subid == LENOVO_X1_SUBVENDOR || 343 subid == LENOVO_X220_SUBVENDOR || 344 subid == LENOVO_T420_SUBVENDOR || 345 subid == LENOVO_T520_SUBVENDOR)) { 346 switch (nid) { 347 case 25: 348 patch = "as=1 seq=15"; 349 break; 350 } 351 } else if (id == HDA_CODEC_ALC269 && 352 (subid == LENOVO_X1CRBN_SUBVENDOR || 353 subid == LENOVO_T430_SUBVENDOR || 354 subid == LENOVO_T430S_SUBVENDOR || 355 subid == LENOVO_T530_SUBVENDOR)) { 356 switch (nid) { 357 case 21: 358 patch = "as=1 seq=15"; 359 break; 360 } 361 } 362 363 if (patch != NULL) 364 config = hdaa_widget_pin_patch(config, patch); 365 HDA_BOOTVERBOSE( 366 if (config != orig) 367 device_printf(w->devinfo->dev, 368 "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 369 nid, orig, config); 370 ); 371 w->wclass.pin.config = config; 372} 373 374static void 375hdaa_widget_patch(struct hdaa_widget *w) 376{ 377 struct hdaa_devinfo *devinfo = w->devinfo; 378 uint32_t orig; 379 nid_t beeper = -1; 380 381 orig = w->param.widget_cap; 382 /* On some codecs beeper is an input pin, but it is not recordable 383 alone. Also most of BIOSes does not declare beeper pin. 384 Change beeper pin node type to beeper to help parser. */ 385 switch (hdaa_codec_id(devinfo)) { 386 case HDA_CODEC_AD1882: 387 case HDA_CODEC_AD1883: 388 case HDA_CODEC_AD1984: 389 case HDA_CODEC_AD1984A: 390 case HDA_CODEC_AD1984B: 391 case HDA_CODEC_AD1987: 392 case HDA_CODEC_AD1988: 393 case HDA_CODEC_AD1988B: 394 case HDA_CODEC_AD1989B: 395 beeper = 26; 396 break; 397 case HDA_CODEC_ALC260: 398 beeper = 23; 399 break; 400 } 401 if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID && 402 hdaa_codec_id(devinfo) != HDA_CODEC_ALC260) 403 beeper = 29; 404 if (w->nid == beeper) { 405 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 406 w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 407 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 408 w->waspin = 1; 409 } 410 /* 411 * Clear "digital" flag from digital mic input, as its signal then goes 412 * to "analog" mixer and this separation just limits functionaity. 413 */ 414 if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A && 415 w->nid == 23) 416 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK; 417 HDA_BOOTVERBOSE( 418 if (w->param.widget_cap != orig) { 419 device_printf(w->devinfo->dev, 420 "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 421 w->nid, orig, w->param.widget_cap); 422 } 423 ); 424 425 if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 426 hdac_pin_patch(w); 427} 428 429void 430hdaa_patch(struct hdaa_devinfo *devinfo) 431{ 432 struct hdaa_widget *w; 433 uint32_t id, subid, subsystemid; 434 int i; 435 436 id = hdaa_codec_id(devinfo); 437 subid = hdaa_card_id(devinfo); 438 subsystemid = hda_get_subsystem_id(devinfo->dev); 439 440 /* 441 * Quirks 442 */ 443 for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 444 if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) && 445 HDA_DEV_MATCH(hdac_quirks[i].id, id) && 446 HDA_DEV_MATCH(hdac_quirks[i].subsystemid, subsystemid))) 447 continue; 448 devinfo->quirks |= hdac_quirks[i].set; 449 devinfo->quirks &= ~(hdac_quirks[i].unset); 450 devinfo->gpio = hdac_quirks[i].gpio; 451 } 452 453 /* Apply per-widget patch. */ 454 for (i = devinfo->startnode; i < devinfo->endnode; i++) { 455 w = hdaa_widget_get(devinfo, i); 456 if (w == NULL) 457 continue; 458 hdaa_widget_patch(w); 459 } 460 461 switch (id) { 462 case HDA_CODEC_AD1983: 463 /* 464 * This CODEC has several possible usages, but none 465 * fit the parser best. Help parser to choose better. 466 */ 467 /* Disable direct unmixed playback to get pcm volume. */ 468 w = hdaa_widget_get(devinfo, 5); 469 if (w != NULL) 470 w->connsenable[0] = 0; 471 w = hdaa_widget_get(devinfo, 6); 472 if (w != NULL) 473 w->connsenable[0] = 0; 474 w = hdaa_widget_get(devinfo, 11); 475 if (w != NULL) 476 w->connsenable[0] = 0; 477 /* Disable mic and line selectors. */ 478 w = hdaa_widget_get(devinfo, 12); 479 if (w != NULL) 480 w->connsenable[1] = 0; 481 w = hdaa_widget_get(devinfo, 13); 482 if (w != NULL) 483 w->connsenable[1] = 0; 484 /* Disable recording from mono playback mix. */ 485 w = hdaa_widget_get(devinfo, 20); 486 if (w != NULL) 487 w->connsenable[3] = 0; 488 break; 489 case HDA_CODEC_AD1986A: 490 /* 491 * This CODEC has overcomplicated input mixing. 492 * Make some cleaning there. 493 */ 494 /* Disable input mono mixer. Not needed and not supported. */ 495 w = hdaa_widget_get(devinfo, 43); 496 if (w != NULL) 497 w->enable = 0; 498 /* Disable any with any input mixing mesh. Use separately. */ 499 w = hdaa_widget_get(devinfo, 39); 500 if (w != NULL) 501 w->enable = 0; 502 w = hdaa_widget_get(devinfo, 40); 503 if (w != NULL) 504 w->enable = 0; 505 w = hdaa_widget_get(devinfo, 41); 506 if (w != NULL) 507 w->enable = 0; 508 w = hdaa_widget_get(devinfo, 42); 509 if (w != NULL) 510 w->enable = 0; 511 /* Disable duplicate mixer node connector. */ 512 w = hdaa_widget_get(devinfo, 15); 513 if (w != NULL) 514 w->connsenable[3] = 0; 515 /* There is only one mic preamplifier, use it effectively. */ 516 w = hdaa_widget_get(devinfo, 31); 517 if (w != NULL) { 518 if ((w->wclass.pin.config & 519 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 520 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 521 w = hdaa_widget_get(devinfo, 16); 522 if (w != NULL) 523 w->connsenable[2] = 0; 524 } else { 525 w = hdaa_widget_get(devinfo, 15); 526 if (w != NULL) 527 w->connsenable[0] = 0; 528 } 529 } 530 w = hdaa_widget_get(devinfo, 32); 531 if (w != NULL) { 532 if ((w->wclass.pin.config & 533 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 534 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 535 w = hdaa_widget_get(devinfo, 16); 536 if (w != NULL) 537 w->connsenable[0] = 0; 538 } else { 539 w = hdaa_widget_get(devinfo, 15); 540 if (w != NULL) 541 w->connsenable[1] = 0; 542 } 543 } 544 545 if (subid == ASUS_A8X_SUBVENDOR) { 546 /* 547 * This is just plain ridiculous.. There 548 * are several A8 series that share the same 549 * pci id but works differently (EAPD). 550 */ 551 w = hdaa_widget_get(devinfo, 26); 552 if (w != NULL && w->type == 553 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 554 (w->wclass.pin.config & 555 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 556 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 557 devinfo->quirks &= 558 ~HDAA_QUIRK_EAPDINV; 559 } 560 break; 561 case HDA_CODEC_AD1981HD: 562 /* 563 * This CODEC has very unusual design with several 564 * points inappropriate for the present parser. 565 */ 566 /* Disable recording from mono playback mix. */ 567 w = hdaa_widget_get(devinfo, 21); 568 if (w != NULL) 569 w->connsenable[3] = 0; 570 /* Disable rear to front mic mixer, use separately. */ 571 w = hdaa_widget_get(devinfo, 31); 572 if (w != NULL) 573 w->enable = 0; 574 /* Disable direct playback, use mixer. */ 575 w = hdaa_widget_get(devinfo, 5); 576 if (w != NULL) 577 w->connsenable[0] = 0; 578 w = hdaa_widget_get(devinfo, 6); 579 if (w != NULL) 580 w->connsenable[0] = 0; 581 w = hdaa_widget_get(devinfo, 9); 582 if (w != NULL) 583 w->connsenable[0] = 0; 584 w = hdaa_widget_get(devinfo, 24); 585 if (w != NULL) 586 w->connsenable[0] = 0; 587 break; 588 case HDA_CODEC_ALC269: 589 /* 590 * ASUS EeePC 1001px has strange variant of ALC269 CODEC, 591 * that mutes speaker if unused mixer at NID 15 is muted. 592 * Probably CODEC incorrectly reports internal connections. 593 * Hide that muter from the driver. There are several CODECs 594 * sharing this ID and I have not enough information about 595 * them to implement more universal solution. 596 */ 597 if (subid == 0x84371043) { 598 w = hdaa_widget_get(devinfo, 15); 599 if (w != NULL) 600 w->param.inamp_cap = 0; 601 } 602 break; 603 case HDA_CODEC_CX20582: 604 case HDA_CODEC_CX20583: 605 case HDA_CODEC_CX20584: 606 case HDA_CODEC_CX20585: 607 case HDA_CODEC_CX20590: 608 /* 609 * These codecs have extra connectivity on record side 610 * too reach for the present parser. 611 */ 612 w = hdaa_widget_get(devinfo, 20); 613 if (w != NULL) 614 w->connsenable[1] = 0; 615 w = hdaa_widget_get(devinfo, 21); 616 if (w != NULL) 617 w->connsenable[1] = 0; 618 w = hdaa_widget_get(devinfo, 22); 619 if (w != NULL) 620 w->connsenable[0] = 0; 621 break; 622 case HDA_CODEC_VT1708S_0: 623 case HDA_CODEC_VT1708S_1: 624 case HDA_CODEC_VT1708S_2: 625 case HDA_CODEC_VT1708S_3: 626 case HDA_CODEC_VT1708S_4: 627 case HDA_CODEC_VT1708S_5: 628 case HDA_CODEC_VT1708S_6: 629 case HDA_CODEC_VT1708S_7: 630 /* 631 * These codecs have hidden mic boost controls. 632 */ 633 w = hdaa_widget_get(devinfo, 26); 634 if (w != NULL) 635 w->param.inamp_cap = 636 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 637 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 638 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 639 w = hdaa_widget_get(devinfo, 30); 640 if (w != NULL) 641 w->param.inamp_cap = 642 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 643 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 644 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 645 break; 646 } 647} 648 649void 650hdaa_patch_direct(struct hdaa_devinfo *devinfo) 651{ 652 device_t dev = devinfo->dev; 653 uint32_t id, subid, val; 654 655 id = hdaa_codec_id(devinfo); 656 subid = hdaa_card_id(devinfo); 657 658 switch (id) { 659 case HDA_CODEC_VT1708S_0: 660 case HDA_CODEC_VT1708S_1: 661 case HDA_CODEC_VT1708S_2: 662 case HDA_CODEC_VT1708S_3: 663 case HDA_CODEC_VT1708S_4: 664 case HDA_CODEC_VT1708S_5: 665 case HDA_CODEC_VT1708S_6: 666 case HDA_CODEC_VT1708S_7: 667 /* Enable Mic Boost Volume controls. */ 668 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 669 0xf98, 0x01)); 670 /* Fall though */ 671 case HDA_CODEC_VT1818S: 672 /* Don't bypass mixer. */ 673 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 674 0xf88, 0xc0)); 675 break; 676 } 677 if (subid == APPLE_INTEL_MAC) 678 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 679 0x7e7, 0)); 680 if (id == HDA_CODEC_ALC269) { 681 if (subid == 0x16e31043 || subid == 0x831a1043 || 682 subid == 0x834a1043 || subid == 0x83981043 || 683 subid == 0x83ce1043) { 684 /* 685 * The ditital mics on some Asus laptops produce 686 * differential signals instead of expected stereo. 687 * That results in silence if downmix it to mono. 688 * To workaround, make codec to handle signal as mono. 689 */ 690 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 691 val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20)); 692 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 693 hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80)); 694 } 695 } 696} 697