2 * pas2_pcm.c Audio routines for PAS16
5 * Copyright (C) by Hannu Savolainen 1993-1997
7 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
8 * Version 2 (June 1991). See the "COPYING" file distributed with this software
12 * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
13 * Alan Cox : Swatted a double allocation of device bug. Made a few
14 * more things module options.
17 #include <linux/config.h>
19 #include "sound_config.h"
28 #define PAS_PCM_INTRBITS (0x08)
30 * Sample buffer timer interrupt enable
37 static unsigned long pcm_speed
= 0; /* sampling rate */
38 static unsigned char pcm_channels
= 1; /* channels (1 or 2) */
39 static unsigned char pcm_bits
= 8; /* bits/sample (8 or 16) */
40 static unsigned char pcm_filter
= 0; /* filter FLAG */
41 static unsigned char pcm_mode
= PCM_NON
;
42 static unsigned long pcm_count
= 0;
43 static unsigned short pcm_bitsok
= 8; /* mask of OK bits */
44 static int pcm_busy
= 0;
45 int pas_audiodev
= -1;
46 static int open_mode
= 0;
48 static int pcm_set_speed(int arg
)
63 foo
= (596590 + (arg
/ 2)) / arg
;
64 arg
= (596590 + (foo
/ 2)) / foo
;
68 foo
= (1193180 + (arg
/ 2)) / arg
;
69 arg
= (1193180 + (foo
/ 2)) / foo
;
74 tmp
= pas_read(0x0B8A);
77 * Set anti-aliasing filters according to sample rate. You really *NEED*
78 * to enable this feature for all normal recording unless you want to
79 * experiment with aliasing effects.
80 * These filters apply to the selected "recording" source.
81 * I (pfw) don't know the encoding of these 5 bits. The values shown
82 * come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
84 * I cleared bit 5 of these values, since that bit controls the master
85 * mute flag. (Olav Wölfelschneider)
88 #if !defined NO_AUTO_FILTER_SET
90 if (pcm_speed
>= 2 * 17897)
92 else if (pcm_speed
>= 2 * 15909)
94 else if (pcm_speed
>= 2 * 11931)
96 else if (pcm_speed
>= 2 * 8948)
98 else if (pcm_speed
>= 2 * 5965)
100 else if (pcm_speed
>= 2 * 2982)
108 pas_write(tmp
& ~(0x40 | 0x80), 0x0B8A);
109 pas_write(0x00 | 0x30 | 0x04, 0x138B);
110 pas_write(foo
& 0xff, 0x1388);
111 pas_write((foo
>> 8) & 0xff, 0x1388);
112 pas_write(tmp
, 0x0B8A);
114 restore_flags(flags
);
119 static int pcm_set_channels(int arg
)
122 if ((arg
!= 1) && (arg
!= 2))
125 if (arg
!= pcm_channels
)
127 pas_write(pas_read(0xF8A) ^ 0x20, 0xF8A);
130 pcm_set_speed(pcm_speed
); /* The speed must be reinitialized */
135 static int pcm_set_bits(int arg
)
140 if ((arg
& pcm_bitsok
) != arg
)
145 pas_write(pas_read(0x8389) ^ 0x04, 0x8389);
152 static int pas_audio_ioctl(int dev
, unsigned int cmd
, caddr_t arg
)
156 DEB(printk("pas2_pcm.c: static int pas_audio_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd
, arg
));
160 case SOUND_PCM_WRITE_RATE
:
161 if (get_user(val
, (int *)arg
))
163 ret
= pcm_set_speed(val
);
166 case SOUND_PCM_READ_RATE
:
170 case SNDCTL_DSP_STEREO
:
171 if (get_user(val
, (int *)arg
))
173 ret
= pcm_set_channels(val
+ 1) - 1;
176 case SOUND_PCM_WRITE_CHANNELS
:
177 if (get_user(val
, (int *)arg
))
179 ret
= pcm_set_channels(val
);
182 case SOUND_PCM_READ_CHANNELS
:
186 case SNDCTL_DSP_SETFMT
:
187 if (get_user(val
, (int *)arg
))
189 ret
= pcm_set_bits(val
);
192 case SOUND_PCM_READ_BITS
:
199 return put_user(ret
, (int *)arg
);
202 static void pas_audio_reset(int dev
)
204 DEB(printk("pas2_pcm.c: static void pas_audio_reset(void)\n"));
206 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A); /* Disable PCM */
209 static int pas_audio_open(int dev
, int mode
)
214 DEB(printk("pas2_pcm.c: static int pas_audio_open(int mode = %X)\n", mode
));
220 restore_flags(flags
);
224 restore_flags(flags
);
226 if ((err
= pas_set_intr(PAS_PCM_INTRBITS
)) < 0)
236 static void pas_audio_close(int dev
)
240 DEB(printk("pas2_pcm.c: static void pas_audio_close(void)\n"));
245 pas_audio_reset(dev
);
246 pas_remove_intr(PAS_PCM_INTRBITS
);
250 restore_flags(flags
);
253 static void pas_audio_output_block(int dev
, unsigned long buf
, int count
,
256 unsigned long flags
, cnt
;
258 DEB(printk("pas2_pcm.c: static void pas_audio_output_block(char *buf = %P, int count = %X)\n", buf
, count
));
261 if (audio_devs
[dev
]->dmap_out
->dma
> 3)
264 if (audio_devs
[dev
]->flags
& DMA_AUTOMODE
&&
272 pas_write(pas_read(0xF8A) & ~0x40,
275 /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
277 if (audio_devs
[dev
]->dmap_out
->dma
> 3)
280 if (count
!= pcm_count
)
282 pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
283 pas_write(0x40 | 0x30 | 0x04, 0x138B);
284 pas_write(count
& 0xff, 0x1389);
285 pas_write((count
>> 8) & 0xff, 0x1389);
286 pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
290 pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
292 pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
297 restore_flags(flags
);
300 static void pas_audio_start_input(int dev
, unsigned long buf
, int count
,
306 DEB(printk("pas2_pcm.c: static void pas_audio_start_input(char *buf = %P, int count = %X)\n", buf
, count
));
309 if (audio_devs
[dev
]->dmap_out
->dma
> 3)
312 if (audio_devs
[pas_audiodev
]->flags
& DMA_AUTOMODE
&&
320 /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
322 if (audio_devs
[dev
]->dmap_out
->dma
> 3)
325 if (count
!= pcm_count
)
327 pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
328 pas_write(0x40 | 0x30 | 0x04, 0x138B);
329 pas_write(count
& 0xff, 0x1389);
330 pas_write((count
>> 8) & 0xff, 0x1389);
331 pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
335 pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
337 pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
342 restore_flags(flags
);
346 static void pas_audio_trigger(int dev
, int state
)
354 if (state
& PCM_ENABLE_OUTPUT
)
355 pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
356 else if (state
& PCM_ENABLE_INPUT
)
357 pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
359 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
361 restore_flags(flags
);
365 static int pas_audio_prepare_for_input(int dev
, int bsize
, int bcount
)
367 pas_audio_reset(dev
);
371 static int pas_audio_prepare_for_output(int dev
, int bsize
, int bcount
)
373 pas_audio_reset(dev
);
377 static struct audio_driver pas_audio_driver
=
381 pas_audio_output_block
,
382 pas_audio_start_input
,
384 pas_audio_prepare_for_input
,
385 pas_audio_prepare_for_output
,
394 void pas_pcm_init(struct address_info
*hw_config
)
396 DEB(printk("pas2_pcm.c: long pas_pcm_init()\n"));
399 if (pas_read(0xEF8B) & 0x08)
402 pcm_set_speed(DSP_DEFAULT_SPEED
);
404 if ((pas_audiodev
= sound_install_audiodrv(AUDIO_DRIVER_VERSION
,
405 "Pro Audio Spectrum",
407 sizeof(struct audio_driver
),
409 AFMT_U8
| AFMT_S16_LE
,
412 hw_config
->dma
)) < 0)
413 printk(KERN_WARNING
"PAS16: Too many PCM devices available\n");
416 void pas_pcm_interrupt(unsigned char status
, int cause
)
421 * Halt the PCM first. Otherwise we don't have time to start a new
422 * block before the PCM chip proceeds to the next sample
425 if (!(audio_devs
[pas_audiodev
]->flags
& DMA_AUTOMODE
))
426 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
431 DMAbuf_outputintr(pas_audiodev
, 1);
435 DMAbuf_inputintr(pas_audiodev
);
439 printk(KERN_WARNING
"PAS: Unexpected PCM interrupt\n");