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