* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-0.99 / drivers / sound / sb16_dsp.c
blob02040c7bda8544f360cebfc0424ccb1520687d70
1 /*
2 * sound/sb16_dsp.c
3 *
4 * The low level driver for the SoundBlaster DSP chip.
5 *
6 * (C) 1993 J. Schubert (jsb@sth.ruhr-uni-bochum.de)
8 * based on SB-driver by (C) Hannu Savolainen
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
12 * met: 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 2.
14 * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
32 #define DEB(x)
33 #define DEB1(x)
35 #define DEB_DMARES
37 #include "sound_config.h"
38 #include "sb.h"
39 #include "sb_mixer.h"
41 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_AUDIO) && !defined(EXCLUDE_SBPRO)
43 extern int sbc_base;
45 static int sb16_dsp_ok = 0; /* Set to 1 after successful initialization */
46 static int dsp_16bit = 0;
47 static int dsp_stereo = 0;
48 static int dsp_current_speed = 8000;/*DSP_DEFAULT_SPEED;*/
49 static int dsp_busy = 0;
50 static int dma16, dma8;
51 static unsigned long dsp_count = 0;
53 static int irq_mode = IMODE_NONE; /* IMODE_INPUT, IMODE_OUTPUT or
54 IMODE_NONE */
55 static int my_dev = 0;
57 static volatile int intr_active = 0;
59 static int sb16_dsp_open (int dev, int mode);
60 static void sb16_dsp_close (int dev);
61 static void sb16_dsp_output_block (int dev, unsigned long buf, int count,int intrflag, int dma_restart);
62 static void sb16_dsp_start_input (int dev, unsigned long buf, int count,int intrflag, int dma_restart);
63 static int sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg,int local);
64 static int sb16_dsp_prepare_for_input (int dev, int bsize, int bcount);
65 static int sb16_dsp_prepare_for_output (int dev, int bsize, int bcount);
66 static void sb16_dsp_reset (int dev);
67 static void sb16_dsp_halt (int dev);
68 static int dsp_set_speed (int);
69 static int dsp_set_stereo (int);
70 static void dsp_cleanup (void);
71 int sb_reset_dsp (void);
73 static struct audio_operations sb16_dsp_operations =
75 "SoundBlaster 16",
76 sb16_dsp_open,
77 sb16_dsp_close,
78 sb16_dsp_output_block,
79 sb16_dsp_start_input,
80 sb16_dsp_ioctl,
81 sb16_dsp_prepare_for_input,
82 sb16_dsp_prepare_for_output,
83 sb16_dsp_reset,
84 sb16_dsp_halt,
85 NULL,
86 NULL
89 static int sb_dsp_command01 (unsigned char val)
91 int i=1<<16;
93 while(--i & (!INB (DSP_STATUS) & 0x80));
94 if(!i)
95 printk("SB16 sb_dsp_command01 Timeout\n");
96 return sb_dsp_command(val);
99 static int wait_data_avail(int t)
101 int loopc=5000000;
102 t+=GET_TIME();
103 do {
104 if(INB(DSP_DATA_AVAIL) & 0x80)
105 return 1;
106 } while(--loopc && GET_TIME()<t);
107 printk("!data_avail l=%d\n",loopc);
108 return 0;
111 static int read_dsp(int t)
113 if(!wait_data_avail(t))
114 return -1;
115 else
116 return INB(DSP_READ);
119 static int dsp_ini2(void)
121 #if 0
122 /* sb_setmixer(0x83, sb_getmixer(0x83) | 0x03); */
123 sb_dsp_command(0xe2);
124 sb_dsp_command(0x76); /* E0 ??? */
125 sb_dsp_command(0xe2);
126 sb_dsp_command(0x30); /* A0 ??? */
127 sb_dsp_command(0xe4);
128 sb_dsp_command(0xaa);
129 sb_dsp_command(0xe8);
130 if(read_dsp(100)!=0xaa)
131 printk("Error dsp_ini2\n");
132 #endif
133 return 0;
136 static char *dsp_getmessage(unsigned char command,int maxn)
138 static char buff[100];
139 int n=0;
141 sb_dsp_command(command);
142 while(n<maxn && wait_data_avail(2)) {
143 buff[++n]=INB(DSP_READ);
144 if(!buff[n])
145 break;
147 buff[0]=n;
148 return buff;
151 static void dsp_showmessage(unsigned char command,int len)
153 int n;
154 unsigned char *c;
155 c=dsp_getmessage(command,len);
156 printk("DSP C=%x l=%d,lr=%d b=",command,len,c[0]);
157 for(n=1;n<=c[0];n++)
158 if(c[n]>=' ' & c[n]<='z')
159 printk("%c",c[n]);
160 else
161 printk("|%x|",c[n]);
162 printk("\n");
165 static int dsp_set_speed(int mode)
167 DEB(printk("dsp_set_speed(%d)\n",mode));
168 if (mode)
170 if (mode < 5000) mode = 5000;
171 if (mode > 44100) mode = 44100;
172 dsp_current_speed=mode;
174 return mode;
177 static int dsp_set_stereo(int mode)
179 DEB(printk("dsp_set_stereo(%d)\n",mode));
181 dsp_stereo=mode;
183 return mode;
186 static int dsp_set_bits(int arg) {
187 DEB(printk("dsp_set_bits(%d)\n",arg));
189 if (arg)
190 switch(arg) {
191 case 8:
192 dsp_16bit=0; break;
193 case 16:
194 dsp_16bit=1; break;
195 default:
196 return RET_ERROR(EINVAL);
198 return dsp_16bit? 16:8;
201 static int
202 sb16_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg,int local)
204 switch (cmd) {
205 case SOUND_PCM_WRITE_RATE:
206 if(local)
207 return dsp_set_speed(arg);
208 return IOCTL_OUT (arg, dsp_set_speed (IOCTL_IN (arg)));
210 case SOUND_PCM_READ_RATE:
211 if(local)
212 return dsp_current_speed;
213 return IOCTL_OUT (arg, dsp_current_speed);
215 case SNDCTL_DSP_STEREO:
216 if (local)
217 return dsp_set_stereo(arg);
218 return IOCTL_OUT (arg, dsp_set_stereo(IOCTL_IN(arg)));
220 case SOUND_PCM_WRITE_CHANNELS:
221 if (local)
222 return dsp_set_stereo(arg-1)+1;
223 return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1);
225 case SOUND_PCM_READ_CHANNELS:
226 if (local)
227 return dsp_stereo+1;
228 return IOCTL_OUT (arg, dsp_stereo+1);
230 case SNDCTL_DSP_SAMPLESIZE:
231 if (local)
232 return dsp_set_bits (arg);
233 return IOCTL_OUT (arg, dsp_set_bits (IOCTL_IN (arg)));
235 case SOUND_PCM_READ_BITS:
236 if (local)
237 return dsp_16bit?16:8;
238 return IOCTL_OUT (arg, dsp_16bit?16:8);
240 case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */
241 if (IOCTL_IN (arg) > 1)
242 return IOCTL_OUT (arg, RET_ERROR (EINVAL));
243 default:
244 return RET_ERROR (EINVAL);
247 return RET_ERROR (EINVAL);
250 static int
251 sb16_dsp_open (int dev, int mode)
253 int retval;
255 DEB(printk("sb16_dsp_open()\n"));
256 if (!sb16_dsp_ok)
258 printk ("SB16 Error: SoundBlaster board not installed\n");
259 return RET_ERROR(ENXIO);
262 if (intr_active)
263 return RET_ERROR(EBUSY);
265 retval = sb_get_irq ();
266 if (retval<0)
267 return retval;
269 if (ALLOC_DMA_CHN (dma8))
271 printk ("SB16: Unable to grab DMA%d\n", dma8);
272 sb_free_irq();
273 return RET_ERROR(EBUSY);
276 if (dma16 != dma8)
277 if (ALLOC_DMA_CHN (dma16))
279 printk ("SB16: Unable to grab DMA%d\n", dma16);
280 sb_free_irq();
281 RELEASE_DMA_CHN (dma8);
282 return RET_ERROR(EBUSY);
285 dsp_ini2();
287 irq_mode = IMODE_NONE;
288 dsp_busy = 1;
290 return 0;
293 static void
294 sb16_dsp_close (int dev)
296 unsigned long flags;
297 DEB(printk("sb16_dsp_close()\n"));
298 sb_dsp_command01(0xd9);
299 sb_dsp_command01(0xd5);
301 DISABLE_INTR (flags);
302 RELEASE_DMA_CHN (dma8);
304 if (dma16 != dma8)
305 RELEASE_DMA_CHN (dma16);
306 sb_free_irq ();
307 dsp_cleanup ();
308 dsp_busy = 0;
309 RESTORE_INTR (flags);
312 static void
313 sb16_dsp_output_block (int dev, unsigned long buf, int count,int intrflag, int dma_restart)
315 unsigned long flags, cnt;
317 cnt = count;
318 if (dsp_16bit)
319 cnt >>= 1;
320 cnt--;
322 #ifdef DEB_DMARES
323 printk("output_block: %x %d %d\n",buf,count,intrflag);
324 if(intrflag) {
325 int pos,chan=sound_dsp_dmachan[dev];
326 DISABLE_INTR (flags);
327 clear_dma_ff(chan);
328 disable_dma(chan);
329 pos=get_dma_residue(chan);
330 enable_dma(chan);
331 RESTORE_INTR (flags);
332 printk("dmapos=%d %x\n",pos,pos);
334 #endif
335 if (sound_dma_automode[dev] &&
336 intrflag &&
337 cnt == dsp_count) {
338 irq_mode = IMODE_OUTPUT;
339 intr_active = 1;
340 return; /* Auto mode on. No need to react */
342 DISABLE_INTR (flags);
344 if (dma_restart)
346 sb16_dsp_halt(dev);
347 DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
349 sb_dsp_command (0x41);
350 sb_dsp_command ((unsigned char)((dsp_current_speed >> 8) & 0xff));
351 sb_dsp_command ((unsigned char)(dsp_current_speed & 0xff));
352 sb_dsp_command ((unsigned char)(dsp_16bit ? 0xb6 : 0xc6));
353 sb_dsp_command ((unsigned char)((dsp_stereo ? 0x20 : 0) +
354 (dsp_16bit ? 0x10:0)));
355 sb_dsp_command01 ((unsigned char)(cnt&0xff));
356 sb_dsp_command ((unsigned char)(cnt>>8));
357 /* sb_dsp_command (0);
358 sb_dsp_command (0); */
360 RESTORE_INTR (flags);
361 dsp_count=cnt;
362 irq_mode = IMODE_OUTPUT;
363 intr_active = 1;
366 static void
367 sb16_dsp_start_input (int dev, unsigned long buf, int count,int intrflag, int dma_restart)
369 unsigned long flags, cnt;
371 cnt = count;
372 if (dsp_16bit)
373 cnt >>= 1;
374 cnt--;
376 #ifdef DEB_DMARES
377 printk("start_input: %x %d %d\n",buf,count,intrflag);
378 if(intrflag) {
379 int pos,chan=sound_dsp_dmachan[dev];
380 DISABLE_INTR (flags);
381 clear_dma_ff(chan);
382 disable_dma(chan);
383 pos=get_dma_residue(chan);
384 enable_dma(chan);
385 RESTORE_INTR (flags);
386 printk("dmapos=%d %x\n",pos,pos);
388 #endif
389 if (sound_dma_automode[dev] &&
390 intrflag &&
391 cnt == dsp_count) {
392 irq_mode = IMODE_INPUT;
393 intr_active = 1;
394 return; /* Auto mode on. No need to react */
396 DISABLE_INTR (flags);
398 if (dma_restart)
400 sb16_dsp_halt(dev);
401 DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
404 sb_dsp_command (0x42);
405 sb_dsp_command ((unsigned char)((dsp_current_speed >> 8) & 0xff));
406 sb_dsp_command ((unsigned char)(dsp_current_speed & 0xff));
407 sb_dsp_command ((unsigned char)(dsp_16bit ? 0xbe : 0xce));
408 sb_dsp_command ((unsigned char)((dsp_stereo ? 0x20 : 0) +
409 (dsp_16bit ? 0x10:0)));
410 sb_dsp_command01 ((unsigned char)(cnt&0xff));
411 sb_dsp_command ((unsigned char)(cnt>>8));
413 /* sb_dsp_command (0);
414 sb_dsp_command (0); */
415 RESTORE_INTR (flags);
416 dsp_count=cnt;
417 irq_mode = IMODE_INPUT;
418 intr_active = 1;
421 static int
422 sb16_dsp_prepare_for_input (int dev, int bsize, int bcount)
424 sound_dsp_dmachan[my_dev] = dsp_16bit? dma16:dma8;
425 dsp_count = 0;
426 dsp_cleanup ();
427 return 0;
430 static int
431 sb16_dsp_prepare_for_output (int dev, int bsize, int bcount)
433 sound_dsp_dmachan[my_dev] = dsp_16bit? dma16:dma8;
434 dsp_count = 0;
435 dsp_cleanup ();
436 return 0;
439 static void
440 dsp_cleanup (void)
442 irq_mode = IMODE_NONE;
443 intr_active = 0;
446 static void
447 sb16_dsp_reset (int dev)
449 unsigned long flags;
451 DISABLE_INTR (flags);
453 sb_reset_dsp ();
454 dsp_cleanup ();
456 RESTORE_INTR (flags);
459 static void
460 sb16_dsp_halt (int dev)
462 if (dsp_16bit)
464 sb_dsp_command01(0xd9);
465 sb_dsp_command01(0xd5);
467 else
469 sb_dsp_command01(0xda);
470 sb_dsp_command01(0xd0);
474 static void
475 set_irq_hw(int level) {
476 int ival;
477 switch(level) {
478 case 5:
479 ival=2; break;
480 case 7:
481 ival=4; break;
482 case 10:
483 ival=8; break;
484 default:
485 printk("SB16_IRQ_LEVEL %d does not exist\n",level);
486 return;
488 sb_setmixer(IRQ_NR,ival);
491 long
492 sb16_dsp_init (long mem_start, struct address_info *hw_config)
494 int i, major, minor;
496 major = minor = 0;
497 sb_dsp_command (0xe1); /* Get version */
499 for (i = 1000; i; i--) {
500 if (INB (DSP_DATA_AVAIL) & 0x80)
501 { /* wait for Data Ready */
502 if (major == 0)
503 major = INB (DSP_READ);
504 else
506 minor = INB (DSP_READ);
507 break;
512 #ifndef SCO
513 sprintf (sb16_dsp_operations.name, "SoundBlaster 16 %d.%d", major, minor);
514 #endif
516 printk (" <%s>", sb16_dsp_operations.name);
518 if (num_dspdevs < MAX_DSP_DEV)
520 dsp_devs[my_dev = num_dspdevs++] = &sb16_dsp_operations;
521 sound_dsp_dmachan[my_dev] = hw_config->dma;
522 sound_buffcounts[my_dev] = 1;
523 sound_buffsizes[my_dev] = DSP_BUFFSIZE;
524 sound_dma_automode[my_dev] = 1;
526 else
527 printk ("SB: Too many DSP devices available\n");
528 sb16_dsp_ok = 1;
529 return mem_start;
533 sb16_dsp_detect (struct address_info *hw_config)
535 struct address_info *sb_config;
537 if (sb16_dsp_ok)
538 return 1; /* Already initialized */
540 if (!(sb_config=sound_getconf(SNDCARD_SB)))
542 printk("SB16 Error: Plain SB not configured\n");
543 return 0;
546 if (sbc_base != hw_config->io_base)
547 printk("Warning! SB16 I/O != SB I/O\n");
549 /* sb_setmixer(OPSW,0xf);
550 if(sb_getmixer(OPSW)!=0xf)
551 return 0; */
553 if (!sb_reset_dsp ())
554 return 0;
556 if (hw_config->irq != sb_config->irq)
558 printk("SB16 Error: Invalid IRQ number %d/%d\n",
559 sb_config->irq, hw_config->irq);
560 return 0;
563 if (hw_config->dma < 4)
564 if (hw_config->dma != sb_config->dma)
566 printk("SB16 Error: Invalid DMA channel %d/%d\n",
567 sb_config->dma, hw_config->dma);
568 return 0;
571 dma16 = hw_config->dma;
572 dma8 = sb_config->dma;
573 set_irq_hw(hw_config->irq);
574 sb_setmixer(DMA_NR, (1<<hw_config->dma) | (1<<sb_config->dma));
576 DEB(printk ("SoundBlaster 16: IRQ %d DMA %d OK\n",hw_config->irq,hw_config->dma));
579 dsp_showmessage(0xe3,99);
581 sb16_dsp_ok = 1;
582 return 1;
585 void
586 sb16_dsp_interrupt (int unused)
588 int data;
589 data = INB (DSP_DATA_AVL16); /* Interrupt acknowledge */
591 if (intr_active)
592 switch (irq_mode)
594 case IMODE_OUTPUT:
595 intr_active = 0;
596 DMAbuf_outputintr (my_dev, 1);
597 break;
599 case IMODE_INPUT:
600 intr_active = 0;
601 DMAbuf_inputintr (my_dev);
602 break;
604 default:
605 printk ("SoundBlaster: Unexpected interrupt\n");
608 #endif