1 /*
2 * Auich BeOS Driver for Intel 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 <driver_settings.h>
33 #include <OS.h>
34 #include <MediaDefs.h>
35 #include <string.h>
36 #include <strings.h>
37
38 #include <kernel.h>
39
40 #include "hmulti_audio.h"
41 #include "multi.h"
42 #include "ac97.h"
43
44 //#define DEBUG 1
45
46 #include "debug.h"
47 #include "auich.h"
48 #include "util.h"
49 #include "io.h"
50
51
52 static void
auich_ac97_get_mix(void * card,const void * cookie,int32 type,float * values)53 auich_ac97_get_mix(void *card, const void *cookie, int32 type, float *values) {
54 auich_dev *dev = (auich_dev*)card;
55 ac97_source_info *info = (ac97_source_info *)cookie;
56 uint16 value, mask;
57 float gain;
58
59 switch(type) {
60 case B_MIX_GAIN:
61 value = auich_codec_read(&dev->config, info->reg);
62 //PRINT(("B_MIX_GAIN value : %u\n", value));
63 if (info->type & B_MIX_STEREO) {
64 mask = ((1 << (info->bits + 1)) - 1) << 8;
65 gain = ((value & mask) >> 8) * info->granularity;
66 if (info->polarity == 1)
67 values[0] = info->max_gain - gain;
68 else
69 values[0] = gain - info->min_gain;
70
71 mask = ((1 << (info->bits + 1)) - 1);
72 gain = (value & mask) * info->granularity;
73 if (info->polarity == 1)
74 values[1] = info->max_gain - gain;
75 else
76 values[1] = gain - info->min_gain;
77 } else {
78 mask = ((1 << (info->bits + 1)) - 1);
79 gain = (value & mask) * info->granularity;
80 if (info->polarity == 1)
81 values[0] = info->max_gain - gain;
82 else
83 values[0] = gain - info->min_gain;
84 }
85 break;
86 case B_MIX_MUTE:
87 mask = ((1 << 1) - 1) << 15;
88 value = auich_codec_read(&dev->config, info->reg);
89 //PRINT(("B_MIX_MUTE value : %u\n", value));
90 value &= mask;
91 values[0] = ((value >> 15) == 1) ? 1.0 : 0.0;
92 break;
93 case B_MIX_MICBOOST:
94 mask = ((1 << 1) - 1) << 6;
95 value = auich_codec_read(&dev->config, info->reg);
96 //PRINT(("B_MIX_MICBOOST value : %u\n", value));
97 value &= mask;
98 values[0] = ((value >> 6) == 1) ? 1.0 : 0.0;
99 break;
100 case B_MIX_MUX:
101 mask = ((1 << 3) - 1);
102 value = auich_codec_read(&dev->config, AC97_RECORD_SELECT);
103 value &= mask;
104 //PRINT(("B_MIX_MUX value : %u\n", value));
105 values[0] = (float)value;
106 break;
107 }
108 }
109
110
111 static void
auich_ac97_set_mix(void * card,const void * cookie,int32 type,float * values)112 auich_ac97_set_mix(void *card, const void *cookie, int32 type, float *values) {
113 auich_dev *dev = (auich_dev*)card;
114 ac97_source_info *info = (ac97_source_info *)cookie;
115 uint16 value, mask;
116 float gain;
117
118 switch(type) {
119 case B_MIX_GAIN:
120 value = auich_codec_read(&dev->config, info->reg);
121 if (info->type & B_MIX_STEREO) {
122 mask = ((1 << (info->bits + 1)) - 1) << 8;
123 value &= ~mask;
124
125 if (info->polarity == 1)
126 gain = info->max_gain - values[0];
127 else
128 gain = values[0] - info->min_gain;
129 value |= ((uint16)(gain / info->granularity) << 8) & mask;
130
131 mask = ((1 << (info->bits + 1)) - 1);
132 value &= ~mask;
133 if (info->polarity == 1)
134 gain = info->max_gain - values[1];
135 else
136 gain = values[1] - info->min_gain;
137 value |= ((uint16)(gain / info->granularity)) & mask;
138 } else {
139 mask = ((1 << (info->bits + 1)) - 1);
140 value &= ~mask;
141 if (info->polarity == 1)
142 gain = info->max_gain - values[0];
143 else
144 gain = values[0] - info->min_gain;
145 value |= ((uint16)(gain / info->granularity)) & mask;
146 }
147 //PRINT(("B_MIX_GAIN value : %u\n", value));
148 auich_codec_write(&dev->config, info->reg, value);
149 break;
150 case B_MIX_MUTE:
151 mask = ((1 << 1) - 1) << 15;
152 value = auich_codec_read(&dev->config, info->reg);
153 value &= ~mask;
154 value |= ((values[0] == 1.0 ? 1 : 0 ) << 15 & mask);
155 if (info->reg == AC97_SURR_VOLUME) {
156 // there is a independent mute for each channel
157 mask = ((1 << 1) - 1) << 7;
158 value &= ~mask;
159 value |= ((values[0] == 1.0 ? 1 : 0 ) << 7 & mask);
160 }
161 //PRINT(("B_MIX_MUTE value : %u\n", value));
162 auich_codec_write(&dev->config, info->reg, value);
163 break;
164 case B_MIX_MICBOOST:
165 mask = ((1 << 1) - 1) << 6;
166 value = auich_codec_read(&dev->config, info->reg);
167 value &= ~mask;
168 value |= ((values[0] == 1.0 ? 1 : 0 ) << 6 & mask);
169 //PRINT(("B_MIX_MICBOOST value : %u\n", value));
170 auich_codec_write(&dev->config, info->reg, value);
171 break;
172 case B_MIX_MUX:
173 mask = ((1 << 3) - 1);
174 value = ((int32)values[0]) & mask;
175 value = value | (value << 8);
176 //PRINT(("B_MIX_MUX value : %u\n", value));
177 auich_codec_write(&dev->config, AC97_RECORD_SELECT, value);
178 break;
179 }
180
181 }
182
183
184 static int32
auich_create_group_control(multi_dev * multi,uint32 * index,int32 parent,int32 string,const char * name)185 auich_create_group_control(multi_dev *multi, uint32 *index, int32 parent, int32 string,
186 const char* name)
187 {
188 uint32 i = *index;
189 (*index)++;
190 multi->controls[i].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + i;
191 multi->controls[i].mix_control.parent = parent;
192 multi->controls[i].mix_control.flags = B_MULTI_MIX_GROUP;
193 multi->controls[i].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
194 multi->controls[i].mix_control.string = string;
195 if (name)
196 strcpy(multi->controls[i].mix_control.name, name);
197
198 return multi->controls[i].mix_control.id;
199 }
200
201
202 static status_t
auich_create_controls_list(multi_dev * multi)203 auich_create_controls_list(multi_dev *multi)
204 {
205 uint32 i = 0, index = 0, count, id, parent, parent2, parent3;
206 const ac97_source_info *info;
207
208 /* AC97 Mixer */
209 parent = auich_create_group_control(multi, &index, 0, 0, "AC97 mixer");
210
211 count = source_info_size;
212 //Note that we ignore first item in source_info
213 //It's for recording, but do match this with ac97.c's source_info
214 for (i = 1; i < count ; i++) {
215 info = &source_info[i];
216 PRINT(("name : %s\n", info->name));
217
218 parent2 = auich_create_group_control(multi, &index, parent, 0, info->name);
219
220 if (info->type & B_MIX_GAIN) {
221 if (info->type & B_MIX_MUTE) {
222 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
223 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE;
224 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
225 multi->controls[index].mix_control.parent = parent2;
226 multi->controls[index].mix_control.string = S_MUTE;
227 multi->controls[index].cookie = info;
228 multi->controls[index].type = B_MIX_MUTE;
229 multi->controls[index].get = &auich_ac97_get_mix;
230 multi->controls[index].set = &auich_ac97_set_mix;
231 index++;
232 }
233
234 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
235 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN;
236 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
237 multi->controls[index].mix_control.parent = parent2;
238 strcpy(multi->controls[index].mix_control.name, info->name);
239 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain;
240 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain;
241 multi->controls[index].mix_control.u.gain.granularity = info->granularity;
242 multi->controls[index].cookie = info;
243 multi->controls[index].type = B_MIX_GAIN;
244 multi->controls[index].get = &auich_ac97_get_mix;
245 multi->controls[index].set = &auich_ac97_set_mix;
246 id = multi->controls[index].mix_control.id;
247 index++;
248
249 if (info->type & B_MIX_STEREO) {
250 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
251 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN;
252 multi->controls[index].mix_control.master = id;
253 multi->controls[index].mix_control.parent = parent2;
254 strcpy(multi->controls[index].mix_control.name, info->name);
255 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain;
256 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain;
257 multi->controls[index].mix_control.u.gain.granularity = info->granularity;
258 multi->controls[index].cookie = info;
259 multi->controls[index].type = B_MIX_GAIN;
260 multi->controls[index].get = &auich_ac97_get_mix;
261 multi->controls[index].set = &auich_ac97_set_mix;
262 index++;
263 }
264
265 if (info->type & B_MIX_MICBOOST) {
266 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
267 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE;
268 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
269 multi->controls[index].mix_control.parent = parent2;
270 strcpy(multi->controls[index].mix_control.name, "+20 dB");
271 multi->controls[index].cookie = info;
272 multi->controls[index].type = B_MIX_MICBOOST;
273 multi->controls[index].get = &auich_ac97_get_mix;
274 multi->controls[index].set = &auich_ac97_set_mix;
275 index++;
276 }
277 }
278 }
279
280 /* AC97 Record */
281 parent = auich_create_group_control(multi, &index, 0, 0, "Recording");
282
283 info = &source_info[0];
284 PRINT(("name : %s\n", info->name));
285
286 parent2 = auich_create_group_control(multi, &index, parent, 0, info->name);
287
288 if (info->type & B_MIX_GAIN) {
289 if (info->type & B_MIX_MUTE) {
290 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
291 multi->controls[index].mix_control.flags = B_MULTI_MIX_ENABLE;
292 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
293 multi->controls[index].mix_control.parent = parent2;
294 multi->controls[index].mix_control.string = S_MUTE;
295 multi->controls[index].cookie = info;
296 multi->controls[index].type = B_MIX_MUTE;
297 multi->controls[index].get = &auich_ac97_get_mix;
298 multi->controls[index].set = &auich_ac97_set_mix;
299 index++;
300 }
301
302 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
303 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN;
304 multi->controls[index].mix_control.master = EMU_MULTI_CONTROL_MASTERID;
305 multi->controls[index].mix_control.parent = parent2;
306 strcpy(multi->controls[index].mix_control.name, info->name);
307 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain;
308 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain;
309 multi->controls[index].mix_control.u.gain.granularity = info->granularity;
310 multi->controls[index].cookie = info;
311 multi->controls[index].type = B_MIX_GAIN;
312 multi->controls[index].get = &auich_ac97_get_mix;
313 multi->controls[index].set = &auich_ac97_set_mix;
314 id = multi->controls[index].mix_control.id;
315 index++;
316
317 if (info->type & B_MIX_STEREO) {
318 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
319 multi->controls[index].mix_control.flags = B_MULTI_MIX_GAIN;
320 multi->controls[index].mix_control.master = id;
321 multi->controls[index].mix_control.parent = parent2;
322 strcpy(multi->controls[index].mix_control.name, info->name);
323 multi->controls[index].mix_control.u.gain.min_gain = info->min_gain;
324 multi->controls[index].mix_control.u.gain.max_gain = info->max_gain;
325 multi->controls[index].mix_control.u.gain.granularity = info->granularity;
326 multi->controls[index].cookie = info;
327 multi->controls[index].type = B_MIX_GAIN;
328 multi->controls[index].get = &auich_ac97_get_mix;
329 multi->controls[index].set = &auich_ac97_set_mix;
330 index++;
331 }
332
333 if (info->type & B_MIX_RECORDMUX) {
334 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
335 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX;
336 multi->controls[index].mix_control.parent = parent2;
337 strcpy(multi->controls[index].mix_control.name, "Record mux");
338 multi->controls[index].cookie = info;
339 multi->controls[index].type = B_MIX_MUX;
340 multi->controls[index].get = &auich_ac97_get_mix;
341 multi->controls[index].set = &auich_ac97_set_mix;
342 parent3 = multi->controls[index].mix_control.id;
343 index++;
344
345 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
346 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
347 multi->controls[index].mix_control.parent = parent3;
348 multi->controls[index].mix_control.string = S_MIC;
349 index++;
350 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
351 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
352 multi->controls[index].mix_control.parent = parent3;
353 strcpy(multi->controls[index].mix_control.name, "CD in");
354 index++;
355 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
356 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
357 multi->controls[index].mix_control.parent = parent3;
358 strcpy(multi->controls[index].mix_control.name, "Video in");
359 index++;
360 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
361 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
362 multi->controls[index].mix_control.parent = parent3;
363 strcpy(multi->controls[index].mix_control.name, "Aux in");
364 index++;
365 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
366 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
367 multi->controls[index].mix_control.parent = parent3;
368 strcpy(multi->controls[index].mix_control.name, "Line in");
369 index++;
370 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
371 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
372 multi->controls[index].mix_control.parent = parent3;
373 multi->controls[index].mix_control.string = S_STEREO_MIX;
374 index++;
375 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
376 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
377 multi->controls[index].mix_control.parent = parent3;
378 multi->controls[index].mix_control.string = S_MONO_MIX;
379 index++;
380 multi->controls[index].mix_control.id = EMU_MULTI_CONTROL_FIRSTID + index;
381 multi->controls[index].mix_control.flags = B_MULTI_MIX_MUX_VALUE;
382 multi->controls[index].mix_control.parent = parent3;
383 strcpy(multi->controls[index].mix_control.name, "TAD");
384 index++;
385 }
386 }
387
388 multi->control_count = index;
389 PRINT(("multi->control_count %" B_PRIu32 "\n", multi->control_count));
390 return B_OK;
391 }
392
393
394 static status_t
auich_get_mix(auich_dev * card,multi_mix_value_info * mmvi)395 auich_get_mix(auich_dev *card, multi_mix_value_info * mmvi)
396 {
397 int32 i, id;
398 multi_mixer_control *control = NULL;
399 for (i = 0; i < mmvi->item_count; i++) {
400 id = mmvi->values[i].id - EMU_MULTI_CONTROL_FIRSTID;
401 if (id < 0 || (uint32)id >= card->multi.control_count) {
402 PRINT(("auich_get_mix : "
403 "invalid control id requested : %" B_PRIi32 "\n", id));
404 continue;
405 }
406 control = &card->multi.controls[id];
407
408 if (control->mix_control.flags & B_MULTI_MIX_GAIN) {
409 if (control->get) {
410 float values[2];
411 control->get(card, control->cookie, control->type, values);
412 if (control->mix_control.master == EMU_MULTI_CONTROL_MASTERID)
413 mmvi->values[i].u.gain = values[0];
414 else
415 mmvi->values[i].u.gain = values[1];
416 }
417 }
418
419 if (control->mix_control.flags & B_MULTI_MIX_ENABLE && control->get) {
420 float values[1];
421 control->get(card, control->cookie, control->type, values);
422 mmvi->values[i].u.enable = (values[0] == 1.0);
423 }
424
425 if (control->mix_control.flags & B_MULTI_MIX_MUX && control->get) {
426 float values[1];
427 control->get(card, control->cookie, control->type, values);
428 mmvi->values[i].u.mux = (int32)values[0];
429 }
430 }
431 return B_OK;
432 }
433
434
435 static status_t
auich_set_mix(auich_dev * card,multi_mix_value_info * mmvi)436 auich_set_mix(auich_dev *card, multi_mix_value_info * mmvi)
437 {
438 int32 i, id;
439 multi_mixer_control *control = NULL;
440 for (i = 0; i < mmvi->item_count; i++) {
441 id = mmvi->values[i].id - EMU_MULTI_CONTROL_FIRSTID;
442 if (id < 0 || (uint32)id >= card->multi.control_count) {
443 PRINT(("auich_set_mix : "
444 "invalid control id requested : %" B_PRIi32 "\n", id));
445 continue;
446 }
447 control = &card->multi.controls[id];
448
449 if (control->mix_control.flags & B_MULTI_MIX_GAIN) {
450 multi_mixer_control *control2 = NULL;
451 if (i+1<mmvi->item_count) {
452 id = mmvi->values[i + 1].id - EMU_MULTI_CONTROL_FIRSTID;
453 if (id < 0 || (uint32)id >= card->multi.control_count) {
454 PRINT(("auich_set_mix : "
455 "invalid control id requested : %" B_PRIi32 "\n", id));
456 } else {
457 control2 = &card->multi.controls[id];
458 if (control2->mix_control.master != control->mix_control.id)
459 control2 = NULL;
460 }
461 }
462
463 if (control->set) {
464 float values[2];
465 values[0] = 0.0;
466 values[1] = 0.0;
467
468 if (control->mix_control.master == EMU_MULTI_CONTROL_MASTERID)
469 values[0] = mmvi->values[i].u.gain;
470 else
471 values[1] = mmvi->values[i].u.gain;
472
473 if (control2 && control2->mix_control.master != EMU_MULTI_CONTROL_MASTERID)
474 values[1] = mmvi->values[i+1].u.gain;
475
476 control->set(card, control->cookie, control->type, values);
477 }
478
479 if (control2)
480 i++;
481 }
482
483 if (control->mix_control.flags & B_MULTI_MIX_ENABLE && control->set) {
484 float values[1];
485
486 values[0] = mmvi->values[i].u.enable ? 1.0 : 0.0;
487 control->set(card, control->cookie, control->type, values);
488 }
489
490 if (control->mix_control.flags & B_MULTI_MIX_MUX && control->set) {
491 float values[1];
492
493 values[0] = (float)mmvi->values[i].u.mux;
494 control->set(card, control->cookie, control->type, values);
495 }
496 }
497 return B_OK;
498 }
499
500
501 static status_t
auich_list_mix_controls(auich_dev * card,multi_mix_control_info * mmci)502 auich_list_mix_controls(auich_dev *card, multi_mix_control_info * mmci)
503 {
504 multi_mix_control *mmc;
505 uint32 i;
506
507 mmc = mmci->controls;
508 if (mmci->control_count < 24)
509 return B_ERROR;
510
511 if (auich_create_controls_list(&card->multi) < B_OK)
512 return B_ERROR;
513
514 for (i = 0; i < card->multi.control_count; i++)
515 mmc[i] = card->multi.controls[i].mix_control;
516
517 mmci->control_count = card->multi.control_count;
518 return B_OK;
519 }
520
521
522 static status_t
auich_list_mix_connections(auich_dev * card,multi_mix_connection_info * data)523 auich_list_mix_connections(auich_dev *card, multi_mix_connection_info * data)
524 {
525 return B_ERROR;
526 }
527
528
529 static status_t
auich_list_mix_channels(auich_dev * card,multi_mix_channel_info * data)530 auich_list_mix_channels(auich_dev *card, multi_mix_channel_info *data)
531 {
532 return B_ERROR;
533 }
534
535 /*multi_channel_info chans[] = {
536 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
537 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
538 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
539 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
540 { 4, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
541 { 5, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
542 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
543 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
544 { 8, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
545 { 9, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
546 { 10, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
547 { 11, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
548 };*/
549
550 /*multi_channel_info chans[] = {
551 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
552 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
553 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_SURROUND_BUS, 0 },
554 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_SURROUND_BUS, 0 },
555 { 4, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARLEFT | B_CHANNEL_SURROUND_BUS, 0 },
556 { 5, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARRIGHT | B_CHANNEL_SURROUND_BUS, 0 },
557 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
558 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
559 { 8, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
560 { 9, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
561 { 10, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
562 { 11, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
563 { 12, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
564 { 13, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
565 };*/
566
567
568 static void
auich_create_channels_list(multi_dev * multi)569 auich_create_channels_list(multi_dev *multi)
570 {
571 auich_stream *stream;
572 uint32 index, i, mode, designations;
573 multi_channel_info *chans;
574 uint32 chan_designations[] = {
575 B_CHANNEL_LEFT,
576 B_CHANNEL_RIGHT,
577 B_CHANNEL_REARLEFT,
578 B_CHANNEL_REARRIGHT,
579 B_CHANNEL_CENTER,
580 B_CHANNEL_SUB
581 };
582
583 chans = multi->chans;
584 index = 0;
585
586 for (mode = AUICH_USE_PLAY; (int32)mode != -1;
587 mode = (mode == AUICH_USE_PLAY) ? AUICH_USE_RECORD : -1) {
588 LIST_FOREACH(stream, &((auich_dev*)multi->card)->streams, next) {
589 if ((stream->use & mode) == 0)
590 continue;
591
592 if (stream->channels == 2)
593 designations = B_CHANNEL_STEREO_BUS;
594 else
595 designations = B_CHANNEL_SURROUND_BUS;
596
597 for (i = 0; i < stream->channels; i++) {
598 chans[index].channel_id = index;
599 chans[index].kind
600 = (mode == AUICH_USE_PLAY) ? B_MULTI_OUTPUT_CHANNEL : B_MULTI_INPUT_CHANNEL;
601 chans[index].designations = designations | chan_designations[i];
602 chans[index].connectors = 0;
603 index++;
604 }
605 }
606
607 if (mode == AUICH_USE_PLAY)
608 multi->output_channel_count = index;
609 else
610 multi->input_channel_count = index - multi->output_channel_count;
611 }
612
613 chans[index].channel_id = index;
614 chans[index].kind = B_MULTI_OUTPUT_BUS;
615 chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS;
616 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
617 index++;
618
619 chans[index].channel_id = index;
620 chans[index].kind = B_MULTI_OUTPUT_BUS;
621 chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS;
622 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
623 index++;
624
625 multi->output_bus_channel_count = index - multi->output_channel_count
626 - multi->input_channel_count;
627
628 chans[index].channel_id = index;
629 chans[index].kind = B_MULTI_INPUT_BUS;
630 chans[index].designations = B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS;
631 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
632 index++;
633
634 chans[index].channel_id = index;
635 chans[index].kind = B_MULTI_INPUT_BUS;
636 chans[index].designations = B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS;
637 chans[index].connectors = B_CHANNEL_MINI_JACK_STEREO;
638 index++;
639
640 multi->input_bus_channel_count = index - multi->output_channel_count
641 - multi->input_channel_count - multi->output_bus_channel_count;
642
643 multi->aux_bus_channel_count = 0;
644 }
645
646
647 static status_t
auich_get_description(auich_dev * card,multi_description * data)648 auich_get_description(auich_dev *card, multi_description *data)
649 {
650 uint32 size;
651
652 data->interface_version = B_CURRENT_INTERFACE_VERSION;
653 data->interface_minimum = B_CURRENT_INTERFACE_VERSION;
654
655 switch(card->info.vendor_id) {
656 case INTEL_VENDOR_ID:
657 strncpy(data->friendly_name, FRIENDLY_NAME_ICH, 32);
658 break;
659 case SIS_VENDOR_ID:
660 strncpy(data->friendly_name, FRIENDLY_NAME_SIS, 32);
661 break;
662 case NVIDIA_VENDOR_ID:
663 strncpy(data->friendly_name, FRIENDLY_NAME_NVIDIA, 32);
664 break;
665 case AMD_VENDOR_ID:
666 strncpy(data->friendly_name, FRIENDLY_NAME_AMD, 32);
667 break;
668 }
669
670 strcpy(data->vendor_info, AUTHOR);
671
672 /*data->output_channel_count = 6;
673 data->input_channel_count = 4;
674 data->output_bus_channel_count = 2;
675 data->input_bus_channel_count = 2;
676 data->aux_bus_channel_count = 0;*/
677
678 data->output_channel_count = card->multi.output_channel_count;
679 data->input_channel_count = card->multi.input_channel_count;
680 data->output_bus_channel_count = card->multi.output_bus_channel_count;
681 data->input_bus_channel_count = card->multi.input_bus_channel_count;
682 data->aux_bus_channel_count = card->multi.aux_bus_channel_count;
683
684 size = card->multi.output_channel_count + card->multi.input_channel_count
685 + card->multi.output_bus_channel_count + card->multi.input_bus_channel_count
686 + card->multi.aux_bus_channel_count;
687
688 // for each channel, starting with the first output channel,
689 // then the second, third..., followed by the first input
690 // channel, second, third, ..., followed by output bus
691 // channels and input bus channels and finally auxillary channels,
692
693 LOG(("request_channel_count = %d\n",data->request_channel_count));
694 if (data->request_channel_count >= (int32)size) {
695 LOG(("copying data\n"));
696 memcpy(data->channels, card->multi.chans, size * sizeof(card->multi.chans[0]));
697 }
698
699 switch (current_settings.sample_rate) {
700 case 48000: data->output_rates = data->input_rates = B_SR_48000; break;
701 case 44100: data->output_rates = data->input_rates = B_SR_44100; break;
702 }
703 data->min_cvsr_rate = 0;
704 data->max_cvsr_rate = 48000;
705
706 data->output_formats = B_FMT_16BIT;
707 data->input_formats = B_FMT_16BIT;
708 data->lock_sources = B_MULTI_LOCK_INTERNAL;
709 data->timecode_sources = 0;
710 data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD;
711 data->start_latency = 3000;
712
713 strcpy(data->control_panel,"");
714
715 return B_OK;
716 }
717
718
719 static status_t
auich_get_enabled_channels(auich_dev * card,multi_channel_enable * data)720 auich_get_enabled_channels(auich_dev *card, multi_channel_enable *data)
721 {
722 B_SET_CHANNEL(data->enable_bits, 0, true);
723 B_SET_CHANNEL(data->enable_bits, 1, true);
724 B_SET_CHANNEL(data->enable_bits, 2, true);
725 B_SET_CHANNEL(data->enable_bits, 3, true);
726 data->lock_source = B_MULTI_LOCK_INTERNAL;
727 /*
728 uint32 lock_source;
729 int32 lock_data;
730 uint32 timecode_source;
731 uint32 * connectors;
732 */
733 return B_OK;
734 }
735
736
737 static status_t
auich_get_global_format(auich_dev * card,multi_format_info * data)738 auich_get_global_format(auich_dev *card, multi_format_info *data)
739 {
740 data->output_latency = 0;
741 data->input_latency = 0;
742 data->timecode_kind = 0;
743 switch (current_settings.sample_rate) {
744 case 48000:
745 data->input.rate = data->output.rate = B_SR_48000;
746 data->input.cvsr = data->output.cvsr = 48000;
747 break;
748 case 44100:
749 data->input.rate = data->output.rate = B_SR_44100;
750 data->input.cvsr = data->output.cvsr = 44100;
751 break;
752 }
753 data->input.format = data->output.format = B_FMT_16BIT;
754 return B_OK;
755 }
756
757
758 static status_t
auich_set_global_format(auich_dev * card,multi_format_info * data)759 auich_set_global_format(auich_dev *card, multi_format_info* data)
760 {
761 // TODO: it looks like we're not supposed to fail; fix this!
762 return B_OK;
763 }
764
765
766 static status_t
auich_get_buffers(auich_dev * card,multi_buffer_list * data)767 auich_get_buffers(auich_dev *card, multi_buffer_list *data)
768 {
769 uint8 i, j, pchannels, rchannels, bufcount;
770
771 LOG(("flags = %#x\n",data->flags));
772 LOG(("request_playback_buffers = %#x\n",data->request_playback_buffers));
773 LOG(("request_playback_channels = %#x\n",data->request_playback_channels));
774 LOG(("request_playback_buffer_size = %#x\n",data->request_playback_buffer_size));
775 LOG(("request_record_buffers = %#x\n",data->request_record_buffers));
776 LOG(("request_record_channels = %#x\n",data->request_record_channels));
777 LOG(("request_record_buffer_size = %#x\n",data->request_record_buffer_size));
778
779 pchannels = card->pstream->channels;
780 rchannels = card->rstream->channels;
781
782 if (data->request_playback_buffers < current_settings.buffer_count ||
783 data->request_playback_channels < (pchannels) ||
784 data->request_record_buffers < current_settings.buffer_count ||
785 data->request_record_channels < (rchannels)) {
786 LOG(("not enough channels/buffers\n"));
787 }
788
789 ASSERT(current_settings.buffer_count == 2);
790
791 data->flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD; // XXX ???
792 // data->flags = 0;
793
794 data->return_playback_buffers = current_settings.buffer_count; /* playback_buffers[b][] */
795 data->return_playback_channels = pchannels; /* playback_buffers[][c] */
796 data->return_playback_buffer_size = current_settings.buffer_frames; /* frames */
797
798 bufcount = current_settings.buffer_count;
799 if (bufcount > data->request_playback_buffers)
800 bufcount = data->request_playback_buffers;
801
802 for (i = 0; i < bufcount; i++) {
803 struct buffer_desc descs[data->return_playback_channels];
804 for (j=0; j<pchannels; j++)
805 auich_stream_get_nth_buffer(card->pstream, j, i,
806 &descs[j].base,
807 &descs[j].stride);
808 if (!IS_USER_ADDRESS(data->playback_buffers[i])
809 || user_memcpy(data->playback_buffers[i], descs, sizeof(descs))
810 < B_OK) {
811 return B_BAD_ADDRESS;
812 }
813 }
814 data->return_record_buffers = current_settings.buffer_count;
815 data->return_record_channels = rchannels;
816 data->return_record_buffer_size = current_settings.buffer_frames; /* frames */
817
818 bufcount = current_settings.buffer_count;
819 if (bufcount > data->request_record_buffers)
820 bufcount = data->request_record_buffers;
821
822 for (i = 0; i < bufcount; i++) {
823 struct buffer_desc descs[data->return_record_channels];
824 for (j=0; j<rchannels; j++)
825 auich_stream_get_nth_buffer(card->rstream, j, i,
826 &descs[j].base,
827 &descs[j].stride);
828 if (!IS_USER_ADDRESS(data->record_buffers[i])
829 || user_memcpy(data->record_buffers[i], descs, sizeof(descs))
830 < B_OK) {
831 return B_BAD_ADDRESS;
832 }
833 }
834 return B_OK;
835 }
836
837
838 static void
auich_play_inth(void * inthparams)839 auich_play_inth(void* inthparams)
840 {
841 auich_stream *stream = (auich_stream *)inthparams;
842 //int32 count;
843
844 acquire_spinlock(&slock);
845 stream->real_time = system_time();
846 stream->frames_count += current_settings.buffer_frames;
847 stream->buffer_cycle = (stream->trigblk
848 + stream->blkmod - 1) % stream->blkmod;
849 stream->update_needed = true;
850 release_spinlock(&slock);
851
852 TRACE(("auich_play_inth : cycle : %d\n", stream->buffer_cycle));
853
854 //get_sem_count(stream->card->buffer_ready_sem, &count);
855 //if (count <= 0)
856 release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
857 }
858
859
860 static void
auich_record_inth(void * inthparams)861 auich_record_inth(void* inthparams)
862 {
863 auich_stream *stream = (auich_stream *)inthparams;
864 //int32 count;
865
866 acquire_spinlock(&slock);
867 stream->real_time = system_time();
868 stream->frames_count += current_settings.buffer_frames;
869 stream->buffer_cycle = (stream->trigblk
870 + stream->blkmod - 1) % stream->blkmod;
871 stream->update_needed = true;
872 release_spinlock(&slock);
873
874 TRACE(("auich_record_inth : cycle : %d\n", stream->buffer_cycle));
875
876 //get_sem_count(stream->card->buffer_ready_sem, &count);
877 //if (count <= 0)
878 release_sem_etc(stream->card->buffer_ready_sem, 1, B_DO_NOT_RESCHEDULE);
879 }
880
881
882 static status_t
auich_buffer_exchange(auich_dev * card,multi_buffer_info * data)883 auich_buffer_exchange(auich_dev *card, multi_buffer_info *data)
884 {
885 cpu_status status;
886 auich_stream *pstream, *rstream;
887 multi_buffer_info buffer_info;
888
889 #ifdef __HAIKU__
890 if (user_memcpy(&buffer_info, data, sizeof(buffer_info)) < B_OK)
891 return B_BAD_ADDRESS;
892 #else
893 memcpy(&buffer_info, data, sizeof(buffer_info));
894 #endif
895
896 buffer_info.flags = B_MULTI_BUFFER_PLAYBACK | B_MULTI_BUFFER_RECORD;
897
898 if (!(card->pstream->state & AUICH_STATE_STARTED))
899 auich_stream_start(card->pstream, auich_play_inth, card->pstream);
900
901 if (!(card->rstream->state & AUICH_STATE_STARTED))
902 auich_stream_start(card->rstream, auich_record_inth, card->rstream);
903
904 if (acquire_sem_etc(card->buffer_ready_sem, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000)
905 == B_TIMED_OUT) {
906 LOG(("buffer_exchange timeout ff\n"));
907 }
908
909 status = lock();
910
911 LIST_FOREACH(pstream, &card->streams, next) {
912 if ((pstream->use & AUICH_USE_PLAY) == 0 ||
913 (pstream->state & AUICH_STATE_STARTED) == 0)
914 continue;
915 if (pstream->update_needed)
916 break;
917 }
918
919 LIST_FOREACH(rstream, &card->streams, next) {
920 if ((rstream->use & AUICH_USE_RECORD) == 0 ||
921 (rstream->state & AUICH_STATE_STARTED) == 0)
922 continue;
923 if (rstream->update_needed)
924 break;
925 }
926
927 if (!pstream)
928 pstream = card->pstream;
929 if (!rstream)
930 rstream = card->rstream;
931
932 /* do playback */
933 buffer_info.playback_buffer_cycle = pstream->buffer_cycle;
934 buffer_info.played_real_time = pstream->real_time;
935 buffer_info.played_frames_count = pstream->frames_count;
936 buffer_info._reserved_0 = pstream->first_channel;
937 pstream->update_needed = false;
938
939 /* do record */
940 buffer_info.record_buffer_cycle = rstream->buffer_cycle;
941 buffer_info.recorded_frames_count = rstream->frames_count;
942 buffer_info.recorded_real_time = rstream->real_time;
943 buffer_info._reserved_1 = rstream->first_channel;
944 rstream->update_needed = false;
945 unlock(status);
946
947 #ifdef __HAIKU__
948 if (user_memcpy(data, &buffer_info, sizeof(buffer_info)) < B_OK)
949 return B_BAD_ADDRESS;
950 #else
951 memcpy(data, &buffer_info, sizeof(buffer_info));
952 #endif
953
954 //TRACE(("buffer_exchange ended\n"));
955 return B_OK;
956 }
957
958
959 static status_t
auich_buffer_force_stop(auich_dev * card)960 auich_buffer_force_stop(auich_dev *card)
961 {
962 //auich_voice_halt(card->pvoice);
963 return B_OK;
964 }
965
966
967 #define cookie_type auich_dev
968 #define get_description auich_get_description
969 #define get_enabled_channels auich_get_enabled_channels
970 #define get_global_format auich_get_global_format
971 #define set_global_format auich_set_global_format
972 #define list_mix_channels auich_list_mix_channels
973 #define list_mix_controls auich_list_mix_controls
974 #define list_mix_connections auich_list_mix_connections
975 #define get_mix auich_get_mix
976 #define set_mix auich_set_mix
977 #define get_buffers auich_get_buffers
978 #define buffer_exchange auich_buffer_exchange
979 #define buffer_force_stop auich_buffer_force_stop
980 #include "../generic/multi.c"
981
982
983 static status_t
auich_multi_control(void * cookie,uint32 op,void * arg,size_t length)984 auich_multi_control(void *cookie, uint32 op, void *arg, size_t length)
985 {
986 auich_dev *card = (auich_dev *)cookie;
987
988 return multi_audio_control_generic(card, op, arg, length);
989 }
990
991 static status_t auich_open(const char *name, uint32 flags, void** cookie);
992 static status_t auich_close(void* cookie);
993 static status_t auich_free(void* cookie);
994 static status_t auich_control(void* cookie, uint32 op, void* arg, size_t len);
995 static status_t auich_read(void* cookie, off_t position, void *buf, size_t* num_bytes);
996 static status_t auich_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes);
997
998 device_hooks multi_hooks = {
999 auich_open, /* -> open entry point */
1000 auich_close, /* -> close entry point */
1001 auich_free, /* -> free cookie */
1002 auich_control, /* -> control entry point */
1003 auich_read, /* -> read entry point */
1004 auich_write, /* -> write entry point */
1005 NULL, /* start select */
1006 NULL, /* stop select */
1007 NULL, /* scatter-gather read from the device */
1008 NULL /* scatter-gather write to the device */
1009 };
1010
1011
1012 static status_t
auich_open(const char * name,uint32 flags,void ** cookie)1013 auich_open(const char *name, uint32 flags, void** cookie)
1014 {
1015 auich_dev *card = NULL;
1016 void *settings_handle;
1017 int ix;
1018
1019 LOG(("open()\n"));
1020
1021 for (ix=0; ix<num_cards; ix++) {
1022 if (!strcmp(cards[ix].name, name)) {
1023 card = &cards[ix];
1024 }
1025 }
1026
1027 if (card == NULL) {
1028 LOG(("open() card not found %s\n", name));
1029 for (ix=0; ix<num_cards; ix++) {
1030 LOG(("open() card available %s\n", cards[ix].name));
1031 }
1032 return B_ERROR;
1033 }
1034
1035 LOG(("open() got card\n"));
1036
1037 if (card->pstream !=NULL)
1038 return B_ERROR;
1039 if (card->rstream !=NULL)
1040 return B_ERROR;
1041
1042 *cookie = card;
1043 card->multi.card = card;
1044
1045 // get driver settings
1046 settings_handle = load_driver_settings(AUICH_SETTINGS);
1047 if (settings_handle != NULL) {
1048 const char *item;
1049 char *end;
1050 uint32 value;
1051
1052 item = get_driver_parameter (settings_handle, "sample_rate", "48000", "48000");
1053 value = strtoul (item, &end, 0);
1054 if (*end == '\0')
1055 current_settings.sample_rate = value;
1056
1057 item = get_driver_parameter (settings_handle, "buffer_frames", "256", "256");
1058 value = strtoul (item, &end, 0);
1059 if (*end == '\0')
1060 current_settings.buffer_frames = value;
1061
1062 item = get_driver_parameter (settings_handle, "buffer_count", "4", "4");
1063 value = strtoul (item, &end, 0);
1064 if (*end == '\0')
1065 current_settings.buffer_count = value;
1066
1067 unload_driver_settings(settings_handle);
1068 }
1069
1070 LOG(("stream_new\n"));
1071
1072 card->rstream = auich_stream_new(card, AUICH_USE_RECORD, current_settings.buffer_frames, current_settings.buffer_count);
1073 card->pstream = auich_stream_new(card, AUICH_USE_PLAY, current_settings.buffer_frames, current_settings.buffer_count);
1074
1075 card->buffer_ready_sem = create_sem(0, "pbuffer ready");
1076
1077 LOG(("stream_setaudio\n"));
1078
1079 auich_stream_set_audioparms(card->pstream, 2, true, current_settings.sample_rate);
1080 auich_stream_set_audioparms(card->rstream, 2, true, current_settings.sample_rate);
1081
1082 card->pstream->first_channel = 0;
1083 card->rstream->first_channel = 2;
1084
1085 auich_stream_commit_parms(card->pstream);
1086 auich_stream_commit_parms(card->rstream);
1087
1088 auich_create_channels_list(&card->multi);
1089
1090 return B_OK;
1091 }
1092
1093
1094 static status_t
auich_close(void * cookie)1095 auich_close(void* cookie)
1096 {
1097 //auich_dev *card = cookie;
1098 LOG(("close()\n"));
1099
1100 return B_OK;
1101 }
1102
1103
1104 static status_t
auich_free(void * cookie)1105 auich_free(void* cookie)
1106 {
1107 auich_dev *card = cookie;
1108 auich_stream *stream;
1109 LOG(("free()\n"));
1110
1111 if (card->buffer_ready_sem > B_OK)
1112 delete_sem(card->buffer_ready_sem);
1113
1114 LIST_FOREACH(stream, &card->streams, next) {
1115 auich_stream_halt(stream);
1116 }
1117
1118 while (!LIST_EMPTY(&card->streams)) {
1119 auich_stream_delete(LIST_FIRST(&card->streams));
1120 }
1121
1122 card->pstream = NULL;
1123 card->rstream = NULL;
1124
1125 return B_OK;
1126 }
1127
1128
1129 static status_t
auich_control(void * cookie,uint32 op,void * arg,size_t len)1130 auich_control(void* cookie, uint32 op, void* arg, size_t len)
1131 {
1132 return auich_multi_control(cookie, op, arg, len);
1133 }
1134
1135
1136 static status_t
auich_read(void * cookie,off_t position,void * buf,size_t * num_bytes)1137 auich_read(void* cookie, off_t position, void *buf, size_t* num_bytes)
1138 {
1139 *num_bytes = 0; /* tell caller nothing was read */
1140 return B_IO_ERROR;
1141 }
1142
1143
1144 static status_t
auich_write(void * cookie,off_t position,const void * buffer,size_t * num_bytes)1145 auich_write(void* cookie, off_t position, const void* buffer, size_t* num_bytes)
1146 {
1147 *num_bytes = 0; /* tell caller nothing was written */
1148 return B_IO_ERROR;
1149 }
1150