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