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