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