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