1/* 2 * BeOS Driver for Intel ICH AC'97 Link interface 3 * 4 * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de> 5 * 6 * All rights reserved. 7 * Redistribution and use in source and binary forms, with or without modification, 8 * are permitted provided that the following conditions are met: 9 * 10 * - Redistributions of source code must retain the above copyright notice, 11 * this list of conditions and the following disclaimer. 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 25 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 */ 28#include <OS.h> 29#include <MediaDefs.h> 30#include "multi_audio.h" 31#include "ac97_multi.h" 32 33//#define DEBUG 1 34 35#include "debug.h" 36#include "ich.h" 37#include "util.h" 38#include "config.h" 39 40/* 41 * 42 * XXX!!! ALL "MIX" ioctls are not implemented by the BeOS R5, get never called :-( 43 * The concept described by B_MULTI_SET_BUFFERS is impossible to implement 44 * B_MULTI_GET_BUFFERS can not be handled as efficient as envisioned by the API creators 45 * 46 */ 47 48static status_t list_mix_controls(multi_mix_control_info *data); 49static status_t list_mix_connections(multi_mix_connection_info *data); 50static status_t list_mix_channels(multi_mix_channel_info *data); 51static status_t get_description(multi_description *data); 52static status_t get_enabled_channels(multi_channel_enable *data); 53static status_t get_global_format(multi_format_info *data); 54static status_t get_buffers(multi_buffer_list *data); 55static status_t buffer_exchange(multi_buffer_info *data); 56static status_t buffer_force_stop(); 57 58static status_t list_mix_controls(multi_mix_control_info * data) 59{ 60 return B_OK; 61} 62 63static status_t list_mix_connections(multi_mix_connection_info * data) 64{ 65 data->actual_count = 0; 66 return B_OK; 67} 68 69static status_t list_mix_channels(multi_mix_channel_info *data) 70{ 71 return B_OK; 72} 73 74multi_channel_info chans[] = { 75{ 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 76{ 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 77{ 2, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 78{ 3, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 79{ 4, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 80{ 5, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 81{ 6, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 82{ 7, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 83}; 84 85static status_t get_description(multi_description *data) 86{ 87 data->interface_version = B_CURRENT_INTERFACE_VERSION; 88 data->interface_minimum = B_CURRENT_INTERFACE_VERSION; 89 90 strcpy(data->friendly_name,"AC97 (ICH)"); 91 strcpy(data->vendor_info,"Marcus Overhagen"); 92 93 data->output_channel_count = 2; 94 data->input_channel_count = 2; 95 data->output_bus_channel_count = 2; 96 data->input_bus_channel_count = 2; 97 data->aux_bus_channel_count = 0; 98 99 // for each channel, starting with the first output channel, 100 // then the second, third..., followed by the first input 101 // channel, second, third, ..., followed by output bus 102 // channels and input bus channels and finally auxillary channels, 103 104 LOG(("request_channel_count = %d\n",data->request_channel_count)); 105 if (data->request_channel_count >= (int)(sizeof(chans) / sizeof(chans[0]))) { 106 LOG(("copying data\n")); 107 memcpy(data->channels,&chans,sizeof(chans)); 108 } 109 110 /* determine output rates */ 111 data->output_rates = 0; 112 if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 8000)) 113 data->output_rates |= B_SR_8000; 114 if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 11025)) 115 data->output_rates |= B_SR_11025; 116 if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 12000)) 117 data->output_rates |= B_SR_12000; 118 if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 16000)) 119 data->output_rates |= B_SR_16000; 120 if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 22050)) 121 data->output_rates |= B_SR_22050; 122 if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 24000)) 123 data->output_rates |= B_SR_24000; 124 if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 32000)) 125 data->output_rates |= B_SR_32000; 126 if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100)) 127 data->output_rates |= B_SR_44100; 128 if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 48000)) 129 data->output_rates |= B_SR_48000; 130 131 /* determine input rates */ 132 data->input_rates = 0; 133 if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 8000)) 134 data->input_rates |= B_SR_8000; 135 if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 11025)) 136 data->input_rates |= B_SR_11025; 137 if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 12000)) 138 data->input_rates |= B_SR_12000; 139 if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 16000)) 140 data->input_rates |= B_SR_16000; 141 if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 22050)) 142 data->input_rates |= B_SR_22050; 143 if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 24000)) 144 data->input_rates |= B_SR_24000; 145 if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 32000)) 146 data->input_rates |= B_SR_32000; 147 if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 44100)) 148 data->input_rates |= B_SR_44100; 149 if (ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 48000)) 150 data->input_rates |= B_SR_48000; 151 152 /* try to set 44100 rate */ 153 if (ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100) 154 && ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 44100)) { 155 config->input_rate = B_SR_44100; 156 config->output_rate = B_SR_44100; 157 } else { 158 /* if that didn't work, continue with 48000 */ 159 ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 48000); 160 ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 48000); 161 config->input_rate = B_SR_48000; 162 config->output_rate = B_SR_48000; 163 } 164 165 /* force existance of 48kHz if variable rates are not supported */ 166 if (data->output_rates == 0) 167 data->output_rates = B_SR_48000; 168 if (data->input_rates == 0) 169 data->input_rates = B_SR_48000; 170 171 data->max_cvsr_rate = 0; 172 data->min_cvsr_rate = 0; 173 174 data->output_formats = B_FMT_16BIT; 175 data->input_formats = B_FMT_16BIT; 176 data->lock_sources = B_MULTI_LOCK_INTERNAL; 177 data->timecode_sources = 0; 178 data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD; 179 data->start_latency = 30000; 180 181 strcpy(data->control_panel,""); 182 183 return B_OK; 184} 185 186static status_t get_enabled_channels(multi_channel_enable *data) 187{ 188 B_SET_CHANNEL(data->enable_bits, 0, true); 189 B_SET_CHANNEL(data->enable_bits, 1, true); 190 B_SET_CHANNEL(data->enable_bits, 2, true); 191 B_SET_CHANNEL(data->enable_bits, 3, true); 192 data->lock_source = B_MULTI_LOCK_INTERNAL; 193/* 194 uint32 lock_source; 195 int32 lock_data; 196 uint32 timecode_source; 197 uint32 * connectors; 198*/ 199 return B_OK; 200} 201 202static status_t get_global_format(multi_format_info *data) 203{ 204 data->output_latency = 0; 205 data->input_latency = 0; 206 data->timecode_kind = 0; 207 data->input.format = B_FMT_16BIT; 208 data->output.format = B_FMT_16BIT; 209 data->input.rate = config->input_rate; 210 data->output.rate = config->output_rate; 211 return B_OK; 212} 213 214static status_t set_global_format(multi_format_info *data) 215{ 216 bool in, out; 217 LOG(("set_global_format: input.rate = 0x%x\n", data->input.rate)); 218 LOG(("set_global_format: input.cvsr = %d\n", data->input.cvsr)); 219 LOG(("set_global_format: output.rate = 0x%x\n", data->output.rate)); 220 LOG(("set_global_format: output.cvsr = %d\n", data->output.cvsr)); 221 switch (data->input.rate) { 222 case B_SR_8000: 223 in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 8000); 224 break; 225 case B_SR_11025: 226 in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 11025); 227 break; 228 case B_SR_12000: 229 in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 12000); 230 break; 231 case B_SR_16000: 232 in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 16000); 233 break; 234 case B_SR_22050: 235 in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 22050); 236 break; 237 case B_SR_24000: 238 in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 24000); 239 break; 240 case B_SR_32000: 241 in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 32000); 242 break; 243 case B_SR_44100: 244 in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 44100); 245 break; 246 case B_SR_48000: 247 in = ac97_set_rate(config->ac97, AC97_PCM_L_R_ADC_RATE, 48000); 248 break; 249 default: 250 in = false; 251 } 252 253 switch (data->output.rate) { 254 case B_SR_8000: 255 out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 8000); 256 break; 257 case B_SR_11025: 258 out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 11025); 259 break; 260 case B_SR_12000: 261 out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 12000); 262 break; 263 case B_SR_16000: 264 out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 16000); 265 break; 266 case B_SR_22050: 267 out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 22050); 268 break; 269 case B_SR_24000: 270 out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 24000); 271 break; 272 case B_SR_32000: 273 out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 32000); 274 break; 275 case B_SR_44100: 276 out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 44100); 277 break; 278 case B_SR_48000: 279 out = ac97_set_rate(config->ac97, AC97_PCM_FRONT_DAC_RATE, 48000); 280 break; 281 default: 282 out = false; 283 } 284 285 if (!in || !out) 286 return B_ERROR; 287 288 config->input_rate = data->input.rate; 289 config->output_rate = data->output.rate; 290 return B_OK; 291} 292 293 294static status_t get_buffers(multi_buffer_list *data) 295{ 296 LOG(("flags = %#x\n",data->flags)); 297 LOG(("request_playback_buffers = %#x\n",data->request_playback_buffers)); 298 LOG(("request_playback_channels = %#x\n",data->request_playback_channels)); 299 LOG(("request_playback_buffer_size = %#x\n",data->request_playback_buffer_size)); 300 LOG(("request_record_buffers = %#x\n",data->request_record_buffers)); 301 LOG(("request_record_channels = %#x\n",data->request_record_channels)); 302 LOG(("request_record_buffer_size = %#x\n",data->request_record_buffer_size)); 303 304 if (data->request_playback_buffers < 2 || 305 data->request_playback_channels < 2 || 306 data->request_record_buffers < 2 || 307 data->request_record_channels < 2) { 308 LOG(("not enough channels/buffers\n")); 309 } 310 311 ASSERT(BUFFER_COUNT == 2); 312 313// data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; // XXX ??? 314 data->flags = 0; 315 316 data->return_playback_buffers = 2; /* playback_buffers[b][] */ 317 data->return_playback_channels = 2; /* playback_buffers[][c] */ 318 data->return_playback_buffer_size = BUFFER_SIZE / 4; /* frames */ 319 320 /* buffer 0, left channel */ 321 data->playback_buffers[0][0].base = chan_po->userbuffer[0]; /* pointer to first sample for channel for buffer */ 322 data->playback_buffers[0][0].stride = 4; /* offset to next sample */ 323 /* buffer 0, right channel */ 324 data->playback_buffers[0][1].base = ((char*)chan_po->userbuffer[0]) + 2; /* pointer to first sample for channel for buffer */ 325 data->playback_buffers[0][1].stride = 4; /* offset to next sample */ 326 /* buffer 1, left channel */ 327 data->playback_buffers[1][0].base = chan_po->userbuffer[1]; /* pointer to first sample for channel for buffer */ 328 data->playback_buffers[1][0].stride = 4; /* offset to next sample */ 329 /* buffer 1, right channel */ 330 data->playback_buffers[1][1].base = ((char*)chan_po->userbuffer[1]) + 2; /* pointer to first sample for channel for buffer */ 331 data->playback_buffers[1][1].stride = 4; /* offset to next sample */ 332 333 data->return_record_buffers = 2; 334 data->return_record_channels = 2; 335 data->return_record_buffer_size = BUFFER_SIZE / 4; /* frames */ 336 337 /* buffer 0, left channel */ 338 data->record_buffers[0][0].base = chan_pi->userbuffer[0]; /* pointer to first sample for channel for buffer */ 339 data->record_buffers[0][0].stride = 4; /* offset to next sample */ 340 /* buffer 0, right channel */ 341 data->record_buffers[0][1].base = ((char*)chan_pi->userbuffer[0]) + 2; /* pointer to first sample for channel for buffer */ 342 data->record_buffers[0][1].stride = 4; /* offset to next sample */ 343 /* buffer 1, left channel */ 344 data->record_buffers[1][0].base = chan_pi->userbuffer[1]; /* pointer to first sample for channel for buffer */ 345 data->record_buffers[1][0].stride = 4; /* offset to next sample */ 346 /* buffer 1, right channel */ 347 data->record_buffers[1][1].base = ((char*)chan_pi->userbuffer[1]) + 2; /* pointer to first sample for channel for buffer */ 348 data->record_buffers[1][1].stride = 4; /* offset to next sample */ 349 350 return B_OK; 351} 352 353static status_t buffer_exchange(multi_buffer_info *data) 354{ 355#if DEBUG 356 static int debug_buffers_exchanged = 0; 357#endif 358 cpu_status status; 359 void *backbuffer; 360/* 361 static int next_input = 0; 362*/ 363 /* 364 * Only playback works for now, recording seems to be broken, but I don't know why 365 */ 366 367 if (!chan_po->running) 368 start_chan(chan_po); 369 370/* 371 if (!chan_pi->running) 372 start_chan(chan_pi); 373*/ 374 375 /* do playback */ 376 acquire_sem(chan_po->buffer_ready_sem); 377 status = lock(); 378 backbuffer = (void *)chan_po->backbuffer; 379 data->played_real_time = chan_po->played_real_time; 380 data->played_frames_count = chan_po->played_frames_count; 381 unlock(status); 382 memcpy(backbuffer, chan_po->userbuffer[data->playback_buffer_cycle], BUFFER_SIZE); 383 384 /* do record */ 385 data->record_buffer_cycle = 0; 386 data->recorded_frames_count = 0; 387/* 388 if (B_OK == acquire_sem_etc(chan_pi->buffer_ready_sem, 1, B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT,200)) { 389 status = lock(); 390 backbuffer = (void *)chan_pi->backbuffer; 391 data->recorded_real_time = chan_pi->played_real_time; 392 unlock(status); 393 data->recorded_frames_count = BUFFER_SIZE / 4; 394 data->record_buffer_cycle = next_input; 395 next_input = (next_input + 1) % 2; 396 memcpy(chan_pi->userbuffer[data->record_buffer_cycle],backbuffer, BUFFER_SIZE); 397 } else { 398 data->record_buffer_cycle = next_input; 399 data->recorded_frames_count = 0; 400 } 401*/ 402#if DEBUG 403 debug_buffers_exchanged++; 404 if (((debug_buffers_exchanged % 100) == 1) && (debug_buffers_exchanged < 1111)) { 405 LOG(("buffer_exchange: %d buffers processed\n", debug_buffers_exchanged)); 406 } 407#endif 408 409 return B_OK; 410 411/* 412 if (data->flags & B_MULTI_BUFFER_PLAYBACK) { 413 dprintf("B_MULTI_BUFFER_PLAYBACK\n"); 414 } 415 416 if (data->flags & B_MULTI_BUFFER_RECORD) { 417 dprintf("B_MULTI_BUFFER_RECORD\n"); 418 data->recorded_real_time = 0; 419 data->recorded_frames_count = 0; 420 data->record_buffer_cycle = 0; 421 } 422 if (data->flags & B_MULTI_BUFFER_METERING) { 423 dprintf("B_MULTI_BUFFER_METERING\n"); 424 data->meter_channel_count = 0; 425 // data->meters_peak 426 // data->meters_average 427 } 428 if (data->flags & B_MULTI_BUFFER_TIMECODE) { 429 dprintf("B_MULTI_BUFFER_TIMECODE\n"); 430 data->hours = 0; 431 data->minutes = 0; 432 data->seconds = 0; 433 data->tc_frames = 0; 434 data->at_frame_delta = 0; 435 } 436 return B_OK; 437*/ 438} 439 440static status_t buffer_force_stop() 441{ 442 return B_OK; 443} 444 445status_t multi_control(void *cookie, uint32 op, void *data, size_t length) 446{ 447 switch (op) { 448 case B_MULTI_GET_DESCRIPTION: 449 LOG(("B_MULTI_GET_DESCRIPTION\n")); 450 return get_description((multi_description *)data); 451 case B_MULTI_GET_EVENT_INFO: 452 LOG(("B_MULTI_GET_EVENT_INFO\n")); 453 return B_ERROR; 454 case B_MULTI_SET_EVENT_INFO: 455 LOG(("B_MULTI_SET_EVENT_INFO\n")); 456 return B_ERROR; 457 case B_MULTI_GET_EVENT: 458 LOG(("B_MULTI_GET_EVENT\n")); 459 return B_ERROR; 460 case B_MULTI_GET_ENABLED_CHANNELS: 461 LOG(("B_MULTI_GET_ENABLED_CHANNELS\n")); 462 return get_enabled_channels((multi_channel_enable *)data); 463 case B_MULTI_SET_ENABLED_CHANNELS: 464 LOG(("B_MULTI_SET_ENABLED_CHANNELS\n")); 465 return B_OK; break; 466 case B_MULTI_GET_GLOBAL_FORMAT: 467 LOG(("B_MULTI_GET_GLOBAL_FORMAT\n")); 468 return get_global_format((multi_format_info *)data); 469 case B_MULTI_SET_GLOBAL_FORMAT: 470 LOG(("B_MULTI_SET_GLOBAL_FORMAT\n")); 471 set_global_format((multi_format_info *)data); 472 return B_OK; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent 473 * BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT 474 */ 475 case B_MULTI_GET_CHANNEL_FORMATS: 476 LOG(("B_MULTI_GET_CHANNEL_FORMATS\n")); 477 return B_ERROR; 478 case B_MULTI_SET_CHANNEL_FORMATS: /* only implemented if possible */ 479 LOG(("B_MULTI_SET_CHANNEL_FORMATS\n")); 480 return B_ERROR; 481 case B_MULTI_GET_MIX: 482 LOG(("B_MULTI_GET_MIX\n")); 483 return B_ERROR; 484 case B_MULTI_SET_MIX: 485 LOG(("B_MULTI_SET_MIX\n")); 486 return B_ERROR; 487 case B_MULTI_LIST_MIX_CHANNELS: 488 LOG(("B_MULTI_LIST_MIX_CHANNELS\n")); 489 return list_mix_channels((multi_mix_channel_info *)data); 490 case B_MULTI_LIST_MIX_CONTROLS: 491 LOG(("B_MULTI_LIST_MIX_CONTROLS\n")); 492 return list_mix_controls((multi_mix_control_info *)data); 493 case B_MULTI_LIST_MIX_CONNECTIONS: 494 LOG(("B_MULTI_LIST_MIX_CONNECTIONS\n")); 495 return list_mix_connections((multi_mix_connection_info *)data); 496 case B_MULTI_GET_BUFFERS: /* Fill out the struct for the first time; doesn't start anything. */ 497 LOG(("B_MULTI_GET_BUFFERS\n")); 498 return get_buffers(data); 499 case B_MULTI_SET_BUFFERS: /* Set what buffers to use, if the driver supports soft buffers. */ 500 LOG(("B_MULTI_SET_BUFFERS\n")); 501 return B_ERROR; /* we do not support soft buffers */ 502 case B_MULTI_SET_START_TIME: /* When to actually start */ 503 LOG(("B_MULTI_SET_START_TIME\n")); 504 return B_ERROR; 505 case B_MULTI_BUFFER_EXCHANGE: /* stop and go are derived from this being called */ 506// dprintf("B_MULTI_BUFFER_EXCHANGE\n"); 507 return buffer_exchange((multi_buffer_info *)data); 508 case B_MULTI_BUFFER_FORCE_STOP: /* force stop of playback */ 509 LOG(("B_MULTI_BUFFER_FORCE_STOP\n")); 510 return buffer_force_stop(); 511 } 512 LOG(("ERROR: unknown multi_control %#x\n",op)); 513 return B_ERROR; 514} 515 516 517