1 /* Driver for SB16 ISA card
2 * Implementing audio/audio_fw.h
4 * February 2006 Integrated standalone driver with audio framework (Peter Boonstoppel)
5 * August 24 2005 Ported audio driver to user space (only audio playback) (Peter Boonstoppel)
6 * May 20 1995 SB16 Driver: Michel R. Prevenier
14 static void dsp_dma_setup(phys_bytes address
, int count
, int sub_dev
);
16 static int dsp_ioctl(int request
, void *val
, int *len
);
17 static int dsp_set_size(unsigned int size
);
18 static int dsp_set_speed(unsigned int speed
);
19 static int dsp_set_stereo(unsigned int stereo
);
20 static int dsp_set_bits(unsigned int bits
);
21 static int dsp_set_sign(unsigned int sign
);
22 static int dsp_get_max_frag_size(u32_t
*val
, int *len
);
25 static unsigned int DspStereo
= DEFAULT_STEREO
;
26 static unsigned int DspSpeed
= DEFAULT_SPEED
;
27 static unsigned int DspBits
= DEFAULT_BITS
;
28 static unsigned int DspSign
= DEFAULT_SIGN
;
29 static unsigned int DspFragmentSize
;
31 static phys_bytes DmaPhys
;
32 static int running
= FALSE
;
36 special_file_t special_file
[3];
42 drv
.DriverName
= "SB16";
43 drv
.NrOfSubDevices
= 2;
44 drv
.NrOfSpecialFiles
= 3;
46 sub_dev
[AUDIO
].readable
= 1;
47 sub_dev
[AUDIO
].writable
= 1;
48 sub_dev
[AUDIO
].DmaSize
= 64 * 1024;
49 sub_dev
[AUDIO
].NrOfDmaFragments
= 2;
50 sub_dev
[AUDIO
].MinFragmentSize
= 1024;
51 sub_dev
[AUDIO
].NrOfExtraBuffers
= 4;
53 sub_dev
[MIXER
].writable
= 0;
54 sub_dev
[MIXER
].readable
= 0;
56 special_file
[0].minor_dev_nr
= 0;
57 special_file
[0].write_chan
= AUDIO
;
58 special_file
[0].read_chan
= NO_CHANNEL
;
59 special_file
[0].io_ctl
= AUDIO
;
61 special_file
[1].minor_dev_nr
= 1;
62 special_file
[1].write_chan
= NO_CHANNEL
;
63 special_file
[1].read_chan
= AUDIO
;
64 special_file
[1].io_ctl
= AUDIO
;
66 special_file
[2].minor_dev_nr
= 2;
67 special_file
[2].write_chan
= NO_CHANNEL
;
68 special_file
[2].read_chan
= NO_CHANNEL
;
69 special_file
[2].io_ctl
= MIXER
;
75 int drv_init_hw(void) {
78 Dprint(("drv_init_hw():\n"));
80 if(drv_reset () != OK
) {
81 Dprint(("sb16: No SoundBlaster card detected\n"));
85 DspVersion
[0] = DspVersion
[1] = 0;
86 dsp_command(DSP_GET_VERSION
); /* Get DSP version bytes */
88 for(i
= 1000; i
; i
--) {
89 if(sb16_inb(DSP_DATA_AVL
) & 0x80) {
90 if(DspVersion
[0] == 0) {
91 DspVersion
[0] = sb16_inb(DSP_READ
);
93 DspVersion
[1] = sb16_inb(DSP_READ
);
99 if(DspVersion
[0] < 4) {
100 Dprint(("sb16: No SoundBlaster 16 compatible card detected\n"));
104 Dprint(("sb16: SoundBlaster DSP version %d.%d detected!\n", DspVersion
[0], DspVersion
[1]));
106 /* set SB to use our IRQ and DMA channels */
107 mixer_set(MIXER_SET_IRQ
, (1 << (SB_IRQ
/ 2 - 1)));
108 mixer_set(MIXER_SET_DMA
, (1 << SB_DMA_8
| 1 << SB_DMA_16
));
110 DspFragmentSize
= sub_dev
[AUDIO
].DmaSize
/ sub_dev
[AUDIO
].NrOfDmaFragments
;
117 int drv_reset(void) {
119 Dprint(("drv_reset():\n"));
121 sb16_outb(DSP_RESET
, 1);
122 for(i
= 0; i
< 1000; i
++); /* wait a while */
123 sb16_outb(DSP_RESET
, 0);
125 for(i
= 0; i
< 1000 && !(sb16_inb(DSP_DATA_AVL
) & 0x80); i
++);
127 if(sb16_inb(DSP_READ
) != 0xAA) return EIO
; /* No SoundBlaster */
134 int drv_start(int channel
, int DmaMode
) {
135 Dprint(("drv_start():\n"));
139 dsp_dma_setup(DmaPhys
, DspFragmentSize
* sub_dev
[channel
].NrOfDmaFragments
, DmaMode
);
141 dsp_set_speed(DspSpeed
);
143 /* Put the speaker on */
144 if(DmaMode
== DEV_WRITE_S
) {
145 dsp_command (DSP_CMD_SPKON
); /* put speaker on */
147 /* Program DSP with dma mode */
148 dsp_command((DspBits
== 8 ? DSP_CMD_8BITAUTO_OUT
: DSP_CMD_16BITAUTO_OUT
));
150 dsp_command (DSP_CMD_SPKOFF
); /* put speaker off */
152 /* Program DSP with dma mode */
153 dsp_command((DspBits
== 8 ? DSP_CMD_8BITAUTO_IN
: DSP_CMD_16BITAUTO_IN
));
156 /* Program DSP with transfer mode */
158 dsp_command((DspStereo
== 1 ? DSP_MODE_STEREO_US
: DSP_MODE_MONO_US
));
160 dsp_command((DspStereo
== 1 ? DSP_MODE_STEREO_S
: DSP_MODE_MONO_S
));
163 /* Give length of fragment to DSP */
164 if (DspBits
== 8) { /* 8 bit transfer */
166 dsp_command((DspFragmentSize
- 1) >> 0);
167 dsp_command((DspFragmentSize
- 1) >> 8);
168 } else { /* 16 bit transfer */
170 dsp_command((DspFragmentSize
- 1) >> 1);
171 dsp_command((DspFragmentSize
- 1) >> 9);
181 int drv_stop(int sub_dev
) {
183 Dprint(("drv_stop():\n"));
184 dsp_command((DspBits
== 8 ? DSP_CMD_DMA8HALT
: DSP_CMD_DMA16HALT
));
186 drv_reenable_int(sub_dev
);
193 int drv_set_dma(u32_t dma
, u32_t
UNUSED(length
), int UNUSED(chan
)) {
194 Dprint(("drv_set_dma():\n"));
201 int drv_reenable_int(int UNUSED(chan
)) {
202 Dprint(("drv_reenable_int()\n"));
203 sb16_inb((DspBits
== 8 ? DSP_DATA_AVL
: DSP_DATA16_AVL
));
209 int drv_int_sum(void) {
210 return mixer_get(MIXER_IRQ_STATUS
) & 0x0F;
215 int drv_int(int sub_dev
) {
216 return sub_dev
== AUDIO
&& mixer_get(MIXER_IRQ_STATUS
) & 0x03;
221 int drv_pause(int chan
) {
228 int drv_resume(int UNUSED(chan
)) {
229 dsp_command((DspBits
== 8 ? DSP_CMD_DMA8CONT
: DSP_CMD_DMA16CONT
));
235 int drv_io_ctl(int request
, void *val
, int *len
, int sub_dev
) {
236 Dprint(("dsp_ioctl: got ioctl %d, argument: %d sub_dev: %d\n", request
, val
, sub_dev
));
238 if(sub_dev
== AUDIO
) {
239 return dsp_ioctl(request
, val
, len
);
240 } else if(sub_dev
== MIXER
) {
241 return mixer_ioctl(request
, val
, len
);
249 int drv_get_irq(char *irq
) {
250 Dprint(("drv_get_irq():\n"));
257 int drv_get_frag_size(u32_t
*frag_size
, int UNUSED(sub_dev
)) {
258 Dprint(("drv_get_frag_size():\n"));
259 *frag_size
= DspFragmentSize
;
265 static int dsp_ioctl(int request
, void *val
, int *len
) {
269 case DSPIORATE
: status
= dsp_set_speed(*((u32_t
*) val
)); break;
270 case DSPIOSTEREO
: status
= dsp_set_stereo(*((u32_t
*) val
)); break;
271 case DSPIOBITS
: status
= dsp_set_bits(*((u32_t
*) val
)); break;
272 case DSPIOSIZE
: status
= dsp_set_size(*((u32_t
*) val
)); break;
273 case DSPIOSIGN
: status
= dsp_set_sign(*((u32_t
*) val
)); break;
274 case DSPIOMAX
: status
= dsp_get_max_frag_size(val
, len
); break;
275 case DSPIORESET
: status
= drv_reset(); break;
276 default: status
= ENOTTY
; break;
284 static void dsp_dma_setup(phys_bytes address
, int count
, int DmaMode
) {
287 Dprint(("Setting up %d bit DMA\n", DspBits
));
289 if(DspBits
== 8) { /* 8 bit sound */
292 pv_set(pvb
[0], DMA8_MASK
, SB_DMA_8
| 0x04); /* Disable DMA channel */
293 pv_set(pvb
[1], DMA8_CLEAR
, 0x00); /* Clear flip flop */
296 pv_set(pvb
[2], DMA8_MODE
, (DmaMode
== DEV_WRITE_S
? DMA8_AUTO_PLAY
: DMA8_AUTO_REC
));
298 pv_set(pvb
[3], DMA8_ADDR
, address
>> 0); /* Low_byte of address */
299 pv_set(pvb
[4], DMA8_ADDR
, address
>> 8); /* High byte of address */
300 pv_set(pvb
[5], DMA8_PAGE
, address
>> 16); /* 64K page number */
301 pv_set(pvb
[6], DMA8_COUNT
, count
>> 0); /* Low byte of count */
302 pv_set(pvb
[7], DMA8_COUNT
, count
>> 8); /* High byte of count */
303 pv_set(pvb
[8], DMA8_MASK
, SB_DMA_8
); /* Enable DMA channel */
306 } else { /* 16 bit sound */
309 pv_set(pvb
[0], DMA16_MASK
, (SB_DMA_16
& 3) | 0x04); /* Disable DMA channel */
311 pv_set(pvb
[1], DMA16_CLEAR
, 0x00); /* Clear flip flop */
314 pv_set(pvb
[2], DMA16_MODE
, (DmaMode
== DEV_WRITE_S
? DMA16_AUTO_PLAY
: DMA16_AUTO_REC
));
316 pv_set(pvb
[3], DMA16_ADDR
, (address
>> 1) & 0xFF); /* Low_byte of address */
317 pv_set(pvb
[4], DMA16_ADDR
, (address
>> 9) & 0xFF); /* High byte of address */
318 pv_set(pvb
[5], DMA16_PAGE
, (address
>> 16) & 0xFE); /* 128K page number */
319 pv_set(pvb
[6], DMA16_COUNT
, count
>> 1); /* Low byte of count */
320 pv_set(pvb
[7], DMA16_COUNT
, count
>> 9); /* High byte of count */
321 pv_set(pvb
[8], DMA16_MASK
, SB_DMA_16
& 3); /* Enable DMA channel */
329 static int dsp_set_size(unsigned int size
) {
330 Dprint(("dsp_set_size(): set fragment size to %u\n", size
));
333 if(size
< sub_dev
[AUDIO
].MinFragmentSize
|| size
> sub_dev
[AUDIO
].DmaSize
/ sub_dev
[AUDIO
].NrOfDmaFragments
|| size
% 2 != 0) {
337 DspFragmentSize
= size
;
344 static int dsp_set_speed(unsigned int speed
) {
345 Dprint(("sb16: setting speed to %u, stereo = %d\n", speed
, DspStereo
));
347 if(speed
< DSP_MIN_SPEED
|| speed
> DSP_MAX_SPEED
) {
351 /* Soundblaster 16 can be programmed with real sample rates
352 * instead of time constants
354 * Since you cannot sample and play at the same time
355 * we set in- and output rate to the same value
358 dsp_command(DSP_INPUT_RATE
); /* set input rate */
359 dsp_command(speed
>> 8); /* high byte of speed */
360 dsp_command(speed
); /* low byte of speed */
361 dsp_command(DSP_OUTPUT_RATE
); /* same for output rate */
362 dsp_command(speed
>> 8);
372 static int dsp_set_stereo(unsigned int stereo
) {
384 static int dsp_set_bits(unsigned int bits
) {
386 if(bits
!= 8 && bits
!= 16) {
397 static int dsp_set_sign(unsigned int sign
) {
398 Dprint(("sb16: set sign to %u\n", sign
));
400 DspSign
= (sign
> 0 ? 1 : 0);
407 static int dsp_get_max_frag_size(u32_t
*val
, int *len
) {
409 *val
= sub_dev
[AUDIO
].DmaSize
/ sub_dev
[AUDIO
].NrOfDmaFragments
;
415 int dsp_command(int value
) {
418 for (i
= 0; i
< SB_TIMEOUT
; i
++) {
419 if((sb16_inb(DSP_STATUS
) & 0x80) == 0) {
420 sb16_outb(DSP_COMMAND
, value
);
425 Dprint(("sb16: SoundBlaster: DSP Command(%x) timeout\n", value
));
431 int sb16_inb(int port
) {
435 if ((s
=sys_inb(port
, &value
)) != OK
)
436 panic("sys_inb() failed: %d", s
);
443 void sb16_outb(int port
, int value
) {
446 if ((s
=sys_outb(port
, value
)) != OK
)
447 panic("sys_outb() failed: %d", s
);