~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/oss/dmasound/dmasound_atari.c

Version: ~ [ linux-5.8-rc3 ] ~ [ linux-5.7.5 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.48 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.129 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.185 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.228 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.228 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  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 
 26 #include <linux/uaccess.h>
 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 
 35 extern void atari_microwire_cmd(int cmd);
 36 
 37 static int is_falcon;
 38 static int write_sq_ignore_int; /* ++TeSche: used for Falcon */
 39 
 40 static int expand_bal;  /* Balance factor for expanding (not volume!) */
 41 static 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 
 71 static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount,
 72                           u_char frame[], ssize_t *frameUsed,
 73                           ssize_t frameLeft);
 74 static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount,
 75                          u_char frame[], ssize_t *frameUsed,
 76                          ssize_t frameLeft);
 77 static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount,
 78                          u_char frame[], ssize_t *frameUsed,
 79                          ssize_t frameLeft);
 80 static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount,
 81                             u_char frame[], ssize_t *frameUsed,
 82                             ssize_t frameLeft);
 83 static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount,
 84                             u_char frame[], ssize_t *frameUsed,
 85                             ssize_t frameLeft);
 86 static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount,
 87                             u_char frame[], ssize_t *frameUsed,
 88                             ssize_t frameLeft);
 89 static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount,
 90                             u_char frame[], ssize_t *frameUsed,
 91                             ssize_t frameLeft);
 92 static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount,
 93                            u_char frame[], ssize_t *frameUsed,
 94                            ssize_t frameLeft);
 95 static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount,
 96                           u_char frame[], ssize_t *frameUsed,
 97                           ssize_t frameLeft);
 98 static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount,
 99                           u_char frame[], ssize_t *frameUsed,
100                           ssize_t frameLeft);
101 static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount,
102                              u_char frame[], ssize_t *frameUsed,
103                              ssize_t frameLeft);
104 static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount,
105                              u_char frame[], ssize_t *frameUsed,
106                              ssize_t frameLeft);
107 static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount,
108                              u_char frame[], ssize_t *frameUsed,
109                              ssize_t frameLeft);
110 static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount,
111                              u_char frame[], ssize_t *frameUsed,
112                              ssize_t frameLeft);
113 
114 
115 /*** Low level stuff *********************************************************/
116 
117 
118 static void *AtaAlloc(unsigned int size, gfp_t flags);
119 static void AtaFree(void *, unsigned int size);
120 static int AtaIrqInit(void);
121 #ifdef MODULE
122 static void AtaIrqCleanUp(void);
123 #endif /* MODULE */
124 static int AtaSetBass(int bass);
125 static int AtaSetTreble(int treble);
126 static void TTSilence(void);
127 static void TTInit(void);
128 static int TTSetFormat(int format);
129 static int TTSetVolume(int volume);
130 static int TTSetGain(int gain);
131 static void FalconSilence(void);
132 static void FalconInit(void);
133 static int FalconSetFormat(int format);
134 static int FalconSetVolume(int volume);
135 static void AtaPlayNextFrame(int index);
136 static void AtaPlay(void);
137 static irqreturn_t AtaInterrupt(int irq, void *dummy);
138 
139 /*** Mid level stuff *********************************************************/
140 
141 static void TTMixerInit(void);
142 static void FalconMixerInit(void);
143 static int AtaMixerIoctl(u_int cmd, u_long arg);
144 static int TTMixerIoctl(u_int cmd, u_long arg);
145 static int FalconMixerIoctl(u_int cmd, u_long arg);
146 static int AtaWriteSqSetup(void);
147 static int AtaSqOpen(fmode_t mode);
148 static int TTStateInfo(char *buffer, size_t space);
149 static int FalconStateInfo(char *buffer, size_t space);
150 
151 
152 /*** Translations ************************************************************/
153 
154 
155 static ssize_t ata_ct_law(const u_char __user *userPtr, size_t userCount,
156                           u_char frame[], ssize_t *frameUsed,
157                           ssize_t frameLeft)
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 
180 static ssize_t ata_ct_s8(const u_char __user *userPtr, size_t userCount,
181                          u_char frame[], ssize_t *frameUsed,
182                          ssize_t frameLeft)
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 
198 static ssize_t ata_ct_u8(const u_char __user *userPtr, size_t userCount,
199                          u_char frame[], ssize_t *frameUsed,
200                          ssize_t frameLeft)
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;
221                         if (get_user(data, (u_short __user *)userPtr))
222                                 return -EFAULT;
223                         userPtr += 2;
224                         *p++ = data ^ 0x8080;
225                         count--;
226                 }
227         }
228         *frameUsed += used;
229         return used;
230 }
231 
232 
233 static ssize_t ata_ct_s16be(const u_char __user *userPtr, size_t userCount,
234                             u_char frame[], ssize_t *frameUsed,
235                             ssize_t frameLeft)
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;
245                         if (get_user(data, (u_short __user *)userPtr))
246                                 return -EFAULT;
247                         userPtr += 2;
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 
265 static ssize_t ata_ct_u16be(const u_char __user *userPtr, size_t userCount,
266                             u_char frame[], ssize_t *frameUsed,
267                             ssize_t frameLeft)
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;
277                         if (get_user(data, (u_short __user *)userPtr))
278                                 return -EFAULT;
279                         userPtr += 2;
280                         data ^= 0x8000;
281                         *p++ = data;
282                         *p++ = data;
283                         count--;
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) {
291                         u_int data;
292                         if (get_user(data, (u_int __user *)userPtr))
293                                 return -EFAULT;
294                         userPtr += 4;
295                         *p++ = data ^ 0x80008000;
296                         count--;
297                 }
298                 *frameUsed += used;
299         }
300         return used;
301 }
302 
303 
304 static ssize_t ata_ct_s16le(const u_char __user *userPtr, size_t userCount,
305                             u_char frame[], ssize_t *frameUsed,
306                             ssize_t frameLeft)
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;
317                         if (get_user(data, (u_short __user *)userPtr))
318                                 return -EFAULT;
319                         userPtr += 2;
320                         data = le2be16(data);
321                         *p++ = data;
322                         *p++ = data;
323                         count--;
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;
332                         if (get_user(data, (u_int __user *)userPtr))
333                                 return -EFAULT;
334                         userPtr += 4;
335                         data = le2be16dbl(data);
336                         *p++ = data;
337                         count--;
338                 }
339                 *frameUsed += used;
340         }
341         return used;
342 }
343 
344 
345 static ssize_t ata_ct_u16le(const u_char __user *userPtr, size_t userCount,
346                             u_char frame[], ssize_t *frameUsed,
347                             ssize_t frameLeft)
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;
358                         if (get_user(data, (u_short __user *)userPtr))
359                                 return -EFAULT;
360                         userPtr += 2;
361                         data = le2be16(data) ^ 0x8000;
362                         *p++ = data;
363                         *p++ = data;
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;
372                         if (get_user(data, (u_int __user *)userPtr))
373                                 return -EFAULT;
374                         userPtr += 4;
375                         data = le2be16dbl(data) ^ 0x80008000;
376                         *p++ = data;
377                         count--;
378                 }
379                 *frameUsed += used;
380         }
381         return used;
382 }
383 
384 
385 static ssize_t ata_ctx_law(const u_char __user *userPtr, size_t userCount,
386                            u_char frame[], ssize_t *frameUsed,
387                            ssize_t frameLeft)
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 
447 static ssize_t ata_ctx_s8(const u_char __user *userPtr, size_t userCount,
448                           u_char frame[], ssize_t *frameUsed,
449                           ssize_t frameLeft)
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;
482                                 if (get_user(data, (u_short __user *)userPtr))
483                                         return -EFAULT;
484                                 userPtr += 2;
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 
501 static ssize_t ata_ctx_u8(const u_char __user *userPtr, size_t userCount,
502                           u_char frame[], ssize_t *frameUsed,
503                           ssize_t frameLeft)
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;
537                                 if (get_user(data, (u_short __user *)userPtr))
538                                         return -EFAULT;
539                                 userPtr += 2;
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 
557 static ssize_t ata_ctx_s16be(const u_char __user *userPtr, size_t userCount,
558                              u_char frame[], ssize_t *frameUsed,
559                              ssize_t frameLeft)
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;
575                                 if (get_user(data, (u_short __user *)userPtr))
576                                         return -EFAULT;
577                                 userPtr += 2;
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;
594                                 if (get_user(data, (u_int __user *)userPtr))
595                                         return -EFAULT;
596                                 userPtr += 4;
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 
613 static ssize_t ata_ctx_u16be(const u_char __user *userPtr, size_t userCount,
614                              u_char frame[], ssize_t *frameUsed,
615                              ssize_t frameLeft)
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;
631                                 if (get_user(data, (u_short __user *)userPtr))
632                                         return -EFAULT;
633                                 userPtr += 2;
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;
651                                 if (get_user(data, (u_int __user *)userPtr))
652                                         return -EFAULT;
653                                 userPtr += 4;
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 
671 static ssize_t ata_ctx_s16le(const u_char __user *userPtr, size_t userCount,
672                              u_char frame[], ssize_t *frameUsed,
673                              ssize_t frameLeft)
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;
689                                 if (get_user(data, (u_short __user *)userPtr))
690                                         return -EFAULT;
691                                 userPtr += 2;
692                                 data = le2be16(data);
693                                 userCount -= 2;
694                                 bal += hSpeed;
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;
709                                 if (get_user(data, (u_int __user *)userPtr))
710                                         return -EFAULT;
711                                 userPtr += 4;
712                                 data = le2be16dbl(data);
713                                 userCount -= 4;
714                                 bal += hSpeed;
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 
729 static ssize_t ata_ctx_u16le(const u_char __user *userPtr, size_t userCount,
730                              u_char frame[], ssize_t *frameUsed,
731                              ssize_t frameLeft)
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;
747                                 if (get_user(data, (u_short __user *)userPtr))
748                                         return -EFAULT;
749                                 userPtr += 2;
750                                 data = le2be16(data) ^ 0x8000;
751                                 userCount -= 2;
752                                 bal += hSpeed;
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;
767                                 if (get_user(data, (u_int __user *)userPtr))
768                                         return -EFAULT;
769                                 userPtr += 4;
770                                 data = le2be16dbl(data) ^ 0x80008000;
771                                 userCount -= 4;
772                                 bal += hSpeed;
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 
787 static TRANS transTTNormal = {
788         .ct_ulaw        = ata_ct_law,
789         .ct_alaw        = ata_ct_law,
790         .ct_s8          = ata_ct_s8,
791         .ct_u8          = ata_ct_u8,
792 };
793 
794 static TRANS transTTExpanding = {
795         .ct_ulaw        = ata_ctx_law,
796         .ct_alaw        = ata_ctx_law,
797         .ct_s8          = ata_ctx_s8,
798         .ct_u8          = ata_ctx_u8,
799 };
800 
801 static TRANS transFalconNormal = {
802         .ct_ulaw        = ata_ct_law,
803         .ct_alaw        = ata_ct_law,
804         .ct_s8          = ata_ct_s8,
805         .ct_u8          = ata_ct_u8,
806         .ct_s16be       = ata_ct_s16be,
807         .ct_u16be       = ata_ct_u16be,
808         .ct_s16le       = ata_ct_s16le,
809         .ct_u16le       = ata_ct_u16le
810 };
811 
812 static TRANS transFalconExpanding = {
813         .ct_ulaw        = ata_ctx_law,
814         .ct_alaw        = ata_ctx_law,
815         .ct_s8          = ata_ctx_s8,
816         .ct_u8          = ata_ctx_u8,
817         .ct_s16be       = ata_ctx_s16be,
818         .ct_u16be       = ata_ctx_u16be,
819         .ct_s16le       = ata_ctx_s16le,
820         .ct_u16le       = ata_ctx_u16le,
821 };
822 
823 
824 /*** Low level stuff *********************************************************/
825 
826 
827 
828 /*
829  * Atari (TT/Falcon)
830  */
831 
832 static void *AtaAlloc(unsigned int size, gfp_t flags)
833 {
834         return atari_stram_alloc(size, "dmasound");
835 }
836 
837 static void AtaFree(void *obj, unsigned int size)
838 {
839         atari_stram_free( obj );
840 }
841 
842 static 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. */
851         st_mfp.tim_ct_a = 0;    /* ++roman: Stop timer before programming! */
852         st_mfp.tim_dt_a = 1;    /* Cause interrupt after first event. */
853         st_mfp.tim_ct_a = 8;    /* Turn on event counting. */
854         /* Register interrupt handler. */
855         if (request_irq(IRQ_MFP_TIMA, AtaInterrupt, 0, "DMA sound",
856                         AtaInterrupt))
857                 return 0;
858         st_mfp.int_en_a |= 0x20;        /* Turn interrupt on. */
859         st_mfp.int_mk_a |= 0x20;
860         return 1;
861 }
862 
863 #ifdef MODULE
864 static void AtaIrqCleanUp(void)
865 {
866         st_mfp.tim_ct_a = 0;            /* stop timer */
867         st_mfp.int_en_a &= ~0x20;       /* turn interrupt off */
868         free_irq(IRQ_MFP_TIMA, AtaInterrupt);
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 
878 static 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 
886 static 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 
900 static 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 
907 static 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 
957 static 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 
990 static 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 
1005 static 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 
1019 static 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 
1033 static 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 
1113 static 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 
1159 static 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 
1169 static 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 
1190 static 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 
1262 static irqreturn_t AtaInterrupt(int irq, void *dummy)
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;
1281                 goto out;
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);
1289                 goto out;
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. */
1326 out:
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 
1344 static 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 
1355 static 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 
1361 static 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 
1396 static 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 
1431 static int FalconMixerIoctl(u_int cmd, u_long arg)
1432 {
1433         int data;
1434         switch (cmd) {
1435             case SOUND_MIXER_READ_RECMASK:
1436                 return IOCTL_OUT(arg, SOUND_MASK_MIC);
1437             case SOUND_MIXER_READ_DEVMASK:
1438                 return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER);
1439             case SOUND_MIXER_READ_STEREODEVS:
1440                 return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC);
1441             case SOUND_MIXER_READ_VOLUME:
1442                 return IOCTL_OUT(arg,
1443                         VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) |
1444                         VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8);
1445             case SOUND_MIXER_READ_CAPS:
1446                 return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT);
1447             case SOUND_MIXER_WRITE_MIC:
1448                 IOCTL_IN(arg, data);
1449                 tt_dmasnd.input_gain =
1450                         RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 |
1451                         RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff);
1452                 /* fall thru, return set value */
1453             case SOUND_MIXER_READ_MIC:
1454                 return IOCTL_OUT(arg,
1455                         RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |
1456                         RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8);
1457         }
1458         return AtaMixerIoctl(cmd, arg);
1459 }
1460 
1461 static int AtaWriteSqSetup(void)
1462 {
1463         write_sq_ignore_int = 0;
1464         return 0 ;
1465 }
1466 
1467 static int AtaSqOpen(fmode_t mode)
1468 {
1469         write_sq_ignore_int = 1;
1470         return 0 ;
1471 }
1472 
1473 static 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 
1491 static 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 
1508 static SETTINGS def_hard_falcon = {
1509         .format         = AFMT_S8,
1510         .stereo         = 0,
1511         .size           = 8,
1512         .speed          = 8195
1513 } ;
1514 
1515 static SETTINGS def_hard_tt = {
1516         .format = AFMT_S8,
1517         .stereo = 0,
1518         .size   = 8,
1519         .speed  = 12517
1520 } ;
1521 
1522 static SETTINGS def_soft = {
1523         .format = AFMT_U8,
1524         .stereo = 0,
1525         .size   = 8,
1526         .speed  = 8000
1527 } ;
1528 
1529 static __initdata MACHINE machTT = {
1530         .name           = "Atari",
1531         .name2          = "TT",
1532         .owner          = THIS_MODULE,
1533         .dma_alloc      = AtaAlloc,
1534         .dma_free       = AtaFree,
1535         .irqinit        = AtaIrqInit,
1536 #ifdef MODULE
1537         .irqcleanup     = AtaIrqCleanUp,
1538 #endif /* MODULE */
1539         .init           = TTInit,
1540         .silence        = TTSilence,
1541         .setFormat      = TTSetFormat,
1542         .setVolume      = TTSetVolume,
1543         .setBass        = AtaSetBass,
1544         .setTreble      = AtaSetTreble,
1545         .setGain        = TTSetGain,
1546         .play           = AtaPlay,
1547         .mixer_init     = TTMixerInit,
1548         .mixer_ioctl    = TTMixerIoctl,
1549         .write_sq_setup = AtaWriteSqSetup,
1550         .sq_open        = AtaSqOpen,
1551         .state_info     = TTStateInfo,
1552         .min_dsp_speed  = 6258,
1553         .version        = ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION),
1554         .hardware_afmts = AFMT_S8,  /* h'ware-supported formats *only* here */
1555         .capabilities   =  DSP_CAP_BATCH        /* As per SNDCTL_DSP_GETCAPS */
1556 };
1557 
1558 static __initdata MACHINE machFalcon = {
1559         .name           = "Atari",
1560         .name2          = "FALCON",
1561         .dma_alloc      = AtaAlloc,
1562         .dma_free       = AtaFree,
1563         .irqinit        = AtaIrqInit,
1564 #ifdef MODULE
1565         .irqcleanup     = AtaIrqCleanUp,
1566 #endif /* MODULE */
1567         .init           = FalconInit,
1568         .silence        = FalconSilence,
1569         .setFormat      = FalconSetFormat,
1570         .setVolume      = FalconSetVolume,
1571         .setBass        = AtaSetBass,
1572         .setTreble      = AtaSetTreble,
1573         .play           = AtaPlay,
1574         .mixer_init     = FalconMixerInit,
1575         .mixer_ioctl    = FalconMixerIoctl,
1576         .write_sq_setup = AtaWriteSqSetup,
1577         .sq_open        = AtaSqOpen,
1578         .state_info     = FalconStateInfo,
1579         .min_dsp_speed  = 8195,
1580         .version        = ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION),
1581         .hardware_afmts = (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */
1582         .capabilities   =  DSP_CAP_BATCH        /* As per SNDCTL_DSP_GETCAPS */
1583 };
1584 
1585 
1586 /*** Config & Setup **********************************************************/
1587 
1588 
1589 static 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;
1604             if ((st_mfp.int_en_a & st_mfp.int_mk_a & 0x20) == 0)
1605                 return dmasound_init();
1606             else {
1607                 printk("DMA sound driver: Timer A interrupt already in use\n");
1608                 return -EBUSY;
1609             }
1610         }
1611         return -ENODEV;
1612 }
1613 
1614 static void __exit dmasound_atari_cleanup(void)
1615 {
1616         dmasound_deinit();
1617 }
1618 
1619 module_init(dmasound_atari_init);
1620 module_exit(dmasound_atari_cleanup);
1621 MODULE_LICENSE("GPL");
1622 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp