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) != 0) { 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) == 0 455 && widget.num_inputs > 0) { 456 hda_widget& child = *hda_audio_group_get_widget(audioGroup, 457 widget.inputs[widget.active_input]); 458 hda_create_control_for_complex(multi, index, parent, child, gain, mute); 459 } 460 461 widget.flags |= WIDGET_FLAG_WIDGET_PATH; 462 } 463 464 465 static status_t 466 hda_create_controls_list(hda_multi* multi) 467 { 468 uint32 index = 0; 469 hda_audio_group* audioGroup = multi->group; 470 471 uint32 parent = hda_create_group_control(multi, &index, 0, S_OUTPUT, NULL); 472 uint32 parent2; 473 474 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 475 hda_widget& complex = audioGroup->widgets[i]; 476 char name[48]; 477 478 if (complex.type != WT_PIN_COMPLEX) 479 continue; 480 if (!PIN_CAP_IS_OUTPUT(complex.d.pin.capabilities)) 481 continue; 482 if ((complex.flags & WIDGET_FLAG_OUTPUT_PATH) == 0) 483 continue; 484 485 TRACE("create complex nid %lu\n", complex.node_id); 486 hda_find_multi_custom_string(complex, name, sizeof(name)); 487 parent2 = hda_create_group_control(multi, &index, parent, S_null, name); 488 bool gain = true, mute = true; 489 490 hda_create_control_for_complex(multi, &index, parent2, complex, gain, 491 mute); 492 } 493 494 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 495 hda_widget& widget = audioGroup->widgets[i]; 496 497 if (widget.type != WT_AUDIO_MIXER) 498 continue; 499 if ((widget.flags & WIDGET_FLAG_WIDGET_PATH) != 0) 500 continue; 501 502 TRACE("create widget nid %lu\n", widget.node_id); 503 504 if (AMP_CAP_NUM_STEPS(widget.capabilities.input_amplifier) >= 1) { 505 for (uint32 j = 0; j < widget.num_inputs; j++) { 506 hda_widget* complex = hda_audio_group_get_widget(audioGroup, 507 widget.inputs[j]); 508 char name[48]; 509 if (complex->type != WT_PIN_COMPLEX) 510 continue; 511 if (!PIN_CAP_IS_INPUT(complex->d.pin.capabilities)) 512 continue; 513 if ((complex->flags & WIDGET_FLAG_OUTPUT_PATH) != 0) 514 continue; 515 TRACE(" create widget input nid %lu\n", widget.inputs[j]); 516 hda_find_multi_custom_string(*complex, name, sizeof(name)); 517 parent2 = hda_create_group_control(multi, &index, 518 parent, S_null, name); 519 bool gain = true, mute = true; 520 hda_create_channel_control(multi, &index, parent2, 0, widget, 521 true, widget.capabilities.input_amplifier, j, gain, mute); 522 } 523 } 524 525 widget.flags |= WIDGET_FLAG_WIDGET_PATH; 526 } 527 528 parent = hda_create_group_control(multi, &index, 0, S_INPUT, NULL); 529 530 for (uint32 i = 0; i < audioGroup->widget_count; i++) { 531 hda_widget& widget = audioGroup->widgets[i]; 532 533 if (widget.type != WT_AUDIO_INPUT) 534 continue; 535 536 uint32 capabilities = widget.capabilities.input_amplifier; 537 if (AMP_CAP_NUM_STEPS(capabilities) < 1) 538 continue; 539 540 parent2 = hda_create_group_control(multi, &index, 541 parent, hda_find_multi_string(widget), "Input"); 542 bool gain = true, mute = true; 543 hda_create_channel_control(multi, &index, parent2, 0, 544 widget, true, capabilities, 0, gain, mute); 545 546 hda_widget *mixer = hda_audio_group_get_widget(audioGroup, 547 widget.inputs[0]); 548 if (mixer->type != WT_AUDIO_MIXER && mixer->type != WT_AUDIO_SELECTOR) 549 continue; 550 TRACE(" create mixer nid %lu\n", mixer->node_id); 551 hda_create_mux_control(multi, &index, parent2, *mixer); 552 } 553 554 multi->control_count = index; 555 TRACE("multi->control_count %lu\n", multi->control_count); 556 return B_OK; 557 } 558 559 560 static status_t 561 list_mix_controls(hda_audio_group* audioGroup, multi_mix_control_info* mmci) 562 { 563 multi_mix_control *mmc = mmci->controls; 564 if (mmci->control_count < 24) 565 return B_ERROR; 566 567 if (hda_create_controls_list(audioGroup->multi) < B_OK) 568 return B_ERROR; 569 for (uint32 i = 0; i < audioGroup->multi->control_count; i++) { 570 mmc[i] = audioGroup->multi->controls[i].mix_control; 571 } 572 573 mmci->control_count = audioGroup->multi->control_count; 574 return B_OK; 575 } 576 577 578 static status_t 579 list_mix_connections(hda_audio_group* audioGroup, 580 multi_mix_connection_info* data) 581 { 582 data->actual_count = 0; 583 return B_OK; 584 } 585 586 587 static status_t 588 list_mix_channels(hda_audio_group* audioGroup, multi_mix_channel_info *data) 589 { 590 return B_OK; 591 } 592 593 594 static void 595 get_control_gain_mute(hda_audio_group* audioGroup, 596 hda_multi_mixer_control *control, uint32 *resp) 597 { 598 uint32 verb[2]; 599 verb[0] = MAKE_VERB(audioGroup->codec->addr, 600 control->nid, 601 VID_GET_AMPLIFIER_GAIN_MUTE, 602 (control->input ? AMP_GET_INPUT : AMP_GET_OUTPUT) 603 | AMP_GET_LEFT_CHANNEL | AMP_GET_INPUT_INDEX(control->index)); 604 verb[1] = 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_RIGHT_CHANNEL | AMP_GET_INPUT_INDEX(control->index)); 609 hda_send_verbs(audioGroup->codec, verb, resp, 2); 610 } 611 612 613 static status_t 614 get_mix(hda_audio_group* audioGroup, multi_mix_value_info * mmvi) 615 { 616 uint32 id; 617 hda_multi_mixer_control *control = NULL; 618 for (int32 i = 0; i < mmvi->item_count; i++) { 619 id = mmvi->values[i].id - MULTI_CONTROL_FIRSTID; 620 if (id < 0 || id >= audioGroup->multi->control_count) { 621 dprintf("hda: get_mix : invalid control id requested : %li\n", id); 622 continue; 623 } 624 control = &audioGroup->multi->controls[id]; 625 626 if ((control->mix_control.flags 627 & (B_MULTI_MIX_GAIN | B_MULTI_MIX_ENABLE)) != 0) { 628 uint32 resp[2]; 629 get_control_gain_mute(audioGroup, control, resp); 630 if ((control->mix_control.flags & B_MULTI_MIX_ENABLE) != 0) { 631 mmvi->values[i].enable = (resp[0] & AMP_MUTE) != 0; 632 TRACE("get_mix: %ld mute: %d\n", control->nid, 633 mmvi->values[i].enable); 634 } else if ((control->mix_control.flags & B_MULTI_MIX_GAIN) != 0) { 635 uint32 value; 636 if (control->mix_control.master == MULTI_CONTROL_MASTERID) 637 value = resp[0] & AMP_GAIN_MASK; 638 else 639 value = resp[1] & AMP_GAIN_MASK; 640 mmvi->values[i].gain = (0.0 + value - AMP_CAP_OFFSET(control->capabilities)) 641 * AMP_CAP_STEP_SIZE(control->capabilities); 642 TRACE("get_mix: %ld gain: %f (%ld)\n", control->nid, mmvi->values[i].gain, value); 643 } 644 645 } else if ((control->mix_control.flags & B_MIX_MUX_MIXER) != 0) { 646 hda_widget* mixer = hda_audio_group_get_widget(audioGroup, 647 control->nid); 648 mmvi->values[i].mux = 0; 649 for (uint32 j = 0; j < mixer->num_inputs; j++) { 650 uint32 verb = MAKE_VERB(audioGroup->codec->addr, 651 control->nid, VID_GET_AMPLIFIER_GAIN_MUTE, AMP_GET_INPUT 652 | AMP_GET_LEFT_CHANNEL | AMP_GET_INPUT_INDEX(j)); 653 uint32 resp; 654 if (hda_send_verbs(audioGroup->codec, &verb, &resp, 1) == B_OK) { 655 TRACE("get_mix: %ld mixer %ld is %smute\n", control->nid, 656 j, (resp & AMP_MUTE) != 0 ? "" : "un"); 657 if ((resp & AMP_MUTE) == 0) { 658 mmvi->values[i].mux = j; 659 #ifndef TRACE_MULTI_AUDIO 660 break; 661 #endif 662 } 663 } 664 } 665 TRACE("get_mix: %ld mixer: %ld\n", control->nid, 666 mmvi->values[i].mux); 667 } else if ((control->mix_control.flags & B_MIX_MUX_SELECTOR) != 0) { 668 uint32 verb = MAKE_VERB(audioGroup->codec->addr, control->nid, 669 VID_GET_CONNECTION_SELECT, 0); 670 uint32 resp; 671 if (hda_send_verbs(audioGroup->codec, &verb, &resp, 1) == B_OK) 672 mmvi->values[i].mux = resp & 0xff; 673 TRACE("get_mix: %ld selector: %ld\n", control->nid, 674 mmvi->values[i].mux); 675 } 676 } 677 return B_OK; 678 } 679 680 681 static status_t 682 set_mix(hda_audio_group* audioGroup, multi_mix_value_info * mmvi) 683 { 684 uint32 id; 685 hda_multi_mixer_control *control = NULL; 686 for (int32 i = 0; i < mmvi->item_count; i++) { 687 id = mmvi->values[i].id - MULTI_CONTROL_FIRSTID; 688 if (id < 0 || id >= audioGroup->multi->control_count) { 689 dprintf("set_mix : invalid control id requested : %li\n", id); 690 continue; 691 } 692 control = &audioGroup->multi->controls[id]; 693 694 if ((control->mix_control.flags & B_MULTI_MIX_ENABLE) != 0) { 695 control->mute = (mmvi->values[i].enable ? AMP_MUTE : 0); 696 TRACE("set_mix: %ld mute: %lx\n", control->nid, control->mute); 697 uint32 resp[2]; 698 get_control_gain_mute(audioGroup, control, resp); 699 700 uint32 verb[2]; 701 verb[0] = MAKE_VERB(audioGroup->codec->addr, 702 control->nid, 703 VID_SET_AMPLIFIER_GAIN_MUTE, 704 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 705 | AMP_SET_LEFT_CHANNEL 706 | AMP_SET_INPUT_INDEX(control->index) 707 | control->mute 708 | (resp[0] & AMP_GAIN_MASK)); 709 TRACE("set_mix: sending verb to %ld: %lx %lx %x %lx\n", control->nid, 710 control->mute, resp[0] & AMP_GAIN_MASK, control->input, 711 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 712 | AMP_SET_LEFT_CHANNEL 713 | AMP_SET_INPUT_INDEX(control->index) 714 | control->mute 715 | (resp[0] & AMP_GAIN_MASK)); 716 verb[1] = MAKE_VERB(audioGroup->codec->addr, 717 control->nid, 718 VID_SET_AMPLIFIER_GAIN_MUTE, 719 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 720 | AMP_SET_RIGHT_CHANNEL 721 | AMP_SET_INPUT_INDEX(control->index) 722 | control->mute 723 | (resp[1] & AMP_GAIN_MASK)); 724 TRACE("set_mix: ctrl2 sending verb to %ld: %lx %lx %x\n", control->nid, 725 control->mute, resp[1] & AMP_GAIN_MASK, control->input); 726 hda_send_verbs(audioGroup->codec, verb, NULL, 2); 727 } else if ((control->mix_control.flags & B_MULTI_MIX_GAIN) != 0) { 728 hda_multi_mixer_control *control2 = NULL; 729 if (i+1<mmvi->item_count) { 730 id = mmvi->values[i + 1].id - MULTI_CONTROL_FIRSTID; 731 if (id < 0 || id >= audioGroup->multi->control_count) { 732 dprintf("set_mix : invalid control id requested : %li\n", id); 733 } else { 734 control2 = &audioGroup->multi->controls[id]; 735 if (control2->mix_control.master != control->mix_control.id) 736 control2 = NULL; 737 } 738 } 739 740 if (control->mix_control.master == MULTI_CONTROL_MASTERID) { 741 control->gain = (uint32)(mmvi->values[i].gain 742 / AMP_CAP_STEP_SIZE(control->capabilities) 743 + AMP_CAP_OFFSET(control->capabilities)); 744 } 745 746 if (control2 747 && control2->mix_control.master != MULTI_CONTROL_MASTERID) { 748 control2->gain = (uint32)(mmvi->values[i+1].gain 749 / AMP_CAP_STEP_SIZE(control2->capabilities) 750 + AMP_CAP_OFFSET(control2->capabilities)); 751 } 752 TRACE("set_mix: %ld gain: %lx and %ld gain: %lx\n", 753 control->nid, control->gain, control2->nid, control2->gain); 754 uint32 resp[2]; 755 get_control_gain_mute(audioGroup, control, resp); 756 control->mute = resp[0] & AMP_MUTE; 757 if (control2) 758 control2->mute = resp[1] & AMP_MUTE; 759 760 uint32 verb[2]; 761 verb[0] = MAKE_VERB(audioGroup->codec->addr, 762 control->nid, 763 VID_SET_AMPLIFIER_GAIN_MUTE, 764 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 765 | AMP_SET_LEFT_CHANNEL 766 | AMP_SET_INPUT_INDEX(control->index) 767 | (control->mute & AMP_MUTE) 768 | (control->gain & AMP_GAIN_MASK)); 769 TRACE("set_mix: sending verb to %ld: %lx %lx %x %lx\n", control->nid, 770 control->mute, control->gain, control->input, 771 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 772 | AMP_SET_LEFT_CHANNEL 773 | AMP_SET_INPUT_INDEX(control->index) 774 | (control->mute & AMP_MUTE) 775 | (control->gain & AMP_GAIN_MASK)); 776 if (control2) { 777 verb[1] = MAKE_VERB(audioGroup->codec->addr, 778 control2->nid, 779 VID_SET_AMPLIFIER_GAIN_MUTE, 780 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 781 | AMP_SET_RIGHT_CHANNEL 782 | AMP_SET_INPUT_INDEX(control->index) 783 | (control2->mute & AMP_MUTE) 784 | (control2->gain & AMP_GAIN_MASK)); 785 TRACE("set_mix: ctrl2 sending verb to %ld: %lx %lx %x\n", 786 control2->nid, control2->mute, control2->gain, 787 control2->input); 788 } 789 hda_send_verbs(audioGroup->codec, verb, NULL, control2 ? 2 : 1); 790 791 if (control2) 792 i++; 793 } else if ((control->mix_control.flags & B_MIX_MUX_MIXER) != 0) { 794 TRACE("set_mix: %ld mixer: %ld\n", control->nid, mmvi->values[i].mux); 795 hda_widget *mixer = hda_audio_group_get_widget(audioGroup, 796 control->nid); 797 uint32 verb[mixer->num_inputs]; 798 for (uint32 j = 0; j < mixer->num_inputs; j++) { 799 verb[j] = MAKE_VERB(audioGroup->codec->addr, 800 control->nid, VID_SET_AMPLIFIER_GAIN_MUTE, AMP_SET_INPUT 801 | AMP_SET_LEFT_CHANNEL | AMP_SET_RIGHT_CHANNEL 802 | AMP_SET_INPUT_INDEX(j) 803 | ((mmvi->values[i].mux == j) ? 0 : AMP_MUTE)); 804 TRACE("set_mix: %ld mixer %smuting %ld (%lx)\n", control->nid, 805 (mmvi->values[i].mux == j) ? "un" : "", j, verb[j]); 806 } 807 if (hda_send_verbs(audioGroup->codec, verb, NULL, mixer->num_inputs) 808 != B_OK) 809 dprintf("hda: Setting mixer %ld failed on widget %ld!\n", 810 mmvi->values[i].mux, control->nid); 811 } else if ((control->mix_control.flags & B_MIX_MUX_SELECTOR) != 0) { 812 uint32 verb = MAKE_VERB(audioGroup->codec->addr, control->nid, 813 VID_SET_CONNECTION_SELECT, mmvi->values[i].mux); 814 if (hda_send_verbs(audioGroup->codec, &verb, NULL, 1) != B_OK) { 815 dprintf("hda: Setting output selector %ld failed on widget " 816 "%ld!\n", mmvi->values[i].mux, control->nid); 817 } 818 TRACE("set_mix: %ld selector: %ld\n", control->nid, 819 mmvi->values[i].mux); 820 } 821 } 822 return B_OK; 823 } 824 825 826 static uint32 827 default_buffer_length_for_rate(uint32 rate) 828 { 829 // keep the latency about the same as 2048 frames per buffer at 44100 Hz 830 switch (rate) { 831 case B_SR_8000: 832 return 512; 833 case B_SR_11025: 834 return 512; 835 case B_SR_16000: 836 return 1024; 837 case B_SR_22050: 838 return 1024; 839 case B_SR_32000: 840 return 2048; 841 case B_SR_44100: 842 return 2048; 843 case B_SR_48000: 844 return 2048; 845 case B_SR_88200: 846 return 4096; 847 case B_SR_96000: 848 return 6144; 849 case B_SR_176400: 850 return 8192; 851 case B_SR_192000: 852 return 10240; 853 case B_SR_384000: 854 return 16384; 855 } 856 return 2048; 857 }; 858 859 860 static status_t 861 get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data) 862 { 863 TRACE("playback: %ld buffers, %ld channels, %ld samples\n", 864 data->request_playback_buffers, data->request_playback_channels, 865 data->request_playback_buffer_size); 866 TRACE("record: %ld buffers, %ld channels, %ld samples\n", 867 data->request_record_buffers, data->request_record_channels, 868 data->request_record_buffer_size); 869 870 /* Determine what buffers we return given the request */ 871 872 data->return_playback_buffers = data->request_playback_buffers; 873 data->return_playback_channels = data->request_playback_channels; 874 data->return_playback_buffer_size = data->request_playback_buffer_size; 875 data->return_record_buffers = data->request_record_buffers; 876 data->return_record_channels = data->request_record_channels; 877 data->return_record_buffer_size = data->request_record_buffer_size; 878 879 /* Workaround for Haiku multi_audio API, since it prefers to let the 880 driver pick values, while the BeOS multi_audio actually gives the 881 user's defaults. */ 882 if (data->return_playback_buffers > STREAM_MAX_BUFFERS 883 || data->return_playback_buffers < STREAM_MIN_BUFFERS) 884 data->return_playback_buffers = STREAM_MIN_BUFFERS; 885 886 if (data->return_record_buffers > STREAM_MAX_BUFFERS 887 || data->return_record_buffers < STREAM_MIN_BUFFERS) 888 data->return_record_buffers = STREAM_MIN_BUFFERS; 889 890 if (data->return_playback_buffer_size == 0) { 891 data->return_playback_buffer_size = default_buffer_length_for_rate( 892 audioGroup->playback_stream->sample_rate); 893 } 894 895 if (data->return_record_buffer_size == 0) { 896 data->return_record_buffer_size = default_buffer_length_for_rate( 897 audioGroup->record_stream->sample_rate); 898 } 899 900 /* ... from here on, we can assume again that a reasonable request is 901 being made */ 902 903 data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; 904 905 /* Copy the settings into the streams */ 906 907 if (audioGroup->playback_stream != NULL) { 908 audioGroup->playback_stream->num_buffers = data->return_playback_buffers; 909 audioGroup->playback_stream->num_channels = data->return_playback_channels; 910 audioGroup->playback_stream->buffer_length 911 = data->return_playback_buffer_size; 912 913 status_t status = hda_stream_setup_buffers(audioGroup, 914 audioGroup->playback_stream, "Playback"); 915 if (status != B_OK) { 916 dprintf("hda: Error setting up playback buffers: %s\n", 917 strerror(status)); 918 return status; 919 } 920 } 921 922 if (audioGroup->record_stream != NULL) { 923 audioGroup->record_stream->num_buffers = data->return_record_buffers; 924 audioGroup->record_stream->num_channels = data->return_record_channels; 925 audioGroup->record_stream->buffer_length 926 = data->return_record_buffer_size; 927 928 status_t status = hda_stream_setup_buffers(audioGroup, 929 audioGroup->record_stream, "Recording"); 930 if (status != B_OK) { 931 dprintf("hda: Error setting up recording buffers: %s\n", 932 strerror(status)); 933 return status; 934 } 935 } 936 937 /* Setup data structure for multi_audio API... */ 938 939 if (audioGroup->playback_stream != NULL) { 940 uint32 playbackSampleSize = audioGroup->playback_stream->sample_size; 941 942 for (int32 i = 0; i < data->return_playback_buffers; i++) { 943 for (int32 channelIndex = 0; 944 channelIndex < data->return_playback_channels; channelIndex++) { 945 data->playback_buffers[i][channelIndex].base 946 = (char*)audioGroup->playback_stream->buffers[i] 947 + playbackSampleSize * channelIndex; 948 data->playback_buffers[i][channelIndex].stride 949 = playbackSampleSize * data->return_playback_channels; 950 } 951 } 952 } 953 954 if (audioGroup->record_stream != NULL) { 955 uint32 recordSampleSize = audioGroup->record_stream->sample_size; 956 957 for (int32 i = 0; i < data->return_record_buffers; i++) { 958 for (int32 channelIndex = 0; 959 channelIndex < data->return_record_channels; channelIndex++) { 960 data->record_buffers[i][channelIndex].base 961 = (char*)audioGroup->record_stream->buffers[i] 962 + recordSampleSize * channelIndex; 963 data->record_buffers[i][channelIndex].stride 964 = recordSampleSize * data->return_record_channels; 965 } 966 } 967 } 968 969 return B_OK; 970 } 971 972 973 /*! playback_buffer_cycle is the buffer we want to have played */ 974 static status_t 975 buffer_exchange(hda_audio_group* audioGroup, multi_buffer_info* data) 976 { 977 cpu_status status; 978 status_t err; 979 multi_buffer_info buffer_info; 980 981 if (audioGroup->playback_stream == NULL) 982 return B_ERROR; 983 984 if (!audioGroup->playback_stream->running) { 985 hda_stream_start(audioGroup->codec->controller, 986 audioGroup->playback_stream); 987 } 988 if (audioGroup->record_stream && !audioGroup->record_stream->running) { 989 hda_stream_start(audioGroup->codec->controller, 990 audioGroup->record_stream); 991 } 992 993 #ifdef __HAIKU__ 994 if (user_memcpy(&buffer_info, data, sizeof(buffer_info)) < B_OK) 995 return B_BAD_ADDRESS; 996 #else 997 memcpy(&buffer_info, data, sizeof(buffer_info)); 998 #endif 999 1000 /* do playback */ 1001 err = acquire_sem_etc(audioGroup->codec->controller->buffer_ready_sem, 1002 1, B_CAN_INTERRUPT, 0); 1003 if (err != B_OK) { 1004 dprintf("%s: Error waiting for playback buffer to finish (%s)!\n", __func__, 1005 strerror(err)); 1006 return err; 1007 } 1008 1009 status = disable_interrupts(); 1010 acquire_spinlock(&audioGroup->playback_stream->lock); 1011 1012 buffer_info.playback_buffer_cycle 1013 = (audioGroup->playback_stream->buffer_cycle) 1014 % audioGroup->playback_stream->num_buffers; 1015 buffer_info.played_real_time = audioGroup->playback_stream->real_time; 1016 buffer_info.played_frames_count = audioGroup->playback_stream->frames_count; 1017 1018 release_spinlock(&audioGroup->playback_stream->lock); 1019 1020 if (audioGroup->record_stream) { 1021 acquire_spinlock(&audioGroup->record_stream->lock); 1022 buffer_info.record_buffer_cycle 1023 = (audioGroup->record_stream->buffer_cycle - 1) 1024 % audioGroup->record_stream->num_buffers; 1025 buffer_info.recorded_real_time = audioGroup->record_stream->real_time; 1026 buffer_info.recorded_frames_count 1027 = audioGroup->record_stream->frames_count; 1028 release_spinlock(&audioGroup->record_stream->lock); 1029 } 1030 1031 restore_interrupts(status); 1032 1033 #ifdef __HAIKU__ 1034 if (user_memcpy(data, &buffer_info, sizeof(buffer_info)) < B_OK) 1035 return B_BAD_ADDRESS; 1036 #else 1037 memcpy(data, &buffer_info, sizeof(buffer_info)); 1038 #endif 1039 1040 #if 0 1041 static int debugBuffersExchanged = 0; 1042 1043 debugBuffersExchanged++; 1044 if ((debugBuffersExchanged % 100) == 1 && debugBuffersExchanged < 1111) 1045 dprintf("%s: %d buffers processed\n", __func__, debugBuffersExchanged); 1046 #endif 1047 return B_OK; 1048 } 1049 1050 1051 static status_t 1052 buffer_force_stop(hda_audio_group* audioGroup) 1053 { 1054 if (audioGroup->playback_stream != NULL) { 1055 hda_stream_stop(audioGroup->codec->controller, 1056 audioGroup->playback_stream); 1057 } 1058 if (audioGroup->record_stream != NULL) { 1059 hda_stream_stop(audioGroup->codec->controller, 1060 audioGroup->record_stream); 1061 } 1062 1063 return B_OK; 1064 } 1065 1066 1067 status_t 1068 multi_audio_control(void* cookie, uint32 op, void* arg, size_t len) 1069 { 1070 hda_codec* codec = (hda_codec*)cookie; 1071 hda_audio_group* audioGroup; 1072 1073 /* FIXME: We should simply pass the audioGroup into here... */ 1074 if (!codec || codec->num_audio_groups == 0) 1075 return ENODEV; 1076 1077 audioGroup = codec->audio_groups[0]; 1078 1079 // TODO: make userland-safe when built for Haiku! 1080 1081 switch (op) { 1082 case B_MULTI_GET_DESCRIPTION: 1083 { 1084 #ifdef __HAIKU__ 1085 multi_description description; 1086 multi_channel_info channels[16]; 1087 multi_channel_info* originalChannels; 1088 1089 if (user_memcpy(&description, arg, sizeof(multi_description)) 1090 != B_OK) 1091 return B_BAD_ADDRESS; 1092 1093 originalChannels = description.channels; 1094 description.channels = channels; 1095 if (description.request_channel_count > 16) 1096 description.request_channel_count = 16; 1097 1098 status_t status = get_description(audioGroup, &description); 1099 if (status != B_OK) 1100 return status; 1101 1102 description.channels = originalChannels; 1103 if (user_memcpy(arg, &description, sizeof(multi_description)) 1104 != B_OK) 1105 return B_BAD_ADDRESS; 1106 return user_memcpy(originalChannels, channels, 1107 sizeof(multi_channel_info) * description.request_channel_count); 1108 #else 1109 return get_description(audioGroup, (multi_description*)arg); 1110 #endif 1111 } 1112 1113 case B_MULTI_GET_ENABLED_CHANNELS: 1114 return get_enabled_channels(audioGroup, (multi_channel_enable*)arg); 1115 case B_MULTI_SET_ENABLED_CHANNELS: 1116 return B_OK; 1117 1118 case B_MULTI_GET_GLOBAL_FORMAT: 1119 return get_global_format(audioGroup, (multi_format_info*)arg); 1120 case B_MULTI_SET_GLOBAL_FORMAT: 1121 return set_global_format(audioGroup, (multi_format_info*)arg); 1122 1123 case B_MULTI_LIST_MIX_CHANNELS: 1124 return list_mix_channels(audioGroup, (multi_mix_channel_info*)arg); 1125 case B_MULTI_LIST_MIX_CONTROLS: 1126 return list_mix_controls(audioGroup, (multi_mix_control_info*)arg); 1127 case B_MULTI_LIST_MIX_CONNECTIONS: 1128 return list_mix_connections(audioGroup, 1129 (multi_mix_connection_info*)arg); 1130 case B_MULTI_GET_MIX: 1131 return get_mix(audioGroup, (multi_mix_value_info *)arg); 1132 case B_MULTI_SET_MIX: 1133 return set_mix(audioGroup, (multi_mix_value_info *)arg); 1134 1135 case B_MULTI_GET_BUFFERS: 1136 return get_buffers(audioGroup, (multi_buffer_list*)arg); 1137 1138 case B_MULTI_BUFFER_EXCHANGE: 1139 return buffer_exchange(audioGroup, (multi_buffer_info*)arg); 1140 case B_MULTI_BUFFER_FORCE_STOP: 1141 return buffer_force_stop(audioGroup); 1142 1143 case B_MULTI_GET_EVENT_INFO: 1144 case B_MULTI_SET_EVENT_INFO: 1145 case B_MULTI_GET_EVENT: 1146 case B_MULTI_GET_CHANNEL_FORMATS: 1147 case B_MULTI_SET_CHANNEL_FORMATS: 1148 case B_MULTI_SET_BUFFERS: 1149 case B_MULTI_SET_START_TIME: 1150 return B_ERROR; 1151 } 1152 1153 return B_BAD_VALUE; 1154 } 1155