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; 465 uint32 i; 466 467 MMC = MMCI->controls; 468 if (MMCI->control_count < 24) 469 return B_ERROR; 470 471 if (hda_create_controls_list(audioGroup->multi) < B_OK) 472 return B_ERROR; 473 for (i=0; i<audioGroup->multi->control_count; i++) { 474 MMC[i] = audioGroup->multi->controls[i].mix_control; 475 } 476 477 MMCI->control_count = audioGroup->multi->control_count; 478 return B_OK; 479 } 480 481 482 static status_t 483 list_mix_connections(hda_audio_group* audioGroup, 484 multi_mix_connection_info* data) 485 { 486 data->actual_count = 0; 487 return B_OK; 488 } 489 490 491 static status_t 492 list_mix_channels(hda_audio_group* audioGroup, multi_mix_channel_info *data) 493 { 494 return B_OK; 495 } 496 497 498 static void 499 get_control_gain_mute(hda_audio_group* audioGroup, hda_multi_mixer_control *control, uint32 *resp) 500 { 501 uint32 verb[2]; 502 verb[0] = MAKE_VERB(audioGroup->codec->addr, 503 control->nid, 504 VID_GET_AMPLIFIER_GAIN_MUTE, 505 (control->input ? AMP_GET_INPUT : AMP_GET_OUTPUT) 506 | AMP_GET_LEFT_CHANNEL | AMP_GET_INPUT_INDEX(control->index)); 507 verb[1] = MAKE_VERB(audioGroup->codec->addr, 508 control->nid, 509 VID_GET_AMPLIFIER_GAIN_MUTE, 510 (control->input ? AMP_GET_INPUT : AMP_GET_OUTPUT) 511 | AMP_GET_RIGHT_CHANNEL | AMP_GET_INPUT_INDEX(control->index)); 512 hda_send_verbs(audioGroup->codec, verb, resp, 2); 513 } 514 515 516 static status_t 517 get_mix(hda_audio_group* audioGroup, multi_mix_value_info * MMVI) 518 { 519 int32 i; 520 uint32 id; 521 hda_multi_mixer_control *control = NULL; 522 for (i=0; i < MMVI->item_count; i++) { 523 id = MMVI->values[i].id - MULTI_CONTROL_FIRSTID; 524 if (id < 0 || id >= audioGroup->multi->control_count) { 525 dprintf("hda: get_mix : invalid control id requested : %li\n", id); 526 continue; 527 } 528 control = &audioGroup->multi->controls[id]; 529 530 if (control->mix_control.flags & (B_MULTI_MIX_GAIN | B_MULTI_MIX_ENABLE)) { 531 uint32 resp[2]; 532 get_control_gain_mute(audioGroup, control, resp); 533 if (control->mix_control.flags & B_MULTI_MIX_ENABLE) { 534 MMVI->values[i].enable = (resp[0] & AMP_MUTE) != 0; 535 TRACE("get_mix: %ld mute: %d\n", control->nid, MMVI->values[i].enable); 536 } else if (control->mix_control.flags & B_MULTI_MIX_GAIN) { 537 uint32 value; 538 if (control->mix_control.master == MULTI_CONTROL_MASTERID) 539 value = resp[0] & AMP_GAIN_MASK; 540 else 541 value = resp[1] & AMP_GAIN_MASK; 542 MMVI->values[i].gain = (value - AMP_CAP_OFFSET(control->capabilities)) 543 * AMP_CAP_STEP_SIZE(control->capabilities); 544 TRACE("get_mix: %ld gain: %f (%ld)\n", control->nid, MMVI->values[i].gain, value); 545 } 546 547 548 } 549 550 /*if (control->mix_control.flags & B_MULTI_MIX_MUX && control->get) { 551 float values[1]; 552 control->get(audioGroup, control, values); 553 MMVI->values[i].mux = (int32)values[0]; 554 }*/ 555 } 556 return B_OK; 557 } 558 559 560 static status_t 561 set_mix(hda_audio_group* audioGroup, multi_mix_value_info * MMVI) 562 { 563 int32 i; 564 uint32 id; 565 hda_multi_mixer_control *control = NULL; 566 for (i=0; i < MMVI->item_count; i++) { 567 id = MMVI->values[i].id - MULTI_CONTROL_FIRSTID; 568 if (id < 0 || id >= audioGroup->multi->control_count) { 569 dprintf("set_mix : invalid control id requested : %li\n", id); 570 continue; 571 } 572 control = &audioGroup->multi->controls[id]; 573 574 if (control->mix_control.flags & B_MULTI_MIX_ENABLE) { 575 control->mute = (MMVI->values[i].enable ? AMP_MUTE : 0); 576 TRACE("set_mix: %ld mute: %lx\n", control->nid, control->mute); 577 uint32 resp[2]; 578 get_control_gain_mute(audioGroup, control, resp); 579 580 uint32 verb[2]; 581 verb[0] = MAKE_VERB(audioGroup->codec->addr, 582 control->nid, 583 VID_SET_AMPLIFIER_GAIN_MUTE, 584 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 585 | AMP_SET_LEFT_CHANNEL 586 | AMP_SET_INPUT_INDEX(control->index) 587 | control->mute 588 | resp[0] & AMP_GAIN_MASK); 589 TRACE("set_mix: sending verb to %ld: %lx %lx %x %lx\n", control->nid, 590 control->mute, resp[0] & AMP_GAIN_MASK, control->input, 591 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 592 | AMP_SET_LEFT_CHANNEL 593 | AMP_SET_INPUT_INDEX(control->index) 594 | control->mute 595 | resp[0] & AMP_GAIN_MASK); 596 verb[1] = MAKE_VERB(audioGroup->codec->addr, 597 control->nid, 598 VID_SET_AMPLIFIER_GAIN_MUTE, 599 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 600 | AMP_SET_RIGHT_CHANNEL 601 | AMP_SET_INPUT_INDEX(control->index) 602 | control->mute 603 | resp[1] & AMP_GAIN_MASK); 604 TRACE("set_mix: ctrl2 sending verb to %ld: %lx %lx %x\n", control->nid, 605 control->mute, resp[1] & AMP_GAIN_MASK, control->input); 606 hda_send_verbs(audioGroup->codec, verb, NULL, 2); 607 } else if (control->mix_control.flags & B_MULTI_MIX_GAIN) { 608 hda_multi_mixer_control *control2 = NULL; 609 if (i+1<MMVI->item_count) { 610 id = MMVI->values[i + 1].id - MULTI_CONTROL_FIRSTID; 611 if (id < 0 || id >= audioGroup->multi->control_count) { 612 dprintf("set_mix : invalid control id requested : %li\n", id); 613 } else { 614 control2 = &audioGroup->multi->controls[id]; 615 if (control2->mix_control.master != control->mix_control.id) 616 control2 = NULL; 617 } 618 } 619 620 if (control->mix_control.master == MULTI_CONTROL_MASTERID) 621 control->gain = (uint32)(MMVI->values[i].gain / AMP_CAP_STEP_SIZE(control->capabilities) 622 + AMP_CAP_OFFSET(control->capabilities)); 623 624 if (control2 && control2->mix_control.master != MULTI_CONTROL_MASTERID) 625 control2->gain = (uint32)(MMVI->values[i+1].gain / AMP_CAP_STEP_SIZE(control2->capabilities) 626 + AMP_CAP_OFFSET(control2->capabilities)); 627 TRACE("set_mix: %ld gain: %lx and %ld gain: %lx\n", 628 control->nid, control->gain, control2->nid, control2->gain); 629 uint32 resp[2]; 630 get_control_gain_mute(audioGroup, control, resp); 631 control->mute = resp[0] & AMP_MUTE; 632 if (control2) 633 control2->mute = resp[1] & AMP_MUTE; 634 635 uint32 verb[2]; 636 verb[0] = MAKE_VERB(audioGroup->codec->addr, 637 control->nid, 638 VID_SET_AMPLIFIER_GAIN_MUTE, 639 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 640 | AMP_SET_LEFT_CHANNEL 641 | AMP_SET_INPUT_INDEX(control->index) 642 | (control->mute & AMP_MUTE) 643 | (control->gain & AMP_GAIN_MASK)); 644 TRACE("set_mix: sending verb to %ld: %lx %lx %x %lx\n", control->nid, 645 control->mute, control->gain, control->input, 646 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 647 | AMP_SET_LEFT_CHANNEL 648 | AMP_SET_INPUT_INDEX(control->index) 649 | (control->mute & AMP_MUTE) 650 | (control->gain & AMP_GAIN_MASK)); 651 if (control2) { 652 verb[1] = MAKE_VERB(audioGroup->codec->addr, 653 control2->nid, 654 VID_SET_AMPLIFIER_GAIN_MUTE, 655 (control->input ? AMP_SET_INPUT : AMP_SET_OUTPUT) 656 | AMP_SET_RIGHT_CHANNEL 657 | AMP_SET_INPUT_INDEX(control->index) 658 | (control2->mute & AMP_MUTE) 659 | (control2->gain & AMP_GAIN_MASK)); 660 TRACE("set_mix: ctrl2 sending verb to %ld: %lx %lx %x\n", control2->nid, 661 control2->mute, control2->gain, control2->input); 662 } 663 hda_send_verbs(audioGroup->codec, verb, NULL, control2 ? 2 : 1); 664 665 if (control2) 666 i++; 667 } 668 669 /*if (control->mix_control.flags & B_MULTI_MIX_MUX && control->set) { 670 float values[1]; 671 672 values[0] = (float)MMVI->values[i].mux; 673 control->set(card, control->channel, control->type, values); 674 }*/ 675 } 676 return B_OK; 677 } 678 679 680 static status_t 681 get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data) 682 { 683 TRACE("playback: %ld buffers, %ld channels, %ld samples\n", 684 data->request_playback_buffers, data->request_playback_channels, 685 data->request_playback_buffer_size); 686 TRACE("record: %ld buffers, %ld channels, %ld samples\n", 687 data->request_record_buffers, data->request_record_channels, 688 data->request_record_buffer_size); 689 690 /* Determine what buffers we return given the request */ 691 692 data->return_playback_buffers = data->request_playback_buffers; 693 data->return_playback_channels = data->request_playback_channels; 694 data->return_playback_buffer_size = data->request_playback_buffer_size; 695 data->return_record_buffers = data->request_record_buffers; 696 data->return_record_channels = data->request_record_channels; 697 data->return_record_buffer_size = data->request_record_buffer_size; 698 699 /* Workaround for Haiku multi_audio API, since it prefers to let the 700 driver pick values, while the BeOS multi_audio actually gives the 701 user's defaults. */ 702 if (data->return_playback_buffers > STREAM_MAX_BUFFERS 703 || data->return_playback_buffers < STREAM_MIN_BUFFERS) 704 data->return_playback_buffers = STREAM_MIN_BUFFERS; 705 706 if (data->return_record_buffers > STREAM_MAX_BUFFERS 707 || data->return_record_buffers < STREAM_MIN_BUFFERS) 708 data->return_record_buffers = STREAM_MIN_BUFFERS; 709 710 if (data->return_playback_buffer_size == 0) 711 data->return_playback_buffer_size = DEFAULT_FRAMES_PER_BUFFER; 712 713 if (data->return_record_buffer_size == 0) 714 data->return_record_buffer_size = DEFAULT_FRAMES_PER_BUFFER; 715 716 /* ... from here on, we can assume again that a reasonable request is 717 being made */ 718 719 data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; 720 721 /* Copy the settings into the streams */ 722 723 if (audioGroup->playback_stream != NULL) { 724 audioGroup->playback_stream->num_buffers = data->return_playback_buffers; 725 audioGroup->playback_stream->num_channels = data->return_playback_channels; 726 audioGroup->playback_stream->buffer_length 727 = data->return_playback_buffer_size; 728 729 status_t status = hda_stream_setup_buffers(audioGroup, 730 audioGroup->playback_stream, "Playback"); 731 if (status != B_OK) { 732 dprintf("hda: Error setting up playback buffers: %s\n", 733 strerror(status)); 734 return status; 735 } 736 } 737 738 if (audioGroup->record_stream != NULL) { 739 audioGroup->record_stream->num_buffers = data->return_record_buffers; 740 audioGroup->record_stream->num_channels = data->return_record_channels; 741 audioGroup->record_stream->buffer_length 742 = data->return_record_buffer_size; 743 744 status_t status = hda_stream_setup_buffers(audioGroup, 745 audioGroup->record_stream, "Recording"); 746 if (status != B_OK) { 747 dprintf("hda: Error setting up recording buffers: %s\n", 748 strerror(status)); 749 return status; 750 } 751 } 752 753 /* Setup data structure for multi_audio API... */ 754 755 if (audioGroup->playback_stream != NULL) { 756 uint32 playbackSampleSize = audioGroup->playback_stream->sample_size; 757 758 for (int32 i = 0; i < data->return_playback_buffers; i++) { 759 for (int32 channelIndex = 0; 760 channelIndex < data->return_playback_channels; channelIndex++) { 761 data->playback_buffers[i][channelIndex].base 762 = (char*)audioGroup->playback_stream->buffers[i] 763 + playbackSampleSize * channelIndex; 764 data->playback_buffers[i][channelIndex].stride 765 = playbackSampleSize * data->return_playback_channels; 766 } 767 } 768 } 769 770 if (audioGroup->record_stream != NULL) { 771 uint32 recordSampleSize = audioGroup->record_stream->sample_size; 772 773 for (int32 i = 0; i < data->return_record_buffers; i++) { 774 for (int32 channelIndex = 0; 775 channelIndex < data->return_record_channels; channelIndex++) { 776 data->record_buffers[i][channelIndex].base 777 = (char*)audioGroup->record_stream->buffers[i] 778 + recordSampleSize * channelIndex; 779 data->record_buffers[i][channelIndex].stride 780 = recordSampleSize * data->return_record_channels; 781 } 782 } 783 } 784 785 return B_OK; 786 } 787 788 789 /*! playback_buffer_cycle is the buffer we want to have played */ 790 static status_t 791 buffer_exchange(hda_audio_group* audioGroup, multi_buffer_info* data) 792 { 793 static int debug_buffers_exchanged = 0; 794 cpu_status status; 795 status_t err; 796 multi_buffer_info buffer_info; 797 798 if (audioGroup->playback_stream == NULL) 799 return B_ERROR; 800 801 if (!audioGroup->playback_stream->running) { 802 hda_stream_start(audioGroup->codec->controller, 803 audioGroup->playback_stream); 804 } 805 if (audioGroup->record_stream && !audioGroup->record_stream->running) { 806 hda_stream_start(audioGroup->codec->controller, 807 audioGroup->record_stream); 808 } 809 810 #ifdef __HAIKU__ 811 if (user_memcpy(&buffer_info, data, sizeof(buffer_info)) < B_OK) 812 return B_BAD_ADDRESS; 813 #else 814 memcpy(&buffer_info, data, sizeof(buffer_info)); 815 #endif 816 817 /* do playback */ 818 err = acquire_sem_etc(audioGroup->playback_stream->buffer_ready_sem, 819 1, B_CAN_INTERRUPT, 0); 820 if (err != B_OK) { 821 dprintf("%s: Error waiting for playback buffer to finish (%s)!\n", __func__, 822 strerror(err)); 823 return err; 824 } 825 826 status = disable_interrupts(); 827 acquire_spinlock(&audioGroup->playback_stream->lock); 828 829 buffer_info.playback_buffer_cycle = audioGroup->playback_stream->buffer_cycle; 830 buffer_info.played_real_time = audioGroup->playback_stream->real_time; 831 buffer_info.played_frames_count = audioGroup->playback_stream->frames_count; 832 833 release_spinlock(&audioGroup->playback_stream->lock); 834 835 if (audioGroup->record_stream) { 836 acquire_spinlock(&audioGroup->record_stream->lock); 837 buffer_info.record_buffer_cycle = audioGroup->record_stream->buffer_cycle; 838 buffer_info.recorded_real_time = audioGroup->record_stream->real_time; 839 buffer_info.recorded_frames_count = audioGroup->record_stream->frames_count; 840 release_spinlock(&audioGroup->record_stream->lock); 841 } 842 843 restore_interrupts(status); 844 845 #ifdef __HAIKU__ 846 if (user_memcpy(data, &buffer_info, sizeof(buffer_info)) < B_OK) 847 return B_BAD_ADDRESS; 848 #else 849 memcpy(data, &buffer_info, sizeof(buffer_info)); 850 #endif 851 852 debug_buffers_exchanged++; 853 if (((debug_buffers_exchanged % 100) == 1) && (debug_buffers_exchanged < 1111)) { 854 dprintf("%s: %d buffers processed\n", __func__, debug_buffers_exchanged); 855 } 856 857 return B_OK; 858 } 859 860 861 static status_t 862 buffer_force_stop(hda_audio_group* audioGroup) 863 { 864 if (audioGroup->playback_stream != NULL) { 865 hda_stream_stop(audioGroup->codec->controller, 866 audioGroup->playback_stream); 867 } 868 if (audioGroup->record_stream != NULL) { 869 hda_stream_stop(audioGroup->codec->controller, 870 audioGroup->record_stream); 871 } 872 //hda_stream_stop(audioGroup->codec->controller, audioGroup->record_stream); 873 874 return B_OK; 875 } 876 877 878 status_t 879 multi_audio_control(void* cookie, uint32 op, void* arg, size_t len) 880 { 881 hda_codec* codec = (hda_codec*)cookie; 882 hda_audio_group* audioGroup; 883 884 /* FIXME: We should simply pass the audioGroup into here... */ 885 if (!codec || codec->num_audio_groups == 0) 886 return ENODEV; 887 888 audioGroup = codec->audio_groups[0]; 889 890 // TODO: make userland-safe when built for Haiku! 891 892 switch (op) { 893 case B_MULTI_GET_DESCRIPTION: 894 { 895 #ifdef __HAIKU__ 896 multi_description description; 897 multi_channel_info channels[16]; 898 multi_channel_info* originalChannels; 899 900 if (user_memcpy(&description, arg, sizeof(multi_description)) 901 != B_OK) 902 return B_BAD_ADDRESS; 903 904 originalChannels = description.channels; 905 description.channels = channels; 906 if (description.request_channel_count > 16) 907 description.request_channel_count = 16; 908 909 status_t status = get_description(audioGroup, &description); 910 if (status != B_OK) 911 return status; 912 913 description.channels = originalChannels; 914 if (user_memcpy(arg, &description, sizeof(multi_description)) 915 != B_OK) 916 return B_BAD_ADDRESS; 917 return user_memcpy(originalChannels, channels, sizeof(multi_channel_info) 918 * description.request_channel_count); 919 #else 920 return get_description(audioGroup, (multi_description*)arg); 921 #endif 922 } 923 924 case B_MULTI_GET_ENABLED_CHANNELS: 925 return get_enabled_channels(audioGroup, (multi_channel_enable*)arg); 926 case B_MULTI_SET_ENABLED_CHANNELS: 927 return B_OK; 928 929 case B_MULTI_GET_GLOBAL_FORMAT: 930 return get_global_format(audioGroup, (multi_format_info*)arg); 931 case B_MULTI_SET_GLOBAL_FORMAT: 932 return set_global_format(audioGroup, (multi_format_info*)arg); 933 934 case B_MULTI_LIST_MIX_CHANNELS: 935 return list_mix_channels(audioGroup, (multi_mix_channel_info*)arg); 936 case B_MULTI_LIST_MIX_CONTROLS: 937 return list_mix_controls(audioGroup, (multi_mix_control_info*)arg); 938 case B_MULTI_LIST_MIX_CONNECTIONS: 939 return list_mix_connections(audioGroup, 940 (multi_mix_connection_info*)arg); 941 case B_MULTI_GET_MIX: 942 return get_mix(audioGroup, (multi_mix_value_info *)arg); 943 case B_MULTI_SET_MIX: 944 return set_mix(audioGroup, (multi_mix_value_info *)arg); 945 946 case B_MULTI_GET_BUFFERS: 947 return get_buffers(audioGroup, (multi_buffer_list*)arg); 948 949 case B_MULTI_BUFFER_EXCHANGE: 950 return buffer_exchange(audioGroup, (multi_buffer_info*)arg); 951 case B_MULTI_BUFFER_FORCE_STOP: 952 return buffer_force_stop(audioGroup); 953 954 case B_MULTI_GET_EVENT_INFO: 955 case B_MULTI_SET_EVENT_INFO: 956 case B_MULTI_GET_EVENT: 957 case B_MULTI_GET_CHANNEL_FORMATS: 958 case B_MULTI_SET_CHANNEL_FORMATS: 959 case B_MULTI_SET_BUFFERS: 960 case B_MULTI_SET_START_TIME: 961 return B_ERROR; 962 } 963 964 return B_BAD_VALUE; 965 } 966