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