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