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_audio_group_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 void 1178 hda_audio_group_check_sense(hda_audio_group* audioGroup, bool disable) 1179 { 1180 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 1181 hda_widget& widget = audioGroup->widgets[i]; 1182 1183 if (widget.type != WT_PIN_COMPLEX 1184 || !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities) 1185 || CONF_DEFAULT_DEVICE(widget.d.pin.config) 1186 != PIN_DEV_HEAD_PHONE_OUT) 1187 continue; 1188 1189 corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id, 1190 VID_GET_PINSENSE, 0); 1191 uint32 response; 1192 hda_send_verbs(audioGroup->codec, &verb, &response, 1); 1193 disable = response & PIN_SENSE_PRESENCE_DETECT; 1194 TRACE("hda: sensed pin widget %ld, %d\n", widget.node_id, disable); 1195 1196 uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget, 1197 true); 1198 verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id, 1199 VID_SET_PIN_WIDGET_CONTROL, disable ? ctrl : 0); 1200 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1201 break; 1202 } 1203 1204 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 1205 hda_widget& widget = audioGroup->widgets[i]; 1206 1207 if (widget.type != WT_PIN_COMPLEX 1208 || !PIN_CAP_IS_OUTPUT(widget.d.pin.capabilities)) 1209 continue; 1210 1211 int device = CONF_DEFAULT_DEVICE(widget.d.pin.config); 1212 if (device != PIN_DEV_AUX 1213 && device != PIN_DEV_SPEAKER 1214 && device != PIN_DEV_LINE_OUT) 1215 continue; 1216 1217 uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget, 1218 true); 1219 corb_t verb = MAKE_VERB(audioGroup->codec->addr, widget.node_id, 1220 VID_SET_PIN_WIDGET_CONTROL, disable ? 0 : ctrl); 1221 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1222 } 1223 } 1224 1225 1226 static status_t 1227 hda_codec_switch_handler(hda_codec* codec) 1228 { 1229 while (acquire_sem(codec->unsol_response_sem) == B_OK) { 1230 uint32 response = codec->unsol_responses[codec->unsol_response_read++]; 1231 codec->unsol_response_read %= MAX_CODEC_UNSOL_RESPONSES; 1232 1233 bool disable = response & 1; 1234 hda_audio_group* audioGroup = codec->audio_groups[0]; 1235 hda_audio_group_check_sense(audioGroup, disable); 1236 } 1237 return B_OK; 1238 } 1239 1240 1241 static void 1242 hda_codec_delete_audio_group(hda_audio_group* audioGroup) 1243 { 1244 if (audioGroup == NULL) 1245 return; 1246 1247 if (audioGroup->playback_stream != NULL) 1248 hda_stream_delete(audioGroup->playback_stream); 1249 1250 if (audioGroup->record_stream != NULL) 1251 hda_stream_delete(audioGroup->record_stream); 1252 free(audioGroup->multi); 1253 free(audioGroup->widgets); 1254 free(audioGroup); 1255 } 1256 1257 1258 static status_t 1259 hda_codec_new_audio_group(hda_codec* codec, uint32 audioGroupNodeID) 1260 { 1261 hda_audio_group* audioGroup = (hda_audio_group*)calloc(1, 1262 sizeof(hda_audio_group)); 1263 if (audioGroup == NULL) 1264 return B_NO_MEMORY; 1265 1266 // Setup minimal info needed by hda_codec_parse_afg 1267 audioGroup->widget.node_id = audioGroupNodeID; 1268 audioGroup->codec = codec; 1269 audioGroup->multi = (hda_multi*)calloc(1, 1270 sizeof(hda_multi)); 1271 if (audioGroup->multi == NULL) { 1272 free(audioGroup); 1273 return B_NO_MEMORY; 1274 } 1275 audioGroup->multi->group = audioGroup; 1276 1277 // Parse all widgets in Audio Function Group 1278 status_t status = hda_codec_parse_audio_group(audioGroup); 1279 if (status != B_OK) 1280 goto err; 1281 1282 // Setup for worst-case scenario; we cannot find any output Pin Widgets 1283 status = ENODEV; 1284 1285 if (hda_audio_group_build_tree(audioGroup) != B_OK) 1286 goto err; 1287 hda_audio_group_switch_init(audioGroup); 1288 1289 audioGroup->playback_stream = hda_stream_new(audioGroup, STREAM_PLAYBACK); 1290 audioGroup->record_stream = hda_stream_new(audioGroup, STREAM_RECORD); 1291 TRACE("hda: streams playback %p, record %p\n", audioGroup->playback_stream, 1292 audioGroup->record_stream); 1293 1294 if (audioGroup->playback_stream != NULL 1295 || audioGroup->record_stream != NULL) { 1296 codec->audio_groups[codec->num_audio_groups++] = audioGroup; 1297 hda_audio_group_check_sense(audioGroup, false); 1298 return B_OK; 1299 } 1300 1301 err: 1302 free(audioGroup->widgets); 1303 free(audioGroup); 1304 return status; 1305 } 1306 1307 1308 // #pragma mark - 1309 1310 1311 status_t 1312 hda_audio_group_get_widgets(hda_audio_group* audioGroup, hda_stream* stream) 1313 { 1314 hda_widget_type type; 1315 uint32 flags; 1316 1317 if (stream->type == STREAM_PLAYBACK) { 1318 type = WT_AUDIO_OUTPUT; 1319 flags = WIDGET_FLAG_OUTPUT_PATH; 1320 } else { 1321 // record 1322 type = WT_AUDIO_INPUT; 1323 flags = WIDGET_FLAG_INPUT_PATH; 1324 } 1325 1326 uint32 count = 0; 1327 1328 for (uint32 i = 0; i < audioGroup->widget_count && count < MAX_IO_WIDGETS; 1329 i++) { 1330 hda_widget& widget = audioGroup->widgets[i]; 1331 1332 if ((widget.flags & flags) != 0) { 1333 if (widget.type == WT_PIN_COMPLEX) { 1334 stream->pin_widget = widget.node_id; 1335 1336 uint32 ctrl = hda_widget_prepare_pin_ctrl(audioGroup, &widget, 1337 flags == WIDGET_FLAG_OUTPUT_PATH); 1338 1339 TRACE("ENABLE pin widget %ld\n", widget.node_id); 1340 // FIXME: Force Pin Widget to unmute; enable hp/output 1341 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 1342 widget.node_id, 1343 VID_SET_PIN_WIDGET_CONTROL, ctrl); 1344 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1345 1346 if (PIN_CAP_IS_EAPD_CAP(widget.d.pin.capabilities)) { 1347 uint32 result; 1348 verb = MAKE_VERB(audioGroup->codec->addr, 1349 widget.node_id, VID_GET_EAPDBTL_EN, 0); 1350 if (hda_send_verbs(audioGroup->codec, &verb, 1351 &result, 1) == B_OK) { 1352 result &= 0xff; 1353 verb = MAKE_VERB(audioGroup->codec->addr, 1354 widget.node_id, VID_SET_EAPDBTL_EN, 1355 result | EAPDBTL_ENABLE_EAPD); 1356 hda_send_verbs(audioGroup->codec, 1357 &verb, NULL, 1); 1358 TRACE("ENABLE EAPD pin widget %ld\n", widget.node_id); 1359 } 1360 } 1361 } 1362 1363 if (widget.capabilities.output_amplifier != 0) { 1364 TRACE("UNMUTE/SET OUTPUT GAIN widget %ld (offset %ld)\n", widget.node_id, 1365 AMP_CAP_OFFSET(widget.capabilities.output_amplifier)); 1366 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 1367 widget.node_id, 1368 VID_SET_AMPLIFIER_GAIN_MUTE, 1369 AMP_SET_OUTPUT | AMP_SET_LEFT_CHANNEL 1370 | AMP_SET_RIGHT_CHANNEL 1371 | AMP_CAP_OFFSET(widget.capabilities.output_amplifier)); 1372 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1373 } 1374 if (widget.capabilities.input_amplifier != 0) { 1375 TRACE("UNMUTE/SET INPUT GAIN widget %ld (offset %ld)\n", widget.node_id, 1376 AMP_CAP_OFFSET(widget.capabilities.input_amplifier)); 1377 for (uint32 i = 0; i < widget.num_inputs; i++) { 1378 corb_t verb = MAKE_VERB(audioGroup->codec->addr, 1379 widget.node_id, 1380 VID_SET_AMPLIFIER_GAIN_MUTE, 1381 AMP_SET_INPUT | AMP_SET_LEFT_CHANNEL 1382 | AMP_SET_RIGHT_CHANNEL 1383 | AMP_SET_INPUT_INDEX(i) 1384 | ((widget.active_input == (int32)i) ? 0 : AMP_MUTE) 1385 | AMP_CAP_OFFSET(widget.capabilities.input_amplifier)); 1386 hda_send_verbs(audioGroup->codec, &verb, NULL, 1); 1387 } 1388 } 1389 } 1390 1391 if (widget.type != type || (widget.flags & flags) == 0 1392 || (widget.capabilities.audio 1393 & (AUDIO_CAP_STEREO | AUDIO_CAP_DIGITAL)) != AUDIO_CAP_STEREO 1394 || widget.d.io.formats == 0) 1395 continue; 1396 1397 if (count == 0) { 1398 stream->sample_format = widget.d.io.formats; 1399 stream->sample_rate = widget.d.io.rates; 1400 } else { 1401 stream->sample_format &= widget.d.io.formats; 1402 stream->sample_rate &= widget.d.io.rates; 1403 } 1404 1405 stream->io_widgets[count++] = widget.node_id; 1406 } 1407 1408 if (count == 0) 1409 return B_ENTRY_NOT_FOUND; 1410 1411 stream->num_io_widgets = count; 1412 return B_OK; 1413 } 1414 1415 1416 void 1417 hda_codec_delete(hda_codec* codec) 1418 { 1419 if (codec == NULL) 1420 return; 1421 1422 delete_sem(codec->response_sem); 1423 delete_sem(codec->unsol_response_sem); 1424 1425 int32 result; 1426 wait_for_thread(codec->unsol_response_thread, &result); 1427 1428 for (uint32 i = 0; i < codec->num_audio_groups; i++) { 1429 hda_codec_delete_audio_group(codec->audio_groups[i]); 1430 codec->audio_groups[i] = NULL; 1431 } 1432 1433 free(codec); 1434 } 1435 1436 1437 hda_codec* 1438 hda_codec_new(hda_controller* controller, uint32 codecAddress) 1439 { 1440 if (codecAddress > HDA_MAX_CODECS) 1441 return NULL; 1442 1443 hda_codec* codec = (hda_codec*)calloc(1, sizeof(hda_codec)); 1444 if (codec == NULL) { 1445 ERROR("hda: Failed to alloc a codec\n"); 1446 return NULL; 1447 } 1448 1449 status_t status; 1450 1451 codec->controller = controller; 1452 codec->addr = codecAddress; 1453 codec->response_sem = create_sem(0, "hda_codec_response_sem"); 1454 if (codec->response_sem < B_OK) { 1455 ERROR("hda: Failed to create semaphore\n"); 1456 goto err; 1457 } 1458 controller->codecs[codecAddress] = codec; 1459 1460 codec->unsol_response_sem = create_sem(0, "hda_codec_unsol_response_sem"); 1461 if (codec->unsol_response_sem < B_OK) { 1462 ERROR("hda: Failed to create semaphore\n"); 1463 goto err; 1464 } 1465 codec->unsol_response_read = 0; 1466 codec->unsol_response_write = 0; 1467 1468 struct { 1469 uint32 device : 16; 1470 uint32 vendor : 16; 1471 uint32 stepping : 8; 1472 uint32 revision : 8; 1473 uint32 minor : 4; 1474 uint32 major : 4; 1475 uint32 _reserved0 : 8; 1476 uint32 count : 8; 1477 uint32 _reserved1 : 8; 1478 uint32 start : 8; 1479 uint32 _reserved2 : 8; 1480 } response; 1481 1482 corb_t verbs[3]; 1483 verbs[0] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_VENDOR_ID); 1484 verbs[1] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, PID_REVISION_ID); 1485 verbs[2] = MAKE_VERB(codecAddress, 0, VID_GET_PARAMETER, 1486 PID_SUB_NODE_COUNT); 1487 1488 status = hda_send_verbs(codec, verbs, (uint32*)&response, 3); 1489 if (status != B_OK) { 1490 ERROR("hda: Failed to get vendor and revision parameters: %s\n", 1491 strerror(status)); 1492 goto err; 1493 } 1494 1495 codec->vendor_id = response.vendor; 1496 codec->product_id = response.device; 1497 codec->stepping = response.stepping; 1498 codec->revision = response.revision; 1499 codec->minor = response.minor; 1500 codec->major = response.major; 1501 hda_codec_get_quirks(codec); 1502 1503 TRACE("Codec %ld Vendor: %04lx Product: %04lx, Revision: " 1504 "%lu.%lu.%lu.%lu\n", codecAddress, response.vendor, response.device, 1505 response.major, response.minor, response.revision, response.stepping); 1506 1507 for (uint32 nodeID = response.start; 1508 nodeID < response.start + response.count; nodeID++) { 1509 uint32 groupType; 1510 verbs[0] = MAKE_VERB(codecAddress, nodeID, VID_GET_PARAMETER, 1511 PID_FUNCTION_GROUP_TYPE); 1512 1513 if (hda_send_verbs(codec, verbs, &groupType, 1) != B_OK) { 1514 ERROR("hda: Failed to get function group type\n"); 1515 goto err; 1516 } 1517 1518 if ((groupType & FUNCTION_GROUP_NODETYPE_MASK) 1519 == FUNCTION_GROUP_NODETYPE_AUDIO) { 1520 // Found an Audio Function Group! 1521 status_t status = hda_codec_new_audio_group(codec, nodeID); 1522 if (status != B_OK) { 1523 ERROR("hda: Failed to setup new audio function group (%s)!\n", 1524 strerror(status)); 1525 goto err; 1526 } 1527 } 1528 } 1529 1530 codec->unsol_response_thread = spawn_kernel_thread( 1531 (status_t(*)(void*))hda_codec_switch_handler, 1532 "hda_codec_unsol_thread", B_LOW_PRIORITY, codec); 1533 if (codec->unsol_response_thread < B_OK) { 1534 ERROR("hda: Failed to spawn thread\n"); 1535 goto err; 1536 } 1537 resume_thread(codec->unsol_response_thread); 1538 1539 return codec; 1540 1541 err: 1542 controller->codecs[codecAddress] = NULL; 1543 hda_codec_delete(codec); 1544 return NULL; 1545 } 1546