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