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