1 /* 2 * Copyright 2007-2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ithamar Adema, ithamar AT unet DOT nl 7 * Axel Dörfler, axeld@pinc-software.de 8 * Jérôme Duval, korli@users.berlios.de 9 */ 10 11 12 #include "driver.h" 13 #include "hda_codec_defs.h" 14 15 #undef TRACE 16 #define TRACE_CODEC 17 #ifdef TRACE_CODEC 18 #define TRACE(a...) dprintf(a) 19 #else 20 #define TRACE(a...) 21 #endif 22 #define ERROR(a...) dprintf(a) 23 24 #define HDA_ALL 0xffffffff 25 #define HDA_QUIRK_GPIO_COUNT 8 26 #define HDA_QUIRK_GPIO0 (1 << 0) 27 #define HDA_QUIRK_GPIO1 (1 << 1) 28 #define HDA_QUIRK_GPIO2 (1 << 2) 29 #define HDA_QUIRK_GPIO3 (1 << 3) 30 #define HDA_QUIRK_GPIO4 (1 << 4) 31 #define HDA_QUIRK_GPIO5 (1 << 5) 32 #define HDA_QUIRK_GPIO6 (1 << 6) 33 #define HDA_QUIRK_GPIO7 (1 << 7) 34 #define HDA_QUIRK_IVREF50 (1 << 8) 35 #define HDA_QUIRK_IVREF80 (1 << 9) 36 #define HDA_QUIRK_IVREF100 (1 << 10) 37 #define HDA_QUIRK_OVREF50 (1 << 11) 38 #define HDA_QUIRK_OVREF80 (1 << 12) 39 #define HDA_QUIRK_OVREF100 (1 << 13) 40 #define HDA_QUIRK_IVREF (HDA_QUIRK_IVREF50 | HDA_QUIRK_IVREF80 \ 41 | HDA_QUIRK_IVREF100) 42 #define HDA_QUIRK_OVREF (HDA_QUIRK_OVREF50 | HDA_QUIRK_OVREF80 \ 43 | HDA_QUIRK_OVREF100) 44 45 46 #define ANALOGDEVICES_VENDORID 0x11d4 47 #define CIRRUSLOGIC_VENDORID 0x1013 48 #define CONEXANT_VENDORID 0x14f1 49 #define REALTEK_VENDORID 0x10ec 50 #define SIGMATEL_VENDORID 0x8384 51 52 53 static const char* kPortConnector[] = { 54 "Jack", "None", "Fixed", "Dual" 55 }; 56 57 static const char* kDefaultDevice[] = { 58 "Line out", "Speaker", "HP out", "CD", "SPDIF out", "Digital other out", 59 "Modem line side", "Modem hand side", "Line in", "AUX", "Mic in", 60 "Telephony", "SPDIF in", "Digital other in", "Reserved", "Other" 61 }; 62 63 static const char* kConnectionType[] = { 64 "N/A", "1/8\"", "1/4\"", "ATAPI internal", "RCA", "Optical", 65 "Other digital", "Other analog", "Multichannel analog (DIN)", 66 "XLR/Professional", "RJ-11 (modem)", "Combination", "-", "-", "-", "Other" 67 }; 68 69 static const char* kJackColor[] = { 70 "N/A", "Black", "Grey", "Blue", "Green", "Red", "Orange", "Yellow", 71 "Purple", "Pink", "-", "-", "-", "-", "White", "Other" 72 }; 73 74 75 static const char* 76 get_widget_type_name(hda_widget_type type) 77 { 78 switch (type) { 79 case WT_AUDIO_OUTPUT: 80 return "Audio output"; 81 case WT_AUDIO_INPUT: 82 return "Audio input"; 83 case WT_AUDIO_MIXER: 84 return "Audio mixer"; 85 case WT_AUDIO_SELECTOR: 86 return "Audio selector"; 87 case WT_PIN_COMPLEX: 88 return "Pin complex"; 89 case WT_POWER: 90 return "Power"; 91 case WT_VOLUME_KNOB: 92 return "Volume knob"; 93 case WT_BEEP_GENERATOR: 94 return "Beep generator"; 95 case WT_VENDOR_DEFINED: 96 return "Vendor defined"; 97 default: 98 return "Unknown"; 99 } 100 } 101 102 103 const char* 104 get_widget_location(uint32 location) 105 { 106 switch (location >> 4) { 107 case 0: 108 case 2: 109 switch (location & 0xf) { 110 case 2: 111 return "Front"; 112 case 3: 113 return "Left"; 114 case 4: 115 return "Right"; 116 case 5: 117 return "Top"; 118 case 6: 119 return "Bottom"; 120 case 7: 121 return "Rear panel"; 122 case 8: 123 return "Drive bay"; 124 case 0: 125 case 1: 126 default: 127 return NULL; 128 } 129 case 1: 130 switch (location & 0xf) { 131 case 7: 132 return "Riser"; 133 case 8: 134 return "HDMI"; 135 default: 136 return NULL; 137 } 138 case 3: 139 switch (location & 0xf) { 140 case 6: 141 return "Bottom"; 142 case 7: 143 return "Inside lid"; 144 case 8: 145 return "Outside lid"; 146 default: 147 return NULL; 148 } 149 } 150 return NULL; 151 } 152 153 154 static void 155 dump_widget_audio_capabilities(uint32 capabilities) 156 { 157 static const struct { 158 uint32 flag; 159 const char* name; 160 } kFlags[] = { 161 {AUDIO_CAP_LEFT_RIGHT_SWAP, "L-R swap"}, 162 {AUDIO_CAP_POWER_CONTROL, "Power"}, 163 {AUDIO_CAP_DIGITAL, "Digital"}, 164 {AUDIO_CAP_CONNECTION_LIST, "Conn. list"}, 165 {AUDIO_CAP_UNSOLICITED_RESPONSES, "Unsol. responses"}, 166 {AUDIO_CAP_PROCESSING_CONTROLS, "Proc widget"}, 167 {AUDIO_CAP_STRIPE, "Stripe"}, 168 {AUDIO_CAP_FORMAT_OVERRIDE, "Format override"}, 169 {AUDIO_CAP_AMPLIFIER_OVERRIDE, "Amplifier override"}, 170 {AUDIO_CAP_OUTPUT_AMPLIFIER, "Out amplifier"}, 171 {AUDIO_CAP_INPUT_AMPLIFIER, "In amplifier"}, 172 {AUDIO_CAP_STEREO, "Stereo"}, 173 }; 174 175 char buffer[256]; 176 int offset = 0; 177 178 for (uint32 j = 0; j < sizeof(kFlags) / sizeof(kFlags[0]); j++) { 179 if (capabilities & kFlags[j].flag) 180 offset += sprintf(buffer + offset, "[%s] ", kFlags[j].name); 181 } 182 183 if (offset != 0) 184 TRACE("\t%s\n", buffer); 185 } 186 187 188 static void 189 dump_widget_inputs(hda_widget& widget) 190 { 191 // dump connections 192 193 char buffer[256]; 194 int offset = 0; 195 196 for (uint32 i = 0; i < widget.num_inputs; i++) { 197 int32 input = widget.inputs[i]; 198 199 if ((int32)i != widget.active_input) 200 offset += sprintf(buffer + offset, "%ld ", input); 201 else 202 offset += sprintf(buffer + offset, "<%ld> ", input); 203 } 204 205 if (offset != 0) 206 TRACE("\tInputs: %s\n", buffer); 207 } 208 209 210 static void 211 dump_widget_amplifier_capabilities(hda_widget& widget, bool input) 212 { 213 uint32 capabilities; 214 if (input) 215 capabilities = widget.capabilities.input_amplifier; 216 else 217 capabilities = widget.capabilities.output_amplifier; 218 219 if (capabilities == 0) 220 return; 221 222 TRACE("\t%s Amp: %sstep size: %f dB, # steps: %ld, offset to 0 dB: " 223 "%ld\n", input ? "In" : "Out", 224 (capabilities & AMP_CAP_MUTE) != 0 ? "supports mute, " : "", 225 AMP_CAP_STEP_SIZE(capabilities), 226 AMP_CAP_NUM_STEPS(capabilities), 227 AMP_CAP_OFFSET(capabilities)); 228 } 229 230 231 static void 232 dump_widget_pm_support(hda_widget& widget) 233 { 234 TRACE("\tSupported power states: %s%s%s%s\n", 235 widget.pm & POWER_STATE_D0 ? "D0 " : "", 236 widget.pm & POWER_STATE_D1 ? "D1 " : "", 237 widget.pm & POWER_STATE_D2 ? "D2 " : "", 238 widget.pm & POWER_STATE_D3 ? "D3 " : ""); 239 } 240 241 242 static void 243 dump_widget_stream_support(hda_widget& widget) 244 { 245 TRACE("\tSupported formats: %s%s%s%s%s%s%s%s%s\n", 246 widget.d.io.formats & B_FMT_8BIT_S ? "8bits " : "", 247 widget.d.io.formats & B_FMT_16BIT ? "16bits " : "", 248 widget.d.io.formats & B_FMT_20BIT ? "20bits " : "", 249 widget.d.io.formats & B_FMT_24BIT ? "24bits " : "", 250 widget.d.io.formats & B_FMT_32BIT ? "32bits " : "", 251 widget.d.io.formats & B_FMT_FLOAT ? "float " : "", 252 widget.d.io.formats & B_FMT_DOUBLE ? "double " : "", 253 widget.d.io.formats & B_FMT_EXTENDED ? "extended " : "", 254 widget.d.io.formats & B_FMT_BITSTREAM ? "bitstream " : ""); 255 TRACE("\tSupported rates: %s%s%s%s%s%s%s%s%s%s%s%s\n", 256 widget.d.io.rates & B_SR_8000 ? "8khz " : "", 257 widget.d.io.rates & B_SR_11025 ? "11khz " : "", 258 widget.d.io.rates & B_SR_16000 ? "16khz " : "", 259 widget.d.io.rates & B_SR_22050 ? "22khz " : "", 260 widget.d.io.rates & B_SR_32000 ? "32khz " : "", 261 widget.d.io.rates & B_SR_44100 ? "44khz " : "", 262 widget.d.io.rates & B_SR_48000 ? "48khz " : "", 263 widget.d.io.rates & B_SR_88200 ? "88khz " : "", 264 widget.d.io.rates & B_SR_96000 ? "96khz " : "", 265 widget.d.io.rates & B_SR_176400 ? "176khz " : "", 266 widget.d.io.rates & B_SR_192000 ? "192khz " : "", 267 widget.d.io.rates & B_SR_384000 ? "384khz " : ""); 268 269 } 270 271 272 static void 273 dump_pin_complex_capabilities(hda_widget& widget) 274 { 275 TRACE("\t%s%s%s%s%s%s%s%s%s%s%s%s%s\n", 276 widget.d.pin.capabilities & PIN_CAP_IMP_SENSE ? "[Imp Sense] " : "", 277 widget.d.pin.capabilities & PIN_CAP_TRIGGER_REQ ? "[Trigger Req]" : "", 278 widget.d.pin.capabilities & PIN_CAP_PRES_DETECT ? "[Pres Detect]" : "", 279 widget.d.pin.capabilities & PIN_CAP_HP_DRIVE ? "[HP Drive]" : "", 280 widget.d.pin.capabilities & PIN_CAP_OUTPUT ? "[Output]" : "", 281 widget.d.pin.capabilities & PIN_CAP_INPUT ? "[Input]" : "", 282 widget.d.pin.capabilities & PIN_CAP_BALANCE ? "[Balance]" : "", 283 widget.d.pin.capabilities & PIN_CAP_VREF_CTRL_HIZ ? "[VRef HIZ]" : "", 284 widget.d.pin.capabilities & PIN_CAP_VREF_CTRL_50 ? "[VRef 50]" : "", 285 widget.d.pin.capabilities & PIN_CAP_VREF_CTRL_GROUND ? "[VRef Gr]" : "", 286 widget.d.pin.capabilities & PIN_CAP_VREF_CTRL_80 ? "[VRef 80]" : "", 287 widget.d.pin.capabilities & PIN_CAP_VREF_CTRL_100 ? "[VRef 100]" : "", 288 widget.d.pin.capabilities & PIN_CAP_EAPD_CAP ? "[EAPD]" : ""); 289 } 290 291 292 static void 293 dump_audiogroup_widgets(hda_audio_group* audioGroup) 294 { 295 TRACE("\tAudiogroup:\n"); 296 /* Iterate over all Widgets and collect info */ 297 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 298 hda_widget& widget = audioGroup->widgets[i]; 299 uint32 nodeID = audioGroup->widget_start + i; 300 301 TRACE("%ld: %s\n", nodeID, get_widget_type_name(widget.type)); 302 303 switch (widget.type) { 304 case WT_AUDIO_OUTPUT: 305 case WT_AUDIO_INPUT: 306 break; 307 308 case WT_PIN_COMPLEX: 309 dump_pin_complex_capabilities(widget); 310 break; 311 312 default: 313 break; 314 } 315 316 dump_widget_pm_support(widget); 317 dump_widget_audio_capabilities(widget.capabilities.audio); 318 dump_widget_amplifier_capabilities(widget, true); 319 dump_widget_amplifier_capabilities(widget, false); 320 dump_widget_inputs(widget); 321 } 322 } 323 324 325 // #pragma mark - 326 327 328 static status_t 329 hda_get_pm_support(hda_codec* codec, uint32 nodeID, uint32* pm) 330 { 331 corb_t verb = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER, 332 PID_POWERSTATE_SUPPORT); 333 status_t rc; 334 uint32 response; 335 336 if ((rc = hda_send_verbs(codec, &verb, &response, 1)) == B_OK) { 337 *pm = response & 0xf; 338 } 339 340 return rc; 341 } 342 343 344 static status_t 345 hda_get_stream_support(hda_codec* codec, uint32 nodeID, uint32* formats, 346 uint32* rates) 347 { 348 corb_t verbs[2]; 349 uint32 resp[2]; 350 status_t status; 351 352 verbs[0] = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER, 353 PID_STREAM_SUPPORT); 354 verbs[1] = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER, 355 PID_PCM_SUPPORT); 356 357 status = hda_send_verbs(codec, verbs, resp, 2); 358 if (status != B_OK) 359 return status; 360 361 *formats = 0; 362 *rates = 0; 363 364 if ((resp[0] & (STREAM_FLOAT | STREAM_PCM)) != 0) { 365 if (resp[1] & (1 << 0)) 366 *rates |= B_SR_8000; 367 if (resp[1] & (1 << 1)) 368 *rates |= B_SR_11025; 369 if (resp[1] & (1 << 2)) 370 *rates |= B_SR_16000; 371 if (resp[1] & (1 << 3)) 372 *rates |= B_SR_22050; 373 if (resp[1] & (1 << 4)) 374 *rates |= B_SR_32000; 375 if (resp[1] & (1 << 5)) 376 *rates |= B_SR_44100; 377 if (resp[1] & (1 << 6)) 378 *rates |= B_SR_48000; 379 if (resp[1] & (1 << 7)) 380 *rates |= B_SR_88200; 381 if (resp[1] & (1 << 8)) 382 *rates |= B_SR_96000; 383 if (resp[1] & (1 << 9)) 384 *rates |= B_SR_176400; 385 if (resp[1] & (1 << 10)) 386 *rates |= B_SR_192000; 387 if (resp[1] & (1 << 11)) 388 *rates |= B_SR_384000; 389 390 if (resp[1] & PCM_8_BIT) 391 *formats |= B_FMT_8BIT_S; 392 if (resp[1] & PCM_16_BIT) 393 *formats |= B_FMT_16BIT; 394 if (resp[1] & PCM_20_BIT) 395 *formats |= B_FMT_20BIT; 396 if (resp[1] & PCM_24_BIT) 397 *formats |= B_FMT_24BIT; 398 if (resp[1] & PCM_32_BIT) 399 *formats |= B_FMT_32BIT; 400 } 401 if ((resp[0] & STREAM_FLOAT) != 0) 402 *formats |= B_FMT_FLOAT; 403 if ((resp[0] & STREAM_AC3) != 0) { 404 *formats |= B_FMT_BITSTREAM; 405 } 406 407 return B_OK; 408 } 409 410 411 // #pragma mark - widget functions 412 413 414 static status_t 415 hda_widget_get_pm_support(hda_audio_group* audioGroup, hda_widget* widget) 416 { 417 return hda_get_pm_support(audioGroup->codec, widget->node_id, 418 &widget->pm); 419 } 420 421 422 static status_t 423 hda_widget_get_stream_support(hda_audio_group* audioGroup, hda_widget* widget) 424 { 425 if (audioGroup->widget.node_id != widget->node_id 426 && (widget->capabilities.audio & AUDIO_CAP_FORMAT_OVERRIDE) == 0) { 427 // adopt capabilities of the audio group 428 widget->d.io.formats = audioGroup->widget.d.io.formats; 429 widget->d.io.rates = audioGroup->widget.d.io.rates; 430 return B_OK; 431 } 432 433 return hda_get_stream_support(audioGroup->codec, widget->node_id, 434 &widget->d.io.formats, &widget->d.io.rates); 435 } 436 437 438 static status_t 439 hda_widget_get_amplifier_capabilities(hda_audio_group* audioGroup, 440 hda_widget* widget) 441 { 442 uint32 response; 443 corb_t verb; 444 445 if ((widget->capabilities.audio & AUDIO_CAP_OUTPUT_AMPLIFIER) != 0 446 || audioGroup->widget.node_id == widget->node_id) { 447 if ((widget->capabilities.audio & AUDIO_CAP_AMPLIFIER_OVERRIDE) != 0 448 || audioGroup->widget.node_id == widget->node_id) { 449 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 450 VID_GET_PARAMETER, PID_OUTPUT_AMPLIFIER_CAP); 451 status_t status = hda_send_verbs(audioGroup->codec, &verb, 452 &response, 1); 453 if (status < B_OK) 454 return status; 455 456 widget->capabilities.output_amplifier = response; 457 } else { 458 // adopt capabilities from the audio function group 459 widget->capabilities.output_amplifier 460 = audioGroup->widget.capabilities.output_amplifier; 461 } 462 } 463 464 if ((widget->capabilities.audio & AUDIO_CAP_INPUT_AMPLIFIER) != 0 465 || audioGroup->widget.node_id == widget->node_id) { 466 if ((widget->capabilities.audio & AUDIO_CAP_AMPLIFIER_OVERRIDE 467 || audioGroup->widget.node_id == widget->node_id) != 0) { 468 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 469 VID_GET_PARAMETER, PID_INPUT_AMPLIFIER_CAP); 470 status_t status = hda_send_verbs(audioGroup->codec, &verb, 471 &response, 1); 472 if (status < B_OK) 473 return status; 474 475 widget->capabilities.input_amplifier = response; 476 } else { 477 // adopt capabilities from the audio function group 478 widget->capabilities.input_amplifier 479 = audioGroup->widget.capabilities.input_amplifier; 480 } 481 } 482 483 return B_OK; 484 } 485 486 487 hda_widget* 488 hda_audio_group_get_widget(hda_audio_group* audioGroup, uint32 nodeID) 489 { 490 if (audioGroup->widget_start > nodeID 491 || audioGroup->widget_start + audioGroup->widget_count < nodeID) 492 return NULL; 493 494 return &audioGroup->widgets[nodeID - audioGroup->widget_start]; 495 } 496 497 498 static status_t 499 hda_widget_get_connections(hda_audio_group* audioGroup, hda_widget* widget) 500 { 501 corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 502 VID_GET_PARAMETER, PID_CONNECTION_LIST_LENGTH); 503 uint32 response; 504 505 if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) != B_OK) 506 return B_ERROR; 507 508 uint32 listEntries = response & 0x7f; 509 bool longForm = (response & 0xf0) != 0; 510 511 if (listEntries == 0) 512 return B_OK; 513 514 #if 1 515 if (widget->num_inputs > 1) { 516 // Get currently active connection 517 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 518 VID_GET_CONNECTION_SELECT, 0); 519 if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) == B_OK) 520 widget->active_input = response & 0xff; 521 } 522 #endif 523 524 uint32 valuesPerEntry = longForm ? 2 : 4; 525 uint32 shift = 32 / valuesPerEntry; 526 uint32 rangeMask = (1 << (shift - 1)); 527 int32 previousInput = -1; 528 uint32 numInputs = 0; 529 530 for (uint32 i = 0; i < listEntries; i++) { 531 if ((i % valuesPerEntry) == 0) { 532 // We get 2 or 4 answers per call depending on if we're 533 // in short or long list mode 534 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 535 VID_GET_CONNECTION_LIST_ENTRY, i); 536 if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) 537 != B_OK) { 538 ERROR("hda: Error parsing inputs for widget %ld!\n", 539 widget->node_id); 540 break; 541 } 542 } 543 544 int32 input = (response >> (shift * (i % valuesPerEntry))) 545 & ((1 << shift) - 1); 546 547 if (input & rangeMask) { 548 // found range 549 input &= ~rangeMask; 550 551 if (input < previousInput || previousInput == -1) { 552 ERROR("hda: invalid range from %ld to %ld\n", previousInput, 553 input); 554 continue; 555 } 556 557 for (int32 rangeInput = previousInput + 1; rangeInput <= input 558 && numInputs < MAX_INPUTS; rangeInput++) { 559 widget->inputs[numInputs++] = rangeInput; 560 } 561 562 previousInput = -1; 563 } else if (numInputs < MAX_INPUTS) { 564 // standard value 565 widget->inputs[numInputs++] = input; 566 previousInput = input; 567 } 568 } 569 570 widget->num_inputs = numInputs; 571 572 if (widget->num_inputs == 1) 573 widget->active_input = 0; 574 575 return B_OK; 576 } 577 578 579 static status_t 580 hda_widget_get_associations(hda_audio_group* audioGroup) 581 { 582 uint32 index = 0; 583 for (uint32 i = 0; i < MAX_ASSOCIATIONS; i++) { 584 for (uint32 j = 0; j < audioGroup->widget_count; j++) { 585 hda_widget& widget = audioGroup->widgets[j]; 586 587 if (widget.type != WT_PIN_COMPLEX) 588 continue; 589 if (CONF_DEFAULT_ASSOCIATION(widget.d.pin.config) != i) 590 continue; 591 if (audioGroup->associations[index].pin_count == 0) { 592 audioGroup->associations[index].index = index; 593 audioGroup->associations[index].enabled = true; 594 } 595 uint32 sequence = CONF_DEFAULT_SEQUENCE(widget.d.pin.config); 596 if (audioGroup->associations[index].pins[sequence] != 0) { 597 audioGroup->associations[index].enabled = false; 598 } 599 audioGroup->associations[index].pins[sequence] = widget.node_id; 600 audioGroup->associations[index].pin_count++; 601 if (i == 15) 602 index++; 603 } 604 if (i != 15 && audioGroup->associations[index].pin_count != 0) 605 index++; 606 } 607 audioGroup->association_count = index; 608 609 return B_OK; 610 } 611 612 613 static uint32 614 hda_widget_prepare_pin_ctrl(hda_audio_group* audioGroup, hda_widget *widget, 615 bool isOutput) 616 { 617 uint32 ctrl = 0; 618 if (isOutput) 619 ctrl = PIN_ENABLE_HEAD_PHONE | PIN_ENABLE_OUTPUT; 620 else 621 ctrl = PIN_ENABLE_INPUT; 622 623 if (PIN_CAP_IS_VREF_CTRL_50_CAP(widget->d.pin.capabilities) 624 && (audioGroup->codec->quirks & (isOutput ? HDA_QUIRK_OVREF50 625 : HDA_QUIRK_IVREF50))) { 626 ctrl |= PIN_ENABLE_VREF_50; 627 TRACE("%s vref 50 enabled\n", isOutput ? "output" : "input"); 628 } 629 if (PIN_CAP_IS_VREF_CTRL_80_CAP(widget->d.pin.capabilities) 630 && (audioGroup->codec->quirks & (isOutput ? HDA_QUIRK_OVREF80 631 : HDA_QUIRK_IVREF80))) { 632 ctrl |= PIN_ENABLE_VREF_80; 633 TRACE("%s vref 80 enabled\n", isOutput ? "output" : "input"); 634 } 635 if (PIN_CAP_IS_VREF_CTRL_100_CAP(widget->d.pin.capabilities) 636 && (audioGroup->codec->quirks & (isOutput ? HDA_QUIRK_OVREF100 637 : HDA_QUIRK_IVREF100))) { 638 ctrl |= PIN_ENABLE_VREF_100; 639 TRACE("%s vref 100 enabled\n", isOutput ? "output" : "input"); 640 } 641 642 return ctrl; 643 } 644 645 646 // #pragma mark - audio group functions 647 648 649 static status_t 650 hda_codec_parse_audio_group(hda_audio_group* audioGroup) 651 { 652 corb_t verbs[3]; 653 uint32 resp[3]; 654 655 hda_widget_get_stream_support(audioGroup, &audioGroup->widget); 656 hda_widget_get_pm_support(audioGroup, &audioGroup->widget); 657 hda_widget_get_amplifier_capabilities(audioGroup, &audioGroup->widget); 658 659 verbs[0] = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id, 660 VID_GET_PARAMETER, PID_AUDIO_GROUP_CAP); 661 verbs[1] = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id, 662 VID_GET_PARAMETER, PID_GPIO_COUNT); 663 verbs[2] = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id, 664 VID_GET_PARAMETER, PID_SUB_NODE_COUNT); 665 666 if (hda_send_verbs(audioGroup->codec, verbs, resp, 3) != B_OK) 667 return B_ERROR; 668 669 TRACE("hda: Audio Group: Output delay: %ld samples, Input delay: %ld " 670 "samples, Beep Generator: %s\n", AUDIO_GROUP_CAP_OUTPUT_DELAY(resp[0]), 671 AUDIO_GROUP_CAP_INPUT_DELAY(resp[0]), 672 AUDIO_GROUP_CAP_BEEPGEN(resp[0]) ? "yes" : "no"); 673 674 TRACE("hda: #GPIO: %ld, #GPO: %ld, #GPI: %ld, unsol: %s, wake: %s\n", 675 GPIO_COUNT_NUM_GPIO(resp[1]), GPIO_COUNT_NUM_GPO(resp[1]), 676 GPIO_COUNT_NUM_GPI(resp[1]), GPIO_COUNT_GPIUNSOL(resp[1]) ? "yes" : "no", 677 GPIO_COUNT_GPIWAKE(resp[1]) ? "yes" : "no"); 678 dump_widget_stream_support(audioGroup->widget); 679 680 audioGroup->gpio = resp[1]; 681 audioGroup->widget_start = SUB_NODE_COUNT_START(resp[2]); 682 audioGroup->widget_count = SUB_NODE_COUNT_TOTAL(resp[2]); 683 684 TRACE("hda: widget start %lu, count %lu\n", audioGroup->widget_start, 685 audioGroup->widget_count); 686 687 audioGroup->widgets = (hda_widget*)calloc(audioGroup->widget_count, 688 sizeof(*audioGroup->widgets)); 689 if (audioGroup->widgets == NULL) { 690 ERROR("ERROR: Not enough memory!\n"); 691 return B_NO_MEMORY; 692 } 693 694 /* Iterate over all Widgets and collect info */ 695 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 696 hda_widget& widget = audioGroup->widgets[i]; 697 uint32 nodeID = audioGroup->widget_start + i; 698 uint32 capabilities; 699 700 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, VID_GET_PARAMETER, 701 PID_AUDIO_WIDGET_CAP); 702 if (hda_send_verbs(audioGroup->codec, verbs, &capabilities, 1) != B_OK) 703 return B_ERROR; 704 705 widget.type = (hda_widget_type)((capabilities & AUDIO_CAP_TYPE_MASK) 706 >> AUDIO_CAP_TYPE_SHIFT); 707 708 /* Check specific node ids declared as inputs as beepers */ 709 switch ((audioGroup->codec->vendor_id << 16) | audioGroup->codec->product_id) { 710 case 0x11d41882: 711 case 0x11d41883: 712 case 0x11d41884: 713 case 0x11d4194a: 714 case 0x11d4194b: 715 case 0x11d41987: 716 case 0x11d41988: 717 case 0x11d4198b: 718 case 0x11d4989b: 719 if (nodeID == 26) 720 widget.type = WT_BEEP_GENERATOR; 721 break; 722 case 0x10ec0260: 723 if (nodeID == 23) 724 widget.type = WT_BEEP_GENERATOR; 725 break; 726 case 0x10ec0262: 727 case 0x10ec0268: 728 case 0x10ec0880: 729 case 0x10ec0882: 730 case 0x10ec0883: 731 case 0x10ec0885: 732 case 0x10ec0888: 733 case 0x10ec0889: 734 if (nodeID == 29) 735 widget.type = WT_BEEP_GENERATOR; 736 break; 737 } 738 widget.active_input = -1; 739 widget.capabilities.audio = capabilities; 740 widget.node_id = nodeID; 741 742 if ((capabilities & AUDIO_CAP_POWER_CONTROL) != 0) { 743 /* We support power; switch us on! */ 744 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 745 VID_SET_POWER_STATE, 0); 746 hda_send_verbs(audioGroup->codec, verbs, NULL, 1); 747 748 snooze(1000); 749 } 750 if ((capabilities & (AUDIO_CAP_INPUT_AMPLIFIER 751 | AUDIO_CAP_OUTPUT_AMPLIFIER)) != 0) { 752 hda_widget_get_amplifier_capabilities(audioGroup, &widget); 753 } 754 755 TRACE("%ld: %s\n", nodeID, get_widget_type_name(widget.type)); 756 757 switch (widget.type) { 758 case WT_AUDIO_OUTPUT: 759 case WT_AUDIO_INPUT: 760 hda_widget_get_stream_support(audioGroup, &widget); 761 dump_widget_stream_support(widget); 762 break; 763 764 case WT_PIN_COMPLEX: 765 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 766 VID_GET_PARAMETER, PID_PIN_CAP); 767 if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) == B_OK) { 768 widget.d.pin.capabilities = resp[0]; 769 770 TRACE("\t%s%s\n", PIN_CAP_IS_INPUT(resp[0]) ? "[Input] " : "", 771 PIN_CAP_IS_OUTPUT(resp[0]) ? "[Output]" : ""); 772 } else { 773 ERROR("%s: Error getting Pin Complex IO\n", __func__); 774 } 775 776 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 777 VID_GET_CONFIGURATION_DEFAULT, 0); 778 if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) == B_OK) { 779 widget.d.pin.config = resp[0]; 780 const char* location = 781 get_widget_location(CONF_DEFAULT_LOCATION(resp[0])); 782 TRACE("\t%s, %s%s%s, %s, %s, Association:%ld\n", 783 kPortConnector[CONF_DEFAULT_CONNECTIVITY(resp[0])], 784 location ? location : "", 785 location ? " " : "", 786 kDefaultDevice[CONF_DEFAULT_DEVICE(resp[0])], 787 kConnectionType[CONF_DEFAULT_CONNTYPE(resp[0])], 788 kJackColor[CONF_DEFAULT_COLOR(resp[0])], 789 CONF_DEFAULT_ASSOCIATION(resp[0])); 790 } 791 break; 792 793 case WT_VOLUME_KNOB: 794 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 795 VID_SET_VOLUME_KNOB_CONTROL, 0x0); 796 hda_send_verbs(audioGroup->codec, verbs, NULL, 1); 797 break; 798 default: 799 break; 800 } 801 802 hda_widget_get_pm_support(audioGroup, &widget); 803 hda_widget_get_connections(audioGroup, &widget); 804 805 dump_widget_pm_support(widget); 806 dump_widget_audio_capabilities(capabilities); 807 dump_widget_amplifier_capabilities(widget, true); 808 dump_widget_amplifier_capabilities(widget, false); 809 dump_widget_inputs(widget); 810 } 811 812 hda_widget_get_associations(audioGroup); 813 814 return B_OK; 815 } 816 817 818 /*! Find output path for widget */ 819 static bool 820 hda_widget_find_output_path(hda_audio_group* audioGroup, hda_widget* widget, 821 uint32 depth) 822 { 823 if (widget == NULL || depth > 16) 824 return false; 825 826 switch (widget->type) { 827 case WT_AUDIO_OUTPUT: 828 widget->flags |= WIDGET_FLAG_OUTPUT_PATH; 829 TRACE(" %*soutput: added output widget %ld\n", (int)depth * 2, "", widget->node_id); 830 return true; 831 832 case WT_AUDIO_MIXER: 833 case WT_AUDIO_SELECTOR: 834 { 835 // already used 836 if (widget->flags & WIDGET_FLAG_OUTPUT_PATH) 837 return false; 838 839 // search for output in this path 840 bool found = false; 841 for (uint32 i = 0; i < widget->num_inputs; i++) { 842 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 843 widget->inputs[i]); 844 845 if (hda_widget_find_output_path(audioGroup, inputWidget, 846 depth + 1)) { 847 if (widget->active_input == -1) 848 widget->active_input = i; 849 850 widget->flags |= WIDGET_FLAG_OUTPUT_PATH; 851 TRACE(" %*soutput: added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 852 found = true; 853 } 854 } 855 if (!found) TRACE(" %*soutput: not added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 856 return found; 857 } 858 859 default: 860 return false; 861 } 862 } 863 864 865 /*! Find input path for widget */ 866 static bool 867 hda_widget_find_input_path(hda_audio_group* audioGroup, hda_widget* widget, 868 uint32 depth) 869 { 870 if (widget == NULL || depth > 16) 871 return false; 872 873 switch (widget->type) { 874 case WT_PIN_COMPLEX: 875 // already used 876 if (widget->flags & WIDGET_FLAG_INPUT_PATH) 877 return false; 878 879 if (PIN_CAP_IS_INPUT(widget->d.pin.capabilities)) { 880 switch (CONF_DEFAULT_DEVICE(widget->d.pin.config)) { 881 case PIN_DEV_CD: 882 case PIN_DEV_LINE_IN: 883 case PIN_DEV_MIC_IN: 884 widget->flags |= WIDGET_FLAG_INPUT_PATH; 885 TRACE(" %*sinput: added input widget %ld\n", (int)depth * 2, "", widget->node_id); 886 return true; 887 break; 888 } 889 } 890 return false; 891 case WT_AUDIO_INPUT: 892 case WT_AUDIO_MIXER: 893 case WT_AUDIO_SELECTOR: 894 { 895 // already used 896 if (widget->flags & WIDGET_FLAG_INPUT_PATH) 897 return false; 898 899 // search for pin complex in this path 900 bool found = false; 901 for (uint32 i = 0; i < widget->num_inputs; i++) { 902 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 903 widget->inputs[i]); 904 905 if (hda_widget_find_input_path(audioGroup, inputWidget, 906 depth + 1)) { 907 if (widget->active_input == -1) 908 widget->active_input = i; 909 910 widget->flags |= WIDGET_FLAG_INPUT_PATH; 911 TRACE(" %*sinput: added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 912 found = true; 913 } 914 } 915 if (!found) TRACE(" %*sinput: not added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 916 return found; 917 } 918 919 default: 920 return false; 921 } 922 } 923 924 static bool 925 hda_audio_group_build_output_tree(hda_audio_group* audioGroup, bool useMixer) 926 { 927 bool found = false; 928 929 TRACE("build output tree: %suse mixer\n", useMixer ? "" : "don't "); 930 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 931 hda_widget& widget = audioGroup->widgets[i]; 932 933 if (widget.type != WT_PIN_COMPLEX || !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities)) 934 continue; 935 936 int device = CONF_DEFAULT_DEVICE(widget.d.pin.config); 937 if (device != PIN_DEV_HEAD_PHONE_OUT 938 && device != PIN_DEV_SPEAKER 939 && device != PIN_DEV_LINE_OUT) 940 continue; 941 942 TRACE(" look at pin widget %ld (%ld inputs)\n", widget.node_id, widget.num_inputs); 943 for (uint32 j = 0; j < widget.num_inputs; j++) { 944 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 945 widget.inputs[j]); 946 TRACE(" try widget %ld: %p\n", widget.inputs[j], inputWidget); 947 if (inputWidget == NULL) 948 continue; 949 950 if (useMixer && inputWidget->type != WT_AUDIO_MIXER 951 && inputWidget->type != WT_AUDIO_SELECTOR) 952 continue; 953 TRACE(" widget %ld is candidate\n", inputWidget->node_id); 954 955 if (hda_widget_find_output_path(audioGroup, inputWidget, 0)) { 956 TRACE(" add pin widget %ld\n", widget.node_id); 957 if (widget.active_input == -1) 958 widget.active_input = j; 959 widget.flags |= WIDGET_FLAG_OUTPUT_PATH; 960 found = true; 961 break; 962 } 963 } 964 } 965 966 return found; 967 } 968 969 970 static bool 971 hda_audio_group_build_input_tree(hda_audio_group* audioGroup) 972 { 973 bool found = false; 974 975 TRACE("build input tree\n"); 976 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 977 hda_widget& widget = audioGroup->widgets[i]; 978 979 if (widget.type != WT_AUDIO_INPUT) 980 continue; 981 982 TRACE(" look at input widget %ld (%ld inputs)\n", widget.node_id, widget.num_inputs); 983 for (uint32 j = 0; j < widget.num_inputs; j++) { 984 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 985 widget.inputs[j]); 986 TRACE(" try widget %ld: %p\n", widget.inputs[j], inputWidget); 987 if (inputWidget == NULL) 988 continue; 989 990 TRACE(" widget %ld is candidate\n", inputWidget->node_id); 991 992 if (hda_widget_find_input_path(audioGroup, inputWidget, 0)) { 993 TRACE(" add pin widget %ld\n", widget.node_id); 994 if (widget.active_input == -1) 995 widget.active_input = j; 996 widget.flags |= WIDGET_FLAG_INPUT_PATH; 997 found = true; 998 break; 999 } 1000 } 1001 } 1002 1003 return found; 1004 } 1005 1006 1007 static status_t 1008 hda_audio_group_build_tree(hda_audio_group* audioGroup) 1009 { 1010 if (!hda_audio_group_build_output_tree(audioGroup, true)) { 1011 // didn't find a mixer path, try again without 1012 TRACE("try without mixer!\n"); 1013 if (!hda_audio_group_build_output_tree(audioGroup, false)) 1014 return ENODEV; 1015 } 1016 1017 if (!hda_audio_group_build_input_tree(audioGroup)) { 1018 ERROR("hda: build input tree failed\n"); 1019 } 1020 1021 TRACE("build tree!\n"); 1022 1023 // select active connections 1024 1025 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 1026 hda_widget& widget = audioGroup->widgets[i]; 1027 1028 if (widget.active_input == -1) 1029 widget.active_input = 0; 1030 if (widget.num_inputs < 2) 1031 continue; 1032 1033 if (widget.type != WT_AUDIO_INPUT 1034 && widget.type != WT_AUDIO_SELECTOR 1035 && widget.type != WT_PIN_COMPLEX) 1036 continue; 1037 1038 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 1039 widget.node_id, VID_SET_CONNECTION_SELECT, widget.active_input); 1040 if (hda_send_verbs(audioGroup->codec, &verb, NULL, 1) != B_OK) 1041 ERROR("hda: Setting output selector %ld failed on widget %ld!\n", 1042 widget.active_input, widget.node_id); 1043 } 1044 1045 // GPIO 1046 uint32 gpio = 0; 1047 for (int32 i = 0; i < GPIO_COUNT_NUM_GPIO(audioGroup->gpio) 1048 && i < HDA_QUIRK_GPIO_COUNT; i++) { 1049 if (audioGroup->codec->quirks & (1 << i)) { 1050 gpio |= (1 << i); 1051 } 1052 } 1053 1054 if (gpio != 0) { 1055 corb_t verb[] = { 1056 MAKE_VERB(audioGroup->codec->addr, 1057 audioGroup->widget.node_id, VID_SET_GPIO_DATA, gpio), 1058 MAKE_VERB(audioGroup->codec->addr, 1059 audioGroup->widget.node_id, VID_SET_GPIO_EN, gpio), 1060 MAKE_VERB(audioGroup->codec->addr, 1061 audioGroup->widget.node_id, VID_SET_GPIO_DIR, gpio) 1062 }; 1063 TRACE("hda: Setting gpio 0x%lx\n", gpio); 1064 if (hda_send_verbs(audioGroup->codec, verb, NULL, 3) != B_OK) 1065 ERROR("hda: Setting gpio failed!\n"); 1066 } 1067 1068 dump_audiogroup_widgets(audioGroup); 1069 1070 return B_OK; 1071 } 1072 1073 1074 static void 1075 hda_codec_switch_init(hda_audio_group* audioGroup) 1076 { 1077 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 1078 hda_widget& widget = audioGroup->widgets[i]; 1079 if (widget.type != WT_PIN_COMPLEX) 1080 continue; 1081 1082 if ((widget.capabilities.audio & AUDIO_CAP_UNSOLICITED_RESPONSES) != 0 1083 && (widget.d.pin.capabilities & PIN_CAP_PRES_DETECT) != 0 1084 && (CONF_DEFAULT_MISC(widget.d.pin.config) & 1) == 0) { 1085 corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id, 1086 VID_SET_UNSOLRESP, UNSOLRESP_ENABLE); 1087 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1088 TRACE("hda: Enabled unsolicited responses on widget %ld\n", 1089 widget.node_id); 1090 } 1091 } 1092 } 1093 1094 1095 static status_t 1096 hda_codec_switch_handler(hda_codec* codec) 1097 { 1098 while (acquire_sem(codec->unsol_response_sem) == B_OK) { 1099 uint32 response = codec->unsol_responses[codec->unsol_response_read++]; 1100 codec->unsol_response_read %= MAX_CODEC_UNSOL_RESPONSES; 1101 1102 bool disable = response & 1; 1103 hda_audio_group* audioGroup = codec->audio_groups[0]; 1104 1105 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 1106 hda_widget& widget = audioGroup->widgets[i]; 1107 1108 if (widget.type != WT_PIN_COMPLEX || !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities)) 1109 continue; 1110 1111 int device = CONF_DEFAULT_DEVICE(widget.d.pin.config); 1112 if (device != PIN_DEV_SPEAKER 1113 && device != PIN_DEV_LINE_OUT) 1114 continue; 1115 1116 uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget, 1117 true); 1118 corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id, 1119 VID_SET_PIN_WIDGET_CONTROL, disable ? 0 : ctrl); 1120 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1121 } 1122 } 1123 1124 return B_OK; 1125 } 1126 1127 1128 static void 1129 hda_codec_delete_audio_group(hda_audio_group* audioGroup) 1130 { 1131 if (audioGroup == NULL) 1132 return; 1133 1134 if (audioGroup->playback_stream != NULL) 1135 hda_stream_delete(audioGroup->playback_stream); 1136 1137 if (audioGroup->record_stream != NULL) 1138 hda_stream_delete(audioGroup->record_stream); 1139 free(audioGroup->multi); 1140 free(audioGroup->widgets); 1141 free(audioGroup); 1142 } 1143 1144 1145 static status_t 1146 hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID) 1147 { 1148 hda_audio_group* audioGroup = (hda_audio_group*)calloc(1, 1149 sizeof(hda_audio_group)); 1150 if (audioGroup == NULL) 1151 return B_NO_MEMORY; 1152 1153 /* Setup minimal info needed by hda_codec_parse_afg */ 1154 audioGroup->widget.node_id = audioGroupNodeID; 1155 audioGroup->codec = codec; 1156 audioGroup->multi = (hda_multi*)calloc(1, 1157 sizeof(hda_multi)); 1158 if (audioGroup->multi == NULL) 1159 return B_NO_MEMORY; 1160 audioGroup->multi->group = audioGroup; 1161 1162 /* Parse all widgets in Audio Function Group */ 1163 status_t status = hda_codec_parse_audio_group(audioGroup); 1164 if (status != B_OK) 1165 goto err; 1166 1167 /* Setup for worst-case scenario; we cannot find any output Pin Widgets */ 1168 status = ENODEV; 1169 1170 if (hda_audio_group_build_tree(audioGroup) != B_OK) 1171 goto err; 1172 hda_codec_switch_init(audioGroup); 1173 1174 audioGroup->playback_stream = hda_stream_new(audioGroup, STREAM_PLAYBACK); 1175 audioGroup->record_stream = hda_stream_new(audioGroup, STREAM_RECORD); 1176 TRACE("hda: streams playback %p, record %p\n", audioGroup->playback_stream, 1177 audioGroup->record_stream); 1178 1179 if (audioGroup->playback_stream != NULL 1180 || audioGroup->record_stream != NULL) { 1181 codec->audio_groups[codec->num_audio_groups++] = audioGroup; 1182 return B_OK; 1183 } 1184 1185 err: 1186 free(audioGroup->widgets); 1187 free(audioGroup); 1188 return status; 1189 } 1190 1191 1192 // #pragma mark - 1193 1194 1195 status_t 1196 hda_audio_group_get_widgets(hda_audio_group* audioGroup, hda_stream* stream) 1197 { 1198 hda_widget_type type; 1199 uint32 flags; 1200 1201 if (stream->type == STREAM_PLAYBACK) { 1202 type = WT_AUDIO_OUTPUT; 1203 flags = WIDGET_FLAG_OUTPUT_PATH; 1204 } else { 1205 // record 1206 type = WT_AUDIO_INPUT; 1207 flags = WIDGET_FLAG_INPUT_PATH; 1208 } 1209 1210 uint32 count = 0; 1211 1212 for (uint32 i = 0; i < audioGroup->widget_count && count < MAX_IO_WIDGETS; 1213 i++) { 1214 hda_widget& widget = audioGroup->widgets[i]; 1215 1216 if ((widget.flags & flags) != 0) { 1217 if (widget.type == WT_PIN_COMPLEX) { 1218 stream->pin_widget = widget.node_id; 1219 1220 uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget, 1221 flags == WIDGET_FLAG_OUTPUT_PATH); 1222 1223 TRACE("ENABLE pin widget %ld\n", widget.node_id); 1224 /* FIXME: Force Pin Widget to unmute; enable hp/output */ 1225 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 1226 widget.node_id, 1227 VID_SET_PIN_WIDGET_CONTROL, ctrl); 1228 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1229 1230 if (PIN_CAP_IS_EAPD_CAP(widget.d.pin.capabilities)) { 1231 uint32 result; 1232 verb = MAKE_VERB(audioGroup->codec->addr, 1233 widget.node_id, VID_GET_EAPDBTL_EN, 0); 1234 if (hda_send_verbs(audioGroup->codec, &verb, 1235 &result, 1) == B_OK) { 1236 result &= 0xff; 1237 verb = MAKE_VERB(audioGroup->codec->addr, 1238 widget.node_id, VID_SET_EAPDBTL_EN, 1239 result | EAPDBTL_ENABLE_EAPD); 1240 hda_send_verbs(audioGroup->codec, 1241 &verb, NULL, 1); 1242 TRACE("ENABLE EAPD pin widget %ld\n", widget.node_id); 1243 } 1244 } 1245 } 1246 1247 if (widget.capabilities.output_amplifier != 0) { 1248 TRACE("UNMUTE/SET OUTPUT GAIN widget %ld (offset %ld)\n", widget.node_id, 1249 AMP_CAP_OFFSET(widget.capabilities.output_amplifier)); 1250 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 1251 widget.node_id, 1252 VID_SET_AMPLIFIER_GAIN_MUTE, 1253 AMP_SET_OUTPUT | AMP_SET_LEFT_CHANNEL 1254 | AMP_SET_RIGHT_CHANNEL 1255 | AMP_CAP_OFFSET(widget.capabilities.output_amplifier)); 1256 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1257 } 1258 if (widget.capabilities.input_amplifier != 0) { 1259 TRACE("UNMUTE/SET INPUT GAIN widget %ld (offset %ld)\n", widget.node_id, 1260 AMP_CAP_OFFSET(widget.capabilities.input_amplifier)); 1261 for (uint32 i = 0; i < widget.num_inputs; i++) { 1262 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 1263 widget.node_id, 1264 VID_SET_AMPLIFIER_GAIN_MUTE, 1265 AMP_SET_INPUT | AMP_SET_LEFT_CHANNEL 1266 | AMP_SET_RIGHT_CHANNEL 1267 | AMP_SET_INPUT_INDEX(i) 1268 | ((widget.active_input == (int32)i) ? 0 : AMP_MUTE) 1269 | AMP_CAP_OFFSET(widget.capabilities.input_amplifier)); 1270 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1271 } 1272 } 1273 } 1274 1275 if (widget.type != type || (widget.flags & flags) == 0 1276 || (widget.capabilities.audio 1277 & (AUDIO_CAP_STEREO | AUDIO_CAP_DIGITAL)) != AUDIO_CAP_STEREO 1278 || widget.d.io.formats == 0) 1279 continue; 1280 1281 if (count == 0) { 1282 stream->sample_format = widget.d.io.formats; 1283 stream->sample_rate = widget.d.io.rates; 1284 } else { 1285 stream->sample_format &= widget.d.io.formats; 1286 stream->sample_rate &= widget.d.io.rates; 1287 } 1288 1289 stream->io_widgets[count++] = widget.node_id; 1290 } 1291 1292 if (count == 0) 1293 return B_ENTRY_NOT_FOUND; 1294 1295 stream->num_io_widgets = count; 1296 return B_OK; 1297 } 1298 1299 1300 static const struct { 1301 uint32 subsystem_vendor_id, subsystem_id; 1302 uint32 codec_vendor_id, codec_id; 1303 uint32 quirks, nonquirks; 1304 } hda_codec_quirks[] = { 1305 { HDA_ALL, HDA_ALL, HDA_ALL, HDA_ALL, HDA_QUIRK_IVREF, 0 }, 1306 { HDA_ALL, HDA_ALL, HDA_ALL, HDA_ALL, HDA_QUIRK_IVREF, 0 }, 1307 { 0x10de, 0xcb79, CIRRUSLOGIC_VENDORID, 0x4206, HDA_QUIRK_GPIO1 | HDA_QUIRK_GPIO3, 0 }, // MacBook Pro 5.5 1308 { 0x8384, 0x7680, SIGMATEL_VENDORID, 0x7680, HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0}, // Apple Intel Mac 1309 { 0x106b, 0x00a3, REALTEK_VENDORID, 0x0885, HDA_QUIRK_GPIO0, 0}, // MacBook 1310 }; 1311 1312 1313 void 1314 hda_codec_get_quirks(hda_codec* codec) 1315 { 1316 codec->quirks = 0; 1317 uint32 subsystem_id = codec->controller->pci_info.u.h0.subsystem_id; 1318 uint32 subsystem_vendor_id = codec->controller->pci_info.u.h0.subsystem_vendor_id; 1319 uint32 codec_vendor_id = codec->vendor_id; 1320 uint32 codec_id = codec->product_id; 1321 for (uint32 i = 0; i < (sizeof(hda_codec_quirks) 1322 / sizeof(hda_codec_quirks[0])); i++) { 1323 if (hda_codec_quirks[i].subsystem_id != 0xffffffff 1324 && hda_codec_quirks[i].subsystem_id != subsystem_id) 1325 continue; 1326 if (hda_codec_quirks[i].subsystem_vendor_id != 0xffffffff 1327 && hda_codec_quirks[i].subsystem_vendor_id != subsystem_vendor_id) 1328 continue; 1329 if (hda_codec_quirks[i].codec_vendor_id != 0xffffffff 1330 && hda_codec_quirks[i].codec_vendor_id != codec_vendor_id) 1331 continue; 1332 if (hda_codec_quirks[i].codec_id != 0xffffffff 1333 && hda_codec_quirks[i].codec_id != codec_id) 1334 continue; 1335 1336 codec->quirks |= hda_codec_quirks[i].quirks; 1337 codec->quirks &= ~(hda_codec_quirks[i].nonquirks); 1338 } 1339 } 1340 1341 1342 void 1343 hda_codec_delete(hda_codec* codec) 1344 { 1345 if (codec == NULL) 1346 return; 1347 1348 delete_sem(codec->response_sem); 1349 delete_sem(codec->unsol_response_sem); 1350 1351 int32 result; 1352 wait_for_thread(codec->unsol_response_thread, &result); 1353 1354 for (uint32 i = 0; i < codec->num_audio_groups; i++) { 1355 hda_codec_delete_audio_group(codec->audio_groups[i]); 1356 codec->audio_groups[i] = NULL; 1357 } 1358 1359 free(codec); 1360 } 1361 1362 1363 hda_codec* 1364 hda_codec_new(hda_controller* controller, uint32 codecAddress) 1365 { 1366 if (codecAddress > HDA_MAX_CODECS) 1367 return NULL; 1368 1369 hda_codec* codec = (hda_codec*)calloc(1, sizeof(hda_codec)); 1370 if (codec == NULL) { 1371 ERROR("hda: Failed to alloc a codec\n"); 1372 return NULL; 1373 } 1374 1375 codec->controller = controller; 1376 codec->addr = codecAddress; 1377 codec->response_sem = create_sem(0, "hda_codec_response_sem"); 1378 if (codec->response_sem < B_OK) { 1379 ERROR("hda: Failed to create semaphore\n"); 1380 goto err; 1381 } 1382 controller->codecs[codecAddress] = codec; 1383 1384 codec->unsol_response_sem = create_sem(0, "hda_codec_unsol_response_sem"); 1385 if (codec->unsol_response_sem < B_OK) { 1386 ERROR("hda: Failed to create semaphore\n"); 1387 goto err; 1388 } 1389 codec->unsol_response_read = 0; 1390 codec->unsol_response_write = 0; 1391 codec->unsol_response_thread = spawn_kernel_thread( 1392 (status_t(*)(void*))hda_codec_switch_handler, 1393 "hda_codec_unsol_thread", B_LOW_PRIORITY, codec); 1394 if (codec->unsol_response_thread < B_OK) { 1395 ERROR("hda: Failed to spawn thread\n"); 1396 goto err; 1397 } 1398 resume_thread(codec->unsol_response_thread); 1399 1400 struct { 1401 uint32 device : 16; 1402 uint32 vendor : 16; 1403 uint32 stepping : 8; 1404 uint32 revision : 8; 1405 uint32 minor : 4; 1406 uint32 major : 4; 1407 uint32 _reserved0 : 8; 1408 uint32 count : 8; 1409 uint32 _reserved1 : 8; 1410 uint32 start : 8; 1411 uint32 _reserved2 : 8; 1412 } response; 1413 corb_t verbs[3]; 1414 1415 verbs[0] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_VENDOR_ID); 1416 verbs[1] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_REVISION_ID); 1417 verbs[2] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, 1418 PID_SUB_NODE_COUNT); 1419 1420 if (hda_send_verbs(codec, verbs, (uint32*)&response, 3) != B_OK) { 1421 ERROR("hda: Failed to get vendor and revision parameters\n"); 1422 goto err; 1423 } 1424 1425 codec->vendor_id = response.vendor; 1426 codec->product_id = response.device; 1427 codec->stepping = response.stepping; 1428 codec->revision = response.revision; 1429 codec->minor = response.minor; 1430 codec->major = response.major; 1431 hda_codec_get_quirks(codec); 1432 1433 TRACE("Codec %ld Vendor: %04lx Product: %04lx, Revision: " 1434 "%lu.%lu.%lu.%lu\n", codecAddress, response.vendor, response.device, 1435 response.major, response.minor, response.revision, response.stepping); 1436 1437 for (uint32 nodeID = response.start; nodeID < response.start 1438 + response.count; nodeID++) { 1439 uint32 groupType; 1440 verbs[0] = MAKE_VERB(codecAddress, nodeID, VID_GET_PARAMETER, 1441 PID_FUNCTION_GROUP_TYPE); 1442 1443 if (hda_send_verbs(codec, verbs, &groupType, 1) != B_OK) { 1444 ERROR("hda: Failed to get function group type\n"); 1445 goto err; 1446 } 1447 1448 if ((groupType & FUNCTION_GROUP_NODETYPE_MASK) == FUNCTION_GROUP_NODETYPE_AUDIO) { 1449 /* Found an Audio Function Group! */ 1450 status_t status = hda_codec_new_audio_group(codec, nodeID); 1451 if (status != B_OK) { 1452 ERROR("hda: Failed to setup new audio function group (%s)!\n", 1453 strerror(status)); 1454 goto err; 1455 } 1456 } 1457 } 1458 1459 return codec; 1460 err: 1461 controller->codecs[codecAddress] = NULL; 1462 hda_codec_delete(codec); 1463 return NULL; 1464 } 1465