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_card_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_card_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 devinfo->quirks |= hdac_quirks[i].set; 405 devinfo->quirks &= ~(hdac_quirks[i].unset); 406 devinfo->gpio = hdac_quirks[i].gpio; 407 } 408 409 /* Apply per-widget patch. */ 410 for (i = devinfo->startnode; i < devinfo->endnode; i++) { 411 w = hdaa_widget_get(devinfo, i); 412 if (w == NULL) 413 continue; 414 hdaa_widget_patch(w); 415 } 416 417 switch (id) { 418 case HDA_CODEC_AD1983: 419 /* 420 * This CODEC has several possible usages, but none 421 * fit the parser best. Help parser to choose better. 422 */ 423 /* Disable direct unmixed playback to get pcm volume. */ 424 w = hdaa_widget_get(devinfo, 5); 425 if (w != NULL) 426 w->connsenable[0] = 0; 427 w = hdaa_widget_get(devinfo, 6); 428 if (w != NULL) 429 w->connsenable[0] = 0; 430 w = hdaa_widget_get(devinfo, 11); 431 if (w != NULL) 432 w->connsenable[0] = 0; 433 /* Disable mic and line selectors. */ 434 w = hdaa_widget_get(devinfo, 12); 435 if (w != NULL) 436 w->connsenable[1] = 0; 437 w = hdaa_widget_get(devinfo, 13); 438 if (w != NULL) 439 w->connsenable[1] = 0; 440 /* Disable recording from mono playback mix. */ 441 w = hdaa_widget_get(devinfo, 20); 442 if (w != NULL) 443 w->connsenable[3] = 0; 444 break; 445 case HDA_CODEC_AD1986A: 446 /* 447 * This CODEC has overcomplicated input mixing. 448 * Make some cleaning there. 449 */ 450 /* Disable input mono mixer. Not needed and not supported. */ 451 w = hdaa_widget_get(devinfo, 43); 452 if (w != NULL) 453 w->enable = 0; 454 /* Disable any with any input mixing mesh. Use separately. */ 455 w = hdaa_widget_get(devinfo, 39); 456 if (w != NULL) 457 w->enable = 0; 458 w = hdaa_widget_get(devinfo, 40); 459 if (w != NULL) 460 w->enable = 0; 461 w = hdaa_widget_get(devinfo, 41); 462 if (w != NULL) 463 w->enable = 0; 464 w = hdaa_widget_get(devinfo, 42); 465 if (w != NULL) 466 w->enable = 0; 467 /* Disable duplicate mixer node connector. */ 468 w = hdaa_widget_get(devinfo, 15); 469 if (w != NULL) 470 w->connsenable[3] = 0; 471 /* There is only one mic preamplifier, use it effectively. */ 472 w = hdaa_widget_get(devinfo, 31); 473 if (w != NULL) { 474 if ((w->wclass.pin.config & 475 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 476 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 477 w = hdaa_widget_get(devinfo, 16); 478 if (w != NULL) 479 w->connsenable[2] = 0; 480 } else { 481 w = hdaa_widget_get(devinfo, 15); 482 if (w != NULL) 483 w->connsenable[0] = 0; 484 } 485 } 486 w = hdaa_widget_get(devinfo, 32); 487 if (w != NULL) { 488 if ((w->wclass.pin.config & 489 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 490 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 491 w = hdaa_widget_get(devinfo, 16); 492 if (w != NULL) 493 w->connsenable[0] = 0; 494 } else { 495 w = hdaa_widget_get(devinfo, 15); 496 if (w != NULL) 497 w->connsenable[1] = 0; 498 } 499 } 500 501 if (subid == ASUS_A8X_SUBVENDOR) { 502 /* 503 * This is just plain ridiculous.. There 504 * are several A8 series that share the same 505 * pci id but works differently (EAPD). 506 */ 507 w = hdaa_widget_get(devinfo, 26); 508 if (w != NULL && w->type == 509 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 510 (w->wclass.pin.config & 511 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 512 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 513 devinfo->quirks &= 514 ~HDAA_QUIRK_EAPDINV; 515 } 516 break; 517 case HDA_CODEC_AD1981HD: 518 /* 519 * This CODEC has very unusual design with several 520 * points inappropriate for the present parser. 521 */ 522 /* Disable recording from mono playback mix. */ 523 w = hdaa_widget_get(devinfo, 21); 524 if (w != NULL) 525 w->connsenable[3] = 0; 526 /* Disable rear to front mic mixer, use separately. */ 527 w = hdaa_widget_get(devinfo, 31); 528 if (w != NULL) 529 w->enable = 0; 530 /* Disable direct playback, use mixer. */ 531 w = hdaa_widget_get(devinfo, 5); 532 if (w != NULL) 533 w->connsenable[0] = 0; 534 w = hdaa_widget_get(devinfo, 6); 535 if (w != NULL) 536 w->connsenable[0] = 0; 537 w = hdaa_widget_get(devinfo, 9); 538 if (w != NULL) 539 w->connsenable[0] = 0; 540 w = hdaa_widget_get(devinfo, 24); 541 if (w != NULL) 542 w->connsenable[0] = 0; 543 break; 544 case HDA_CODEC_ALC269: 545 /* 546 * ASUS EeePC 1001px has strange variant of ALC269 CODEC, 547 * that mutes speaker if unused mixer at NID 15 is muted. 548 * Probably CODEC incorrectly reports internal connections. 549 * Hide that muter from the driver. There are several CODECs 550 * sharing this ID and I have not enough information about 551 * them to implement more universal solution. 552 */ 553 if (subid == 0x84371043) { 554 w = hdaa_widget_get(devinfo, 15); 555 if (w != NULL) 556 w->param.inamp_cap = 0; 557 } 558 break; 559 case HDA_CODEC_CX20582: 560 case HDA_CODEC_CX20583: 561 case HDA_CODEC_CX20584: 562 case HDA_CODEC_CX20585: 563 case HDA_CODEC_CX20590: 564 /* 565 * These codecs have extra connectivity on record side 566 * too reach for the present parser. 567 */ 568 w = hdaa_widget_get(devinfo, 20); 569 if (w != NULL) 570 w->connsenable[1] = 0; 571 w = hdaa_widget_get(devinfo, 21); 572 if (w != NULL) 573 w->connsenable[1] = 0; 574 w = hdaa_widget_get(devinfo, 22); 575 if (w != NULL) 576 w->connsenable[0] = 0; 577 break; 578 case HDA_CODEC_VT1708S_0: 579 case HDA_CODEC_VT1708S_1: 580 case HDA_CODEC_VT1708S_2: 581 case HDA_CODEC_VT1708S_3: 582 case HDA_CODEC_VT1708S_4: 583 case HDA_CODEC_VT1708S_5: 584 case HDA_CODEC_VT1708S_6: 585 case HDA_CODEC_VT1708S_7: 586 /* 587 * These codecs have hidden mic boost controls. 588 */ 589 w = hdaa_widget_get(devinfo, 26); 590 if (w != NULL) 591 w->param.inamp_cap = 592 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 593 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 594 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 595 w = hdaa_widget_get(devinfo, 30); 596 if (w != NULL) 597 w->param.inamp_cap = 598 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 599 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 600 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 601 break; 602 } 603 } 604 605 void 606 hdaa_patch_direct(struct hdaa_devinfo *devinfo) 607 { 608 device_t dev = devinfo->dev; 609 uint32_t id, subid, val; 610 611 id = hdaa_codec_id(devinfo); 612 subid = hdaa_card_id(devinfo); 613 614 switch (id) { 615 case HDA_CODEC_VT1708S_0: 616 case HDA_CODEC_VT1708S_1: 617 case HDA_CODEC_VT1708S_2: 618 case HDA_CODEC_VT1708S_3: 619 case HDA_CODEC_VT1708S_4: 620 case HDA_CODEC_VT1708S_5: 621 case HDA_CODEC_VT1708S_6: 622 case HDA_CODEC_VT1708S_7: 623 /* Enable Mic Boost Volume controls. */ 624 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 625 0xf98, 0x01)); 626 /* Fall though */ 627 case HDA_CODEC_VT1818S: 628 /* Don't bypass mixer. */ 629 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 630 0xf88, 0xc0)); 631 break; 632 } 633 if (subid == APPLE_INTEL_MAC) 634 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 635 0x7e7, 0)); 636 if (id == HDA_CODEC_ALC269) { 637 if (subid == 0x16e31043 || subid == 0x831a1043 || 638 subid == 0x834a1043 || subid == 0x83981043 || 639 subid == 0x83ce1043) { 640 /* 641 * The ditital mics on some Asus laptops produce 642 * differential signals instead of expected stereo. 643 * That results in silence if downmix it to mono. 644 * To workaround, make codec to handle signal as mono. 645 */ 646 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 647 val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20)); 648 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 649 hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80)); 650 } 651 } 652 } 653