1 #include "driver.h" 2 3 multi_channel_info chans[] = { 4 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 5 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 6 { 2, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 }, 7 { 3, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 }, 8 { 4, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 9 { 5, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 10 { 6, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 11 { 7, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO }, 12 }; 13 14 static int32 15 format2size(uint32 format) 16 { 17 switch(format) { 18 case B_FMT_8BIT_S: 19 case B_FMT_16BIT: 20 return 2; 21 22 default: 23 return -1; 24 } 25 } 26 27 static status_t 28 get_description(sb16_dev_t* dev, multi_description* data) 29 { 30 data->interface_version = B_CURRENT_INTERFACE_VERSION; 31 data->interface_minimum = B_CURRENT_INTERFACE_VERSION; 32 33 strcpy(data->friendly_name,"SoundBlaster 16"); 34 strcpy(data->vendor_info,"Haiku"); 35 36 data->output_channel_count = 2; 37 data->input_channel_count = 2; 38 data->output_bus_channel_count = 2; 39 data->input_bus_channel_count = 2; 40 data->aux_bus_channel_count = 0; 41 42 if (data->request_channel_count >= (int)(sizeof(chans) / sizeof(chans[0]))) { 43 memcpy(data->channels,&chans,sizeof(chans)); 44 } 45 46 /* determine output/input rates */ 47 data->output_rates = 48 data->input_rates = B_SR_44100 | B_SR_22050 | B_SR_11025; 49 50 data->max_cvsr_rate = 0; 51 data->min_cvsr_rate = 0; 52 53 data->output_formats = 54 data->input_formats = B_FMT_8BIT_S | B_FMT_16BIT; 55 data->lock_sources = B_MULTI_LOCK_INTERNAL; 56 data->timecode_sources = 0; 57 data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD; 58 data->start_latency = 30000; 59 60 strcpy(data->control_panel,""); 61 62 return B_OK; 63 } 64 65 static status_t 66 get_enabled_channels(sb16_dev_t* dev, multi_channel_enable* data) 67 { 68 B_SET_CHANNEL(data->enable_bits, 0, true); 69 B_SET_CHANNEL(data->enable_bits, 1, true); 70 B_SET_CHANNEL(data->enable_bits, 2, true); 71 B_SET_CHANNEL(data->enable_bits, 3, true); 72 data->lock_source = B_MULTI_LOCK_INTERNAL; 73 74 return B_OK; 75 } 76 77 static status_t 78 get_global_format(sb16_dev_t* dev, multi_format_info* data) 79 { 80 data->output_latency = 0; 81 data->input_latency = 0; 82 data->timecode_kind = 0; 83 84 data->output.format = dev->playback_stream.sampleformat; 85 data->output.rate = dev->playback_stream.samplerate; 86 87 data->input.format = dev->record_stream.sampleformat; 88 data->input.rate = dev->record_stream.samplerate; 89 90 return B_OK; 91 } 92 93 static status_t 94 set_global_format(sb16_dev_t* dev, multi_format_info* data) 95 { 96 dev->playback_stream.sampleformat = data->output.format; 97 dev->playback_stream.samplerate = data->output.rate; 98 dev->playback_stream.sample_size = format2size(dev->playback_stream.sampleformat); 99 100 dev->record_stream.sampleformat = data->input.format; 101 dev->record_stream.samplerate = data->input.rate; 102 dev->record_stream.sample_size = format2size(dev->record_stream.sampleformat); 103 104 return B_OK; 105 } 106 107 static int32 108 create_group_control(multi_mix_control* multi, int32 idx, int32 parent, int32 string, const char* name) 109 { 110 multi->id = SB16_MULTI_CONTROL_FIRSTID + idx; 111 multi->parent = parent; 112 multi->flags = B_MULTI_MIX_GROUP; 113 multi->master = SB16_MULTI_CONTROL_MASTERID; 114 multi->string = string; 115 if(name) 116 strcpy(multi->name, name); 117 118 return multi->id; 119 } 120 121 static status_t 122 list_mix_controls(sb16_dev_t* dev, multi_mix_control_info * data) 123 { 124 int32 parent; 125 126 parent = create_group_control(data->controls +0, 0, 0, 0, "Record"); 127 parent = create_group_control(data->controls +1, 1, 0, 0, "AC97 Mixer"); 128 parent = create_group_control(data->controls +2, 2, 0, S_SETUP, NULL); 129 data->control_count = 3; 130 131 return B_OK; 132 } 133 134 static status_t 135 list_mix_connections(sb16_dev_t* dev, multi_mix_connection_info * data) 136 { 137 return B_ERROR; 138 } 139 140 static status_t 141 list_mix_channels(sb16_dev_t* dev, multi_mix_channel_info *data) 142 { 143 return B_ERROR; 144 } 145 146 static status_t 147 get_buffers(sb16_dev_t* dev, multi_buffer_list* data) 148 { 149 uint32 playback_sample_size = dev->playback_stream.sample_size; 150 uint32 record_sample_size = dev->record_stream.sample_size; 151 int32 bidx; 152 int32 cidx; 153 status_t rc; 154 155 dprintf("%s: playback: %" B_PRId32 " buffers, %" B_PRIu32 " channels, %" B_PRIu32 " samples\n", 156 __func__, data->request_playback_buffers, data->request_playback_channels, 157 data->request_playback_buffer_size); 158 dprintf("%s: record: %" B_PRId32 " buffers, %" B_PRIu32 " channels, %" B_PRIu32 " samples\n", 159 __func__, data->request_record_buffers, data->request_record_channels, 160 data->request_record_buffer_size); 161 162 /* Workaround for Haiku multi_audio API, since it prefers to let the driver pick 163 values, while the BeOS multi_audio actually gives the user's defaults. */ 164 if (data->request_playback_buffers > STRMAXBUF || 165 data->request_playback_buffers < STRMINBUF) { 166 data->request_playback_buffers = STRMINBUF; 167 } 168 169 if (data->request_record_buffers > STRMAXBUF || 170 data->request_record_buffers < STRMINBUF) { 171 data->request_record_buffers = STRMINBUF; 172 } 173 174 if (data->request_playback_buffer_size == 0) 175 data->request_playback_buffer_size = DEFAULT_FRAMESPERBUF; 176 177 if (data->request_record_buffer_size == 0) 178 data->request_record_buffer_size = DEFAULT_FRAMESPERBUF; 179 180 /* ... from here on, we can assume again that a reasonable request is being made */ 181 182 data->flags = 0; 183 184 /* Copy the requested settings into the streams */ 185 dev->playback_stream.num_buffers = data->request_playback_buffers; 186 dev->playback_stream.num_channels = data->request_playback_channels; 187 dev->playback_stream.buffer_length = data->request_playback_buffer_size; 188 if ((rc=sb16_stream_setup_buffers(dev, &dev->playback_stream, "Playback")) != B_OK) { 189 dprintf("%s: Error setting up playback buffers (%s)\n", __func__, strerror(rc)); 190 return rc; 191 } 192 193 dev->record_stream.num_buffers = data->request_record_buffers; 194 dev->record_stream.num_channels = data->request_record_channels; 195 dev->record_stream.buffer_length = data->request_record_buffer_size; 196 if ((rc=sb16_stream_setup_buffers(dev, &dev->record_stream, "Recording")) != B_OK) { 197 dprintf("%s: Error setting up recording buffers (%s)\n", __func__, strerror(rc)); 198 return rc; 199 } 200 201 /* Setup data structure for multi_audio API... */ 202 data->return_playback_buffers = data->request_playback_buffers; 203 data->return_playback_channels = data->request_playback_channels; 204 data->return_playback_buffer_size = data->request_playback_buffer_size; /* frames */ 205 206 for (bidx=0; bidx < data->return_playback_buffers; bidx++) { 207 for (cidx=0; cidx < data->return_playback_channels; cidx++) { 208 data->playback_buffers[bidx][cidx].base 209 = (char*)dev->playback_stream.buffers[bidx] + (playback_sample_size * cidx); 210 data->playback_buffers[bidx][cidx].stride 211 = playback_sample_size * data->return_playback_channels; 212 } 213 } 214 215 data->return_record_buffers = data->request_record_buffers; 216 data->return_record_channels = data->request_record_channels; 217 data->return_record_buffer_size = data->request_record_buffer_size; /* frames */ 218 219 for (bidx=0; bidx < data->return_record_buffers; bidx++) { 220 for (cidx=0; cidx < data->return_record_channels; cidx++) { 221 data->record_buffers[bidx][cidx].base 222 = (char*)dev->record_stream.buffers[bidx] + (record_sample_size * cidx); 223 data->record_buffers[bidx][cidx].stride 224 = record_sample_size * data->return_record_channels; 225 } 226 } 227 228 return B_OK; 229 } 230 231 static status_t 232 buffer_exchange(sb16_dev_t* dev, multi_buffer_info* data) 233 { 234 static int debug_buffers_exchanged = 0; 235 cpu_status status; 236 status_t rc; 237 238 if (!dev->playback_stream.running) 239 sb16_stream_start(dev, &dev->playback_stream); 240 241 /* do playback */ 242 rc=acquire_sem(dev->playback_stream.buffer_ready_sem); 243 if (rc != B_OK) { 244 dprintf("%s: Error waiting for playback buffer to finish (%s)!\n", __func__, 245 strerror(rc)); 246 return rc; 247 } 248 249 status = disable_interrupts(); 250 acquire_spinlock(&dev->playback_stream.lock); 251 252 data->playback_buffer_cycle = dev->playback_stream.buffer_cycle; 253 data->played_real_time = dev->playback_stream.real_time; 254 data->played_frames_count = dev->playback_stream.frames_count; 255 256 release_spinlock(&dev->playback_stream.lock); 257 restore_interrupts(status); 258 259 debug_buffers_exchanged++; 260 if (((debug_buffers_exchanged % 100) == 1) && (debug_buffers_exchanged < 1111)) { 261 dprintf("%s: %d buffers processed\n", __func__, debug_buffers_exchanged); 262 } 263 264 return B_OK; 265 } 266 267 static status_t 268 buffer_force_stop(sb16_dev_t* dev) 269 { 270 sb16_stream_stop(dev, &dev->playback_stream); 271 sb16_stream_stop(dev, &dev->record_stream); 272 273 delete_sem(dev->playback_stream.buffer_ready_sem); 274 delete_sem(dev->record_stream.buffer_ready_sem); 275 276 return B_OK; 277 } 278 279 status_t 280 multi_audio_control(void* cookie, uint32 op, void* arg, size_t len) 281 { 282 switch(op) { 283 case B_MULTI_GET_DESCRIPTION: return get_description(cookie, arg); 284 case B_MULTI_GET_EVENT_INFO: return B_ERROR; 285 case B_MULTI_SET_EVENT_INFO: return B_ERROR; 286 case B_MULTI_GET_EVENT: return B_ERROR; 287 case B_MULTI_GET_ENABLED_CHANNELS: return get_enabled_channels(cookie, arg); 288 case B_MULTI_SET_ENABLED_CHANNELS: return B_OK; 289 case B_MULTI_GET_GLOBAL_FORMAT: return get_global_format(cookie, arg); 290 case B_MULTI_SET_GLOBAL_FORMAT: return set_global_format(cookie, arg); 291 case B_MULTI_GET_CHANNEL_FORMATS: return B_ERROR; 292 case B_MULTI_SET_CHANNEL_FORMATS: return B_ERROR; 293 case B_MULTI_GET_MIX: return B_ERROR; 294 case B_MULTI_SET_MIX: return B_ERROR; 295 case B_MULTI_LIST_MIX_CHANNELS: return list_mix_channels(cookie, arg); 296 case B_MULTI_LIST_MIX_CONTROLS: return list_mix_controls(cookie, arg); 297 case B_MULTI_LIST_MIX_CONNECTIONS: return list_mix_connections(cookie, arg); 298 case B_MULTI_GET_BUFFERS: return get_buffers(cookie, arg); 299 case B_MULTI_SET_BUFFERS: return B_ERROR; 300 case B_MULTI_SET_START_TIME: return B_ERROR; 301 case B_MULTI_BUFFER_EXCHANGE: return buffer_exchange(cookie, arg); 302 case B_MULTI_BUFFER_FORCE_STOP: return buffer_force_stop(cookie); 303 } 304 305 return B_BAD_VALUE; 306 } 307