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 1109 || !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities) 1110 || CONF_DEFAULT_DEVICE(widget.d.pin.config) 1111 != PIN_DEV_HEAD_PHONE_OUT) 1112 continue; 1113 1114 corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id, 1115 VID_GET_PINSENSE, 0); 1116 uint32 response; 1117 hda_send_verbs(audioGroup->codec, &verb, &response, 1); 1118 disable = response & PIN_SENSE_PRESENCE_DETECT; 1119 TRACE("hda: sensed pin widget %ld, %d\n", widget.node_id, disable); 1120 break; 1121 } 1122 1123 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 1124 hda_widget& widget = audioGroup->widgets[i]; 1125 1126 if (widget.type != WT_PIN_COMPLEX 1127 || !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities)) 1128 continue; 1129 1130 int device = CONF_DEFAULT_DEVICE(widget.d.pin.config); 1131 if (device != PIN_DEV_AUX 1132 && device != PIN_DEV_SPEAKER 1133 && device != PIN_DEV_LINE_OUT) 1134 continue; 1135 1136 uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget, 1137 true); 1138 corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id, 1139 VID_SET_PIN_WIDGET_CONTROL, disable ? 0 : ctrl); 1140 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1141 } 1142 } 1143 1144 return B_OK; 1145 } 1146 1147 1148 static void 1149 hda_codec_delete_audio_group(hda_audio_group* audioGroup) 1150 { 1151 if (audioGroup == NULL) 1152 return; 1153 1154 if (audioGroup->playback_stream != NULL) 1155 hda_stream_delete(audioGroup->playback_stream); 1156 1157 if (audioGroup->record_stream != NULL) 1158 hda_stream_delete(audioGroup->record_stream); 1159 free(audioGroup->multi); 1160 free(audioGroup->widgets); 1161 free(audioGroup); 1162 } 1163 1164 1165 static status_t 1166 hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID) 1167 { 1168 hda_audio_group* audioGroup = (hda_audio_group*)calloc(1, 1169 sizeof(hda_audio_group)); 1170 if (audioGroup == NULL) 1171 return B_NO_MEMORY; 1172 1173 /* Setup minimal info needed by hda_codec_parse_afg */ 1174 audioGroup->widget.node_id = audioGroupNodeID; 1175 audioGroup->codec = codec; 1176 audioGroup->multi = (hda_multi*)calloc(1, 1177 sizeof(hda_multi)); 1178 if (audioGroup->multi == NULL) { 1179 free(audioGroup); 1180 return B_NO_MEMORY; 1181 } 1182 audioGroup->multi->group = audioGroup; 1183 1184 /* Parse all widgets in Audio Function Group */ 1185 status_t status = hda_codec_parse_audio_group(audioGroup); 1186 if (status != B_OK) 1187 goto err; 1188 1189 /* Setup for worst-case scenario; we cannot find any output Pin Widgets */ 1190 status = ENODEV; 1191 1192 if (hda_audio_group_build_tree(audioGroup) != B_OK) 1193 goto err; 1194 hda_codec_switch_init(audioGroup); 1195 1196 audioGroup->playback_stream = hda_stream_new(audioGroup, STREAM_PLAYBACK); 1197 audioGroup->record_stream = hda_stream_new(audioGroup, STREAM_RECORD); 1198 TRACE("hda: streams playback %p, record %p\n", audioGroup->playback_stream, 1199 audioGroup->record_stream); 1200 1201 if (audioGroup->playback_stream != NULL 1202 || audioGroup->record_stream != NULL) { 1203 codec->audio_groups[codec->num_audio_groups++] = audioGroup; 1204 return B_OK; 1205 } 1206 1207 err: 1208 free(audioGroup->widgets); 1209 free(audioGroup); 1210 return status; 1211 } 1212 1213 1214 // #pragma mark - 1215 1216 1217 status_t 1218 hda_audio_group_get_widgets(hda_audio_group* audioGroup, hda_stream* stream) 1219 { 1220 hda_widget_type type; 1221 uint32 flags; 1222 1223 if (stream->type == STREAM_PLAYBACK) { 1224 type = WT_AUDIO_OUTPUT; 1225 flags = WIDGET_FLAG_OUTPUT_PATH; 1226 } else { 1227 // record 1228 type = WT_AUDIO_INPUT; 1229 flags = WIDGET_FLAG_INPUT_PATH; 1230 } 1231 1232 uint32 count = 0; 1233 1234 for (uint32 i = 0; i < audioGroup->widget_count && count < MAX_IO_WIDGETS; 1235 i++) { 1236 hda_widget& widget = audioGroup->widgets[i]; 1237 1238 if ((widget.flags & flags) != 0) { 1239 if (widget.type == WT_PIN_COMPLEX) { 1240 stream->pin_widget = widget.node_id; 1241 1242 uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget, 1243 flags == WIDGET_FLAG_OUTPUT_PATH); 1244 1245 TRACE("ENABLE pin widget %ld\n", widget.node_id); 1246 /* FIXME: Force Pin Widget to unmute; enable hp/output */ 1247 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 1248 widget.node_id, 1249 VID_SET_PIN_WIDGET_CONTROL, ctrl); 1250 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1251 1252 if (PIN_CAP_IS_EAPD_CAP(widget.d.pin.capabilities)) { 1253 uint32 result; 1254 verb = MAKE_VERB(audioGroup->codec->addr, 1255 widget.node_id, VID_GET_EAPDBTL_EN, 0); 1256 if (hda_send_verbs(audioGroup->codec, &verb, 1257 &result, 1) == B_OK) { 1258 result &= 0xff; 1259 verb = MAKE_VERB(audioGroup->codec->addr, 1260 widget.node_id, VID_SET_EAPDBTL_EN, 1261 result | EAPDBTL_ENABLE_EAPD); 1262 hda_send_verbs(audioGroup->codec, 1263 &verb, NULL, 1); 1264 TRACE("ENABLE EAPD pin widget %ld\n", widget.node_id); 1265 } 1266 } 1267 } 1268 1269 if (widget.capabilities.output_amplifier != 0) { 1270 TRACE("UNMUTE/SET OUTPUT GAIN widget %ld (offset %ld)\n", widget.node_id, 1271 AMP_CAP_OFFSET(widget.capabilities.output_amplifier)); 1272 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 1273 widget.node_id, 1274 VID_SET_AMPLIFIER_GAIN_MUTE, 1275 AMP_SET_OUTPUT | AMP_SET_LEFT_CHANNEL 1276 | AMP_SET_RIGHT_CHANNEL 1277 | AMP_CAP_OFFSET(widget.capabilities.output_amplifier)); 1278 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1279 } 1280 if (widget.capabilities.input_amplifier != 0) { 1281 TRACE("UNMUTE/SET INPUT GAIN widget %ld (offset %ld)\n", widget.node_id, 1282 AMP_CAP_OFFSET(widget.capabilities.input_amplifier)); 1283 for (uint32 i = 0; i < widget.num_inputs; i++) { 1284 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 1285 widget.node_id, 1286 VID_SET_AMPLIFIER_GAIN_MUTE, 1287 AMP_SET_INPUT | AMP_SET_LEFT_CHANNEL 1288 | AMP_SET_RIGHT_CHANNEL 1289 | AMP_SET_INPUT_INDEX(i) 1290 | ((widget.active_input == (int32)i) ? 0 : AMP_MUTE) 1291 | AMP_CAP_OFFSET(widget.capabilities.input_amplifier)); 1292 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1293 } 1294 } 1295 } 1296 1297 if (widget.type != type || (widget.flags & flags) == 0 1298 || (widget.capabilities.audio 1299 & (AUDIO_CAP_STEREO | AUDIO_CAP_DIGITAL)) != AUDIO_CAP_STEREO 1300 || widget.d.io.formats == 0) 1301 continue; 1302 1303 if (count == 0) { 1304 stream->sample_format = widget.d.io.formats; 1305 stream->sample_rate = widget.d.io.rates; 1306 } else { 1307 stream->sample_format &= widget.d.io.formats; 1308 stream->sample_rate &= widget.d.io.rates; 1309 } 1310 1311 stream->io_widgets[count++] = widget.node_id; 1312 } 1313 1314 if (count == 0) 1315 return B_ENTRY_NOT_FOUND; 1316 1317 stream->num_io_widgets = count; 1318 return B_OK; 1319 } 1320 1321 1322 static const struct { 1323 uint32 subsystem_vendor_id, subsystem_id; 1324 uint32 codec_vendor_id, codec_id; 1325 uint32 quirks, nonquirks; 1326 } hda_codec_quirks[] = { 1327 { HDA_ALL, HDA_ALL, HDA_ALL, HDA_ALL, HDA_QUIRK_IVREF, 0 }, 1328 { HDA_ALL, HDA_ALL, HDA_ALL, HDA_ALL, HDA_QUIRK_IVREF, 0 }, 1329 { 0x10de, 0xcb79, CIRRUSLOGIC_VENDORID, 0x4206, HDA_QUIRK_GPIO1 | HDA_QUIRK_GPIO3, 0 }, // MacBook Pro 5.5 1330 { 0x8384, 0x7680, SIGMATEL_VENDORID, 0x7680, HDA_QUIRK_GPIO0 | HDA_QUIRK_GPIO1, 0}, // Apple Intel Mac 1331 { 0x106b, 0x00a3, REALTEK_VENDORID, 0x0885, HDA_QUIRK_GPIO0, 0}, // MacBook 1332 }; 1333 1334 1335 void 1336 hda_codec_get_quirks(hda_codec* codec) 1337 { 1338 codec->quirks = 0; 1339 uint32 subsystem_id = codec->controller->pci_info.u.h0.subsystem_id; 1340 uint32 subsystem_vendor_id = codec->controller->pci_info.u.h0.subsystem_vendor_id; 1341 uint32 codec_vendor_id = codec->vendor_id; 1342 uint32 codec_id = codec->product_id; 1343 for (uint32 i = 0; i < (sizeof(hda_codec_quirks) 1344 / sizeof(hda_codec_quirks[0])); i++) { 1345 if (hda_codec_quirks[i].subsystem_id != 0xffffffff 1346 && hda_codec_quirks[i].subsystem_id != subsystem_id) 1347 continue; 1348 if (hda_codec_quirks[i].subsystem_vendor_id != 0xffffffff 1349 && hda_codec_quirks[i].subsystem_vendor_id != subsystem_vendor_id) 1350 continue; 1351 if (hda_codec_quirks[i].codec_vendor_id != 0xffffffff 1352 && hda_codec_quirks[i].codec_vendor_id != codec_vendor_id) 1353 continue; 1354 if (hda_codec_quirks[i].codec_id != 0xffffffff 1355 && hda_codec_quirks[i].codec_id != codec_id) 1356 continue; 1357 1358 codec->quirks |= hda_codec_quirks[i].quirks; 1359 codec->quirks &= ~(hda_codec_quirks[i].nonquirks); 1360 } 1361 } 1362 1363 1364 void 1365 hda_codec_delete(hda_codec* codec) 1366 { 1367 if (codec == NULL) 1368 return; 1369 1370 delete_sem(codec->response_sem); 1371 delete_sem(codec->unsol_response_sem); 1372 1373 int32 result; 1374 wait_for_thread(codec->unsol_response_thread, &result); 1375 1376 for (uint32 i = 0; i < codec->num_audio_groups; i++) { 1377 hda_codec_delete_audio_group(codec->audio_groups[i]); 1378 codec->audio_groups[i] = NULL; 1379 } 1380 1381 free(codec); 1382 } 1383 1384 1385 hda_codec* 1386 hda_codec_new(hda_controller* controller, uint32 codecAddress) 1387 { 1388 if (codecAddress > HDA_MAX_CODECS) 1389 return NULL; 1390 1391 hda_codec* codec = (hda_codec*)calloc(1, sizeof(hda_codec)); 1392 if (codec == NULL) { 1393 ERROR("hda: Failed to alloc a codec\n"); 1394 return NULL; 1395 } 1396 1397 codec->controller = controller; 1398 codec->addr = codecAddress; 1399 codec->response_sem = create_sem(0, "hda_codec_response_sem"); 1400 if (codec->response_sem < B_OK) { 1401 ERROR("hda: Failed to create semaphore\n"); 1402 goto err; 1403 } 1404 controller->codecs[codecAddress] = codec; 1405 1406 codec->unsol_response_sem = create_sem(0, "hda_codec_unsol_response_sem"); 1407 if (codec->unsol_response_sem < B_OK) { 1408 ERROR("hda: Failed to create semaphore\n"); 1409 goto err; 1410 } 1411 codec->unsol_response_read = 0; 1412 codec->unsol_response_write = 0; 1413 1414 struct { 1415 uint32 device : 16; 1416 uint32 vendor : 16; 1417 uint32 stepping : 8; 1418 uint32 revision : 8; 1419 uint32 minor : 4; 1420 uint32 major : 4; 1421 uint32 _reserved0 : 8; 1422 uint32 count : 8; 1423 uint32 _reserved1 : 8; 1424 uint32 start : 8; 1425 uint32 _reserved2 : 8; 1426 } response; 1427 corb_t verbs[3]; 1428 1429 verbs[0] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_VENDOR_ID); 1430 verbs[1] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_REVISION_ID); 1431 verbs[2] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, 1432 PID_SUB_NODE_COUNT); 1433 1434 if (hda_send_verbs(codec, verbs, (uint32*)&response, 3) != B_OK) { 1435 ERROR("hda: Failed to get vendor and revision parameters\n"); 1436 goto err; 1437 } 1438 1439 codec->vendor_id = response.vendor; 1440 codec->product_id = response.device; 1441 codec->stepping = response.stepping; 1442 codec->revision = response.revision; 1443 codec->minor = response.minor; 1444 codec->major = response.major; 1445 hda_codec_get_quirks(codec); 1446 1447 TRACE("Codec %ld Vendor: %04lx Product: %04lx, Revision: " 1448 "%lu.%lu.%lu.%lu\n", codecAddress, response.vendor, response.device, 1449 response.major, response.minor, response.revision, response.stepping); 1450 1451 for (uint32 nodeID = response.start; nodeID < response.start 1452 + response.count; nodeID++) { 1453 uint32 groupType; 1454 verbs[0] = MAKE_VERB(codecAddress, nodeID, VID_GET_PARAMETER, 1455 PID_FUNCTION_GROUP_TYPE); 1456 1457 if (hda_send_verbs(codec, verbs, &groupType, 1) != B_OK) { 1458 ERROR("hda: Failed to get function group type\n"); 1459 goto err; 1460 } 1461 1462 if ((groupType & FUNCTION_GROUP_NODETYPE_MASK) == FUNCTION_GROUP_NODETYPE_AUDIO) { 1463 /* Found an Audio Function Group! */ 1464 status_t status = hda_codec_new_audio_group(codec, nodeID); 1465 if (status != B_OK) { 1466 ERROR("hda: Failed to setup new audio function group (%s)!\n", 1467 strerror(status)); 1468 goto err; 1469 } 1470 } 1471 } 1472 1473 codec->unsol_response_thread = spawn_kernel_thread( 1474 (status_t(*)(void*))hda_codec_switch_handler, 1475 "hda_codec_unsol_thread", B_LOW_PRIORITY, codec); 1476 if (codec->unsol_response_thread < B_OK) { 1477 ERROR("hda: Failed to spawn thread\n"); 1478 goto err; 1479 } 1480 resume_thread(codec->unsol_response_thread); 1481 1482 return codec; 1483 err: 1484 controller->codecs[codecAddress] = NULL; 1485 hda_codec_delete(codec); 1486 return NULL; 1487 } 1488