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