This source file includes following definitions.
- sb_dsp_command
- sbintr
- sb_get_irq
- sb_free_irq
- sb_reset_dsp
- dsp_speaker
- dsp_speed
- dsp_set_stereo
- sb_dsp_output_block
- sb_dsp_start_input
- dsp_cleanup
- sb_dsp_prepare_for_input
- sb_dsp_prepare_for_output
- sb_dsp_halt_xfer
- verify_irq
- sb_dsp_open
- sb_dsp_close
- sb_dsp_ioctl
- sb_dsp_reset
- sb_dsp_detect
- sb_dsp_init
- sb_dsp_disable_midi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include "sound_config.h"
31
32 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB)
33
34 #include "sb.h"
35 #include "sb_mixer.h"
36 #undef SB_TEST_IRQ
37
38 int sbc_base = 0;
39 static int sbc_irq = 0;
40 static int open_mode = 0;
41
42
43
44
45
46
47
48
49
50 int sb_dsp_ok = 0;
51
52
53
54
55 static int midi_disabled = 0;
56 int sb_dsp_highspeed = 0;
57 int sbc_major = 1, sbc_minor = 0;
58
59
60
61 static int dsp_stereo = 0;
62 static int dsp_current_speed = DSP_DEFAULT_SPEED;
63 static int sb16 = 0;
64 static int irq_verified = 0;
65
66 int sb_midi_mode = NORMAL_MIDI;
67 int sb_midi_busy = 0;
68
69
70
71
72 int sb_dsp_busy = 0;
73
74 volatile int sb_irq_mode = IMODE_NONE;
75
76
77
78
79
80 static volatile int irq_ok = 0;
81
82 int sb_duplex_midi = 0;
83 static int my_dev = 0;
84
85 volatile int sb_intr_active = 0;
86
87 static int dsp_speed (int);
88 static int dsp_set_stereo (int mode);
89 int sb_dsp_command (unsigned char val);
90
91 #if !defined(EXCLUDE_MIDI) || !defined(EXCLUDE_AUDIO)
92
93
94
95
96
97 int
98 sb_dsp_command (unsigned char val)
99 {
100 int i;
101 unsigned long limit;
102
103 limit = GET_TIME () + HZ / 10;
104
105
106
107
108
109
110
111
112
113
114
115 for (i = 0; i < 500000 && GET_TIME () < limit; i++)
116 {
117 if ((INB (DSP_STATUS) & 0x80) == 0)
118 {
119 OUTB (val, DSP_COMMAND);
120 return 1;
121 }
122 }
123
124 printk ("SoundBlaster: DSP Command(%x) Timeout.\n", val);
125 printk ("IRQ conflict???\n");
126 return 0;
127 }
128
129 void
130 sbintr (int unit)
131 {
132 int status;
133
134 #ifndef EXCLUDE_SBPRO
135 if (sb16)
136 {
137 unsigned char src = sb_getmixer (IRQ_STAT);
138
139
140
141
142
143
144 #ifndef EXCLUDE_SB16
145 if (src & 3)
146 sb16_dsp_interrupt (unit);
147
148 #ifndef EXCLUDE_MIDI
149 if (src & 4)
150 sb16midiintr (unit);
151
152
153 #endif
154
155 #endif
156
157 if (!(src & 1))
158 return;
159
160
161 }
162 #endif
163
164 status = INB (DSP_DATA_AVAIL);
165
166
167
168 if (sb_intr_active)
169 switch (sb_irq_mode)
170 {
171 case IMODE_OUTPUT:
172 sb_intr_active = 0;
173 DMAbuf_outputintr (my_dev, 1);
174 break;
175
176 case IMODE_INPUT:
177 sb_intr_active = 0;
178 DMAbuf_inputintr (my_dev);
179
180
181
182 break;
183
184 case IMODE_INIT:
185 sb_intr_active = 0;
186 irq_ok = 1;
187 break;
188
189 case IMODE_MIDI:
190 #ifndef EXCLUDE_MIDI
191 sb_midi_interrupt (unit);
192 #endif
193 break;
194
195 default:
196 printk ("SoundBlaster: Unexpected interrupt\n");
197 }
198 }
199
200 static int sb_irq_usecount = 0;
201
202 int
203 sb_get_irq (void)
204 {
205 int ok;
206
207 if (!sb_irq_usecount)
208 if ((ok = snd_set_irq_handler (sbc_irq, sbintr)) < 0)
209 return ok;
210
211 sb_irq_usecount++;
212
213 return 0;
214 }
215
216 void
217 sb_free_irq (void)
218 {
219 if (!sb_irq_usecount)
220 return;
221
222 sb_irq_usecount--;
223
224 if (!sb_irq_usecount)
225 snd_release_irq (sbc_irq);
226 }
227
228 int
229 sb_reset_dsp (void)
230 {
231 int loopc;
232
233 OUTB (1, DSP_RESET);
234 tenmicrosec ();
235 OUTB (0, DSP_RESET);
236 tenmicrosec ();
237 tenmicrosec ();
238 tenmicrosec ();
239
240 for (loopc = 0; loopc < 1000 && !(INB (DSP_DATA_AVAIL) & 0x80); loopc++);
241
242
243
244
245
246
247
248
249 if (INB (DSP_READ) != 0xAA)
250 return 0;
251
252
253
254 return 1;
255 }
256
257 #endif
258
259 #ifndef EXCLUDE_AUDIO
260
261 static void
262 dsp_speaker (char state)
263 {
264 if (state)
265 sb_dsp_command (DSP_CMD_SPKON);
266 else
267 sb_dsp_command (DSP_CMD_SPKOFF);
268 }
269
270 static int
271 dsp_speed (int speed)
272 {
273 unsigned char tconst;
274 unsigned long flags;
275 int max_speed = 44100;
276
277 if (speed < 4000)
278 speed = 4000;
279
280
281
282
283
284 if (sbc_major < 2 ||
285 (sbc_major == 2 && sbc_minor == 0))
286 max_speed = 22050;
287
288
289
290
291 if (open_mode != OPEN_WRITE)
292 if (sbc_major < 3)
293 if (sbc_major == 2 && sbc_minor > 0)
294 max_speed = 15000;
295 else
296 max_speed = 13000;
297
298 if (speed > max_speed)
299 speed = max_speed;
300
301
302
303 if (dsp_stereo && speed > 22050)
304 speed = 22050;
305
306
307
308
309 if ((speed > 22050) && sb_midi_busy)
310 {
311 printk ("SB Warning: High speed DSP not possible simultaneously with MIDI output\n");
312 speed = 22050;
313 }
314
315 if (dsp_stereo)
316 speed *= 2;
317
318
319
320
321
322 if (speed > 22050)
323 {
324
325
326 int tmp;
327
328 tconst = (unsigned char) ((65536 -
329 ((256000000 + speed / 2) / speed)) >> 8);
330 sb_dsp_highspeed = 1;
331
332 DISABLE_INTR (flags);
333 if (sb_dsp_command (0x40))
334 sb_dsp_command (tconst);
335 RESTORE_INTR (flags);
336
337 tmp = 65536 - (tconst << 8);
338 speed = (256000000 + tmp / 2) / tmp;
339 }
340 else
341 {
342 int tmp;
343
344 sb_dsp_highspeed = 0;
345 tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff;
346
347 DISABLE_INTR (flags);
348 if (sb_dsp_command (0x40))
349
350
351 sb_dsp_command (tconst);
352 RESTORE_INTR (flags);
353
354 tmp = 256 - tconst;
355 speed = (1000000 + tmp / 2) / tmp;
356 }
357
358 if (dsp_stereo)
359 speed /= 2;
360
361 dsp_current_speed = speed;
362 return speed;
363 }
364
365 static int
366 dsp_set_stereo (int mode)
367 {
368 dsp_stereo = 0;
369
370 #ifdef EXCLUDE_SBPRO
371 return 0;
372 #else
373 if (sbc_major < 3 || sb16)
374 return 0;
375
376
377
378 if (mode && sb_midi_busy)
379 {
380 printk ("SB Warning: Stereo DSP not possible simultaneously with MIDI output\n");
381 return 0;
382 }
383
384 dsp_stereo = !!mode;
385 return dsp_stereo;
386 #endif
387 }
388
389 static void
390 sb_dsp_output_block (int dev, unsigned long buf, int count,
391 int intrflag, int restart_dma)
392 {
393 unsigned long flags;
394
395 if (!sb_irq_mode)
396 dsp_speaker (ON);
397
398 sb_irq_mode = IMODE_OUTPUT;
399 DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
400
401 if (audio_devs[dev]->dmachan > 3)
402 count >>= 1;
403 count--;
404
405 if (sb_dsp_highspeed)
406 {
407 DISABLE_INTR (flags);
408 if (sb_dsp_command (0x48))
409
410
411 {
412 sb_dsp_command ((unsigned char) (count & 0xff));
413 sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
414 sb_dsp_command (0x91);
415
416
417 }
418 else
419 printk ("SB Error: Unable to start (high speed) DAC\n");
420 RESTORE_INTR (flags);
421 }
422 else
423 {
424 DISABLE_INTR (flags);
425 if (sb_dsp_command (0x14))
426
427
428 {
429 sb_dsp_command ((unsigned char) (count & 0xff));
430 sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
431 }
432 else
433 printk ("SB Error: Unable to start DAC\n");
434 RESTORE_INTR (flags);
435 }
436 sb_intr_active = 1;
437 }
438
439 static void
440 sb_dsp_start_input (int dev, unsigned long buf, int count, int intrflag,
441 int restart_dma)
442 {
443
444
445
446
447 unsigned long flags;
448
449 if (!sb_irq_mode)
450 dsp_speaker (OFF);
451
452 sb_irq_mode = IMODE_INPUT;
453 DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
454
455 if (audio_devs[dev]->dmachan > 3)
456 count >>= 1;
457 count--;
458
459 if (sb_dsp_highspeed)
460 {
461 DISABLE_INTR (flags);
462 if (sb_dsp_command (0x48))
463
464
465 {
466 sb_dsp_command ((unsigned char) (count & 0xff));
467 sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
468 sb_dsp_command (0x99);
469
470
471 }
472 else
473 printk ("SB Error: Unable to start (high speed) ADC\n");
474 RESTORE_INTR (flags);
475 }
476 else
477 {
478 DISABLE_INTR (flags);
479 if (sb_dsp_command (0x24))
480
481
482 {
483 sb_dsp_command ((unsigned char) (count & 0xff));
484 sb_dsp_command ((unsigned char) ((count >> 8) & 0xff));
485 }
486 else
487 printk ("SB Error: Unable to start ADC\n");
488 RESTORE_INTR (flags);
489 }
490
491 sb_intr_active = 1;
492 }
493
494 static void
495 dsp_cleanup (void)
496 {
497 sb_intr_active = 0;
498 }
499
500 static int
501 sb_dsp_prepare_for_input (int dev, int bsize, int bcount)
502 {
503 dsp_cleanup ();
504 dsp_speaker (OFF);
505
506 if (sbc_major == 3)
507
508
509 {
510 if (dsp_stereo)
511 sb_dsp_command (0xa8);
512 else
513 sb_dsp_command (0xa0);
514
515 dsp_speed (dsp_current_speed);
516
517
518
519 }
520 return 0;
521 }
522
523 static int
524 sb_dsp_prepare_for_output (int dev, int bsize, int bcount)
525 {
526 dsp_cleanup ();
527 dsp_speaker (ON);
528
529 #ifndef EXCLUDE_SBPRO
530 if (sbc_major == 3)
531
532
533 {
534 sb_mixer_set_stereo (dsp_stereo);
535 dsp_speed (dsp_current_speed);
536
537
538
539 }
540 #endif
541 return 0;
542 }
543
544 static void
545 sb_dsp_halt_xfer (int dev)
546 {
547 }
548
549 static int
550 verify_irq (void)
551 {
552 #if 0
553 DEFINE_WAIT_QUEUE (testq, testf);
554
555 irq_ok = 0;
556
557 if (sb_get_irq () == -1)
558 {
559 printk ("*** SB Error: Irq %d already in use\n", sbc_irq);
560 return 0;
561 }
562
563
564 sb_irq_mode = IMODE_INIT;
565
566 sb_dsp_command (0xf2);
567
568
569
570 DO_SLEEP (testq, testf, HZ / 5);
571
572 sb_free_irq ();
573
574 if (!irq_ok)
575 {
576 printk ("SB Warning: IRQ%d test not passed!", sbc_irq);
577 irq_ok = 1;
578 }
579 #else
580 irq_ok = 1;
581 #endif
582 return irq_ok;
583 }
584
585 static int
586 sb_dsp_open (int dev, int mode)
587 {
588 int retval;
589
590 if (!sb_dsp_ok)
591 {
592 printk ("SB Error: SoundBlaster board not installed\n");
593 return RET_ERROR (ENXIO);
594 }
595
596 if (sb_intr_active || (sb_midi_busy && sb_midi_mode == UART_MIDI))
597 {
598 printk ("SB: PCM not possible during MIDI input\n");
599 return RET_ERROR (EBUSY);
600 }
601
602 if (!irq_verified)
603 {
604 verify_irq ();
605 irq_verified = 1;
606 }
607 else if (!irq_ok)
608 printk ("SB Warning: Incorrect IRQ setting %d\n",
609 sbc_irq);
610
611 retval = sb_get_irq ();
612 if (retval)
613 return retval;
614
615 if (DMAbuf_open_dma (dev) < 0)
616 {
617 sb_free_irq ();
618 printk ("SB: DMA Busy\n");
619 return RET_ERROR (EBUSY);
620 }
621
622 sb_irq_mode = IMODE_NONE;
623
624 sb_dsp_busy = 1;
625 open_mode = mode;
626
627 return 0;
628 }
629
630 static void
631 sb_dsp_close (int dev)
632 {
633 DMAbuf_close_dma (dev);
634 sb_free_irq ();
635 dsp_cleanup ();
636 dsp_speaker (OFF);
637 sb_dsp_busy = 0;
638 sb_dsp_highspeed = 0;
639 open_mode = 0;
640 }
641
642 static int
643 sb_dsp_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
644 {
645 switch (cmd)
646 {
647 case SOUND_PCM_WRITE_RATE:
648 if (local)
649 return dsp_speed (arg);
650 return IOCTL_OUT (arg, dsp_speed (IOCTL_IN (arg)));
651 break;
652
653 case SOUND_PCM_READ_RATE:
654 if (local)
655 return dsp_current_speed;
656 return IOCTL_OUT (arg, dsp_current_speed);
657 break;
658
659 case SOUND_PCM_WRITE_CHANNELS:
660 if (local)
661 return dsp_set_stereo (arg - 1) + 1;
662 return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg) - 1) + 1);
663 break;
664
665 case SOUND_PCM_READ_CHANNELS:
666 if (local)
667 return dsp_stereo + 1;
668 return IOCTL_OUT (arg, dsp_stereo + 1);
669 break;
670
671 case SNDCTL_DSP_STEREO:
672 if (local)
673 return dsp_set_stereo (arg);
674 return IOCTL_OUT (arg, dsp_set_stereo (IOCTL_IN (arg)));
675 break;
676
677 case SOUND_PCM_WRITE_BITS:
678 case SOUND_PCM_READ_BITS:
679 if (local)
680 return 8;
681 return IOCTL_OUT (arg, 8);
682
683
684 break;
685
686 case SOUND_PCM_WRITE_FILTER:
687 case SOUND_PCM_READ_FILTER:
688 return RET_ERROR (EINVAL);
689 break;
690
691 default:
692 return RET_ERROR (EINVAL);
693 }
694
695 return RET_ERROR (EINVAL);
696 }
697
698 static void
699 sb_dsp_reset (int dev)
700 {
701 unsigned long flags;
702
703 DISABLE_INTR (flags);
704
705 sb_reset_dsp ();
706 dsp_speed (dsp_current_speed);
707 dsp_cleanup ();
708
709 RESTORE_INTR (flags);
710 }
711
712 #endif
713
714 int
715 sb_dsp_detect (struct address_info *hw_config)
716 {
717 sbc_base = hw_config->io_base;
718 sbc_irq = hw_config->irq;
719
720 if (sb_dsp_ok)
721 return 0;
722
723
724
725 if (!sb_reset_dsp ())
726 return 0;
727
728 return 1;
729
730
731 }
732
733 #ifndef EXCLUDE_AUDIO
734 static struct audio_operations sb_dsp_operations =
735 {
736 "SoundBlaster",
737 NOTHING_SPECIAL,
738 AFMT_U8,
739 NULL,
740 sb_dsp_open,
741 sb_dsp_close,
742 sb_dsp_output_block,
743 sb_dsp_start_input,
744 sb_dsp_ioctl,
745 sb_dsp_prepare_for_input,
746 sb_dsp_prepare_for_output,
747 sb_dsp_reset,
748 sb_dsp_halt_xfer,
749 NULL,
750 NULL
751 };
752
753 #endif
754
755 long
756 sb_dsp_init (long mem_start, struct address_info *hw_config)
757 {
758 int i;
759
760 sbc_major = sbc_minor = 0;
761 sb_dsp_command (0xe1);
762
763
764
765 for (i = 1000; i; i--)
766 {
767 if (INB (DSP_DATA_AVAIL) & 0x80)
768 {
769
770
771 if (sbc_major == 0)
772 sbc_major = INB (DSP_READ);
773 else
774 {
775 sbc_minor = INB (DSP_READ);
776 break;
777 }
778 }
779 }
780
781 if (sbc_major == 2 || sbc_major == 3)
782 sb_duplex_midi = 1;
783
784 if (sbc_major == 4)
785 sb16 = 1;
786
787 #ifndef EXCLUDE_SBPRO
788 if (sbc_major >= 3)
789 sb_mixer_init (sbc_major);
790 #endif
791
792 #ifndef EXCLUDE_YM8312
793
794 if (sbc_major > 3 ||
795 (sbc_major == 3 && INB (0x388) == 0x00))
796 enable_opl3_mode (OPL3_LEFT, OPL3_RIGHT, OPL3_BOTH);
797 #endif
798
799 if (sbc_major >= 3)
800 {
801 #ifndef SCO
802 sprintf (sb_dsp_operations.name, "SoundBlaster Pro %d.%d", sbc_major, sbc_minor);
803 #endif
804 }
805 else
806 {
807 #ifndef SCO
808 sprintf (sb_dsp_operations.name, "SoundBlaster %d.%d", sbc_major, sbc_minor);
809 #endif
810 }
811
812 printk (" <%s>", sb_dsp_operations.name);
813
814 #ifndef EXCLUDE_AUDIO
815 #if !defined(EXCLUDE_SB16) && !defined(EXCLUDE_SBPRO)
816 if (!sb16)
817
818
819 #endif
820 if (num_audiodevs < MAX_AUDIO_DEV)
821 {
822 audio_devs[my_dev = num_audiodevs++] = &sb_dsp_operations;
823 audio_devs[my_dev]->buffcount = DSP_BUFFCOUNT;
824 audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
825 audio_devs[my_dev]->dmachan = hw_config->dma;
826 }
827 else
828 printk ("SB: Too many DSP devices available\n");
829 #endif
830
831 #ifndef EXCLUDE_MIDI
832 if (!midi_disabled && !sb16)
833
834
835
836 sb_midi_init (sbc_major);
837 #endif
838
839 sb_dsp_ok = 1;
840 return mem_start;
841 }
842
843 void
844 sb_dsp_disable_midi (void)
845 {
846 midi_disabled = 1;
847 }
848
849 #endif