5 * The low level driver for the Pro Audio Spectrum ADC/DAC.
7 * Copyright by Hannu Savolainen 1993
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
31 #include "sound_config.h"
33 #ifdef CONFIGURE_SOUNDCARD
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 */
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;
58 pcm_set_speed (int arg
)
76 tmp
= pas_read (FILTER_FREQUENCY
);
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
);
92 pcm_set_channels (int arg
)
95 if ((arg
!= 1) && (arg
!= 2))
98 if (arg
!= pcm_channels
)
100 pas_write (pas_read (PCM_CONTROL
) ^ P_C_PCM_MONO
, PCM_CONTROL
);
103 pcm_set_speed (pcm_speed
);/* The speed must be reinitialized */
110 pcm_set_bits (int arg
)
112 if ((arg
& pcm_bitsok
) != arg
)
117 pas_write (pas_read (SYSTEM_CONFIGURATION_2
) ^ S_C_2_PCM_16_BIT
, SYSTEM_CONFIGURATION_2
);
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
));
132 case SOUND_PCM_WRITE_RATE
:
134 return pcm_set_speed (arg
);
135 return IOCTL_OUT (arg
, pcm_set_speed (IOCTL_IN (arg
)));
138 case SOUND_PCM_READ_RATE
:
141 return IOCTL_OUT (arg
, pcm_speed
);
144 case SNDCTL_DSP_STEREO
:
146 return pcm_set_channels (arg
+ 1) - 1;
147 return IOCTL_OUT (arg
, pcm_set_channels (IOCTL_IN (arg
) + 1) - 1);
150 case SOUND_PCM_WRITE_CHANNELS
:
152 return pcm_set_channels (arg
);
153 return IOCTL_OUT (arg
, pcm_set_channels (IOCTL_IN (arg
)));
156 case SOUND_PCM_READ_CHANNELS
:
159 return IOCTL_OUT (arg
, pcm_channels
);
162 case SNDCTL_DSP_SAMPLESIZE
:
164 return pcm_set_bits (arg
);
165 return IOCTL_OUT (arg
, pcm_set_bits (IOCTL_IN (arg
)));
168 case SOUND_PCM_READ_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
));
178 pcm_filter
= IOCTL_IN (arg
);
179 case SOUND_PCM_READ_FILTER
:
180 return IOCTL_OUT (arg
, pcm_filter
);
184 return RET_ERROR (EINVAL
);
187 return RET_ERROR (EINVAL
);
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
);
199 pas_pcm_open (int dev
, int mode
)
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)
208 if (!DMAbuf_open_dma (dev
))
210 pas_remove_intr (PAS_PCM_INTRBITS
);
211 return RET_ERROR (EBUSY
);
220 pas_pcm_close (int dev
)
224 TRACE (printk ("pas2_pcm.c: static void pas_pcm_close(void)\n"));
226 DISABLE_INTR (flags
);
229 DMAbuf_close_dma (dev
);
230 pas_remove_intr (PAS_PCM_INTRBITS
);
233 RESTORE_INTR (flags
);
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
));
245 if (sound_dsp_dmachan
[dev
] > 3)
248 if (sound_dma_automode
[dev
] &&
251 return; /* Auto mode on. No need to react */
253 DISABLE_INTR (flags
);
255 pas_write (pas_read (PCM_CONTROL
) & ~P_C_PCM_ENABLE
,
259 DMAbuf_start_dma (dev
, buf
, count
, DMA_MODE_WRITE
);
261 if (sound_dsp_dmachan
[dev
] > 3)
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
);
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
);
279 RESTORE_INTR (flags
);
283 pas_pcm_start_input (int dev
, unsigned long buf
, int count
,
284 int intrflag
, int restart_dma
)
289 TRACE (printk ("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf
, count
));
292 if (sound_dsp_dmachan
[dev
] > 3)
295 if (sound_dma_automode
[my_devnum
] &&
298 return; /* Auto mode on. No need to react */
300 DISABLE_INTR (flags
);
303 DMAbuf_start_dma (dev
, buf
, count
, DMA_MODE_READ
);
305 if (sound_dsp_dmachan
[dev
] > 3)
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
);
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
);
323 RESTORE_INTR (flags
);
327 pas_pcm_prepare_for_input (int dev
, int bsize
, int bcount
)
332 pas_pcm_prepare_for_output (int dev
, int bsize
, int bcount
)
337 static struct audio_operations pas_pcm_operations
=
339 "Pro Audio Spectrum",
342 pas_pcm_output_block
, /* */
343 pas_pcm_start_input
, /* */
345 pas_pcm_prepare_for_input
, /* */
346 pas_pcm_prepare_for_output
, /* */
348 pas_pcm_reset
, /* halt_xfer */
349 NULL
, /* has_output_drained */
350 NULL
/* copy_from_user */
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
));
359 if (pas_read (OPERATION_MODE_1
) & O_M_1_PCM_TYPE
)
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;
377 sound_buffcounts
[my_devnum
] = 1;
378 sound_buffsizes
[my_devnum
] = DSP_BUFFSIZE
;
379 sound_dma_automode
[my_devnum
] = 1;
382 sound_buffcounts
[my_devnum
] = 2;
383 sound_buffsizes
[my_devnum
] = DSP_BUFFSIZE
;
384 sound_dma_automode
[my_devnum
] = 0;
388 printk ("PAS2: Too many PCM devices available\n");
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
,
413 DMAbuf_outputintr (my_devnum
, 1);
417 DMAbuf_inputintr (my_devnum
);
421 printk ("PAS: Unexpected PCM interrupt\n");