This source file includes following definitions.
- pcm_set_speed
- pcm_set_channels
- pcm_set_bits
- pas_pcm_ioctl
- pas_pcm_reset
- pas_pcm_open
- pas_pcm_close
- pas_pcm_output_block
- pas_pcm_start_input
- pas_pcm_prepare_for_input
- pas_pcm_prepare_for_output
- pas_pcm_init
- pas_pcm_interrupt
1 #define _PAS2_PCM_C_
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 #include "sound_config.h"
32
33 #ifdef CONFIGURE_SOUNDCARD
34
35 #include "pas.h"
36
37 #if !defined(EXCLUDE_PAS) && !defined(EXCLUDE_AUDIO)
38
39 #define TRACE(WHAT)
40
41 #define PAS_PCM_INTRBITS (0x08)
42
43
44 #define PCM_NON 0
45 #define PCM_DAC 1
46 #define PCM_ADC 2
47
48 static unsigned long pcm_speed = 0;
49 static unsigned char pcm_channels = 1;
50 static unsigned char pcm_bits = 8;
51 static unsigned char pcm_filter = 0;
52 static unsigned char pcm_mode = PCM_NON;
53 static unsigned long pcm_count = 0;
54 static unsigned short pcm_bitsok = 8;
55 static int my_devnum = 0;
56
57 int
58 pcm_set_speed (int arg)
59 {
60 int foo, tmp;
61 unsigned long flags;
62
63 if (arg > 44100)
64 arg = 44100;
65 if (arg < 5000)
66 arg = 5000;
67
68 foo = 1193180 / arg;
69 arg = 1193180 / foo;
70
71 if (pcm_channels & 2)
72 foo = foo >> 1;
73
74 pcm_speed = arg;
75
76 tmp = pas_read (FILTER_FREQUENCY);
77
78 DISABLE_INTR (flags);
79
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);
85
86 RESTORE_INTR (flags);
87
88 return pcm_speed;
89 }
90
91 int
92 pcm_set_channels (int arg)
93 {
94
95 if ((arg != 1) && (arg != 2))
96 return pcm_channels;
97
98 if (arg != pcm_channels)
99 {
100 pas_write (pas_read (PCM_CONTROL) ^ P_C_PCM_MONO, PCM_CONTROL);
101
102 pcm_channels = arg;
103 pcm_set_speed (pcm_speed);
104 }
105
106 return pcm_channels;
107 }
108
109 int
110 pcm_set_bits (int arg)
111 {
112 if ((arg & pcm_bitsok) != arg)
113 return pcm_bits;
114
115 if (arg != pcm_bits)
116 {
117 pas_write (pas_read (SYSTEM_CONFIGURATION_2) ^ S_C_2_PCM_16_BIT, SYSTEM_CONFIGURATION_2);
118
119 pcm_bits = arg;
120 }
121
122 return pcm_bits;
123 }
124
125 static int
126 pas_pcm_ioctl (int dev, unsigned int cmd, unsigned int arg, int local)
127 {
128 TRACE (printk ("pas2_pcm.c: static int pas_pcm_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
129
130 switch (cmd)
131 {
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;
137
138 case SOUND_PCM_READ_RATE:
139 if (local)
140 return pcm_speed;
141 return IOCTL_OUT (arg, pcm_speed);
142 break;
143
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;
149
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;
155
156 case SOUND_PCM_READ_CHANNELS:
157 if (local)
158 return pcm_channels;
159 return IOCTL_OUT (arg, pcm_channels);
160 break;
161
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;
167
168 case SOUND_PCM_READ_BITS:
169 if (local)
170 return pcm_bits;
171 return IOCTL_OUT (arg, pcm_bits);
172
173 case SOUND_PCM_WRITE_FILTER:
174 if (IOCTL_IN (arg) > 1)
175 return IOCTL_OUT (arg, RET_ERROR (EINVAL));
176 break;
177
178 pcm_filter = IOCTL_IN (arg);
179 case SOUND_PCM_READ_FILTER:
180 return IOCTL_OUT (arg, pcm_filter);
181 break;
182
183 default:
184 return RET_ERROR (EINVAL);
185 }
186
187 return RET_ERROR (EINVAL);
188 }
189
190 static void
191 pas_pcm_reset (int dev)
192 {
193 TRACE (printk ("pas2_pcm.c: static void pas_pcm_reset(void)\n"));
194
195 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE, PCM_CONTROL);
196 }
197
198 static int
199 pas_pcm_open (int dev, int mode)
200 {
201 int err;
202
203 TRACE (printk ("pas2_pcm.c: static int pas_pcm_open(int mode = %X)\n", mode));
204
205 if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0)
206 return err;
207
208 if (!DMAbuf_open_dma (dev))
209 {
210 pas_remove_intr (PAS_PCM_INTRBITS);
211 return RET_ERROR (EBUSY);
212 }
213
214 pcm_count = 0;
215
216 return 0;
217 }
218
219 static void
220 pas_pcm_close (int dev)
221 {
222 unsigned long flags;
223
224 TRACE (printk ("pas2_pcm.c: static void pas_pcm_close(void)\n"));
225
226 DISABLE_INTR (flags);
227
228 pas_pcm_reset (dev);
229 DMAbuf_close_dma (dev);
230 pas_remove_intr (PAS_PCM_INTRBITS);
231 pcm_mode = PCM_NON;
232
233 RESTORE_INTR (flags);
234 }
235
236 static void
237 pas_pcm_output_block (int dev, unsigned long buf, int count,
238 int intrflag, int restart_dma)
239 {
240 unsigned long flags, cnt;
241
242 TRACE (printk ("pas2_pcm.c: static void pas_pcm_output_block(char *buf = %P, int count = %X)\n", buf, count));
243
244 cnt = count;
245 if (sound_dsp_dmachan[dev] > 3)
246 cnt >>= 1;
247
248 if (sound_dma_automode[dev] &&
249 intrflag &&
250 cnt == pcm_count)
251 return;
252
253 DISABLE_INTR (flags);
254
255 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
256 PCM_CONTROL);
257
258 if (restart_dma)
259 DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
260
261 if (sound_dsp_dmachan[dev] > 3)
262 count >>= 1;
263
264 if (count != pcm_count)
265 {
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);
271
272 pcm_count = count;
273 }
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);
276
277 pcm_mode = PCM_DAC;
278
279 RESTORE_INTR (flags);
280 }
281
282 static void
283 pas_pcm_start_input (int dev, unsigned long buf, int count,
284 int intrflag, int restart_dma)
285 {
286 unsigned long flags;
287 int cnt;
288
289 TRACE (printk ("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf, count));
290
291 cnt = count;
292 if (sound_dsp_dmachan[dev] > 3)
293 cnt >>= 1;
294
295 if (sound_dma_automode[my_devnum] &&
296 intrflag &&
297 cnt == pcm_count)
298 return;
299
300 DISABLE_INTR (flags);
301
302 if (restart_dma)
303 DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
304
305 if (sound_dsp_dmachan[dev] > 3)
306 count >>= 1;
307
308 if (count != pcm_count)
309 {
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);
315
316 pcm_count = count;
317 }
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);
320
321 pcm_mode = PCM_ADC;
322
323 RESTORE_INTR (flags);
324 }
325
326 static int
327 pas_pcm_prepare_for_input (int dev, int bsize, int bcount)
328 {
329 return 0;
330 }
331 static int
332 pas_pcm_prepare_for_output (int dev, int bsize, int bcount)
333 {
334 return 0;
335 }
336
337 static struct audio_operations pas_pcm_operations =
338 {
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,
349 NULL,
350 NULL
351 };
352
353 long
354 pas_pcm_init (long mem_start, struct address_info *hw_config)
355 {
356 TRACE (printk ("pas2_pcm.c: long pas_pcm_init(long mem_start = %X)\n", mem_start));
357
358 pcm_bitsok = 8;
359 if (pas_read (OPERATION_MODE_1) & O_M_1_PCM_TYPE)
360 pcm_bitsok |= 16;
361
362 pcm_set_speed (DSP_DEFAULT_SPEED);
363
364 if (num_dspdevs < MAX_DSP_DEV)
365 {
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)
370 {
371 sound_buffcounts[my_devnum] = 1;
372 sound_buffsizes[my_devnum] = 2 * 65536;
373 sound_dma_automode[my_devnum] = 1;
374 }
375 else
376 {
377 sound_buffcounts[my_devnum] = 1;
378 sound_buffsizes[my_devnum] = DSP_BUFFSIZE;
379 sound_dma_automode[my_devnum] = 1;
380 }
381 #else
382 sound_buffcounts[my_devnum] = 2;
383 sound_buffsizes[my_devnum] = DSP_BUFFSIZE;
384 sound_dma_automode[my_devnum] = 0;
385 #endif
386 }
387 else
388 printk ("PAS2: Too many PCM devices available\n");
389
390 return mem_start;
391 }
392
393 void
394 pas_pcm_interrupt (unsigned char status, int cause)
395 {
396 if (cause == 1)
397 {
398
399
400
401
402
403 if (!sound_dma_automode[my_devnum])
404 {
405 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
406 PCM_CONTROL);
407 }
408
409 switch (pcm_mode)
410 {
411
412 case PCM_DAC:
413 DMAbuf_outputintr (my_devnum, 1);
414 break;
415
416 case PCM_ADC:
417 DMAbuf_inputintr (my_devnum);
418 break;
419
420 default:
421 printk ("PAS: Unexpected PCM interrupt\n");
422 }
423 }
424 }
425
426 #endif
427
428 #endif