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 (mode != OPEN_READ && mode != OPEN_WRITE)
204 {
205 printk ("PAS2: Attempt to open PCM device for simultaneous read and write");
206 return RET_ERROR (EINVAL);
207 }
208
209 if ((err = pas_set_intr (PAS_PCM_INTRBITS)) < 0)
210 return err;
211
212 if (!DMAbuf_open_dma (dev))
213 {
214 pas_remove_intr (PAS_PCM_INTRBITS);
215 return RET_ERROR (EBUSY);
216 }
217
218 pcm_count = 0;
219
220 pcm_set_bits (8);
221 pcm_set_channels (1);
222 pcm_set_speed (DSP_DEFAULT_SPEED);
223
224 return 0;
225 }
226
227 static void
228 pas_pcm_close (int dev)
229 {
230 unsigned long flags;
231
232 TRACE (printk ("pas2_pcm.c: static void pas_pcm_close(void)\n"));
233
234 DISABLE_INTR (flags);
235
236 pas_pcm_reset (dev);
237 DMAbuf_close_dma (dev);
238 pas_remove_intr (PAS_PCM_INTRBITS);
239 pcm_mode = PCM_NON;
240
241 RESTORE_INTR (flags);
242 }
243
244 static void
245 pas_pcm_output_block (int dev, unsigned long buf, int count, int intrflag)
246 {
247 unsigned long flags, cnt;
248
249 TRACE (printk ("pas2_pcm.c: static void pas_pcm_output_block(char *buf = %P, int count = %X)\n", buf, count));
250
251 cnt = count;
252 if (sound_dsp_dmachan[dev] > 3)
253 cnt >>= 1;
254 cnt--;
255
256 if (sound_dma_automode[dev] &&
257 intrflag &&
258 cnt == pcm_count)
259 return;
260
261 DISABLE_INTR (flags);
262
263 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
264 PCM_CONTROL);
265
266 DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
267
268 if (sound_dsp_dmachan[dev] > 3)
269 count >>= 1;
270 count--;
271
272 if (count != pcm_count)
273 {
274 pas_write (pas_read (FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
275 pas_write (S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
276 pas_write (count & 0xff, SAMPLE_BUFFER_COUNTER);
277 pas_write ((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
278 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
279
280 pcm_count = count;
281 }
282 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
283 pas_write (pas_read (PCM_CONTROL) | P_C_PCM_ENABLE | P_C_PCM_DAC_MODE, PCM_CONTROL);
284
285 pcm_mode = PCM_DAC;
286
287 RESTORE_INTR (flags);
288 }
289
290 static void
291 pas_pcm_start_input (int dev, unsigned long buf, int count, int intrflag)
292 {
293 unsigned long flags;
294 int cnt;
295
296 TRACE (printk ("pas2_pcm.c: static void pas_pcm_start_input(char *buf = %P, int count = %X)\n", buf, count));
297
298 cnt = count;
299 if (sound_dsp_dmachan[dev] > 3)
300 cnt >>= 1;
301 cnt--;
302
303 if (sound_dma_automode[my_devnum] &&
304 intrflag &&
305 cnt == pcm_count)
306 return;
307
308 DISABLE_INTR (flags);
309
310 DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
311
312 if (sound_dsp_dmachan[dev] > 3)
313 count >>= 1;
314
315 count--;
316
317 if (count != pcm_count)
318 {
319 pas_write (pas_read (FILTER_FREQUENCY) & ~F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
320 pas_write (S_C_C_SAMPLE_BUFFER | S_C_C_LSB_THEN_MSB | S_C_C_SQUARE_WAVE, SAMPLE_COUNTER_CONTROL);
321 pas_write (count & 0xff, SAMPLE_BUFFER_COUNTER);
322 pas_write ((count >> 8) & 0xff, SAMPLE_BUFFER_COUNTER);
323 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER, FILTER_FREQUENCY);
324
325 pcm_count = count;
326 }
327 pas_write (pas_read (FILTER_FREQUENCY) | F_F_PCM_BUFFER_COUNTER | F_F_PCM_RATE_COUNTER, FILTER_FREQUENCY);
328 pas_write ((pas_read (PCM_CONTROL) | P_C_PCM_ENABLE) & ~P_C_PCM_DAC_MODE, PCM_CONTROL);
329
330 pcm_mode = PCM_ADC;
331
332 RESTORE_INTR (flags);
333 }
334
335 static int
336 pas_pcm_prepare_for_input (int dev, int bsize, int bcount)
337 {
338 return 0;
339 }
340 static int
341 pas_pcm_prepare_for_output (int dev, int bsize, int bcount)
342 {
343 return 0;
344 }
345
346 static struct audio_operations pas_pcm_operations =
347 {
348 "Pro Audio Spectrum",
349 pas_pcm_open,
350 pas_pcm_close,
351 pas_pcm_output_block,
352 pas_pcm_start_input,
353 pas_pcm_ioctl,
354 pas_pcm_prepare_for_input,
355 pas_pcm_prepare_for_output,
356 pas_pcm_reset,
357 pas_pcm_reset,
358 NULL,
359 NULL
360 };
361
362 long
363 pas_pcm_init (long mem_start, struct address_info *hw_config)
364 {
365 TRACE (printk ("pas2_pcm.c: long pas_pcm_init(long mem_start = %X)\n", mem_start));
366
367 pcm_bitsok = 8;
368 if (pas_read (OPERATION_MODE_1) & O_M_1_PCM_TYPE)
369 pcm_bitsok |= 16;
370
371 pcm_set_speed (DSP_DEFAULT_SPEED);
372
373 if (num_dspdevs < MAX_DSP_DEV)
374 {
375 dsp_devs[my_devnum = num_dspdevs++] = &pas_pcm_operations;
376 sound_dsp_dmachan[my_devnum] = hw_config->dma;
377 if (hw_config->dma > 3)
378 {
379 sound_buffcounts[my_devnum] = 1;
380 sound_buffsizes[my_devnum] = 2 * 65536;
381 sound_dma_automode[my_devnum] = 1;
382 }
383 else
384 {
385 sound_buffcounts[my_devnum] = 1;
386 sound_buffsizes[my_devnum] = DSP_BUFFSIZE;
387 sound_dma_automode[my_devnum] = 1;
388 }
389 }
390 else
391 printk ("PAS2: Too many PCM devices available\n");
392
393 return mem_start;
394 }
395
396 void
397 pas_pcm_interrupt (unsigned char status, int cause)
398 {
399 if (cause == 1)
400 {
401
402
403
404
405
406 if (!sound_dma_automode[my_devnum])
407 {
408 pas_write (pas_read (PCM_CONTROL) & ~P_C_PCM_ENABLE,
409 PCM_CONTROL);
410 }
411
412 switch (pcm_mode)
413 {
414
415 case PCM_DAC:
416 DMAbuf_outputintr (my_devnum);
417 break;
418
419 case PCM_ADC:
420 DMAbuf_inputintr (my_devnum);
421 break;
422
423 default:
424 printk ("PAS: Unexpected PCM interrupt\n");
425 }
426 }
427 }
428
429 #endif
430
431 #endif