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