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 "sound_config.h"
28 #define PAS_PCM_INTRBITS (0x08)
30 * Sample buffer timer interrupt enable
37 static unsigned long pcm_speed; /* 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; /* filter FLAG */
41 static unsigned char pcm_mode = PCM_NON;
42 static unsigned long pcm_count;
43 static unsigned short pcm_bitsok = 8; /* mask of OK bits */
45 int pas_audiodev = -1;
48 extern spinlock_t pas_lock;
50 static int pcm_set_speed(int arg)
65 foo = (596590 + (arg / 2)) / arg;
66 arg = (596590 + (foo / 2)) / foo;
70 foo = (1193180 + (arg / 2)) / arg;
71 arg = (1193180 + (foo / 2)) / foo;
76 tmp = pas_read(0x0B8A);
79 * Set anti-aliasing filters according to sample rate. You really *NEED*
80 * to enable this feature for all normal recording unless you want to
81 * experiment with aliasing effects.
82 * These filters apply to the selected "recording" source.
83 * I (pfw) don't know the encoding of these 5 bits. The values shown
84 * come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
86 * I cleared bit 5 of these values, since that bit controls the master
87 * mute flag. (Olav Wölfelschneider)
90 #if !defined NO_AUTO_FILTER_SET
92 if (pcm_speed >= 2 * 17897)
94 else if (pcm_speed >= 2 * 15909)
96 else if (pcm_speed >= 2 * 11931)
98 else if (pcm_speed >= 2 * 8948)
100 else if (pcm_speed >= 2 * 5965)
102 else if (pcm_speed >= 2 * 2982)
107 spin_lock_irqsave(&pas_lock, flags);
109 pas_write(tmp & ~(0x40 | 0x80), 0x0B8A);
110 pas_write(0x00 | 0x30 | 0x04, 0x138B);
111 pas_write(foo & 0xff, 0x1388);
112 pas_write((foo >> 8) & 0xff, 0x1388);
113 pas_write(tmp, 0x0B8A);
115 spin_unlock_irqrestore(&pas_lock, flags);
120 static int pcm_set_channels(int arg)
123 if ((arg != 1) && (arg != 2))
126 if (arg != pcm_channels)
128 pas_write(pas_read(0xF8A) ^ 0x20, 0xF8A);
131 pcm_set_speed(pcm_speed); /* The speed must be reinitialized */
136 static int pcm_set_bits(int arg)
141 if ((arg & pcm_bitsok) != arg)
146 pas_write(pas_read(0x8389) ^ 0x04, 0x8389);
153 static int pas_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
157 DEB(printk("pas2_pcm.c: static int pas_audio_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
161 case SOUND_PCM_WRITE_RATE:
162 if (get_user(val, (int *)arg))
164 ret = pcm_set_speed(val);
167 case SOUND_PCM_READ_RATE:
171 case SNDCTL_DSP_STEREO:
172 if (get_user(val, (int *)arg))
174 ret = pcm_set_channels(val + 1) - 1;
177 case SOUND_PCM_WRITE_CHANNELS:
178 if (get_user(val, (int *)arg))
180 ret = pcm_set_channels(val);
183 case SOUND_PCM_READ_CHANNELS:
187 case SNDCTL_DSP_SETFMT:
188 if (get_user(val, (int *)arg))
190 ret = pcm_set_bits(val);
193 case SOUND_PCM_READ_BITS:
200 return put_user(ret, (int *)arg);
203 static void pas_audio_reset(int dev)
205 DEB(printk("pas2_pcm.c: static void pas_audio_reset(void)\n"));
207 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A); /* Disable PCM */
210 static int pas_audio_open(int dev, int mode)
215 DEB(printk("pas2_pcm.c: static int pas_audio_open(int mode = %X)\n", mode));
217 spin_lock_irqsave(&pas_lock, flags);
220 spin_unlock_irqrestore(&pas_lock, flags);
224 spin_unlock_irqrestore(&pas_lock, 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"));
242 spin_lock_irqsave(&pas_lock, flags);
244 pas_audio_reset(dev);
245 pas_remove_intr(PAS_PCM_INTRBITS);
249 spin_unlock_irqrestore(&pas_lock, flags);
252 static void pas_audio_output_block(int dev, unsigned long buf, int count,
255 unsigned long flags, cnt;
257 DEB(printk("pas2_pcm.c: static void pas_audio_output_block(char *buf = %P, int count = %X)\n", buf, count));
260 if (audio_devs[dev]->dmap_out->dma > 3)
263 if (audio_devs[dev]->flags & DMA_AUTOMODE &&
268 spin_lock_irqsave(&pas_lock, flags);
270 pas_write(pas_read(0xF8A) & ~0x40,
273 /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
275 if (audio_devs[dev]->dmap_out->dma > 3)
278 if (count != pcm_count)
280 pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
281 pas_write(0x40 | 0x30 | 0x04, 0x138B);
282 pas_write(count & 0xff, 0x1389);
283 pas_write((count >> 8) & 0xff, 0x1389);
284 pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
288 pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
290 pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
295 spin_unlock_irqrestore(&pas_lock, flags);
298 static void pas_audio_start_input(int dev, unsigned long buf, int count,
304 DEB(printk("pas2_pcm.c: static void pas_audio_start_input(char *buf = %P, int count = %X)\n", buf, count));
307 if (audio_devs[dev]->dmap_out->dma > 3)
310 if (audio_devs[pas_audiodev]->flags & DMA_AUTOMODE &&
315 spin_lock_irqsave(&pas_lock, flags);
317 /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
319 if (audio_devs[dev]->dmap_out->dma > 3)
322 if (count != pcm_count)
324 pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
325 pas_write(0x40 | 0x30 | 0x04, 0x138B);
326 pas_write(count & 0xff, 0x1389);
327 pas_write((count >> 8) & 0xff, 0x1389);
328 pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
332 pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
334 pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
339 spin_unlock_irqrestore(&pas_lock, flags);
343 static void pas_audio_trigger(int dev, int state)
347 spin_lock_irqsave(&pas_lock, flags);
350 if (state & PCM_ENABLE_OUTPUT)
351 pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
352 else if (state & PCM_ENABLE_INPUT)
353 pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
355 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
357 spin_unlock_irqrestore(&pas_lock, flags);
361 static int pas_audio_prepare_for_input(int dev, int bsize, int bcount)
363 pas_audio_reset(dev);
367 static int pas_audio_prepare_for_output(int dev, int bsize, int bcount)
369 pas_audio_reset(dev);
373 static struct audio_driver pas_audio_driver =
375 .owner = THIS_MODULE,
376 .open = pas_audio_open,
377 .close = pas_audio_close,
378 .output_block = pas_audio_output_block,
379 .start_input = pas_audio_start_input,
380 .ioctl = pas_audio_ioctl,
381 .prepare_for_input = pas_audio_prepare_for_input,
382 .prepare_for_output = pas_audio_prepare_for_output,
383 .halt_io = pas_audio_reset,
384 .trigger = pas_audio_trigger
387 void __init pas_pcm_init(struct address_info *hw_config)
389 DEB(printk("pas2_pcm.c: long pas_pcm_init()\n"));
392 if (pas_read(0xEF8B) & 0x08)
395 pcm_set_speed(DSP_DEFAULT_SPEED);
397 if ((pas_audiodev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
398 "Pro Audio Spectrum",
400 sizeof(struct audio_driver),
402 AFMT_U8 | AFMT_S16_LE,
405 hw_config->dma)) < 0)
406 printk(KERN_WARNING "PAS16: Too many PCM devices available\n");
409 void pas_pcm_interrupt(unsigned char status, int cause)
414 * Halt the PCM first. Otherwise we don't have time to start a new
415 * block before the PCM chip proceeds to the next sample
418 if (!(audio_devs[pas_audiodev]->flags & DMA_AUTOMODE))
419 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
424 DMAbuf_outputintr(pas_audiodev, 1);
428 DMAbuf_inputintr(pas_audiodev);
432 printk(KERN_WARNING "PAS: Unexpected PCM interrupt\n");