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