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