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