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