]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - sound/oss/dmasound/dmasound_atari.c
ALSA: Use fallthrough pseudo-keyword
[mirror_ubuntu-hirsute-kernel.git] / sound / oss / dmasound / dmasound_atari.c
CommitLineData
09c434b8 1// SPDX-License-Identifier: GPL-2.0-only
1da177e4
LT
2/*
3 * linux/sound/oss/dmasound/dmasound_atari.c
4 *
5 * Atari TT and Falcon DMA Sound Driver
6 *
7 * See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits
8 * prior to 28/01/2001
9 *
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.
15 */
16
17
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>
25
7c0f6ba6 26#include <linux/uaccess.h>
1da177e4
LT
27#include <asm/atariints.h>
28#include <asm/atari_stram.h>
29
30#include "dmasound.h"
31
32#define DMASOUND_ATARI_REVISION 0
33#define DMASOUND_ATARI_EDITION 3
34
35extern void atari_microwire_cmd(int cmd);
36
37static int is_falcon;
38static int write_sq_ignore_int; /* ++TeSche: used for Falcon */
39
40static int expand_bal; /* Balance factor for expanding (not volume!) */
41static int expand_data; /* Data for expanding */
42
43
44/*** Translations ************************************************************/
45
46
47/* ++TeSche: radically changed for new expanding purposes...
48 *
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.
57 *
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. :)
63 *
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!
67 *
68 * ++geert: split in even more functions (one per format)
69 */
70
031eb4cd 71static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
72 u_char frame[], ssize_t *frameUsed,
73 ssize_t frameLeft);
031eb4cd 74static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
75 u_char frame[], ssize_t *frameUsed,
76 ssize_t frameLeft);
031eb4cd 77static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
78 u_char frame[], ssize_t *frameUsed,
79 ssize_t frameLeft);
031eb4cd 80static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
81 u_char frame[], ssize_t *frameUsed,
82 ssize_t frameLeft);
031eb4cd 83static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
84 u_char frame[], ssize_t *frameUsed,
85 ssize_t frameLeft);
031eb4cd 86static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
87 u_char frame[], ssize_t *frameUsed,
88 ssize_t frameLeft);
031eb4cd 89static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
90 u_char frame[], ssize_t *frameUsed,
91 ssize_t frameLeft);
031eb4cd 92static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
93 u_char frame[], ssize_t *frameUsed,
94 ssize_t frameLeft);
031eb4cd 95static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
96 u_char frame[], ssize_t *frameUsed,
97 ssize_t frameLeft);
031eb4cd 98static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
99 u_char frame[], ssize_t *frameUsed,
100 ssize_t frameLeft);
031eb4cd 101static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
102 u_char frame[], ssize_t *frameUsed,
103 ssize_t frameLeft);
031eb4cd 104static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
105 u_char frame[], ssize_t *frameUsed,
106 ssize_t frameLeft);
031eb4cd 107static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
108 u_char frame[], ssize_t *frameUsed,
109 ssize_t frameLeft);
031eb4cd 110static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
111 u_char frame[], ssize_t *frameUsed,
112 ssize_t frameLeft);
113
114
115/*** Low level stuff *********************************************************/
116
117
1ef64e67 118static void *AtaAlloc(unsigned int size, gfp_t flags);
1da177e4
LT
119static void AtaFree(void *, unsigned int size);
120static int AtaIrqInit(void);
121#ifdef MODULE
122static void AtaIrqCleanUp(void);
123#endif /* MODULE */
124static int AtaSetBass(int bass);
125static int AtaSetTreble(int treble);
126static void TTSilence(void);
127static void TTInit(void);
128static int TTSetFormat(int format);
129static int TTSetVolume(int volume);
130static int TTSetGain(int gain);
131static void FalconSilence(void);
132static void FalconInit(void);
133static int FalconSetFormat(int format);
134static int FalconSetVolume(int volume);
135static void AtaPlayNextFrame(int index);
136static void AtaPlay(void);
7d12e780 137static irqreturn_t AtaInterrupt(int irq, void *dummy);
1da177e4
LT
138
139/*** Mid level stuff *********************************************************/
140
141static void TTMixerInit(void);
142static void FalconMixerInit(void);
143static int AtaMixerIoctl(u_int cmd, u_long arg);
144static int TTMixerIoctl(u_int cmd, u_long arg);
145static int FalconMixerIoctl(u_int cmd, u_long arg);
146static int AtaWriteSqSetup(void);
aeb5d727 147static int AtaSqOpen(fmode_t mode);
1da177e4
LT
148static int TTStateInfo(char *buffer, size_t space);
149static int FalconStateInfo(char *buffer, size_t space);
150
151
152/*** Translations ************************************************************/
153
154
031eb4cd 155static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
156 u_char frame[], ssize_t *frameUsed,
157 ssize_t frameLeft)
158{
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];
163
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--;
174 }
175 *frameUsed += used;
176 return used;
177}
178
179
031eb4cd 180static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
181 u_char frame[], ssize_t *frameUsed,
182 ssize_t frameLeft)
183{
184 ssize_t count, used;
185 void *p = &frame[*frameUsed];
186
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;
195}
196
197
031eb4cd 198static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
199 u_char frame[], ssize_t *frameUsed,
200 ssize_t frameLeft)
201{
202 ssize_t count, used;
203
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--;
214 }
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;
031eb4cd 221 if (get_user(data, (u_short __user *)userPtr))
1da177e4 222 return -EFAULT;
3756513d 223 userPtr += 2;
1da177e4
LT
224 *p++ = data ^ 0x8080;
225 count--;
226 }
227 }
228 *frameUsed += used;
229 return used;
230}
231
232
031eb4cd 233static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
234 u_char frame[], ssize_t *frameUsed,
235 ssize_t frameLeft)
236{
237 ssize_t count, used;
238
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;
031eb4cd 245 if (get_user(data, (u_short __user *)userPtr))
1da177e4 246 return -EFAULT;
3756513d 247 userPtr += 2;
1da177e4
LT
248 *p++ = data;
249 *p++ = data;
250 count--;
251 }
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;
260 }
261 return used;
262}
263
264
031eb4cd 265static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
266 u_char frame[], ssize_t *frameUsed,
267 ssize_t frameLeft)
268{
269 ssize_t count, used;
270
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;
031eb4cd 277 if (get_user(data, (u_short __user *)userPtr))
1da177e4 278 return -EFAULT;
3756513d 279 userPtr += 2;
1da177e4
LT
280 data ^= 0x8000;
281 *p++ = data;
282 *p++ = data;
283 count--;
284 }
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) {
031eb4cd
AV
291 u_int data;
292 if (get_user(data, (u_int __user *)userPtr))
1da177e4 293 return -EFAULT;
3756513d 294 userPtr += 4;
1da177e4
LT
295 *p++ = data ^ 0x80008000;
296 count--;
297 }
298 *frameUsed += used;
299 }
300 return used;
301}
302
303
031eb4cd 304static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
305 u_char frame[], ssize_t *frameUsed,
306 ssize_t frameLeft)
307{
308 ssize_t count, used;
309
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;
031eb4cd 317 if (get_user(data, (u_short __user *)userPtr))
1da177e4 318 return -EFAULT;
3756513d 319 userPtr += 2;
1da177e4
LT
320 data = le2be16(data);
321 *p++ = data;
322 *p++ = data;
323 count--;
324 }
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;
031eb4cd 332 if (get_user(data, (u_int __user *)userPtr))
1da177e4 333 return -EFAULT;
3756513d 334 userPtr += 4;
1da177e4
LT
335 data = le2be16dbl(data);
336 *p++ = data;
337 count--;
338 }
339 *frameUsed += used;
340 }
341 return used;
342}
343
344
031eb4cd 345static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
346 u_char frame[], ssize_t *frameUsed,
347 ssize_t frameLeft)
348{
349 ssize_t count, used;
350
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;
031eb4cd 358 if (get_user(data, (u_short __user *)userPtr))
1da177e4 359 return -EFAULT;
3756513d 360 userPtr += 2;
1da177e4
LT
361 data = le2be16(data) ^ 0x8000;
362 *p++ = data;
363 *p++ = data;
364 }
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;
031eb4cd 372 if (get_user(data, (u_int __user *)userPtr))
1da177e4 373 return -EFAULT;
3756513d 374 userPtr += 4;
1da177e4
LT
375 data = le2be16dbl(data) ^ 0x80008000;
376 *p++ = data;
377 count--;
378 }
379 *frameUsed += used;
380 }
381 return used;
382}
383
384
031eb4cd 385static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
386 u_char frame[], ssize_t *frameUsed,
387 ssize_t frameLeft)
388{
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;
395
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;
411 }
412 *p++ = data;
413 frameLeft--;
414 bal -= sSpeed;
415 }
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;
433 }
434 *p++ = data;
435 frameLeft -= 2;
436 bal -= sSpeed;
437 }
438 expand_data = data;
439 }
440 expand_bal = bal;
441 used -= userCount;
442 *frameUsed += usedf-frameLeft;
443 return used;
444}
445
446
031eb4cd 447static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
448 u_char frame[], ssize_t *frameUsed,
449 ssize_t frameLeft)
450{
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;
455
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;
469 }
470 *p++ = data;
471 frameLeft--;
472 bal -= sSpeed;
473 }
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;
031eb4cd 482 if (get_user(data, (u_short __user *)userPtr))
1da177e4 483 return -EFAULT;
3756513d 484 userPtr += 2;
1da177e4
LT
485 userCount -= 2;
486 bal += hSpeed;
487 }
488 *p++ = data;
489 frameLeft -= 2;
490 bal -= sSpeed;
491 }
492 expand_data = data;
493 }
494 expand_bal = bal;
495 used -= userCount;
496 *frameUsed += usedf-frameLeft;
497 return used;
498}
499
500
031eb4cd 501static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
502 u_char frame[], ssize_t *frameUsed,
503 ssize_t frameLeft)
504{
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;
509
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;
524 }
525 *p++ = data;
526 frameLeft--;
527 bal -= sSpeed;
528 }
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;
031eb4cd 537 if (get_user(data, (u_short __user *)userPtr))
1da177e4 538 return -EFAULT;
3756513d 539 userPtr += 2;
1da177e4
LT
540 data ^= 0x8080;
541 userCount -= 2;
542 bal += hSpeed;
543 }
544 *p++ = data;
545 frameLeft -= 2;
546 bal -= sSpeed;
547 }
548 expand_data = data;
549 }
550 expand_bal = bal;
551 used -= userCount;
552 *frameUsed += usedf-frameLeft;
553 return used;
554}
555
556
031eb4cd 557static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
558 u_char frame[], ssize_t *frameUsed,
559 ssize_t frameLeft)
560{
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;
565
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;
031eb4cd 575 if (get_user(data, (u_short __user *)userPtr))
1da177e4 576 return -EFAULT;
3756513d 577 userPtr += 2;
1da177e4
LT
578 userCount -= 2;
579 bal += hSpeed;
580 }
581 *p++ = data;
582 *p++ = data;
583 frameLeft -= 4;
584 bal -= sSpeed;
585 }
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;
031eb4cd 594 if (get_user(data, (u_int __user *)userPtr))
1da177e4 595 return -EFAULT;
3756513d 596 userPtr += 4;
1da177e4
LT
597 userCount -= 4;
598 bal += hSpeed;
599 }
600 *p++ = data;
601 frameLeft -= 4;
602 bal -= sSpeed;
603 }
604 expand_data = data;
605 }
606 expand_bal = bal;
607 used -= userCount;
608 *frameUsed += usedf-frameLeft;
609 return used;
610}
611
612
031eb4cd 613static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
614 u_char frame[], ssize_t *frameUsed,
615 ssize_t frameLeft)
616{
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;
621
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;
031eb4cd 631 if (get_user(data, (u_short __user *)userPtr))
1da177e4 632 return -EFAULT;
3756513d 633 userPtr += 2;
1da177e4
LT
634 data ^= 0x8000;
635 userCount -= 2;
636 bal += hSpeed;
637 }
638 *p++ = data;
639 *p++ = data;
640 frameLeft -= 4;
641 bal -= sSpeed;
642 }
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;
031eb4cd 651 if (get_user(data, (u_int __user *)userPtr))
1da177e4 652 return -EFAULT;
3756513d 653 userPtr += 4;
1da177e4
LT
654 data ^= 0x80008000;
655 userCount -= 4;
656 bal += hSpeed;
657 }
658 *p++ = data;
659 frameLeft -= 4;
660 bal -= sSpeed;
661 }
662 expand_data = data;
663 }
664 expand_bal = bal;
665 used -= userCount;
666 *frameUsed += usedf-frameLeft;
667 return used;
668}
669
670
031eb4cd 671static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
672 u_char frame[], ssize_t *frameUsed,
673 ssize_t frameLeft)
674{
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;
679
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;
031eb4cd 689 if (get_user(data, (u_short __user *)userPtr))
1da177e4 690 return -EFAULT;
3756513d 691 userPtr += 2;
1da177e4
LT
692 data = le2be16(data);
693 userCount -= 2;
694 bal += hSpeed;
695 }
696 *p++ = data;
697 *p++ = data;
698 frameLeft -= 4;
699 bal -= sSpeed;
700 }
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;
031eb4cd 709 if (get_user(data, (u_int __user *)userPtr))
1da177e4 710 return -EFAULT;
3756513d 711 userPtr += 4;
1da177e4
LT
712 data = le2be16dbl(data);
713 userCount -= 4;
714 bal += hSpeed;
715 }
716 *p++ = data;
717 frameLeft -= 4;
718 bal -= sSpeed;
719 }
720 expand_data = data;
721 }
722 expand_bal = bal;
723 used -= userCount;
724 *frameUsed += usedf-frameLeft;
725 return used;
726}
727
728
031eb4cd 729static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount,
1da177e4
LT
730 u_char frame[], ssize_t *frameUsed,
731 ssize_t frameLeft)
732{
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;
737
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;
031eb4cd 747 if (get_user(data, (u_short __user *)userPtr))
1da177e4 748 return -EFAULT;
3756513d 749 userPtr += 2;
1da177e4
LT
750 data = le2be16(data) ^ 0x8000;
751 userCount -= 2;
752 bal += hSpeed;
753 }
754 *p++ = data;
755 *p++ = data;
756 frameLeft -= 4;
757 bal -= sSpeed;
758 }
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;
031eb4cd 767 if (get_user(data, (u_int __user *)userPtr))
1da177e4 768 return -EFAULT;
3756513d 769 userPtr += 4;
1da177e4
LT
770 data = le2be16dbl(data) ^ 0x80008000;
771 userCount -= 4;
772 bal += hSpeed;
773 }
774 *p++ = data;
775 frameLeft -= 4;
776 bal -= sSpeed;
777 }
778 expand_data = data;
779 }
780 expand_bal = bal;
781 used -= userCount;
782 *frameUsed += usedf-frameLeft;
783 return used;
784}
785
786
787static 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,
792};
793
794static 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,
799};
800
801static 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
810};
811
812static 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,
821};
822
823
824/*** Low level stuff *********************************************************/
825
826
827
828/*
829 * Atari (TT/Falcon)
830 */
831
1ef64e67 832static void *AtaAlloc(unsigned int size, gfp_t flags)
1da177e4
LT
833{
834 return atari_stram_alloc(size, "dmasound");
835}
836
837static void AtaFree(void *obj, unsigned int size)
838{
839 atari_stram_free( obj );
840}
841
842static int __init AtaIrqInit(void)
843{
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. */
3d92e8f3
GU
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. */
1da177e4 854 /* Register interrupt handler. */
80dbb01a 855 if (request_irq(IRQ_MFP_TIMA, AtaInterrupt, 0, "DMA sound",
89bde7b8
GU
856 AtaInterrupt))
857 return 0;
3d92e8f3
GU
858 st_mfp.int_en_a |= 0x20; /* Turn interrupt on. */
859 st_mfp.int_mk_a |= 0x20;
1da177e4
LT
860 return 1;
861}
862
863#ifdef MODULE
864static void AtaIrqCleanUp(void)
865{
3d92e8f3
GU
866 st_mfp.tim_ct_a = 0; /* stop timer */
867 st_mfp.int_en_a &= ~0x20; /* turn interrupt off */
1da177e4
LT
868 free_irq(IRQ_MFP_TIMA, AtaInterrupt);
869}
870#endif /* MODULE */
871
872
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)
876
877
878static int AtaSetBass(int bass)
879{
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);
883}
884
885
886static int AtaSetTreble(int treble)
887{
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);
891}
892
893
894
895/*
896 * TT
897 */
898
899
900static void TTSilence(void)
901{
902 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
903 atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */
904}
905
906
907static void TTInit(void)
908{
909 int mode, i, idx;
910 const int freq[4] = {50066, 25033, 12517, 6258};
911
912 /* search a frequency that fits into the allowed error range */
913
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.
918 */
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;
926
927 TTSilence();
928 dmasound.hard = dmasound.soft;
929
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;
947 }
948
949 tt_dmasnd.mode = (dmasound.hard.stereo ?
950 DMASND_MODE_STEREO : DMASND_MODE_MONO) |
951 DMASND_MODE_8BIT | mode;
952
953 expand_bal = -dmasound.soft.speed;
954}
955
956
957static int TTSetFormat(int format)
958{
959 /* TT sound DMA supports only 8bit modes */
960
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;
971 }
972
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;
978 }
979 TTInit();
980
981 return format;
982}
983
984
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)
988
989
990static int TTSetVolume(int volume)
991{
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);
998}
999
1000
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)
1004
1005static int TTSetGain(int gain)
1006{
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);
1010}
1011
1012
1013
1014/*
1015 * Falcon
1016 */
1017
1018
1019static void FalconSilence(void)
1020{
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 */
1030}
1031
1032
1033static void FalconInit(void)
1034{
1035 int divider, i, idx;
1036 const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};
1037
1038 /* search a frequency that fits into the allowed error range */
1039
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
1045 */
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;
1053
1054 FalconSilence();
1055 dmasound.hard = dmasound.soft;
1056
1057 if (dmasound.hard.size == 16) {
1058 /* the Falcon can play 16bit samples only in stereo */
1059 dmasound.hard.stereo = 1;
1060 }
1061
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;
1091 }
1092 tt_dmasnd.int_div = divider;
1093
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 */
1102
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;
1108
1109 expand_bal = -dmasound.soft.speed;
1110}
1111
1112
1113static int FalconSetFormat(int format)
1114{
1115 int size;
1116 /* Falcon sound DMA supports 8bit and 16bit modes */
1117
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;
1136 }
1137
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;
1143 }
1144
1145 FalconInit();
1146
1147 return format;
1148}
1149
1150
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.
1153 */
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)
1157
1158
1159static int FalconSetVolume(int volume)
1160{
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;
1166}
1167
1168
1169static void AtaPlayNextFrame(int index)
1170{
1171 char *start, *end;
1172
1173 /* used by AtaPlay() if all doubts whether there really is something
1174 * to be played are already wiped out.
1175 */
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;
1187}
1188
1189
1190static void AtaPlay(void)
1191{
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).
1195 *
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!
1204 */
1205 atari_disable_irq(IRQ_MFP_TIMA);
1206
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;
1211 }
1212
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).
1216 */
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?
1222 */
1223 atari_enable_irq(IRQ_MFP_TIMA);
1224 return;
1225 }
1226 AtaPlayNextFrame(1);
1227 if (write_sq.count == 1) {
1228 /* no more frames */
1229 atari_enable_irq(IRQ_MFP_TIMA);
1230 return;
1231 }
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?
1237 */
1238 atari_enable_irq(IRQ_MFP_TIMA);
1239 return;
1240 }
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.
1246 */
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?
1252 */
1253 atari_enable_irq(IRQ_MFP_TIMA);
1254 return;
1255 }
1256 AtaPlayNextFrame(2);
1257 }
1258 atari_enable_irq(IRQ_MFP_TIMA);
1259}
1260
1261
7d12e780 1262static irqreturn_t AtaInterrupt(int irq, void *dummy)
1da177e4
LT
1263{
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;
1272 }
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.
1279 */
1280 write_sq_ignore_int = 0;
1efddcc9 1281 goto out;
1da177e4
LT
1282 }
1283
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.
1287 */
1288 WAKE_UP(write_sq.sync_queue);
1efddcc9 1289 goto out;
1da177e4
LT
1290 }
1291
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.
1298 */
1299 write_sq.count--;
1300 write_sq.active--;
1301
1302 if (!write_sq.active) {
1303 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1304 write_sq_ignore_int = 1;
1305 }
1306
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. */
1311
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.
1319 */
1320 AtaPlay();
1321
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. */
1efddcc9 1326out:
1da177e4
LT
1327 spin_unlock(&dmasound.lock);
1328 return IRQ_HANDLED;
1329}
1330
1331
1332/*** Mid level stuff *********************************************************/
1333
1334
1335/*
1336 * /dev/mixer abstraction
1337 */
1338
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)
1342
1343
1344static void __init TTMixerInit(void)
1345{
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));
1353}
1354
1355static void __init FalconMixerInit(void)
1356{
1357 dmasound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
1358 dmasound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
1359}
1360
1361static int AtaMixerIoctl(u_int cmd, u_long arg)
1362{
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);
1374 }
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);
1390 }
1391 }
1392 return -EINVAL;
1393}
1394
1395
1396static int TTMixerIoctl(u_int cmd, u_long arg)
1397{
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));
1427 }
1428 return AtaMixerIoctl(cmd, arg);
1429}
1430
1431static int FalconMixerIoctl(u_int cmd, u_long arg)
1432{
1433 int data;
1434 switch (cmd) {
8e774e02 1435 case SOUND_MIXER_READ_RECMASK:
1da177e4 1436 return IOCTL_OUT(arg, SOUND_MASK_MIC);
8e774e02 1437 case SOUND_MIXER_READ_DEVMASK:
1da177e4 1438 return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER);
8e774e02 1439 case SOUND_MIXER_READ_STEREODEVS:
1da177e4 1440 return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC);
8e774e02 1441 case SOUND_MIXER_READ_VOLUME:
1da177e4
LT
1442 return IOCTL_OUT(arg,
1443 VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) |
1444 VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8);
8e774e02 1445 case SOUND_MIXER_READ_CAPS:
1da177e4 1446 return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT);
8e774e02 1447 case SOUND_MIXER_WRITE_MIC:
1da177e4
LT
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);
c0dbbdad 1452 fallthrough; /* return set value */
8e774e02 1453 case SOUND_MIXER_READ_MIC:
1da177e4
LT
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);
1457 }
1458 return AtaMixerIoctl(cmd, arg);
1459}
1460
1461static int AtaWriteSqSetup(void)
1462{
1463 write_sq_ignore_int = 0;
1464 return 0 ;
1465}
1466
aeb5d727 1467static int AtaSqOpen(fmode_t mode)
1da177e4
LT
1468{
1469 write_sq_ignore_int = 1;
1470 return 0 ;
1471}
1472
1473static int TTStateInfo(char *buffer, size_t space)
1474{
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 ;
1487 }
1488 return len;
1489}
1490
1491static int FalconStateInfo(char *buffer, size_t space)
1492{
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 ;
1501 }
1502 return len;
1503}
1504
1505
1506/*** Machine definitions *****************************************************/
1507
1508static SETTINGS def_hard_falcon = {
1509 .format = AFMT_S8,
1510 .stereo = 0,
1511 .size = 8,
1512 .speed = 8195
1513} ;
1514
1515static SETTINGS def_hard_tt = {
1516 .format = AFMT_S8,
1517 .stereo = 0,
1518 .size = 8,
1519 .speed = 12517
1520} ;
1521
1522static SETTINGS def_soft = {
1523 .format = AFMT_U8,
1524 .stereo = 0,
1525 .size = 8,
1526 .speed = 8000
1527} ;
1528
d497e3ab 1529static __initdata MACHINE machTT = {
1da177e4
LT
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 */
1556};
1557
d497e3ab 1558static __initdata MACHINE machFalcon = {
1da177e4
LT
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 */
1583};
1584
1585
1586/*** Config & Setup **********************************************************/
1587
1588
1589static int __init dmasound_atari_init(void)
1590{
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;
3d92e8f3 1604 if ((st_mfp.int_en_a & st_mfp.int_mk_a & 0x20) == 0)
1da177e4
LT
1605 return dmasound_init();
1606 else {
1607 printk("DMA sound driver: Timer A interrupt already in use\n");
1608 return -EBUSY;
1609 }
1610 }
1611 return -ENODEV;
1612}
1613
1614static void __exit dmasound_atari_cleanup(void)
1615{
1616 dmasound_deinit();
1617}
1618
1619module_init(dmasound_atari_init);
1620module_exit(dmasound_atari_cleanup);
1621MODULE_LICENSE("GPL");