1 /* 2 * Copyright 2007-2008, 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 */ 9 10 11 #include "driver.h" 12 #include "hda_codec_defs.h" 13 14 15 static const char* kPortConnector[] = { 16 "Jack", "None", "Fixed", "Dual" 17 }; 18 19 static const char* kDefaultDevice[] = { 20 "Line Out", "Speaker", "HP Out", "CD", "SPDIF out", "Digital Other Out", 21 "Modem Line Side", "Modem Hand Side", "Line In", "AUX", "Mic In", 22 "Telephony", "SPDIF In", "Digital Other In", "Reserved", "Other" 23 }; 24 25 static const char* kConnectionType[] = { 26 "N/A", "1/8\"", "1/4\"", "ATAPI internal", "RCA", "Optical", 27 "Other Digital", "Other Analog", "Multichannel Analog (DIN)", 28 "XLR/Professional", "RJ-11 (Modem)", "Combination", "-", "-", "-", "Other" 29 }; 30 31 static const char* kJackColor[] = { 32 "N/A", "Black", "Grey", "Blue", "Green", "Red", "Orange", "Yellow", 33 "Purple", "Pink", "-", "-", "-", "-", "White", "Other" 34 }; 35 36 37 static const char* 38 get_widget_type_name(hda_widget_type type) 39 { 40 switch (type) { 41 case WT_AUDIO_OUTPUT: 42 return "Audio Output"; 43 case WT_AUDIO_INPUT: 44 return "Audio Input"; 45 case WT_AUDIO_MIXER: 46 return "Audio Mixer"; 47 case WT_AUDIO_SELECTOR: 48 return "Audio Selector"; 49 case WT_PIN_COMPLEX: 50 return "Pin Complex"; 51 case WT_POWER: 52 return "Power"; 53 case WT_VOLUME_KNOB: 54 return "Volume Knob"; 55 case WT_BEEP_GENERATOR: 56 return "Beep Generator"; 57 case WT_VENDOR_DEFINED: 58 return "Vendor Defined"; 59 default: 60 return "Unknown"; 61 } 62 } 63 64 65 static void 66 dump_widget_audio_capabilities(uint32 capabilities) 67 { 68 static const struct { 69 uint32 flag; 70 const char* name; 71 } kFlags[] = { 72 {AUDIO_CAP_LEFT_RIGHT_SWAP, "L-R Swap"}, 73 {AUDIO_CAP_POWER_CONTROL, "Power"}, 74 {AUDIO_CAP_DIGITAL, "Digital"}, 75 {AUDIO_CAP_CONNECTION_LIST, "Conn. List"}, 76 {AUDIO_CAP_UNSOLICITED_RESPONSES, "Unsol. Responses"}, 77 {AUDIO_CAP_PROCESSING_CONTROLS, "Proc Widget"}, 78 {AUDIO_CAP_STRIPE, "Stripe"}, 79 {AUDIO_CAP_FORMAT_OVERRIDE, "Format Override"}, 80 {AUDIO_CAP_AMPLIFIER_OVERRIDE, "Amplifier Override"}, 81 {AUDIO_CAP_OUTPUT_AMPLIFIER, "Out Amplifier"}, 82 {AUDIO_CAP_INPUT_AMPLIFIER, "In Amplifier"}, 83 {AUDIO_CAP_STEREO, "Stereo"}, 84 }; 85 86 char buffer[256]; 87 int offset = 0; 88 89 for (uint32 j = 0; j < sizeof(kFlags) / sizeof(kFlags[0]); j++) { 90 if (capabilities & kFlags[j].flag) 91 offset += sprintf(buffer + offset, "[%s] ", kFlags[j].name); 92 } 93 94 if (offset != 0) 95 dprintf("\t%s\n", buffer); 96 } 97 98 99 static void 100 dump_widget_inputs(hda_widget& widget) 101 { 102 // dump connections 103 104 char buffer[256]; 105 int offset = 0; 106 107 for (uint32 i = 0; i < widget.num_inputs; i++) { 108 int32 input = widget.inputs[i]; 109 110 if ((int32)i != widget.active_input) 111 offset += sprintf(buffer + offset, "%ld ", input); 112 else 113 offset += sprintf(buffer + offset, "<%ld> ", input); 114 } 115 116 if (offset != 0) 117 dprintf("\tInputs: %s\n", buffer); 118 } 119 120 121 static void 122 dump_widget_amplifier_capabilities(hda_widget& widget, bool input) 123 { 124 uint32 capabilities; 125 if (input) 126 capabilities = widget.capabilities.input_amplifier; 127 else 128 capabilities = widget.capabilities.output_amplifier; 129 130 if (capabilities == 0) 131 return; 132 133 dprintf("\t%s Amp: %sstep size: %f dB, # steps: %ld, offset to 0 dB: " 134 "%ld\n", input ? "In" : "Out", 135 (capabilities & AMP_CAP_MUTE) != 0 ? "supports mute, " : "", 136 AMP_CAP_STEP_SIZE(capabilities), 137 AMP_CAP_NUM_STEPS(capabilities), 138 AMP_CAP_OFFSET(capabilities)); 139 } 140 141 142 static void 143 dump_widget_pm_support(hda_widget& widget) 144 { 145 dprintf("\tSupported power states: %s%s%s%s\n", 146 widget.pm & POWER_STATE_D0 ? "D0 " : "", 147 widget.pm & POWER_STATE_D1 ? "D1 " : "", 148 widget.pm & POWER_STATE_D2 ? "D2 " : "", 149 widget.pm & POWER_STATE_D3 ? "D3 " : ""); 150 } 151 152 153 static void 154 dump_audiogroup_widgets(hda_audio_group* audioGroup) 155 { 156 dprintf("\tAudiogroup:\n"); 157 /* Iterate over all Widgets and collect info */ 158 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 159 hda_widget& widget = audioGroup->widgets[i]; 160 uint32 nodeID = audioGroup->widget_start + i; 161 162 dprintf("%ld: %s\n", nodeID, get_widget_type_name(widget.type)); 163 164 switch (widget.type) { 165 case WT_AUDIO_OUTPUT: 166 case WT_AUDIO_INPUT: 167 break; 168 169 case WT_PIN_COMPLEX: 170 dprintf("\t%s%s%s\n", PIN_CAP_IS_INPUT(widget.d.pin.capabilities) ? "[Input] " : "", 171 PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities) ? "[Output]" : "", 172 PIN_CAP_IS_EAPD_CAP(widget.d.pin.capabilities) ? "[EAPD Cap]" : ""); 173 174 break; 175 176 default: 177 break; 178 } 179 180 dump_widget_pm_support(widget); 181 dump_widget_audio_capabilities(widget.capabilities.audio); 182 dump_widget_amplifier_capabilities(widget, true); 183 dump_widget_amplifier_capabilities(widget, false); 184 dump_widget_inputs(widget); 185 } 186 } 187 188 189 // #pragma mark - 190 191 192 static status_t 193 hda_get_pm_support(hda_codec* codec, uint32 nodeID, uint32* pm) 194 { 195 corb_t verb = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER, 196 PID_POWERSTATE_SUPPORT); 197 status_t rc; 198 uint32 response; 199 200 if ((rc = hda_send_verbs(codec, &verb, &response, 1)) == B_OK) { 201 *pm = response & 0xf; 202 } 203 204 return rc; 205 } 206 207 208 static status_t 209 hda_get_stream_support(hda_codec* codec, uint32 nodeID, uint32* formats, 210 uint32* rates) 211 { 212 corb_t verbs[2]; 213 uint32 resp[2]; 214 status_t status; 215 216 verbs[0] = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER, 217 PID_STREAM_SUPPORT); 218 verbs[1] = MAKE_VERB(codec->addr, nodeID, VID_GET_PARAMETER, 219 PID_PCM_SUPPORT); 220 221 status = hda_send_verbs(codec, verbs, resp, 2); 222 if (status != B_OK) 223 return status; 224 225 *formats = 0; 226 *rates = 0; 227 228 if ((resp[0] & (STREAM_FLOAT | STREAM_PCM)) != 0) { 229 if (resp[1] & (1 << 0)) 230 *rates |= B_SR_8000; 231 if (resp[1] & (1 << 1)) 232 *rates |= B_SR_11025; 233 if (resp[1] & (1 << 2)) 234 *rates |= B_SR_16000; 235 if (resp[1] & (1 << 3)) 236 *rates |= B_SR_22050; 237 if (resp[1] & (1 << 4)) 238 *rates |= B_SR_32000; 239 if (resp[1] & (1 << 5)) 240 *rates |= B_SR_44100; 241 if (resp[1] & (1 << 6)) 242 *rates |= B_SR_48000; 243 if (resp[1] & (1 << 7)) 244 *rates |= B_SR_88200; 245 if (resp[1] & (1 << 8)) 246 *rates |= B_SR_96000; 247 if (resp[1] & (1 << 9)) 248 *rates |= B_SR_176400; 249 if (resp[1] & (1 << 10)) 250 *rates |= B_SR_192000; 251 if (resp[1] & (1 << 11)) 252 *rates |= B_SR_384000; 253 254 if (resp[1] & PCM_8_BIT) 255 *formats |= B_FMT_8BIT_S; 256 if (resp[1] & PCM_16_BIT) 257 *formats |= B_FMT_16BIT; 258 if (resp[1] & PCM_20_BIT) 259 *formats |= B_FMT_20BIT; 260 if (resp[1] & PCM_24_BIT) 261 *formats |= B_FMT_24BIT; 262 if (resp[1] & PCM_32_BIT) 263 *formats |= B_FMT_32BIT; 264 } 265 if ((resp[0] & STREAM_FLOAT) != 0) 266 *formats |= B_FMT_FLOAT; 267 if ((resp[0] & STREAM_AC3) != 0) { 268 *formats |= B_FMT_BITSTREAM; 269 } 270 271 return B_OK; 272 } 273 274 275 // #pragma mark - widget functions 276 277 278 static status_t 279 hda_widget_get_pm_support(hda_audio_group* audioGroup, hda_widget* widget) 280 { 281 return hda_get_pm_support(audioGroup->codec, widget->node_id, 282 &widget->pm); 283 } 284 285 286 static status_t 287 hda_widget_get_stream_support(hda_audio_group* audioGroup, hda_widget* widget) 288 { 289 if (audioGroup->widget.node_id != widget->node_id 290 && (widget->capabilities.audio & AUDIO_CAP_FORMAT_OVERRIDE) == 0) { 291 // adopt capabilities of the audio group 292 widget->d.io.formats = audioGroup->widget.d.io.formats; 293 widget->d.io.rates = audioGroup->widget.d.io.rates; 294 return B_OK; 295 } 296 297 return hda_get_stream_support(audioGroup->codec, widget->node_id, 298 &widget->d.io.formats, &widget->d.io.rates); 299 } 300 301 302 static status_t 303 hda_widget_get_amplifier_capabilities(hda_audio_group* audioGroup, 304 hda_widget* widget) 305 { 306 uint32 response; 307 corb_t verb; 308 309 if ((widget->capabilities.audio & AUDIO_CAP_OUTPUT_AMPLIFIER) != 0 310 || audioGroup->widget.node_id == widget->node_id) { 311 if ((widget->capabilities.audio & AUDIO_CAP_AMPLIFIER_OVERRIDE) != 0 312 || audioGroup->widget.node_id == widget->node_id) { 313 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 314 VID_GET_PARAMETER, PID_OUTPUT_AMPLIFIER_CAP); 315 status_t status = hda_send_verbs(audioGroup->codec, &verb, 316 &response, 1); 317 if (status < B_OK) 318 return status; 319 320 widget->capabilities.output_amplifier = response; 321 } else { 322 // adopt capabilities from the audio function group 323 widget->capabilities.output_amplifier 324 = audioGroup->widget.capabilities.output_amplifier; 325 } 326 } 327 328 if ((widget->capabilities.audio & AUDIO_CAP_INPUT_AMPLIFIER) != 0 329 || audioGroup->widget.node_id == widget->node_id) { 330 if ((widget->capabilities.audio & AUDIO_CAP_AMPLIFIER_OVERRIDE 331 || audioGroup->widget.node_id == widget->node_id) != 0) { 332 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 333 VID_GET_PARAMETER, PID_INPUT_AMPLIFIER_CAP); 334 status_t status = hda_send_verbs(audioGroup->codec, &verb, 335 &response, 1); 336 if (status < B_OK) 337 return status; 338 339 widget->capabilities.input_amplifier = response; 340 } else { 341 // adopt capabilities from the audio function group 342 widget->capabilities.input_amplifier 343 = audioGroup->widget.capabilities.input_amplifier; 344 } 345 } 346 347 return B_OK; 348 } 349 350 351 hda_widget* 352 hda_audio_group_get_widget(hda_audio_group* audioGroup, uint32 nodeID) 353 { 354 if (audioGroup->widget_start > nodeID 355 || audioGroup->widget_start + audioGroup->widget_count < nodeID) 356 return NULL; 357 358 return &audioGroup->widgets[nodeID - audioGroup->widget_start]; 359 } 360 361 362 static status_t 363 hda_widget_get_connections(hda_audio_group* audioGroup, hda_widget* widget) 364 { 365 uint32 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 366 VID_GET_PARAMETER, PID_CONNECTION_LIST_LENGTH); 367 uint32 response; 368 369 if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) != B_OK) 370 return B_ERROR; 371 372 uint32 listEntries = response & 0x7f; 373 bool longForm = (response & 0xf0) != 0; 374 375 if (listEntries == 0) 376 return B_OK; 377 378 #if 1 379 if (widget->num_inputs > 1) { 380 // Get currently active connection 381 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 382 VID_GET_CONNECTION_SELECT, 0); 383 if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) == B_OK) 384 widget->active_input = response & 0xff; 385 } 386 #endif 387 388 uint32 valuesPerEntry = longForm ? 2 : 4; 389 uint32 shift = 32 / valuesPerEntry; 390 uint32 rangeMask = (1 << (shift - 1)); 391 int32 previousInput = -1; 392 uint32 numInputs = 0; 393 394 for (uint32 i = 0; i < listEntries; i++) { 395 if ((i % valuesPerEntry) == 0) { 396 // We get 2 or 4 answers per call depending on if we're 397 // in short or long list mode 398 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 399 VID_GET_CONNECTION_LIST_ENTRY, i); 400 if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) 401 != B_OK) { 402 dprintf("hda: Error parsing inputs for widget %ld!\n", 403 widget->node_id); 404 break; 405 } 406 } 407 408 int32 input = (response >> (shift * (i % valuesPerEntry))) 409 & ((1 << shift) - 1); 410 411 if (input & rangeMask) { 412 // found range 413 input &= ~rangeMask; 414 415 if (input < previousInput || previousInput == -1) { 416 dprintf("hda: invalid range from %ld to %ld\n", previousInput, 417 input); 418 continue; 419 } 420 421 for (int32 rangeInput = previousInput + 1; rangeInput <= input 422 && numInputs < MAX_INPUTS; rangeInput++) { 423 widget->inputs[numInputs++] = rangeInput; 424 } 425 426 previousInput = -1; 427 } else if (numInputs < MAX_INPUTS) { 428 // standard value 429 widget->inputs[numInputs++] = input; 430 previousInput = input; 431 } 432 } 433 434 widget->num_inputs = numInputs; 435 436 if (widget->num_inputs == 1) 437 widget->active_input = 0; 438 439 return B_OK; 440 } 441 442 443 static status_t 444 hda_widget_get_associations(hda_audio_group* audioGroup) 445 { 446 uint32 index = 0; 447 for (uint32 i = 0; i < MAX_ASSOCIATIONS; i++) { 448 for (uint32 j = 0; j < audioGroup->widget_count; j++) { 449 hda_widget& widget = audioGroup->widgets[j]; 450 451 if (widget.type != WT_PIN_COMPLEX) 452 continue; 453 if (CONF_DEFAULT_ASSOCIATION(widget.d.pin.config) != i) 454 continue; 455 if (audioGroup->associations[index].pin_count == 0) { 456 audioGroup->associations[index].index = index; 457 audioGroup->associations[index].enabled = true; 458 } 459 uint32 sequence = CONF_DEFAULT_SEQUENCE(widget.d.pin.config); 460 if (audioGroup->associations[index].pins[sequence] != 0) { 461 audioGroup->associations[index].enabled = false; 462 } 463 audioGroup->associations[index].pins[sequence] = widget.node_id; 464 audioGroup->associations[index].pin_count++; 465 if (i == 15) 466 index++; 467 } 468 if (i != 15 && audioGroup->associations[index].pin_count != 0) 469 index++; 470 } 471 audioGroup->association_count = index; 472 473 return B_OK; 474 } 475 476 477 // #pragma mark - audio group functions 478 479 480 static status_t 481 hda_codec_parse_audio_group(hda_audio_group* audioGroup) 482 { 483 corb_t verbs[3]; 484 uint32 resp[3]; 485 486 hda_widget_get_stream_support(audioGroup, &audioGroup->widget); 487 hda_widget_get_pm_support(audioGroup, &audioGroup->widget); 488 hda_widget_get_amplifier_capabilities(audioGroup, &audioGroup->widget); 489 490 verbs[0] = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id, 491 VID_GET_PARAMETER, PID_AUDIO_GROUP_CAP); 492 verbs[1] = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id, 493 VID_GET_PARAMETER, PID_GPIO_COUNT); 494 verbs[2] = MAKE_VERB(audioGroup->codec->addr, audioGroup->widget.node_id, 495 VID_GET_PARAMETER, PID_SUB_NODE_COUNT); 496 497 if (hda_send_verbs(audioGroup->codec, verbs, resp, 3) != B_OK) 498 return B_ERROR; 499 500 dprintf("hda: Audio Group: Output delay: %ld samples, Input delay: %ld " 501 "samples, Beep Generator: %s\n", AUDIO_GROUP_CAP_OUTPUT_DELAY(resp[0]), 502 AUDIO_GROUP_CAP_INPUT_DELAY(resp[0]), 503 AUDIO_GROUP_CAP_BEEPGEN(resp[0]) ? "yes" : "no"); 504 505 dprintf("hda: #GPIO: %ld, #GPO: %ld, #GPI: %ld, unsol: %s, wake: %s\n", 506 GPIO_COUNT_NUM_GPIO(resp[1]), GPIO_COUNT_NUM_GPO(resp[1]), 507 GPIO_COUNT_NUM_GPI(resp[1]), GPIO_COUNT_GPIUNSOL(resp[1]) ? "yes" : "no", 508 GPIO_COUNT_GPIWAKE(resp[1]) ? "yes" : "no"); 509 510 audioGroup->widget_start = SUB_NODE_COUNT_START(resp[2]); 511 audioGroup->widget_count = SUB_NODE_COUNT_TOTAL(resp[2]); 512 513 dprintf("hda: widget start %lu, count %lu\n", audioGroup->widget_start, 514 audioGroup->widget_count); 515 516 audioGroup->widgets = (hda_widget*)calloc(audioGroup->widget_count, 517 sizeof(*audioGroup->widgets)); 518 if (audioGroup->widgets == NULL) { 519 dprintf("ERROR: Not enough memory!\n"); 520 return B_NO_MEMORY; 521 } 522 523 /* Iterate over all Widgets and collect info */ 524 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 525 hda_widget& widget = audioGroup->widgets[i]; 526 uint32 nodeID = audioGroup->widget_start + i; 527 uint32 capabilities; 528 529 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, VID_GET_PARAMETER, 530 PID_AUDIO_WIDGET_CAP); 531 if (hda_send_verbs(audioGroup->codec, verbs, &capabilities, 1) != B_OK) 532 return B_ERROR; 533 534 widget.type = (hda_widget_type)((capabilities & AUDIO_CAP_TYPE_MASK) 535 >> AUDIO_CAP_TYPE_SHIFT); 536 537 /* Check specific node ids declared as inputs as beepers */ 538 switch ((audioGroup->codec->vendor_id << 16) | audioGroup->codec->product_id) { 539 case 0x11d41882: 540 case 0x11d41883: 541 case 0x11d41884: 542 case 0x11d4194a: 543 case 0x11d4194b: 544 case 0x11d41987: 545 case 0x11d41988: 546 case 0x11d4198b: 547 case 0x11d4989b: 548 if (nodeID == 26) 549 widget.type = WT_BEEP_GENERATOR; 550 break; 551 case 0x10ec0260: 552 if (nodeID == 23) 553 widget.type = WT_BEEP_GENERATOR; 554 break; 555 case 0x10ec0262: 556 case 0x10ec0268: 557 case 0x10ec0880: 558 case 0x10ec0882: 559 case 0x10ec0883: 560 case 0x10ec0885: 561 case 0x10ec0888: 562 case 0x10ec0889: 563 if (nodeID == 29) 564 widget.type = WT_BEEP_GENERATOR; 565 break; 566 } 567 widget.active_input = -1; 568 widget.capabilities.audio = capabilities; 569 widget.node_id = nodeID; 570 571 if ((capabilities & AUDIO_CAP_POWER_CONTROL) != 0) { 572 /* We support power; switch us on! */ 573 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 574 VID_SET_POWER_STATE, 0); 575 hda_send_verbs(audioGroup->codec, verbs, NULL, 1); 576 577 snooze(1000); 578 } 579 if ((capabilities & (AUDIO_CAP_INPUT_AMPLIFIER 580 | AUDIO_CAP_OUTPUT_AMPLIFIER)) != 0) { 581 hda_widget_get_amplifier_capabilities(audioGroup, &widget); 582 } 583 584 dprintf("%ld: %s\n", nodeID, get_widget_type_name(widget.type)); 585 586 switch (widget.type) { 587 case WT_AUDIO_OUTPUT: 588 case WT_AUDIO_INPUT: 589 hda_widget_get_stream_support(audioGroup, &widget); 590 break; 591 592 case WT_PIN_COMPLEX: 593 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 594 VID_GET_PARAMETER, PID_PIN_CAP); 595 if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) == B_OK) { 596 widget.d.pin.capabilities = resp[0]; 597 598 dprintf("\t%s%s\n", PIN_CAP_IS_INPUT(resp[0]) ? "[Input] " : "", 599 PIN_CAP_IS_OUTPUT(resp[0]) ? "[Output]" : ""); 600 } else { 601 dprintf("%s: Error getting Pin Complex IO\n", __func__); 602 } 603 604 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 605 VID_GET_CONFIGURATION_DEFAULT, 0); 606 if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) == B_OK) { 607 widget.d.pin.config = resp[0]; 608 dprintf("\t%s, %s, %s, %s, Association:%ld\n", 609 kPortConnector[CONF_DEFAULT_CONNECTIVITY(resp[0])], 610 kDefaultDevice[CONF_DEFAULT_DEVICE(resp[0])], 611 kConnectionType[CONF_DEFAULT_CONNTYPE(resp[0])], 612 kJackColor[CONF_DEFAULT_COLOR(resp[0])], 613 CONF_DEFAULT_ASSOCIATION(resp[0])); 614 } 615 break; 616 617 case WT_VOLUME_KNOB: 618 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 619 VID_SET_VOLUME_KNOB_CONTROL, 0x0); 620 hda_send_verbs(audioGroup->codec, verbs, NULL, 1); 621 break; 622 default: 623 break; 624 } 625 626 hda_widget_get_pm_support(audioGroup, &widget); 627 hda_widget_get_connections(audioGroup, &widget); 628 629 dump_widget_pm_support(widget); 630 dump_widget_audio_capabilities(capabilities); 631 dump_widget_amplifier_capabilities(widget, true); 632 dump_widget_amplifier_capabilities(widget, false); 633 dump_widget_inputs(widget); 634 } 635 636 hda_widget_get_associations(audioGroup); 637 638 return B_OK; 639 } 640 641 642 /*! Find output path for widget */ 643 static bool 644 hda_widget_find_output_path(hda_audio_group* audioGroup, hda_widget* widget, 645 uint32 depth) 646 { 647 if (widget == NULL || depth > 16) 648 return false; 649 650 switch (widget->type) { 651 case WT_AUDIO_OUTPUT: 652 widget->flags |= WIDGET_FLAG_OUTPUT_PATH; 653 dprintf(" %*soutput: added output widget %ld\n", (int)depth * 2, "", widget->node_id); 654 return true; 655 656 case WT_AUDIO_MIXER: 657 case WT_AUDIO_SELECTOR: 658 { 659 // already used 660 if (widget->flags & WIDGET_FLAG_OUTPUT_PATH) 661 return false; 662 663 // search for output in this path 664 bool found = false; 665 for (uint32 i = 0; i < widget->num_inputs; i++) { 666 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 667 widget->inputs[i]); 668 669 if (hda_widget_find_output_path(audioGroup, inputWidget, 670 depth + 1)) { 671 if (widget->active_input == -1) 672 widget->active_input = i; 673 674 widget->flags |= WIDGET_FLAG_OUTPUT_PATH; 675 dprintf(" %*soutput: added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 676 found = true; 677 } 678 } 679 if (!found) dprintf(" %*soutput: not added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 680 return found; 681 } 682 683 default: 684 return false; 685 } 686 } 687 688 689 /*! Find input path for widget */ 690 static bool 691 hda_widget_find_input_path(hda_audio_group* audioGroup, hda_widget* widget, 692 uint32 depth) 693 { 694 if (widget == NULL || depth > 16) 695 return false; 696 697 switch (widget->type) { 698 case WT_PIN_COMPLEX: 699 // already used 700 if (widget->flags & WIDGET_FLAG_INPUT_PATH) 701 return false; 702 703 if (PIN_CAP_IS_INPUT(widget->d.pin.capabilities)) { 704 switch (CONF_DEFAULT_DEVICE(widget->d.pin.config)) { 705 case PIN_DEV_CD: 706 case PIN_DEV_LINE_IN: 707 case PIN_DEV_MIC_IN: 708 widget->flags |= WIDGET_FLAG_INPUT_PATH; 709 dprintf(" %*sinput: added input widget %ld\n", (int)depth * 2, "", widget->node_id); 710 return true; 711 break; 712 } 713 } 714 return false; 715 case WT_AUDIO_INPUT: 716 case WT_AUDIO_MIXER: 717 case WT_AUDIO_SELECTOR: 718 { 719 // already used 720 if (widget->flags & WIDGET_FLAG_INPUT_PATH) 721 return false; 722 723 // search for pin complex in this path 724 bool found = false; 725 for (uint32 i = 0; i < widget->num_inputs; i++) { 726 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 727 widget->inputs[i]); 728 729 if (hda_widget_find_input_path(audioGroup, inputWidget, 730 depth + 1)) { 731 if (widget->active_input == -1) 732 widget->active_input = i; 733 734 widget->flags |= WIDGET_FLAG_INPUT_PATH; 735 dprintf(" %*sinput: added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 736 found = true; 737 } 738 } 739 if (!found) dprintf(" %*sinput: not added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 740 return found; 741 } 742 743 default: 744 return false; 745 } 746 } 747 748 static bool 749 hda_audio_group_build_output_tree(hda_audio_group* audioGroup, bool useMixer) 750 { 751 bool found = false; 752 753 dprintf("build output tree: %suse mixer\n", useMixer ? "" : "don't "); 754 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 755 hda_widget& widget = audioGroup->widgets[i]; 756 757 if (widget.type != WT_PIN_COMPLEX || !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities)) 758 continue; 759 760 int device = CONF_DEFAULT_DEVICE(widget.d.pin.config); 761 if (device != PIN_DEV_HEAD_PHONE_OUT 762 && device != PIN_DEV_SPEAKER 763 && device != PIN_DEV_LINE_OUT) 764 continue; 765 766 dprintf(" look at pin widget %ld (%ld inputs)\n", widget.node_id, widget.num_inputs); 767 for (uint32 j = 0; j < widget.num_inputs; j++) { 768 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 769 widget.inputs[j]); 770 dprintf(" try widget %ld: %p\n", widget.inputs[j], inputWidget); 771 if (inputWidget == NULL) 772 continue; 773 774 if (useMixer && inputWidget->type != WT_AUDIO_MIXER 775 && inputWidget->type != WT_AUDIO_SELECTOR) 776 continue; 777 dprintf(" widget %ld is candidate\n", inputWidget->node_id); 778 779 if (hda_widget_find_output_path(audioGroup, inputWidget, 0)) { 780 dprintf(" add pin widget %ld\n", widget.node_id); 781 if (widget.active_input == -1) 782 widget.active_input = j; 783 widget.flags |= WIDGET_FLAG_OUTPUT_PATH; 784 found = true; 785 break; 786 } 787 } 788 } 789 790 return found; 791 } 792 793 794 static bool 795 hda_audio_group_build_input_tree(hda_audio_group* audioGroup) 796 { 797 bool found = false; 798 799 dprintf("build input tree\n"); 800 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 801 hda_widget& widget = audioGroup->widgets[i]; 802 803 if (widget.type != WT_AUDIO_INPUT) 804 continue; 805 806 dprintf(" look at input widget %ld (%ld inputs)\n", widget.node_id, widget.num_inputs); 807 for (uint32 j = 0; j < widget.num_inputs; j++) { 808 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 809 widget.inputs[j]); 810 dprintf(" try widget %ld: %p\n", widget.inputs[j], inputWidget); 811 if (inputWidget == NULL) 812 continue; 813 814 dprintf(" widget %ld is candidate\n", inputWidget->node_id); 815 816 if (hda_widget_find_input_path(audioGroup, inputWidget, 0)) { 817 dprintf(" add pin widget %ld\n", widget.node_id); 818 if (widget.active_input == -1) 819 widget.active_input = j; 820 widget.flags |= WIDGET_FLAG_INPUT_PATH; 821 found = true; 822 break; 823 } 824 } 825 } 826 827 return found; 828 } 829 830 831 static status_t 832 hda_audio_group_build_tree(hda_audio_group* audioGroup) 833 { 834 if (!hda_audio_group_build_output_tree(audioGroup, true)) { 835 // didn't find a mixer path, try again without 836 dprintf("try without mixer!\n"); 837 if (!hda_audio_group_build_output_tree(audioGroup, false)) 838 return ENODEV; 839 } 840 841 if (!hda_audio_group_build_input_tree(audioGroup)) { 842 dprintf("hda: build input tree failed\n"); 843 } 844 845 dprintf("build tree!\n"); 846 847 // select active connections 848 849 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 850 hda_widget& widget = audioGroup->widgets[i]; 851 852 if (widget.active_input == -1) 853 widget.active_input = 0; 854 if (widget.num_inputs < 2) 855 continue; 856 857 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 858 widget.node_id, VID_SET_CONNECTION_SELECT, widget.active_input); 859 if (hda_send_verbs(audioGroup->codec, &verb, NULL, 1) != B_OK) { 860 dprintf("hda: Setting output selector %ld failed on widget %ld!\n", 861 widget.active_input, widget.node_id); 862 } 863 } 864 865 dump_audiogroup_widgets(audioGroup); 866 867 return B_OK; 868 } 869 870 871 static void 872 hda_codec_delete_audio_group(hda_audio_group* audioGroup) 873 { 874 if (audioGroup == NULL) 875 return; 876 877 if (audioGroup->playback_stream != NULL) 878 hda_stream_delete(audioGroup->playback_stream); 879 880 if (audioGroup->record_stream != NULL) 881 hda_stream_delete(audioGroup->record_stream); 882 free(audioGroup->multi); 883 free(audioGroup->widgets); 884 free(audioGroup); 885 } 886 887 888 static status_t 889 hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID) 890 { 891 hda_audio_group* audioGroup = (hda_audio_group*)calloc(1, 892 sizeof(hda_audio_group)); 893 if (audioGroup == NULL) 894 return B_NO_MEMORY; 895 896 /* Setup minimal info needed by hda_codec_parse_afg */ 897 audioGroup->widget.node_id = audioGroupNodeID; 898 audioGroup->codec = codec; 899 audioGroup->multi = (hda_multi*)calloc(1, 900 sizeof(hda_multi)); 901 if (audioGroup->multi == NULL) 902 return B_NO_MEMORY; 903 audioGroup->multi->group = audioGroup; 904 905 /* Parse all widgets in Audio Function Group */ 906 status_t status = hda_codec_parse_audio_group(audioGroup); 907 if (status != B_OK) 908 goto err; 909 910 /* Setup for worst-case scenario; we cannot find any output Pin Widgets */ 911 status = ENODEV; 912 913 if (hda_audio_group_build_tree(audioGroup) != B_OK) 914 goto err; 915 916 audioGroup->playback_stream = hda_stream_new(audioGroup, STREAM_PLAYBACK); 917 audioGroup->record_stream = hda_stream_new(audioGroup, STREAM_RECORD); 918 dprintf("hda: streams playback %p, record %p\n", audioGroup->playback_stream, 919 audioGroup->record_stream); 920 921 if (audioGroup->playback_stream != NULL 922 || audioGroup->record_stream != NULL) { 923 codec->audio_groups[codec->num_audio_groups++] = audioGroup; 924 return B_OK; 925 } 926 927 err: 928 free(audioGroup->widgets); 929 free(audioGroup); 930 return status; 931 } 932 933 934 // #pragma mark - 935 936 937 status_t 938 hda_audio_group_get_widgets(hda_audio_group* audioGroup, hda_stream* stream) 939 { 940 hda_widget_type type; 941 uint32 flags; 942 943 if (stream->type == STREAM_PLAYBACK) { 944 type = WT_AUDIO_OUTPUT; 945 flags = WIDGET_FLAG_OUTPUT_PATH; 946 } else { 947 // record 948 type = WT_AUDIO_INPUT; 949 flags = WIDGET_FLAG_INPUT_PATH; 950 } 951 952 uint32 count = 0; 953 954 for (uint32 i = 0; i < audioGroup->widget_count && count < MAX_IO_WIDGETS; 955 i++) { 956 hda_widget& widget = audioGroup->widgets[i]; 957 958 if ((widget.flags & flags) != 0) { 959 if (widget.type == WT_PIN_COMPLEX) { 960 stream->pin_widget = widget.node_id; 961 962 dprintf("ENABLE pin widget %ld\n", widget.node_id); 963 /* FIXME: Force Pin Widget to unmute; enable hp/output */ 964 uint32 verb = MAKE_VERB(audioGroup->codec->addr, 965 widget.node_id, 966 VID_SET_PIN_WIDGET_CONTROL, 967 flags == WIDGET_FLAG_OUTPUT_PATH ? 968 PIN_ENABLE_HEAD_PHONE | PIN_ENABLE_OUTPUT 969 : PIN_ENABLE_INPUT); 970 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 971 972 if (PIN_CAP_IS_EAPD_CAP(widget.d.pin.capabilities)) { 973 uint32 result; 974 verb = MAKE_VERB(audioGroup->codec->addr, 975 widget.node_id, VID_GET_EAPDBTL_EN, 0); 976 if (hda_send_verbs(audioGroup->codec, &verb, 977 &result, 1) == B_OK) { 978 result &= 0xff; 979 verb = MAKE_VERB(audioGroup->codec->addr, 980 widget.node_id, VID_SET_EAPDBTL_EN, 981 result | EAPDBTL_ENABLE_EAPD); 982 hda_send_verbs(audioGroup->codec, 983 &verb, NULL, 1); 984 dprintf("ENABLE EAPD pin widget %ld\n", widget.node_id); 985 } 986 } 987 } 988 989 if (widget.capabilities.output_amplifier != 0) { 990 dprintf("UNMUTE/SET OUTPUT GAIN widget %ld (offset %ld)\n", widget.node_id, 991 AMP_CAP_OFFSET(widget.capabilities.output_amplifier)); 992 uint32 verb = MAKE_VERB(audioGroup->codec->addr, 993 widget.node_id, 994 VID_SET_AMPLIFIER_GAIN_MUTE, 995 AMP_SET_OUTPUT | AMP_SET_LEFT_CHANNEL 996 | AMP_SET_RIGHT_CHANNEL 997 | AMP_CAP_OFFSET(widget.capabilities.output_amplifier)); 998 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 999 } 1000 if (widget.capabilities.input_amplifier != 0) { 1001 dprintf("UNMUTE/SET INPUT GAIN widget %ld (offset %ld)\n", widget.node_id, 1002 AMP_CAP_OFFSET(widget.capabilities.input_amplifier)); 1003 for (uint32 i = 0; i < widget.num_inputs; i++) { 1004 uint32 verb = MAKE_VERB(audioGroup->codec->addr, 1005 widget.node_id, 1006 VID_SET_AMPLIFIER_GAIN_MUTE, 1007 AMP_SET_INPUT | AMP_SET_LEFT_CHANNEL 1008 | AMP_SET_RIGHT_CHANNEL 1009 | AMP_SET_INPUT_INDEX(i) 1010 | AMP_CAP_OFFSET(widget.capabilities.input_amplifier)); 1011 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1012 } 1013 } 1014 } 1015 1016 if (widget.type != type || (widget.flags & flags) == 0 1017 || (widget.capabilities.audio 1018 & (AUDIO_CAP_STEREO | AUDIO_CAP_DIGITAL)) != AUDIO_CAP_STEREO 1019 || widget.d.io.formats == 0) 1020 continue; 1021 1022 if (count == 0) { 1023 stream->sample_format = widget.d.io.formats; 1024 stream->sample_rate = widget.d.io.rates; 1025 } else { 1026 stream->sample_format &= widget.d.io.formats; 1027 stream->sample_rate &= widget.d.io.rates; 1028 } 1029 1030 stream->io_widgets[count++] = widget.node_id; 1031 } 1032 1033 if (count == 0) 1034 return B_ENTRY_NOT_FOUND; 1035 1036 stream->num_io_widgets = count; 1037 return B_OK; 1038 } 1039 1040 1041 void 1042 hda_codec_delete(hda_codec* codec) 1043 { 1044 if (codec == NULL) 1045 return; 1046 1047 delete_sem(codec->response_sem); 1048 1049 for (uint32 i = 0; i < codec->num_audio_groups; i++) { 1050 hda_codec_delete_audio_group(codec->audio_groups[i]); 1051 codec->audio_groups[i] = NULL; 1052 } 1053 1054 free(codec); 1055 } 1056 1057 1058 hda_codec* 1059 hda_codec_new(hda_controller* controller, uint32 codecAddress) 1060 { 1061 if (codecAddress > HDA_MAX_CODECS) 1062 return NULL; 1063 1064 hda_codec* codec = (hda_codec*)calloc(1, sizeof(hda_codec)); 1065 if (codec == NULL) { 1066 dprintf("hda: Failed to alloc a codec\n"); 1067 return NULL; 1068 } 1069 1070 codec->controller = controller; 1071 codec->addr = codecAddress; 1072 codec->response_sem = create_sem(0, "hda_codec_response_sem"); 1073 controller->codecs[codecAddress] = codec; 1074 1075 struct { 1076 uint32 device : 16; 1077 uint32 vendor : 16; 1078 uint32 stepping : 8; 1079 uint32 revision : 8; 1080 uint32 minor : 4; 1081 uint32 major : 4; 1082 uint32 _reserved0 : 8; 1083 uint32 count : 8; 1084 uint32 _reserved1 : 8; 1085 uint32 start : 8; 1086 uint32 _reserved2 : 8; 1087 } response; 1088 corb_t verbs[3]; 1089 1090 verbs[0] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_VENDOR_ID); 1091 verbs[1] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_REVISION_ID); 1092 verbs[2] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, 1093 PID_SUB_NODE_COUNT); 1094 1095 if (hda_send_verbs(codec, verbs, (uint32*)&response, 3) != B_OK) { 1096 dprintf("hda: Failed to get vendor and revision parameters\n"); 1097 goto err; 1098 } 1099 1100 codec->vendor_id = response.vendor; 1101 codec->product_id = response.device; 1102 codec->stepping = response.stepping; 1103 codec->revision = response.revision; 1104 codec->minor = response.minor; 1105 codec->major = response.major; 1106 1107 dprintf("Codec %ld Vendor: %04lx Product: %04lx, Revision: " 1108 "%lu.%lu.%lu.%lu\n", codecAddress, response.vendor, response.device, 1109 response.major, response.minor, response.revision, response.stepping); 1110 1111 for (uint32 nodeID = response.start; nodeID < response.start 1112 + response.count; nodeID++) { 1113 uint32 groupType; 1114 verbs[0] = MAKE_VERB(codecAddress, nodeID, VID_GET_PARAMETER, 1115 PID_FUNCTION_GROUP_TYPE); 1116 1117 if (hda_send_verbs(codec, verbs, &groupType, 1) != B_OK) { 1118 dprintf("hda: Failed to get function group type\n"); 1119 goto err; 1120 } 1121 1122 if ((groupType & FUNCTION_GROUP_NODETYPE_MASK) == FUNCTION_GROUP_NODETYPE_AUDIO) { 1123 /* Found an Audio Function Group! */ 1124 status_t status = hda_codec_new_audio_group(codec, nodeID); 1125 if (status != B_OK) { 1126 dprintf("hda: Failed to setup new audio function group (%s)!\n", 1127 strerror(status)); 1128 goto err; 1129 } 1130 } 1131 } 1132 1133 return codec; 1134 1135 err: 1136 controller->codecs[codecAddress] = NULL; 1137 hda_codec_delete(codec); 1138 return NULL; 1139 } 1140