* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-0.99 / drivers / sound / pas2_pcm.c
blobb396f61532d81e909809994d66eca2d9c1790080
1 #define _PAS2_PCM_C_
2 /*
3 * sound/pas2_pcm.c
4 *
5 * The low level driver for the Pro Audio Spectrum ADC/DAC.
6 *
7 * Copyright by Hannu Savolainen 1993
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met: 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 2.
13 * Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
31 #include "sound_config.h"
33 #ifdef CONFIGURE_SOUNDCARD
35 #include "pas.h"
37 #if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_AUDIO)
39 #define TRACE(WHAT) /* (WHAT) */
41 #define PAS_PCM_INTRBITS (0x08)
42 /* Sample buffer timer interrupt enable */
44 #define PCM_NON 0
45 #define PCM_DAC 1
46 #define PCM_ADC 2
48 static unsigned long pcm_speed = 0; /* sampling rate */
49 static unsigned char pcm_channels = 1; /* channels/sample (1 or 2) */
50 static unsigned char pcm_bits = 8; /* bits/sample (8 or 16) */
51 static unsigned char pcm_filter = 0; /* filter FLAG */
52 static unsigned char pcm_mode = PCM_NON;
53 static unsigned long pcm_count = 0;
54 static unsigned short pcm_bitsok = 8; /* mask of OK bits */
55 static int my_devnum = 0;
57 int
58 pcm_set_speed (int arg)
60 int foo, tmp;
61 unsigned long flags;
63 if (arg > 44100)
64 arg = 44100;
65 if (arg < 5000)
66 arg = 5000;
68 foo = 1193180 / arg;
69 arg = 1193180 / foo;
71 if (pcm_channels & 2)
72 foo = foo >> 1;
74 pcm_speed = arg;
76 tmp = pas_read (FILTER_FREQUENCY);
78 DISABLE_INTR (flags);
80 pas_write (tmp & ~(F_F_PCM_RATE_COUNTER | F_F_PCM_BUFFER_COUNTER), FILTER_FREQUENCY);
81 pas_write (S_C_C_SAMPLE_RATE | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
82 pas_write (foo & 0xff, SAMPLE_RATE_TIMER);
83 pas_write ((foo >> 8) & 0xff, SAMPLE_RATE_TIMER);
84 pas_write (tmp, FILTER_FREQUENCY);
86 RESTORE_INTR (flags);
88 return pcm_speed;
91 int
92 pcm_set_channels (int arg)
95 if ((arg != 1) && (arg != 2))
96 return pcm_channels;
98 if (arg != pcm_channels)
100 pas_write (pas_read (PCM_CONTROL) ^ P_C_PCM_MONO, PCM_CONTROL);
102 pcm_channels = arg;
103 pcm_set_speed (pcm_speed);/* The speed must be reinitialized */
106 return pcm_channels;
110 pcm_set_bits (int arg)
112 if ((arg & pcm_bitsok) != arg)
113 return pcm_bits;
115 if (arg != pcm_bits)
117 pas_write (pas_read (SYSTEM_CONFIGURATION_2) ^ S_C_2_PCM_16_BIT, SYSTEM_CONFIGURATION_2);
119 pcm_bits = arg;
122 return pcm_bits;
125 static int
126 pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
128 TRACE (printk ("pas2_pcm.c: static int pas_pcm_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
130 switch (cmd)
132 case SOUND_PCM_WRITE_RATE:
133 if (local)
134 return pcm_set_speed (arg);
135 return IOCTL_OUT (arg, pcm_set_speed (IOCTL_IN (arg)));
136 break;
138 case SOUND_PCM_READ_RATE:
139 if (local)
140 return pcm_speed;
141 return IOCTL_OUT (arg, pcm_speed);
142 break;
144 case SNDCTL_DSP_STEREO:
145 if (local)
146 return pcm_set_channels (arg + 1) - 1;
147 return IOCTL_OUT (arg, pcm_set_channels (IOCTL_IN (arg) + 1) - 1);
148 break;
150 case SOUND_PCM_WRITE_CHANNELS:
151 if (local)
152 return pcm_set_channels (arg);
153 return IOCTL_OUT (arg, pcm_set_channels (IOCTL_IN (arg)));
154 break;
156 case SOUND_PCM_READ_CHANNELS:
157 if (local)
158 return pcm_channels;
159 return IOCTL_OUT (arg, pcm_channels);
160 break;
162 case SNDCTL_DSP_SAMPLESIZE:
163 if (local)
164 return pcm_set_bits (arg);
165 return IOCTL_OUT (arg, pcm_set_bits (IOCTL_IN (arg)));
166 break;
168 case SOUND_PCM_READ_BITS:
169 if (local)
170 return pcm_bits;
171 return IOCTL_OUT (arg, pcm_bits);
173 case SOUND_PCM_WRITE_FILTER: /* NOT YET IMPLEMENTED */
174 if (IOCTL_IN (arg) > 1)
175 return IOCTL_OUT (arg, RET_ERROR (EINVAL));
176 break;
178 pcm_filter = IOCTL_IN (arg);
179 case SOUND_PCM_READ_FILTER:
180 return IOCTL_OUT (arg, pcm_filter);
181 break;
183 default:
184 return RET_ERROR (EINVAL);
187 return RET_ERROR (EINVAL);
190 static void
191 pas_pcm_reset (int dev)
193 TRACE (printk ("pas2_pcm.c: static void pas_pcm_reset(void)\n"));
195 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE, PCM_CONTROL);
198 static int
199 pas_pcm_open (int dev, int mode)
201 int err;
203 TRACE (printk ("pas2_pcm.c: static int pas_pcm_open(int mode = %X)\n", mode));
205 if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0)
206 return err;
208 if (!DMAbuf_open_dma (dev))
210 pas_remove_intr (PAS_PCM_INTRBITS);
211 return RET_ERROR (EBUSY);
214 pcm_count = 0;
216 return 0;
219 static void
220 pas_pcm_close (int dev)
222 unsigned long flags;
224 TRACE (printk ("pas2_pcm.c: static void pas_pcm_close(void)\n"));
226 DISABLE_INTR (flags);
228 pas_pcm_reset (dev);
229 DMAbuf_close_dma (dev);
230 pas_remove_intr (PAS_PCM_INTRBITS);
231 pcm_mode = PCM_NON;
233 RESTORE_INTR (flags);
236 static void
237 pas_pcm_output_block (int dev, unsigned long buf, int count,
238 int intrflag, int restart_dma)
240 unsigned long flags, cnt;
242 TRACE (printk ("pas2_pcm.c: static void pas_pcm_output_block(char *buf = %P, int count = %X)\n", buf, count));
244 cnt = count;
245 if (sound_dsp_dmachan[dev] > 3)
246 cnt >>= 1;
248 if (sound_dma_automode[dev] &&
249 intrflag &&
250 cnt == pcm_count)
251 return; /* Auto mode on. No need to react */
253 DISABLE_INTR (flags);
255 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
256 PCM_CONTROL);
258 if (restart_dma)
259 DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
261 if (sound_dsp_dmachan[dev] > 3)
262 count >>= 1;
264 if (count != pcm_count)
266 pas_write (pas_read (FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
267 pas_write (S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
268 pas_write (count & 0xff, SAMPLE_BUFFER_COUNTER);
269 pas_write ((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
270 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
272 pcm_count = count;
274 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
275 pas_write (pas_read (PCM_CONTROL) | P_C_PCM_ENABLE | P_C_PCM_DAC_MODE, PCM_CONTROL);
277 pcm_mode = PCM_DAC;
279 RESTORE_INTR (flags);
282 static void
283 pas_pcm_start_input (int dev, unsigned long buf, int count,
284 int intrflag, int restart_dma)
286 unsigned long flags;
287 int cnt;
289 TRACE (printk ("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf, count));
291 cnt = count;
292 if (sound_dsp_dmachan[dev] > 3)
293 cnt >>= 1;
295 if (sound_dma_automode[my_devnum] &&
296 intrflag &&
297 cnt == pcm_count)
298 return; /* Auto mode on. No need to react */
300 DISABLE_INTR (flags);
302 if (restart_dma)
303 DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
305 if (sound_dsp_dmachan[dev] > 3)
306 count >>= 1;
308 if (count != pcm_count)
310 pas_write (pas_read (FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
311 pas_write (S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
312 pas_write (count & 0xff, SAMPLE_BUFFER_COUNTER);
313 pas_write ((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
314 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
316 pcm_count = count;
318 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
319 pas_write ((pas_read (PCM_CONTROL) | P_C_PCM_ENABLE) & ~P_C_PCM_DAC_MODE, PCM_CONTROL);
321 pcm_mode = PCM_ADC;
323 RESTORE_INTR (flags);
326 static int
327 pas_pcm_prepare_for_input (int dev, int bsize, int bcount)
329 return 0;
331 static int
332 pas_pcm_prepare_for_output (int dev, int bsize, int bcount)
334 return 0;
337 static struct audio_operations pas_pcm_operations =
339 "Pro Audio Spectrum",
340 pas_pcm_open, /* */
341 pas_pcm_close, /* */
342 pas_pcm_output_block, /* */
343 pas_pcm_start_input, /* */
344 pas_pcm_ioctl, /* */
345 pas_pcm_prepare_for_input, /* */
346 pas_pcm_prepare_for_output, /* */
347 pas_pcm_reset, /* */
348 pas_pcm_reset, /* halt_xfer */
349 NULL, /* has_output_drained */
350 NULL /* copy_from_user */
353 long
354 pas_pcm_init (long mem_start, struct address_info *hw_config)
356 TRACE (printk ("pas2_pcm.c: long pas_pcm_init(long mem_start = %X)\n", mem_start));
358 pcm_bitsok = 8;
359 if (pas_read (OPERATION_MODE_1) & O_M_1_PCM_TYPE)
360 pcm_bitsok |= 16;
362 pcm_set_speed (DSP_DEFAULT_SPEED);
364 if (num_dspdevs < MAX_DSP_DEV)
366 dsp_devs[my_devnum = num_dspdevs++] = &pas_pcm_operations;
367 sound_dsp_dmachan[my_devnum] = hw_config->dma;
368 #ifndef PAS_NO_AUTODMA
369 if (hw_config->dma > 3)
371 sound_buffcounts[my_devnum] = 1;
372 sound_buffsizes[my_devnum] = 2 * 65536;
373 sound_dma_automode[my_devnum] = 1;
375 else
377 sound_buffcounts[my_devnum] = 1;
378 sound_buffsizes[my_devnum] = DSP_BUFFSIZE;
379 sound_dma_automode[my_devnum] = 1;
381 #else
382 sound_buffcounts[my_devnum] = 2;
383 sound_buffsizes[my_devnum] = DSP_BUFFSIZE;
384 sound_dma_automode[my_devnum] = 0;
385 #endif
387 else
388 printk ("PAS2: Too many PCM devices available\n");
390 return mem_start;
393 void
394 pas_pcm_interrupt (unsigned char status, int cause)
396 if (cause == 1) /* PCM buffer done */
399 * Halt the PCM first. Otherwise we don't have time to start a new
400 * block before the PCM chip proceeds to the next sample
403 if (!sound_dma_automode[my_devnum])
405 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
406 PCM_CONTROL);
409 switch (pcm_mode)
412 case PCM_DAC:
413 DMAbuf_outputintr (my_devnum, 1);
414 break;
416 case PCM_ADC:
417 DMAbuf_inputintr (my_devnum);
418 break;
420 default:
421 printk ("PAS: Unexpected PCM interrupt\n");
426 #endif
428 #endif