2 * Auich BeOS Driver for Intel Southbridge audio
4 * Copyright (c) 2003, Jerome Duval (jerome.duval@free.fr)
6 * Original code : BeOS Driver for Intel ICH AC'97 Link interface
7 * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
10 * Redistribution and use in source and binary forms, with or without modification,
11 * are permitted provided that the following conditions are met:
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.
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.
32 #include <driver_settings.h>
34 #include <MediaDefs.h>
36 #include "hmulti_audio.h"
49 auich_ac97_get_mix(void *card
, const void *cookie
, int32 type
, float *values
) {
50 auich_dev
*dev
= (auich_dev
*)card
;
51 ac97_source_info
*info
= (ac97_source_info
*)cookie
;
57 value
= auich_codec_read(&dev
->config
, info
->reg
);
58 //PRINT(("B_MIX_GAIN value : %u\n", value));
59 if (info
->type
& B_MIX_STEREO
) {
60 mask
= ((1 << (info
->bits
+ 1)) - 1) << 8;
61 gain
= ((value
& mask
) >> 8) * info
->granularity
;
62 if (info
->polarity
== 1)
63 values
[0] = info
->max_gain
- gain
;
65 values
[0] = gain
- info
->min_gain
;
67 mask
= ((1 << (info
->bits
+ 1)) - 1);
68 gain
= (value
& mask
) * info
->granularity
;
69 if (info
->polarity
== 1)
70 values
[1] = info
->max_gain
- gain
;
72 values
[1] = gain
- info
->min_gain
;
74 mask
= ((1 << (info
->bits
+ 1)) - 1);
75 gain
= (value
& mask
) * info
->granularity
;
76 if (info
->polarity
== 1)
77 values
[0] = info
->max_gain
- gain
;
79 values
[0] = gain
- info
->min_gain
;
83 mask
= ((1 << 1) - 1) << 15;
84 value
= auich_codec_read(&dev
->config
, info
->reg
);
85 //PRINT(("B_MIX_MUTE value : %u\n", value));
87 values
[0] = ((value
>> 15) == 1) ? 1.0 : 0.0;
90 mask
= ((1 << 1) - 1) << 6;
91 value
= auich_codec_read(&dev
->config
, info
->reg
);
92 //PRINT(("B_MIX_MICBOOST value : %u\n", value));
94 values
[0] = ((value
>> 6) == 1) ? 1.0 : 0.0;
97 mask
= ((1 << 3) - 1);
98 value
= auich_codec_read(&dev
->config
, AC97_RECORD_SELECT
);
100 //PRINT(("B_MIX_MUX value : %u\n", value));
101 values
[0] = (float)value
;
108 auich_ac97_set_mix(void *card
, const void *cookie
, int32 type
, float *values
) {
109 auich_dev
*dev
= (auich_dev
*)card
;
110 ac97_source_info
*info
= (ac97_source_info
*)cookie
;
116 value
= auich_codec_read(&dev
->config
, info
->reg
);
117 if (info
->type
& B_MIX_STEREO
) {
118 mask
= ((1 << (info
->bits
+ 1)) - 1) << 8;
121 if (info
->polarity
== 1)
122 gain
= info
->max_gain
- values
[0];
124 gain
= values
[0] - info
->min_gain
;
125 value
|= ((uint16
)(gain
/ info
->granularity
) << 8) & mask
;
127 mask
= ((1 << (info
->bits
+ 1)) - 1);
129 if (info
->polarity
== 1)
130 gain
= info
->max_gain
- values
[1];
132 gain
= values
[1] - info
->min_gain
;
133 value
|= ((uint16
)(gain
/ info
->granularity
)) & mask
;
135 mask
= ((1 << (info
->bits
+ 1)) - 1);
137 if (info
->polarity
== 1)
138 gain
= info
->max_gain
- values
[0];
140 gain
= values
[0] - info
->min_gain
;
141 value
|= ((uint16
)(gain
/ info
->granularity
)) & mask
;
143 //PRINT(("B_MIX_GAIN value : %u\n", value));
144 auich_codec_write(&dev
->config
, info
->reg
, value
);
147 mask
= ((1 << 1) - 1) << 15;
148 value
= auich_codec_read(&dev
->config
, info
->reg
);
150 value
|= ((values
[0] == 1.0 ? 1 : 0 ) << 15 & mask
);
151 if (info
->reg
== AC97_SURR_VOLUME
) {
152 // there is a independent mute for each channel
153 mask
= ((1 << 1) - 1) << 7;
155 value
|= ((values
[0] == 1.0 ? 1 : 0 ) << 7 & mask
);
157 //PRINT(("B_MIX_MUTE value : %u\n", value));
158 auich_codec_write(&dev
->config
, info
->reg
, value
);
161 mask
= ((1 << 1) - 1) << 6;
162 value
= auich_codec_read(&dev
->config
, info
->reg
);
164 value
|= ((values
[0] == 1.0 ? 1 : 0 ) << 6 & mask
);
165 //PRINT(("B_MIX_MICBOOST value : %u\n", value));
166 auich_codec_write(&dev
->config
, info
->reg
, value
);
169 mask
= ((1 << 3) - 1);
170 value
= ((int32
)values
[0]) & mask
;
171 value
= value
| (value
<< 8);
172 //PRINT(("B_MIX_MUX value : %u\n", value));
173 auich_codec_write(&dev
->config
, AC97_RECORD_SELECT
, value
);
181 auich_create_group_control(multi_dev
*multi
, int32
*index
, int32 parent
,
182 int32 string
, const char* name
) {
185 multi
->controls
[i
].mix_control
.id
= EMU_MULTI_CONTROL_FIRSTID
+ i
;
186 multi
->controls
[i
].mix_control
.parent
= parent
;
187 multi
->controls
[i
].mix_control
.flags
= B_MULTI_MIX_GROUP
;
188 multi
->controls
[i
].mix_control
.master
= EMU_MULTI_CONTROL_MASTERID
;
189 multi
->controls
[i
].mix_control
.string
= string
;
191 strcpy(multi
->controls
[i
].mix_control
.name
, name
);
193 return multi
->controls
[i
].mix_control
.id
;
198 auich_create_controls_list(multi_dev
*multi
)
200 uint32 i
= 0, index
= 0, count
, id
, parent
, parent2
, parent3
;
201 const ac97_source_info
*info
;
204 parent
= auich_create_group_control(multi
, &index
, 0, 0, "AC97 mixer");
206 count
= source_info_size
;
207 //Note that we ignore first item in source_info
208 //It's for recording, but do match this with ac97.c's source_info
209 for (i
= 1; i
< count
; i
++) {
210 info
= &source_info
[i
];
211 PRINT(("name : %s\n", info
->name
));
213 parent2
= auich_create_group_control(multi
, &index
, parent
, 0, info
->name
);
215 if (info
->type
& B_MIX_GAIN
) {
216 if (info
->type
& B_MIX_MUTE
) {
217 multi
->controls
[index
].mix_control
.id
= EMU_MULTI_CONTROL_FIRSTID
+ index
;
218 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_ENABLE
;
219 multi
->controls
[index
].mix_control
.master
= EMU_MULTI_CONTROL_MASTERID
;
220 multi
->controls
[index
].mix_control
.parent
= parent2
;
221 multi
->controls
[index
].mix_control
.string
= S_MUTE
;
222 multi
->controls
[index
].cookie
= info
;
223 multi
->controls
[index
].type
= B_MIX_MUTE
;
224 multi
->controls
[index
].get
= &auich_ac97_get_mix
;
225 multi
->controls
[index
].set
= &auich_ac97_set_mix
;
229 multi
->controls
[index
].mix_control
.id
= EMU_MULTI_CONTROL_FIRSTID
+ index
;
230 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_GAIN
;
231 multi
->controls
[index
].mix_control
.master
= EMU_MULTI_CONTROL_MASTERID
;
232 multi
->controls
[index
].mix_control
.parent
= parent2
;
233 strcpy(multi
->controls
[index
].mix_control
.name
, info
->name
);
234 multi
->controls
[index
].mix_control
.u
.gain
.min_gain
= info
->min_gain
;
235 multi
->controls
[index
].mix_control
.u
.gain
.max_gain
= info
->max_gain
;
236 multi
->controls
[index
].mix_control
.u
.gain
.granularity
= info
->granularity
;
237 multi
->controls
[index
].cookie
= info
;
238 multi
->controls
[index
].type
= B_MIX_GAIN
;
239 multi
->controls
[index
].get
= &auich_ac97_get_mix
;
240 multi
->controls
[index
].set
= &auich_ac97_set_mix
;
241 id
= multi
->controls
[index
].mix_control
.id
;
244 if (info
->type
& B_MIX_STEREO
) {
245 multi
->controls
[index
].mix_control
.id
= EMU_MULTI_CONTROL_FIRSTID
+ index
;
246 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_GAIN
;
247 multi
->controls
[index
].mix_control
.master
= id
;
248 multi
->controls
[index
].mix_control
.parent
= parent2
;
249 strcpy(multi
->controls
[index
].mix_control
.name
, info
->name
);
250 multi
->controls
[index
].mix_control
.u
.gain
.min_gain
= info
->min_gain
;
251 multi
->controls
[index
].mix_control
.u
.gain
.max_gain
= info
->max_gain
;
252 multi
->controls
[index
].mix_control
.u
.gain
.granularity
= info
->granularity
;
253 multi
->controls
[index
].cookie
= info
;
254 multi
->controls
[index
].type
= B_MIX_GAIN
;
255 multi
->controls
[index
].get
= &auich_ac97_get_mix
;
256 multi
->controls
[index
].set
= &auich_ac97_set_mix
;
260 if (info
->type
& B_MIX_MICBOOST
) {
261 multi
->controls
[index
].mix_control
.id
= EMU_MULTI_CONTROL_FIRSTID
+ index
;
262 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_ENABLE
;
263 multi
->controls
[index
].mix_control
.master
= EMU_MULTI_CONTROL_MASTERID
;
264 multi
->controls
[index
].mix_control
.parent
= parent2
;
265 strcpy(multi
->controls
[index
].mix_control
.name
, "+20 dB");
266 multi
->controls
[index
].cookie
= info
;
267 multi
->controls
[index
].type
= B_MIX_MICBOOST
;
268 multi
->controls
[index
].get
= &auich_ac97_get_mix
;
269 multi
->controls
[index
].set
= &auich_ac97_set_mix
;
276 parent
= auich_create_group_control(multi
, &index
, 0, 0, "Recording");
278 info
= &source_info
[0];
279 PRINT(("name : %s\n", info
->name
));
281 parent2
= auich_create_group_control(multi
, &index
, parent
, 0, info
->name
);
283 if (info
->type
& B_MIX_GAIN
) {
284 if (info
->type
& B_MIX_MUTE
) {
285 multi
->controls
[index
].mix_control
.id
= EMU_MULTI_CONTROL_FIRSTID
+ index
;
286 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_ENABLE
;
287 multi
->controls
[index
].mix_control
.master
= EMU_MULTI_CONTROL_MASTERID
;
288 multi
->controls
[index
].mix_control
.parent
= parent2
;
289 multi
->controls
[index
].mix_control
.string
= S_MUTE
;
290 multi
->controls
[index
].cookie
= info
;
291 multi
->controls
[index
].type
= B_MIX_MUTE
;
292 multi
->controls
[index
].get
= &auich_ac97_get_mix
;
293 multi
->controls
[index
].set
= &auich_ac97_set_mix
;
297 multi
->controls
[index
].mix_control
.id
= EMU_MULTI_CONTROL_FIRSTID
+ index
;
298 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_GAIN
;
299 multi
->controls
[index
].mix_control
.master
= EMU_MULTI_CONTROL_MASTERID
;
300 multi
->controls
[index
].mix_control
.parent
= parent2
;
301 strcpy(multi
->controls
[index
].mix_control
.name
, info
->name
);
302 multi
->controls
[index
].mix_control
.u
.gain
.min_gain
= info
->min_gain
;
303 multi
->controls
[index
].mix_control
.u
.gain
.max_gain
= info
->max_gain
;
304 multi
->controls
[index
].mix_control
.u
.gain
.granularity
= info
->granularity
;
305 multi
->controls
[index
].cookie
= info
;
306 multi
->controls
[index
].type
= B_MIX_GAIN
;
307 multi
->controls
[index
].get
= &auich_ac97_get_mix
;
308 multi
->controls
[index
].set
= &auich_ac97_set_mix
;
309 id
= multi
->controls
[index
].mix_control
.id
;
312 if (info
->type
& B_MIX_STEREO
) {
313 multi
->controls
[index
].mix_control
.id
= EMU_MULTI_CONTROL_FIRSTID
+ index
;
314 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_GAIN
;
315 multi
->controls
[index
].mix_control
.master
= id
;
316 multi
->controls
[index
].mix_control
.parent
= parent2
;
317 strcpy(multi
->controls
[index
].mix_control
.name
, info
->name
);
318 multi
->controls
[index
].mix_control
.u
.gain
.min_gain
= info
->min_gain
;
319 multi
->controls
[index
].mix_control
.u
.gain
.max_gain
= info
->max_gain
;
320 multi
->controls
[index
].mix_control
.u
.gain
.granularity
= info
->granularity
;
321 multi
->controls
[index
].cookie
= info
;
322 multi
->controls
[index
].type
= B_MIX_GAIN
;
323 multi
->controls
[index
].get
= &auich_ac97_get_mix
;
324 multi
->controls
[index
].set
= &auich_ac97_set_mix
;
328 if (info
->type
& B_MIX_RECORDMUX
) {
329 multi
->controls
[index
].mix_control
.id
= EMU_MULTI_CONTROL_FIRSTID
+ index
;
330 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX
;
331 multi
->controls
[index
].mix_control
.parent
= parent2
;
332 strcpy(multi
->controls
[index
].mix_control
.name
, "Record mux");
333 multi
->controls
[index
].cookie
= info
;
334 multi
->controls
[index
].type
= B_MIX_MUX
;
335 multi
->controls
[index
].get
= &auich_ac97_get_mix
;
336 multi
->controls
[index
].set
= &auich_ac97_set_mix
;
337 parent3
= multi
->controls
[index
].mix_control
.id
;
340 multi
->controls
[index
].mix_control
.id
= EMU_MULTI_CONTROL_FIRSTID
+ index
;
341 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX_VALUE
;
342 multi
->controls
[index
].mix_control
.parent
= parent3
;
343 multi
->controls
[index
].mix_control
.string
= S_MIC
;
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 strcpy(multi
->controls
[index
].mix_control
.name
, "CD in");
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
, "Video in");
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
, "Aux in");
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
, "Line in");
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 multi
->controls
[index
].mix_control
.string
= S_STEREO_MIX
;
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_MONO_MIX
;
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 strcpy(multi
->controls
[index
].mix_control
.name
, "TAD");
383 multi
->control_count
= index
;
384 PRINT(("multi->control_count %lu\n", multi
->control_count
));
390 auich_get_mix(auich_dev
*card
, multi_mix_value_info
* mmvi
)
393 multi_mixer_control
*control
= NULL
;
394 for (i
= 0; i
< mmvi
->item_count
; i
++) {
395 id
= mmvi
->values
[i
].id
- EMU_MULTI_CONTROL_FIRSTID
;
396 if (id
< 0 || id
>= card
->multi
.control_count
) {
397 PRINT(("auich_get_mix : invalid control id requested : %li\n", id
));
400 control
= &card
->multi
.controls
[id
];
402 if (control
->mix_control
.flags
& B_MULTI_MIX_GAIN
) {
405 control
->get(card
, control
->cookie
, control
->type
, values
);
406 if (control
->mix_control
.master
== EMU_MULTI_CONTROL_MASTERID
)
407 mmvi
->values
[i
].u
.gain
= values
[0];
409 mmvi
->values
[i
].u
.gain
= values
[1];
413 if (control
->mix_control
.flags
& B_MULTI_MIX_ENABLE
&& control
->get
) {
415 control
->get(card
, control
->cookie
, control
->type
, values
);
416 mmvi
->values
[i
].u
.enable
= (values
[0] == 1.0);
419 if (control
->mix_control
.flags
& B_MULTI_MIX_MUX
&& control
->get
) {
421 control
->get(card
, control
->cookie
, control
->type
, values
);
422 mmvi
->values
[i
].u
.mux
= (int32
)values
[0];
430 auich_set_mix(auich_dev
*card
, multi_mix_value_info
* mmvi
)
433 multi_mixer_control
*control
= NULL
;
434 for (i
= 0; i
< mmvi
->item_count
; i
++) {
435 id
= mmvi
->values
[i
].id
- EMU_MULTI_CONTROL_FIRSTID
;
436 if (id
< 0 || id
>= card
->multi
.control_count
) {
437 PRINT(("auich_set_mix : invalid control id requested : %li\n", id
));
440 control
= &card
->multi
.controls
[id
];
442 if (control
->mix_control
.flags
& B_MULTI_MIX_GAIN
) {
443 multi_mixer_control
*control2
= NULL
;
444 if (i
+1<mmvi
->item_count
) {
445 id
= mmvi
->values
[i
+ 1].id
- EMU_MULTI_CONTROL_FIRSTID
;
446 if (id
< 0 || id
>= card
->multi
.control_count
) {
447 PRINT(("auich_set_mix : invalid control id requested : %li\n", id
));
449 control2
= &card
->multi
.controls
[id
];
450 if (control2
->mix_control
.master
!= control
->mix_control
.id
)
460 if (control
->mix_control
.master
== EMU_MULTI_CONTROL_MASTERID
)
461 values
[0] = mmvi
->values
[i
].u
.gain
;
463 values
[1] = mmvi
->values
[i
].u
.gain
;
465 if (control2
&& control2
->mix_control
.master
!= EMU_MULTI_CONTROL_MASTERID
)
466 values
[1] = mmvi
->values
[i
+1].u
.gain
;
468 control
->set(card
, control
->cookie
, control
->type
, values
);
475 if (control
->mix_control
.flags
& B_MULTI_MIX_ENABLE
&& control
->set
) {
478 values
[0] = mmvi
->values
[i
].u
.enable
? 1.0 : 0.0;
479 control
->set(card
, control
->cookie
, control
->type
, values
);
482 if (control
->mix_control
.flags
& B_MULTI_MIX_MUX
&& control
->set
) {
485 values
[0] = (float)mmvi
->values
[i
].u
.mux
;
486 control
->set(card
, control
->cookie
, control
->type
, values
);
494 auich_list_mix_controls(auich_dev
*card
, multi_mix_control_info
* mmci
)
496 multi_mix_control
*mmc
;
499 mmc
= mmci
->controls
;
500 if (mmci
->control_count
< 24)
503 if (auich_create_controls_list(&card
->multi
) < B_OK
)
505 for (i
= 0; i
< card
->multi
.control_count
; i
++) {
506 mmc
[i
] = card
->multi
.controls
[i
].mix_control
;
509 mmci
->control_count
= card
->multi
.control_count
;
515 auich_list_mix_connections(auich_dev
*card
, multi_mix_connection_info
* data
)
522 auich_list_mix_channels(auich_dev
*card
, multi_mix_channel_info
*data
)
527 /*multi_channel_info chans[] = {
528 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
529 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
530 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
531 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
532 { 4, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
533 { 5, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
534 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
535 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
536 { 8, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
537 { 9, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
538 { 10, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
539 { 11, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
542 /*multi_channel_info chans[] = {
543 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
544 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
545 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_SURROUND_BUS, 0 },
546 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_SURROUND_BUS, 0 },
547 { 4, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARLEFT | B_CHANNEL_SURROUND_BUS, 0 },
548 { 5, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARRIGHT | B_CHANNEL_SURROUND_BUS, 0 },
549 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
550 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
551 { 8, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
552 { 9, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
553 { 10, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
554 { 11, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
555 { 12, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
556 { 13, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
561 auich_create_channels_list(multi_dev
*multi
)
563 auich_stream
*stream
;
564 uint32 index
, i
, mode
, designations
;
565 multi_channel_info
*chans
;
566 uint32 chan_designations
[] = {
575 chans
= multi
->chans
;
578 for (mode
=AUICH_USE_PLAY
; mode
!=-1;
579 mode
= (mode
== AUICH_USE_PLAY
) ? AUICH_USE_RECORD
: -1) {
580 LIST_FOREACH(stream
, &((auich_dev
*)multi
->card
)->streams
, next
) {
581 if ((stream
->use
& mode
) == 0)
584 if (stream
->channels
== 2)
585 designations
= B_CHANNEL_STEREO_BUS
;
587 designations
= B_CHANNEL_SURROUND_BUS
;
589 for (i
= 0; i
< stream
->channels
; i
++) {
590 chans
[index
].channel_id
= index
;
591 chans
[index
].kind
= (mode
== AUICH_USE_PLAY
) ? B_MULTI_OUTPUT_CHANNEL
: B_MULTI_INPUT_CHANNEL
;
592 chans
[index
].designations
= designations
| chan_designations
[i
];
593 chans
[index
].connectors
= 0;
598 if (mode
==AUICH_USE_PLAY
) {
599 multi
->output_channel_count
= index
;
601 multi
->input_channel_count
= index
- multi
->output_channel_count
;
605 chans
[index
].channel_id
= index
;
606 chans
[index
].kind
= B_MULTI_OUTPUT_BUS
;
607 chans
[index
].designations
= B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
;
608 chans
[index
].connectors
= B_CHANNEL_MINI_JACK_STEREO
;
611 chans
[index
].channel_id
= index
;
612 chans
[index
].kind
= B_MULTI_OUTPUT_BUS
;
613 chans
[index
].designations
= B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
;
614 chans
[index
].connectors
= B_CHANNEL_MINI_JACK_STEREO
;
617 multi
->output_bus_channel_count
= index
- multi
->output_channel_count
618 - multi
->input_channel_count
;
620 chans
[index
].channel_id
= index
;
621 chans
[index
].kind
= B_MULTI_INPUT_BUS
;
622 chans
[index
].designations
= B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
;
623 chans
[index
].connectors
= B_CHANNEL_MINI_JACK_STEREO
;
626 chans
[index
].channel_id
= index
;
627 chans
[index
].kind
= B_MULTI_INPUT_BUS
;
628 chans
[index
].designations
= B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
;
629 chans
[index
].connectors
= B_CHANNEL_MINI_JACK_STEREO
;
632 multi
->input_bus_channel_count
= index
- multi
->output_channel_count
633 - multi
->input_channel_count
- multi
->output_bus_channel_count
;
635 multi
->aux_bus_channel_count
= 0;
640 auich_get_description(auich_dev
*card
, multi_description
*data
)
644 data
->interface_version
= B_CURRENT_INTERFACE_VERSION
;
645 data
->interface_minimum
= B_CURRENT_INTERFACE_VERSION
;
647 switch(card
->info
.vendor_id
) {
648 case INTEL_VENDOR_ID
:
649 strncpy(data
->friendly_name
, FRIENDLY_NAME_ICH
, 32);
652 strncpy(data
->friendly_name
, FRIENDLY_NAME_SIS
, 32);
654 case NVIDIA_VENDOR_ID
:
655 strncpy(data
->friendly_name
, FRIENDLY_NAME_NVIDIA
, 32);
658 strncpy(data
->friendly_name
, FRIENDLY_NAME_AMD
, 32);
662 strcpy(data
->vendor_info
, AUTHOR
);
664 /*data->output_channel_count = 6;
665 data->input_channel_count = 4;
666 data->output_bus_channel_count = 2;
667 data->input_bus_channel_count = 2;
668 data->aux_bus_channel_count = 0;*/
670 data
->output_channel_count
= card
->multi
.output_channel_count
;
671 data
->input_channel_count
= card
->multi
.input_channel_count
;
672 data
->output_bus_channel_count
= card
->multi
.output_bus_channel_count
;
673 data
->input_bus_channel_count
= card
->multi
.input_bus_channel_count
;
674 data
->aux_bus_channel_count
= card
->multi
.aux_bus_channel_count
;
676 size
= card
->multi
.output_channel_count
+ card
->multi
.input_channel_count
677 + card
->multi
.output_bus_channel_count
+ card
->multi
.input_bus_channel_count
678 + card
->multi
.aux_bus_channel_count
;
680 // for each channel, starting with the first output channel,
681 // then the second, third..., followed by the first input
682 // channel, second, third, ..., followed by output bus
683 // channels and input bus channels and finally auxillary channels,
685 LOG(("request_channel_count = %d\n",data
->request_channel_count
));
686 if (data
->request_channel_count
>= size
) {
687 LOG(("copying data\n"));
688 memcpy(data
->channels
, card
->multi
.chans
, size
* sizeof(card
->multi
.chans
[0]));
691 switch (current_settings
.sample_rate
) {
692 case 48000: data
->output_rates
= data
->input_rates
= B_SR_48000
; break;
693 case 44100: data
->output_rates
= data
->input_rates
= B_SR_44100
; break;
695 data
->min_cvsr_rate
= 0;
696 data
->max_cvsr_rate
= 48000;
698 data
->output_formats
= B_FMT_16BIT
;
699 data
->input_formats
= B_FMT_16BIT
;
700 data
->lock_sources
= B_MULTI_LOCK_INTERNAL
;
701 data
->timecode_sources
= 0;
702 data
->interface_flags
= B_MULTI_INTERFACE_PLAYBACK
| B_MULTI_INTERFACE_RECORD
;
703 data
->start_latency
= 3000;
705 strcpy(data
->control_panel
,"");
712 auich_get_enabled_channels(auich_dev
*card
, multi_channel_enable
*data
)
714 B_SET_CHANNEL(data
->enable_bits
, 0, true);
715 B_SET_CHANNEL(data
->enable_bits
, 1, true);
716 B_SET_CHANNEL(data
->enable_bits
, 2, true);
717 B_SET_CHANNEL(data
->enable_bits
, 3, true);
718 data
->lock_source
= B_MULTI_LOCK_INTERNAL
;
722 uint32 timecode_source;
730 auich_set_enabled_channels(auich_dev
*card
, multi_channel_enable
*data
)
732 PRINT(("set_enabled_channels 0 : %s\n", B_TEST_CHANNEL(data
->enable_bits
, 0) ? "enabled": "disabled"));
733 PRINT(("set_enabled_channels 1 : %s\n", B_TEST_CHANNEL(data
->enable_bits
, 1) ? "enabled": "disabled"));
734 PRINT(("set_enabled_channels 2 : %s\n", B_TEST_CHANNEL(data
->enable_bits
, 2) ? "enabled": "disabled"));
735 PRINT(("set_enabled_channels 3 : %s\n", B_TEST_CHANNEL(data
->enable_bits
, 3) ? "enabled": "disabled"));
741 auich_get_global_format(auich_dev
*card
, multi_format_info
*data
)
743 data
->output_latency
= 0;
744 data
->input_latency
= 0;
745 data
->timecode_kind
= 0;
746 switch (current_settings
.sample_rate
) {
748 data
->input
.rate
= data
->output
.rate
= B_SR_48000
;
749 data
->input
.cvsr
= data
->output
.cvsr
= 48000;
752 data
->input
.rate
= data
->output
.rate
= B_SR_44100
;
753 data
->input
.cvsr
= data
->output
.cvsr
= 44100;
756 data
->input
.format
= data
->output
.format
= B_FMT_16BIT
;
762 auich_get_buffers(auich_dev
*card
, multi_buffer_list
*data
)
764 uint8 i
, j
, pchannels
, rchannels
, bufcount
;
766 LOG(("flags = %#x\n",data
->flags
));
767 LOG(("request_playback_buffers = %#x\n",data
->request_playback_buffers
));
768 LOG(("request_playback_channels = %#x\n",data
->request_playback_channels
));
769 LOG(("request_playback_buffer_size = %#x\n",data
->request_playback_buffer_size
));
770 LOG(("request_record_buffers = %#x\n",data
->request_record_buffers
));
771 LOG(("request_record_channels = %#x\n",data
->request_record_channels
));
772 LOG(("request_record_buffer_size = %#x\n",data
->request_record_buffer_size
));
774 pchannels
= card
->pstream
->channels
;
775 rchannels
= card
->rstream
->channels
;
777 if (data
->request_playback_buffers
< current_settings
.buffer_count
||
778 data
->request_playback_channels
< (pchannels
) ||
779 data
->request_record_buffers
< current_settings
.buffer_count
||
780 data
->request_record_channels
< (rchannels
)) {
781 LOG(("not enough channels/buffers\n"));
784 ASSERT(current_settings
.buffer_count
== 2);
786 data
->flags
= B_MULTI_BUFFER_PLAYBACK
| B_MULTI_BUFFER_RECORD
; // XXX ???
789 data
->return_playback_buffers
= current_settings
.buffer_count
; /* playback_buffers[b][] */
790 data
->return_playback_channels
= pchannels
; /* playback_buffers[][c] */
791 data
->return_playback_buffer_size
= current_settings
.buffer_frames
; /* frames */
793 bufcount
= current_settings
.buffer_count
;
794 if (bufcount
> data
->request_playback_buffers
)
795 bufcount
= data
->request_playback_buffers
;
797 for (i
= 0; i
< bufcount
; i
++)
798 for (j
=0; j
<pchannels
; j
++)
799 auich_stream_get_nth_buffer(card
->pstream
, j
, i
,
800 &data
->playback_buffers
[i
][j
].base
,
801 &data
->playback_buffers
[i
][j
].stride
);
803 data
->return_record_buffers
= current_settings
.buffer_count
;
804 data
->return_record_channels
= rchannels
;
805 data
->return_record_buffer_size
= current_settings
.buffer_frames
; /* frames */
807 bufcount
= current_settings
.buffer_count
;
808 if (bufcount
> data
->request_record_buffers
)
809 bufcount
= data
->request_record_buffers
;
811 for (i
= 0; i
< bufcount
; i
++)
812 for (j
=0; j
<rchannels
; j
++)
813 auich_stream_get_nth_buffer(card
->rstream
, j
, i
,
814 &data
->record_buffers
[i
][j
].base
,
815 &data
->record_buffers
[i
][j
].stride
);
822 auich_play_inth(void* inthparams
)
824 auich_stream
*stream
= (auich_stream
*)inthparams
;
827 acquire_spinlock(&slock
);
828 stream
->real_time
= system_time();
829 stream
->frames_count
+= current_settings
.buffer_frames
;
830 stream
->buffer_cycle
= (stream
->trigblk
831 + stream
->blkmod
- 1) % stream
->blkmod
;
832 stream
->update_needed
= true;
833 release_spinlock(&slock
);
835 TRACE(("auich_play_inth : cycle : %d\n", stream
->buffer_cycle
));
837 //get_sem_count(stream->card->buffer_ready_sem, &count);
839 release_sem_etc(stream
->card
->buffer_ready_sem
, 1, B_DO_NOT_RESCHEDULE
);
844 auich_record_inth(void* inthparams
)
846 auich_stream
*stream
= (auich_stream
*)inthparams
;
849 acquire_spinlock(&slock
);
850 stream
->real_time
= system_time();
851 stream
->frames_count
+= current_settings
.buffer_frames
;
852 stream
->buffer_cycle
= (stream
->trigblk
853 + stream
->blkmod
- 1) % stream
->blkmod
;
854 stream
->update_needed
= true;
855 release_spinlock(&slock
);
857 TRACE(("auich_record_inth : cycle : %d\n", stream
->buffer_cycle
));
859 //get_sem_count(stream->card->buffer_ready_sem, &count);
861 release_sem_etc(stream
->card
->buffer_ready_sem
, 1, B_DO_NOT_RESCHEDULE
);
866 auich_buffer_exchange(auich_dev
*card
, multi_buffer_info
*data
)
869 auich_stream
*pstream
, *rstream
;
870 multi_buffer_info buffer_info
;
873 if (user_memcpy(&buffer_info
, data
, sizeof(buffer_info
)) < B_OK
)
874 return B_BAD_ADDRESS
;
876 memcpy(&buffer_info
, data
, sizeof(buffer_info
));
879 buffer_info
.flags
= B_MULTI_BUFFER_PLAYBACK
| B_MULTI_BUFFER_RECORD
;
881 if (!(card
->pstream
->state
& AUICH_STATE_STARTED
))
882 auich_stream_start(card
->pstream
, auich_play_inth
, card
->pstream
);
884 if (!(card
->rstream
->state
& AUICH_STATE_STARTED
))
885 auich_stream_start(card
->rstream
, auich_record_inth
, card
->rstream
);
887 if (acquire_sem_etc(card
->buffer_ready_sem
, 1, B_RELATIVE_TIMEOUT
| B_CAN_INTERRUPT
, 50000)
889 LOG(("buffer_exchange timeout ff\n"));
894 LIST_FOREACH(pstream
, &card
->streams
, next
) {
895 if ((pstream
->use
& AUICH_USE_PLAY
) == 0 ||
896 (pstream
->state
& AUICH_STATE_STARTED
) == 0)
898 if (pstream
->update_needed
)
902 LIST_FOREACH(rstream
, &card
->streams
, next
) {
903 if ((rstream
->use
& AUICH_USE_RECORD
) == 0 ||
904 (rstream
->state
& AUICH_STATE_STARTED
) == 0)
906 if (rstream
->update_needed
)
911 pstream
= card
->pstream
;
913 rstream
= card
->rstream
;
916 buffer_info
.playback_buffer_cycle
= pstream
->buffer_cycle
;
917 buffer_info
.played_real_time
= pstream
->real_time
;
918 buffer_info
.played_frames_count
= pstream
->frames_count
;
919 buffer_info
._reserved_0
= pstream
->first_channel
;
920 pstream
->update_needed
= false;
923 buffer_info
.record_buffer_cycle
= rstream
->buffer_cycle
;
924 buffer_info
.recorded_frames_count
= rstream
->frames_count
;
925 buffer_info
.recorded_real_time
= rstream
->real_time
;
926 buffer_info
._reserved_1
= rstream
->first_channel
;
927 rstream
->update_needed
= false;
931 if (user_memcpy(data
, &buffer_info
, sizeof(buffer_info
)) < B_OK
)
932 return B_BAD_ADDRESS
;
934 memcpy(data
, &buffer_info
, sizeof(buffer_info
));
937 //TRACE(("buffer_exchange ended\n"));
943 auich_buffer_force_stop(auich_dev
*card
)
945 //auich_voice_halt(card->pvoice);
951 auich_multi_control(void *cookie
, uint32 op
, void *data
, size_t length
)
953 auich_dev
*card
= (auich_dev
*)cookie
;
956 case B_MULTI_GET_DESCRIPTION
:
957 LOG(("B_MULTI_GET_DESCRIPTION\n"));
958 return auich_get_description(card
, (multi_description
*)data
);
959 case B_MULTI_GET_EVENT_INFO
:
960 LOG(("B_MULTI_GET_EVENT_INFO\n"));
962 case B_MULTI_SET_EVENT_INFO
:
963 LOG(("B_MULTI_SET_EVENT_INFO\n"));
965 case B_MULTI_GET_EVENT
:
966 LOG(("B_MULTI_GET_EVENT\n"));
968 case B_MULTI_GET_ENABLED_CHANNELS
:
969 LOG(("B_MULTI_GET_ENABLED_CHANNELS\n"));
970 return auich_get_enabled_channels(card
, (multi_channel_enable
*)data
);
971 case B_MULTI_SET_ENABLED_CHANNELS
:
972 LOG(("B_MULTI_SET_ENABLED_CHANNELS\n"));
973 return auich_set_enabled_channels(card
, (multi_channel_enable
*)data
);
974 case B_MULTI_GET_GLOBAL_FORMAT
:
975 LOG(("B_MULTI_GET_GLOBAL_FORMAT\n"));
976 return auich_get_global_format(card
, (multi_format_info
*)data
);
977 case B_MULTI_SET_GLOBAL_FORMAT
:
978 LOG(("B_MULTI_SET_GLOBAL_FORMAT\n"));
979 return B_OK
; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent
980 * BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT
982 case B_MULTI_GET_CHANNEL_FORMATS
:
983 LOG(("B_MULTI_GET_CHANNEL_FORMATS\n"));
985 case B_MULTI_SET_CHANNEL_FORMATS
: /* only implemented if possible */
986 LOG(("B_MULTI_SET_CHANNEL_FORMATS\n"));
988 case B_MULTI_GET_MIX
:
989 LOG(("B_MULTI_GET_MIX\n"));
990 return auich_get_mix(card
, (multi_mix_value_info
*)data
);
991 case B_MULTI_SET_MIX
:
992 LOG(("B_MULTI_SET_MIX\n"));
993 return auich_set_mix(card
, (multi_mix_value_info
*)data
);
994 case B_MULTI_LIST_MIX_CHANNELS
:
995 LOG(("B_MULTI_LIST_MIX_CHANNELS\n"));
996 return auich_list_mix_channels(card
, (multi_mix_channel_info
*)data
);
997 case B_MULTI_LIST_MIX_CONTROLS
:
998 LOG(("B_MULTI_LIST_MIX_CONTROLS\n"));
999 return auich_list_mix_controls(card
, (multi_mix_control_info
*)data
);
1000 case B_MULTI_LIST_MIX_CONNECTIONS
:
1001 LOG(("B_MULTI_LIST_MIX_CONNECTIONS\n"));
1002 return auich_list_mix_connections(card
, (multi_mix_connection_info
*)data
);
1003 case B_MULTI_GET_BUFFERS
: /* Fill out the struct for the first time; doesn't start anything. */
1004 LOG(("B_MULTI_GET_BUFFERS\n"));
1005 return auich_get_buffers(card
, data
);
1006 case B_MULTI_SET_BUFFERS
: /* Set what buffers to use, if the driver supports soft buffers. */
1007 LOG(("B_MULTI_SET_BUFFERS\n"));
1008 return B_ERROR
; /* we do not support soft buffers */
1009 case B_MULTI_SET_START_TIME
: /* When to actually start */
1010 LOG(("B_MULTI_SET_START_TIME\n"));
1012 case B_MULTI_BUFFER_EXCHANGE
: /* stop and go are derived from this being called */
1013 //TRACE(("B_MULTI_BUFFER_EXCHANGE\n"));
1014 return auich_buffer_exchange(card
, (multi_buffer_info
*)data
);
1015 case B_MULTI_BUFFER_FORCE_STOP
: /* force stop of playback, nothing in data */
1016 LOG(("B_MULTI_BUFFER_FORCE_STOP\n"));
1017 return auich_buffer_force_stop(card
);
1019 LOG(("ERROR: unknown multi_control %#x\n",op
));
1023 static status_t
auich_open(const char *name
, uint32 flags
, void** cookie
);
1024 static status_t
auich_close(void* cookie
);
1025 static status_t
auich_free(void* cookie
);
1026 static status_t
auich_control(void* cookie
, uint32 op
, void* arg
, size_t len
);
1027 static status_t
auich_read(void* cookie
, off_t position
, void *buf
, size_t* num_bytes
);
1028 static status_t
auich_write(void* cookie
, off_t position
, const void* buffer
, size_t* num_bytes
);
1030 device_hooks multi_hooks
= {
1031 auich_open
, /* -> open entry point */
1032 auich_close
, /* -> close entry point */
1033 auich_free
, /* -> free cookie */
1034 auich_control
, /* -> control entry point */
1035 auich_read
, /* -> read entry point */
1036 auich_write
, /* -> write entry point */
1037 NULL
, /* start select */
1038 NULL
, /* stop select */
1039 NULL
, /* scatter-gather read from the device */
1040 NULL
/* scatter-gather write to the device */
1045 auich_open(const char *name
, uint32 flags
, void** cookie
)
1047 auich_dev
*card
= NULL
;
1048 void *settings_handle
;
1053 for (ix
=0; ix
<num_cards
; ix
++) {
1054 if (!strcmp(cards
[ix
].name
, name
)) {
1060 LOG(("open() card not found %s\n", name
));
1061 for (ix
=0; ix
<num_cards
; ix
++) {
1062 LOG(("open() card available %s\n", cards
[ix
].name
));
1067 LOG(("open() got card\n"));
1069 if (card
->pstream
!=NULL
)
1071 if (card
->rstream
!=NULL
)
1075 card
->multi
.card
= card
;
1077 // get driver settings
1078 settings_handle
= load_driver_settings(AUICH_SETTINGS
);
1079 if (settings_handle
!= NULL
) {
1084 item
= get_driver_parameter (settings_handle
, "sample_rate", "48000", "48000");
1085 value
= strtoul (item
, &end
, 0);
1087 current_settings
.sample_rate
= value
;
1089 item
= get_driver_parameter (settings_handle
, "buffer_frames", "256", "256");
1090 value
= strtoul (item
, &end
, 0);
1092 current_settings
.buffer_frames
= value
;
1094 item
= get_driver_parameter (settings_handle
, "buffer_count", "4", "4");
1095 value
= strtoul (item
, &end
, 0);
1097 current_settings
.buffer_count
= value
;
1099 unload_driver_settings(settings_handle
);
1102 LOG(("stream_new\n"));
1104 card
->rstream
= auich_stream_new(card
, AUICH_USE_RECORD
, current_settings
.buffer_frames
, current_settings
.buffer_count
);
1105 card
->pstream
= auich_stream_new(card
, AUICH_USE_PLAY
, current_settings
.buffer_frames
, current_settings
.buffer_count
);
1107 card
->buffer_ready_sem
= create_sem(0, "pbuffer ready");
1109 LOG(("stream_setaudio\n"));
1111 auich_stream_set_audioparms(card
->pstream
, 2, true, current_settings
.sample_rate
);
1112 auich_stream_set_audioparms(card
->rstream
, 2, true, current_settings
.sample_rate
);
1114 card
->pstream
->first_channel
= 0;
1115 card
->rstream
->first_channel
= 2;
1117 auich_stream_commit_parms(card
->pstream
);
1118 auich_stream_commit_parms(card
->rstream
);
1120 auich_create_channels_list(&card
->multi
);
1127 auich_close(void* cookie
)
1129 //auich_dev *card = cookie;
1137 auich_free(void* cookie
)
1139 auich_dev
*card
= cookie
;
1140 auich_stream
*stream
;
1143 if (card
->buffer_ready_sem
> B_OK
)
1144 delete_sem(card
->buffer_ready_sem
);
1146 LIST_FOREACH(stream
, &card
->streams
, next
) {
1147 auich_stream_halt(stream
);
1150 while (!LIST_EMPTY(&card
->streams
)) {
1151 auich_stream_delete(LIST_FIRST(&card
->streams
));
1154 card
->pstream
= NULL
;
1155 card
->rstream
= NULL
;
1162 auich_control(void* cookie
, uint32 op
, void* arg
, size_t len
)
1164 return auich_multi_control(cookie
, op
, arg
, len
);
1169 auich_read(void* cookie
, off_t position
, void *buf
, size_t* num_bytes
)
1171 *num_bytes
= 0; /* tell caller nothing was read */
1177 auich_write(void* cookie
, off_t position
, const void* buffer
, size_t* num_bytes
)
1179 *num_bytes
= 0; /* tell caller nothing was written */