kernel tree reorganization stage 1: Major cvs repository work (not logged as
[dragonfly.git] / sys / dev / sound / isa / i386 / sbxvi / sb16_dsp.c
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)
7  * 
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.
17  * 
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.
29  *
30  * $FreeBSD: src/sys/i386/isa/sound/sb16_dsp.c,v 1.33 1999/12/27 04:37:18 tanimura Exp $
31  * $DragonFly: src/sys/dev/sound/isa/i386/sbxvi/Attic/sb16_dsp.c,v 1.3 2003/08/07 21:17:12 dillon Exp $
32  * 
33  */
34
35 #define DEB(x)
36 #define DEB1(x)
37 #include "use_sb.h"
38
39 #include <dev/sound/isa/i386/sound_config.h>
40 #include <dev/sound/isa/i386/sb_mixer.h>
41 #include <dev/sound/isa/i386/sbcard.h>
42
43 #if defined(CONFIG_SB16) && (NSB > 0) && defined(CONFIG_AUDIO) && defined(CONFIG_SBPRO)
44
45 extern sound_os_info *sb_osp;
46 extern int      sbc_base;
47
48 static int      sb16_dsp_ok = 0;
49 static int      dsp_16bit = 0;
50 static int      dsp_stereo = 0;
51 static int      dsp_current_speed = 8000;
52 static int      dsp_busy = 0;
53 static int      dma16, dma8;
54
55
56 static int      trigger_bits = 0;
57 static u_long dsp_count = 0;
58
59 static int      irq_mode = IMODE_NONE;
60 static int      my_dev = 0;
61
62 static volatile int intr_active = 0;
63
64 static int      sb16_dsp_open(int dev, int mode);
65 static void     sb16_dsp_close(int dev);
66 static void     sb16_dsp_output_block(int dev, u_long buf, int count, int intrflag, int dma_restart);
67 static void     sb16_dsp_start_input(int dev, u_long buf, int count, int intrflag, int dma_restart);
68 static int      sb16_dsp_ioctl(int dev, u_int cmd, ioctl_arg arg, int local);
69 static int      sb16_dsp_prepare_for_input(int dev, int bsize, int bcount);
70 static int      sb16_dsp_prepare_for_output(int dev, int bsize, int bcount);
71 static void     sb16_dsp_reset(int dev);
72 static void     sb16_dsp_halt(int dev);
73 static void     sb16_dsp_trigger(int dev, int bits);
74 static int      dsp_set_speed(int);
75 static int      dsp_set_stereo(int);
76 static void     dsp_cleanup(void);
77
78 static struct audio_operations sb16_dsp_operations =
79 {
80         "SoundBlaster 16",
81         DMA_AUTOMODE,
82         AFMT_U8 | AFMT_S16_LE,
83         NULL,
84         sb16_dsp_open,
85         sb16_dsp_close,
86         sb16_dsp_output_block,
87         sb16_dsp_start_input,
88         sb16_dsp_ioctl,
89         sb16_dsp_prepare_for_input,
90         sb16_dsp_prepare_for_output,
91         sb16_dsp_reset,
92         sb16_dsp_halt,
93         NULL,
94         NULL,
95         NULL,
96         NULL,
97         sb16_dsp_trigger
98 };
99
100 static int
101 sb_dsp_command01(u_char val)
102 {
103     int             i = 1 << 16;
104
105     while (--i & (!inb(DSP_STATUS) & 0x80));
106     if (!i)
107         printf("SB16 sb_dsp_command01 Timeout\n");
108     return sb_dsp_command(val);
109 }
110
111 static int
112 dsp_set_speed(int mode)
113 {
114     DEB(printf("dsp_set_speed(%d)\n", mode));
115     if (mode) {
116         RANGE (mode, 5000, 44100);
117         dsp_current_speed = mode;
118     }
119     return mode;
120 }
121
122 static int
123 dsp_set_stereo(int mode)
124 {
125     DEB(printf("dsp_set_stereo(%d)\n", mode));
126     dsp_stereo = mode;
127     return mode;
128 }
129
130 static int
131 dsp_set_bits(int arg)
132 {
133     DEB(printf("dsp_set_bits(%d)\n", arg));
134
135     if (arg)
136         dsp_16bit =  (arg == 16) ? 1 : 0 ;
137     return dsp_16bit ? 16 : 8;
138 }
139
140 static int
141 sb16_dsp_ioctl(int dev, u_int cmd, ioctl_arg arg, int local)
142 {
143     switch (cmd) {
144     case SOUND_PCM_WRITE_RATE:
145         if (local)
146             return dsp_set_speed((int) arg);
147         return *(int *) arg = dsp_set_speed((*(int *) arg));
148
149     case SOUND_PCM_READ_RATE:
150         if (local)
151             return dsp_current_speed;
152         return *(int *) arg = dsp_current_speed;
153
154     case SNDCTL_DSP_STEREO:
155         if (local)
156             return dsp_set_stereo((int) arg);
157         return *(int *) arg = dsp_set_stereo((*(int *) arg));
158
159     case SOUND_PCM_WRITE_CHANNELS:
160         if (local)
161             return dsp_set_stereo((int) arg - 1) + 1;
162         return *(int *) arg = dsp_set_stereo((*(int *) arg) - 1) + 1;
163
164     case SOUND_PCM_READ_CHANNELS:
165         if (local)
166             return dsp_stereo + 1;
167         return *(int *) arg = dsp_stereo + 1;
168
169     case SNDCTL_DSP_SETFMT:
170         if (local)
171             return dsp_set_bits((int) arg);
172         return *(int *) arg = dsp_set_bits((*(int *) arg));
173
174     case SOUND_PCM_READ_BITS:
175         if (local)
176             return dsp_16bit ? 16 : 8;
177         return *(int *) arg = dsp_16bit ? 16 : 8;
178
179     case SOUND_PCM_WRITE_FILTER:        /* NOT YET IMPLEMENTED */
180         if ((*(int *) arg) > 1)
181             return *(int *) arg = -(EINVAL);
182
183     case FIOASYNC:
184         if (local)
185             return 1;
186         return *(int *) arg = 1;
187
188     case FIONBIO:
189         if (local)
190             return 1;
191         return *(int *) arg = 1;
192
193     default:
194         return -(EINVAL);
195     }
196
197     return -(EINVAL);
198 }
199
200 static int
201 sb16_dsp_open(int dev, int mode)
202 {
203     DEB(printf("sb16_dsp_open()\n"));
204
205     if (!sb16_dsp_ok) {
206         printf("SB16 Error: SoundBlaster board not installed\n");
207         return -(ENXIO);
208     }
209     if (intr_active)
210         return -(EBUSY);
211
212     sb_reset_dsp();
213
214
215     irq_mode = IMODE_NONE;
216     dsp_busy = 1;
217     trigger_bits = 0;
218
219     return 0;
220 }
221
222 static void
223 sb16_dsp_close(int dev)
224 {
225     u_long   flags;
226
227     DEB(printf("sb16_dsp_close()\n"));
228     sb_dsp_command01(0xd9);
229     sb_dsp_command01(0xd5);
230
231     flags = splhigh();
232
233     audio_devs[dev]->dmachan1 = dma8;
234
235     dsp_cleanup();
236     dsp_busy = 0;
237
238
239     splx(flags);
240 }
241
242 static void
243 sb16_dsp_output_block(int dev, u_long buf, int count, int intrflag, int dma_restart)
244 {
245     u_long   flags, cnt;
246
247
248     cnt = count;
249     if (dsp_16bit)
250         cnt >>= 1;
251     cnt--;
252
253     if (audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt==dsp_count) {
254         irq_mode = IMODE_OUTPUT;
255         intr_active = 1;
256         return;         /* Auto mode on. No need to react */
257     }
258     flags = splhigh();
259
260     if (dma_restart) {
261
262         sb16_dsp_halt(dev);
263         DMAbuf_start_dma(dev, buf, count, 1);
264     }
265
266
267     sb_dsp_command(0x41);
268     sb_dsp_command((u_char) ((dsp_current_speed >> 8) & 0xff));
269     sb_dsp_command((u_char) (dsp_current_speed & 0xff));
270     sb_dsp_command((u_char) (dsp_16bit ? 0xb6 : 0xc6));
271     dsp_count = cnt;
272     sb_dsp_command((u_char) ((dsp_stereo ? 0x20 : 0) +
273                                 (dsp_16bit ? 0x10 : 0)));
274     sb_dsp_command((u_char) (cnt & 0xff));
275     sb_dsp_command((u_char) (cnt >> 8));
276
277     irq_mode = IMODE_OUTPUT;
278     intr_active = 1;
279     splx(flags);
280 }
281
282 static void
283 sb16_dsp_start_input(int dev, u_long buf, int count, int intrflag, int dma_restart)
284 {
285     u_long   flags, cnt;
286
287     cnt = count;
288     if (dsp_16bit)
289         cnt >>= 1;
290     cnt--;
291
292     if (audio_devs[dev]->flags & DMA_AUTOMODE && intrflag && cnt == dsp_count) {
293         irq_mode = IMODE_INPUT;
294         intr_active = 1;
295         return;         /* Auto mode on. No need to react */
296     }
297     flags = splhigh();
298
299     if (dma_restart) {
300         sb_reset_dsp();
301         DMAbuf_start_dma(dev, buf, count, 0);
302     }
303     sb_dsp_command(0x42);
304     sb_dsp_command((u_char) ((dsp_current_speed >> 8) & 0xff));
305     sb_dsp_command((u_char) (dsp_current_speed & 0xff));
306     sb_dsp_command((u_char) (dsp_16bit ? 0xbe : 0xce));
307     dsp_count = cnt;
308     sb_dsp_command((u_char) ((dsp_stereo ? 0x20 : 0) +
309                                     (dsp_16bit ? 0x10 : 0)));
310     sb_dsp_command01((u_char) (cnt & 0xff));
311     sb_dsp_command((u_char) (cnt >> 8));
312
313     irq_mode = IMODE_INPUT;
314     intr_active = 1;
315     splx(flags);
316 }
317
318 static int
319 sb16_dsp_prepare_for_input(int dev, int bsize, int bcount)
320 {
321     int fudge;
322     struct dma_buffparms *dmap =  audio_devs[dev]->dmap_in;
323
324     audio_devs[my_dev]->dmachan2 = dsp_16bit ? dma16 : dma8;
325
326
327     fudge =  audio_devs[my_dev]->dmachan2 ;
328
329     if (dmap->dma_chan != fudge ) {
330       isa_dma_release( dmap->dma_chan);
331       isa_dma_acquire(fudge);
332       dmap->dma_chan = fudge;
333     }
334
335     dsp_count = 0;
336     dsp_cleanup();
337     if (dsp_16bit) 
338         sb_dsp_command(0xd5);   /* Halt DMA until trigger() is called */
339     else
340         sb_dsp_command(0xd0);   /* Halt DMA until trigger() is called */
341
342     trigger_bits = 0;
343     return 0;
344 }
345
346 static int
347 sb16_dsp_prepare_for_output(int dev, int bsize, int bcount)
348 {
349     int fudge = dsp_16bit ? dma16 : dma8;
350     struct dma_buffparms *dmap =  audio_devs[dev]->dmap_out;
351
352     if (dmap->dma_chan != fudge ) {
353       isa_dma_release( dmap->dma_chan);
354       isa_dma_acquire(fudge);
355       dmap->dma_chan = fudge;
356     }
357
358     audio_devs[my_dev]->dmachan1 = fudge;
359
360     dsp_count = 0;
361     dsp_cleanup();
362     if (dsp_16bit) 
363         sb_dsp_command(0xd5);   /* Halt DMA until trigger() is called */
364     else
365         sb_dsp_command(0xd0);   /* Halt DMA until trigger() is called */
366
367     trigger_bits = 0;
368     return 0;
369 }
370
371 static void
372 sb16_dsp_trigger(int dev, int bits)
373 {
374     if (bits != 0)
375         bits = 1;
376
377     if (bits == trigger_bits)   /* No change */
378         return;
379
380     trigger_bits = bits;
381
382     if (!bits)
383         sb_dsp_command(0xd0);   /* Halt DMA */
384     else if (bits & irq_mode) {
385         if (dsp_16bit)
386             sb_dsp_command(0xd6);       /* Continue 16bit DMA */
387         else
388             sb_dsp_command(0xd4);       /* Continue 8bit DMA */
389     }
390 }
391
392 static void
393 dsp_cleanup(void)
394 {
395     irq_mode = IMODE_NONE;
396     intr_active = 0;
397 }
398
399 static void
400 sb16_dsp_reset(int dev)
401 {
402     u_long   flags;
403
404     flags = splhigh();
405
406     sb_reset_dsp();
407     dsp_cleanup();
408
409     splx(flags);
410 }
411
412 static void
413 sb16_dsp_halt(int dev)
414 {
415
416     if (dsp_16bit) {
417         sb_dsp_command01(0xd9);
418         sb_dsp_command01(0xd5);
419     } else {
420         sb_dsp_command01(0xda);
421         sb_dsp_command01(0xd0);
422     }
423
424
425 }
426
427 static void
428 set_irq_hw(int level)
429 {
430     int             ival;
431
432     switch (level) {
433 #ifdef PC98
434     case 5:
435         ival = 8;
436         break;
437     case 3:
438         ival = 1;
439         break;
440     case 10:
441         ival = 2;
442         break;  
443 #else
444     case 5:
445         ival = 2;
446         break;
447     case 7:
448         ival = 4;
449         break;
450     case 9:
451         ival = 1;
452         break;
453     case 10:
454         ival = 8;
455         break;
456 #endif
457     default:
458         printf("SB16_IRQ_LEVEL %d does not exist\n", level);
459         return;
460     }
461     sb_setmixer(IRQ_NR, ival);
462 }
463
464 void
465 sb16_dsp_init(struct address_info * hw_config)
466 {
467     if (sbc_major < 4)
468         return;         /* Not a SB16 */
469
470     snprintf(sb16_dsp_operations.name, sizeof(sb16_dsp_operations.name),
471         "SoundBlaster 16 %d.%d", sbc_major, sbc_minor);
472
473     conf_printf(sb16_dsp_operations.name, hw_config);
474
475     if (num_audiodevs < MAX_AUDIO_DEV) {
476         audio_devs[my_dev = num_audiodevs++] = &sb16_dsp_operations;
477         audio_devs[my_dev]->dmachan1 = dma8;
478         audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
479
480     } else
481         printf("SB: Too many DSP devices available\n");
482     sb16_dsp_ok = 1;
483     return;
484 }
485
486 int
487 sb16_dsp_detect(struct address_info * hw_config)
488 {
489     struct address_info *sb_config;
490
491     if (sb16_dsp_ok)
492         return 1;       /* Can't drive two cards */
493
494     if (!(sb_config = sound_getconf(SNDCARD_SB))) {
495         printf("SB16 Error: Plain SB not configured\n");
496         return 0;
497     }
498     /*
499      * sb_setmixer(OPSW,0xf); if(sb_getmixer(OPSW)!=0xf) return 0;
500      */
501
502     if (!sb_reset_dsp())
503         return 0;
504
505     if (sbc_major < 4)  /* Set by the plain SB driver */
506         return 0;       /* Not a SB16 */
507
508 #ifdef PC98
509     hw_config->dma = sb_config->dma;
510 #else 
511     if (hw_config->dma < 4)
512         if (hw_config->dma != sb_config->dma) {
513             printf("SB16 Error: Invalid DMA channel %d/%d\n",
514                    sb_config->dma, hw_config->dma);
515             return 0;
516         }
517 #endif
518     dma16 = hw_config->dma;
519     dma8 = sb_config->dma;
520     /*    hw_config->irq = 0;  sb_config->irq; 
521     hw_config->io_base = sb_config->io_base;
522     */
523     set_irq_hw(sb_config->irq);
524
525 #ifdef PC98
526     sb_setmixer (DMA_NR, hw_config->dma == 0 ? 1 : 2);
527 #else
528     sb_setmixer(DMA_NR, (1 << hw_config->dma) | (1 << sb_config->dma));
529 #endif
530
531     DEB(printf("SoundBlaster 16: IRQ %d DMA %d OK\n",
532                 sb_config->irq, hw_config->dma));
533
534     /*
535      * dsp_showmessage(0xe3,99);
536      */
537     sb16_dsp_ok = 1;
538     return 1;
539 }
540
541 void
542 sb16_dsp_interrupt(int unused)
543 {
544         int             data;
545
546         data = inb(DSP_DATA_AVL16);     /* Interrupt acknowledge */
547
548         if (intr_active)
549                 switch (irq_mode) {
550                 case IMODE_OUTPUT:
551                         DMAbuf_outputintr(my_dev, 1);
552                         break;
553
554                 case IMODE_INPUT:
555                         DMAbuf_inputintr(my_dev);
556                         break;
557
558                 default:
559                         printf("SoundBlaster: Unexpected interrupt\n");
560                 }
561 }
562 #endif