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 "multi_audio.h" 12 #include "driver.h" 13 14 15 #ifdef TRACE 16 # undef TRACE 17 #endif 18 19 #ifdef TRACE_MULTI_AUDIO 20 # define TRACE(a...) dprintf("\33[34mhda:\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_24BIT: 52 case B_FMT_32BIT: 53 case B_FMT_FLOAT: 54 return 4; 55 56 default: 57 return -1; 58 } 59 } 60 61 62 static status_t 63 get_description(hda_audio_group* audioGroup, multi_description* data) 64 { 65 data->interface_version = B_CURRENT_INTERFACE_VERSION; 66 data->interface_minimum = B_CURRENT_INTERFACE_VERSION; 67 68 strcpy(data->friendly_name, "HD Audio"); 69 strcpy(data->vendor_info, "Haiku"); 70 71 int32 inChannels = 0; 72 if (audioGroup->record_stream != NULL) 73 inChannels = 2; 74 75 int32 outChannels = 0; 76 if (audioGroup->playback_stream != NULL) 77 outChannels = 2; 78 79 data->output_channel_count = outChannels; 80 data->output_bus_channel_count = outChannels; 81 data->input_channel_count = inChannels; 82 data->input_bus_channel_count = inChannels; 83 data->aux_bus_channel_count = 0; 84 85 dprintf("%s: request_channel_count: %ld\n", __func__, 86 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 = audioGroup->supported_rates; 95 data->input_rates = audioGroup->supported_rates; 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 = audioGroup->supported_formats; 107 data->input_formats = audioGroup->supported_formats; 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(hda_audio_group* audioGroup, 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(hda_audio_group* audioGroup, multi_format_info* data) 134 { 135 data->output_latency = 0; 136 data->input_latency = 0; 137 data->timecode_kind = 0; 138 139 if (audioGroup->playback_stream != NULL) { 140 data->output.format = audioGroup->playback_stream->sample_format; 141 data->output.rate = audioGroup->playback_stream->sample_rate; 142 } else { 143 data->output.format = 0; 144 data->output.rate = 0; 145 } 146 147 if (audioGroup->record_stream != NULL) { 148 data->input.format = audioGroup->record_stream->sample_format; 149 data->input.rate = audioGroup->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(hda_audio_group* audioGroup, 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 (audioGroup->playback_stream != NULL) { 170 audioGroup->playback_stream->sample_format = data->output.format; 171 audioGroup->playback_stream->sample_rate = data->output.rate; 172 audioGroup->playback_stream->sample_size = format2size( 173 audioGroup->playback_stream->sample_format); 174 } 175 176 if (audioGroup->record_stream != NULL) { 177 audioGroup->record_stream->sample_rate = data->input.rate; 178 audioGroup->record_stream->sample_format = data->input.format; 179 audioGroup->record_stream->sample_size = format2size( 180 audioGroup->record_stream->sample_format); 181 } 182 183 return B_OK; 184 } 185 186 187 static status_t 188 list_mix_controls(hda_audio_group* audioGroup, multi_mix_control_info* data) 189 { 190 data->control_count = 0; 191 return B_OK; 192 } 193 194 195 static status_t 196 list_mix_connections(hda_audio_group* audioGroup, 197 multi_mix_connection_info* data) 198 { 199 data->actual_count = 0; 200 return B_OK; 201 } 202 203 204 static status_t 205 list_mix_channels(hda_audio_group* audioGroup, multi_mix_channel_info *data) 206 { 207 return B_OK; 208 } 209 210 211 static status_t 212 get_buffers(hda_audio_group* audioGroup, multi_buffer_list* data) 213 { 214 TRACE("playback: %ld buffers, %ld channels, %ld samples\n", 215 data->request_playback_buffers, data->request_playback_channels, 216 data->request_playback_buffer_size); 217 TRACE("record: %ld buffers, %ld channels, %ld samples\n", 218 data->request_record_buffers, data->request_record_channels, 219 data->request_record_buffer_size); 220 221 /* Determine what buffers we return given the request */ 222 223 data->return_playback_buffers = data->request_playback_buffers; 224 data->return_playback_channels = data->request_playback_channels; 225 data->return_playback_buffer_size = data->request_playback_buffer_size; 226 data->return_record_buffers = data->request_record_buffers; 227 data->return_record_channels = data->request_record_channels; 228 data->return_record_buffer_size = data->request_record_buffer_size; 229 230 /* Workaround for Haiku multi_audio API, since it prefers to let the 231 driver pick values, while the BeOS multi_audio actually gives the 232 user's defaults. */ 233 if (data->return_playback_buffers > STREAM_MAX_BUFFERS 234 || data->return_playback_buffers < STREAM_MIN_BUFFERS) 235 data->return_playback_buffers = STREAM_MIN_BUFFERS; 236 237 if (data->return_record_buffers > STREAM_MAX_BUFFERS 238 || data->return_record_buffers < STREAM_MIN_BUFFERS) 239 data->return_record_buffers = STREAM_MIN_BUFFERS; 240 241 if (data->return_playback_buffer_size == 0) 242 data->return_playback_buffer_size = DEFAULT_FRAMES_PER_BUFFER; 243 244 if (data->return_record_buffer_size == 0) 245 data->return_record_buffer_size = DEFAULT_FRAMES_PER_BUFFER; 246 247 /* ... from here on, we can assume again that a reasonable request is 248 being made */ 249 250 data->flags = B_MULTI_BUFFER_PLAYBACK; 251 252 /* Copy the settings into the streams */ 253 254 if (audioGroup->playback_stream != NULL) { 255 audioGroup->playback_stream->num_buffers = data->return_playback_buffers; 256 audioGroup->playback_stream->num_channels = data->return_playback_channels; 257 audioGroup->playback_stream->buffer_length 258 = data->return_playback_buffer_size; 259 260 status_t status = hda_stream_setup_buffers(audioGroup, 261 audioGroup->playback_stream, "Playback"); 262 if (status != B_OK) { 263 dprintf("hda: Error setting up playback buffers: %s\n", 264 strerror(status)); 265 return status; 266 } 267 } 268 269 if (audioGroup->record_stream != NULL) { 270 audioGroup->record_stream->num_buffers = data->return_record_buffers; 271 audioGroup->record_stream->num_channels = data->return_record_channels; 272 audioGroup->record_stream->buffer_length 273 = data->return_record_buffer_size; 274 275 status_t status = hda_stream_setup_buffers(audioGroup, 276 audioGroup->record_stream, "Recording"); 277 if (status != B_OK) { 278 dprintf("hda: Error setting up recording buffers: %s\n", 279 strerror(status)); 280 return status; 281 } 282 } 283 284 /* Setup data structure for multi_audio API... */ 285 286 if (audioGroup->playback_stream != NULL) { 287 uint32 playbackSampleSize = audioGroup->playback_stream->sample_size; 288 289 for (int32 i = 0; i < data->return_playback_buffers; i++) { 290 for (int32 channelIndex = 0; 291 channelIndex < data->return_playback_channels; channelIndex++) { 292 data->playback_buffers[i][channelIndex].base 293 = (char*)audioGroup->playback_stream->buffers[i] 294 + playbackSampleSize * channelIndex; 295 data->playback_buffers[i][channelIndex].stride 296 = playbackSampleSize * data->return_playback_channels; 297 } 298 } 299 } 300 301 if (audioGroup->record_stream != NULL) { 302 uint32 recordSampleSize = audioGroup->record_stream->sample_size; 303 304 for (int32 i = 0; i < data->return_record_buffers; i++) { 305 for (int32 channelIndex = 0; 306 channelIndex < data->return_record_channels; channelIndex++) { 307 data->record_buffers[i][channelIndex].base 308 = (char*)audioGroup->record_stream->buffers[i] 309 + recordSampleSize * channelIndex; 310 data->record_buffers[i][channelIndex].stride 311 = recordSampleSize * data->return_record_channels; 312 } 313 } 314 } 315 316 return B_OK; 317 } 318 319 320 /*! playback_buffer_cycle is the buffer we want to have played */ 321 static status_t 322 buffer_exchange(hda_audio_group* audioGroup, multi_buffer_info* data) 323 { 324 static int debug_buffers_exchanged = 0; 325 cpu_status status; 326 status_t rc; 327 328 // TODO: support recording! 329 if (audioGroup->playback_stream == NULL) 330 return B_ERROR; 331 332 if (!audioGroup->playback_stream->running) { 333 hda_stream_start(audioGroup->codec->controller, 334 audioGroup->playback_stream); 335 } 336 337 /* do playback */ 338 rc = acquire_sem_etc(audioGroup->playback_stream->buffer_ready_sem, 339 1, B_CAN_INTERRUPT, 0); 340 if (rc != B_OK) { 341 dprintf("%s: Error waiting for playback buffer to finish (%s)!\n", __func__, 342 strerror(rc)); 343 return rc; 344 } 345 346 status = disable_interrupts(); 347 acquire_spinlock(&audioGroup->playback_stream->lock); 348 349 data->playback_buffer_cycle = audioGroup->playback_stream->buffer_cycle; 350 data->played_real_time = audioGroup->playback_stream->real_time; 351 data->played_frames_count = audioGroup->playback_stream->frames_count; 352 353 release_spinlock(&audioGroup->playback_stream->lock); 354 restore_interrupts(status); 355 356 debug_buffers_exchanged++; 357 if (((debug_buffers_exchanged % 100) == 1) && (debug_buffers_exchanged < 1111)) { 358 dprintf("%s: %d buffers processed\n", __func__, debug_buffers_exchanged); 359 } 360 361 return B_OK; 362 } 363 364 365 static status_t 366 buffer_force_stop(hda_audio_group* audioGroup) 367 { 368 if (audioGroup->playback_stream != NULL) { 369 hda_stream_stop(audioGroup->codec->controller, 370 audioGroup->playback_stream); 371 } 372 //hda_stream_stop(audioGroup->codec->controller, audioGroup->record_stream); 373 374 return B_OK; 375 } 376 377 378 status_t 379 multi_audio_control(void* cookie, uint32 op, void* arg, size_t len) 380 { 381 hda_codec* codec = (hda_codec*)cookie; 382 hda_audio_group* audioGroup; 383 384 /* FIXME: We should simply pass the audioGroup into here... */ 385 if (!codec || codec->num_audio_groups == 0) 386 return ENODEV; 387 388 audioGroup = codec->audio_groups[0]; 389 390 // TODO: make userland-safe when built for Haiku! 391 392 switch (op) { 393 case B_MULTI_GET_DESCRIPTION: 394 { 395 #ifdef __HAIKU 396 multi_description description; 397 multi_channel_info channels[16]; 398 multi_channel_info* originalChannels; 399 400 if (user_memcpy(&description, arg, sizeof(multi_description)) 401 != B_OK) 402 return B_BAD_ADDRESS; 403 404 originalChannels = description.channels; 405 description.channels = channels; 406 if (description.request_channel_count > 16) 407 description.request_channel_count = 16; 408 409 status_t status = get_description(audioGroup, &description); 410 if (status != B_OK) 411 return status; 412 413 description.channels = originalChannels; 414 return user_memcpy(arg, &description, sizeof(multi_description)) 415 && user_memcpy(originalChannels, channels, 416 sizeof(multi_channel_info) 417 * description.request_channel_count; 418 #else 419 return get_description(audioGroup, (multi_description*)arg); 420 #endif 421 } 422 423 case B_MULTI_GET_ENABLED_CHANNELS: 424 return get_enabled_channels(audioGroup, (multi_channel_enable*)arg); 425 case B_MULTI_SET_ENABLED_CHANNELS: 426 return B_OK; 427 428 case B_MULTI_GET_GLOBAL_FORMAT: 429 return get_global_format(audioGroup, (multi_format_info*)arg); 430 case B_MULTI_SET_GLOBAL_FORMAT: 431 return set_global_format(audioGroup, (multi_format_info*)arg); 432 433 case B_MULTI_LIST_MIX_CHANNELS: 434 return list_mix_channels(audioGroup, (multi_mix_channel_info*)arg); 435 case B_MULTI_LIST_MIX_CONTROLS: 436 return list_mix_controls(audioGroup, (multi_mix_control_info*)arg); 437 case B_MULTI_LIST_MIX_CONNECTIONS: 438 return list_mix_connections(audioGroup, 439 (multi_mix_connection_info*)arg); 440 case B_MULTI_GET_BUFFERS: 441 return get_buffers(audioGroup, (multi_buffer_list*)arg); 442 443 case B_MULTI_BUFFER_EXCHANGE: 444 return buffer_exchange(audioGroup, (multi_buffer_info*)arg); 445 case B_MULTI_BUFFER_FORCE_STOP: 446 return buffer_force_stop(audioGroup); 447 448 case B_MULTI_GET_EVENT_INFO: 449 case B_MULTI_SET_EVENT_INFO: 450 case B_MULTI_GET_EVENT: 451 case B_MULTI_GET_CHANNEL_FORMATS: 452 case B_MULTI_SET_CHANNEL_FORMATS: 453 case B_MULTI_GET_MIX: 454 case B_MULTI_SET_MIX: 455 case B_MULTI_SET_BUFFERS: 456 case B_MULTI_SET_START_TIME: 457 return B_ERROR; 458 } 459 460 return B_BAD_VALUE; 461 } 462