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