aboutsummaryrefslogtreecommitdiffstats
path: root/sound/oss/dmasound/dmasound_atari.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/oss/dmasound/dmasound_atari.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'sound/oss/dmasound/dmasound_atari.c')
-rw-r--r--sound/oss/dmasound/dmasound_atari.c1600
1 files changed, 1600 insertions, 0 deletions
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c
new file mode 100644
index 000000000000..8daaf87664ba
--- /dev/null
+++ b/sound/oss/dmasound/dmasound_atari.c
@@ -0,0 +1,1600 @@
1/*
2 * linux/sound/oss/dmasound/dmasound_atari.c
3 *
4 * Atari TT and Falcon DMA Sound Driver
5 *
6 * See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits
7 * prior to 28/01/2001
8 *
9 * 28/01/2001 [0.1] Iain Sandoe
10 * - added versioning
11 * - put in and populated the hardware_afmts field.
12 * [0.2] - put in SNDCTL_DSP_GETCAPS value.
13 * 01/02/2001 [0.3] - put in default hard/soft settings.
14 */
15
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/soundcard.h>
21#include <linux/mm.h>
22#include <linux/spinlock.h>
23#include <linux/interrupt.h>
24
25#include <asm/uaccess.h>
26#include <asm/atariints.h>
27#include <asm/atari_stram.h>
28
29#include "dmasound.h"
30
31#define DMASOUND_ATARI_REVISION 0
32#define DMASOUND_ATARI_EDITION 3
33
34extern void atari_microwire_cmd(int cmd);
35
36static int is_falcon;
37static int write_sq_ignore_int; /* ++TeSche: used for Falcon */
38
39static int expand_bal; /* Balance factor for expanding (not volume!) */
40static int expand_data; /* Data for expanding */
41
42
43/*** Translations ************************************************************/
44
45
46/* ++TeSche: radically changed for new expanding purposes...
47 *
48 * These two routines now deal with copying/expanding/translating the samples
49 * from user space into our buffer at the right frequency. They take care about
50 * how much data there's actually to read, how much buffer space there is and
51 * to convert samples into the right frequency/encoding. They will only work on
52 * complete samples so it may happen they leave some bytes in the input stream
53 * if the user didn't write a multiple of the current sample size. They both
54 * return the number of bytes they've used from both streams so you may detect
55 * such a situation. Luckily all programs should be able to cope with that.
56 *
57 * I think I've optimized anything as far as one can do in plain C, all
58 * variables should fit in registers and the loops are really short. There's
59 * one loop for every possible situation. Writing a more generalized and thus
60 * parameterized loop would only produce slower code. Feel free to optimize
61 * this in assembler if you like. :)
62 *
63 * I think these routines belong here because they're not yet really hardware
64 * independent, especially the fact that the Falcon can play 16bit samples
65 * only in stereo is hardcoded in both of them!
66 *
67 * ++geert: split in even more functions (one per format)
68 */
69
70static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,
71 u_char frame[], ssize_t *frameUsed,
72 ssize_t frameLeft);
73static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,
74 u_char frame[], ssize_t *frameUsed,
75 ssize_t frameLeft);
76static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,
77 u_char frame[], ssize_t *frameUsed,
78 ssize_t frameLeft);
79static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,
80 u_char frame[], ssize_t *frameUsed,
81 ssize_t frameLeft);
82static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
83 u_char frame[], ssize_t *frameUsed,
84 ssize_t frameLeft);
85static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
86 u_char frame[], ssize_t *frameUsed,
87 ssize_t frameLeft);
88static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
89 u_char frame[], ssize_t *frameUsed,
90 ssize_t frameLeft);
91static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,
92 u_char frame[], ssize_t *frameUsed,
93 ssize_t frameLeft);
94static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,
95 u_char frame[], ssize_t *frameUsed,
96 ssize_t frameLeft);
97static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,
98 u_char frame[], ssize_t *frameUsed,
99 ssize_t frameLeft);
100static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
101 u_char frame[], ssize_t *frameUsed,
102 ssize_t frameLeft);
103static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
104 u_char frame[], ssize_t *frameUsed,
105 ssize_t frameLeft);
106static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
107 u_char frame[], ssize_t *frameUsed,
108 ssize_t frameLeft);
109static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
110 u_char frame[], ssize_t *frameUsed,
111 ssize_t frameLeft);
112
113
114/*** Low level stuff *********************************************************/
115
116
117static void *AtaAlloc(unsigned int size, int flags);
118static void AtaFree(void *, unsigned int size);
119static int AtaIrqInit(void);
120#ifdef MODULE
121static void AtaIrqCleanUp(void);
122#endif /* MODULE */
123static int AtaSetBass(int bass);
124static int AtaSetTreble(int treble);
125static void TTSilence(void);
126static void TTInit(void);
127static int TTSetFormat(int format);
128static int TTSetVolume(int volume);
129static int TTSetGain(int gain);
130static void FalconSilence(void);
131static void FalconInit(void);
132static int FalconSetFormat(int format);
133static int FalconSetVolume(int volume);
134static void AtaPlayNextFrame(int index);
135static void AtaPlay(void);
136static irqreturn_t AtaInterrupt(int irq, void *dummy, struct pt_regs *fp);
137
138/*** Mid level stuff *********************************************************/
139
140static void TTMixerInit(void);
141static void FalconMixerInit(void);
142static int AtaMixerIoctl(u_int cmd, u_long arg);
143static int TTMixerIoctl(u_int cmd, u_long arg);
144static int FalconMixerIoctl(u_int cmd, u_long arg);
145static int AtaWriteSqSetup(void);
146static int AtaSqOpen(mode_t mode);
147static int TTStateInfo(char *buffer, size_t space);
148static int FalconStateInfo(char *buffer, size_t space);
149
150
151/*** Translations ************************************************************/
152
153
154static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,
155 u_char frame[], ssize_t *frameUsed,
156 ssize_t frameLeft)
157{
158 char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8
159 : dmasound_alaw2dma8;
160 ssize_t count, used;
161 u_char *p = &frame[*frameUsed];
162
163 count = min_t(unsigned long, userCount, frameLeft);
164 if (dmasound.soft.stereo)
165 count &= ~1;
166 used = count;
167 while (count > 0) {
168 u_char data;
169 if (get_user(data, userPtr++))
170 return -EFAULT;
171 *p++ = table[data];
172 count--;
173 }
174 *frameUsed += used;
175 return used;
176}
177
178
179static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,
180 u_char frame[], ssize_t *frameUsed,
181 ssize_t frameLeft)
182{
183 ssize_t count, used;
184 void *p = &frame[*frameUsed];
185
186 count = min_t(unsigned long, userCount, frameLeft);
187 if (dmasound.soft.stereo)
188 count &= ~1;
189 used = count;
190 if (copy_from_user(p, userPtr, count))
191 return -EFAULT;
192 *frameUsed += used;
193 return used;
194}
195
196
197static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,
198 u_char frame[], ssize_t *frameUsed,
199 ssize_t frameLeft)
200{
201 ssize_t count, used;
202
203 if (!dmasound.soft.stereo) {
204 u_char *p = &frame[*frameUsed];
205 count = min_t(unsigned long, userCount, frameLeft);
206 used = count;
207 while (count > 0) {
208 u_char data;
209 if (get_user(data, userPtr++))
210 return -EFAULT;
211 *p++ = data ^ 0x80;
212 count--;
213 }
214 } else {
215 u_short *p = (u_short *)&frame[*frameUsed];
216 count = min_t(unsigned long, userCount, frameLeft)>>1;
217 used = count*2;
218 while (count > 0) {
219 u_short data;
220 if (get_user(data, ((u_short *)userPtr)++))
221 return -EFAULT;
222 *p++ = data ^ 0x8080;
223 count--;
224 }
225 }
226 *frameUsed += used;
227 return used;
228}
229
230
231static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,
232 u_char frame[], ssize_t *frameUsed,
233 ssize_t frameLeft)
234{
235 ssize_t count, used;
236
237 if (!dmasound.soft.stereo) {
238 u_short *p = (u_short *)&frame[*frameUsed];
239 count = min_t(unsigned long, userCount, frameLeft)>>1;
240 used = count*2;
241 while (count > 0) {
242 u_short data;
243 if (get_user(data, ((u_short *)userPtr)++))
244 return -EFAULT;
245 *p++ = data;
246 *p++ = data;
247 count--;
248 }
249 *frameUsed += used*2;
250 } else {
251 void *p = (u_short *)&frame[*frameUsed];
252 count = min_t(unsigned long, userCount, frameLeft) & ~3;
253 used = count;
254 if (copy_from_user(p, userPtr, count))
255 return -EFAULT;
256 *frameUsed += used;
257 }
258 return used;
259}
260
261
262static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
263 u_char frame[], ssize_t *frameUsed,
264 ssize_t frameLeft)
265{
266 ssize_t count, used;
267
268 if (!dmasound.soft.stereo) {
269 u_short *p = (u_short *)&frame[*frameUsed];
270 count = min_t(unsigned long, userCount, frameLeft)>>1;
271 used = count*2;
272 while (count > 0) {
273 u_short data;
274 if (get_user(data, ((u_short *)userPtr)++))
275 return -EFAULT;
276 data ^= 0x8000;
277 *p++ = data;
278 *p++ = data;
279 count--;
280 }
281 *frameUsed += used*2;
282 } else {
283 u_long *p = (u_long *)&frame[*frameUsed];
284 count = min_t(unsigned long, userCount, frameLeft)>>2;
285 used = count*4;
286 while (count > 0) {
287 u_long data;
288 if (get_user(data, ((u_int *)userPtr)++))
289 return -EFAULT;
290 *p++ = data ^ 0x80008000;
291 count--;
292 }
293 *frameUsed += used;
294 }
295 return used;
296}
297
298
299static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
300 u_char frame[], ssize_t *frameUsed,
301 ssize_t frameLeft)
302{
303 ssize_t count, used;
304
305 count = frameLeft;
306 if (!dmasound.soft.stereo) {
307 u_short *p = (u_short *)&frame[*frameUsed];
308 count = min_t(unsigned long, userCount, frameLeft)>>1;
309 used = count*2;
310 while (count > 0) {
311 u_short data;
312 if (get_user(data, ((u_short *)userPtr)++))
313 return -EFAULT;
314 data = le2be16(data);
315 *p++ = data;
316 *p++ = data;
317 count--;
318 }
319 *frameUsed += used*2;
320 } else {
321 u_long *p = (u_long *)&frame[*frameUsed];
322 count = min_t(unsigned long, userCount, frameLeft)>>2;
323 used = count*4;
324 while (count > 0) {
325 u_long data;
326 if (get_user(data, ((u_int *)userPtr)++))
327 return -EFAULT;
328 data = le2be16dbl(data);
329 *p++ = data;
330 count--;
331 }
332 *frameUsed += used;
333 }
334 return used;
335}
336
337
338static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
339 u_char frame[], ssize_t *frameUsed,
340 ssize_t frameLeft)
341{
342 ssize_t count, used;
343
344 count = frameLeft;
345 if (!dmasound.soft.stereo) {
346 u_short *p = (u_short *)&frame[*frameUsed];
347 count = min_t(unsigned long, userCount, frameLeft)>>1;
348 used = count*2;
349 while (count > 0) {
350 u_short data;
351 if (get_user(data, ((u_short *)userPtr)++))
352 return -EFAULT;
353 data = le2be16(data) ^ 0x8000;
354 *p++ = data;
355 *p++ = data;
356 }
357 *frameUsed += used*2;
358 } else {
359 u_long *p = (u_long *)&frame[*frameUsed];
360 count = min_t(unsigned long, userCount, frameLeft)>>2;
361 used = count;
362 while (count > 0) {
363 u_long data;
364 if (get_user(data, ((u_int *)userPtr)++))
365 return -EFAULT;
366 data = le2be16dbl(data) ^ 0x80008000;
367 *p++ = data;
368 count--;
369 }
370 *frameUsed += used;
371 }
372 return used;
373}
374
375
376static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,
377 u_char frame[], ssize_t *frameUsed,
378 ssize_t frameLeft)
379{
380 char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8
381 : dmasound_alaw2dma8;
382 /* this should help gcc to stuff everything into registers */
383 long bal = expand_bal;
384 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
385 ssize_t used, usedf;
386
387 used = userCount;
388 usedf = frameLeft;
389 if (!dmasound.soft.stereo) {
390 u_char *p = &frame[*frameUsed];
391 u_char data = expand_data;
392 while (frameLeft) {
393 u_char c;
394 if (bal < 0) {
395 if (!userCount)
396 break;
397 if (get_user(c, userPtr++))
398 return -EFAULT;
399 data = table[c];
400 userCount--;
401 bal += hSpeed;
402 }
403 *p++ = data;
404 frameLeft--;
405 bal -= sSpeed;
406 }
407 expand_data = data;
408 } else {
409 u_short *p = (u_short *)&frame[*frameUsed];
410 u_short data = expand_data;
411 while (frameLeft >= 2) {
412 u_char c;
413 if (bal < 0) {
414 if (userCount < 2)
415 break;
416 if (get_user(c, userPtr++))
417 return -EFAULT;
418 data = table[c] << 8;
419 if (get_user(c, userPtr++))
420 return -EFAULT;
421 data |= table[c];
422 userCount -= 2;
423 bal += hSpeed;
424 }
425 *p++ = data;
426 frameLeft -= 2;
427 bal -= sSpeed;
428 }
429 expand_data = data;
430 }
431 expand_bal = bal;
432 used -= userCount;
433 *frameUsed += usedf-frameLeft;
434 return used;
435}
436
437
438static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,
439 u_char frame[], ssize_t *frameUsed,
440 ssize_t frameLeft)
441{
442 /* this should help gcc to stuff everything into registers */
443 long bal = expand_bal;
444 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
445 ssize_t used, usedf;
446
447 used = userCount;
448 usedf = frameLeft;
449 if (!dmasound.soft.stereo) {
450 u_char *p = &frame[*frameUsed];
451 u_char data = expand_data;
452 while (frameLeft) {
453 if (bal < 0) {
454 if (!userCount)
455 break;
456 if (get_user(data, userPtr++))
457 return -EFAULT;
458 userCount--;
459 bal += hSpeed;
460 }
461 *p++ = data;
462 frameLeft--;
463 bal -= sSpeed;
464 }
465 expand_data = data;
466 } else {
467 u_short *p = (u_short *)&frame[*frameUsed];
468 u_short data = expand_data;
469 while (frameLeft >= 2) {
470 if (bal < 0) {
471 if (userCount < 2)
472 break;
473 if (get_user(data, ((u_short *)userPtr)++))
474 return -EFAULT;
475 userCount -= 2;
476 bal += hSpeed;
477 }
478 *p++ = data;
479 frameLeft -= 2;
480 bal -= sSpeed;
481 }
482 expand_data = data;
483 }
484 expand_bal = bal;
485 used -= userCount;
486 *frameUsed += usedf-frameLeft;
487 return used;
488}
489
490
491static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,
492 u_char frame[], ssize_t *frameUsed,
493 ssize_t frameLeft)
494{
495 /* this should help gcc to stuff everything into registers */
496 long bal = expand_bal;
497 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
498 ssize_t used, usedf;
499
500 used = userCount;
501 usedf = frameLeft;
502 if (!dmasound.soft.stereo) {
503 u_char *p = &frame[*frameUsed];
504 u_char data = expand_data;
505 while (frameLeft) {
506 if (bal < 0) {
507 if (!userCount)
508 break;
509 if (get_user(data, userPtr++))
510 return -EFAULT;
511 data ^= 0x80;
512 userCount--;
513 bal += hSpeed;
514 }
515 *p++ = data;
516 frameLeft--;
517 bal -= sSpeed;
518 }
519 expand_data = data;
520 } else {
521 u_short *p = (u_short *)&frame[*frameUsed];
522 u_short data = expand_data;
523 while (frameLeft >= 2) {
524 if (bal < 0) {
525 if (userCount < 2)
526 break;
527 if (get_user(data, ((u_short *)userPtr)++))
528 return -EFAULT;
529 data ^= 0x8080;
530 userCount -= 2;
531 bal += hSpeed;
532 }
533 *p++ = data;
534 frameLeft -= 2;
535 bal -= sSpeed;
536 }
537 expand_data = data;
538 }
539 expand_bal = bal;
540 used -= userCount;
541 *frameUsed += usedf-frameLeft;
542 return used;
543}
544
545
546static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
547 u_char frame[], ssize_t *frameUsed,
548 ssize_t frameLeft)
549{
550 /* this should help gcc to stuff everything into registers */
551 long bal = expand_bal;
552 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
553 ssize_t used, usedf;
554
555 used = userCount;
556 usedf = frameLeft;
557 if (!dmasound.soft.stereo) {
558 u_short *p = (u_short *)&frame[*frameUsed];
559 u_short data = expand_data;
560 while (frameLeft >= 4) {
561 if (bal < 0) {
562 if (userCount < 2)
563 break;
564 if (get_user(data, ((u_short *)userPtr)++))
565 return -EFAULT;
566 userCount -= 2;
567 bal += hSpeed;
568 }
569 *p++ = data;
570 *p++ = data;
571 frameLeft -= 4;
572 bal -= sSpeed;
573 }
574 expand_data = data;
575 } else {
576 u_long *p = (u_long *)&frame[*frameUsed];
577 u_long data = expand_data;
578 while (frameLeft >= 4) {
579 if (bal < 0) {
580 if (userCount < 4)
581 break;
582 if (get_user(data, ((u_int *)userPtr)++))
583 return -EFAULT;
584 userCount -= 4;
585 bal += hSpeed;
586 }
587 *p++ = data;
588 frameLeft -= 4;
589 bal -= sSpeed;
590 }
591 expand_data = data;
592 }
593 expand_bal = bal;
594 used -= userCount;
595 *frameUsed += usedf-frameLeft;
596 return used;
597}
598
599
600static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
601 u_char frame[], ssize_t *frameUsed,
602 ssize_t frameLeft)
603{
604 /* this should help gcc to stuff everything into registers */
605 long bal = expand_bal;
606 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
607 ssize_t used, usedf;
608
609 used = userCount;
610 usedf = frameLeft;
611 if (!dmasound.soft.stereo) {
612 u_short *p = (u_short *)&frame[*frameUsed];
613 u_short data = expand_data;
614 while (frameLeft >= 4) {
615 if (bal < 0) {
616 if (userCount < 2)
617 break;
618 if (get_user(data, ((u_short *)userPtr)++))
619 return -EFAULT;
620 data ^= 0x8000;
621 userCount -= 2;
622 bal += hSpeed;
623 }
624 *p++ = data;
625 *p++ = data;
626 frameLeft -= 4;
627 bal -= sSpeed;
628 }
629 expand_data = data;
630 } else {
631 u_long *p = (u_long *)&frame[*frameUsed];
632 u_long data = expand_data;
633 while (frameLeft >= 4) {
634 if (bal < 0) {
635 if (userCount < 4)
636 break;
637 if (get_user(data, ((u_int *)userPtr)++))
638 return -EFAULT;
639 data ^= 0x80008000;
640 userCount -= 4;
641 bal += hSpeed;
642 }
643 *p++ = data;
644 frameLeft -= 4;
645 bal -= sSpeed;
646 }
647 expand_data = data;
648 }
649 expand_bal = bal;
650 used -= userCount;
651 *frameUsed += usedf-frameLeft;
652 return used;
653}
654
655
656static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
657 u_char frame[], ssize_t *frameUsed,
658 ssize_t frameLeft)
659{
660 /* this should help gcc to stuff everything into registers */
661 long bal = expand_bal;
662 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
663 ssize_t used, usedf;
664
665 used = userCount;
666 usedf = frameLeft;
667 if (!dmasound.soft.stereo) {
668 u_short *p = (u_short *)&frame[*frameUsed];
669 u_short data = expand_data;
670 while (frameLeft >= 4) {
671 if (bal < 0) {
672 if (userCount < 2)
673 break;
674 if (get_user(data, ((u_short *)userPtr)++))
675 return -EFAULT;
676 data = le2be16(data);
677 userCount -= 2;
678 bal += hSpeed;
679 }
680 *p++ = data;
681 *p++ = data;
682 frameLeft -= 4;
683 bal -= sSpeed;
684 }
685 expand_data = data;
686 } else {
687 u_long *p = (u_long *)&frame[*frameUsed];
688 u_long data = expand_data;
689 while (frameLeft >= 4) {
690 if (bal < 0) {
691 if (userCount < 4)
692 break;
693 if (get_user(data, ((u_int *)userPtr)++))
694 return -EFAULT;
695 data = le2be16dbl(data);
696 userCount -= 4;
697 bal += hSpeed;
698 }
699 *p++ = data;
700 frameLeft -= 4;
701 bal -= sSpeed;
702 }
703 expand_data = data;
704 }
705 expand_bal = bal;
706 used -= userCount;
707 *frameUsed += usedf-frameLeft;
708 return used;
709}
710
711
712static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
713 u_char frame[], ssize_t *frameUsed,
714 ssize_t frameLeft)
715{
716 /* this should help gcc to stuff everything into registers */
717 long bal = expand_bal;
718 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
719 ssize_t used, usedf;
720
721 used = userCount;
722 usedf = frameLeft;
723 if (!dmasound.soft.stereo) {
724 u_short *p = (u_short *)&frame[*frameUsed];
725 u_short data = expand_data;
726 while (frameLeft >= 4) {
727 if (bal < 0) {
728 if (userCount < 2)
729 break;
730 if (get_user(data, ((u_short *)userPtr)++))
731 return -EFAULT;
732 data = le2be16(data) ^ 0x8000;
733 userCount -= 2;
734 bal += hSpeed;
735 }
736 *p++ = data;
737 *p++ = data;
738 frameLeft -= 4;
739 bal -= sSpeed;
740 }
741 expand_data = data;
742 } else {
743 u_long *p = (u_long *)&frame[*frameUsed];
744 u_long data = expand_data;
745 while (frameLeft >= 4) {
746 if (bal < 0) {
747 if (userCount < 4)
748 break;
749 if (get_user(data, ((u_int *)userPtr)++))
750 return -EFAULT;
751 data = le2be16dbl(data) ^ 0x80008000;
752 userCount -= 4;
753 bal += hSpeed;
754 }
755 *p++ = data;
756 frameLeft -= 4;
757 bal -= sSpeed;
758 }
759 expand_data = data;
760 }
761 expand_bal = bal;
762 used -= userCount;
763 *frameUsed += usedf-frameLeft;
764 return used;
765}
766
767
768static TRANS transTTNormal = {
769 .ct_ulaw = ata_ct_law,
770 .ct_alaw = ata_ct_law,
771 .ct_s8 = ata_ct_s8,
772 .ct_u8 = ata_ct_u8,
773};
774
775static TRANS transTTExpanding = {
776 .ct_ulaw = ata_ctx_law,
777 .ct_alaw = ata_ctx_law,
778 .ct_s8 = ata_ctx_s8,
779 .ct_u8 = ata_ctx_u8,
780};
781
782static TRANS transFalconNormal = {
783 .ct_ulaw = ata_ct_law,
784 .ct_alaw = ata_ct_law,
785 .ct_s8 = ata_ct_s8,
786 .ct_u8 = ata_ct_u8,
787 .ct_s16be = ata_ct_s16be,
788 .ct_u16be = ata_ct_u16be,
789 .ct_s16le = ata_ct_s16le,
790 .ct_u16le = ata_ct_u16le
791};
792
793static TRANS transFalconExpanding = {
794 .ct_ulaw = ata_ctx_law,
795 .ct_alaw = ata_ctx_law,
796 .ct_s8 = ata_ctx_s8,
797 .ct_u8 = ata_ctx_u8,
798 .ct_s16be = ata_ctx_s16be,
799 .ct_u16be = ata_ctx_u16be,
800 .ct_s16le = ata_ctx_s16le,
801 .ct_u16le = ata_ctx_u16le,
802};
803
804
805/*** Low level stuff *********************************************************/
806
807
808
809/*
810 * Atari (TT/Falcon)
811 */
812
813static void *AtaAlloc(unsigned int size, int flags)
814{
815 return atari_stram_alloc(size, "dmasound");
816}
817
818static void AtaFree(void *obj, unsigned int size)
819{
820 atari_stram_free( obj );
821}
822
823static int __init AtaIrqInit(void)
824{
825 /* Set up timer A. Timer A
826 will receive a signal upon end of playing from the sound
827 hardware. Furthermore Timer A is able to count events
828 and will cause an interrupt after a programmed number
829 of events. So all we need to keep the music playing is
830 to provide the sound hardware with new data upon
831 an interrupt from timer A. */
832 mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */
833 mfp.tim_dt_a = 1; /* Cause interrupt after first event. */
834 mfp.tim_ct_a = 8; /* Turn on event counting. */
835 /* Register interrupt handler. */
836 request_irq(IRQ_MFP_TIMA, AtaInterrupt, IRQ_TYPE_SLOW, "DMA sound",
837 AtaInterrupt);
838 mfp.int_en_a |= 0x20; /* Turn interrupt on. */
839 mfp.int_mk_a |= 0x20;
840 return 1;
841}
842
843#ifdef MODULE
844static void AtaIrqCleanUp(void)
845{
846 mfp.tim_ct_a = 0; /* stop timer */
847 mfp.int_en_a &= ~0x20; /* turn interrupt off */
848 free_irq(IRQ_MFP_TIMA, AtaInterrupt);
849}
850#endif /* MODULE */
851
852
853#define TONE_VOXWARE_TO_DB(v) \
854 (((v) < 0) ? -12 : ((v) > 100) ? 12 : ((v) - 50) * 6 / 25)
855#define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50)
856
857
858static int AtaSetBass(int bass)
859{
860 dmasound.bass = TONE_VOXWARE_TO_DB(bass);
861 atari_microwire_cmd(MW_LM1992_BASS(dmasound.bass));
862 return TONE_DB_TO_VOXWARE(dmasound.bass);
863}
864
865
866static int AtaSetTreble(int treble)
867{
868 dmasound.treble = TONE_VOXWARE_TO_DB(treble);
869 atari_microwire_cmd(MW_LM1992_TREBLE(dmasound.treble));
870 return TONE_DB_TO_VOXWARE(dmasound.treble);
871}
872
873
874
875/*
876 * TT
877 */
878
879
880static void TTSilence(void)
881{
882 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
883 atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */
884}
885
886
887static void TTInit(void)
888{
889 int mode, i, idx;
890 const int freq[4] = {50066, 25033, 12517, 6258};
891
892 /* search a frequency that fits into the allowed error range */
893
894 idx = -1;
895 for (i = 0; i < ARRAY_SIZE(freq); i++)
896 /* this isn't as much useful for a TT than for a Falcon, but
897 * then it doesn't hurt very much to implement it for a TT too.
898 */
899 if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius)
900 idx = i;
901 if (idx > -1) {
902 dmasound.soft.speed = freq[idx];
903 dmasound.trans_write = &transTTNormal;
904 } else
905 dmasound.trans_write = &transTTExpanding;
906
907 TTSilence();
908 dmasound.hard = dmasound.soft;
909
910 if (dmasound.hard.speed > 50066) {
911 /* we would need to squeeze the sound, but we won't do that */
912 dmasound.hard.speed = 50066;
913 mode = DMASND_MODE_50KHZ;
914 dmasound.trans_write = &transTTNormal;
915 } else if (dmasound.hard.speed > 25033) {
916 dmasound.hard.speed = 50066;
917 mode = DMASND_MODE_50KHZ;
918 } else if (dmasound.hard.speed > 12517) {
919 dmasound.hard.speed = 25033;
920 mode = DMASND_MODE_25KHZ;
921 } else if (dmasound.hard.speed > 6258) {
922 dmasound.hard.speed = 12517;
923 mode = DMASND_MODE_12KHZ;
924 } else {
925 dmasound.hard.speed = 6258;
926 mode = DMASND_MODE_6KHZ;
927 }
928
929 tt_dmasnd.mode = (dmasound.hard.stereo ?
930 DMASND_MODE_STEREO : DMASND_MODE_MONO) |
931 DMASND_MODE_8BIT | mode;
932
933 expand_bal = -dmasound.soft.speed;
934}
935
936
937static int TTSetFormat(int format)
938{
939 /* TT sound DMA supports only 8bit modes */
940
941 switch (format) {
942 case AFMT_QUERY:
943 return dmasound.soft.format;
944 case AFMT_MU_LAW:
945 case AFMT_A_LAW:
946 case AFMT_S8:
947 case AFMT_U8:
948 break;
949 default:
950 format = AFMT_S8;
951 }
952
953 dmasound.soft.format = format;
954 dmasound.soft.size = 8;
955 if (dmasound.minDev == SND_DEV_DSP) {
956 dmasound.dsp.format = format;
957 dmasound.dsp.size = 8;
958 }
959 TTInit();
960
961 return format;
962}
963
964
965#define VOLUME_VOXWARE_TO_DB(v) \
966 (((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40)
967#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2)
968
969
970static int TTSetVolume(int volume)
971{
972 dmasound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff);
973 atari_microwire_cmd(MW_LM1992_BALLEFT(dmasound.volume_left));
974 dmasound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8);
975 atari_microwire_cmd(MW_LM1992_BALRIGHT(dmasound.volume_right));
976 return VOLUME_DB_TO_VOXWARE(dmasound.volume_left) |
977 (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8);
978}
979
980
981#define GAIN_VOXWARE_TO_DB(v) \
982 (((v) < 0) ? -80 : ((v) > 100) ? 0 : ((v) * 4) / 5 - 80)
983#define GAIN_DB_TO_VOXWARE(v) ((((v) + 80) * 5 + 1) / 4)
984
985static int TTSetGain(int gain)
986{
987 dmasound.gain = GAIN_VOXWARE_TO_DB(gain);
988 atari_microwire_cmd(MW_LM1992_VOLUME(dmasound.gain));
989 return GAIN_DB_TO_VOXWARE(dmasound.gain);
990}
991
992
993
994/*
995 * Falcon
996 */
997
998
999static void FalconSilence(void)
1000{
1001 /* stop playback, set sample rate 50kHz for PSG sound */
1002 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1003 tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT;
1004 tt_dmasnd.int_div = 0; /* STE compatible divider */
1005 tt_dmasnd.int_ctrl = 0x0;
1006 tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */
1007 tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */
1008 tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */
1009 tt_dmasnd.adc_src = 3; /* ADC Input = PSG */
1010}
1011
1012
1013static void FalconInit(void)
1014{
1015 int divider, i, idx;
1016 const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};
1017
1018 /* search a frequency that fits into the allowed error range */
1019
1020 idx = -1;
1021 for (i = 0; i < ARRAY_SIZE(freq); i++)
1022 /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would
1023 * be playable without expanding, but that now a kernel runtime
1024 * option
1025 */
1026 if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius)
1027 idx = i;
1028 if (idx > -1) {
1029 dmasound.soft.speed = freq[idx];
1030 dmasound.trans_write = &transFalconNormal;
1031 } else
1032 dmasound.trans_write = &transFalconExpanding;
1033
1034 FalconSilence();
1035 dmasound.hard = dmasound.soft;
1036
1037 if (dmasound.hard.size == 16) {
1038 /* the Falcon can play 16bit samples only in stereo */
1039 dmasound.hard.stereo = 1;
1040 }
1041
1042 if (dmasound.hard.speed > 49170) {
1043 /* we would need to squeeze the sound, but we won't do that */
1044 dmasound.hard.speed = 49170;
1045 divider = 1;
1046 dmasound.trans_write = &transFalconNormal;
1047 } else if (dmasound.hard.speed > 32780) {
1048 dmasound.hard.speed = 49170;
1049 divider = 1;
1050 } else if (dmasound.hard.speed > 24585) {
1051 dmasound.hard.speed = 32780;
1052 divider = 2;
1053 } else if (dmasound.hard.speed > 19668) {
1054 dmasound.hard.speed = 24585;
1055 divider = 3;
1056 } else if (dmasound.hard.speed > 16390) {
1057 dmasound.hard.speed = 19668;
1058 divider = 4;
1059 } else if (dmasound.hard.speed > 12292) {
1060 dmasound.hard.speed = 16390;
1061 divider = 5;
1062 } else if (dmasound.hard.speed > 9834) {
1063 dmasound.hard.speed = 12292;
1064 divider = 7;
1065 } else if (dmasound.hard.speed > 8195) {
1066 dmasound.hard.speed = 9834;
1067 divider = 9;
1068 } else {
1069 dmasound.hard.speed = 8195;
1070 divider = 11;
1071 }
1072 tt_dmasnd.int_div = divider;
1073
1074 /* Setup Falcon sound DMA for playback */
1075 tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */
1076 tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */
1077 tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */
1078 tt_dmasnd.cbar_dst = 0x0000;
1079 tt_dmasnd.rec_track_select = 0;
1080 tt_dmasnd.dac_src = 2; /* connect matrix to DAC */
1081 tt_dmasnd.adc_src = 0; /* ADC Input = Mic */
1082
1083 tt_dmasnd.mode = (dmasound.hard.stereo ?
1084 DMASND_MODE_STEREO : DMASND_MODE_MONO) |
1085 ((dmasound.hard.size == 8) ?
1086 DMASND_MODE_8BIT : DMASND_MODE_16BIT) |
1087 DMASND_MODE_6KHZ;
1088
1089 expand_bal = -dmasound.soft.speed;
1090}
1091
1092
1093static int FalconSetFormat(int format)
1094{
1095 int size;
1096 /* Falcon sound DMA supports 8bit and 16bit modes */
1097
1098 switch (format) {
1099 case AFMT_QUERY:
1100 return dmasound.soft.format;
1101 case AFMT_MU_LAW:
1102 case AFMT_A_LAW:
1103 case AFMT_U8:
1104 case AFMT_S8:
1105 size = 8;
1106 break;
1107 case AFMT_S16_BE:
1108 case AFMT_U16_BE:
1109 case AFMT_S16_LE:
1110 case AFMT_U16_LE:
1111 size = 16;
1112 break;
1113 default: /* :-) */
1114 size = 8;
1115 format = AFMT_S8;
1116 }
1117
1118 dmasound.soft.format = format;
1119 dmasound.soft.size = size;
1120 if (dmasound.minDev == SND_DEV_DSP) {
1121 dmasound.dsp.format = format;
1122 dmasound.dsp.size = dmasound.soft.size;
1123 }
1124
1125 FalconInit();
1126
1127 return format;
1128}
1129
1130
1131/* This is for the Falcon output *attenuation* in 1.5dB steps,
1132 * i.e. output level from 0 to -22.5dB in -1.5dB steps.
1133 */
1134#define VOLUME_VOXWARE_TO_ATT(v) \
1135 ((v) < 0 ? 15 : (v) > 100 ? 0 : 15 - (v) * 3 / 20)
1136#define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3)
1137
1138
1139static int FalconSetVolume(int volume)
1140{
1141 dmasound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff);
1142 dmasound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8);
1143 tt_dmasnd.output_atten = dmasound.volume_left << 8 | dmasound.volume_right << 4;
1144 return VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) |
1145 VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8;
1146}
1147
1148
1149static void AtaPlayNextFrame(int index)
1150{
1151 char *start, *end;
1152
1153 /* used by AtaPlay() if all doubts whether there really is something
1154 * to be played are already wiped out.
1155 */
1156 start = write_sq.buffers[write_sq.front];
1157 end = start+((write_sq.count == index) ? write_sq.rear_size
1158 : write_sq.block_size);
1159 /* end might not be a legal virtual address. */
1160 DMASNDSetEnd(virt_to_phys(end - 1) + 1);
1161 DMASNDSetBase(virt_to_phys(start));
1162 /* Since only an even number of samples per frame can
1163 be played, we might lose one byte here. (TO DO) */
1164 write_sq.front = (write_sq.front+1) % write_sq.max_count;
1165 write_sq.active++;
1166 tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT;
1167}
1168
1169
1170static void AtaPlay(void)
1171{
1172 /* ++TeSche: Note that write_sq.active is no longer just a flag but
1173 * holds the number of frames the DMA is currently programmed for
1174 * instead, may be 0, 1 (currently being played) or 2 (pre-programmed).
1175 *
1176 * Changes done to write_sq.count and write_sq.active are a bit more
1177 * subtle again so now I must admit I also prefer disabling the irq
1178 * here rather than considering all possible situations. But the point
1179 * is that disabling the irq doesn't have any bad influence on this
1180 * version of the driver as we benefit from having pre-programmed the
1181 * DMA wherever possible: There's no need to reload the DMA at the
1182 * exact time of an interrupt but only at some time while the
1183 * pre-programmed frame is playing!
1184 */
1185 atari_disable_irq(IRQ_MFP_TIMA);
1186
1187 if (write_sq.active == 2 || /* DMA is 'full' */
1188 write_sq.count <= 0) { /* nothing to do */
1189 atari_enable_irq(IRQ_MFP_TIMA);
1190 return;
1191 }
1192
1193 if (write_sq.active == 0) {
1194 /* looks like there's nothing 'in' the DMA yet, so try
1195 * to put two frames into it (at least one is available).
1196 */
1197 if (write_sq.count == 1 &&
1198 write_sq.rear_size < write_sq.block_size &&
1199 !write_sq.syncing) {
1200 /* hmmm, the only existing frame is not
1201 * yet filled and we're not syncing?
1202 */
1203 atari_enable_irq(IRQ_MFP_TIMA);
1204 return;
1205 }
1206 AtaPlayNextFrame(1);
1207 if (write_sq.count == 1) {
1208 /* no more frames */
1209 atari_enable_irq(IRQ_MFP_TIMA);
1210 return;
1211 }
1212 if (write_sq.count == 2 &&
1213 write_sq.rear_size < write_sq.block_size &&
1214 !write_sq.syncing) {
1215 /* hmmm, there were two frames, but the second
1216 * one is not yet filled and we're not syncing?
1217 */
1218 atari_enable_irq(IRQ_MFP_TIMA);
1219 return;
1220 }
1221 AtaPlayNextFrame(2);
1222 } else {
1223 /* there's already a frame being played so we may only stuff
1224 * one new into the DMA, but even if this may be the last
1225 * frame existing the previous one is still on write_sq.count.
1226 */
1227 if (write_sq.count == 2 &&
1228 write_sq.rear_size < write_sq.block_size &&
1229 !write_sq.syncing) {
1230 /* hmmm, the only existing frame is not
1231 * yet filled and we're not syncing?
1232 */
1233 atari_enable_irq(IRQ_MFP_TIMA);
1234 return;
1235 }
1236 AtaPlayNextFrame(2);
1237 }
1238 atari_enable_irq(IRQ_MFP_TIMA);
1239}
1240
1241
1242static irqreturn_t AtaInterrupt(int irq, void *dummy, struct pt_regs *fp)
1243{
1244#if 0
1245 /* ++TeSche: if you should want to test this... */
1246 static int cnt;
1247 if (write_sq.active == 2)
1248 if (++cnt == 10) {
1249 /* simulate losing an interrupt */
1250 cnt = 0;
1251 return IRQ_HANDLED;
1252 }
1253#endif
1254 spin_lock(&dmasound.lock);
1255 if (write_sq_ignore_int && is_falcon) {
1256 /* ++TeSche: Falcon only: ignore first irq because it comes
1257 * immediately after starting a frame. after that, irqs come
1258 * (almost) like on the TT.
1259 */
1260 write_sq_ignore_int = 0;
1261 return IRQ_HANDLED;
1262 }
1263
1264 if (!write_sq.active) {
1265 /* playing was interrupted and sq_reset() has already cleared
1266 * the sq variables, so better don't do anything here.
1267 */
1268 WAKE_UP(write_sq.sync_queue);
1269 return IRQ_HANDLED;
1270 }
1271
1272 /* Probably ;) one frame is finished. Well, in fact it may be that a
1273 * pre-programmed one is also finished because there has been a long
1274 * delay in interrupt delivery and we've completely lost one, but
1275 * there's no way to detect such a situation. In such a case the last
1276 * frame will be played more than once and the situation will recover
1277 * as soon as the irq gets through.
1278 */
1279 write_sq.count--;
1280 write_sq.active--;
1281
1282 if (!write_sq.active) {
1283 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1284 write_sq_ignore_int = 1;
1285 }
1286
1287 WAKE_UP(write_sq.action_queue);
1288 /* At least one block of the queue is free now
1289 so wake up a writing process blocked because
1290 of a full queue. */
1291
1292 if ((write_sq.active != 1) || (write_sq.count != 1))
1293 /* We must be a bit carefully here: write_sq.count indicates the
1294 * number of buffers used and not the number of frames to be
1295 * played. If write_sq.count==1 and write_sq.active==1 that
1296 * means the only remaining frame was already programmed
1297 * earlier (and is currently running) so we mustn't call
1298 * AtaPlay() here, otherwise we'll play one frame too much.
1299 */
1300 AtaPlay();
1301
1302 if (!write_sq.active) WAKE_UP(write_sq.sync_queue);
1303 /* We are not playing after AtaPlay(), so there
1304 is nothing to play any more. Wake up a process
1305 waiting for audio output to drain. */
1306 spin_unlock(&dmasound.lock);
1307 return IRQ_HANDLED;
1308}
1309
1310
1311/*** Mid level stuff *********************************************************/
1312
1313
1314/*
1315 * /dev/mixer abstraction
1316 */
1317
1318#define RECLEVEL_VOXWARE_TO_GAIN(v) \
1319 ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20)
1320#define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3)
1321
1322
1323static void __init TTMixerInit(void)
1324{
1325 atari_microwire_cmd(MW_LM1992_VOLUME(0));
1326 dmasound.volume_left = 0;
1327 atari_microwire_cmd(MW_LM1992_BALLEFT(0));
1328 dmasound.volume_right = 0;
1329 atari_microwire_cmd(MW_LM1992_BALRIGHT(0));
1330 atari_microwire_cmd(MW_LM1992_TREBLE(0));
1331 atari_microwire_cmd(MW_LM1992_BASS(0));
1332}
1333
1334static void __init FalconMixerInit(void)
1335{
1336 dmasound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
1337 dmasound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
1338}
1339
1340static int AtaMixerIoctl(u_int cmd, u_long arg)
1341{
1342 int data;
1343 unsigned long flags;
1344 switch (cmd) {
1345 case SOUND_MIXER_READ_SPEAKER:
1346 if (is_falcon || MACH_IS_TT) {
1347 int porta;
1348 spin_lock_irqsave(&dmasound.lock, flags);
1349 sound_ym.rd_data_reg_sel = 14;
1350 porta = sound_ym.rd_data_reg_sel;
1351 spin_unlock_irqrestore(&dmasound.lock, flags);
1352 return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);
1353 }
1354 break;
1355 case SOUND_MIXER_WRITE_VOLUME:
1356 IOCTL_IN(arg, data);
1357 return IOCTL_OUT(arg, dmasound_set_volume(data));
1358 case SOUND_MIXER_WRITE_SPEAKER:
1359 if (is_falcon || MACH_IS_TT) {
1360 int porta;
1361 IOCTL_IN(arg, data);
1362 spin_lock_irqsave(&dmasound.lock, flags);
1363 sound_ym.rd_data_reg_sel = 14;
1364 porta = (sound_ym.rd_data_reg_sel & ~0x40) |
1365 (data < 50 ? 0x40 : 0);
1366 sound_ym.wd_data = porta;
1367 spin_unlock_irqrestore(&dmasound.lock, flags);
1368 return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);
1369 }
1370 }
1371 return -EINVAL;
1372}
1373
1374
1375static int TTMixerIoctl(u_int cmd, u_long arg)
1376{
1377 int data;
1378 switch (cmd) {
1379 case SOUND_MIXER_READ_RECMASK:
1380 return IOCTL_OUT(arg, 0);
1381 case SOUND_MIXER_READ_DEVMASK:
1382 return IOCTL_OUT(arg,
1383 SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
1384 (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0));
1385 case SOUND_MIXER_READ_STEREODEVS:
1386 return IOCTL_OUT(arg, SOUND_MASK_VOLUME);
1387 case SOUND_MIXER_READ_VOLUME:
1388 return IOCTL_OUT(arg,
1389 VOLUME_DB_TO_VOXWARE(dmasound.volume_left) |
1390 (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8));
1391 case SOUND_MIXER_READ_BASS:
1392 return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.bass));
1393 case SOUND_MIXER_READ_TREBLE:
1394 return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.treble));
1395 case SOUND_MIXER_READ_OGAIN:
1396 return IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(dmasound.gain));
1397 case SOUND_MIXER_WRITE_BASS:
1398 IOCTL_IN(arg, data);
1399 return IOCTL_OUT(arg, dmasound_set_bass(data));
1400 case SOUND_MIXER_WRITE_TREBLE:
1401 IOCTL_IN(arg, data);
1402 return IOCTL_OUT(arg, dmasound_set_treble(data));
1403 case SOUND_MIXER_WRITE_OGAIN:
1404 IOCTL_IN(arg, data);
1405 return IOCTL_OUT(arg, dmasound_set_gain(data));
1406 }
1407 return AtaMixerIoctl(cmd, arg);
1408}
1409
1410static int FalconMixerIoctl(u_int cmd, u_long arg)
1411{
1412 int data;
1413 switch (cmd) {
1414 case SOUND_MIXER_READ_RECMASK:
1415 return IOCTL_OUT(arg, SOUND_MASK_MIC);
1416 case SOUND_MIXER_READ_DEVMASK:
1417 return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER);
1418 case SOUND_MIXER_READ_STEREODEVS:
1419 return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC);
1420 case SOUND_MIXER_READ_VOLUME:
1421 return IOCTL_OUT(arg,
1422 VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) |
1423 VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8);
1424 case SOUND_MIXER_READ_CAPS:
1425 return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT);
1426 case SOUND_MIXER_WRITE_MIC:
1427 IOCTL_IN(arg, data);
1428 tt_dmasnd.input_gain =
1429 RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 |
1430 RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff);
1431 /* fall thru, return set value */
1432 case SOUND_MIXER_READ_MIC:
1433 return IOCTL_OUT(arg,
1434 RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |
1435 RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8);
1436 }
1437 return AtaMixerIoctl(cmd, arg);
1438}
1439
1440static int AtaWriteSqSetup(void)
1441{
1442 write_sq_ignore_int = 0;
1443 return 0 ;
1444}
1445
1446static int AtaSqOpen(mode_t mode)
1447{
1448 write_sq_ignore_int = 1;
1449 return 0 ;
1450}
1451
1452static int TTStateInfo(char *buffer, size_t space)
1453{
1454 int len = 0;
1455 len += sprintf(buffer+len, "\tvol left %ddB [-40... 0]\n",
1456 dmasound.volume_left);
1457 len += sprintf(buffer+len, "\tvol right %ddB [-40... 0]\n",
1458 dmasound.volume_right);
1459 len += sprintf(buffer+len, "\tbass %ddB [-12...+12]\n",
1460 dmasound.bass);
1461 len += sprintf(buffer+len, "\ttreble %ddB [-12...+12]\n",
1462 dmasound.treble);
1463 if (len >= space) {
1464 printk(KERN_ERR "dmasound_atari: overflowed state buffer alloc.\n") ;
1465 len = space ;
1466 }
1467 return len;
1468}
1469
1470static int FalconStateInfo(char *buffer, size_t space)
1471{
1472 int len = 0;
1473 len += sprintf(buffer+len, "\tvol left %ddB [-22.5 ... 0]\n",
1474 dmasound.volume_left);
1475 len += sprintf(buffer+len, "\tvol right %ddB [-22.5 ... 0]\n",
1476 dmasound.volume_right);
1477 if (len >= space) {
1478 printk(KERN_ERR "dmasound_atari: overflowed state buffer alloc.\n") ;
1479 len = space ;
1480 }
1481 return len;
1482}
1483
1484
1485/*** Machine definitions *****************************************************/
1486
1487static SETTINGS def_hard_falcon = {
1488 .format = AFMT_S8,
1489 .stereo = 0,
1490 .size = 8,
1491 .speed = 8195
1492} ;
1493
1494static SETTINGS def_hard_tt = {
1495 .format = AFMT_S8,
1496 .stereo = 0,
1497 .size = 8,
1498 .speed = 12517
1499} ;
1500
1501static SETTINGS def_soft = {
1502 .format = AFMT_U8,
1503 .stereo = 0,
1504 .size = 8,
1505 .speed = 8000
1506} ;
1507
1508static MACHINE machTT = {
1509 .name = "Atari",
1510 .name2 = "TT",
1511 .owner = THIS_MODULE,
1512 .dma_alloc = AtaAlloc,
1513 .dma_free = AtaFree,
1514 .irqinit = AtaIrqInit,
1515#ifdef MODULE
1516 .irqcleanup = AtaIrqCleanUp,
1517#endif /* MODULE */
1518 .init = TTInit,
1519 .silence = TTSilence,
1520 .setFormat = TTSetFormat,
1521 .setVolume = TTSetVolume,
1522 .setBass = AtaSetBass,
1523 .setTreble = AtaSetTreble,
1524 .setGain = TTSetGain,
1525 .play = AtaPlay,
1526 .mixer_init = TTMixerInit,
1527 .mixer_ioctl = TTMixerIoctl,
1528 .write_sq_setup = AtaWriteSqSetup,
1529 .sq_open = AtaSqOpen,
1530 .state_info = TTStateInfo,
1531 .min_dsp_speed = 6258,
1532 .version = ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION),
1533 .hardware_afmts = AFMT_S8, /* h'ware-supported formats *only* here */
1534 .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */
1535};
1536
1537static MACHINE machFalcon = {
1538 .name = "Atari",
1539 .name2 = "FALCON",
1540 .dma_alloc = AtaAlloc,
1541 .dma_free = AtaFree,
1542 .irqinit = AtaIrqInit,
1543#ifdef MODULE
1544 .irqcleanup = AtaIrqCleanUp,
1545#endif /* MODULE */
1546 .init = FalconInit,
1547 .silence = FalconSilence,
1548 .setFormat = FalconSetFormat,
1549 .setVolume = FalconSetVolume,
1550 .setBass = AtaSetBass,
1551 .setTreble = AtaSetTreble,
1552 .play = AtaPlay,
1553 .mixer_init = FalconMixerInit,
1554 .mixer_ioctl = FalconMixerIoctl,
1555 .write_sq_setup = AtaWriteSqSetup,
1556 .sq_open = AtaSqOpen,
1557 .state_info = FalconStateInfo,
1558 .min_dsp_speed = 8195,
1559 .version = ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION),
1560 .hardware_afmts = (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */
1561 .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */
1562};
1563
1564
1565/*** Config & Setup **********************************************************/
1566
1567
1568static int __init dmasound_atari_init(void)
1569{
1570 if (MACH_IS_ATARI && ATARIHW_PRESENT(PCM_8BIT)) {
1571 if (ATARIHW_PRESENT(CODEC)) {
1572 dmasound.mach = machFalcon;
1573 dmasound.mach.default_soft = def_soft ;
1574 dmasound.mach.default_hard = def_hard_falcon ;
1575 is_falcon = 1;
1576 } else if (ATARIHW_PRESENT(MICROWIRE)) {
1577 dmasound.mach = machTT;
1578 dmasound.mach.default_soft = def_soft ;
1579 dmasound.mach.default_hard = def_hard_tt ;
1580 is_falcon = 0;
1581 } else
1582 return -ENODEV;
1583 if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0)
1584 return dmasound_init();
1585 else {
1586 printk("DMA sound driver: Timer A interrupt already in use\n");
1587 return -EBUSY;
1588 }
1589 }
1590 return -ENODEV;
1591}
1592
1593static void __exit dmasound_atari_cleanup(void)
1594{
1595 dmasound_deinit();
1596}
1597
1598module_init(dmasound_atari_init);
1599module_exit(dmasound_atari_cleanup);
1600MODULE_LICENSE("GPL");