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 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("\tConnections: %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: %ld dB, # steps: %ld, offset to 0 dB: " 134 "%ld\n", input ? "In" : "Out", 135 (capabilities & AMP_CAP_MUTE) != 0 ? "supports mute, " : "", 136 (((capabilities & AMP_CAP_STEP_SIZE_MASK) 137 >> AMP_CAP_STEP_SIZE_SHIFT) + 1) / 4, 138 (capabilities & AMP_CAP_NUM_STEPS_MASK) >> AMP_CAP_NUM_STEPS_SHIFT, 139 capabilities & AMP_CAP_OFFSET_MASK); 140 } 141 142 143 static void 144 dump_widget_pm_support(hda_widget& widget) 145 { 146 dprintf("\tSupported power states: %s%s%s%s\n", 147 widget.pm & POWER_STATE_D0 ? "D0 " : "", 148 widget.pm & POWER_STATE_D1 ? "D1 " : "", 149 widget.pm & POWER_STATE_D2 ? "D2 " : "", 150 widget.pm & POWER_STATE_D3 ? "D3 " : ""); 151 } 152 153 154 static void 155 dump_audiogroup_widgets(hda_audio_group* audioGroup) 156 { 157 dprintf("\tAudiogroup:\n"); 158 /* Iterate over all Widgets and collect info */ 159 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 160 hda_widget& widget = audioGroup->widgets[i]; 161 uint32 nodeID = audioGroup->widget_start + i; 162 163 dprintf("%ld: %s\n", nodeID, get_widget_type_name(widget.type)); 164 165 switch (widget.type) { 166 case WT_AUDIO_OUTPUT: 167 case WT_AUDIO_INPUT: 168 break; 169 170 case WT_PIN_COMPLEX: 171 dprintf("\t%s%s\n", widget.d.pin.input ? "[Input] " : "", 172 widget.d.pin.output ? "[Output]" : ""); 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 268 //FIXME: if (resp[0] & (1 << 2)) /* Sort out how to handle AC3 */; 269 270 return B_OK; 271 } 272 273 274 // #pragma mark - widget functions 275 276 277 static status_t 278 hda_widget_get_pm_support(hda_audio_group* audioGroup, hda_widget* widget) 279 { 280 return hda_get_pm_support(audioGroup->codec, widget->node_id, 281 &widget->pm); 282 } 283 284 285 static status_t 286 hda_widget_get_stream_support(hda_audio_group* audioGroup, hda_widget* widget) 287 { 288 if ((widget->capabilities.audio & AUDIO_CAP_FORMAT_OVERRIDE) == 0) { 289 // adopt capabilities of the audio group 290 widget->d.io.formats = audioGroup->supported_formats; 291 widget->d.io.rates = audioGroup->supported_rates; 292 return B_OK; 293 } 294 295 return hda_get_stream_support(audioGroup->codec, widget->node_id, 296 &widget->d.io.formats, &widget->d.io.rates); 297 } 298 299 300 static status_t 301 hda_widget_get_amplifier_capabilities(hda_audio_group* audioGroup, 302 hda_widget* widget) 303 { 304 uint32 response; 305 corb_t verb; 306 307 if ((widget->capabilities.audio & AUDIO_CAP_OUTPUT_AMPLIFIER) != 0) { 308 if ((widget->capabilities.audio & AUDIO_CAP_AMPLIFIER_OVERRIDE) != 0) { 309 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 310 VID_GET_PARAMETER, PID_OUTPUT_AMPLIFIER_CAP); 311 status_t status = hda_send_verbs(audioGroup->codec, &verb, 312 &response, 1); 313 if (status < B_OK) 314 return status; 315 316 widget->capabilities.output_amplifier = response; 317 } else { 318 // adopt capabilities from the audio function group 319 widget->capabilities.output_amplifier 320 = audioGroup->output_amplifier_capabilities; 321 } 322 } 323 324 if ((widget->capabilities.audio & AUDIO_CAP_INPUT_AMPLIFIER) != 0) { 325 if ((widget->capabilities.audio & AUDIO_CAP_AMPLIFIER_OVERRIDE) != 0) { 326 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 327 VID_GET_PARAMETER, PID_INPUT_AMPLIFIER_CAP); 328 status_t status = hda_send_verbs(audioGroup->codec, &verb, 329 &response, 1); 330 if (status < B_OK) 331 return status; 332 333 widget->capabilities.input_amplifier = response; 334 } else { 335 // adopt capabilities from the audio function group 336 widget->capabilities.input_amplifier 337 = audioGroup->input_amplifier_capabilities; 338 } 339 } 340 341 return B_OK; 342 } 343 344 345 static hda_widget* 346 hda_audio_group_get_widget(hda_audio_group* audioGroup, uint32 nodeID) 347 { 348 if (audioGroup->widget_start > nodeID 349 || audioGroup->widget_start + audioGroup->widget_count < nodeID) 350 return NULL; 351 352 return &audioGroup->widgets[nodeID - audioGroup->widget_start]; 353 } 354 355 356 static status_t 357 hda_widget_get_connections(hda_audio_group* audioGroup, hda_widget* widget) 358 { 359 uint32 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 360 VID_GET_PARAMETER, PID_CONNECTION_LIST_LENGTH); 361 uint32 response; 362 363 if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) != B_OK) 364 return B_ERROR; 365 366 uint32 listEntries = response & 0x7f; 367 bool longForm = (response & 0xf0) != 0; 368 369 if (listEntries == 0) 370 return B_OK; 371 372 #if 1 373 if (widget->num_inputs > 1) { 374 // Get currently active connection 375 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 376 VID_GET_CONNECTION_SELECT, 0); 377 if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) == B_OK) 378 widget->active_input = response & 0xff; 379 } 380 #endif 381 382 uint32 valuesPerEntry = longForm ? 2 : 4; 383 uint32 shift = 32 / valuesPerEntry; 384 uint32 rangeMask = (1 << (shift - 1)); 385 int32 previousInput = -1; 386 uint32 numInputs = 0; 387 388 for (uint32 i = 0; i < listEntries; i++) { 389 if ((i % valuesPerEntry) == 0) { 390 // We get 2 or 4 answers per call depending on if we're 391 // in short or long list mode 392 verb = MAKE_VERB(audioGroup->codec->addr, widget->node_id, 393 VID_GET_CONNECTION_LIST_ENTRY, i); 394 if (hda_send_verbs(audioGroup->codec, &verb, &response, 1) 395 != B_OK) { 396 dprintf("hda: Error parsing inputs for widget %ld!\n", 397 widget->node_id); 398 break; 399 } 400 } 401 402 int32 input = (response >> (shift * (i % valuesPerEntry))) 403 & ((1 << shift) - 1); 404 405 if (input & rangeMask) { 406 // found range 407 input &= ~rangeMask; 408 409 if (input < previousInput || previousInput == -1) { 410 dprintf("hda: invalid range from %ld to %ld\n", previousInput, 411 input); 412 continue; 413 } 414 415 for (int32 rangeInput = previousInput + 1; rangeInput <= input 416 && numInputs < MAX_INPUTS; rangeInput++) { 417 widget->inputs[numInputs++] = rangeInput; 418 } 419 420 previousInput = -1; 421 } else if (numInputs < MAX_INPUTS) { 422 // standard value 423 widget->inputs[numInputs++] = input; 424 previousInput = input; 425 } 426 } 427 428 widget->num_inputs = numInputs; 429 430 if (widget->num_inputs == 1) 431 widget->active_input = 0; 432 433 return B_OK; 434 } 435 436 437 // #pragma mark - audio group functions 438 439 440 static status_t 441 hda_codec_parse_audio_group(hda_audio_group* audioGroup) 442 { 443 corb_t verbs[3]; 444 uint32 resp[3]; 445 446 hda_get_stream_support(audioGroup->codec, audioGroup->root_node_id, 447 &audioGroup->supported_formats, &audioGroup->supported_rates); 448 hda_get_pm_support(audioGroup->codec, audioGroup->root_node_id, 449 &audioGroup->supported_pm); 450 451 verbs[0] = MAKE_VERB(audioGroup->codec->addr, audioGroup->root_node_id, 452 VID_GET_PARAMETER, PID_AUDIO_GROUP_CAP); 453 verbs[1] = MAKE_VERB(audioGroup->codec->addr, audioGroup->root_node_id, 454 VID_GET_PARAMETER, PID_GPIO_COUNT); 455 verbs[2] = MAKE_VERB(audioGroup->codec->addr, audioGroup->root_node_id, 456 VID_GET_PARAMETER, PID_SUB_NODE_COUNT); 457 458 if (hda_send_verbs(audioGroup->codec, verbs, resp, 3) != B_OK) 459 return B_ERROR; 460 461 dprintf("hda: Audio Group: Output delay: %ld samples, Input delay: %ld " 462 "samples, Beep Generator: %s\n", resp[0] & 0xf, 463 (resp[0] >> 8) & 0xf, (resp[0] & (1 << 16)) ? "yes" : "no"); 464 465 dprintf("hda: #GPIO: %ld, #GPO: %ld, #GPI: %ld, unsol: %s, wake: %s\n", 466 resp[4] & 0xff, (resp[1] >> 8) & 0xff, 467 (resp[1] >> 16) & 0xff, (resp[1] & (1 << 30)) ? "yes" : "no", 468 (resp[1] & (1 << 31)) ? "yes" : "no"); 469 470 audioGroup->widget_start = resp[2] >> 16; 471 audioGroup->widget_count = resp[2] & 0xff; 472 473 dprintf("hda: widget start %lu, count %lu\n", audioGroup->widget_start, 474 audioGroup->widget_count); 475 476 audioGroup->widgets = (hda_widget*)calloc(audioGroup->widget_count, 477 sizeof(*audioGroup->widgets)); 478 if (audioGroup->widgets == NULL) { 479 dprintf("ERROR: Not enough memory!\n"); 480 return B_NO_MEMORY; 481 } 482 483 /* Iterate over all Widgets and collect info */ 484 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 485 hda_widget& widget = audioGroup->widgets[i]; 486 uint32 nodeID = audioGroup->widget_start + i; 487 uint32 capabilities; 488 489 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, VID_GET_PARAMETER, 490 PID_AUDIO_WIDGET_CAP); 491 if (hda_send_verbs(audioGroup->codec, verbs, &capabilities, 1) != B_OK) 492 return B_ERROR; 493 494 widget.type = (hda_widget_type)((capabilities & AUDIO_CAP_TYPE_MASK) 495 >> AUDIO_CAP_TYPE_SHIFT); 496 widget.active_input = -1; 497 widget.capabilities.audio = capabilities; 498 widget.node_id = nodeID; 499 500 if ((capabilities & AUDIO_CAP_POWER_CONTROL) != 0) { 501 /* We support power; switch us on! */ 502 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 503 VID_SET_POWER_STATE, 0); 504 hda_send_verbs(audioGroup->codec, verbs, NULL, 1); 505 506 snooze(1000); 507 } 508 if ((capabilities & (AUDIO_CAP_INPUT_AMPLIFIER 509 | AUDIO_CAP_OUTPUT_AMPLIFIER)) != 0) { 510 hda_widget_get_amplifier_capabilities(audioGroup, &widget); 511 } 512 513 dprintf("%ld: %s\n", nodeID, get_widget_type_name(widget.type)); 514 515 switch (widget.type) { 516 case WT_AUDIO_OUTPUT: 517 case WT_AUDIO_INPUT: 518 hda_widget_get_stream_support(audioGroup, &widget); 519 break; 520 521 case WT_PIN_COMPLEX: 522 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 523 VID_GET_PARAMETER, PID_PIN_CAP); 524 if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) == B_OK) { 525 widget.d.pin.input = resp[0] & PIN_CAP_IN; 526 widget.d.pin.output = resp[0] & PIN_CAP_OUT; 527 528 dprintf("\t%s%s\n", widget.d.pin.input ? "[Input] " : "", 529 widget.d.pin.output ? "[Output]" : ""); 530 } else { 531 dprintf("%s: Error getting Pin Complex IO\n", __func__); 532 } 533 534 verbs[0] = MAKE_VERB(audioGroup->codec->addr, nodeID, 535 VID_GET_CONFIGURATION_DEFAULT, 0); 536 if (hda_send_verbs(audioGroup->codec, verbs, resp, 1) == B_OK) { 537 widget.d.pin.device = (pin_dev_type) 538 ((resp[0] >> 20) & 0xf); 539 dprintf("\t%s, %s, %s, %s\n", 540 kPortConnector[resp[0] >> 30], 541 kDefaultDevice[widget.d.pin.device], 542 kConnectionType[(resp[0] >> 16) & 0xF], 543 kJackColor[(resp[0] >> 12) & 0xF]); 544 } 545 break; 546 547 default: 548 break; 549 } 550 551 hda_widget_get_pm_support(audioGroup, &widget); 552 hda_widget_get_connections(audioGroup, &widget); 553 554 dump_widget_pm_support(widget); 555 dump_widget_audio_capabilities(capabilities); 556 dump_widget_amplifier_capabilities(widget, true); 557 dump_widget_amplifier_capabilities(widget, false); 558 dump_widget_inputs(widget); 559 } 560 561 return B_OK; 562 } 563 564 565 /*! Find output path for widget */ 566 static bool 567 hda_widget_find_output_path(hda_audio_group* audioGroup, hda_widget* widget, 568 uint32 depth) 569 { 570 if (widget == NULL || depth > 16) 571 return false; 572 573 switch (widget->type) { 574 case WT_AUDIO_OUTPUT: 575 widget->flags |= WIDGET_FLAG_OUTPUT_PATH; 576 dprintf(" %*soutput: added output widget %ld\n", (int)depth * 2, "", widget->node_id); 577 return true; 578 579 case WT_AUDIO_MIXER: 580 case WT_AUDIO_SELECTOR: 581 { 582 // already used 583 if (widget->flags & WIDGET_FLAG_OUTPUT_PATH) 584 return false; 585 586 // search for output in this path 587 bool found = false; 588 for (uint32 i = 0; i < widget->num_inputs; i++) { 589 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 590 widget->inputs[i]); 591 592 if (hda_widget_find_output_path(audioGroup, inputWidget, 593 depth + 1)) { 594 if (widget->active_input == -1) 595 widget->active_input = i; 596 597 widget->flags |= WIDGET_FLAG_OUTPUT_PATH; 598 dprintf(" %*soutput: added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 599 found = true; 600 } 601 } 602 if (!found) dprintf(" %*soutput: not added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 603 return found; 604 } 605 606 default: 607 return false; 608 } 609 } 610 611 612 /*! Find input path for widget */ 613 static bool 614 hda_widget_find_input_path(hda_audio_group* audioGroup, hda_widget* widget, 615 uint32 depth) 616 { 617 if (widget == NULL || depth > 16) 618 return false; 619 620 switch (widget->type) { 621 case WT_PIN_COMPLEX: 622 if (widget->d.pin.input 623 && (widget->d.pin.device == PIN_DEV_CD 624 || widget->d.pin.device == PIN_DEV_LINE_IN 625 || widget->d.pin.device == PIN_DEV_MIC_IN)) { 626 widget->flags |= WIDGET_FLAG_INPUT_PATH; 627 dprintf(" %*sinput: added input widget %ld\n", (int)depth * 2, "", widget->node_id); 628 return true; 629 } 630 return false; 631 case WT_AUDIO_INPUT: 632 case WT_AUDIO_MIXER: 633 case WT_AUDIO_SELECTOR: 634 { 635 // already used 636 if (widget->flags & WIDGET_FLAG_INPUT_PATH) 637 return false; 638 639 // search for pin complex in this path 640 bool found = false; 641 for (uint32 i = 0; i < widget->num_inputs; i++) { 642 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 643 widget->inputs[i]); 644 645 if (hda_widget_find_input_path(audioGroup, inputWidget, 646 depth + 1)) { 647 if (widget->active_input == -1) 648 widget->active_input = i; 649 650 widget->flags |= WIDGET_FLAG_INPUT_PATH; 651 dprintf(" %*sinput: added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 652 found = true; 653 } 654 } 655 if (!found) dprintf(" %*sinput: not added mixer/selector widget %ld\n", (int)depth * 2, "", widget->node_id); 656 return found; 657 } 658 659 default: 660 return false; 661 } 662 } 663 664 static bool 665 hda_audio_group_build_output_tree(hda_audio_group* audioGroup, bool useMixer) 666 { 667 bool found = false; 668 669 dprintf("build output tree: %suse mixer\n", useMixer ? "" : "don't "); 670 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 671 hda_widget& widget = audioGroup->widgets[i]; 672 673 if (widget.type != WT_PIN_COMPLEX || !widget.d.pin.output 674 || (widget.d.pin.device != PIN_DEV_HEAD_PHONE_OUT 675 && widget.d.pin.device != PIN_DEV_SPEAKER 676 && widget.d.pin.device != PIN_DEV_LINE_OUT)) 677 continue; 678 679 dprintf(" look at pin widget %ld (%ld inputs)\n", widget.node_id, widget.num_inputs); 680 for (uint32 j = 0; j < widget.num_inputs; j++) { 681 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 682 widget.inputs[j]); 683 dprintf(" try widget %ld: %p\n", widget.inputs[j], inputWidget); 684 if (inputWidget == NULL) 685 continue; 686 687 if (useMixer && inputWidget->type != WT_AUDIO_MIXER 688 && inputWidget->type != WT_AUDIO_SELECTOR) 689 continue; 690 dprintf(" widget %ld is candidate\n", inputWidget->node_id); 691 692 if (hda_widget_find_output_path(audioGroup, inputWidget, 0)) { 693 dprintf(" add pin widget %ld\n", widget.node_id); 694 if (widget.active_input == -1) 695 widget.active_input = j; 696 widget.flags |= WIDGET_FLAG_OUTPUT_PATH; 697 found = true; 698 break; 699 } 700 } 701 } 702 703 return found; 704 } 705 706 707 static bool 708 hda_audio_group_build_input_tree(hda_audio_group* audioGroup) 709 { 710 bool found = false; 711 712 dprintf("build input tree\n"); 713 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 714 hda_widget& widget = audioGroup->widgets[i]; 715 716 if (widget.type != WT_AUDIO_INPUT) 717 continue; 718 719 dprintf(" look at input widget %ld (%ld inputs)\n", widget.node_id, widget.num_inputs); 720 for (uint32 j = 0; j < widget.num_inputs; j++) { 721 hda_widget* inputWidget = hda_audio_group_get_widget(audioGroup, 722 widget.inputs[j]); 723 dprintf(" try widget %ld: %p\n", widget.inputs[j], inputWidget); 724 if (inputWidget == NULL) 725 continue; 726 727 dprintf(" widget %ld is candidate\n", inputWidget->node_id); 728 729 if (hda_widget_find_input_path(audioGroup, inputWidget, 0)) { 730 dprintf(" add pin widget %ld\n", widget.node_id); 731 if (widget.active_input == -1) 732 widget.active_input = j; 733 widget.flags |= WIDGET_FLAG_INPUT_PATH; 734 found = true; 735 break; 736 } 737 } 738 } 739 740 return found; 741 } 742 743 744 static status_t 745 hda_audio_group_build_tree(hda_audio_group* audioGroup) 746 { 747 if (!hda_audio_group_build_output_tree(audioGroup, true)) { 748 // didn't find a mixer path, try again without 749 dprintf("try without mixer!\n"); 750 if (!hda_audio_group_build_output_tree(audioGroup, false)) 751 return ENODEV; 752 } 753 754 if (!hda_audio_group_build_input_tree(audioGroup)) { 755 dprintf("hda: build input tree failed\n"); 756 } 757 758 dprintf("build tree!\n"); 759 760 // select active connections 761 762 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 763 hda_widget& widget = audioGroup->widgets[i]; 764 765 if (widget.active_input == -1) 766 widget.active_input = 0; 767 if (widget.num_inputs < 2) 768 continue; 769 770 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 771 widget.node_id, VID_SET_CONNECTION_SELECT, widget.active_input); 772 if (hda_send_verbs(audioGroup->codec, &verb, NULL, 1) != B_OK) { 773 dprintf("hda: Setting output selector %ld failed on widget %ld!\n", 774 widget.active_input, widget.node_id); 775 } 776 } 777 778 dump_audiogroup_widgets(audioGroup); 779 780 return B_OK; 781 } 782 783 784 static void 785 hda_codec_delete_audio_group(hda_audio_group* audioGroup) 786 { 787 if (audioGroup == NULL) 788 return; 789 790 if (audioGroup->playback_stream != NULL) 791 hda_stream_delete(audioGroup->playback_stream); 792 793 if (audioGroup->record_stream != NULL) 794 hda_stream_delete(audioGroup->record_stream); 795 796 free(audioGroup->widgets); 797 free(audioGroup); 798 } 799 800 801 static status_t 802 hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID) 803 { 804 hda_audio_group* audioGroup = (hda_audio_group*)calloc(1, 805 sizeof(hda_audio_group)); 806 if (audioGroup == NULL) 807 return B_NO_MEMORY; 808 809 /* Setup minimal info needed by hda_codec_parse_afg */ 810 audioGroup->root_node_id = audioGroupNodeID; 811 audioGroup->codec = codec; 812 813 /* Parse all widgets in Audio Function Group */ 814 status_t status = hda_codec_parse_audio_group(audioGroup); 815 if (status != B_OK) 816 goto err; 817 818 /* Setup for worst-case scenario; we cannot find any output Pin Widgets */ 819 status = ENODEV; 820 821 if (hda_audio_group_build_tree(audioGroup) != B_OK) 822 goto err; 823 824 audioGroup->playback_stream = hda_stream_new(audioGroup, STREAM_PLAYBACK); 825 audioGroup->record_stream = hda_stream_new(audioGroup, STREAM_RECORD); 826 dprintf("hda: streams playback %p, record %p\n", audioGroup->playback_stream, 827 audioGroup->record_stream); 828 829 if (audioGroup->playback_stream != NULL 830 || audioGroup->record_stream != NULL) { 831 codec->audio_groups[codec->num_audio_groups++] = audioGroup; 832 return B_OK; 833 } 834 835 err: 836 free(audioGroup->widgets); 837 free(audioGroup); 838 return status; 839 } 840 841 842 // #pragma mark - 843 844 845 status_t 846 hda_audio_group_get_widgets(hda_audio_group* audioGroup, hda_stream* stream) 847 { 848 hda_widget_type type; 849 uint32 flags; 850 851 if (stream->type == STREAM_PLAYBACK) { 852 type = WT_AUDIO_OUTPUT; 853 flags = WIDGET_FLAG_OUTPUT_PATH; 854 } else { 855 // record 856 type = WT_AUDIO_INPUT; 857 flags = WIDGET_FLAG_INPUT_PATH; 858 } 859 860 uint32 count = 0; 861 862 for (uint32 i = 0; i < audioGroup->widget_count && count < MAX_IO_WIDGETS; 863 i++) { 864 hda_widget& widget = audioGroup->widgets[i]; 865 866 if ((widget.flags & flags) != 0) { 867 if (widget.type == WT_PIN_COMPLEX) { 868 stream->pin_widget = widget.node_id; 869 870 dprintf("ENABLE pin widget %ld\n", widget.node_id); 871 /* FIXME: Force Pin Widget to unmute; enable hp/output */ 872 uint32 verb = MAKE_VERB(audioGroup->codec->addr, 873 widget.node_id, 874 VID_SET_PIN_WIDGET_CONTROL, 875 flags == WIDGET_FLAG_OUTPUT_PATH ? 876 PIN_ENABLE_HEAD_PHONE | PIN_ENABLE_OUTPUT 877 : PIN_ENABLE_INPUT); 878 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 879 } 880 881 if (widget.capabilities.output_amplifier != 0) { 882 dprintf("UNMUTE/SET GAIN widget %ld (offset %ld)\n", widget.node_id, 883 widget.capabilities.output_amplifier & AMP_CAP_OFFSET_MASK); 884 uint32 verb = MAKE_VERB(audioGroup->codec->addr, 885 widget.node_id, 886 VID_SET_AMPLIFIER_GAIN_MUTE, 887 AMP_SET_OUTPUT | AMP_SET_LEFT_CHANNEL 888 | AMP_SET_RIGHT_CHANNEL 889 | (widget.capabilities.output_amplifier 890 & AMP_CAP_OFFSET_MASK)); 891 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 892 } 893 } 894 895 if (widget.type != type || (widget.flags & flags) == 0 896 || (widget.capabilities.audio 897 & (AUDIO_CAP_STEREO | AUDIO_CAP_DIGITAL)) != AUDIO_CAP_STEREO 898 || widget.d.io.formats == 0) 899 continue; 900 901 if (count == 0) { 902 stream->sample_format = widget.d.io.formats; 903 stream->sample_rate = widget.d.io.rates; 904 } else { 905 stream->sample_format &= widget.d.io.formats; 906 stream->sample_rate &= widget.d.io.rates; 907 } 908 909 stream->io_widgets[count++] = widget.node_id; 910 } 911 912 if (count == 0) 913 return B_ENTRY_NOT_FOUND; 914 915 stream->num_io_widgets = count; 916 return B_OK; 917 } 918 919 920 void 921 hda_codec_delete(hda_codec* codec) 922 { 923 if (codec == NULL) 924 return; 925 926 delete_sem(codec->response_sem); 927 928 for (uint32 i = 0; i < codec->num_audio_groups; i++) { 929 hda_codec_delete_audio_group(codec->audio_groups[i]); 930 codec->audio_groups[i] = NULL; 931 } 932 933 free(codec); 934 } 935 936 937 hda_codec* 938 hda_codec_new(hda_controller* controller, uint32 codecAddress) 939 { 940 if (codecAddress > HDA_MAX_CODECS) 941 return NULL; 942 943 hda_codec* codec = (hda_codec*)calloc(1, sizeof(hda_codec)); 944 if (codec == NULL) 945 return NULL; 946 947 codec->controller = controller; 948 codec->addr = codecAddress; 949 codec->response_sem = create_sem(0, "hda_codec_response_sem"); 950 controller->codecs[codecAddress] = codec; 951 952 struct { 953 uint32 device : 16; 954 uint32 vendor : 16; 955 uint32 stepping : 8; 956 uint32 revision : 8; 957 uint32 minor : 4; 958 uint32 major : 4; 959 uint32 _reserved0 : 8; 960 uint32 count : 8; 961 uint32 _reserved1 : 8; 962 uint32 start : 8; 963 uint32 _reserved2 : 8; 964 } response; 965 corb_t verbs[3]; 966 967 verbs[0] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_VENDOR_ID); 968 verbs[1] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_REVISION_ID); 969 verbs[2] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, 970 PID_SUB_NODE_COUNT); 971 972 if (hda_send_verbs(codec, verbs, (uint32*)&response, 3) != B_OK) 973 goto err; 974 975 dprintf("Codec %ld Vendor: %04lx Product: %04lx, Revision: " 976 "%lu.%lu.%lu.%lu\n", codecAddress, response.vendor, response.device, 977 response.major, response.minor, response.revision, response.stepping); 978 979 for (uint32 nodeID = response.start; nodeID < response.start 980 + response.count; nodeID++) { 981 uint32 groupType; 982 verbs[0] = MAKE_VERB(codecAddress, nodeID, VID_GET_PARAMETER, 983 PID_FUNCTION_GROUP_TYPE); 984 985 if (hda_send_verbs(codec, verbs, &groupType, 1) != B_OK) 986 goto err; 987 988 if ((groupType & 0xff) == 1) { 989 /* Found an Audio Function Group! */ 990 status_t status = hda_codec_new_audio_group(codec, nodeID); 991 if (status != B_OK) { 992 dprintf("hda: Failed to setup new audio function group (%s)!\n", 993 strerror(status)); 994 goto err; 995 } 996 } 997 } 998 999 return codec; 1000 1001 err: 1002 controller->codecs[codecAddress] = NULL; 1003 hda_codec_delete(codec); 1004 return NULL; 1005 } 1006