Import 2.3.49pre2
[davej-history.git] / drivers / sound / pas2_pcm.c
blob36fc7f72b295975acbbfcf0caa42639ac162af15
1 /*
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
9 * for more info.
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 "sound_config.h"
19 #ifndef DEB
20 #define DEB(WHAT)
21 #endif
23 #define PAS_PCM_INTRBITS (0x08)
25 * Sample buffer timer interrupt enable
28 #define PCM_NON 0
29 #define PCM_DAC 1
30 #define PCM_ADC 2
32 static unsigned long pcm_speed = 0; /* sampling rate */
33 static unsigned char pcm_channels = 1; /* channels (1 or 2) */
34 static unsigned char pcm_bits = 8; /* bits/sample (8 or 16) */
35 static unsigned char pcm_filter = 0; /* filter FLAG */
36 static unsigned char pcm_mode = PCM_NON;
37 static unsigned long pcm_count = 0;
38 static unsigned short pcm_bitsok = 8; /* mask of OK bits */
39 static int pcm_busy = 0;
40 int pas_audiodev = -1;
41 static int open_mode = 0;
43 static int pcm_set_speed(int arg)
45 int foo, tmp;
46 unsigned long flags;
48 if (arg == 0)
49 return pcm_speed;
51 if (arg > 44100)
52 arg = 44100;
53 if (arg < 5000)
54 arg = 5000;
56 if (pcm_channels & 2)
58 foo = (596590 + (arg / 2)) / arg;
59 arg = (596590 + (foo / 2)) / foo;
61 else
63 foo = (1193180 + (arg / 2)) / arg;
64 arg = (1193180 + (foo / 2)) / foo;
67 pcm_speed = arg;
69 tmp = pas_read(0x0B8A);
72 * Set anti-aliasing filters according to sample rate. You really *NEED*
73 * to enable this feature for all normal recording unless you want to
74 * experiment with aliasing effects.
75 * These filters apply to the selected "recording" source.
76 * I (pfw) don't know the encoding of these 5 bits. The values shown
77 * come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
79 * I cleared bit 5 of these values, since that bit controls the master
80 * mute flag. (Olav Wölfelschneider)
83 #if !defined NO_AUTO_FILTER_SET
84 tmp &= 0xe0;
85 if (pcm_speed >= 2 * 17897)
86 tmp |= 0x01;
87 else if (pcm_speed >= 2 * 15909)
88 tmp |= 0x02;
89 else if (pcm_speed >= 2 * 11931)
90 tmp |= 0x09;
91 else if (pcm_speed >= 2 * 8948)
92 tmp |= 0x11;
93 else if (pcm_speed >= 2 * 5965)
94 tmp |= 0x19;
95 else if (pcm_speed >= 2 * 2982)
96 tmp |= 0x04;
97 pcm_filter = tmp;
98 #endif
100 save_flags(flags);
101 cli();
103 pas_write(tmp & ~(0x40 | 0x80), 0x0B8A);
104 pas_write(0x00 | 0x30 | 0x04, 0x138B);
105 pas_write(foo & 0xff, 0x1388);
106 pas_write((foo >> 8) & 0xff, 0x1388);
107 pas_write(tmp, 0x0B8A);
109 restore_flags(flags);
111 return pcm_speed;
114 static int pcm_set_channels(int arg)
117 if ((arg != 1) && (arg != 2))
118 return pcm_channels;
120 if (arg != pcm_channels)
122 pas_write(pas_read(0xF8A) ^ 0x20, 0xF8A);
124 pcm_channels = arg;
125 pcm_set_speed(pcm_speed); /* The speed must be reinitialized */
127 return pcm_channels;
130 static int pcm_set_bits(int arg)
132 if (arg == 0)
133 return pcm_bits;
135 if ((arg & pcm_bitsok) != arg)
136 return pcm_bits;
138 if (arg != pcm_bits)
140 pas_write(pas_read(0x8389) ^ 0x04, 0x8389);
142 pcm_bits = arg;
144 return pcm_bits;
147 static int pas_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
149 int val, ret;
151 DEB(printk("pas2_pcm.c: static int pas_audio_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
153 switch (cmd)
155 case SOUND_PCM_WRITE_RATE:
156 if (get_user(val, (int *)arg))
157 return -EFAULT;
158 ret = pcm_set_speed(val);
159 break;
161 case SOUND_PCM_READ_RATE:
162 ret = pcm_speed;
163 break;
165 case SNDCTL_DSP_STEREO:
166 if (get_user(val, (int *)arg))
167 return -EFAULT;
168 ret = pcm_set_channels(val + 1) - 1;
169 break;
171 case SOUND_PCM_WRITE_CHANNELS:
172 if (get_user(val, (int *)arg))
173 return -EFAULT;
174 ret = pcm_set_channels(val);
175 break;
177 case SOUND_PCM_READ_CHANNELS:
178 ret = pcm_channels;
179 break;
181 case SNDCTL_DSP_SETFMT:
182 if (get_user(val, (int *)arg))
183 return -EFAULT;
184 ret = pcm_set_bits(val);
185 break;
187 case SOUND_PCM_READ_BITS:
188 ret = pcm_bits;
189 break;
191 default:
192 return -EINVAL;
194 return put_user(ret, (int *)arg);
197 static void pas_audio_reset(int dev)
199 DEB(printk("pas2_pcm.c: static void pas_audio_reset(void)\n"));
201 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A); /* Disable PCM */
204 static int pas_audio_open(int dev, int mode)
206 int err;
207 unsigned long flags;
209 DEB(printk("pas2_pcm.c: static int pas_audio_open(int mode = %X)\n", mode));
211 save_flags(flags);
212 cli();
213 if (pcm_busy)
215 restore_flags(flags);
216 return -EBUSY;
218 pcm_busy = 1;
219 restore_flags(flags);
221 if ((err = pas_set_intr(PAS_PCM_INTRBITS)) < 0)
222 return err;
225 pcm_count = 0;
226 open_mode = mode;
228 return 0;
231 static void pas_audio_close(int dev)
233 unsigned long flags;
235 DEB(printk("pas2_pcm.c: static void pas_audio_close(void)\n"));
237 save_flags(flags);
238 cli();
240 pas_audio_reset(dev);
241 pas_remove_intr(PAS_PCM_INTRBITS);
242 pcm_mode = PCM_NON;
244 pcm_busy = 0;
245 restore_flags(flags);
248 static void pas_audio_output_block(int dev, unsigned long buf, int count,
249 int intrflag)
251 unsigned long flags, cnt;
253 DEB(printk("pas2_pcm.c: static void pas_audio_output_block(char *buf = %P, int count = %X)\n", buf, count));
255 cnt = count;
256 if (audio_devs[dev]->dmap_out->dma > 3)
257 cnt >>= 1;
259 if (audio_devs[dev]->flags & DMA_AUTOMODE &&
260 intrflag &&
261 cnt == pcm_count)
262 return;
264 save_flags(flags);
265 cli();
267 pas_write(pas_read(0xF8A) & ~0x40,
268 0xF8A);
270 /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
272 if (audio_devs[dev]->dmap_out->dma > 3)
273 count >>= 1;
275 if (count != pcm_count)
277 pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
278 pas_write(0x40 | 0x30 | 0x04, 0x138B);
279 pas_write(count & 0xff, 0x1389);
280 pas_write((count >> 8) & 0xff, 0x1389);
281 pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
283 pcm_count = count;
285 pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
286 #ifdef NO_TRIGGER
287 pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
288 #endif
290 pcm_mode = PCM_DAC;
292 restore_flags(flags);
295 static void pas_audio_start_input(int dev, unsigned long buf, int count,
296 int intrflag)
298 unsigned long flags;
299 int cnt;
301 DEB(printk("pas2_pcm.c: static void pas_audio_start_input(char *buf = %P, int count = %X)\n", buf, count));
303 cnt = count;
304 if (audio_devs[dev]->dmap_out->dma > 3)
305 cnt >>= 1;
307 if (audio_devs[pas_audiodev]->flags & DMA_AUTOMODE &&
308 intrflag &&
309 cnt == pcm_count)
310 return;
312 save_flags(flags);
313 cli();
315 /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
317 if (audio_devs[dev]->dmap_out->dma > 3)
318 count >>= 1;
320 if (count != pcm_count)
322 pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
323 pas_write(0x40 | 0x30 | 0x04, 0x138B);
324 pas_write(count & 0xff, 0x1389);
325 pas_write((count >> 8) & 0xff, 0x1389);
326 pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
328 pcm_count = count;
330 pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
331 #ifdef NO_TRIGGER
332 pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
333 #endif
335 pcm_mode = PCM_ADC;
337 restore_flags(flags);
340 #ifndef NO_TRIGGER
341 static void pas_audio_trigger(int dev, int state)
343 unsigned long flags;
345 save_flags(flags);
346 cli();
347 state &= open_mode;
349 if (state & PCM_ENABLE_OUTPUT)
350 pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
351 else if (state & PCM_ENABLE_INPUT)
352 pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
353 else
354 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
356 restore_flags(flags);
358 #endif
360 static int pas_audio_prepare_for_input(int dev, int bsize, int bcount)
362 pas_audio_reset(dev);
363 return 0;
366 static int pas_audio_prepare_for_output(int dev, int bsize, int bcount)
368 pas_audio_reset(dev);
369 return 0;
372 static struct audio_driver pas_audio_driver =
374 pas_audio_open,
375 pas_audio_close,
376 pas_audio_output_block,
377 pas_audio_start_input,
378 pas_audio_ioctl,
379 pas_audio_prepare_for_input,
380 pas_audio_prepare_for_output,
381 pas_audio_reset,
382 NULL,
383 NULL,
384 NULL,
385 NULL,
386 pas_audio_trigger
389 void pas_pcm_init(struct address_info *hw_config)
391 DEB(printk("pas2_pcm.c: long pas_pcm_init()\n"));
393 pcm_bitsok = 8;
394 if (pas_read(0xEF8B) & 0x08)
395 pcm_bitsok |= 16;
397 pcm_set_speed(DSP_DEFAULT_SPEED);
399 if ((pas_audiodev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
400 "Pro Audio Spectrum",
401 &pas_audio_driver,
402 sizeof(struct audio_driver),
403 DMA_AUTOMODE,
404 AFMT_U8 | AFMT_S16_LE,
405 NULL,
406 hw_config->dma,
407 hw_config->dma)) < 0)
408 printk(KERN_WARNING "PAS16: Too many PCM devices available\n");
411 void pas_pcm_interrupt(unsigned char status, int cause)
413 if (cause == 1)
416 * Halt the PCM first. Otherwise we don't have time to start a new
417 * block before the PCM chip proceeds to the next sample
420 if (!(audio_devs[pas_audiodev]->flags & DMA_AUTOMODE))
421 pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
423 switch (pcm_mode)
425 case PCM_DAC:
426 DMAbuf_outputintr(pas_audiodev, 1);
427 break;
429 case PCM_ADC:
430 DMAbuf_inputintr(pas_audiodev);
431 break;
433 default:
434 printk(KERN_WARNING "PAS: Unexpected PCM interrupt\n");