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