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

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

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

~ [ 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