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
42 #define PAS_PCM_INTRBITS (0x08)
43
44
45
46
47 #define PCM_NON 0
48 #define PCM_DAC 1
49 #define PCM_ADC 2
50
51 static unsigned long pcm_speed = 0;
52 static unsigned char pcm_channels = 1;
53 static unsigned char pcm_bits = 8;
54 static unsigned char pcm_filter = 0;
55 static unsigned char pcm_mode = PCM_NON;
56 static unsigned long pcm_count = 0;
57 static unsigned short pcm_bitsok = 8;
58 static int my_devnum = 0;
59
60 int
61 pcm_set_speed (int arg)
62 {
63 int foo, tmp;
64 unsigned long flags;
65
66 if (arg > 44100)
67 arg = 44100;
68 if (arg < 5000)
69 arg = 5000;
70
71 foo = (1193180 + (arg / 2)) / arg;
72 arg = 1193180 / foo;
73
74 if (pcm_channels & 2)
75 foo = foo >> 1;
76
77 pcm_speed = arg;
78
79 tmp = pas_read (FILTER_FREQUENCY);
80
81
82
83
84
85
86
87
88
89 #if !defined NO_AUTO_FILTER_SET
90 tmp &= 0xe0;
91 if (pcm_speed >= 2 * 17897)
92 tmp |= 0x21;
93 else if (pcm_speed >= 2 * 15909)
94 tmp |= 0x22;
95 else if (pcm_speed >= 2 * 11931)
96 tmp |= 0x29;
97 else if (pcm_speed >= 2 * 8948)
98 tmp |= 0x31;
99 else if (pcm_speed >= 2 * 5965)
100 tmp |= 0x39;
101 else if (pcm_speed >= 2 * 2982)
102 tmp |= 0x24;
103 pcm_filter = tmp;
104 #endif
105
106 save_flags (flags);
107 cli ();
108
109 pas_write (tmp & ~(F_F_PCM_RATE_COUNTER | F_F_PCM_BUFFER_COUNTER), FILTER_FREQUENCY);
110 pas_write (S_C_C_SAMPLE_RATE | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
111 pas_write (foo & 0xff, SAMPLE_RATE_TIMER);
112 pas_write ((foo >> 8) & 0xff, SAMPLE_RATE_TIMER);
113 pas_write (tmp, FILTER_FREQUENCY);
114
115 restore_flags (flags);
116
117 return pcm_speed;
118 }
119
120 int
121 pcm_set_channels (int arg)
122 {
123
124 if ((arg != 1) && (arg != 2))
125 return pcm_channels;
126
127 if (arg != pcm_channels)
128 {
129 pas_write (pas_read (PCM_CONTROL) ^ P_C_PCM_MONO, PCM_CONTROL);
130
131 pcm_channels = arg;
132 pcm_set_speed (pcm_speed);
133
134
135 }
136
137 return pcm_channels;
138 }
139
140 int
141 pcm_set_bits (int arg)
142 {
143 if ((arg & pcm_bitsok) != arg)
144 return pcm_bits;
145
146 if (arg != pcm_bits)
147 {
148 pas_write (pas_read (SYSTEM_CONFIGURATION_2) ^ S_C_2_PCM_16_BIT, SYSTEM_CONFIGURATION_2);
149
150 pcm_bits = arg;
151 }
152
153 return pcm_bits;
154 }
155
156 static int
157 pas_pcm_ioctl (int dev, unsigned int cmd, ioctl_arg arg, int local)
158 {
159 TRACE (printk ("pas2_pcm.c: static int pas_pcm_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
160
161 switch (cmd)
162 {
163 case SOUND_PCM_WRITE_RATE:
164 if (local)
165 return pcm_set_speed ((int) arg);
166 return snd_ioctl_return ((int *) arg, pcm_set_speed (get_fs_long ((long *) arg)));
167 break;
168
169 case SOUND_PCM_READ_RATE:
170 if (local)
171 return pcm_speed;
172 return snd_ioctl_return ((int *) arg, pcm_speed);
173 break;
174
175 case SNDCTL_DSP_STEREO:
176 if (local)
177 return pcm_set_channels ((int) arg + 1) - 1;
178 return snd_ioctl_return ((int *) arg, pcm_set_channels (get_fs_long ((long *) arg) + 1) - 1);
179 break;
180
181 case SOUND_PCM_WRITE_CHANNELS:
182 if (local)
183 return pcm_set_channels ((int) arg);
184 return snd_ioctl_return ((int *) arg, pcm_set_channels (get_fs_long ((long *) arg)));
185 break;
186
187 case SOUND_PCM_READ_CHANNELS:
188 if (local)
189 return pcm_channels;
190 return snd_ioctl_return ((int *) arg, pcm_channels);
191 break;
192
193 case SNDCTL_DSP_SETFMT:
194 if (local)
195 return pcm_set_bits ((int) arg);
196 return snd_ioctl_return ((int *) arg, pcm_set_bits (get_fs_long ((long *) arg)));
197 break;
198
199 case SOUND_PCM_READ_BITS:
200 if (local)
201 return pcm_bits;
202 return snd_ioctl_return ((int *) arg, pcm_bits);
203
204 case SOUND_PCM_WRITE_FILTER:
205
206
207 if (get_fs_long ((long *) arg) > 1)
208 return -EINVAL;
209 pcm_filter = get_fs_long ((long *) arg);
210 break;
211
212 case SOUND_PCM_READ_FILTER:
213 return snd_ioctl_return ((int *) arg, pcm_filter);
214 break;
215
216 default:
217 return -EINVAL;
218 }
219
220 return -EINVAL;
221 }
222
223 static void
224 pas_pcm_reset (int dev)
225 {
226 TRACE (printk ("pas2_pcm.c: static void pas_pcm_reset(void)\n"));
227
228 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE, PCM_CONTROL);
229 }
230
231 static int
232 pas_pcm_open (int dev, int mode)
233 {
234 int err;
235
236 TRACE (printk ("pas2_pcm.c: static int pas_pcm_open(int mode = %X)\n", mode));
237
238 if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0)
239 return err;
240
241
242 pcm_count = 0;
243
244 return 0;
245 }
246
247 static void
248 pas_pcm_close (int dev)
249 {
250 unsigned long flags;
251
252 TRACE (printk ("pas2_pcm.c: static void pas_pcm_close(void)\n"));
253
254 save_flags (flags);
255 cli ();
256
257 pas_pcm_reset (dev);
258 pas_remove_intr (PAS_PCM_INTRBITS);
259 pcm_mode = PCM_NON;
260
261 restore_flags (flags);
262 }
263
264 static void
265 pas_pcm_output_block (int dev, unsigned long buf, int count,
266 int intrflag, int restart_dma)
267 {
268 unsigned long flags, cnt;
269
270 TRACE (printk ("pas2_pcm.c: static void pas_pcm_output_block(char *buf = %P, int count = %X)\n", buf, count));
271
272 cnt = count;
273 if (audio_devs[dev]->dmachan1 > 3)
274 cnt >>= 1;
275
276 if (audio_devs[dev]->flags & DMA_AUTOMODE &&
277 intrflag &&
278 cnt == pcm_count)
279 return;
280
281
282
283 save_flags (flags);
284 cli ();
285
286 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
287 PCM_CONTROL);
288
289 if (restart_dma)
290 DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
291
292 if (audio_devs[dev]->dmachan1 > 3)
293 count >>= 1;
294
295 if (count != pcm_count)
296 {
297 pas_write (pas_read (FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
298 pas_write (S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
299 pas_write (count & 0xff, SAMPLE_BUFFER_COUNTER);
300 pas_write ((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
301 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
302
303 pcm_count = count;
304 }
305 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
306 pas_write (pas_read (PCM_CONTROL) | P_C_PCM_ENABLE | P_C_PCM_DAC_MODE, PCM_CONTROL);
307
308 pcm_mode = PCM_DAC;
309
310 restore_flags (flags);
311 }
312
313 static void
314 pas_pcm_start_input (int dev, unsigned long buf, int count,
315 int intrflag, int restart_dma)
316 {
317 unsigned long flags;
318 int cnt;
319
320 TRACE (printk ("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf, count));
321
322 cnt = count;
323 if (audio_devs[dev]->dmachan1 > 3)
324 cnt >>= 1;
325
326 if (audio_devs[my_devnum]->flags & DMA_AUTOMODE &&
327 intrflag &&
328 cnt == pcm_count)
329 return;
330
331
332
333 save_flags (flags);
334 cli ();
335
336 if (restart_dma)
337 DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
338
339 if (audio_devs[dev]->dmachan1 > 3)
340 count >>= 1;
341
342 if (count != pcm_count)
343 {
344 pas_write (pas_read (FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
345 pas_write (S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
346 pas_write (count & 0xff, SAMPLE_BUFFER_COUNTER);
347 pas_write ((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
348 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
349
350 pcm_count = count;
351 }
352 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
353 pas_write ((pas_read (PCM_CONTROL) | P_C_PCM_ENABLE) & ~P_C_PCM_DAC_MODE, PCM_CONTROL);
354
355 pcm_mode = PCM_ADC;
356
357 restore_flags (flags);
358 }
359
360 static int
361 pas_pcm_prepare_for_input (int dev, int bsize, int bcount)
362 {
363 return 0;
364 }
365 static int
366 pas_pcm_prepare_for_output (int dev, int bsize, int bcount)
367 {
368 return 0;
369 }
370
371 static struct audio_operations pas_pcm_operations =
372 {
373 "Pro Audio Spectrum",
374 DMA_AUTOMODE,
375 AFMT_U8 | AFMT_S16_LE,
376 NULL,
377 pas_pcm_open,
378 pas_pcm_close,
379 pas_pcm_output_block,
380 pas_pcm_start_input,
381 pas_pcm_ioctl,
382 pas_pcm_prepare_for_input,
383 pas_pcm_prepare_for_output,
384 pas_pcm_reset,
385 pas_pcm_reset,
386 NULL,
387 NULL
388 };
389
390 long
391 pas_pcm_init (long mem_start, struct address_info *hw_config)
392 {
393 TRACE (printk ("pas2_pcm.c: long pas_pcm_init(long mem_start = %X)\n", mem_start));
394
395 pcm_bitsok = 8;
396 if (pas_read (OPERATION_MODE_1) & O_M_1_PCM_TYPE)
397 pcm_bitsok |= 16;
398
399 pcm_set_speed (DSP_DEFAULT_SPEED);
400
401 if (num_audiodevs < MAX_AUDIO_DEV)
402 {
403 audio_devs[my_devnum = num_audiodevs++] = &pas_pcm_operations;
404 audio_devs[my_devnum]->dmachan1 = hw_config->dma;
405 audio_devs[my_devnum]->buffsize = DSP_BUFFSIZE;
406 }
407 else
408 printk ("PAS2: Too many PCM devices available\n");
409
410 return mem_start;
411 }
412
413 void
414 pas_pcm_interrupt (unsigned char status, int cause)
415 {
416 if (cause == 1)
417
418
419 {
420
421
422
423
424
425 if (!(audio_devs[my_devnum]->flags & DMA_AUTOMODE))
426 {
427 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
428 PCM_CONTROL);
429 }
430
431 switch (pcm_mode)
432 {
433
434 case PCM_DAC:
435 DMAbuf_outputintr (my_devnum, 1);
436 break;
437
438 case PCM_ADC:
439 DMAbuf_inputintr (my_devnum);
440 break;
441
442 default:
443 printk ("PAS: Unexpected PCM interrupt\n");
444 }
445 }
446 }
447
448 #endif
449
450 #endif