Resent-Date: Wed, 22 Sep 1999 18:31:48 +0200 (MET DST)
Date: Wed, 22 Sep 1999 18:31:43 +0200 (MET DST)
From: Holger Jakob <jakob@ph-cip.uni-koeln.de>
To: linux-m68k@lists.linux-m68k.org
Subject: 2.3.17: dmasound patch
Resent-From: linux-m68k@phil.uni-sb.de

Hi!

Here is my patch for a better sounding AMIGA dmasound driver:

* After turning off audio DMA a high rectangular sound was produced.
* The channel de-syncing bug should be (hopefully) fixed.

There is still a problem when 3 or more programs open /dev/dsp.
After the first one has finished, the kernel panic somewhere in
wake_up_interruptible().

If compiled as a module and playing was interrupted via a signal
the release with sq_fsync() could also be interrupted and a wrong
module open counter will remain. Will a MOD_DEC_USE_COUNT before
sq_fsync() fix this?

Holger

ps: Diff offsets are relative to linux-2.3.17!


--- drivers/sound/dmasound.c~~	Wed Sep 22 17:32:58 1999
+++ drivers/sound/dmasound.c	Wed Sep 22 17:31:33 1999
@@ -2886,6 +2886,9 @@
  * Amiga
  */
 
+#define StopDMA custom.aud[0].audvol = custom.aud[1].audvol = 0; \
+		custom.aud[2].audvol = custom.aud[3].audvol = 0; \
+		custom.dmacon = AMI_AUDIO_OFF;
 
 static void *AmiAlloc(unsigned int size, int flags)
 {
@@ -2900,7 +2903,7 @@
 static int __init AmiIrqInit(void)
 {
 	/* turn off DMA for audio channels */
-	custom.dmacon = AMI_AUDIO_OFF;
+	StopDMA;
 
 	/* Register interrupt handler. */
 	if (request_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0,
@@ -2913,7 +2916,7 @@
 static void AmiIrqCleanUp(void)
 {
 	/* turn off DMA for audio channels */
-	custom.dmacon = AMI_AUDIO_OFF;
+	StopDMA;
 	/* release the interrupt */
 	free_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt);
 }
@@ -2922,7 +2925,7 @@
 static void AmiSilence(void)
 {
 	/* turn off DMA for audio channels */
-	custom.dmacon = AMI_AUDIO_OFF;
+	StopDMA;
 }
 
 
@@ -3003,6 +3006,15 @@
 	custom.aud[0].audvol = sound.volume_left;
 	sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);
 	custom.aud[1].audvol = sound.volume_right;
+	if (sound.hard.size == 16) {
+		if (sound.volume_left == 64 && sound.volume_right == 64) {
+			custom.aud[2].audvol = 1;
+			custom.aud[3].audvol = 1;
+		} else {
+			custom.aud[2].audvol = 0;
+			custom.aud[3].audvol = 0;
+		}
+	}
 	return(VOLUME_AMI_TO_VOXWARE(sound.volume_left) |
 	       (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8));
 }
@@ -3042,6 +3054,9 @@
 		ch0 = start;
 		ch1 = start;
 	}
+
+	custom.aud[0].audvol = sound.volume_left;
+	custom.aud[1].audvol = sound.volume_right;
 	if (sound.hard.size == 8) {
 		custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
 		custom.aud[0].audlen = size;
@@ -3065,11 +3080,14 @@
 			custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);
 			custom.aud[3].audlen = size;
 			custom.dmacon = AMI_AUDIO_14;
-		} else
+		} else {
+			custom.aud[2].audvol = 0;
+			custom.aud[3].audvol = 0;
 			custom.dmacon = AMI_AUDIO_8;
+		}
 	}
 	sq.front = (sq.front+1) % sq.max_count;
-	sq.active |= AMI_PLAY_LOADED;
+	sq.playing |= AMI_PLAY_LOADED;
 }
 
 
@@ -3113,6 +3131,8 @@
 {
 	int minframes = 1;
 
+	custom.intena = IF_AUD0;
+
 	if (!sq.active) {
 		/* Playing was interrupted and sq_reset() has already cleared
 		 * the sq variables, so better don't do anything here.
@@ -3136,7 +3156,9 @@
 
 	if (!sq.active)
 		/* No frame is playing, disable audio DMA */
-		custom.dmacon = AMI_AUDIO_OFF;
+		StopDMA;
+
+	custom.intena = IF_SETCLR | IF_AUD0;
 
 	if (sq.count >= minframes)
 		/* Try to play the next frame */

