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.
15 * Bartlomiej Zolnierkiewicz : Added __init to pas_pcm_init()
18 #include <linux/init.h>
19 #include <linux/spinlock.h>
20 #include <linux/timex.h>
21 #include "sound_config.h"
25 #define PAS_PCM_INTRBITS (0x08)
27 * Sample buffer timer interrupt enable
34 static unsigned long pcm_speed
; /* sampling rate */
35 static unsigned char pcm_channels
= 1; /* channels (1 or 2) */
36 static unsigned char pcm_bits
= 8; /* bits/sample (8 or 16) */
37 static unsigned char pcm_filter
; /* filter FLAG */
38 static unsigned char pcm_mode
= PCM_NON
;
39 static unsigned long pcm_count
;
40 static unsigned short pcm_bitsok
= 8; /* mask of OK bits */
42 int pas_audiodev
= -1;
45 extern spinlock_t pas_lock
;
47 static int pcm_set_speed(int arg
)
62 foo
= ((PIT_TICK_RATE
/ 2) + (arg
/ 2)) / arg
;
63 arg
= ((PIT_TICK_RATE
/ 2) + (foo
/ 2)) / foo
;
67 foo
= (PIT_TICK_RATE
+ (arg
/ 2)) / arg
;
68 arg
= (PIT_TICK_RATE
+ (foo
/ 2)) / foo
;
73 tmp
= pas_read(0x0B8A);
76 * Set anti-aliasing filters according to sample rate. You really *NEED*
77 * to enable this feature for all normal recording unless you want to
78 * experiment with aliasing effects.
79 * These filters apply to the selected "recording" source.
80 * I (pfw) don't know the encoding of these 5 bits. The values shown
81 * come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
83 * I cleared bit 5 of these values, since that bit controls the master
84 * mute flag. (Olav Wölfelschneider)
87 #if !defined NO_AUTO_FILTER_SET
89 if (pcm_speed
>= 2 * 17897)
91 else if (pcm_speed
>= 2 * 15909)
93 else if (pcm_speed
>= 2 * 11931)
95 else if (pcm_speed
>= 2 * 8948)
97 else if (pcm_speed
>= 2 * 5965)
99 else if (pcm_speed
>= 2 * 2982)
104 spin_lock_irqsave(&pas_lock
, flags
);
106 pas_write(tmp
& ~(0x40 | 0x80), 0x0B8A);
107 pas_write(0x00 | 0x30 | 0x04, 0x138B);
108 pas_write(foo
& 0xff, 0x1388);
109 pas_write((foo
>> 8) & 0xff, 0x1388);
110 pas_write(tmp
, 0x0B8A);
112 spin_unlock_irqrestore(&pas_lock
, flags
);
117 static int pcm_set_channels(int arg
)
120 if ((arg
!= 1) && (arg
!= 2))
123 if (arg
!= pcm_channels
)
125 pas_write(pas_read(0xF8A) ^ 0x20, 0xF8A);
128 pcm_set_speed(pcm_speed
); /* The speed must be reinitialized */
133 static int pcm_set_bits(int arg
)
138 if ((arg
& pcm_bitsok
) != arg
)
143 pas_write(pas_read(0x8389) ^ 0x04, 0x8389);
150 static int pas_audio_ioctl(int dev
, unsigned int cmd
, void __user
*arg
)
157 case SOUND_PCM_WRITE_RATE
:
158 if (get_user(val
, p
))
160 ret
= pcm_set_speed(val
);
163 case SOUND_PCM_READ_RATE
:
167 case SNDCTL_DSP_STEREO
:
168 if (get_user(val
, p
))
170 ret
= pcm_set_channels(val
+ 1) - 1;
173 case SOUND_PCM_WRITE_CHANNELS
:
174 if (get_user(val
, p
))
176 ret
= pcm_set_channels(val
);
179 case SOUND_PCM_READ_CHANNELS
:
183 case SNDCTL_DSP_SETFMT
:
184 if (get_user(val
, p
))
186 ret
= pcm_set_bits(val
);
189 case SOUND_PCM_READ_BITS
:
196 return put_user(ret
, p
);
199 static void pas_audio_reset(int dev
)
201 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A); /* Disable PCM */
204 static int pas_audio_open(int dev
, int mode
)
209 spin_lock_irqsave(&pas_lock
, flags
);
212 spin_unlock_irqrestore(&pas_lock
, flags
);
216 spin_unlock_irqrestore(&pas_lock
, flags
);
218 if ((err
= pas_set_intr(PAS_PCM_INTRBITS
)) < 0)
228 static void pas_audio_close(int dev
)
232 spin_lock_irqsave(&pas_lock
, flags
);
234 pas_audio_reset(dev
);
235 pas_remove_intr(PAS_PCM_INTRBITS
);
239 spin_unlock_irqrestore(&pas_lock
, flags
);
242 static void pas_audio_output_block(int dev
, unsigned long buf
, int count
,
245 unsigned long flags
, cnt
;
248 if (audio_devs
[dev
]->dmap_out
->dma
> 3)
251 if (audio_devs
[dev
]->flags
& DMA_AUTOMODE
&&
256 spin_lock_irqsave(&pas_lock
, flags
);
258 pas_write(pas_read(0xF8A) & ~0x40,
261 /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
263 if (audio_devs
[dev
]->dmap_out
->dma
> 3)
266 if (count
!= pcm_count
)
268 pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
269 pas_write(0x40 | 0x30 | 0x04, 0x138B);
270 pas_write(count
& 0xff, 0x1389);
271 pas_write((count
>> 8) & 0xff, 0x1389);
272 pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
276 pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
278 pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
283 spin_unlock_irqrestore(&pas_lock
, flags
);
286 static void pas_audio_start_input(int dev
, unsigned long buf
, int count
,
293 if (audio_devs
[dev
]->dmap_out
->dma
> 3)
296 if (audio_devs
[pas_audiodev
]->flags
& DMA_AUTOMODE
&&
301 spin_lock_irqsave(&pas_lock
, flags
);
303 /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
305 if (audio_devs
[dev
]->dmap_out
->dma
> 3)
308 if (count
!= pcm_count
)
310 pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
311 pas_write(0x40 | 0x30 | 0x04, 0x138B);
312 pas_write(count
& 0xff, 0x1389);
313 pas_write((count
>> 8) & 0xff, 0x1389);
314 pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
318 pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
320 pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
325 spin_unlock_irqrestore(&pas_lock
, flags
);
329 static void pas_audio_trigger(int dev
, int state
)
333 spin_lock_irqsave(&pas_lock
, flags
);
336 if (state
& PCM_ENABLE_OUTPUT
)
337 pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
338 else if (state
& PCM_ENABLE_INPUT
)
339 pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
341 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
343 spin_unlock_irqrestore(&pas_lock
, flags
);
347 static int pas_audio_prepare_for_input(int dev
, int bsize
, int bcount
)
349 pas_audio_reset(dev
);
353 static int pas_audio_prepare_for_output(int dev
, int bsize
, int bcount
)
355 pas_audio_reset(dev
);
359 static struct audio_driver pas_audio_driver
=
361 .owner
= THIS_MODULE
,
362 .open
= pas_audio_open
,
363 .close
= pas_audio_close
,
364 .output_block
= pas_audio_output_block
,
365 .start_input
= pas_audio_start_input
,
366 .ioctl
= pas_audio_ioctl
,
367 .prepare_for_input
= pas_audio_prepare_for_input
,
368 .prepare_for_output
= pas_audio_prepare_for_output
,
369 .halt_io
= pas_audio_reset
,
370 .trigger
= pas_audio_trigger
373 void __init
pas_pcm_init(struct address_info
*hw_config
)
376 if (pas_read(0xEF8B) & 0x08)
379 pcm_set_speed(DSP_DEFAULT_SPEED
);
381 if ((pas_audiodev
= sound_install_audiodrv(AUDIO_DRIVER_VERSION
,
382 "Pro Audio Spectrum",
384 sizeof(struct audio_driver
),
386 AFMT_U8
| AFMT_S16_LE
,
389 hw_config
->dma
)) < 0)
390 printk(KERN_WARNING
"PAS16: Too many PCM devices available\n");
393 void pas_pcm_interrupt(unsigned char status
, int cause
)
398 * Halt the PCM first. Otherwise we don't have time to start a new
399 * block before the PCM chip proceeds to the next sample
402 if (!(audio_devs
[pas_audiodev
]->flags
& DMA_AUTOMODE
))
403 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
408 DMAbuf_outputintr(pas_audiodev
, 1);
412 DMAbuf_inputintr(pas_audiodev
);
416 printk(KERN_WARNING
"PAS: Unexpected PCM interrupt\n");