1 /*
2 * Auvia BeOS Driver for Via VT82xx Southbridge audio
3 *
4 * Copyright (c) 2003, Jerome Duval (jerome.duval@free.fr)
5 *
6 * Original code : BeOS Driver for Intel ICH AC'97 Link interface
7 * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
8 *
9 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without modification,
11 * are permitted provided that the following conditions are met:
12 *
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32 #include <OS.h>
33 #include <string.h>
34 #include <MediaDefs.h>
35 #include "hmulti_audio.h"
36 #include "multi.h"
37 #include "ac97.h"
38
39 //#define DEBUG 1
40
41 #include "debug.h"
42 #include "auvia.h"
43 #include "util.h"
44 #include "io.h"
45
46
47 static void
auvia_ac97_get_mix(void * card,const void * cookie,int32 type,float * values)48 auvia_ac97_get_mix(void *card, const void *cookie, int32 type, float *values) {
49 auvia_dev *dev = (auvia_dev*)card;
50 ac97_source_info *info = (ac97_source_info *)cookie;
51 uint16 value, mask;
52 float gain;
53
54 switch (type) {
55 case B_MIX_GAIN:
56 value = auvia_codec_read(&dev->config, info->reg);
57 //PRINT(("B_MIX_GAIN value : %u\n", value));
58 if (info->type & B_MIX_STEREO) {
59 mask = ((1 << (info->bits + 1)) - 1) << 8;
60 gain = ((value & mask) >> 8) * info->granularity;
61 if (info->polarity == 1)
62 values[0] = info->max_gain - gain;
63 else
64 values[0] = gain - info->min_gain;
65
66 mask = ((1 << (info->bits + 1)) - 1);
67 gain = (value & mask) * info->granularity;
68 if (info->polarity == 1)
69 values[1] = info->max_gain - gain;
70 else
71 values[1] = gain - info->min_gain;
72 } else {
73 mask = ((1 << (info->bits + 1)) - 1);
74 gain = (value & mask) * info->granularity;
75 if (info->polarity == 1)
76 values[0] = info->max_gain - gain;
77 else
78 values[0] = gain - info->min_gain;
79 }
80 break;
81 case B_MIX_MUTE:
82 mask = ((1 << 1) - 1) << 15;
83 value = auvia_codec_read(&dev->config, info->reg);
84 //PRINT(("B_MIX_MUTE value : %u\n", value));
85 value &= mask;
86 values[0] = ((value >> 15) == 1) ? 1.0 : 0.0;
87 break;
88 case B_MIX_MICBOOST:
89 mask = ((1 << 1) - 1) << 6;
90 value = auvia_codec_read(&dev->config, info->reg);
91 //PRINT(("B_MIX_MICBOOST value : %u\n", value));
92 value &= mask;
93 values[0] = ((value >> 6) == 1) ? 1.0 : 0.0;
94 break;
95 case B_MIX_MUX:
96 mask = ((1 << 3) - 1);
97 value = auvia_codec_read(&dev->config, AC97_RECORD_SELECT);
98 value &= mask;
99 //PRINT(("B_MIX_MUX value : %u\n", value));
100 values[0] = (float)value;
101 break;
102 }
103 }
104
105 static void
auvia_ac97_set_mix(void * card,const void * cookie,int32 type,float * values)106 auvia_ac97_set_mix(void *card, const void *cookie, int32 type, float *values) {
107 auvia_dev *dev = (auvia_dev*)card;
108 ac97_source_info *info = (ac97_source_info *)cookie;
109 uint16 value, mask;
110 float gain;
111
112 switch (type) {
113 case B_MIX_GAIN:
114 value = auvia_codec_read(&dev->config, info->reg);
115 if (info->type & B_MIX_STEREO) {
116 mask = ((1 << (info->bits + 1)) - 1) << 8;
117 value &= ~mask;
118
119 if (info->polarity == 1)
120 gain = info->max_gain - values[0];
121 else
122 gain = values[0] - info->min_gain;
123 value |= ((uint16)(gain / info->granularity) << 8) & mask;
124
125 mask = ((1 << (info->bits + 1)) - 1);
126 value &= ~mask;
127 if (info->polarity == 1)
128 gain = info->max_gain - values[1];
129 else
130 gain = values[1] - info->min_gain;
131 value |= ((uint16)(gain / info->granularity)) & mask;
132 } else {
133 mask = ((1 << (info->bits + 1)) - 1);
134 value &= ~mask;
135 if (info->polarity == 1)
136 gain = info->max_gain - values[0];
137 else
138 gain = values[0] - info->min_gain;
139 value |= ((uint16)(gain / info->granularity)) & mask;
140 }
141 //PRINT(("B_MIX_GAIN value : %u\n", value));
142 auvia_codec_write(&dev->config, info->reg, value);
143 break;
144 case B_MIX_MUTE:
145 mask = ((1 << 1) - 1) << 15;
146 value = auvia_codec_read(&dev->config, info->reg);
147 value &= ~mask;
148 value |= ((values[0] == 1.0 ? 1 : 0 ) << 15 & mask);
149 if (info->reg == AC97_SURR_VOLUME) {
150 // there is a independent mute for each channel
151 mask = ((1 << 1) - 1) << 7;
152 value &= ~mask;
153 value |= ((values[0] == 1.0 ? 1 : 0 ) << 7 & mask);
154 }
155 //PRINT(("B_MIX_MUTE value : %u\n", value));
156 auvia_codec_write(&dev->config, info->reg, value);
157 break;
158 case B_MIX_MICBOOST:
159 mask = ((1 << 1) - 1) << 6;
160 value = auvia_codec_read(&dev->config, info->reg);
161 value &= ~mask;
162 value |= ((values[0] == 1.0 ? 1 : 0 ) << 6 & mask);
163 //PRINT(("B_MIX_MICBOOST value : %u\n", value));
164 auvia_codec_write(&dev->config, info->reg, value);
165 break;
166 case B_MIX_MUX:
167 mask = ((1 << 3) - 1);
168 value = ((int32)values[0]) & mask;
169 value = value | (value << 8);
170 //PRINT(("B_MIX_MUX value : %u\n", value));
171 auvia_codec_write(&dev->config, AC97_RECORD_SELECT, value);
172 break;
173 }
174
175 }
176
177
178 static int32
auvia_create_group_control(multi_dev * multi,uint32 * index,int32 parent,int32 string,const char * name)179 auvia_create_group_control(multi_dev* multi, uint32* index, int32 parent, int32 string,
180 const char* name)
181 {
182 int32 i = *index;
183 (*index)++;
184 multi->controls[i].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + i;
185 multi->controls[i].mix_control.parent = parent;
186 multi->controls[i].mix_control.flags = B_MULTI_MIX_GROUP;
187 multi->controls[i].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
188 multi->controls[i].mix_control.string = string;
189 if (name) {
190 strlcpy(multi->controls[i].mix_control.name, name,
191 sizeof(multi->controls[i].mix_control.name));
192 }
193
194 return multi->controls[i].mix_control.id;
195 }
196
197
198 static status_t
auvia_create_controls_list(multi_dev * multi)199 auvia_create_controls_list(multi_dev *multi)
200 {
201 uint32 i = 0, index = 0, count, id, parent, parent2, parent3;
202 const ac97_source_info *info;
203
204 parent = auvia_create_group_control(multi, &index, 0, 0, "Record");
205
206 /* AC97 Record */
207 info = &source_info[0];
208 PRINT(("name : %s\n", info->name));
209
210 parent2 = auvia_create_group_control(multi, &index, parent, 0, info->name);
211
212 if (info->type & B_MIX_GAIN) {
213 if (info->type & B_MIX_MUTE) {
214 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
215 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE;
216 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
217 multi->controls[index].mix_control.parent = parent2;
218 multi->controls[index].mix_control.string = S_MUTE;
219 multi->controls[index].cookie = info;
220 multi->controls[index].type = B_MIX_MUTE;
221 multi->controls[index].get = &auvia_ac97_get_mix;
222 multi->controls[index].set = &auvia_ac97_set_mix;
223 index++;
224 }
225
226 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
227 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN;
228 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
229 multi->controls[index].mix_control.parent = parent2;
230 strlcpy(multi->controls[index].mix_control.name, info->name,
231 sizeof(multi->controls[index].mix_control.name));
232 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain;
233 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain;
234 multi->controls[index].mix_control.u.gain.granularity = info->granularity;
235 multi->controls[index].cookie = info;
236 multi->controls[index].type = B_MIX_GAIN;
237 multi->controls[index].get = &auvia_ac97_get_mix;
238 multi->controls[index].set = &auvia_ac97_set_mix;
239 id = multi->controls[index].mix_control.id;
240 index++;
241
242 if (info->type & B_MIX_STEREO) {
243 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
244 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN;
245 multi->controls[index].mix_control.master = id;
246 multi->controls[index].mix_control.parent = parent2;
247 strlcpy(multi->controls[index].mix_control.name, info->name,
248 sizeof(multi->controls[index].mix_control.name));
249 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain;
250 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain;
251 multi->controls[index].mix_control.u.gain.granularity = info->granularity;
252 multi->controls[index].cookie = info;
253 multi->controls[index].type = B_MIX_GAIN;
254 multi->controls[index].get = &auvia_ac97_get_mix;
255 multi->controls[index].set = &auvia_ac97_set_mix;
256 index++;
257 }
258
259 if (info->type & B_MIX_RECORDMUX) {
260 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
261 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX;
262 multi->controls[index].mix_control.parent = parent2;
263 strcpy(multi->controls[index].mix_control.name, "Record mux");
264 multi->controls[index].cookie = info;
265 multi->controls[index].type = B_MIX_MUX;
266 multi->controls[index].get = &auvia_ac97_get_mix;
267 multi->controls[index].set = &auvia_ac97_set_mix;
268 parent3 = multi->controls[index].mix_control.id;
269 index++;
270
271 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
272 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
273 multi->controls[index].mix_control.parent = parent3;
274 multi->controls[index].mix_control.string = S_MIC;
275 index++;
276 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
277 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
278 multi->controls[index].mix_control.parent = parent3;
279 strcpy(multi->controls[index].mix_control.name, "CD in");
280 index++;
281 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
282 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
283 multi->controls[index].mix_control.parent = parent3;
284 strcpy(multi->controls[index].mix_control.name, "Video in");
285 index++;
286 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
287 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
288 multi->controls[index].mix_control.parent = parent3;
289 strcpy(multi->controls[index].mix_control.name, "Aux in");
290 index++;
291 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
292 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
293 multi->controls[index].mix_control.parent = parent3;
294 strcpy(multi->controls[index].mix_control.name, "Line in");
295 index++;
296 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
297 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
298 multi->controls[index].mix_control.parent = parent3;
299 multi->controls[index].mix_control.string = S_STEREO_MIX;
300 index++;
301 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
302 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
303 multi->controls[index].mix_control.parent = parent3;
304 multi->controls[index].mix_control.string = S_MONO_MIX;
305 index++;
306 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
307 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
308 multi->controls[index].mix_control.parent = parent3;
309 strcpy(multi->controls[index].mix_control.name, "TAD");
310 index++;
311 }
312 }
313
314 parent = auvia_create_group_control(multi, &index, 0, 0, "AC97 mixer");
315
316 count = source_info_size;
317 count--;
318
319 for (i = 1; i < count ; i++) {
320 info = &source_info[i];
321 PRINT(("name : %s\n", info->name));
322
323 parent2 = auvia_create_group_control(multi, &index, parent, 0, info->name);
324
325 if (info->type & B_MIX_GAIN) {
326 if (info->type & B_MIX_MUTE) {
327 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
328 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE;
329 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
330 multi->controls[index].mix_control.parent = parent2;
331 multi->controls[index].mix_control.string = S_MUTE;
332 multi->controls[index].cookie = info;
333 multi->controls[index].type = B_MIX_MUTE;
334 multi->controls[index].get = &auvia_ac97_get_mix;
335 multi->controls[index].set = &auvia_ac97_set_mix;
336 index++;
337 }
338
339 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
340 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN;
341 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
342 multi->controls[index].mix_control.parent = parent2;
343 strlcpy(multi->controls[index].mix_control.name, info->name,
344 sizeof(multi->controls[index].mix_control.name));
345 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain;
346 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain;
347 multi->controls[index].mix_control.u.gain.granularity = info->granularity;
348 multi->controls[index].cookie = info;
349 multi->controls[index].type = B_MIX_GAIN;
350 multi->controls[index].get = &auvia_ac97_get_mix;
351 multi->controls[index].set = &auvia_ac97_set_mix;
352 id = multi->controls[index].mix_control.id;
353 index++;
354
355 if (info->type & B_MIX_STEREO) {
356 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
357 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN;
358 multi->controls[index].mix_control.master = id;
359 multi->controls[index].mix_control.parent = parent2;
360 strlcpy(multi->controls[index].mix_control.name, info->name,
361 sizeof(multi->controls[index].mix_control.name));
362 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain;
363 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain;
364 multi->controls[index].mix_control.u.gain.granularity = info->granularity;
365 multi->controls[index].cookie = info;
366 multi->controls[index].type = B_MIX_GAIN;
367 multi->controls[index].get = &auvia_ac97_get_mix;
368 multi->controls[index].set = &auvia_ac97_set_mix;
369 index++;
370 }
371 }
372 }
373
374 parent = auvia_create_group_control(multi, &index, 0, S_SETUP, NULL);
375
376 /* AC97 20db Boost Mic */
377 info = &source_info[6];
378
379 if (info->type & B_MIX_GAIN && info->type & B_MIX_MICBOOST) {
380 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
381 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE;
382 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
383 multi->controls[index].mix_control.parent = parent;
384 strcpy(multi->controls[index].mix_control.name, "Mic +20dB");
385 multi->controls[index].cookie = info;
386 multi->controls[index].type = B_MIX_MICBOOST;
387 multi->controls[index].get = &auvia_ac97_get_mix;
388 multi->controls[index].set = &auvia_ac97_set_mix;
389 index++;
390 }
391
392 multi->control_count = index;
393 PRINT(("multi->control_count %" B_PRIu32 "\n", multi->control_count));
394 return B_OK;
395 }
396
397
398 static status_t
auvia_get_mix(auvia_dev * card,multi_mix_value_info * mmvi)399 auvia_get_mix(auvia_dev *card, multi_mix_value_info * mmvi)
400 {
401 int32 i, id;
402 multi_mixer_control *control = NULL;
403 for (i = 0; i < mmvi->item_count; i++) {
404 id = mmvi->values[i].id - EMU_MULTI_CONTROL_FIRSTID;
405 if (id < 0 || (uint32)id >= card->multi.control_count) {
406 PRINT(("auvia_get_mix : "
407 "invalid control id requested : %" B_PRIi32 "\n", id));
408 continue;
409 }
410 control = &card->multi.controls[id];
411
412 if (control->mix_control.flags & B_MULTI_MIX_GAIN) {
413 if (control->get) {
414 float values[2];
415 control->get(card, control->cookie, control->type, values);
416 if (control->mix_control.master == EMU_MULTI_CONTROL_MASTERID)
417 mmvi->values[i].u.gain = values[0];
418 else
419 mmvi->values[i].u.gain = values[1];
420 }
421 }
422
423 if (control->mix_control.flags & B_MULTI_MIX_ENABLE && control->get) {
424 float values[1];
425 control->get(card, control->cookie, control->type, values);
426 mmvi->values[i].u.enable = (values[0] == 1.0);
427 }
428
429 if (control->mix_control.flags & B_MULTI_MIX_MUX && control->get) {
430 float values[1];
431 control->get(card, control->cookie, control->type, values);
432 mmvi->values[i].u.mux = (int32)values[0];
433 }
434 }
435 return B_OK;
436 }
437
438
439 static status_t
auvia_set_mix(auvia_dev * card,multi_mix_value_info * mmvi)440 auvia_set_mix(auvia_dev *card, multi_mix_value_info * mmvi)
441 {
442 int32 i, id;
443 multi_mixer_control *control = NULL;
444 for (i = 0; i < mmvi->item_count; i++) {
445 id = mmvi->values[i].id - EMU_MULTI_CONTROL_FIRSTID;
446 if (id < 0 || (uint32)id >= card->multi.control_count) {
447 PRINT(("auvia_set_mix : "
448 "invalid control id requested : %" B_PRIi32 "\n", id));
449 continue;
450 }
451 control = &card->multi.controls[id];
452
453 if (control->mix_control.flags & B_MULTI_MIX_GAIN) {
454 multi_mixer_control *control2 = NULL;
455 if (i + 1 < mmvi->item_count) {
456 id = mmvi->values[i + 1].id - EMU_MULTI_CONTROL_FIRSTID;
457 if (id < 0 || (uint32)id >= card->multi.control_count) {
458 PRINT(("auvia_set_mix : "
459 "invalid control id requested : %" B_PRIi32 "\n", id));
460 } else {
461 control2 = &card->multi.controls[id];
462 if (control2->mix_control.master != control->mix_control.id)
463 control2 = NULL;
464 }
465 }
466
467 if (control->set) {
468 float values[2];
469 values[0] = 0.0;
470 values[1] = 0.0;
471
472 if (control->mix_control.master == EMU_MULTI_CONTROL_MASTERID)
473 values[0] = mmvi->values[i].u.gain;
474 else
475 values[1] = mmvi->values[i].u.gain;
476
477 if (control2 && control2->mix_control.master != EMU_MULTI_CONTROL_MASTERID)
478 values[1] = mmvi->values[i + 1].u.gain;
479
480 control->set(card, control->cookie, control->type, values);
481 }
482
483 if (control2)
484 i++;
485 }
486
487 if (control->mix_control.flags & B_MULTI_MIX_ENABLE && control->set) {
488 float values[1];
489
490 values[0] = mmvi->values[i].u.enable ? 1.0 : 0.0;
491 control->set(card, control->cookie, control->type, values);
492 }
493
494 if (control->mix_control.flags & B_MULTI_MIX_MUX && control->set) {
495 float values[1];
496
497 values[0] = (float)mmvi->values[i].u.mux;
498 control->set(card, control->cookie, control->type, values);
499 }
500 }
501 return B_OK;
502 }
503
504
505 static status_t
auvia_list_mix_controls(auvia_dev * card,multi_mix_control_info * mmci)506 auvia_list_mix_controls(auvia_dev *card, multi_mix_control_info * mmci)
507 {
508 multi_mix_control *mmc;
509 uint32 i;
510
511 mmc = mmci->controls;
512 if (mmci->control_count < 24)
513 return B_ERROR;
514
515 if (auvia_create_controls_list(&card->multi) < B_OK)
516 return B_ERROR;
517 for (i = 0; i < card->multi.control_count; i++) {
518 mmc[i] = card->multi.controls[i].mix_control;
519 }
520
521 mmci->control_count = card->multi.control_count;
522 return B_OK;
523 }
524
525
526 static status_t
auvia_list_mix_connections(auvia_dev * card,multi_mix_connection_info * data)527 auvia_list_mix_connections(auvia_dev *card, multi_mix_connection_info * data)
528 {
529 return B_ERROR;
530 }
531
532
533 static status_t
auvia_list_mix_channels(auvia_dev * card,multi_mix_channel_info * data)534 auvia_list_mix_channels(auvia_dev *card, multi_mix_channel_info *data)
535 {
536 return B_ERROR;
537 }
538
539 /*multi_channel_info chans[] = {
540 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
541 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
542 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
543 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
544 { 4, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
545 { 5, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
546 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
547 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
548 { 8, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
549 { 9, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
550 { 10, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
551 { 11, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
552 };*/
553
554 /*multi_channel_info chans[] = {
555 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
556 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
557 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_SURROUND_BUS, 0 },
558 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_SURROUND_BUS, 0 },
559 { 4, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARLEFT | B_CHANNEL_SURROUND_BUS, 0 },
560 { 5, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARRIGHT | B_CHANNEL_SURROUND_BUS, 0 },
561 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
562 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
563 { 8, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
564 { 9, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
565 { 10, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
566 { 11, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
567 { 12, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
568 { 13, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
569 };*/
570
571
572 static void
auvia_create_channels_list(multi_dev * multi)573 auvia_create_channels_list(multi_dev *multi)
574 {
575 auvia_stream *stream;
576 uint32 index, i, designations;
577 int32 mode;
578 multi_channel_info *chans;
579 uint32 chan_designations[] = {
580 B_CHANNEL_LEFT,
581 B_CHANNEL_RIGHT,
582 B_CHANNEL_REARLEFT,
583 B_CHANNEL_REARRIGHT,
584 B_CHANNEL_CENTER,
585 B_CHANNEL_SUB
586 };
587
588 chans = multi->chans;
589 index = 0;
590
591 for (mode = AUVIA_USE_PLAY; mode != -1;
592 mode = (mode == AUVIA_USE_PLAY) ? AUVIA_USE_RECORD : -1) {
593 LIST_FOREACH(stream, &((auvia_dev*)multi->card)->streams, next) {
594 if ((stream->use & mode) == 0)
595 continue;
596
597 if (stream->channels == 2)
598 designations = B_CHANNEL_STEREO_BUS;
599 else
600 designations = B_CHANNEL_SURROUND_BUS;
601
602 for (i = 0; i < stream->channels; i++) {
603 chans[index].channel_id = index;
604 chans[index].kind =
605 (mode == AUVIA_USE_PLAY) ? B_MULTI_OUTPUT_CHANNEL : B_MULTI_INPUT_CHANNEL;
606 chans[index].designations = designations | chan_designations[i];
607 chans[index].connectors = 0;
608 index++;
609 }
610 }
611
612 if (mode == AUVIA_USE_PLAY) {
613 multi->output_channel_count = index;
614 } else {
615 multi->input_channel_count = index - multi->output_channel_count;
616 }
617 }
618
619 chans[index].channel_id = index;
620 chans[index].kind = B_MULTI_OUTPUT_BUS;
621 chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS;
622 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
623 index++;
624
625 chans[index].channel_id = index;
626 chans[index].kind = B_MULTI_OUTPUT_BUS;
627 chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS;
628 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
629 index++;
630
631 multi->output_bus_channel_count = index - multi->output_channel_count
632 - multi->input_channel_count;
633
634 chans[index].channel_id = index;
635 chans[index].kind = B_MULTI_INPUT_BUS;
636 chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS;
637 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
638 index++;
639
640 chans[index].channel_id = index;
641 chans[index].kind = B_MULTI_INPUT_BUS;
642 chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS;
643 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
644 index++;
645
646 multi->input_bus_channel_count = index - multi->output_channel_count
647 - multi->input_channel_count - multi->output_bus_channel_count;
648
649 multi->aux_bus_channel_count = 0;
650 }
651
652
653 static status_t
auvia_get_description(auvia_dev * card,multi_description * data)654 auvia_get_description(auvia_dev *card, multi_description *data)
655 {
656 uint32 size;
657
658 data->interface_version = B_CURRENT_INTERFACE_VERSION;
659 data->interface_minimum = B_CURRENT_INTERFACE_VERSION;
660
661 if (IS_686(&card->config))
662 strncpy(data->friendly_name, FRIENDLY_NAME_686, 32);
663 else if (IS_8233(&card->config)) {
664 switch (card->info.revision) {
665 case VIATECH_8233_AC97_REV_8233_10:
666 strncpy(data->friendly_name, FRIENDLY_NAME_8233, 32);
667 break;
668 case VIATECH_8233_AC97_REV_8233C:
669 strncpy(data->friendly_name, FRIENDLY_NAME_8233C, 32);
670 break;
671 case VIATECH_8233_AC97_REV_8233:
672 strncpy(data->friendly_name, FRIENDLY_NAME_8233, 32);
673 break;
674 case VIATECH_8233_AC97_REV_8233A:
675 strncpy(data->friendly_name, FRIENDLY_NAME_8233A, 32);
676 break;
677 case VIATECH_8233_AC97_REV_8235:
678 strncpy(data->friendly_name, FRIENDLY_NAME_8235, 32);
679 break;
680 case VIATECH_8233_AC97_REV_8237:
681 strncpy(data->friendly_name, FRIENDLY_NAME_8237, 32);
682 break;
683 default:
684 strncpy(data->friendly_name, FRIENDLY_NAME, 32);
685 }
686 }
687 strcpy(data->vendor_info, AUTHOR);
688
689 /*data->output_channel_count = 6;
690 data->input_channel_count = 4;
691 data->output_bus_channel_count = 2;
692 data->input_bus_channel_count = 2;
693 data->aux_bus_channel_count = 0;*/
694
695 data->output_channel_count = card->multi.output_channel_count;
696 data->input_channel_count = card->multi.input_channel_count;
697 data->output_bus_channel_count = card->multi.output_bus_channel_count;
698 data->input_bus_channel_count = card->multi.input_bus_channel_count;
699 data->aux_bus_channel_count = card->multi.aux_bus_channel_count;
700
701 size = card->multi.output_channel_count + card->multi.input_channel_count
702 + card->multi.output_bus_channel_count + card->multi.input_bus_channel_count
703 + card->multi.aux_bus_channel_count;
704
705 // for each channel, starting with the first output channel,
706 // then the second, third..., followed by the first input
707 // channel, second, third, ..., followed by output bus
708 // channels and input bus channels and finally auxillary channels,
709
710 LOG(("request_channel_count = %d\n",data->request_channel_count));
711 if (data->request_channel_count >= (int32)size) {
712 LOG(("copying data\n"));
713 memcpy(data->channels, card->multi.chans, size * sizeof(card->multi.chans[0]));
714 }
715
716 data->output_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR;
717 data->input_rates = B_SR_48000;// | B_SR_44100 | B_SR_CVSR;
718 //data->output_rates = B_SR_44100;
719 //data->input_rates = B_SR_44100;
720 data->min_cvsr_rate = 0;
721 data->max_cvsr_rate = 48000;
722 //data->max_cvsr_rate = 44100;
723
724 data->output_formats = B_FMT_16BIT;
725 data->input_formats = B_FMT_16BIT;
726 data->lock_sources = B_MULTI_LOCK_INTERNAL;
727 data->timecode_sources = 0;
728 data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD;
729 data->start_latency = 3000;
730
731 strcpy(data->control_panel, "");
732
733 return B_OK;
734 }
735
736
737 static status_t
auvia_get_enabled_channels(auvia_dev * card,multi_channel_enable * data)738 auvia_get_enabled_channels(auvia_dev *card, multi_channel_enable *data)
739 {
740 B_SET_CHANNEL(data->enable_bits, 0, true);
741 B_SET_CHANNEL(data->enable_bits, 1, true);
742 B_SET_CHANNEL(data->enable_bits, 2, true);
743 B_SET_CHANNEL(data->enable_bits, 3, true);
744 data->lock_source = B_MULTI_LOCK_INTERNAL;
745 /*
746 uint32 lock_source;
747 int32 lock_data;
748 uint32 timecode_source;
749 uint32 * connectors;
750 */
751 return B_OK;
752 }
753
754
755 static status_t
auvia_set_enabled_channels(auvia_dev * card,multi_channel_enable * data)756 auvia_set_enabled_channels(auvia_dev *card, multi_channel_enable *data)
757 {
758 PRINT(("set_enabled_channels 0 : %s\n", B_TEST_CHANNEL(data->enable_bits, 0) ? "enabled": "disabled"));
759 PRINT(("set_enabled_channels 1 : %s\n", B_TEST_CHANNEL(data->enable_bits, 1) ? "enabled": "disabled"));
760 PRINT(("set_enabled_channels 2 : %s\n", B_TEST_CHANNEL(data->enable_bits, 2) ? "enabled": "disabled"));
761 PRINT(("set_enabled_channels 3 : %s\n", B_TEST_CHANNEL(data->enable_bits, 3) ? "enabled": "disabled"));
762 return B_OK;
763 }
764
765
766 static status_t
auvia_get_global_format(auvia_dev * card,multi_format_info * data)767 auvia_get_global_format(auvia_dev *card, multi_format_info *data)
768 {
769 data->output_latency = 0;
770 data->input_latency = 0;
771 data->timecode_kind = 0;
772 data->input.rate = B_SR_48000;
773 data->input.cvsr = 48000;
774 data->input.format = B_FMT_16BIT;
775 data->output.rate = B_SR_48000;
776 data->output.cvsr = 48000;
777 data->output.format = B_FMT_16BIT;
778 /*data->input.rate = B_SR_44100;
779 data->input.cvsr = 44100;
780 data->input.format = B_FMT_16BIT;
781 data->output.rate = B_SR_44100;
782 data->output.cvsr = 44100;
783 data->output.format = B_FMT_16BIT;*/
784 return B_OK;
785 }
786
787
788 static status_t
auvia_get_buffers(auvia_dev * card,multi_buffer_list * data)789 auvia_get_buffers(auvia_dev *card, multi_buffer_list *data)
790 {
791 uint32 i, j, pchannels, rchannels;
792
793 LOG(("flags = %#x\n",data->flags));
794 LOG(("request_playback_buffers = %#x\n",data->request_playback_buffers));
795 LOG(("request_playback_channels = %#x\n",data->request_playback_channels));
796 LOG(("request_playback_buffer_size = %#x\n",data->request_playback_buffer_size));
797 LOG(("request_record_buffers = %#x\n",data->request_record_buffers));
798 LOG(("request_record_channels = %#x\n",data->request_record_channels));
799 LOG(("request_record_buffer_size = %#x\n",data->request_record_buffer_size));
800
801 pchannels = card->pstream->channels;
802 rchannels = card->rstream->channels;
803
804 if (data->request_playback_buffers < BUFFER_COUNT
805 || data->request_playback_channels < (int32)(pchannels)
806 || data->request_record_buffers < BUFFER_COUNT
807 || data->request_record_channels < (int32)(rchannels)) {
808 LOG(("not enough channels/buffers\n"));
809 }
810
811 ASSERT(BUFFER_COUNT == 2);
812
813 data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; // XXX ???
814 // data->flags = 0;
815
816 data->return_playback_buffers = BUFFER_COUNT; /* playback_buffers[b][] */
817 data->return_playback_channels = pchannels; /* playback_buffers[][c] */
818 data->return_playback_buffer_size = BUFFER_FRAMES; /* frames */
819
820 for (i = 0; i < BUFFER_COUNT; i++)
821 for (j = 0; j < pchannels; j++)
822 auvia_stream_get_nth_buffer(card->pstream, j, i,
823 &data->playback_buffers[i][j].base,
824 &data->playback_buffers[i][j].stride);
825
826 data->return_record_buffers = BUFFER_COUNT;
827 data->return_record_channels = rchannels;
828 data->return_record_buffer_size = BUFFER_FRAMES; /* frames */
829
830 for (i = 0; i < BUFFER_COUNT; i++)
831 for (j = 0; j<rchannels; j++)
832 auvia_stream_get_nth_buffer(card->rstream, j, i,
833 &data->record_buffers[i][j].base,
834 &data->record_buffers[i][j].stride);
835
836 return B_OK;
837 }
838
839
840 static void
auvia_play_inth(void * inthparams)841 auvia_play_inth(void* inthparams)
842 {
843 auvia_stream *stream = (auvia_stream *)inthparams;
844 //int32 count;
845
846 //TRACE(("auvia_play_inth\n"));
847
848 acquire_spinlock(&slock);
849 stream->real_time = system_time();
850 stream->frames_count += BUFFER_FRAMES;
851 stream->buffer_cycle = (stream->trigblk
852 + stream->blkmod - 1) % stream->blkmod;
853 stream->update_needed = true;
854 release_spinlock(&slock);
855
856 //get_sem_count(stream->card->buffer_ready_sem, &count);
857 //if (count <= 0)
858 release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
859 }
860
861
862 static void
auvia_record_inth(void * inthparams)863 auvia_record_inth(void* inthparams)
864 {
865 auvia_stream *stream = (auvia_stream *)inthparams;
866 //int32 count;
867
868 //TRACE(("auvia_record_inth\n"));
869
870 acquire_spinlock(&slock);
871 stream->real_time = system_time();
872 stream->frames_count += BUFFER_FRAMES;
873 stream->buffer_cycle = (stream->trigblk
874 + stream->blkmod - 1) % stream->blkmod;
875 stream->update_needed = true;
876 release_spinlock(&slock);
877
878 //get_sem_count(stream->card->buffer_ready_sem, &count);
879 //if (count <= 0)
880 release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
881 }
882
883
884 static status_t
auvia_buffer_exchange(auvia_dev * card,multi_buffer_info * data)885 auvia_buffer_exchange(auvia_dev *card, multi_buffer_info *data)
886 {
887 cpu_status status;
888 auvia_stream *pstream, *rstream;
889 multi_buffer_info buffer_info;
890
891 #ifdef __HAIKU__
892 if (user_memcpy(&buffer_info, data, sizeof(buffer_info)) < B_OK)
893 return B_BAD_ADDRESS;
894 #else
895 memcpy(&buffer_info, data, sizeof(buffer_info));
896 #endif
897
898 buffer_info.flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD;
899
900 if (!(card->pstream->state & AUVIA_STATE_STARTED))
901 auvia_stream_start(card->pstream, auvia_play_inth, card->pstream);
902
903 if (!(card->rstream->state & AUVIA_STATE_STARTED))
904 auvia_stream_start(card->rstream, auvia_record_inth, card->rstream);
905
906 if (acquire_sem_etc(card->buffer_ready_sem, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000)
907 == B_TIMED_OUT) {
908 LOG(("buffer_exchange timeout ff\n"));
909 }
910
911 status = lock();
912
913 LIST_FOREACH(pstream, &card->streams, next) {
914 if ((pstream->use & AUVIA_USE_PLAY) == 0 ||
915 (pstream->state & AUVIA_STATE_STARTED) == 0)
916 continue;
917 if (pstream->update_needed)
918 break;
919 }
920
921 LIST_FOREACH(rstream, &card->streams, next) {
922 if ((rstream->use & AUVIA_USE_RECORD) == 0 ||
923 (rstream->state & AUVIA_STATE_STARTED) == 0)
924 continue;
925 if (rstream->update_needed)
926 break;
927 }
928
929 if (!pstream)
930 pstream = card->pstream;
931 if (!rstream)
932 rstream = card->rstream;
933
934 /* do playback */
935 buffer_info.playback_buffer_cycle = pstream->buffer_cycle;
936 buffer_info.played_real_time = pstream->real_time;
937 buffer_info.played_frames_count = pstream->frames_count;
938 buffer_info._reserved_0 = pstream->first_channel;
939 pstream->update_needed = false;
940
941 /* do record */
942 buffer_info.record_buffer_cycle = rstream->buffer_cycle;
943 buffer_info.recorded_frames_count = rstream->frames_count;
944 buffer_info.recorded_real_time = rstream->real_time;
945 buffer_info._reserved_1 = rstream->first_channel;
946 rstream->update_needed = false;
947 unlock(status);
948
949 #ifdef __HAIKU__
950 if (user_memcpy(data, &buffer_info, sizeof(buffer_info)) < B_OK)
951 return B_BAD_ADDRESS;
952 #else
953 memcpy(data, &buffer_info, sizeof(buffer_info));
954 #endif
955
956 //TRACE(("buffer_exchange ended\n"));
957 return B_OK;
958 }
959
960
961 static status_t
auvia_buffer_force_stop(auvia_dev * card)962 auvia_buffer_force_stop(auvia_dev *card)
963 {
964 //auvia_voice_halt(card->pvoice);
965 return B_OK;
966 }
967
968
969 static status_t
auvia_multi_control(void * cookie,uint32 op,void * data,size_t length)970 auvia_multi_control(void *cookie, uint32 op, void *data, size_t length)
971 {
972 auvia_dev *card = (auvia_dev *)cookie;
973
974 switch (op) {
975 case B_MULTI_GET_DESCRIPTION:
976 LOG(("B_MULTI_GET_DESCRIPTION\n"));
977 return auvia_get_description(card, (multi_description *)data);
978 case B_MULTI_GET_EVENT_INFO:
979 LOG(("B_MULTI_GET_EVENT_INFO\n"));
980 return B_ERROR;
981 case B_MULTI_SET_EVENT_INFO:
982 LOG(("B_MULTI_SET_EVENT_INFO\n"));
983 return B_ERROR;
984 case B_MULTI_GET_EVENT:
985 LOG(("B_MULTI_GET_EVENT\n"));
986 return B_ERROR;
987 case B_MULTI_GET_ENABLED_CHANNELS:
988 LOG(("B_MULTI_GET_ENABLED_CHANNELS\n"));
989 return auvia_get_enabled_channels(card, (multi_channel_enable *)data);
990 case B_MULTI_SET_ENABLED_CHANNELS:
991 LOG(("B_MULTI_SET_ENABLED_CHANNELS\n"));
992 return auvia_set_enabled_channels(card, (multi_channel_enable *)data);
993 case B_MULTI_GET_GLOBAL_FORMAT:
994 LOG(("B_MULTI_GET_GLOBAL_FORMAT\n"));
995 return auvia_get_global_format(card, (multi_format_info *)data);
996 case B_MULTI_SET_GLOBAL_FORMAT:
997 LOG(("B_MULTI_SET_GLOBAL_FORMAT\n"));
998 return B_OK; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent
999 * BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT
1000 */
1001 case B_MULTI_GET_CHANNEL_FORMATS:
1002 LOG(("B_MULTI_GET_CHANNEL_FORMATS\n"));
1003 return B_ERROR;
1004 case B_MULTI_SET_CHANNEL_FORMATS: /* only implemented if possible */
1005 LOG(("B_MULTI_SET_CHANNEL_FORMATS\n"));
1006 return B_ERROR;
1007 case B_MULTI_GET_MIX:
1008 LOG(("B_MULTI_GET_MIX\n"));
1009 return auvia_get_mix(card, (multi_mix_value_info *)data);
1010 case B_MULTI_SET_MIX:
1011 LOG(("B_MULTI_SET_MIX\n"));
1012 return auvia_set_mix(card, (multi_mix_value_info *)data);
1013 case B_MULTI_LIST_MIX_CHANNELS:
1014 LOG(("B_MULTI_LIST_MIX_CHANNELS\n"));
1015 return auvia_list_mix_channels(card, (multi_mix_channel_info *)data);
1016 case B_MULTI_LIST_MIX_CONTROLS:
1017 LOG(("B_MULTI_LIST_MIX_CONTROLS\n"));
1018 return auvia_list_mix_controls(card, (multi_mix_control_info *)data);
1019 case B_MULTI_LIST_MIX_CONNECTIONS:
1020 LOG(("B_MULTI_LIST_MIX_CONNECTIONS\n"));
1021 return auvia_list_mix_connections(card, (multi_mix_connection_info *)data);
1022 case B_MULTI_GET_BUFFERS: /* Fill out the struct for the first time; doesn't start anything. */
1023 LOG(("B_MULTI_GET_BUFFERS\n"));
1024 return auvia_get_buffers(card, data);
1025 case B_MULTI_SET_BUFFERS: /* Set what buffers to use, if the driver supports soft buffers. */
1026 LOG(("B_MULTI_SET_BUFFERS\n"));
1027 return B_ERROR; /* we do not support soft buffers */
1028 case B_MULTI_SET_START_TIME: /* When to actually start */
1029 LOG(("B_MULTI_SET_START_TIME\n"));
1030 return B_ERROR;
1031 case B_MULTI_BUFFER_EXCHANGE: /* stop and go are derived from this being called */
1032 //TRACE(("B_MULTI_BUFFER_EXCHANGE\n"));
1033 return auvia_buffer_exchange(card, (multi_buffer_info *)data);
1034 case B_MULTI_BUFFER_FORCE_STOP: /* force stop of playback, nothing in data */
1035 LOG(("B_MULTI_BUFFER_FORCE_STOP\n"));
1036 return auvia_buffer_force_stop(card);
1037 }
1038 LOG(("ERROR: unknown multi_control %#x\n",op));
1039 return B_ERROR;
1040 }
1041
1042 static status_t auvia_open(const char *name, uint32 flags, void** cookie);
1043 static status_t auvia_close(void* cookie);
1044 static status_t auvia_free(void* cookie);
1045 static status_t auvia_control(void* cookie, uint32 op, void* arg, size_t len);
1046 static status_t auvia_read(void* cookie, off_t position, void *buf, size_t* num_bytes);
1047 static status_t auvia_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes);
1048
1049 device_hooks multi_hooks = {
1050 auvia_open, /* -> open entry point */
1051 auvia_close, /* -> close entry point */
1052 auvia_free, /* -> free cookie */
1053 auvia_control, /* -> control entry point */
1054 auvia_read, /* -> read entry point */
1055 auvia_write, /* -> write entry point */
1056 NULL, /* start select */
1057 NULL, /* stop select */
1058 NULL, /* scatter-gather read from the device */
1059 NULL /* scatter-gather write to the device */
1060 };
1061
1062
1063 static status_t
auvia_open(const char * name,uint32 flags,void ** cookie)1064 auvia_open(const char *name, uint32 flags, void** cookie)
1065 {
1066 auvia_dev *card = NULL;
1067 int ix;
1068
1069 LOG(("open()\n"));
1070
1071 for (ix=0; ix<num_cards; ix++) {
1072 if (!strcmp(cards[ix].name, name)) {
1073 card = &cards[ix];
1074 }
1075 }
1076
1077 if (card == NULL) {
1078 LOG(("open() card not found %s\n", name));
1079 for (ix=0; ix<num_cards; ix++) {
1080 LOG(("open() card available %s\n", cards[ix].name));
1081 }
1082 return B_ERROR;
1083 }
1084
1085 LOG(("open() got card\n"));
1086
1087 if (card->pstream !=NULL)
1088 return B_ERROR;
1089 if (card->rstream !=NULL)
1090 return B_ERROR;
1091
1092 *cookie = card;
1093 card->multi.card = card;
1094
1095 LOG(("stream_new\n"));
1096
1097 card->rstream = auvia_stream_new(card, AUVIA_USE_RECORD, BUFFER_FRAMES, BUFFER_COUNT);
1098 card->pstream = auvia_stream_new(card, AUVIA_USE_PLAY, BUFFER_FRAMES, BUFFER_COUNT);
1099
1100 card->buffer_ready_sem = create_sem(0, "pbuffer ready");
1101
1102 LOG(("stream_setaudio\n"));
1103
1104 auvia_stream_set_audioparms(card->pstream, 2, true, 48000);
1105 auvia_stream_set_audioparms(card->rstream, 2, true, 48000);
1106
1107 card->pstream->first_channel = 0;
1108 card->rstream->first_channel = 2;
1109
1110 auvia_stream_commit_parms(card->pstream);
1111 auvia_stream_commit_parms(card->rstream);
1112
1113 auvia_create_channels_list(&card->multi);
1114
1115 return B_OK;
1116 }
1117
1118
1119 static status_t
auvia_close(void * cookie)1120 auvia_close(void* cookie)
1121 {
1122 //auvia_dev *card = cookie;
1123 LOG(("close()\n"));
1124
1125 return B_OK;
1126 }
1127
1128
1129 static status_t
auvia_free(void * cookie)1130 auvia_free(void* cookie)
1131 {
1132 auvia_dev *card = cookie;
1133 auvia_stream *stream;
1134 LOG(("free()\n"));
1135
1136 if (card->buffer_ready_sem > B_OK)
1137 delete_sem(card->buffer_ready_sem);
1138
1139 LIST_FOREACH(stream, &card->streams, next) {
1140 auvia_stream_halt(stream);
1141 }
1142
1143 while (!LIST_EMPTY(&card->streams)) {
1144 auvia_stream_delete(LIST_FIRST(&card->streams));
1145 }
1146
1147 card->pstream = NULL;
1148 card->rstream = NULL;
1149
1150 return B_OK;
1151 }
1152
1153
1154 static status_t
auvia_control(void * cookie,uint32 op,void * arg,size_t len)1155 auvia_control(void* cookie, uint32 op, void* arg, size_t len)
1156 {
1157 return auvia_multi_control(cookie, op, arg, len);
1158 }
1159
1160
1161 static status_t
auvia_read(void * cookie,off_t position,void * buf,size_t * num_bytes)1162 auvia_read(void* cookie, off_t position, void *buf, size_t* num_bytes)
1163 {
1164 *num_bytes = 0; /* tell caller nothing was read */
1165 return B_IO_ERROR;
1166 }
1167
1168
1169 static status_t
auvia_write(void * cookie,off_t position,const void * buffer,size_t * num_bytes)1170 auvia_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes)
1171 {
1172 *num_bytes = 0; /* tell caller nothing was written */
1173 return B_IO_ERROR;
1174 }
1175