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
format2size(uint32 format)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
get_description(geode_controller * controller,multi_description * data)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
get_enabled_channels(geode_controller * controller,multi_channel_enable * data)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
get_global_format(geode_controller * controller,multi_format_info * data)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
set_global_format(geode_controller * controller,multi_format_info * data)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
geode_ac97_get_mix(geode_controller * controller,const void * cookie,int32 type,float * values)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
geode_ac97_set_mix(geode_controller * controller,const void * cookie,int32 type,float * values)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
create_group_control(geode_multi * multi,uint32 * index,uint32 parent,strind_id string,const char * name)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
create_controls_list(geode_multi * multi)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
list_mix_controls(geode_controller * controller,multi_mix_control_info * mmci)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
list_mix_connections(geode_controller * controller,multi_mix_connection_info * data)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
list_mix_channels(geode_controller * controller,multi_mix_channel_info * data)554 list_mix_channels(geode_controller* controller, multi_mix_channel_info *data)
555 {
556 return B_OK;
557 }
558
559
560 static status_t
get_mix(geode_controller * controller,multi_mix_value_info * mmvi)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
set_mix(geode_controller * controller,multi_mix_value_info * mmvi)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
get_buffers(geode_controller * controller,multi_buffer_list * data)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
buffer_exchange(geode_controller * controller,multi_buffer_info * data)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
buffer_force_stop(geode_controller * controller)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
multi_audio_control(geode_controller * controller,uint32 op,void * arg,size_t len)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