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