1 /* 2 * Copyright 2007-2010, 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 */ 9 10 11 #include <driver_settings.h> 12 13 #include "hmulti_audio.h" 14 #include "driver.h" 15 16 #include <kernel.h> 17 18 19 #ifdef TRACE 20 # undef TRACE 21 #endif 22 23 //#define TRACE_MULTI_AUDIO 24 #ifdef TRACE_MULTI_AUDIO 25 # define TRACE(a...) dprintf("hda: " a) 26 #else 27 # define TRACE(a...) ; 28 #endif 29 #define ERROR(a...) dprintf("hda: " a) 30 31 typedef enum { 32 B_MIX_GAIN = 1 << 0, 33 B_MIX_MUTE = 1 << 1, 34 B_MIX_MUX_MIXER = 1 << 2, 35 B_MIX_MUX_SELECTOR = 1 << 3 36 } mixer_type; 37 38 39 static multi_channel_info sChannels[] = { 40 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 41 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 42 { 2, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 43 { 3, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 44 { 4, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 45 B_CHANNEL_MINI_JACK_STEREO }, 46 { 5, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 47 B_CHANNEL_MINI_JACK_STEREO }, 48 { 6, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 49 B_CHANNEL_MINI_JACK_STEREO }, 50 { 7, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 51 B_CHANNEL_MINI_JACK_STEREO }, 52 }; 53 54 55 static int32 56 format2size(uint32 format) 57 { 58 switch (format) { 59 case B_FMT_8BIT_S: 60 case B_FMT_16BIT: 61 return 2; 62 63 case B_FMT_18BIT: 64 case B_FMT_20BIT: 65 case B_FMT_24BIT: 66 case B_FMT_32BIT: 67 case B_FMT_FLOAT: 68 return 4; 69 70 default: 71 return -1; 72 } 73 } 74 75 76 #define HDA_SETTINGS "hda.settings" 77 78 static struct { 79 int32 play_buffer_frames; 80 int32 play_buffer_count; 81 int32 record_buffer_frames; 82 int32 record_buffer_count; 83 } requested_settings; 84 85 86 void 87 get_settings_from_file() 88 { 89 const char *item; 90 char *end; 91 uint32 value; 92 93 memset(&requested_settings, 0, sizeof(requested_settings)); 94 dprintf("looking for settings file\n"); 95 96 void *settings_handle = load_driver_settings(HDA_SETTINGS); 97 if (settings_handle == NULL) 98 return; 99 100 item = get_driver_parameter (settings_handle, "play_buffer_frames", NULL, 101 NULL); 102 if (item) { 103 value = strtoul (item, &end, 0); 104 if (*end == '\0') 105 requested_settings.play_buffer_frames = value; 106 } 107 108 item = get_driver_parameter (settings_handle, "play_buffer_count", NULL, 109 NULL); 110 if (item) { 111 value = strtoul (item, &end, 0); 112 if (*end == '\0') 113 requested_settings.play_buffer_count = value; 114 } 115 116 item = get_driver_parameter (settings_handle, "record_buffer_frames", NULL, 117 NULL); 118 if (item) { 119 value = strtoul (item, &end, 0); 120 if (*end == '\0') 121 requested_settings.record_buffer_frames = value; 122 } 123 124 item = get_driver_parameter (settings_handle, "record_buffer_count", NULL, 125 NULL); 126 if (item) { 127 value = strtoul (item, &end, 0); 128 if (*end == '\0') 129 requested_settings.record_buffer_count = value; 130 } 131 132 unload_driver_settings(settings_handle); 133 } 134 135 136 static status_t 137 get_description(hda_audio_group* audioGroup, multi_description* data) 138 { 139 data->interface_version = B_CURRENT_INTERFACE_VERSION; 140 data->interface_minimum = B_CURRENT_INTERFACE_VERSION; 141 142 strcpy(data->friendly_name, "HD Audio"); 143 strcpy(data->vendor_info, "Haiku"); 144 145 int32 inChannels = 0; 146 if (audioGroup->record_stream != NULL) 147 inChannels = 2; 148 149 int32 outChannels = 0; 150 if (audioGroup->playback_stream != NULL) 151 outChannels = 2; 152 153 data->output_channel_count = outChannels; 154 data->output_bus_channel_count = outChannels; 155 data->input_channel_count = inChannels; 156 data->input_bus_channel_count = inChannels; 157 data->aux_bus_channel_count = 0; 158 159 TRACE("%s: request_channel_count: %" B_PRId32 "\n", __func__, 160 data->request_channel_count); 161 162 if (data->request_channel_count >= (int)(sizeof(sChannels) 163 / sizeof(sChannels[0]))) { 164 memcpy(data->channels, &sChannels, sizeof(sChannels)); 165 } 166 167 if (audioGroup->playback_stream != NULL) { 168 data->output_rates = audioGroup->playback_stream->sample_rate; 169 data->output_formats = audioGroup->playback_stream->sample_format; 170 } else { 171 data->output_rates = 0; 172 data->output_formats = 0; 173 } 174 175 if (audioGroup->record_stream != NULL) { 176 data->input_rates = audioGroup->record_stream->sample_rate; 177 data->input_formats = audioGroup->record_stream->sample_format; 178 } else { 179 data->input_rates = 0; 180 data->input_formats = 0; 181 } 182 183 // force existance of 48kHz if variable rates are not supported 184 if (data->output_rates == 0) 185 data->output_rates = B_SR_48000; 186 if (data->input_rates == 0) 187 data->input_rates = B_SR_48000; 188 189 data->max_cvsr_rate = 0; 190 data->min_cvsr_rate = 0; 191 192 data->lock_sources = B_MULTI_LOCK_INTERNAL; 193 data->timecode_sources = 0; 194 data->interface_flags 195 = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD; 196 data->start_latency = 30000; 197 198 strcpy(data->control_panel, ""); 199 200 return B_OK; 201 } 202 203 204 static status_t 205 get_enabled_channels(hda_audio_group* audioGroup, multi_channel_enable* data) 206 { 207 data->lock_source = B_MULTI_LOCK_INTERNAL; 208 209 int32 inChannels = 0; 210 if (audioGroup->record_stream != NULL) 211 inChannels = 2; 212 213 int32 outChannels = 0; 214 if (audioGroup->playback_stream != NULL) 215 outChannels = 2; 216 217 uint32 enable_bits = 0; 218 uint32 maxChannels = min_c(32, inChannels + outChannels); 219 for (uint32 i = 0; i < maxChannels; i++) 220 B_SET_CHANNEL(&enable_bits, i, true); 221 222 return B_OK; 223 } 224 225 226 static status_t 227 get_global_format(hda_audio_group* audioGroup, multi_format_info* data) 228 { 229 data->output_latency = 0; 230 data->input_latency = 0; 231 data->timecode_kind = 0; 232 233 if (audioGroup->playback_stream != NULL) { 234 data->output.format = audioGroup->playback_stream->sample_format; 235 data->output.rate = audioGroup->playback_stream->sample_rate; 236 } else { 237 data->output.format = 0; 238 data->output.rate = 0; 239 } 240 241 if (audioGroup->record_stream != NULL) { 242 data->input.format = audioGroup->record_stream->sample_format; 243 data->input.rate = audioGroup->record_stream->sample_rate; 244 } else { 245 data->input.format = 0; 246 data->input.rate = 0; 247 } 248 249 return B_OK; 250 } 251 252 253 static status_t 254 set_global_format(hda_audio_group* audioGroup, multi_format_info* data) 255 { 256 // TODO: it looks like we're not supposed to fail; fix this! 257 #if 0 258 if ((data->output.format & audioGroup->supported_formats) == 0) 259 || (data->output.rate & audioGroup->supported_rates) == 0) 260 return B_BAD_VALUE; 261 #endif 262 263 if (audioGroup->playback_stream != NULL) { 264 audioGroup->playback_stream->sample_format = data->output.format; 265 audioGroup->playback_stream->sample_rate = data->output.rate; 266 audioGroup->playback_stream->sample_size = format2size( 267 audioGroup->playback_stream->sample_format); 268 } 269 270 if (audioGroup->record_stream != NULL) { 271 audioGroup->record_stream->sample_rate = data->input.rate; 272 audioGroup->record_stream->sample_format = data->input.format; 273 audioGroup->record_stream->sample_size = format2size( 274 audioGroup->record_stream->sample_format); 275 } 276 277 return B_OK; 278 } 279 280 281 static enum strind_id 282 hda_find_multi_string(hda_widget& widget) 283 { 284 switch (CONF_DEFAULT_DEVICE(widget.d.pin.config)) { 285 case PIN_DEV_CD: 286 return S_CD; 287 case PIN_DEV_LINE_IN: 288 case PIN_DEV_LINE_OUT: 289 return S_LINE; 290 case PIN_DEV_MIC_IN: 291 return S_MIC; 292 case PIN_DEV_AUX: 293 return S_AUX; 294 case PIN_DEV_SPDIF_IN: 295 case PIN_DEV_SPDIF_OUT: 296 return S_SPDIF; 297 case PIN_DEV_HEAD_PHONE_OUT: 298 return S_HEADPHONE; 299 } 300 ERROR("couln't find a string for widget %" B_PRIu32 " in " 301 "hda_find_multi_string()\n", widget.node_id); 302 return S_null; 303 } 304 305 306 static void 307 hda_find_multi_custom_string(hda_widget& widget, char* custom, uint32 size) 308 { 309 const char* device = NULL; 310 switch (CONF_DEFAULT_DEVICE(widget.d.pin.config)) { 311 case PIN_DEV_LINE_IN: 312 device = "Line in"; 313 case PIN_DEV_LINE_OUT: 314 if (device == NULL) 315 device = "Line out"; 316 case PIN_DEV_MIC_IN: 317 if (device == NULL) 318 device = "Mic in"; 319 switch (CONF_DEFAULT_COLOR(widget.d.pin.config)) { 320 case 1: 321 device = "Rear"; 322 break; 323 case 2: 324 device = "Side"; 325 break; 326 case 3: 327 device = "Line in"; 328 break; 329 case 4: 330 device = "Front"; 331 break; 332 case 6: 333 device = "Center/Sub"; 334 break; 335 case 9: 336 device = "Mic in"; 337 break; 338 } 339 break; 340 case PIN_DEV_SPDIF_IN: 341 device = "SPDIF in"; 342 break; 343 case PIN_DEV_SPDIF_OUT: 344 device = "SPDIF out"; 345 break; 346 case PIN_DEV_CD: 347 device = "CD"; 348 break; 349 case PIN_DEV_HEAD_PHONE_OUT: 350 device = "Headphones"; 351 break; 352 case PIN_DEV_SPEAKER: 353 device = "Speaker"; 354 break; 355 } 356 if (device == NULL) { 357 ERROR("couldn't find a string for widget %" B_PRIu32 " in " 358 "hda_find_multi_custom_string()\n", widget.node_id); 359 } 360 361 const char* location 362 = get_widget_location(CONF_DEFAULT_LOCATION(widget.d.pin.config)); 363 snprintf(custom, size, "%s%s%s", location ? location : "", 364 location ? " " : "", device); 365 } 366 367 368 static int32 369 hda_create_group_control(hda_multi *multi, uint32 *index, int32 parent, 370 enum strind_id string, const char* name) 371 { 372 uint32 i = *index; 373 (*index)++; 374 multi->controls[i].mix_control.id = MULTI_CONTROL_FIRSTID + i; 375 multi->controls[i].mix_control.parent = parent; 376 multi->controls[i].mix_control.flags = B_MULTI_MIX_GROUP; 377 multi->controls[i].mix_control.master = MULTI_CONTROL_MASTERID; 378 multi->controls[i].mix_control.string = string; 379 if (name) 380 strcpy(multi->controls[i].mix_control.name, name); 381 382 return multi->controls[i].mix_control.id; 383 } 384 385 386 static void 387 hda_create_channel_control(hda_multi* multi, uint32* index, int32 parent, 388 int32 string, hda_widget& widget, bool input, uint32 capabilities, 389 int32 inputIndex, bool& gain, bool& mute) 390 { 391 uint32 i = *index, id; 392 hda_multi_mixer_control control; 393 394 control.nid = widget.node_id; 395 control.input = input; 396 control.mute = 0; 397 control.gain = 0; 398 control.capabilities = capabilities; 399 control.index = inputIndex; 400 control.mix_control.master = MULTI_CONTROL_MASTERID; 401 control.mix_control.parent = parent; 402 403 if (mute && (capabilities & AMP_CAP_MUTE) != 0) { 404 control.mix_control.id = MULTI_CONTROL_FIRSTID + i; 405 control.mix_control.flags = B_MULTI_MIX_ENABLE; 406 control.mix_control.string = S_MUTE; 407 control.type = B_MIX_MUTE; 408 multi->controls[i++] = control; 409 TRACE("control nid %" B_PRIu32 " mute\n", control.nid); 410 mute = false; 411 } 412 413 if (gain && AMP_CAP_NUM_STEPS(capabilities) >= 1) { 414 control.mix_control.gain.granularity = AMP_CAP_STEP_SIZE(capabilities); 415 control.mix_control.gain.min_gain = (0.0 - AMP_CAP_OFFSET(capabilities)) 416 * control.mix_control.gain.granularity; 417 control.mix_control.gain.max_gain = (AMP_CAP_NUM_STEPS(capabilities) 418 - AMP_CAP_OFFSET(capabilities)) 419 * control.mix_control.gain.granularity; 420 421 control.mix_control.id = MULTI_CONTROL_FIRSTID + i; 422 control.mix_control.flags = B_MULTI_MIX_GAIN; 423 control.mix_control.string = S_null; 424 control.type = B_MIX_GAIN; 425 strcpy(control.mix_control.name, "Gain"); 426 multi->controls[i++] = control; 427 id = control.mix_control.id; 428 429 // second channel 430 control.mix_control.id = MULTI_CONTROL_FIRSTID + i; 431 control.mix_control.master = id; 432 multi->controls[i++] = control; 433 TRACE("control nid %" B_PRIu32 " %f min %f max %f\n", control.nid, 434 control.mix_control.gain.granularity, 435 control.mix_control.gain.min_gain, 436 control.mix_control.gain.max_gain); 437 gain = false; 438 } 439 440 *index = i; 441 } 442 443 444 static void 445 hda_create_mux_control(hda_multi *multi, uint32 *index, int32 parent, 446 hda_widget& widget) 447 { 448 uint32 i = *index, parent2; 449 hda_multi_mixer_control control; 450 hda_audio_group *audioGroup = multi->group; 451 452 control.nid = widget.node_id; 453 control.input = true; 454 control.mute = 0; 455 control.gain = 0; 456 control.mix_control.master = MULTI_CONTROL_MASTERID; 457 control.mix_control.parent = parent; 458 control.mix_control.id = MULTI_CONTROL_FIRSTID + i; 459 control.mix_control.flags = B_MULTI_MIX_MUX; 460 control.mix_control.string = S_null; 461 control.type = widget.type == WT_AUDIO_MIXER 462 ? B_MIX_MUX_MIXER : B_MIX_MUX_SELECTOR; 463 multi->controls[i] = control; 464 strcpy(multi->controls[i].mix_control.name, ""); 465 i++; 466 parent2 = control.mix_control.id; 467 468 for (uint32 j = 0; j < widget.num_inputs; j++) { 469 hda_widget *input = 470 hda_audio_group_get_widget(audioGroup, widget.inputs[j]); 471 if (input->type != WT_PIN_COMPLEX) 472 continue; 473 control.nid = widget.node_id; 474 control.input = true; 475 control.mix_control.id = MULTI_CONTROL_FIRSTID + i; 476 control.mix_control.flags = B_MULTI_MIX_MUX_VALUE; 477 control.mix_control.parent = parent2; 478 control.mix_control.string = S_null; 479 multi->controls[i] = control; 480 hda_find_multi_custom_string(*input, 481 multi->controls[i].mix_control.name, 482 sizeof(multi->controls[i].mix_control.name)); 483 i++; 484 } 485 486 *index = i; 487 } 488 489 490 static void 491 hda_create_control_for_complex(hda_multi* multi, uint32* index, uint32 parent, 492 hda_widget& widget, bool& gain, bool& mute) 493 { 494 hda_audio_group* audioGroup = multi->group; 495 496 switch (widget.type) { 497 case WT_AUDIO_OUTPUT: 498 case WT_AUDIO_MIXER: 499 case WT_AUDIO_SELECTOR: 500 case WT_PIN_COMPLEX: 501 break; 502 default: 503 return; 504 } 505 506 if ((widget.flags & WIDGET_FLAG_WIDGET_PATH) != 0) 507 return; 508 509 TRACE(" create widget nid %" B_PRIu32 "\n", widget.node_id); 510 hda_create_channel_control(multi, index, parent, 0, 511 widget, false, widget.capabilities.output_amplifier, 0, gain, mute); 512 513 if (!gain && !mute) { 514 widget.flags |= WIDGET_FLAG_WIDGET_PATH; 515 return; 516 } 517 518 if (widget.type == WT_AUDIO_MIXER) { 519 hda_create_channel_control(multi, index, parent, 0, 520 widget, true, widget.capabilities.input_amplifier, 0, gain, mute); 521 if (!gain && !mute) { 522 widget.flags |= WIDGET_FLAG_WIDGET_PATH; 523 return; 524 } 525 } 526 527 if (widget.type != WT_AUDIO_OUTPUT && widget.num_inputs > 0) { 528 hda_widget& child = *hda_audio_group_get_widget(audioGroup, 529 widget.inputs[widget.active_input]); 530 hda_create_control_for_complex(multi, index, parent, child, gain, mute); 531 } 532 533 widget.flags |= WIDGET_FLAG_WIDGET_PATH; 534 } 535 536 537 static status_t 538 hda_create_controls_list(hda_multi* multi) 539 { 540 uint32 index = 0; 541 hda_audio_group* audioGroup = multi->group; 542 543 uint32 parent = hda_create_group_control(multi, &index, 0, S_OUTPUT, NULL); 544 uint32 parent2; 545 546 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 547 hda_widget& complex = audioGroup->widgets[i]; 548 char name[48]; 549 550 if (complex.type != WT_PIN_COMPLEX) 551 continue; 552 if (!PIN_CAP_IS_OUTPUT(complex.d.pin.capabilities)) 553 continue; 554 if ((complex.flags & WIDGET_FLAG_OUTPUT_PATH) == 0) 555 continue; 556 557 TRACE("create complex nid %" B_PRIu32 "\n", complex.node_id); 558 hda_find_multi_custom_string(complex, name, sizeof(name)); 559 parent2 = hda_create_group_control(multi, &index, parent, S_null, name); 560 bool gain = true, mute = true; 561 562 hda_create_control_for_complex(multi, &index, parent2, complex, gain, 563 mute); 564 } 565 566 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 567 hda_widget& widget = audioGroup->widgets[i]; 568 569 if (widget.type != WT_AUDIO_MIXER) 570 continue; 571 if ((widget.flags & WIDGET_FLAG_WIDGET_PATH) != 0) 572 continue; 573 574 TRACE("create widget nid %" B_PRIu32 "\n", widget.node_id); 575 576 if (AMP_CAP_NUM_STEPS(widget.capabilities.input_amplifier) >= 1) { 577 for (uint32 j = 0; j < widget.num_inputs; j++) { 578 hda_widget* complex = hda_audio_group_get_widget(audioGroup, 579 widget.inputs[j]); 580 char name[48]; 581 if (complex->type != WT_PIN_COMPLEX) 582 continue; 583 if (!PIN_CAP_IS_INPUT(complex->d.pin.capabilities)) 584 continue; 585 if ((complex->flags & WIDGET_FLAG_OUTPUT_PATH) != 0) 586 continue; 587 TRACE(" create widget input nid %" B_PRIu32 "\n", 588 widget.inputs[j]); 589 hda_find_multi_custom_string(*complex, name, sizeof(name)); 590 parent2 = hda_create_group_control(multi, &index, 591 parent, S_null, name); 592 bool gain = true, mute = true; 593 hda_create_channel_control(multi, &index, parent2, 0, widget, 594 true, widget.capabilities.input_amplifier, j, gain, mute); 595 } 596 } 597 598 widget.flags |= WIDGET_FLAG_WIDGET_PATH; 599 } 600 601 parent = hda_create_group_control(multi, &index, 0, S_INPUT, NULL); 602 603 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 604 hda_widget& widget = audioGroup->widgets[i]; 605 606 if (widget.type != WT_AUDIO_INPUT) 607 continue; 608 609 uint32 capabilities = widget.capabilities.input_amplifier; 610 if (AMP_CAP_NUM_STEPS(capabilities) < 1) 611 continue; 612 613 parent2 = hda_create_group_control(multi, &index, 614 parent, hda_find_multi_string(widget), "Input"); 615 bool gain = true, mute = true; 616 hda_create_channel_control(multi, &index, parent2, 0, 617 widget, true, capabilities, 0, gain, mute); 618 619 if (widget.num_inputs > 1) { 620 TRACE(" create mux for nid %" B_PRIu32 "\n", widget.node_id); 621 hda_create_mux_control(multi, &index, parent2, widget); 622 continue; 623 } 624 625 hda_widget *mixer = hda_audio_group_get_widget(audioGroup, 626 widget.inputs[0]); 627 if (mixer->type != WT_AUDIO_MIXER && mixer->type != WT_AUDIO_SELECTOR) 628 continue; 629 TRACE(" create mixer nid %" B_PRIu32 "\n", mixer->node_id); 630 hda_create_mux_control(multi, &index, parent2, *mixer); 631 } 632 633 multi->control_count = index; 634 TRACE("multi->control_count %" B_PRIu32 "\n", multi->control_count); 635 return B_OK; 636 } 637 638 639 static status_t 640 list_mix_controls(hda_audio_group* audioGroup, multi_mix_control_info* mmci) 641 { 642 multi_mix_control *mmc = mmci->controls; 643 if (mmci->control_count < 24) 644 return B_ERROR; 645 646 if (hda_create_controls_list(audioGroup->multi) < B_OK) 647 return B_ERROR; 648 for (uint32 i = 0; i < audioGroup->multi->control_count; i++) { 649 mmc[i] = audioGroup->multi->controls[i].mix_control; 650 } 651 652 mmci->control_count = audioGroup->multi->control_count; 653 return B_OK; 654 } 655 656 657 static status_t 658 list_mix_connections(hda_audio_group* audioGroup, 659 multi_mix_connection_info* data) 660 { 661 data->actual_count = 0; 662 return B_OK; 663 } 664 665 666 static status_t 667 list_mix_channels(hda_audio_group* audioGroup, multi_mix_channel_info *data) 668 { 669 return B_OK; 670 } 671 672 673 static void 674 get_control_gain_mute(hda_audio_group* audioGroup, 675 hda_multi_mixer_control *control, uint32 *resp) 676 { 677 uint32 verb[2]; 678 verb[0] = MAKE_VERB(audioGroup->codec->addr, 679 control->nid, 680 VID_GET_AMPLIFIER_GAIN_MUTE, 681 (control->input ? AMP_GET_INPUT : AMP_GET_OUTPUT) 682 | AMP_GET_LEFT_CHANNEL | AMP_GET_INPUT_INDEX(control->index)); 683 verb[1] = MAKE_VERB(audioGroup->codec->addr, 684 control->nid, 685 VID_GET_AMPLIFIER_GAIN_MUTE, 686 (control->input ? AMP_GET_INPUT : AMP_GET_OUTPUT) 687 | AMP_GET_RIGHT_CHANNEL | AMP_GET_INPUT_INDEX(control->index)); 688 hda_send_verbs(audioGroup->codec, verb, resp, 2); 689 } 690 691 692 static status_t 693 get_mix(hda_audio_group* audioGroup, multi_mix_value_info * mmvi) 694 { 695 int32 id; 696 hda_multi_mixer_control *control = NULL; 697 for (int32 i = 0; i < mmvi->item_count; i++) { 698 id = mmvi->values[i].id - MULTI_CONTROL_FIRSTID; 699 if (id < 0 || id >= (int32)audioGroup->multi->control_count) { 700 dprintf("hda: get_mix : invalid control id requested : %" B_PRId32 701 "\n", id); 702 continue; 703 } 704 control = &audioGroup->multi->controls[id]; 705 706 if ((control->mix_control.flags 707 & (B_MULTI_MIX_GAIN | B_MULTI_MIX_ENABLE)) != 0) { 708 uint32 resp[2]; 709 get_control_gain_mute(audioGroup, control, resp); 710 if ((control->mix_control.flags & B_MULTI_MIX_ENABLE) != 0) { 711 mmvi->values[i].enable = (resp[0] & AMP_MUTE) != 0; 712 TRACE("get_mix: %" B_PRId32 " mute: %d\n", control->nid, 713 mmvi->values[i].enable); 714 } else if ((control->mix_control.flags & B_MULTI_MIX_GAIN) != 0) { 715 uint32 value; 716 if (control->mix_control.master == MULTI_CONTROL_MASTERID) 717 value = resp[0] & AMP_GAIN_MASK; 718 else 719 value = resp[1] & AMP_GAIN_MASK; 720 mmvi->values[i].gain = (0.0 + value - AMP_CAP_OFFSET(control->capabilities)) 721 * AMP_CAP_STEP_SIZE(control->capabilities); 722 TRACE("get_mix: %" B_PRId32 " gain: %f (%" B_PRIu32 ")\n", 723 control->nid, mmvi->values[i].gain, value); 724 } 725 726 } else if ((control->mix_control.flags & B_MIX_MUX_MIXER) != 0) { 727 hda_widget* mixer = hda_audio_group_get_widget(audioGroup, 728 control->nid); 729 mmvi->values[i].mux = 0; 730 for (uint32 j = 0; j < mixer->num_inputs; j++) { 731 uint32 verb = MAKE_VERB(audioGroup->codec->addr, 732 control->nid, VID_GET_AMPLIFIER_GAIN_MUTE, AMP_GET_INPUT 733 | AMP_GET_LEFT_CHANNEL | AMP_GET_INPUT_INDEX(j)); 734 uint32 resp; 735 if (hda_send_verbs(audioGroup->codec, &verb, &resp, 1) == B_OK) { 736 TRACE("get_mix: %" B_PRId32 " mixer %" B_PRIu32 737 " is %smute\n", control->nid, 738 j, (resp & AMP_MUTE) != 0 ? "" : "un"); 739 if ((resp & AMP_MUTE) == 0) { 740 mmvi->values[i].mux = j; 741 #ifndef TRACE_MULTI_AUDIO 742 break; 743 #endif 744 } 745 } 746 } 747 TRACE("get_mix: %" B_PRId32 " mixer: %" B_PRIu32 "\n", 748 control->nid, mmvi->values[i].mux); 749 } else if ((control->mix_control.flags & B_MIX_MUX_SELECTOR) != 0) { 750 uint32 verb = MAKE_VERB(audioGroup->codec->addr, control->nid, 751 VID_GET_CONNECTION_SELECT, 0); 752 uint32 resp; 753 if (hda_send_verbs(audioGroup->codec, &verb, &resp, 1) == B_OK) 754 mmvi->values[i].mux = resp & 0xff; 755 TRACE("get_mix: %" B_PRId32 " selector: %" B_PRIu32 "\n", 756 control->nid, mmvi->values[i].mux); 757 } 758 } 759 return B_OK; 760 } 761 762 763 static status_t 764 set_mix(hda_audio_group* audioGroup, multi_mix_value_info * mmvi) 765 { 766 int32 id; 767 hda_multi_mixer_control *control = NULL; 768 for (int32 i = 0; i < mmvi->item_count; i++) { 769 id = mmvi->values[i].id - MULTI_CONTROL_FIRSTID; 770 if (id < 0 || id >= (int32)audioGroup->multi->control_count) { 771 dprintf("set_mix : invalid control id requested : %" B_PRId32 "\n", 772 id); 773 continue; 774 } 775 control = &audioGroup->multi->controls[id]; 776 777 if ((control->mix_control.flags & B_MULTI_MIX_ENABLE) != 0) { 778 control->mute = (mmvi->values[i].enable ? AMP_MUTE : 0); 779 TRACE("set_mix: %" B_PRId32 " mute: %" B_PRIx32 "\n", control->nid, 780 control->mute); 781 uint32 resp[2]; 782 get_control_gain_mute(audioGroup, control, resp); 783 784 uint32 verb[2]; 785 verb[0] = MAKE_VERB(audioGroup->codec->addr, 786 control->nid, 787 VID_SET_AMPLIFIER_GAIN_MUTE, 788 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 789 | AMP_SET_LEFT_CHANNEL 790 | AMP_SET_INPUT_INDEX(control->index) 791 | control->mute 792 | (resp[0] & AMP_GAIN_MASK)); 793 TRACE("set_mix: sending verb to %" B_PRId32 ": %" B_PRIx32 " %" 794 B_PRIx32 " %x %lx\n", control->nid, 795 control->mute, resp[0] & AMP_GAIN_MASK, control->input, 796 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 797 | AMP_SET_LEFT_CHANNEL 798 | AMP_SET_INPUT_INDEX(control->index) 799 | control->mute 800 | (resp[0] & AMP_GAIN_MASK)); 801 verb[1] = MAKE_VERB(audioGroup->codec->addr, 802 control->nid, 803 VID_SET_AMPLIFIER_GAIN_MUTE, 804 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 805 | AMP_SET_RIGHT_CHANNEL 806 | AMP_SET_INPUT_INDEX(control->index) 807 | control->mute 808 | (resp[1] & AMP_GAIN_MASK)); 809 TRACE("set_mix: ctrl2 sending verb to %" B_PRId32 ": %" B_PRIx32 810 " %" B_PRIx32 " %x\n", control->nid, control->mute, 811 resp[1] & AMP_GAIN_MASK, control->input); 812 hda_send_verbs(audioGroup->codec, verb, NULL, 2); 813 } else if ((control->mix_control.flags & B_MULTI_MIX_GAIN) != 0) { 814 hda_multi_mixer_control *control2 = NULL; 815 if (i+1<mmvi->item_count) { 816 id = mmvi->values[i + 1].id - MULTI_CONTROL_FIRSTID; 817 if (id < 0 || id >= (int32)audioGroup->multi->control_count) { 818 dprintf("set_mix : invalid control id requested : %" 819 B_PRId32 "\n", id); 820 } else { 821 control2 = &audioGroup->multi->controls[id]; 822 if (control2->mix_control.master != control->mix_control.id) 823 control2 = NULL; 824 } 825 } 826 827 if (control->mix_control.master == MULTI_CONTROL_MASTERID) { 828 control->gain = (uint32)(mmvi->values[i].gain 829 / AMP_CAP_STEP_SIZE(control->capabilities) 830 + AMP_CAP_OFFSET(control->capabilities)); 831 } 832 833 if (control2 834 && control2->mix_control.master != MULTI_CONTROL_MASTERID) { 835 control2->gain = (uint32)(mmvi->values[i+1].gain 836 / AMP_CAP_STEP_SIZE(control2->capabilities) 837 + AMP_CAP_OFFSET(control2->capabilities)); 838 } 839 TRACE("set_mix: %" B_PRId32 " gain: %" B_PRIx32 " and %" B_PRId32 840 " gain: %" B_PRIx32 "\n", control->nid, control->gain, 841 control2->nid, control2->gain); 842 uint32 resp[2]; 843 get_control_gain_mute(audioGroup, control, resp); 844 control->mute = resp[0] & AMP_MUTE; 845 if (control2) 846 control2->mute = resp[1] & AMP_MUTE; 847 848 uint32 verb[2]; 849 verb[0] = MAKE_VERB(audioGroup->codec->addr, 850 control->nid, 851 VID_SET_AMPLIFIER_GAIN_MUTE, 852 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 853 | AMP_SET_LEFT_CHANNEL 854 | AMP_SET_INPUT_INDEX(control->index) 855 | (control->mute & AMP_MUTE) 856 | (control->gain & AMP_GAIN_MASK)); 857 TRACE("set_mix: sending verb to %" B_PRId32 ": %" B_PRIx32 " %" 858 B_PRIx32 " %x %lx\n", control->nid, 859 control->mute, control->gain, control->input, 860 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 861 | AMP_SET_LEFT_CHANNEL 862 | AMP_SET_INPUT_INDEX(control->index) 863 | (control->mute & AMP_MUTE) 864 | (control->gain & AMP_GAIN_MASK)); 865 if (control2) { 866 verb[1] = MAKE_VERB(audioGroup->codec->addr, 867 control2->nid, 868 VID_SET_AMPLIFIER_GAIN_MUTE, 869 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 870 | AMP_SET_RIGHT_CHANNEL 871 | AMP_SET_INPUT_INDEX(control->index) 872 | (control2->mute & AMP_MUTE) 873 | (control2->gain & AMP_GAIN_MASK)); 874 TRACE("set_mix: ctrl2 sending verb to %" B_PRId32 ": %" 875 B_PRIx32 " %" B_PRIx32 " %x\n", control2->nid, 876 control2->mute, control2->gain, control2->input); 877 } 878 hda_send_verbs(audioGroup->codec, verb, NULL, control2 ? 2 : 1); 879 880 if (control2) 881 i++; 882 } else if ((control->mix_control.flags & B_MIX_MUX_MIXER) != 0) { 883 TRACE("set_mix: %" B_PRId32 " mixer: %" B_PRIu32 "\n", 884 control->nid, mmvi->values[i].mux); 885 hda_widget *mixer = hda_audio_group_get_widget(audioGroup, 886 control->nid); 887 uint32 verb[mixer->num_inputs]; 888 for (uint32 j = 0; j < mixer->num_inputs; j++) { 889 verb[j] = MAKE_VERB(audioGroup->codec->addr, 890 control->nid, VID_SET_AMPLIFIER_GAIN_MUTE, AMP_SET_INPUT 891 | AMP_SET_LEFT_CHANNEL | AMP_SET_RIGHT_CHANNEL 892 | AMP_SET_INPUT_INDEX(j) 893 | ((mmvi->values[i].mux == j) ? 0 : AMP_MUTE)); 894 TRACE("set_mix: %" B_PRId32 " mixer %smuting %" B_PRIu32 " (%" 895 B_PRIu32 ")\n", control->nid, 896 (mmvi->values[i].mux == j) ? "un" : "", j, verb[j]); 897 } 898 if (hda_send_verbs(audioGroup->codec, verb, NULL, mixer->num_inputs) 899 != B_OK) 900 dprintf("hda: Setting mixer %" B_PRId32 " failed on widget %" 901 B_PRIu32 "!\n", mmvi->values[i].mux, control->nid); 902 } else if ((control->mix_control.flags & B_MIX_MUX_SELECTOR) != 0) { 903 uint32 verb = MAKE_VERB(audioGroup->codec->addr, control->nid, 904 VID_SET_CONNECTION_SELECT, mmvi->values[i].mux); 905 if (hda_send_verbs(audioGroup->codec, &verb, NULL, 1) != B_OK) { 906 dprintf("hda: Setting output selector %" B_PRId32 " failed on " 907 "widget %" B_PRIu32 "!\n", mmvi->values[i].mux, 908 control->nid); 909 } 910 TRACE("set_mix: %" B_PRId32 " selector: %" B_PRIu32 "\n", 911 control->nid, mmvi->values[i].mux); 912 } 913 } 914 return B_OK; 915 } 916 917 918 static uint32 919 default_buffer_length_for_rate(uint32 rate) 920 { 921 // keep the latency about the same as 2048 frames per buffer at 44100 Hz 922 switch (rate) { 923 case B_SR_8000: 924 return 512; 925 case B_SR_11025: 926 return 512; 927 case B_SR_16000: 928 return 1024; 929 case B_SR_22050: 930 return 1024; 931 case B_SR_32000: 932 return 2048; 933 case B_SR_44100: 934 return 2048; 935 case B_SR_48000: 936 return 2048; 937 case B_SR_88200: 938 return 4096; 939 case B_SR_96000: 940 return 6144; 941 case B_SR_176400: 942 return 8192; 943 case B_SR_192000: 944 return 10240; 945 case B_SR_384000: 946 return 16384; 947 } 948 return 2048; 949 }; 950 951 952 static status_t 953 get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data) 954 { 955 if (requested_settings.play_buffer_frames != 0) 956 data->request_playback_buffer_size = requested_settings.play_buffer_frames; 957 958 if (requested_settings.play_buffer_count != 0) 959 data->request_playback_buffers = requested_settings.play_buffer_count; 960 961 if (requested_settings.record_buffer_frames != 0) 962 data->request_record_buffer_size = requested_settings.record_buffer_frames; 963 964 if (requested_settings.record_buffer_count != 0) 965 data->request_record_buffers = requested_settings.record_buffer_count; 966 967 TRACE("playback: %" B_PRId32 " buffers, %" B_PRId32 " channels, %" B_PRIu32 968 " samples\n", data->request_playback_buffers, 969 data->request_playback_channels, data->request_playback_buffer_size); 970 TRACE("record: %" B_PRId32 " buffers, %" B_PRId32 " channels, %" B_PRIu32 971 " samples\n", data->request_record_buffers, 972 data->request_record_channels, data->request_record_buffer_size); 973 974 /* Determine what buffers we return given the request */ 975 976 data->return_playback_buffers = data->request_playback_buffers; 977 data->return_playback_channels = data->request_playback_channels; 978 data->return_playback_buffer_size = data->request_playback_buffer_size; 979 data->return_record_buffers = data->request_record_buffers; 980 data->return_record_channels = data->request_record_channels; 981 data->return_record_buffer_size = data->request_record_buffer_size; 982 983 /* Workaround for Haiku multi_audio API, since it prefers to let the 984 driver pick values, while the BeOS multi_audio actually gives the 985 user's defaults. */ 986 if (data->return_playback_buffers > STREAM_MAX_BUFFERS 987 || data->return_playback_buffers < STREAM_MIN_BUFFERS) 988 data->return_playback_buffers = STREAM_MIN_BUFFERS; 989 990 if (data->return_record_buffers > STREAM_MAX_BUFFERS 991 || data->return_record_buffers < STREAM_MIN_BUFFERS) 992 data->return_record_buffers = STREAM_MIN_BUFFERS; 993 994 if (data->return_playback_buffer_size == 0 995 && audioGroup->playback_stream != NULL) { 996 data->return_playback_buffer_size = default_buffer_length_for_rate( 997 audioGroup->playback_stream->sample_rate); 998 } 999 1000 if (data->return_record_buffer_size == 0 1001 && audioGroup->record_stream != NULL) { 1002 data->return_record_buffer_size = default_buffer_length_for_rate( 1003 audioGroup->record_stream->sample_rate); 1004 } 1005 1006 /* ... from here on, we can assume again that a reasonable request is 1007 being made */ 1008 1009 data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; 1010 1011 /* Copy the settings into the streams */ 1012 1013 if (audioGroup->playback_stream != NULL) { 1014 audioGroup->playback_stream->num_buffers = data->return_playback_buffers; 1015 audioGroup->playback_stream->num_channels = data->return_playback_channels; 1016 audioGroup->playback_stream->buffer_length 1017 = data->return_playback_buffer_size; 1018 1019 status_t status = hda_stream_setup_buffers(audioGroup, 1020 audioGroup->playback_stream, "Playback"); 1021 if (status != B_OK) { 1022 dprintf("hda: Error setting up playback buffers: %s\n", 1023 strerror(status)); 1024 return status; 1025 } 1026 } 1027 1028 if (audioGroup->record_stream != NULL) { 1029 audioGroup->record_stream->num_buffers = data->return_record_buffers; 1030 audioGroup->record_stream->num_channels = data->return_record_channels; 1031 audioGroup->record_stream->buffer_length 1032 = data->return_record_buffer_size; 1033 1034 status_t status = hda_stream_setup_buffers(audioGroup, 1035 audioGroup->record_stream, "Recording"); 1036 if (status != B_OK) { 1037 dprintf("hda: Error setting up recording buffers: %s\n", 1038 strerror(status)); 1039 return status; 1040 } 1041 } 1042 1043 /* Setup data structure for multi_audio API... */ 1044 1045 if (audioGroup->playback_stream != NULL) { 1046 uint32 playbackSampleSize = audioGroup->playback_stream->sample_size; 1047 1048 for (int32 i = 0; i < data->return_playback_buffers; i++) { 1049 struct buffer_desc descs[data->return_playback_channels]; 1050 for (int32 channelIndex = 0; 1051 channelIndex < data->return_playback_channels; channelIndex++) { 1052 descs[channelIndex].base = (char*)audioGroup->playback_stream->buffers[i] 1053 + playbackSampleSize * channelIndex; 1054 descs[channelIndex].stride = playbackSampleSize 1055 * data->return_playback_channels; 1056 } 1057 if (!IS_USER_ADDRESS(data->playback_buffers[i]) 1058 || user_memcpy(data->playback_buffers[i], descs, sizeof(descs)) 1059 < B_OK) { 1060 return B_BAD_ADDRESS; 1061 } 1062 } 1063 } 1064 1065 if (audioGroup->record_stream != NULL) { 1066 uint32 recordSampleSize = audioGroup->record_stream->sample_size; 1067 1068 for (int32 i = 0; i < data->return_record_buffers; i++) { 1069 struct buffer_desc descs[data->return_record_channels]; 1070 for (int32 channelIndex = 0; 1071 channelIndex < data->return_record_channels; channelIndex++) { 1072 descs[channelIndex].base = (char*)audioGroup->record_stream->buffers[i] 1073 + recordSampleSize * channelIndex; 1074 descs[channelIndex].stride = recordSampleSize 1075 * data->return_record_channels; 1076 } 1077 if (!IS_USER_ADDRESS(data->record_buffers[i]) 1078 || user_memcpy(data->record_buffers[i], descs, sizeof(descs)) 1079 < B_OK) { 1080 return B_BAD_ADDRESS; 1081 } 1082 } 1083 } 1084 1085 return B_OK; 1086 } 1087 1088 1089 /*! playback_buffer_cycle is the buffer we want to have played */ 1090 static status_t 1091 buffer_exchange(hda_audio_group* audioGroup, multi_buffer_info* data) 1092 { 1093 cpu_status status; 1094 status_t err; 1095 multi_buffer_info buffer_info; 1096 1097 if (audioGroup->playback_stream == NULL) 1098 return B_ERROR; 1099 1100 if (!audioGroup->playback_stream->running) { 1101 hda_stream_start(audioGroup->codec->controller, 1102 audioGroup->playback_stream); 1103 } 1104 if (audioGroup->record_stream && !audioGroup->record_stream->running) { 1105 hda_stream_start(audioGroup->codec->controller, 1106 audioGroup->record_stream); 1107 } 1108 1109 #ifdef __HAIKU__ 1110 if (user_memcpy(&buffer_info, data, sizeof(buffer_info)) < B_OK) 1111 return B_BAD_ADDRESS; 1112 #else 1113 memcpy(&buffer_info, data, sizeof(buffer_info)); 1114 #endif 1115 1116 /* do playback */ 1117 err = acquire_sem_etc(audioGroup->codec->controller->buffer_ready_sem, 1118 1, B_CAN_INTERRUPT, 0); 1119 if (err != B_OK) { 1120 ERROR("%s: Error waiting for playback buffer to finish (%s)!\n", __func__, 1121 strerror(err)); 1122 return err; 1123 } 1124 1125 status = disable_interrupts(); 1126 acquire_spinlock(&audioGroup->playback_stream->lock); 1127 1128 buffer_info.playback_buffer_cycle 1129 = (audioGroup->playback_stream->buffer_cycle) 1130 % audioGroup->playback_stream->num_buffers; 1131 buffer_info.played_real_time = audioGroup->playback_stream->real_time; 1132 buffer_info.played_frames_count = audioGroup->playback_stream->frames_count; 1133 1134 release_spinlock(&audioGroup->playback_stream->lock); 1135 1136 if (audioGroup->record_stream) { 1137 acquire_spinlock(&audioGroup->record_stream->lock); 1138 buffer_info.record_buffer_cycle 1139 = (audioGroup->record_stream->buffer_cycle - 1) 1140 % audioGroup->record_stream->num_buffers; 1141 buffer_info.recorded_real_time = audioGroup->record_stream->real_time; 1142 buffer_info.recorded_frames_count 1143 = audioGroup->record_stream->frames_count; 1144 release_spinlock(&audioGroup->record_stream->lock); 1145 } 1146 1147 restore_interrupts(status); 1148 1149 #ifdef __HAIKU__ 1150 if (user_memcpy(data, &buffer_info, sizeof(buffer_info)) < B_OK) 1151 return B_BAD_ADDRESS; 1152 #else 1153 memcpy(data, &buffer_info, sizeof(buffer_info)); 1154 #endif 1155 1156 #if 0 1157 static int debugBuffersExchanged = 0; 1158 1159 debugBuffersExchanged++; 1160 if ((debugBuffersExchanged % 100) == 1 && debugBuffersExchanged < 1111) 1161 dprintf("%s: %d buffers processed\n", __func__, debugBuffersExchanged); 1162 #endif 1163 return B_OK; 1164 } 1165 1166 1167 static status_t 1168 buffer_force_stop(hda_audio_group* audioGroup) 1169 { 1170 if (audioGroup->playback_stream != NULL) { 1171 hda_stream_stop(audioGroup->codec->controller, 1172 audioGroup->playback_stream); 1173 } 1174 if (audioGroup->record_stream != NULL) { 1175 hda_stream_stop(audioGroup->codec->controller, 1176 audioGroup->record_stream); 1177 } 1178 1179 return B_OK; 1180 } 1181 1182 1183 #define cookie_type hda_audio_group 1184 #include "../generic/multi.c" 1185 1186 1187 status_t 1188 multi_audio_control(void* cookie, uint32 op, void* arg, size_t len) 1189 { 1190 hda_codec* codec = (hda_codec*)cookie; 1191 hda_audio_group* audioGroup; 1192 1193 /* FIXME: We should simply pass the audioGroup into here... */ 1194 if (!codec || codec->num_audio_groups == 0) 1195 return ENODEV; 1196 1197 audioGroup = codec->audio_groups[0]; 1198 1199 return multi_audio_control_generic(audioGroup, op, arg, len); 1200 } 1201