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