18 #include <linux/module.h>
22 #include <linux/soundcard.h>
26 #include <asm/uaccess.h>
27 #include <asm/setup.h>
30 #include <asm/machdep.h>
34 #define DMASOUND_PAULA_REVISION 0
35 #define DMASOUND_PAULA_EDITION 4
37 #define custom amiga_custom
58 #define AMI_AUDIO_OFF (DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3)
59 #define AMI_AUDIO_8 (DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1)
60 #define AMI_AUDIO_14 (AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3)
67 static int write_sq_block_size_half, write_sq_block_size_quarter;
74 static void AmiFree(
void *obj,
unsigned int size);
75 static int AmiIrqInit(
void);
77 static void AmiIrqCleanUp(
void);
79 static void AmiSilence(
void);
80 static void AmiInit(
void);
81 static int AmiSetFormat(
int format);
82 static int AmiSetVolume(
int volume);
83 static int AmiSetTreble(
int treble);
84 static void AmiPlayNextFrame(
int index);
85 static void AmiPlay(
void);
88 #ifdef CONFIG_HEARTBEAT
112 #define disable_heartbeat() do { } while (0)
113 #define enable_heartbeat() do { } while (0)
119 static void AmiMixerInit(
void);
121 static int AmiWriteSqSetup(
void);
122 static int AmiStateInfo(
char *
buffer,
size_t space);
156 static ssize_t ami_ct_s8(
const u_char __user *userPtr,
size_t userCount,
162 void *
p = &frame[*frameUsed];
163 count =
min_t(
unsigned long, userCount, frameLeft) & ~1;
170 count =
min_t(
unsigned long, userCount, frameLeft)>>1 & ~1;
188 #define GENERATE_AMI_CT8(funcname, convsample) \
189 static ssize_t funcname(const u_char __user *userPtr, size_t userCount, \
190 u_char frame[], ssize_t *frameUsed, \
193 ssize_t count, used; \
195 if (!dmasound.soft.stereo) { \
196 u_char *p = &frame[*frameUsed]; \
197 count = min_t(size_t, userCount, frameLeft) & ~1; \
199 while (count > 0) { \
201 if (get_user(data, userPtr++)) \
203 *p++ = convsample(data); \
207 u_char *left = &frame[*frameUsed>>1]; \
208 u_char *right = left+write_sq_block_size_half; \
209 count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \
211 while (count > 0) { \
213 if (get_user(data, userPtr++)) \
215 *left++ = convsample(data); \
216 if (get_user(data, userPtr++)) \
218 *right++ = convsample(data); \
222 *frameUsed += used; \
226 #define AMI_CT_ULAW(x) (dmasound_ulaw2dma8[(x)])
227 #define AMI_CT_ALAW(x) (dmasound_alaw2dma8[(x)])
228 #define AMI_CT_U8(x) ((x) ^ 0x80)
239 #define GENERATE_AMI_CT_16(funcname, convsample) \
240 static ssize_t funcname(const u_char __user *userPtr, size_t userCount, \
241 u_char frame[], ssize_t *frameUsed, \
244 const u_short __user *ptr = (const u_short __user *)userPtr; \
245 ssize_t count, used; \
248 if (!dmasound.soft.stereo) { \
249 u_char *high = &frame[*frameUsed>>1]; \
250 u_char *low = high+write_sq_block_size_half; \
251 count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \
253 while (count > 0) { \
254 if (get_user(data, ptr++)) \
256 data = convsample(data); \
258 *low++ = (data>>2) & 0x3f; \
262 u_char *lefth = &frame[*frameUsed>>2]; \
263 u_char *leftl = lefth+write_sq_block_size_quarter; \
264 u_char *righth = lefth+write_sq_block_size_half; \
265 u_char *rightl = righth+write_sq_block_size_quarter; \
266 count = min_t(size_t, userCount, frameLeft)>>2 & ~1; \
268 while (count > 0) { \
269 if (get_user(data, ptr++)) \
271 data = convsample(data); \
272 *lefth++ = data>>8; \
273 *leftl++ = (data>>2) & 0x3f; \
274 if (get_user(data, ptr++)) \
276 data = convsample(data); \
277 *righth++ = data>>8; \
278 *rightl++ = (data>>2) & 0x3f; \
282 *frameUsed += used; \
286 #define AMI_CT_S16BE(x) (x)
287 #define AMI_CT_U16BE(x) ((x) ^ 0x8000)
288 #define AMI_CT_S16LE(x) (le2be16((x)))
289 #define AMI_CT_U16LE(x) (le2be16((x)) ^ 0x8000)
297 static
TRANS transAmiga = {
299 .ct_alaw = ami_ct_alaw,
302 .ct_s16be = ami_ct_s16be,
303 .ct_u16be = ami_ct_u16be,
304 .ct_s16le = ami_ct_s16le,
305 .ct_u16le = ami_ct_u16le,
310 static inline void StopDMA(
void)
323 static void AmiFree(
void *obj,
unsigned int size)
328 static int __init AmiIrqInit(
void)
341 static void AmiIrqCleanUp(
void)
350 static void AmiSilence(
void)
357 static void AmiInit(
void)
373 }
else if (period > 65535) {
378 for (i = 0; i < 4; i++)
379 custom.aud[i].audper = period;
384 static int AmiSetFormat(
int format)
422 #define VOLUME_VOXWARE_TO_AMI(v) \
423 (((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100)
424 #define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64)
426 static int AmiSetVolume(
int volume)
445 static int AmiSetTreble(
int treble)
456 #define AMI_PLAY_LOADED 1
457 #define AMI_PLAY_PLAYING 2
458 #define AMI_PLAY_MASK 3
461 static void AmiPlayNextFrame(
int index)
475 ch1 = start+write_sq_block_size_half;
499 ch3 = ch0+write_sq_block_size_quarter;
500 ch2 = ch1+write_sq_block_size_quarter;
519 static void AmiPlay(
void)
550 AmiPlayNextFrame(minframes);
607 static void __init AmiMixerInit(
void)
634 return IOCTL_OUT(arg, dmasound_set_volume(data));
639 return IOCTL_OUT(arg, dmasound_set_treble(data));
645 static int AmiWriteSqSetup(
void)
647 write_sq_block_size_half =
write_sq.block_size>>1;
648 write_sq_block_size_quarter = write_sq_block_size_half>>1;
653 static int AmiStateInfo(
char *
buffer,
size_t space)
656 len +=
sprintf(buffer+len,
"\tsound.volume_left = %d [0...64]\n",
658 len +=
sprintf(buffer+len,
"\tsound.volume_right = %d [0...64]\n",
661 printk(
KERN_ERR "dmasound_paula: overflowed state buffer alloc.\n") ;
688 .dma_alloc = AmiAlloc,
690 .irqinit = AmiIrqInit,
692 .irqcleanup = AmiIrqCleanUp,
695 .silence = AmiSilence,
696 .setFormat = AmiSetFormat,
697 .setVolume = AmiSetVolume,
698 .setTreble = AmiSetTreble,
700 .mixer_init = AmiMixerInit,
701 .mixer_ioctl = AmiMixerIoctl,
702 .write_sq_setup = AmiWriteSqSetup,
703 .state_info = AmiStateInfo,
704 .min_dsp_speed = 8000,
717 dmasound.mach.default_hard = def_hard ;
718 dmasound.mach.default_soft = def_soft ;
729 .remove =
__exit_p(amiga_audio_remove),
731 .name =
"amiga-audio",
736 static int __init amiga_audio_init(
void)
743 static void __exit amiga_audio_exit(
void)