1 /* 2 * Copyright 2009, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jérôme Duval (korli@users.berlios.de) 7 */ 8 9 10 #include "hmulti_audio.h" 11 #include "driver.h" 12 13 14 #ifdef TRACE 15 # undef TRACE 16 #endif 17 18 #define TRACE_MULTI_AUDIO 19 #ifdef TRACE_MULTI_AUDIO 20 # define TRACE(a...) dprintf("\33[34mgeode:\33[0m " a) 21 #else 22 # define TRACE(a...) ; 23 #endif 24 25 26 static multi_channel_info sChannels[] = { 27 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 28 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 29 { 2, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 30 { 3, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 31 { 4, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 32 B_CHANNEL_MINI_JACK_STEREO }, 33 { 5, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 34 B_CHANNEL_MINI_JACK_STEREO }, 35 { 6, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 36 B_CHANNEL_MINI_JACK_STEREO }, 37 { 7, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 38 B_CHANNEL_MINI_JACK_STEREO }, 39 }; 40 41 42 static int32 43 format2size(uint32 format) 44 { 45 switch (format) { 46 case B_FMT_8BIT_S: 47 case B_FMT_16BIT: 48 return 2; 49 50 case B_FMT_18BIT: 51 case B_FMT_20BIT: 52 case B_FMT_24BIT: 53 case B_FMT_32BIT: 54 case B_FMT_FLOAT: 55 return 4; 56 57 default: 58 return -1; 59 } 60 } 61 62 63 static status_t 64 get_description(geode_controller* controller, multi_description* data) 65 { 66 data->interface_version = B_CURRENT_INTERFACE_VERSION; 67 data->interface_minimum = B_CURRENT_INTERFACE_VERSION; 68 69 strcpy(data->friendly_name, "Geode"); 70 strcpy(data->vendor_info, "Haiku"); 71 72 int32 inChannels = 0; 73 if (controller->record_stream != NULL) 74 inChannels = 2; 75 76 int32 outChannels = 0; 77 if (controller->playback_stream != NULL) 78 outChannels = 2; 79 80 data->output_channel_count = outChannels; 81 data->output_bus_channel_count = outChannels; 82 data->input_channel_count = inChannels; 83 data->input_bus_channel_count = inChannels; 84 data->aux_bus_channel_count = 0; 85 86 dprintf("%s: request_channel_count: %" B_PRId32 "\n", __func__, data->request_channel_count); 87 88 if (data->request_channel_count >= (int)(sizeof(sChannels) 89 / sizeof(sChannels[0]))) { 90 memcpy(data->channels, &sChannels, sizeof(sChannels)); 91 } 92 93 /* determine output/input rates */ 94 data->output_rates = B_SR_48000; 95 data->input_rates = B_SR_48000; 96 97 /* force existance of 48kHz if variable rates are not supported */ 98 if (data->output_rates == 0) 99 data->output_rates = B_SR_48000; 100 if (data->input_rates == 0) 101 data->input_rates = B_SR_48000; 102 103 data->max_cvsr_rate = 0; 104 data->min_cvsr_rate = 0; 105 106 data->output_formats = B_FMT_16BIT; 107 data->input_formats = B_FMT_16BIT; 108 data->lock_sources = B_MULTI_LOCK_INTERNAL; 109 data->timecode_sources = 0; 110 data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD; 111 data->start_latency = 30000; 112 113 strcpy(data->control_panel, ""); 114 115 return B_OK; 116 } 117 118 119 static status_t 120 get_enabled_channels(geode_controller* controller, multi_channel_enable* data) 121 { 122 B_SET_CHANNEL(data->enable_bits, 0, true); 123 B_SET_CHANNEL(data->enable_bits, 1, true); 124 B_SET_CHANNEL(data->enable_bits, 2, true); 125 B_SET_CHANNEL(data->enable_bits, 3, true); 126 data->lock_source = B_MULTI_LOCK_INTERNAL; 127 128 return B_OK; 129 } 130 131 132 static status_t 133 get_global_format(geode_controller* controller, multi_format_info* data) 134 { 135 data->output_latency = 0; 136 data->input_latency = 0; 137 data->timecode_kind = 0; 138 139 if (controller->playback_stream != NULL) { 140 data->output.format = controller->playback_stream->sample_format; 141 data->output.rate = controller->playback_stream->sample_rate; 142 } else { 143 data->output.format = 0; 144 data->output.rate = 0; 145 } 146 147 if (controller->record_stream != NULL) { 148 data->input.format = controller->record_stream->sample_format; 149 data->input.rate = controller->record_stream->sample_format; 150 } else { 151 data->input.format = 0; 152 data->input.rate = 0; 153 } 154 155 return B_OK; 156 } 157 158 159 static status_t 160 set_global_format(geode_controller* controller, multi_format_info* data) 161 { 162 // TODO: it looks like we're not supposed to fail; fix this! 163 #if 0 164 if ((data->output.format & audioGroup->supported_formats) == 0) 165 || (data->output.rate & audioGroup->supported_rates) == 0) 166 return B_BAD_VALUE; 167 #endif 168 169 if (controller->playback_stream != NULL) { 170 controller->playback_stream->sample_format = data->output.format; 171 controller->playback_stream->sample_rate = data->output.rate; 172 controller->playback_stream->sample_size = format2size( 173 controller->playback_stream->sample_format); 174 } 175 176 if (controller->record_stream != NULL) { 177 controller->record_stream->sample_rate = data->input.rate; 178 controller->record_stream->sample_format = data->input.format; 179 controller->record_stream->sample_size = format2size( 180 controller->record_stream->sample_format); 181 } 182 183 return B_OK; 184 } 185 186 187 static void 188 geode_ac97_get_mix(geode_controller *controller, const void *cookie, int32 type, float *values) { 189 ac97_source_info *info = (ac97_source_info *)cookie; 190 uint16 value, mask; 191 float gain; 192 193 switch(type) { 194 case B_MIX_GAIN: 195 value = ac97_reg_cached_read(controller->ac97, info->reg); 196 //TRACE("B_MIX_GAIN value : %u\n", value); 197 if (info->type & B_MIX_STEREO) { 198 mask = ((1 << (info->bits + 1)) - 1) << 8; 199 gain = ((value & mask) >> 8) * info->granularity; 200 if (info->polarity == 1) 201 values[0] = info->max_gain - gain; 202 else 203 values[0] = gain - info->min_gain; 204 205 mask = ((1 << (info->bits + 1)) - 1); 206 gain = (value & mask) * info->granularity; 207 if (info->polarity == 1) 208 values[1] = info->max_gain - gain; 209 else 210 values[1] = gain - info->min_gain; 211 } else { 212 mask = ((1 << (info->bits + 1)) - 1); 213 gain = (value & mask) * info->granularity; 214 if (info->polarity == 1) 215 values[0] = info->max_gain - gain; 216 else 217 values[0] = gain - info->min_gain; 218 } 219 break; 220 case B_MIX_MUTE: 221 mask = ((1 << 1) - 1) << 15; 222 value = ac97_reg_cached_read(controller->ac97, info->reg); 223 //TRACE("B_MIX_MUTE value : %u\n", value); 224 value &= mask; 225 values[0] = ((value >> 15) == 1) ? 1.0 : 0.0; 226 break; 227 case B_MIX_MICBOOST: 228 mask = ((1 << 1) - 1) << 6; 229 value = ac97_reg_cached_read(controller->ac97, info->reg); 230 //TRACE("B_MIX_MICBOOST value : %u\n", value); 231 value &= mask; 232 values[0] = ((value >> 6) == 1) ? 1.0 : 0.0; 233 break; 234 case B_MIX_MUX: 235 mask = ((1 << 3) - 1); 236 value = ac97_reg_cached_read(controller->ac97, AC97_RECORD_SELECT); 237 value &= mask; 238 //TRACE("B_MIX_MUX value : %u\n", value); 239 values[0] = (float)value; 240 break; 241 } 242 } 243 244 245 static void 246 geode_ac97_set_mix(geode_controller *controller, const void *cookie, int32 type, float *values) { 247 ac97_source_info *info = (ac97_source_info *)cookie; 248 uint16 value, mask; 249 float gain; 250 251 switch(type) { 252 case B_MIX_GAIN: 253 value = ac97_reg_cached_read(controller->ac97, info->reg); 254 if (info->type & B_MIX_STEREO) { 255 mask = ((1 << (info->bits + 1)) - 1) << 8; 256 value &= ~mask; 257 258 if (info->polarity == 1) 259 gain = info->max_gain - values[0]; 260 else 261 gain = values[0] - info->min_gain; 262 value |= ((uint16)(gain / info->granularity) << 8) & mask; 263 264 mask = ((1 << (info->bits + 1)) - 1); 265 value &= ~mask; 266 if (info->polarity == 1) 267 gain = info->max_gain - values[1]; 268 else 269 gain = values[1] - info->min_gain; 270 value |= ((uint16)(gain / info->granularity)) & mask; 271 } else { 272 mask = ((1 << (info->bits + 1)) - 1); 273 value &= ~mask; 274 if (info->polarity == 1) 275 gain = info->max_gain - values[0]; 276 else 277 gain = values[0] - info->min_gain; 278 value |= ((uint16)(gain / info->granularity)) & mask; 279 } 280 //TRACE("B_MIX_GAIN value : %u\n", value); 281 ac97_reg_cached_write(controller->ac97, info->reg, value); 282 break; 283 case B_MIX_MUTE: 284 mask = ((1 << 1) - 1) << 15; 285 value = ac97_reg_cached_read(controller->ac97, info->reg); 286 value &= ~mask; 287 value |= ((values[0] == 1.0 ? 1 : 0 ) << 15 & mask); 288 if (info->reg == AC97_SURR_VOLUME) { 289 // there is a independent mute for each channel 290 mask = ((1 << 1) - 1) << 7; 291 value &= ~mask; 292 value |= ((values[0] == 1.0 ? 1 : 0 ) << 7 & mask); 293 } 294 //TRACE("B_MIX_MUTE value : %u\n", value); 295 ac97_reg_cached_write(controller->ac97, info->reg, value); 296 break; 297 case B_MIX_MICBOOST: 298 mask = ((1 << 1) - 1) << 6; 299 value = ac97_reg_cached_read(controller->ac97, info->reg); 300 value &= ~mask; 301 value |= ((values[0] == 1.0 ? 1 : 0 ) << 6 & mask); 302 //TRACE("B_MIX_MICBOOST value : %u\n", value); 303 ac97_reg_cached_write(controller->ac97, info->reg, value); 304 break; 305 case B_MIX_MUX: 306 mask = ((1 << 3) - 1); 307 value = ((int32)values[0]) & mask; 308 value = value | (value << 8); 309 //TRACE("B_MIX_MUX value : %u\n", value); 310 ac97_reg_cached_write(controller->ac97, AC97_RECORD_SELECT, value); 311 break; 312 } 313 314 } 315 316 317 static int32 318 create_group_control(geode_multi *multi, uint32 *index, uint32 parent, 319 strind_id string, const char* name) { 320 int32 i = *index; 321 (*index)++; 322 multi->controls[i].mix_control.id = MULTI_CONTROL_FIRSTID + i; 323 multi->controls[i].mix_control.parent = parent; 324 multi->controls[i].mix_control.flags = B_MULTI_MIX_GROUP; 325 multi->controls[i].mix_control.master = MULTI_CONTROL_MASTERID; 326 multi->controls[i].mix_control.string = string; 327 if (name) 328 strcpy(multi->controls[i].mix_control.name, name); 329 330 return multi->controls[i].mix_control.id; 331 } 332 333 334 static status_t 335 create_controls_list(geode_multi *multi) 336 { 337 uint32 i = 0, index = 0, count, id, parent, parent2, parent3; 338 const ac97_source_info *info; 339 340 /* AC97 Mixer */ 341 parent = create_group_control(multi, &index, 0, S_null, "AC97 mixer"); 342 343 count = source_info_size; 344 //Note that we ignore first item in source_info 345 //It's for recording, but do match this with ac97.c's source_info 346 for (i = 1; i < count ; i++) { 347 info = &source_info[i]; 348 TRACE("name : %s\n", info->name); 349 350 parent2 = create_group_control(multi, &index, parent, S_null, info->name); 351 352 if (info->type & B_MIX_GAIN) { 353 if (info->type & B_MIX_MUTE) { 354 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 355 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE; 356 multi->controls[index].mix_control.master = MULTI_CONTROL_MASTERID; 357 multi->controls[index].mix_control.parent = parent2; 358 multi->controls[index].mix_control.string = S_MUTE; 359 multi->controls[index].cookie = info; 360 multi->controls[index].type = B_MIX_MUTE; 361 multi->controls[index].get = &geode_ac97_get_mix; 362 multi->controls[index].set = &geode_ac97_set_mix; 363 index++; 364 } 365 366 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 367 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN; 368 multi->controls[index].mix_control.master = MULTI_CONTROL_MASTERID; 369 multi->controls[index].mix_control.parent = parent2; 370 strcpy(multi->controls[index].mix_control.name, info->name); 371 multi->controls[index].mix_control.gain.min_gain = info->min_gain; 372 multi->controls[index].mix_control.gain.max_gain = info->max_gain; 373 multi->controls[index].mix_control.gain.granularity = info->granularity; 374 multi->controls[index].cookie = info; 375 multi->controls[index].type = B_MIX_GAIN; 376 multi->controls[index].get = &geode_ac97_get_mix; 377 multi->controls[index].set = &geode_ac97_set_mix; 378 id = multi->controls[index].mix_control.id; 379 index++; 380 381 if (info->type & B_MIX_STEREO) { 382 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 383 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN; 384 multi->controls[index].mix_control.master = id; 385 multi->controls[index].mix_control.parent = parent2; 386 strcpy(multi->controls[index].mix_control.name, info->name); 387 multi->controls[index].mix_control.gain.min_gain = info->min_gain; 388 multi->controls[index].mix_control.gain.max_gain = info->max_gain; 389 multi->controls[index].mix_control.gain.granularity = info->granularity; 390 multi->controls[index].cookie = info; 391 multi->controls[index].type = B_MIX_GAIN; 392 multi->controls[index].get = &geode_ac97_get_mix; 393 multi->controls[index].set = &geode_ac97_set_mix; 394 index++; 395 } 396 397 if (info->type & B_MIX_MICBOOST) { 398 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 399 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE; 400 multi->controls[index].mix_control.master = MULTI_CONTROL_MASTERID; 401 multi->controls[index].mix_control.parent = parent2; 402 strcpy(multi->controls[index].mix_control.name, "+20 dB"); 403 multi->controls[index].cookie = info; 404 multi->controls[index].type = B_MIX_MICBOOST; 405 multi->controls[index].get = &geode_ac97_get_mix; 406 multi->controls[index].set = &geode_ac97_set_mix; 407 index++; 408 } 409 } 410 } 411 412 /* AC97 Record */ 413 parent = create_group_control(multi, &index, 0, S_null, "Recording"); 414 415 info = &source_info[0]; 416 TRACE("name : %s\n", info->name); 417 418 parent2 = create_group_control(multi, &index, parent, S_null, info->name); 419 420 if (info->type & B_MIX_GAIN) { 421 if (info->type & B_MIX_MUTE) { 422 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 423 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE; 424 multi->controls[index].mix_control.master = MULTI_CONTROL_MASTERID; 425 multi->controls[index].mix_control.parent = parent2; 426 multi->controls[index].mix_control.string = S_MUTE; 427 multi->controls[index].cookie = info; 428 multi->controls[index].type = B_MIX_MUTE; 429 multi->controls[index].get = &geode_ac97_get_mix; 430 multi->controls[index].set = &geode_ac97_set_mix; 431 index++; 432 } 433 434 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 435 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN; 436 multi->controls[index].mix_control.master = MULTI_CONTROL_MASTERID; 437 multi->controls[index].mix_control.parent = parent2; 438 strcpy(multi->controls[index].mix_control.name, info->name); 439 multi->controls[index].mix_control.gain.min_gain = info->min_gain; 440 multi->controls[index].mix_control.gain.max_gain = info->max_gain; 441 multi->controls[index].mix_control.gain.granularity = info->granularity; 442 multi->controls[index].cookie = info; 443 multi->controls[index].type = B_MIX_GAIN; 444 multi->controls[index].get = &geode_ac97_get_mix; 445 multi->controls[index].set = &geode_ac97_set_mix; 446 id = multi->controls[index].mix_control.id; 447 index++; 448 449 if (info->type & B_MIX_STEREO) { 450 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 451 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN; 452 multi->controls[index].mix_control.master = id; 453 multi->controls[index].mix_control.parent = parent2; 454 strcpy(multi->controls[index].mix_control.name, info->name); 455 multi->controls[index].mix_control.gain.min_gain = info->min_gain; 456 multi->controls[index].mix_control.gain.max_gain = info->max_gain; 457 multi->controls[index].mix_control.gain.granularity = info->granularity; 458 multi->controls[index].cookie = info; 459 multi->controls[index].type = B_MIX_GAIN; 460 multi->controls[index].get = &geode_ac97_get_mix; 461 multi->controls[index].set = &geode_ac97_set_mix; 462 index++; 463 } 464 465 if (info->type & B_MIX_RECORDMUX) { 466 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 467 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX; 468 multi->controls[index].mix_control.parent = parent2; 469 strcpy(multi->controls[index].mix_control.name, "Record mux"); 470 multi->controls[index].cookie = info; 471 multi->controls[index].type = B_MIX_MUX; 472 multi->controls[index].get = &geode_ac97_get_mix; 473 multi->controls[index].set = &geode_ac97_set_mix; 474 parent3 = multi->controls[index].mix_control.id; 475 index++; 476 477 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 478 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 479 multi->controls[index].mix_control.parent = parent3; 480 multi->controls[index].mix_control.string = S_MIC; 481 index++; 482 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 483 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 484 multi->controls[index].mix_control.parent = parent3; 485 strcpy(multi->controls[index].mix_control.name, "CD in"); 486 index++; 487 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 488 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 489 multi->controls[index].mix_control.parent = parent3; 490 strcpy(multi->controls[index].mix_control.name, "Video in"); 491 index++; 492 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 493 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 494 multi->controls[index].mix_control.parent = parent3; 495 strcpy(multi->controls[index].mix_control.name, "Aux in"); 496 index++; 497 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 498 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 499 multi->controls[index].mix_control.parent = parent3; 500 strcpy(multi->controls[index].mix_control.name, "Line in"); 501 index++; 502 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 503 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 504 multi->controls[index].mix_control.parent = parent3; 505 multi->controls[index].mix_control.string = S_STEREO_MIX; 506 index++; 507 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 508 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 509 multi->controls[index].mix_control.parent = parent3; 510 multi->controls[index].mix_control.string = S_MONO_MIX; 511 index++; 512 multi->controls[index].mix_control.id = MULTI_CONTROL_FIRSTID + index; 513 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE; 514 multi->controls[index].mix_control.parent = parent3; 515 strcpy(multi->controls[index].mix_control.name, "TAD"); 516 index++; 517 } 518 } 519 520 multi->control_count = index; 521 TRACE("multi->control_count %" B_PRIu32 "\n", multi->control_count); 522 return B_OK; 523 } 524 525 526 static status_t 527 list_mix_controls(geode_controller* controller, multi_mix_control_info* mmci) 528 { 529 multi_mix_control* mmc = mmci->controls; 530 if (mmci->control_count < 24) 531 return B_ERROR; 532 533 if (create_controls_list(controller->multi) < B_OK) 534 return B_ERROR; 535 for (uint32 i = 0; i < controller->multi->control_count; i++) { 536 mmc[i] = controller->multi->controls[i].mix_control; 537 } 538 539 mmci->control_count = controller->multi->control_count; 540 return B_OK; 541 } 542 543 544 static status_t 545 list_mix_connections(geode_controller* controller, 546 multi_mix_connection_info* data) 547 { 548 data->actual_count = 0; 549 return B_OK; 550 } 551 552 553 static status_t 554 list_mix_channels(geode_controller* controller, multi_mix_channel_info *data) 555 { 556 return B_OK; 557 } 558 559 560 static status_t 561 get_mix(geode_controller *controller, multi_mix_value_info * mmvi) 562 { 563 for (int32 i = 0; i < mmvi->item_count; i++) { 564 uint32 id = mmvi->values[i].id - MULTI_CONTROL_FIRSTID; 565 if (id < 0 || id >= controller->multi->control_count) { 566 dprintf("geode_get_mix : invalid control id requested : %" B_PRId32 "\n", id); 567 continue; 568 } 569 multi_mixer_control *control = &controller->multi->controls[id]; 570 571 if (control->mix_control.flags & B_MULTI_MIX_GAIN) { 572 if (control->get) { 573 float values[2]; 574 control->get(controller, control->cookie, control->type, values); 575 if (control->mix_control.master == MULTI_CONTROL_MASTERID) 576 mmvi->values[i].gain = values[0]; 577 else 578 mmvi->values[i].gain = values[1]; 579 } 580 } 581 582 if (control->mix_control.flags & B_MULTI_MIX_ENABLE && control->get) { 583 float values[1]; 584 control->get(controller, control->cookie, control->type, values); 585 mmvi->values[i].enable = (values[0] == 1.0); 586 } 587 588 if (control->mix_control.flags & B_MULTI_MIX_MUX && control->get) { 589 float values[1]; 590 control->get(controller, control->cookie, control->type, values); 591 mmvi->values[i].mux = (int32)values[0]; 592 } 593 } 594 return B_OK; 595 } 596 597 598 static status_t 599 set_mix(geode_controller *controller, multi_mix_value_info * mmvi) 600 { 601 geode_multi *multi = controller->multi; 602 for (int32 i = 0; i < mmvi->item_count; i++) { 603 uint32 id = mmvi->values[i].id - MULTI_CONTROL_FIRSTID; 604 if (id < 0 || id >= multi->control_count) { 605 dprintf("geode_set_mix : invalid control id requested : %" B_PRId32 "\n", id); 606 continue; 607 } 608 multi_mixer_control *control = &multi->controls[id]; 609 610 if (control->mix_control.flags & B_MULTI_MIX_GAIN) { 611 multi_mixer_control *control2 = NULL; 612 if (i+1<mmvi->item_count) { 613 id = mmvi->values[i + 1].id - MULTI_CONTROL_FIRSTID; 614 if (id < 0 || id >= multi->control_count) { 615 dprintf("geode_set_mix : invalid control id requested : %" B_PRId32 "\n", id); 616 } else { 617 control2 = &multi->controls[id]; 618 if (control2->mix_control.master != control->mix_control.id) 619 control2 = NULL; 620 } 621 } 622 623 if (control->set) { 624 float values[2]; 625 values[0] = 0.0; 626 values[1] = 0.0; 627 628 if (control->mix_control.master == MULTI_CONTROL_MASTERID) 629 values[0] = mmvi->values[i].gain; 630 else 631 values[1] = mmvi->values[i].gain; 632 633 if (control2 && control2->mix_control.master != MULTI_CONTROL_MASTERID) 634 values[1] = mmvi->values[i+1].gain; 635 636 control->set(controller, control->cookie, control->type, values); 637 } 638 639 if (control2) 640 i++; 641 } 642 643 if (control->mix_control.flags & B_MULTI_MIX_ENABLE && control->set) { 644 float values[1]; 645 646 values[0] = mmvi->values[i].enable ? 1.0 : 0.0; 647 control->set(controller, control->cookie, control->type, values); 648 } 649 650 if (control->mix_control.flags & B_MULTI_MIX_MUX && control->set) { 651 float values[1]; 652 653 values[0] = (float)mmvi->values[i].mux; 654 control->set(controller, control->cookie, control->type, values); 655 } 656 } 657 return B_OK; 658 } 659 660 661 static status_t 662 get_buffers(geode_controller* controller, multi_buffer_list* data) 663 { 664 TRACE("playback: %" B_PRId32 " buffers, %" B_PRId32 " channels, %" B_PRIu32 " samples\n", 665 data->request_playback_buffers, data->request_playback_channels, 666 data->request_playback_buffer_size); 667 TRACE("record: %" B_PRId32 " buffers, %" B_PRId32 " channels, %" B_PRIu32 " samples\n", 668 data->request_record_buffers, data->request_record_channels, 669 data->request_record_buffer_size); 670 671 /* Determine what buffers we return given the request */ 672 673 data->return_playback_buffers = data->request_playback_buffers; 674 data->return_playback_channels = data->request_playback_channels; 675 data->return_playback_buffer_size = data->request_playback_buffer_size; 676 data->return_record_buffers = data->request_record_buffers; 677 data->return_record_channels = data->request_record_channels; 678 data->return_record_buffer_size = data->request_record_buffer_size; 679 680 /* Workaround for Haiku multi_audio API, since it prefers to let the 681 driver pick values, while the BeOS multi_audio actually gives the 682 user's defaults. */ 683 if (data->return_playback_buffers > STREAM_MAX_BUFFERS 684 || data->return_playback_buffers < STREAM_MIN_BUFFERS) 685 data->return_playback_buffers = STREAM_MIN_BUFFERS; 686 687 if (data->return_record_buffers > STREAM_MAX_BUFFERS 688 || data->return_record_buffers < STREAM_MIN_BUFFERS) 689 data->return_record_buffers = STREAM_MIN_BUFFERS; 690 691 if (data->return_playback_buffer_size == 0) 692 data->return_playback_buffer_size = DEFAULT_FRAMES_PER_BUFFER; 693 694 if (data->return_record_buffer_size == 0) 695 data->return_record_buffer_size = DEFAULT_FRAMES_PER_BUFFER; 696 697 /* ... from here on, we can assume again that a reasonable request is 698 being made */ 699 700 data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; 701 702 /* Copy the settings into the streams */ 703 704 if (controller->playback_stream != NULL) { 705 controller->playback_stream->num_buffers = data->return_playback_buffers; 706 controller->playback_stream->num_channels = data->return_playback_channels; 707 controller->playback_stream->buffer_length 708 = data->return_playback_buffer_size; 709 710 status_t status = geode_stream_setup_buffers( 711 controller->playback_stream, "Playback"); 712 if (status != B_OK) { 713 dprintf("geode: Error setting up playback buffers: %s\n", 714 strerror(status)); 715 return status; 716 } 717 } 718 719 if (controller->record_stream != NULL) { 720 controller->record_stream->num_buffers = data->return_record_buffers; 721 controller->record_stream->num_channels = data->return_record_channels; 722 controller->record_stream->buffer_length 723 = data->return_record_buffer_size; 724 725 status_t status = geode_stream_setup_buffers( 726 controller->record_stream, "Recording"); 727 if (status != B_OK) { 728 dprintf("geode: Error setting up recording buffers: %s\n", 729 strerror(status)); 730 return status; 731 } 732 } 733 734 /* Setup data structure for multi_audio API... */ 735 736 if (controller->playback_stream != NULL) { 737 uint32 playbackSampleSize = controller->playback_stream->sample_size; 738 739 for (int32 i = 0; i < data->return_playback_buffers; i++) { 740 for (int32 channelIndex = 0; 741 channelIndex < data->return_playback_channels; channelIndex++) { 742 data->playback_buffers[i][channelIndex].base 743 = (char*)controller->playback_stream->buffers[i] 744 + playbackSampleSize * channelIndex; 745 data->playback_buffers[i][channelIndex].stride 746 = playbackSampleSize * data->return_playback_channels; 747 } 748 } 749 } 750 751 if (controller->record_stream != NULL) { 752 uint32 recordSampleSize = controller->record_stream->sample_size; 753 754 for (int32 i = 0; i < data->return_record_buffers; i++) { 755 for (int32 channelIndex = 0; 756 channelIndex < data->return_record_channels; channelIndex++) { 757 data->record_buffers[i][channelIndex].base 758 = (char*)controller->record_stream->buffers[i] 759 + recordSampleSize * channelIndex; 760 data->record_buffers[i][channelIndex].stride 761 = recordSampleSize * data->return_record_channels; 762 } 763 } 764 } 765 766 return B_OK; 767 } 768 769 770 /*! playback_buffer_cycle is the buffer we want to have played */ 771 static status_t 772 buffer_exchange(geode_controller* controller, multi_buffer_info* data) 773 { 774 static int debug_buffers_exchanged = 0; 775 cpu_status status; 776 status_t err; 777 multi_buffer_info buffer_info; 778 779 if (controller->playback_stream == NULL) 780 return B_ERROR; 781 782 if (!controller->playback_stream->running) { 783 geode_stream_start(controller->playback_stream); 784 } 785 if (controller->record_stream && !controller->record_stream->running) { 786 geode_stream_start(controller->record_stream); 787 } 788 789 #ifdef __HAIKU__ 790 if (user_memcpy(&buffer_info, data, sizeof(buffer_info)) < B_OK) 791 return B_BAD_ADDRESS; 792 #else 793 memcpy(&buffer_info, data, sizeof(buffer_info)); 794 #endif 795 796 /* do playback */ 797 err = acquire_sem_etc(controller->playback_stream->buffer_ready_sem, 798 1, B_CAN_INTERRUPT, 0); 799 if (err != B_OK) { 800 dprintf("%s: Error waiting for playback buffer to finish (%s)!\n", __func__, 801 strerror(err)); 802 return err; 803 } 804 805 status = disable_interrupts(); 806 acquire_spinlock(&controller->playback_stream->lock); 807 808 buffer_info.playback_buffer_cycle = controller->playback_stream->buffer_cycle; 809 buffer_info.played_real_time = controller->playback_stream->real_time; 810 buffer_info.played_frames_count = controller->playback_stream->frames_count; 811 812 release_spinlock(&controller->playback_stream->lock); 813 814 if (controller->record_stream) { 815 acquire_spinlock(&controller->record_stream->lock); 816 buffer_info.record_buffer_cycle = controller->record_stream->buffer_cycle; 817 buffer_info.recorded_real_time = controller->record_stream->real_time; 818 buffer_info.recorded_frames_count = controller->record_stream->frames_count; 819 release_spinlock(&controller->record_stream->lock); 820 } 821 822 restore_interrupts(status); 823 824 #ifdef __HAIKU__ 825 if (user_memcpy(data, &buffer_info, sizeof(buffer_info)) < B_OK) 826 return B_BAD_ADDRESS; 827 #else 828 memcpy(data, &buffer_info, sizeof(buffer_info)); 829 #endif 830 831 debug_buffers_exchanged++; 832 if (((debug_buffers_exchanged % 100) == 1) && (debug_buffers_exchanged < 1111)) { 833 dprintf("%s: %d buffers processed\n", __func__, debug_buffers_exchanged); 834 } 835 836 return B_OK; 837 } 838 839 840 static status_t 841 buffer_force_stop(geode_controller* controller) 842 { 843 if (controller->playback_stream != NULL) { 844 geode_stream_stop(controller->playback_stream); 845 } 846 if (controller->record_stream != NULL) { 847 geode_stream_stop(controller->record_stream); 848 } 849 850 return B_OK; 851 } 852 853 854 status_t 855 multi_audio_control(geode_controller* controller, uint32 op, void* arg, size_t len) 856 { 857 // TODO: make userland-safe when built for Haiku! 858 859 switch (op) { 860 case B_MULTI_GET_DESCRIPTION: 861 { 862 #ifdef __HAIKU__ 863 multi_description description; 864 multi_channel_info channels[16]; 865 multi_channel_info* originalChannels; 866 867 if (user_memcpy(&description, arg, sizeof(multi_description)) 868 != B_OK) 869 return B_BAD_ADDRESS; 870 871 originalChannels = description.channels; 872 description.channels = channels; 873 if (description.request_channel_count > 16) 874 description.request_channel_count = 16; 875 876 status_t status = get_description(controller, &description); 877 if (status != B_OK) 878 return status; 879 880 description.channels = originalChannels; 881 if (user_memcpy(arg, &description, sizeof(multi_description)) 882 != B_OK) 883 return B_BAD_ADDRESS; 884 return user_memcpy(originalChannels, channels, sizeof(multi_channel_info) 885 * description.request_channel_count); 886 #else 887 return get_description(controller, (multi_description*)arg); 888 #endif 889 } 890 891 case B_MULTI_GET_ENABLED_CHANNELS: 892 return get_enabled_channels(controller, (multi_channel_enable*)arg); 893 case B_MULTI_SET_ENABLED_CHANNELS: 894 return B_OK; 895 896 case B_MULTI_GET_GLOBAL_FORMAT: 897 return get_global_format(controller, (multi_format_info*)arg); 898 case B_MULTI_SET_GLOBAL_FORMAT: 899 return set_global_format(controller, (multi_format_info*)arg); 900 901 case B_MULTI_LIST_MIX_CHANNELS: 902 return list_mix_channels(controller, (multi_mix_channel_info*)arg); 903 case B_MULTI_LIST_MIX_CONTROLS: 904 return list_mix_controls(controller, (multi_mix_control_info*)arg); 905 case B_MULTI_LIST_MIX_CONNECTIONS: 906 return list_mix_connections(controller, 907 (multi_mix_connection_info*)arg); 908 case B_MULTI_GET_MIX: 909 return get_mix(controller, (multi_mix_value_info *)arg); 910 case B_MULTI_SET_MIX: 911 return set_mix(controller, (multi_mix_value_info *)arg); 912 913 case B_MULTI_GET_BUFFERS: 914 return get_buffers(controller, (multi_buffer_list*)arg); 915 916 case B_MULTI_BUFFER_EXCHANGE: 917 return buffer_exchange(controller, (multi_buffer_info*)arg); 918 case B_MULTI_BUFFER_FORCE_STOP: 919 return buffer_force_stop(controller); 920 921 case B_MULTI_GET_EVENT_INFO: 922 case B_MULTI_SET_EVENT_INFO: 923 case B_MULTI_GET_EVENT: 924 case B_MULTI_GET_CHANNEL_FORMATS: 925 case B_MULTI_SET_CHANNEL_FORMATS: 926 case B_MULTI_SET_BUFFERS: 927 case B_MULTI_SET_START_TIME: 928 return B_ERROR; 929 } 930 931 return B_BAD_VALUE; 932 } 933