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