xref: /linux/sound/oss/dmasound/dmasound_paula.c (revision de2fe5e07d58424bc286fff3fd3c1b0bf933cd58)
1 /*
2  *  linux/sound/oss/dmasound/dmasound_paula.c
3  *
4  *  Amiga `Paula' 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  *	       [0.3] - put in constraint on state buffer usage.
14  *	       [0.4] - put in default hard/soft settings
15 */
16 
17 
18 #include <linux/module.h>
19 #include <linux/config.h>
20 #include <linux/mm.h>
21 #include <linux/init.h>
22 #include <linux/ioport.h>
23 #include <linux/soundcard.h>
24 #include <linux/interrupt.h>
25 
26 #include <asm/uaccess.h>
27 #include <asm/setup.h>
28 #include <asm/amigahw.h>
29 #include <asm/amigaints.h>
30 #include <asm/machdep.h>
31 
32 #include "dmasound.h"
33 
34 #define DMASOUND_PAULA_REVISION 0
35 #define DMASOUND_PAULA_EDITION 4
36 
37 #define custom amiga_custom
38    /*
39     *	The minimum period for audio depends on htotal (for OCS/ECS/AGA)
40     *	(Imported from arch/m68k/amiga/amisound.c)
41     */
42 
43 extern volatile u_short amiga_audio_min_period;
44 
45 
46    /*
47     *	amiga_mksound() should be able to restore the period after beeping
48     *	(Imported from arch/m68k/amiga/amisound.c)
49     */
50 
51 extern u_short amiga_audio_period;
52 
53 
54    /*
55     *	Audio DMA masks
56     */
57 
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)
61 
62 
63     /*
64      *  Helper pointers for 16(14)-bit sound
65      */
66 
67 static int write_sq_block_size_half, write_sq_block_size_quarter;
68 
69 
70 /*** Low level stuff *********************************************************/
71 
72 
73 static void *AmiAlloc(unsigned int size, gfp_t flags);
74 static void AmiFree(void *obj, unsigned int size);
75 static int AmiIrqInit(void);
76 #ifdef MODULE
77 static void AmiIrqCleanUp(void);
78 #endif
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);
86 static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp);
87 
88 #ifdef CONFIG_HEARTBEAT
89 
90     /*
91      *  Heartbeat interferes with sound since the 7 kHz low-pass filter and the
92      *  power LED are controlled by the same line.
93      */
94 
95 #ifdef CONFIG_APUS
96 #define mach_heartbeat	ppc_md.heartbeat
97 #endif
98 
99 static void (*saved_heartbeat)(int) = NULL;
100 
101 static inline void disable_heartbeat(void)
102 {
103 	if (mach_heartbeat) {
104 	    saved_heartbeat = mach_heartbeat;
105 	    mach_heartbeat = NULL;
106 	}
107 	AmiSetTreble(dmasound.treble);
108 }
109 
110 static inline void enable_heartbeat(void)
111 {
112 	if (saved_heartbeat)
113 	    mach_heartbeat = saved_heartbeat;
114 }
115 #else /* !CONFIG_HEARTBEAT */
116 #define disable_heartbeat()	do { } while (0)
117 #define enable_heartbeat()	do { } while (0)
118 #endif /* !CONFIG_HEARTBEAT */
119 
120 
121 /*** Mid level stuff *********************************************************/
122 
123 static void AmiMixerInit(void);
124 static int AmiMixerIoctl(u_int cmd, u_long arg);
125 static int AmiWriteSqSetup(void);
126 static int AmiStateInfo(char *buffer, size_t space);
127 
128 
129 /*** Translations ************************************************************/
130 
131 /* ++TeSche: radically changed for new expanding purposes...
132  *
133  * These two routines now deal with copying/expanding/translating the samples
134  * from user space into our buffer at the right frequency. They take care about
135  * how much data there's actually to read, how much buffer space there is and
136  * to convert samples into the right frequency/encoding. They will only work on
137  * complete samples so it may happen they leave some bytes in the input stream
138  * if the user didn't write a multiple of the current sample size. They both
139  * return the number of bytes they've used from both streams so you may detect
140  * such a situation. Luckily all programs should be able to cope with that.
141  *
142  * I think I've optimized anything as far as one can do in plain C, all
143  * variables should fit in registers and the loops are really short. There's
144  * one loop for every possible situation. Writing a more generalized and thus
145  * parameterized loop would only produce slower code. Feel free to optimize
146  * this in assembler if you like. :)
147  *
148  * I think these routines belong here because they're not yet really hardware
149  * independent, especially the fact that the Falcon can play 16bit samples
150  * only in stereo is hardcoded in both of them!
151  *
152  * ++geert: split in even more functions (one per format)
153  */
154 
155 
156     /*
157      *  Native format
158      */
159 
160 static ssize_t ami_ct_s8(const u_char __user *userPtr, size_t userCount,
161 			 u_char frame[], ssize_t *frameUsed, ssize_t frameLeft)
162 {
163 	ssize_t count, used;
164 
165 	if (!dmasound.soft.stereo) {
166 		void *p = &frame[*frameUsed];
167 		count = min_t(unsigned long, userCount, frameLeft) & ~1;
168 		used = count;
169 		if (copy_from_user(p, userPtr, count))
170 			return -EFAULT;
171 	} else {
172 		u_char *left = &frame[*frameUsed>>1];
173 		u_char *right = left+write_sq_block_size_half;
174 		count = min_t(unsigned long, userCount, frameLeft)>>1 & ~1;
175 		used = count*2;
176 		while (count > 0) {
177 			if (get_user(*left++, userPtr++)
178 			    || get_user(*right++, userPtr++))
179 				return -EFAULT;
180 			count--;
181 		}
182 	}
183 	*frameUsed += used;
184 	return used;
185 }
186 
187 
188     /*
189      *  Copy and convert 8 bit data
190      */
191 
192 #define GENERATE_AMI_CT8(funcname, convsample)				\
193 static ssize_t funcname(const u_char __user *userPtr, size_t userCount,	\
194 			u_char frame[], ssize_t *frameUsed,		\
195 			ssize_t frameLeft)				\
196 {									\
197 	ssize_t count, used;						\
198 									\
199 	if (!dmasound.soft.stereo) {					\
200 		u_char *p = &frame[*frameUsed];				\
201 		count = min_t(size_t, userCount, frameLeft) & ~1;	\
202 		used = count;						\
203 		while (count > 0) {					\
204 			u_char data;					\
205 			if (get_user(data, userPtr++))			\
206 				return -EFAULT;				\
207 			*p++ = convsample(data);			\
208 			count--;					\
209 		}							\
210 	} else {							\
211 		u_char *left = &frame[*frameUsed>>1];			\
212 		u_char *right = left+write_sq_block_size_half;		\
213 		count = min_t(size_t, userCount, frameLeft)>>1 & ~1;	\
214 		used = count*2;						\
215 		while (count > 0) {					\
216 			u_char data;					\
217 			if (get_user(data, userPtr++))			\
218 				return -EFAULT;				\
219 			*left++ = convsample(data);			\
220 			if (get_user(data, userPtr++))			\
221 				return -EFAULT;				\
222 			*right++ = convsample(data);			\
223 			count--;					\
224 		}							\
225 	}								\
226 	*frameUsed += used;						\
227 	return used;							\
228 }
229 
230 #define AMI_CT_ULAW(x)	(dmasound_ulaw2dma8[(x)])
231 #define AMI_CT_ALAW(x)	(dmasound_alaw2dma8[(x)])
232 #define AMI_CT_U8(x)	((x) ^ 0x80)
233 
234 GENERATE_AMI_CT8(ami_ct_ulaw, AMI_CT_ULAW)
235 GENERATE_AMI_CT8(ami_ct_alaw, AMI_CT_ALAW)
236 GENERATE_AMI_CT8(ami_ct_u8, AMI_CT_U8)
237 
238 
239     /*
240      *  Copy and convert 16 bit data
241      */
242 
243 #define GENERATE_AMI_CT_16(funcname, convsample)			\
244 static ssize_t funcname(const u_char __user *userPtr, size_t userCount,	\
245 			u_char frame[], ssize_t *frameUsed,		\
246 			ssize_t frameLeft)				\
247 {									\
248 	const u_short __user *ptr = (const u_short __user *)userPtr;	\
249 	ssize_t count, used;						\
250 	u_short data;							\
251 									\
252 	if (!dmasound.soft.stereo) {					\
253 		u_char *high = &frame[*frameUsed>>1];			\
254 		u_char *low = high+write_sq_block_size_half;		\
255 		count = min_t(size_t, userCount, frameLeft)>>1 & ~1;	\
256 		used = count*2;						\
257 		while (count > 0) {					\
258 			if (get_user(data, ptr++))			\
259 				return -EFAULT;				\
260 			data = convsample(data);			\
261 			*high++ = data>>8;				\
262 			*low++ = (data>>2) & 0x3f;			\
263 			count--;					\
264 		}							\
265 	} else {							\
266 		u_char *lefth = &frame[*frameUsed>>2];			\
267 		u_char *leftl = lefth+write_sq_block_size_quarter;	\
268 		u_char *righth = lefth+write_sq_block_size_half;	\
269 		u_char *rightl = righth+write_sq_block_size_quarter;	\
270 		count = min_t(size_t, userCount, frameLeft)>>2 & ~1;	\
271 		used = count*4;						\
272 		while (count > 0) {					\
273 			if (get_user(data, ptr++))			\
274 				return -EFAULT;				\
275 			data = convsample(data);			\
276 			*lefth++ = data>>8;				\
277 			*leftl++ = (data>>2) & 0x3f;			\
278 			if (get_user(data, ptr++))			\
279 				return -EFAULT;				\
280 			data = convsample(data);			\
281 			*righth++ = data>>8;				\
282 			*rightl++ = (data>>2) & 0x3f;			\
283 			count--;					\
284 		}							\
285 	}								\
286 	*frameUsed += used;						\
287 	return used;							\
288 }
289 
290 #define AMI_CT_S16BE(x)	(x)
291 #define AMI_CT_U16BE(x)	((x) ^ 0x8000)
292 #define AMI_CT_S16LE(x)	(le2be16((x)))
293 #define AMI_CT_U16LE(x)	(le2be16((x)) ^ 0x8000)
294 
295 GENERATE_AMI_CT_16(ami_ct_s16be, AMI_CT_S16BE)
296 GENERATE_AMI_CT_16(ami_ct_u16be, AMI_CT_U16BE)
297 GENERATE_AMI_CT_16(ami_ct_s16le, AMI_CT_S16LE)
298 GENERATE_AMI_CT_16(ami_ct_u16le, AMI_CT_U16LE)
299 
300 
301 static TRANS transAmiga = {
302 	.ct_ulaw	= ami_ct_ulaw,
303 	.ct_alaw	= ami_ct_alaw,
304 	.ct_s8		= ami_ct_s8,
305 	.ct_u8		= ami_ct_u8,
306 	.ct_s16be	= ami_ct_s16be,
307 	.ct_u16be	= ami_ct_u16be,
308 	.ct_s16le	= ami_ct_s16le,
309 	.ct_u16le	= ami_ct_u16le,
310 };
311 
312 /*** Low level stuff *********************************************************/
313 
314 static inline void StopDMA(void)
315 {
316 	custom.aud[0].audvol = custom.aud[1].audvol = 0;
317 	custom.aud[2].audvol = custom.aud[3].audvol = 0;
318 	custom.dmacon = AMI_AUDIO_OFF;
319 	enable_heartbeat();
320 }
321 
322 static void *AmiAlloc(unsigned int size, gfp_t flags)
323 {
324 	return amiga_chip_alloc((long)size, "dmasound [Paula]");
325 }
326 
327 static void AmiFree(void *obj, unsigned int size)
328 {
329 	amiga_chip_free (obj);
330 }
331 
332 static int __init AmiIrqInit(void)
333 {
334 	/* turn off DMA for audio channels */
335 	StopDMA();
336 
337 	/* Register interrupt handler. */
338 	if (request_irq(IRQ_AMIGA_AUD0, AmiInterrupt, 0, "DMA sound",
339 			AmiInterrupt))
340 		return 0;
341 	return 1;
342 }
343 
344 #ifdef MODULE
345 static void AmiIrqCleanUp(void)
346 {
347 	/* turn off DMA for audio channels */
348 	StopDMA();
349 	/* release the interrupt */
350 	free_irq(IRQ_AMIGA_AUD0, AmiInterrupt);
351 }
352 #endif /* MODULE */
353 
354 static void AmiSilence(void)
355 {
356 	/* turn off DMA for audio channels */
357 	StopDMA();
358 }
359 
360 
361 static void AmiInit(void)
362 {
363 	int period, i;
364 
365 	AmiSilence();
366 
367 	if (dmasound.soft.speed)
368 		period = amiga_colorclock/dmasound.soft.speed-1;
369 	else
370 		period = amiga_audio_min_period;
371 	dmasound.hard = dmasound.soft;
372 	dmasound.trans_write = &transAmiga;
373 
374 	if (period < amiga_audio_min_period) {
375 		/* we would need to squeeze the sound, but we won't do that */
376 		period = amiga_audio_min_period;
377 	} else if (period > 65535) {
378 		period = 65535;
379 	}
380 	dmasound.hard.speed = amiga_colorclock/(period+1);
381 
382 	for (i = 0; i < 4; i++)
383 		custom.aud[i].audper = period;
384 	amiga_audio_period = period;
385 }
386 
387 
388 static int AmiSetFormat(int format)
389 {
390 	int size;
391 
392 	/* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */
393 
394 	switch (format) {
395 	case AFMT_QUERY:
396 		return dmasound.soft.format;
397 	case AFMT_MU_LAW:
398 	case AFMT_A_LAW:
399 	case AFMT_U8:
400 	case AFMT_S8:
401 		size = 8;
402 		break;
403 	case AFMT_S16_BE:
404 	case AFMT_U16_BE:
405 	case AFMT_S16_LE:
406 	case AFMT_U16_LE:
407 		size = 16;
408 		break;
409 	default: /* :-) */
410 		size = 8;
411 		format = AFMT_S8;
412 	}
413 
414 	dmasound.soft.format = format;
415 	dmasound.soft.size = size;
416 	if (dmasound.minDev == SND_DEV_DSP) {
417 		dmasound.dsp.format = format;
418 		dmasound.dsp.size = dmasound.soft.size;
419 	}
420 	AmiInit();
421 
422 	return format;
423 }
424 
425 
426 #define VOLUME_VOXWARE_TO_AMI(v) \
427 	(((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100)
428 #define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64)
429 
430 static int AmiSetVolume(int volume)
431 {
432 	dmasound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff);
433 	custom.aud[0].audvol = dmasound.volume_left;
434 	dmasound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);
435 	custom.aud[1].audvol = dmasound.volume_right;
436 	if (dmasound.hard.size == 16) {
437 		if (dmasound.volume_left == 64 && dmasound.volume_right == 64) {
438 			custom.aud[2].audvol = 1;
439 			custom.aud[3].audvol = 1;
440 		} else {
441 			custom.aud[2].audvol = 0;
442 			custom.aud[3].audvol = 0;
443 		}
444 	}
445 	return VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) |
446 	       (VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8);
447 }
448 
449 static int AmiSetTreble(int treble)
450 {
451 	dmasound.treble = treble;
452 	if (treble < 50)
453 		ciaa.pra &= ~0x02;
454 	else
455 		ciaa.pra |= 0x02;
456 	return treble;
457 }
458 
459 
460 #define AMI_PLAY_LOADED		1
461 #define AMI_PLAY_PLAYING	2
462 #define AMI_PLAY_MASK		3
463 
464 
465 static void AmiPlayNextFrame(int index)
466 {
467 	u_char *start, *ch0, *ch1, *ch2, *ch3;
468 	u_long size;
469 
470 	/* used by AmiPlay() if all doubts whether there really is something
471 	 * to be played are already wiped out.
472 	 */
473 	start = write_sq.buffers[write_sq.front];
474 	size = (write_sq.count == index ? write_sq.rear_size
475 					: write_sq.block_size)>>1;
476 
477 	if (dmasound.hard.stereo) {
478 		ch0 = start;
479 		ch1 = start+write_sq_block_size_half;
480 		size >>= 1;
481 	} else {
482 		ch0 = start;
483 		ch1 = start;
484 	}
485 
486 	disable_heartbeat();
487 	custom.aud[0].audvol = dmasound.volume_left;
488 	custom.aud[1].audvol = dmasound.volume_right;
489 	if (dmasound.hard.size == 8) {
490 		custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
491 		custom.aud[0].audlen = size;
492 		custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
493 		custom.aud[1].audlen = size;
494 		custom.dmacon = AMI_AUDIO_8;
495 	} else {
496 		size >>= 1;
497 		custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
498 		custom.aud[0].audlen = size;
499 		custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
500 		custom.aud[1].audlen = size;
501 		if (dmasound.volume_left == 64 && dmasound.volume_right == 64) {
502 			/* We can play pseudo 14-bit only with the maximum volume */
503 			ch3 = ch0+write_sq_block_size_quarter;
504 			ch2 = ch1+write_sq_block_size_quarter;
505 			custom.aud[2].audvol = 1;  /* we are being affected by the beeps */
506 			custom.aud[3].audvol = 1;  /* restoring volume here helps a bit */
507 			custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2);
508 			custom.aud[2].audlen = size;
509 			custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);
510 			custom.aud[3].audlen = size;
511 			custom.dmacon = AMI_AUDIO_14;
512 		} else {
513 			custom.aud[2].audvol = 0;
514 			custom.aud[3].audvol = 0;
515 			custom.dmacon = AMI_AUDIO_8;
516 		}
517 	}
518 	write_sq.front = (write_sq.front+1) % write_sq.max_count;
519 	write_sq.active |= AMI_PLAY_LOADED;
520 }
521 
522 
523 static void AmiPlay(void)
524 {
525 	int minframes = 1;
526 
527 	custom.intena = IF_AUD0;
528 
529 	if (write_sq.active & AMI_PLAY_LOADED) {
530 		/* There's already a frame loaded */
531 		custom.intena = IF_SETCLR | IF_AUD0;
532 		return;
533 	}
534 
535 	if (write_sq.active & AMI_PLAY_PLAYING)
536 		/* Increase threshold: frame 1 is already being played */
537 		minframes = 2;
538 
539 	if (write_sq.count < minframes) {
540 		/* Nothing to do */
541 		custom.intena = IF_SETCLR | IF_AUD0;
542 		return;
543 	}
544 
545 	if (write_sq.count <= minframes &&
546 	    write_sq.rear_size < write_sq.block_size && !write_sq.syncing) {
547 		/* hmmm, the only existing frame is not
548 		 * yet filled and we're not syncing?
549 		 */
550 		custom.intena = IF_SETCLR | IF_AUD0;
551 		return;
552 	}
553 
554 	AmiPlayNextFrame(minframes);
555 
556 	custom.intena = IF_SETCLR | IF_AUD0;
557 }
558 
559 
560 static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp)
561 {
562 	int minframes = 1;
563 
564 	custom.intena = IF_AUD0;
565 
566 	if (!write_sq.active) {
567 		/* Playing was interrupted and sq_reset() has already cleared
568 		 * the sq variables, so better don't do anything here.
569 		 */
570 		WAKE_UP(write_sq.sync_queue);
571 		return IRQ_HANDLED;
572 	}
573 
574 	if (write_sq.active & AMI_PLAY_PLAYING) {
575 		/* We've just finished a frame */
576 		write_sq.count--;
577 		WAKE_UP(write_sq.action_queue);
578 	}
579 
580 	if (write_sq.active & AMI_PLAY_LOADED)
581 		/* Increase threshold: frame 1 is already being played */
582 		minframes = 2;
583 
584 	/* Shift the flags */
585 	write_sq.active = (write_sq.active<<1) & AMI_PLAY_MASK;
586 
587 	if (!write_sq.active)
588 		/* No frame is playing, disable audio DMA */
589 		StopDMA();
590 
591 	custom.intena = IF_SETCLR | IF_AUD0;
592 
593 	if (write_sq.count >= minframes)
594 		/* Try to play the next frame */
595 		AmiPlay();
596 
597 	if (!write_sq.active)
598 		/* Nothing to play anymore.
599 		   Wake up a process waiting for audio output to drain. */
600 		WAKE_UP(write_sq.sync_queue);
601 	return IRQ_HANDLED;
602 }
603 
604 /*** Mid level stuff *********************************************************/
605 
606 
607 /*
608  * /dev/mixer abstraction
609  */
610 
611 static void __init AmiMixerInit(void)
612 {
613 	dmasound.volume_left = 64;
614 	dmasound.volume_right = 64;
615 	custom.aud[0].audvol = dmasound.volume_left;
616 	custom.aud[3].audvol = 1;	/* For pseudo 14bit */
617 	custom.aud[1].audvol = dmasound.volume_right;
618 	custom.aud[2].audvol = 1;	/* For pseudo 14bit */
619 	dmasound.treble = 50;
620 }
621 
622 static int AmiMixerIoctl(u_int cmd, u_long arg)
623 {
624 	int data;
625 	switch (cmd) {
626 	    case SOUND_MIXER_READ_DEVMASK:
627 		    return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE);
628 	    case SOUND_MIXER_READ_RECMASK:
629 		    return IOCTL_OUT(arg, 0);
630 	    case SOUND_MIXER_READ_STEREODEVS:
631 		    return IOCTL_OUT(arg, SOUND_MASK_VOLUME);
632 	    case SOUND_MIXER_READ_VOLUME:
633 		    return IOCTL_OUT(arg,
634 			    VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) |
635 			    VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8);
636 	    case SOUND_MIXER_WRITE_VOLUME:
637 		    IOCTL_IN(arg, data);
638 		    return IOCTL_OUT(arg, dmasound_set_volume(data));
639 	    case SOUND_MIXER_READ_TREBLE:
640 		    return IOCTL_OUT(arg, dmasound.treble);
641 	    case SOUND_MIXER_WRITE_TREBLE:
642 		    IOCTL_IN(arg, data);
643 		    return IOCTL_OUT(arg, dmasound_set_treble(data));
644 	}
645 	return -EINVAL;
646 }
647 
648 
649 static int AmiWriteSqSetup(void)
650 {
651 	write_sq_block_size_half = write_sq.block_size>>1;
652 	write_sq_block_size_quarter = write_sq_block_size_half>>1;
653 	return 0;
654 }
655 
656 
657 static int AmiStateInfo(char *buffer, size_t space)
658 {
659 	int len = 0;
660 	len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n",
661 		       dmasound.volume_left);
662 	len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n",
663 		       dmasound.volume_right);
664 	if (len >= space) {
665 		printk(KERN_ERR "dmasound_paula: overlowed state buffer alloc.\n") ;
666 		len = space ;
667 	}
668 	return len;
669 }
670 
671 
672 /*** Machine definitions *****************************************************/
673 
674 static SETTINGS def_hard = {
675 	.format	= AFMT_S8,
676 	.stereo	= 0,
677 	.size	= 8,
678 	.speed	= 8000
679 } ;
680 
681 static SETTINGS def_soft = {
682 	.format	= AFMT_U8,
683 	.stereo	= 0,
684 	.size	= 8,
685 	.speed	= 8000
686 } ;
687 
688 static MACHINE machAmiga = {
689 	.name		= "Amiga",
690 	.name2		= "AMIGA",
691 	.owner		= THIS_MODULE,
692 	.dma_alloc	= AmiAlloc,
693 	.dma_free	= AmiFree,
694 	.irqinit	= AmiIrqInit,
695 #ifdef MODULE
696 	.irqcleanup	= AmiIrqCleanUp,
697 #endif /* MODULE */
698 	.init		= AmiInit,
699 	.silence	= AmiSilence,
700 	.setFormat	= AmiSetFormat,
701 	.setVolume	= AmiSetVolume,
702 	.setTreble	= AmiSetTreble,
703 	.play		= AmiPlay,
704 	.mixer_init	= AmiMixerInit,
705 	.mixer_ioctl	= AmiMixerIoctl,
706 	.write_sq_setup	= AmiWriteSqSetup,
707 	.state_info	= AmiStateInfo,
708 	.min_dsp_speed	= 8000,
709 	.version	= ((DMASOUND_PAULA_REVISION<<8) | DMASOUND_PAULA_EDITION),
710 	.hardware_afmts	= (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */
711 	.capabilities	= DSP_CAP_BATCH          /* As per SNDCTL_DSP_GETCAPS */
712 };
713 
714 
715 /*** Config & Setup **********************************************************/
716 
717 
718 int __init dmasound_paula_init(void)
719 {
720 	int err;
721 
722 	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_AUDIO)) {
723 	    if (!request_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40,
724 				    "dmasound [Paula]"))
725 		return -EBUSY;
726 	    dmasound.mach = machAmiga;
727 	    dmasound.mach.default_hard = def_hard ;
728 	    dmasound.mach.default_soft = def_soft ;
729 	    err = dmasound_init();
730 	    if (err)
731 		release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);
732 	    return err;
733 	} else
734 	    return -ENODEV;
735 }
736 
737 static void __exit dmasound_paula_cleanup(void)
738 {
739 	dmasound_deinit();
740 	release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);
741 }
742 
743 module_init(dmasound_paula_init);
744 module_exit(dmasound_paula_cleanup);
745 MODULE_LICENSE("GPL");
746