source: cmedia/trunk/Lib32/sound.c@ 559

Last change on this file since 559 was 354, checked in by stevenhl, 17 years ago

Import untested baseline cmedia sources, work products and binaries
Binaries and work products should be deleted from repository.
once new builds are verified to work.

File size: 18.4 KB
Line 
1/* $Id: sound.c,v 1.5 2000/07/23 16:21:56 sandervl Exp $ */
2
3//******************************************************************************
4// MMPM/2 to OSS interface translation layer
5//
6// Copyright 2000 Sander van Leeuwen (sandervl@xs4all.nl)
7//
8// This program is free software; you can redistribute it and/or
9// modify it under the terms of the GNU General Public License as
10// published by the Free Software Foundation; either version 2 of
11// the License, or (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public
19// License along with this program; if not, write to the Free
20// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
21// USA.
22//
23//******************************************************************************
24//Note: Opening and closing the mixer device for each mixer command might
25// not be a good idea if the SB Live code changes. (right now it hardly
26// matters)
27#include "hwaccess.h"
28#include <linux/init.h>
29#include <linux/poll.h>
30#include <asm/uaccess.h>
31#include <asm/hardirq.h>
32/*
33#include "..\sblive\icardmid.h"
34#include "..\sblive\cardmi.h"
35#include "..\sblive\midi.h"
36*/
37#define LINUX
38#include <ossidc.h>
39#include <stacktoflat.h>
40
41struct file_operations oss_devices[OSS_MAX_DEVICES];
42
43#ifdef KEE
44 #define STACK_REF(p) ((ULONG)(p))
45#else
46 #define STACK_REF(p) ((ULONG)__StackToFlat((ULONG)p))
47#endif
48
49
50//******************************************************************************
51//******************************************************************************
52
53int register_sound_special(struct file_operations *fops, int unit)
54{
55 memcpy(&oss_devices[OSS_SPECIALID], fops, sizeof(struct file_operations));
56 return OSS_SPECIALID;
57}
58
59//******************************************************************************
60//******************************************************************************
61
62int register_sound_mixer(struct file_operations *fops, int dev)
63{
64 memcpy(&oss_devices[OSS_MIXERID], fops, sizeof(struct file_operations));
65 return OSS_MIXERID;
66}
67
68//******************************************************************************
69//******************************************************************************
70
71int register_sound_midi(struct file_operations *fops, int dev)
72{
73 memcpy(&oss_devices[OSS_MIDIID], fops, sizeof(struct file_operations));
74 return OSS_MIDIID;
75}
76
77//******************************************************************************
78//******************************************************************************
79
80int register_sound_dsp(struct file_operations *fops, int dev)
81{
82 memcpy(&oss_devices[OSS_DSPID], fops, sizeof(struct file_operations));
83 return OSS_DSPID;
84}
85
86//******************************************************************************
87//******************************************************************************
88
89int register_sound_synth(struct file_operations *fops, int dev)
90{
91 memcpy(&oss_devices[OSS_SYNTHID], fops, sizeof(struct file_operations));
92 return OSS_SYNTHID;
93}
94
95//******************************************************************************
96//******************************************************************************
97
98void unregister_sound_special(int unit)
99{
100 memset(&oss_devices[OSS_SPECIALID], 0, sizeof(struct file_operations));
101}
102
103//******************************************************************************
104//******************************************************************************
105
106void unregister_sound_mixer(int unit)
107{
108 memset(&oss_devices[OSS_MIXERID], 0, sizeof(struct file_operations));
109}
110
111//******************************************************************************
112//******************************************************************************
113
114void unregister_sound_midi(int unit)
115{
116 memset(&oss_devices[OSS_MIDIID], 0, sizeof(struct file_operations));
117}
118
119//******************************************************************************
120//******************************************************************************
121
122void unregister_sound_dsp(int unit)
123{
124 memset(&oss_devices[OSS_DSPID], 0, sizeof(struct file_operations));
125}
126
127//******************************************************************************
128//******************************************************************************
129
130void unregister_sound_synth(int unit)
131{
132 memset(&oss_devices[OSS_SYNTHID], 0, sizeof(struct file_operations));
133}
134
135//******************************************************************************
136//******************************************************************************
137
138ULONG OSS32_StreamOpen(ULONG streamtype)
139{
140 struct inode ossinode;
141 struct file ossfile;
142 ULONG ossid = streamtype & OSS_IDMASK;
143
144 if(!oss_devices[ossid].open) {
145 return 0;
146 }
147
148 ossinode.i_rdev = ossid;
149 ossfile.f_flags = 0;
150
151 switch(streamtype) {
152 case OSS_STREAM_WAVEOUT:
153 ossfile.f_mode = FMODE_WRITE;
154 break;
155 case OSS_STREAM_WAVEIN:
156 ossfile.f_mode = FMODE_READ;
157 break;
158 case OSS_STREAM_MIDIOUT:
159 ossfile.f_mode = FMODE_WRITE;
160 break;
161 case OSS_STREAM_MIDIIN:
162 ossfile.f_mode = FMODE_READ;
163 break;
164 }
165
166 if(oss_devices[ossid].open(&ossinode, &ossfile)) {
167 DebugInt3();
168 return 0;
169 }
170
171 return (ULONG)ossfile.private_data;
172}
173
174//******************************************************************************
175//******************************************************************************
176
177ULONG OSS32_StreamClose(ULONG streamtype, ULONG streamid)
178{
179 struct inode ossinode;
180 struct file ossfile;
181 ULONG ossid = streamtype & OSS_IDMASK;
182
183 if(!oss_devices[ossid].release) {
184 return 0;
185 }
186
187 ossinode.i_rdev = ossid;
188 ossfile.private_data = (void *)streamid;
189 ossfile.f_flags = 0;
190
191 switch(streamtype) {
192 case OSS_STREAM_WAVEOUT:
193 ossfile.f_mode = FMODE_WRITE;
194 break;
195 case OSS_STREAM_WAVEIN:
196 ossfile.f_mode = FMODE_READ;
197 break;
198 case OSS_STREAM_MIDIOUT:
199 ossfile.f_mode = FMODE_WRITE;
200 break;
201 case OSS_STREAM_MIDIIN:
202 ossfile.f_mode = FMODE_READ;
203 break;
204 }
205
206 if(oss_devices[ossid].release(&ossinode, &ossfile)) {
207 DebugInt3();
208 return 0;
209 }
210
211 return 1;
212}
213
214//******************************************************************************
215//******************************************************************************
216
217ULONG OSS32_StreamIOCtl(ULONG streamtype,
218 ULONG streamid, ULONG cmd, char NEAR *buffer)
219{
220 struct inode ossinode;
221 struct file ossfile;
222 count_info cinfo;
223 ULONG ossid = streamtype & OSS_IDMASK;
224 ULONG param, fraginfo, fragsize, newcmd = (ULONG)-1;
225
226 if(!oss_devices[ossid].ioctl) {
227 return 0;
228 }
229
230 ossinode.i_rdev = ossid;
231 ossfile.private_data = (void *)streamid;
232 ossfile.f_flags = 0;
233
234 switch(streamtype) {
235 case OSS_STREAM_WAVEOUT:
236 ossfile.f_mode = FMODE_WRITE;
237 break;
238 case OSS_STREAM_WAVEIN:
239 ossfile.f_mode = FMODE_READ;
240 break;
241 case OSS_STREAM_MIDIOUT:
242 ossfile.f_mode = FMODE_WRITE;
243 break;
244 case OSS_STREAM_MIDIIN:
245 ossfile.f_mode = FMODE_READ;
246 break;
247 }
248
249 switch(cmd) {
250 case IOCTL_GETPOS:
251 if(streamtype == OSS_STREAM_WAVEOUT) {
252 newcmd = SNDCTL_DSP_GETOPTR;
253 }
254 else newcmd = SNDCTL_DSP_GETIPTR;
255
256 param = STACK_REF(&cinfo);
257 break;
258
259 case IOCTL_SETFRAGMENT:
260//Rudi: round up fragment size
261 newcmd = SNDCTL_DSP_SETFRAGMENT;
262 fragsize = *(ULONG NEAR *)buffer;
263 for( fraginfo = (16 << 16) + 1; (fragsize >>= 1) != 0; fraginfo++ ) ;
264
265 param = STACK_REF(&fraginfo);
266 break;
267
268 default:
269 DebugInt3();
270 return 0;
271 }
272
273 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, newcmd, param)) {
274 return 0;
275 }
276
277 if( cmd == IOCTL_GETPOS ) *(ULONG NEAR *)buffer = cinfo.bytes;
278
279 return 1;
280}
281
282//******************************************************************************
283//******************************************************************************
284
285ULONG OSS32_StreamSetFormat(ULONG streamtype,
286 ULONG streamid, ULONG cmd, FORMAT_INFO NEAR *pFormatInfo)
287{
288 struct inode ossinode;
289 struct file ossfile;
290 ULONG ossid = streamtype & OSS_IDMASK;
291
292 if(!oss_devices[ossid].ioctl) {
293 return 0;
294 }
295
296 ossinode.i_rdev = ossid;
297 ossfile.private_data = (void *)streamid;
298 ossfile.f_flags = 0;
299
300 switch(streamtype) {
301 case OSS_STREAM_WAVEOUT:
302 ossfile.f_mode = FMODE_WRITE;
303 break;
304 case OSS_STREAM_WAVEIN:
305 ossfile.f_mode = FMODE_READ;
306 break;
307 case OSS_STREAM_MIDIOUT:
308 ossfile.f_mode = FMODE_WRITE;
309 break;
310 case OSS_STREAM_MIDIIN:
311 ossfile.f_mode = FMODE_READ;
312 break;
313 }
314
315 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, SNDCTL_DSP_SPEED, (ULONG)&pFormatInfo->ulSampleRate)) {
316 return 0;
317 }
318 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, SNDCTL_DSP_CHANNELS, (ULONG)&pFormatInfo->ulNumChannels)) {
319 return 0;
320 }
321// if(oss_devices[ossid].ioctl(&ossinode, &ossfile, SNDCTL_DSP_SETFMT, (ULONG)&pFormatInfo->ulBitsPerSample)) {
322 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, SNDCTL_DSP_SETFMT, (ULONG)&pFormatInfo->ulDataType)) {
323 return 0;
324 }
325
326 return 1;
327}
328
329//******************************************************************************
330//******************************************************************************
331
332ULONG OSS32_StreamTrigger(ULONG streamtype, ULONG streamid, ULONG NEAR *fStart)
333{
334 struct inode ossinode;
335 struct file ossfile;
336 ULONG ossid = streamtype & OSS_IDMASK;
337 ULONG cmd;
338
339 if(!oss_devices[ossid].ioctl) {
340 return 0;
341 }
342
343 ossinode.i_rdev = ossid;
344 ossfile.private_data = (void *)streamid;
345 ossfile.f_flags = 0;
346
347 switch(streamtype) {
348 case OSS_STREAM_WAVEOUT:
349 ossfile.f_mode = FMODE_WRITE;
350 *fStart = (*fStart) ? PCM_ENABLE_OUTPUT : 0;
351 cmd = SNDCTL_DSP_SETTRIGGER;
352 break;
353 case OSS_STREAM_WAVEIN:
354 ossfile.f_mode = FMODE_READ;
355 *fStart = (*fStart) ? PCM_ENABLE_INPUT : 0;
356 cmd = SNDCTL_DSP_SETTRIGGER;
357 break;
358 case OSS_STREAM_MIDIOUT:
359 ossfile.f_mode = FMODE_WRITE;
360 break;
361 case OSS_STREAM_MIDIIN:
362 ossfile.f_mode = FMODE_READ;
363 break;
364 }
365
366
367 if(ossfile.f_mode == FMODE_READ && *fStart == PCM_ENABLE_INPUT) {
368 //need to call poll to really start the stream
369 int rc;
370 struct poll_table_struct poll = {0};
371
372 rc = oss_devices[ossid].poll(&ossfile, &poll);
373 if(rc & POLLERR)
374 return 0;
375// Rudi
376// return 1;
377 }
378
379 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, (ULONG)fStart)) {
380 return 0;
381 }
382
383 return 1;
384}
385//******************************************************************************
386//******************************************************************************
387ULONG OSS32_StreamReset(ULONG streamtype, ULONG streamid)
388{
389 struct inode ossinode;
390 struct file ossfile;
391 ULONG ossid = streamtype & OSS_IDMASK;
392 ULONG cmd;
393
394 if(!oss_devices[ossid].ioctl) {
395 return 0;
396 }
397
398 ossinode.i_rdev = ossid;
399 ossfile.private_data = (void *)streamid;
400 ossfile.f_flags = 0;
401
402 switch(streamtype) {
403 case OSS_STREAM_WAVEOUT:
404 ossfile.f_mode = FMODE_WRITE;
405 cmd = SNDCTL_DSP_RESET;
406 break;
407 case OSS_STREAM_WAVEIN:
408 ossfile.f_mode = FMODE_READ;
409 cmd = SNDCTL_DSP_RESET;
410 break;
411 case OSS_STREAM_MIDIOUT:
412 ossfile.f_mode = FMODE_WRITE;
413 break;
414 case OSS_STREAM_MIDIIN:
415 ossfile.f_mode = FMODE_READ;
416 break;
417 }
418
419 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, 0)) {
420 return 0;
421 }
422 return 1;
423}
424
425//******************************************************************************
426//******************************************************************************
427
428ULONG OSS32_StreamAddBuffer(ULONG streamtype,
429 ULONG streamid, ULONG buffer, ULONG size)
430{
431 struct inode ossinode;
432 struct file ossfile;
433 struct dentry ossdentry;
434 int transferred;
435 ULONG ossid = streamtype & OSS_IDMASK;
436 audio_buf_info info;
437 ULONG cmd;
438
439 if(!oss_devices[ossid].write || !oss_devices[ossid].read || !oss_devices[ossid].ioctl) {
440 return 0;
441 }
442
443 ossinode.i_rdev = ossid;
444 ossfile.private_data = (void *)streamid;
445 ossfile.f_flags = 0;
446 ossfile.f_dentry = &ossdentry;
447 ossdentry.d_inode = &ossinode;
448
449 switch(streamtype) {
450 case OSS_STREAM_WAVEOUT:
451 ossfile.f_mode = FMODE_WRITE;
452 cmd = SNDCTL_DSP_GETOSPACE;
453 break;
454 case OSS_STREAM_WAVEIN:
455 ossfile.f_mode = FMODE_READ;
456 cmd = SNDCTL_DSP_GETISPACE;
457 break;
458 case OSS_STREAM_MIDIOUT:
459 ossfile.f_mode = FMODE_WRITE;
460 break;
461 case OSS_STREAM_MIDIIN:
462 ossfile.f_mode = FMODE_READ;
463 break;
464 }
465
466 //check how much room is left in the circular dma buffer
467 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, STACK_REF(&info))) {
468 return 0;
469 }
470 size = min(size, info.bytes);
471
472 if(size == 0) {
473 return 0; //no room left, fail
474 }
475
476 if(streamtype == OSS_STREAM_WAVEIN)
477 transferred = oss_devices[ossid].read(&ossfile, (char *)buffer, size, &ossfile.f_pos);
478 else
479 transferred = oss_devices[ossid].write(&ossfile, (char *)buffer, size, &ossfile.f_pos);
480
481 return ( transferred > 0 ) ? transferred : 0;
482}
483
484//******************************************************************************
485//******************************************************************************
486
487ULONG OSS32_StreamGetSpace(ULONG streamtype, ULONG streamid)
488{
489 struct inode ossinode;
490 struct file ossfile;
491 struct dentry ossdentry;
492 int transferred;
493 ULONG ossid = streamtype & OSS_IDMASK;
494 audio_buf_info info;
495 ULONG cmd;
496
497 if(!oss_devices[ossid].write || !oss_devices[ossid].read || !oss_devices[ossid].ioctl) {
498 return 0;
499 }
500
501 ossinode.i_rdev = ossid;
502 ossfile.private_data = (void *)streamid;
503 ossfile.f_flags = 0;
504 ossfile.f_dentry = &ossdentry;
505 ossdentry.d_inode = &ossinode;
506
507 switch(streamtype) {
508 case OSS_STREAM_WAVEOUT:
509 ossfile.f_mode = FMODE_WRITE;
510 cmd = SNDCTL_DSP_GETOSPACE;
511 break;
512 case OSS_STREAM_WAVEIN:
513 ossfile.f_mode = FMODE_READ;
514 cmd = SNDCTL_DSP_GETISPACE;
515 break;
516 case OSS_STREAM_MIDIOUT:
517 ossfile.f_mode = FMODE_WRITE;
518 break;
519 case OSS_STREAM_MIDIIN:
520 ossfile.f_mode = FMODE_READ;
521 break;
522 }
523
524 //check how much room is left in the circular dma buffer
525 if(oss_devices[ossid].ioctl(&ossinode, &ossfile, cmd, STACK_REF(&info))) {
526 return 0;
527 }
528
529 return info.bytes;
530}
531
532//******************************************************************************
533//******************************************************************************
534
535ULONG OSS32_SetVolume(ULONG streamtype, ULONG streamid, ULONG cmd, ULONG volume)
536{
537 struct inode ossinode;
538 struct file ossfile;
539 struct dentry ossdentry;
540 int result;
541 ULONG ioctl;
542
543 if(!oss_devices[OSS_MIXERID].ioctl || !oss_devices[OSS_MIXERID].open || !oss_devices[OSS_MIXERID].release) {
544 return 0;
545 }
546
547 ossinode.i_rdev = OSS_MIXERID;
548 ossfile.private_data = (void *)streamid;
549 ossfile.f_flags = 0;
550 ossfile.f_dentry = &ossdentry;
551 ossfile.f_mode = FMODE_WRITE;
552 ossdentry.d_inode = &ossinode;
553
554 switch(cmd) {
555 case MIX_SETMASTERVOL:
556 ioctl = SOUND_MIXER_WRITE_VOLUME;
557 break;
558
559 case MIX_SETWAVEVOL:
560 ioctl = SOUND_MIXER_WRITE_PCM;
561 break;
562
563 case MIX_SETMIDIVOL:
564 ioctl = SOUND_MIXER_WRITE_SYNTH;
565 break;
566
567 case MIX_SETINPUTSRC:
568 ioctl = SOUND_MIXER_WRITE_RECSRC; //todo
569 switch(volume)
570 {
571 case MIX_RECSRC_MIC:
572 volume = SOUND_MASK_MIC;
573 break;
574 case MIX_RECSRC_CD:
575 volume = SOUND_MASK_CD;
576 break;
577 case MIX_RECSRC_LINE:
578 volume = SOUND_MASK_LINE;
579 break;
580 case MIX_RECSRC_VIDEO:
581 volume = SOUND_MASK_VIDEO;
582 break;
583 case MIX_RECSRC_MIXER:
584 volume = SOUND_MASK_MONITOR;
585 break;
586 case MIX_RECSRC_AUX:
587 volume = SOUND_MASK_LINE1;
588 break;
589 case MIX_RECSRC_SPDIF1:
590 volume = SOUND_MASK_DIGITAL1;
591 break;
592 default:
593 DebugInt3();
594 return 0;
595 }
596 break;
597
598 case MIX_SETINPUTGAIN:
599 ioctl = SOUND_MIXER_WRITE_IGAIN;
600// ioctl = SOUND_MIXER_WRITE_RECLEV;
601 break;
602
603 case MIX_SETLINEINVOL:
604 case MIX_SETLINEINMUTE:
605 ioctl = SOUND_MIXER_WRITE_LINE;
606 break;
607
608 case MIX_SETMICVOL:
609 case MIX_SETMICMUTE:
610 ioctl = SOUND_MIXER_WRITE_MIC;
611 break;
612
613 case MIX_SETCDVOL:
614 case MIX_SETCDMUTE:
615 ioctl = SOUND_MIXER_WRITE_CD;
616 break;
617
618 case MIX_SETVIDEOVOL:
619 case MIX_SETVIDEOMUTE:
620 ioctl = SOUND_MIXER_WRITE_VIDEO;
621 break;
622
623 case MIX_SETAUXVOL:
624 case MIX_SETAUXMUTE:
625 ioctl = SOUND_MIXER_WRITE_LINE1;
626 break;
627
628 case MIX_SETBASS:
629 ioctl = SOUND_MIXER_WRITE_BASS;
630 break;
631
632 case MIX_SETTREBLE:
633 ioctl = SOUND_MIXER_WRITE_TREBLE;
634 break;
635
636 case MIX_SETSPKVOL:
637 case MIX_SETSPKMUTE:
638 ioctl = SOUND_MIXER_WRITE_SPEAKER;
639 break;
640/*
641 case MIX_SETPCMVOL:
642 case MIX_SETPCMMUTE:
643 ioctl = SOUND_MIXER_WRITE_LINE2;
644 break;
645
646 case MIX_SETSPDIFVOL:
647 case MIX_SETSPDIFMUTE:
648 ioctl = MIXER_WRITE(SOUND_MIXER_DIGITAL1);
649 break;
650*/
651
652 default:
653 DebugInt3();
654 return 0;
655 }
656
657
658 if(oss_devices[OSS_MIXERID].open(&ossinode, &ossfile)) {
659 return 0;
660 }
661
662 result = oss_devices[OSS_MIXERID].ioctl(&ossinode, &ossfile,
663 ioctl, STACK_REF(&volume));
664
665 oss_devices[OSS_MIXERID].release(&ossinode, &ossfile);
666
667 return result == 0;
668}
669
670
671#if 0
672
673//******************************************************************************
674//******************************************************************************
675
676unsigned long OSS32_StreamMidiWrite(unsigned long streamid,
677 unsigned long midiByte)
678{
679 struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *)streamid;
680
681 return emu10k1_mpu_write_data(midi_dev->card, (u8)midiByte) == 0;
682}
683
684//******************************************************************************
685//******************************************************************************
686
687unsigned long OSS32_StreamMidiRead(unsigned long streamid,
688 char near *buffer, unsigned long bufsize)
689{
690 struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *)streamid;
691 int count = 0;
692 u8 MPUIvalue;
693
694 while(TRUE) {
695 if(emu10k1_mpu_read_data(midi_dev->card, &MPUIvalue) == 0) {
696 buffer[count] = MPUIvalue;
697 count++;
698 }
699 else break;
700
701 if(count >= bufsize) {
702 break;
703 }
704 }
705 return count;
706}
707
708#endif
709
710//******************************************************************************
711//******************************************************************************
Note: See TracBrowser for help on using the repository browser.