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_AD1984A && 275 subid == LENOVO_X300_SUBVENDOR) { 276 switch (nid) { 277 case 17: /* Headphones with redirection */ 278 patch = "as=1 seq=15"; 279 break; 280 case 20: /* Two mics together */ 281 patch = "as=2 seq=15"; 282 break; 283 } 284 } else if (id == HDA_CODEC_AD1986A && 285 (subid == ASUS_M2NPVMX_SUBVENDOR || 286 subid == ASUS_A8NVMCSM_SUBVENDOR || 287 subid == ASUS_P5PL2_SUBVENDOR)) { 288 switch (nid) { 289 case 26: /* Headphones with redirection */ 290 patch = "as=1 seq=15"; 291 break; 292 case 28: /* 5.1 out => 2.0 out + 1 input */ 293 patch = "device=Line-in as=8 seq=1"; 294 break; 295 case 29: /* Can't use this as input, as the only available mic 296 * preamplifier is busy by front panel mic (nid 31). 297 * If you want to use this rear connector as mic input, 298 * you have to disable the front panel one. */ 299 patch = "as=0"; 300 break; 301 case 31: /* Lot of inputs configured with as=15 and unusable */ 302 patch = "as=8 seq=3"; 303 break; 304 case 32: 305 patch = "as=8 seq=4"; 306 break; 307 case 34: 308 patch = "as=8 seq=5"; 309 break; 310 case 36: 311 patch = "as=8 seq=6"; 312 break; 313 } 314 } else if (id == HDA_CODEC_ALC260 && 315 HDA_DEV_MATCH(SONY_S5_SUBVENDOR, subid)) { 316 switch (nid) { 317 case 16: 318 patch = "seq=15 device=Headphones"; 319 break; 320 } 321 } else if (id == HDA_CODEC_ALC268) { 322 if (subid == ACER_T5320_SUBVENDOR) { 323 switch (nid) { 324 case 20: /* Headphones Jack */ 325 patch = "as=1 seq=15"; 326 break; 327 } 328 } 329 } else if (id == HDA_CODEC_CX20561 && 330 subid == LENOVO_B450_SUBVENDOR) { 331 switch (nid) { 332 case 22: 333 patch = "as=1 seq=15"; 334 break; 335 } 336 } 337 338 if (patch != NULL) 339 config = hdaa_widget_pin_patch(config, patch); 340 HDA_BOOTVERBOSE( 341 if (config != orig) 342 device_printf(w->devinfo->dev, 343 "Patching pin config nid=%u 0x%08x -> 0x%08x\n", 344 nid, orig, config); 345 ); 346 w->wclass.pin.config = config; 347 } 348 349 static void 350 hdaa_widget_patch(struct hdaa_widget *w) 351 { 352 struct hdaa_devinfo *devinfo = w->devinfo; 353 uint32_t orig; 354 nid_t beeper = -1; 355 356 orig = w->param.widget_cap; 357 /* On some codecs beeper is an input pin, but it is not recordable 358 alone. Also most of BIOSes does not declare beeper pin. 359 Change beeper pin node type to beeper to help parser. */ 360 switch (hdaa_codec_id(devinfo)) { 361 case HDA_CODEC_AD1882: 362 case HDA_CODEC_AD1883: 363 case HDA_CODEC_AD1984: 364 case HDA_CODEC_AD1984A: 365 case HDA_CODEC_AD1984B: 366 case HDA_CODEC_AD1987: 367 case HDA_CODEC_AD1988: 368 case HDA_CODEC_AD1988B: 369 case HDA_CODEC_AD1989B: 370 beeper = 26; 371 break; 372 case HDA_CODEC_ALC260: 373 beeper = 23; 374 break; 375 } 376 if (hda_get_vendor_id(devinfo->dev) == REALTEK_VENDORID && 377 hdaa_codec_id(devinfo) != HDA_CODEC_ALC260) 378 beeper = 29; 379 if (w->nid == beeper) { 380 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_MASK; 381 w->param.widget_cap |= HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_BEEP_WIDGET << 382 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_SHIFT; 383 w->waspin = 1; 384 } 385 /* 386 * Clear "digital" flag from digital mic input, as its signal then goes 387 * to "analog" mixer and this separation just limits functionaity. 388 */ 389 if (hdaa_codec_id(devinfo) == HDA_CODEC_AD1984A && 390 w->nid == 23) 391 w->param.widget_cap &= ~HDA_PARAM_AUDIO_WIDGET_CAP_DIGITAL_MASK; 392 HDA_BOOTVERBOSE( 393 if (w->param.widget_cap != orig) { 394 device_printf(w->devinfo->dev, 395 "Patching widget caps nid=%u 0x%08x -> 0x%08x\n", 396 w->nid, orig, w->param.widget_cap); 397 } 398 ); 399 400 if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) 401 hdac_pin_patch(w); 402 } 403 404 void 405 hdaa_patch(struct hdaa_devinfo *devinfo) 406 { 407 struct hdaa_widget *w; 408 uint32_t id, subid; 409 int i; 410 411 id = hdaa_codec_id(devinfo); 412 subid = hdaa_card_id(devinfo); 413 414 /* 415 * Quirks 416 */ 417 for (i = 0; i < HDAC_QUIRKS_LEN; i++) { 418 if (!(HDA_DEV_MATCH(hdac_quirks[i].model, subid) && 419 HDA_DEV_MATCH(hdac_quirks[i].id, id))) 420 continue; 421 devinfo->quirks |= hdac_quirks[i].set; 422 devinfo->quirks &= ~(hdac_quirks[i].unset); 423 devinfo->gpio = hdac_quirks[i].gpio; 424 } 425 426 /* Apply per-widget patch. */ 427 for (i = devinfo->startnode; i < devinfo->endnode; i++) { 428 w = hdaa_widget_get(devinfo, i); 429 if (w == NULL) 430 continue; 431 hdaa_widget_patch(w); 432 } 433 434 switch (id) { 435 case HDA_CODEC_AD1983: 436 /* 437 * This CODEC has several possible usages, but none 438 * fit the parser best. Help parser to choose better. 439 */ 440 /* Disable direct unmixed playback to get pcm volume. */ 441 w = hdaa_widget_get(devinfo, 5); 442 if (w != NULL) 443 w->connsenable[0] = 0; 444 w = hdaa_widget_get(devinfo, 6); 445 if (w != NULL) 446 w->connsenable[0] = 0; 447 w = hdaa_widget_get(devinfo, 11); 448 if (w != NULL) 449 w->connsenable[0] = 0; 450 /* Disable mic and line selectors. */ 451 w = hdaa_widget_get(devinfo, 12); 452 if (w != NULL) 453 w->connsenable[1] = 0; 454 w = hdaa_widget_get(devinfo, 13); 455 if (w != NULL) 456 w->connsenable[1] = 0; 457 /* Disable recording from mono playback mix. */ 458 w = hdaa_widget_get(devinfo, 20); 459 if (w != NULL) 460 w->connsenable[3] = 0; 461 break; 462 case HDA_CODEC_AD1986A: 463 /* 464 * This CODEC has overcomplicated input mixing. 465 * Make some cleaning there. 466 */ 467 /* Disable input mono mixer. Not needed and not supported. */ 468 w = hdaa_widget_get(devinfo, 43); 469 if (w != NULL) 470 w->enable = 0; 471 /* Disable any with any input mixing mesh. Use separately. */ 472 w = hdaa_widget_get(devinfo, 39); 473 if (w != NULL) 474 w->enable = 0; 475 w = hdaa_widget_get(devinfo, 40); 476 if (w != NULL) 477 w->enable = 0; 478 w = hdaa_widget_get(devinfo, 41); 479 if (w != NULL) 480 w->enable = 0; 481 w = hdaa_widget_get(devinfo, 42); 482 if (w != NULL) 483 w->enable = 0; 484 /* Disable duplicate mixer node connector. */ 485 w = hdaa_widget_get(devinfo, 15); 486 if (w != NULL) 487 w->connsenable[3] = 0; 488 /* There is only one mic preamplifier, use it effectively. */ 489 w = hdaa_widget_get(devinfo, 31); 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[2] = 0; 497 } else { 498 w = hdaa_widget_get(devinfo, 15); 499 if (w != NULL) 500 w->connsenable[0] = 0; 501 } 502 } 503 w = hdaa_widget_get(devinfo, 32); 504 if (w != NULL) { 505 if ((w->wclass.pin.config & 506 HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) == 507 HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) { 508 w = hdaa_widget_get(devinfo, 16); 509 if (w != NULL) 510 w->connsenable[0] = 0; 511 } else { 512 w = hdaa_widget_get(devinfo, 15); 513 if (w != NULL) 514 w->connsenable[1] = 0; 515 } 516 } 517 518 if (subid == ASUS_A8X_SUBVENDOR) { 519 /* 520 * This is just plain ridiculous.. There 521 * are several A8 series that share the same 522 * pci id but works differently (EAPD). 523 */ 524 w = hdaa_widget_get(devinfo, 26); 525 if (w != NULL && w->type == 526 HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX && 527 (w->wclass.pin.config & 528 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_MASK) != 529 HDA_CONFIG_DEFAULTCONF_CONNECTIVITY_NONE) 530 devinfo->quirks &= 531 ~HDAA_QUIRK_EAPDINV; 532 } 533 break; 534 case HDA_CODEC_AD1981HD: 535 /* 536 * This CODEC has very unusual design with several 537 * points inappropriate for the present parser. 538 */ 539 /* Disable recording from mono playback mix. */ 540 w = hdaa_widget_get(devinfo, 21); 541 if (w != NULL) 542 w->connsenable[3] = 0; 543 /* Disable rear to front mic mixer, use separately. */ 544 w = hdaa_widget_get(devinfo, 31); 545 if (w != NULL) 546 w->enable = 0; 547 /* Disable direct playback, use mixer. */ 548 w = hdaa_widget_get(devinfo, 5); 549 if (w != NULL) 550 w->connsenable[0] = 0; 551 w = hdaa_widget_get(devinfo, 6); 552 if (w != NULL) 553 w->connsenable[0] = 0; 554 w = hdaa_widget_get(devinfo, 9); 555 if (w != NULL) 556 w->connsenable[0] = 0; 557 w = hdaa_widget_get(devinfo, 24); 558 if (w != NULL) 559 w->connsenable[0] = 0; 560 break; 561 case HDA_CODEC_ALC269: 562 /* 563 * ASUS EeePC 1001px has strange variant of ALC269 CODEC, 564 * that mutes speaker if unused mixer at NID 15 is muted. 565 * Probably CODEC incorrectly reports internal connections. 566 * Hide that muter from the driver. There are several CODECs 567 * sharing this ID and I have not enough information about 568 * them to implement more universal solution. 569 */ 570 if (subid == 0x84371043) { 571 w = hdaa_widget_get(devinfo, 15); 572 if (w != NULL) 573 w->param.inamp_cap = 0; 574 } 575 break; 576 case HDA_CODEC_CX20582: 577 case HDA_CODEC_CX20583: 578 case HDA_CODEC_CX20584: 579 case HDA_CODEC_CX20585: 580 case HDA_CODEC_CX20590: 581 /* 582 * These codecs have extra connectivity on record side 583 * too reach for the present parser. 584 */ 585 w = hdaa_widget_get(devinfo, 20); 586 if (w != NULL) 587 w->connsenable[1] = 0; 588 w = hdaa_widget_get(devinfo, 21); 589 if (w != NULL) 590 w->connsenable[1] = 0; 591 w = hdaa_widget_get(devinfo, 22); 592 if (w != NULL) 593 w->connsenable[0] = 0; 594 break; 595 case HDA_CODEC_VT1708S_0: 596 case HDA_CODEC_VT1708S_1: 597 case HDA_CODEC_VT1708S_2: 598 case HDA_CODEC_VT1708S_3: 599 case HDA_CODEC_VT1708S_4: 600 case HDA_CODEC_VT1708S_5: 601 case HDA_CODEC_VT1708S_6: 602 case HDA_CODEC_VT1708S_7: 603 /* 604 * These codecs have hidden mic boost controls. 605 */ 606 w = hdaa_widget_get(devinfo, 26); 607 if (w != NULL) 608 w->param.inamp_cap = 609 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 610 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 611 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 612 w = hdaa_widget_get(devinfo, 30); 613 if (w != NULL) 614 w->param.inamp_cap = 615 (40 << HDA_PARAM_OUTPUT_AMP_CAP_STEPSIZE_SHIFT) | 616 (3 << HDA_PARAM_OUTPUT_AMP_CAP_NUMSTEPS_SHIFT) | 617 (0 << HDA_PARAM_OUTPUT_AMP_CAP_OFFSET_SHIFT); 618 break; 619 } 620 } 621 622 void 623 hdaa_patch_direct(struct hdaa_devinfo *devinfo) 624 { 625 device_t dev = devinfo->dev; 626 uint32_t id, subid, val; 627 628 id = hdaa_codec_id(devinfo); 629 subid = hdaa_card_id(devinfo); 630 631 switch (id) { 632 case HDA_CODEC_VT1708S_0: 633 case HDA_CODEC_VT1708S_1: 634 case HDA_CODEC_VT1708S_2: 635 case HDA_CODEC_VT1708S_3: 636 case HDA_CODEC_VT1708S_4: 637 case HDA_CODEC_VT1708S_5: 638 case HDA_CODEC_VT1708S_6: 639 case HDA_CODEC_VT1708S_7: 640 /* Enable Mic Boost Volume controls. */ 641 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 642 0xf98, 0x01)); 643 /* Fall though */ 644 case HDA_CODEC_VT1818S: 645 /* Don't bypass mixer. */ 646 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 647 0xf88, 0xc0)); 648 break; 649 } 650 if (subid == APPLE_INTEL_MAC) 651 hda_command(dev, HDA_CMD_12BIT(0, devinfo->nid, 652 0x7e7, 0)); 653 if (id == HDA_CODEC_ALC269) { 654 if (subid == 0x16e31043 || subid == 0x831a1043 || 655 subid == 0x834a1043 || subid == 0x83981043 || 656 subid == 0x83ce1043) { 657 /* 658 * The ditital mics on some Asus laptops produce 659 * differential signals instead of expected stereo. 660 * That results in silence if downmix it to mono. 661 * To workaround, make codec to handle signal as mono. 662 */ 663 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 664 val = hda_command(dev, HDA_CMD_GET_PROCESSING_COEFF(0, 0x20)); 665 hda_command(dev, HDA_CMD_SET_COEFF_INDEX(0, 0x20, 0x07)); 666 hda_command(dev, HDA_CMD_SET_PROCESSING_COEFF(0, 0x20, val|0x80)); 667 } 668 } 669 } 670