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