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