Fix for PPC audio devices that can't reendianize samples

Derrik Pates demon at devrandom.net
Sat Aug 11 01:45:42 EST 2001


The attached patch adds code to drivers/sound/dmasound/trans_16.c to
byteswap little-endian audio samples for hardware that needs it (like the
DACA audio chip in the iBook and iBook FireWire), and also marks the DACA
in the iBook FireWire as being unable to handle little-endian audio
samples (in dmasound_awacs.c).
-------------- next part --------------
--- /home/linux-2.4-benh.dist/drivers/sound/dmasound/dmasound_awacs.c	Thu Aug  9 07:12:02 2001
+++ drivers/sound/dmasound/dmasound_awacs.c	Thu Aug  9 12:35:14 2001
@@ -2004,6 +2004,10 @@
 		is_ibook = 1 ;
 		return ;
 	}
+	if (machine_is_compatible("PowerBook2,2")) {	/* ibook 2 (firewire) */
+		is_ibook = 1 ;
+		return ;
+	}
 }
 
 /* Get the OF node that tells us about the registers, interrupts etc. to use
@@ -2258,10 +2262,10 @@
 			break;
 		}
 	}
-	if (rev == 2) {
+	if (rev >= 2) {
 		hw_can_byteswap = 0;
 #ifdef DEBUG_DMASOUND
-printk("dmasound_pmac: found Keylargo rev 2 - H/W byte-swap disabled\n") ;
+printk("dmasound_pmac: found Keylargo rev 2 or later - H/W byte-swap disabled\n") ;
 #endif
 	}
 }
--- /home/linux-2.4-benh.dist/drivers/sound/dmasound/trans_16.c	Thu Aug  9 07:12:01 2001
+++ drivers/sound/dmasound/trans_16.c	Thu Aug  9 12:33:01 2001
@@ -12,6 +12,7 @@
 
 #include <linux/soundcard.h>
 #include <asm/uaccess.h>
+#include <asm/byteorder.h>
 #include "dmasound.h"
 
 static short dmasound_alaw2dma16[] ;
@@ -26,10 +27,16 @@
 static ssize_t pmac_ct_u8(const u_char *userPtr, size_t userCount,
 			  u_char frame[], ssize_t *frameUsed,
 			  ssize_t frameLeft);
-static ssize_t pmac_ct_s16(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ct_s16le(const u_char *userPtr, size_t userCount,
 			   u_char frame[], ssize_t *frameUsed,
 			   ssize_t frameLeft);
-static ssize_t pmac_ct_u16(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ct_s16be(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft);
+static ssize_t pmac_ct_u16le(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft);
+static ssize_t pmac_ct_u16be(const u_char *userPtr, size_t userCount,
 			   u_char frame[], ssize_t *frameUsed,
 			   ssize_t frameLeft);
 
@@ -42,17 +49,29 @@
 static ssize_t pmac_ctx_u8(const u_char *userPtr, size_t userCount,
 			   u_char frame[], ssize_t *frameUsed,
 			   ssize_t frameLeft);
-static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ctx_s16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t pmac_ctx_s16be(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft);
+static ssize_t pmac_ctx_u16le(const u_char *userPtr, size_t userCount,
 			    u_char frame[], ssize_t *frameUsed,
 			    ssize_t frameLeft);
-static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ctx_u16be(const u_char *userPtr, size_t userCount,
 			    u_char frame[], ssize_t *frameUsed,
 			    ssize_t frameLeft);
 
-static ssize_t pmac_ct_s16_read(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ct_s16le_read(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft);
+static ssize_t pmac_ct_s16be_read(const u_char *userPtr, size_t userCount,
 			   u_char frame[], ssize_t *frameUsed,
 			   ssize_t frameLeft);
-static ssize_t pmac_ct_u16_read(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ct_u16le_read(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft);
+static ssize_t pmac_ct_u16be_read(const u_char *userPtr, size_t userCount,
 			   u_char frame[], ssize_t *frameUsed,
 			   ssize_t frameLeft);
 
@@ -156,7 +175,37 @@
 }
 
 
-static ssize_t pmac_ct_s16(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ct_s16le(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft)
+{
+	ssize_t count, used;
+	int stereo = dmasound.soft.stereo;
+	short *fp = (short *) &frame[*frameUsed];
+	short *up = (short *) userPtr;
+
+	frameLeft >>= 2;
+	userCount >>= (stereo? 2: 1);
+	used = count = min(userCount, frameLeft);
+	while (count > 0) {
+		short data;
+		if (get_user(data, up++))
+			return -EFAULT;
+		__arch__swab16s(&data);
+		*fp++ = data;
+		if (stereo) {
+			if (get_user(data, up++))
+				return -EFAULT;
+			__arch__swab16s(&data);
+		}
+		*fp++ = data;
+		count--;
+	}
+	*frameUsed += used * 4;
+	return stereo? used * 4: used * 2;
+}
+
+static ssize_t pmac_ct_s16be(const u_char *userPtr, size_t userCount,
 			   u_char frame[], ssize_t *frameUsed,
 			   ssize_t frameLeft)
 {
@@ -185,7 +234,40 @@
 	return stereo? used * 4: used * 2;
 }
 
-static ssize_t pmac_ct_u16(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ct_u16le(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft)
+{
+	ssize_t count, used;
+	int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
+	int stereo = dmasound.soft.stereo;
+	short *fp = (short *) &frame[*frameUsed];
+	short *up = (short *) userPtr;
+
+	frameLeft >>= 2;
+	userCount >>= (stereo? 2: 1);
+	used = count = min(userCount, frameLeft);
+	while (count > 0) {
+		short data;
+		if (get_user(data, up++))
+			return -EFAULT;
+		data ^= mask;
+		__arch__swab16s(&data);
+		*fp++ = data;
+		if (stereo) {
+			if (get_user(data, up++))
+				return -EFAULT;
+			data ^= mask;
+			__arch__swab16s(&data);
+		}
+		*fp++ = data;
+		count--;
+	}
+	*frameUsed += used * 4;
+	return stereo? used * 4: used * 2;
+}
+
+static ssize_t pmac_ct_u16be(const u_char *userPtr, size_t userCount,
 			   u_char frame[], ssize_t *frameUsed,
 			   ssize_t frameLeft)
 {
@@ -354,7 +436,53 @@
 }
 
 
-static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ctx_s16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
+{
+	unsigned int *p = (unsigned int *) &frame[*frameUsed];
+	unsigned int data = expand_data;
+	unsigned short *up = (unsigned short *) userPtr;
+	int bal = expand_bal;
+	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
+	int stereo = dmasound.soft.stereo;
+	int utotal, ftotal;
+
+	frameLeft >>= 2;
+	userCount >>= (stereo? 2: 1);
+	ftotal = frameLeft;
+	utotal = userCount;
+	while (frameLeft) {
+		unsigned short c;
+		if (bal < 0) {
+			if (userCount == 0)
+				break;
+			if (get_user(data, up++))
+				return -EFAULT;
+			if (stereo) {
+				if (get_user(c, up++))
+					return -EFAULT;
+				data = (data << 16) + c;
+			} else
+				data = (data << 16) + data;
+			userCount--;
+			bal += hSpeed;
+		}
+		__arch__swab16s((short *)&data);
+		__arch__swab16s(((short *)&data + 1));
+		*p++ = data;
+		frameLeft--;
+		bal -= sSpeed;
+	}
+	expand_bal = bal;
+	expand_data = data;
+	*frameUsed += (ftotal - frameLeft) * 4;
+	utotal -= userCount;
+	return stereo? utotal * 4: utotal * 2;
+}
+
+
+static ssize_t pmac_ctx_s16be(const u_char *userPtr, size_t userCount,
 			    u_char frame[], ssize_t *frameUsed,
 			    ssize_t frameLeft)
 {
@@ -398,7 +526,55 @@
 }
 
 
-static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ctx_u16le(const u_char *userPtr, size_t userCount,
+			    u_char frame[], ssize_t *frameUsed,
+			    ssize_t frameLeft)
+{
+	int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
+	unsigned int *p = (unsigned int *) &frame[*frameUsed];
+	unsigned int data = expand_data;
+	unsigned short *up = (unsigned short *) userPtr;
+	int bal = expand_bal;
+	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
+	int stereo = dmasound.soft.stereo;
+	int utotal, ftotal;
+
+	frameLeft >>= 2;
+	userCount >>= (stereo? 2: 1);
+	ftotal = frameLeft;
+	utotal = userCount;
+	while (frameLeft) {
+		unsigned short c;
+		if (bal < 0) {
+			if (userCount == 0)
+				break;
+			if (get_user(data, up++))
+				return -EFAULT;
+			data ^= mask;
+			if (stereo) {
+				if (get_user(c, up++))
+					return -EFAULT;
+				data = (data << 16) + (c ^ mask);
+			} else
+				data = (data << 16) + data;
+			userCount--;
+			bal += hSpeed;
+		}
+		__arch__swab16s((short *)&data);
+		__arch__swab16s(((short *)&data + 1));
+		*p++ = data;
+		frameLeft--;
+		bal -= sSpeed;
+	}
+	expand_bal = bal;
+	expand_data = data;
+	*frameUsed += (ftotal - frameLeft) * 4;
+	utotal -= userCount;
+	return stereo? utotal * 4: utotal * 2;
+}
+
+
+static ssize_t pmac_ctx_u16be(const u_char *userPtr, size_t userCount,
 			    u_char frame[], ssize_t *frameUsed,
 			    ssize_t frameLeft)
 {
@@ -510,7 +686,38 @@
 	return stereo? used * 2: used;
 }
 
-static ssize_t pmac_ct_s16_read(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ct_s16le_read(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft)
+{
+	ssize_t count, used;
+	int stereo = dmasound.soft.stereo;
+	short *fp = (short *) &frame[*frameUsed];
+	short *up = (short *) userPtr;
+
+	frameLeft >>= 2;
+	userCount >>= (stereo? 2: 1);
+	used = count = min(userCount, frameLeft);
+	while (count > 0) {
+		short data;
+		data = *fp++;
+		__arch__swab16s(&data);
+		if (put_user(data, up++))
+			return -EFAULT;
+		if (stereo) {
+			data = *fp;
+			__arch__swab16s(&data);
+			if (put_user(data, up++))
+				return -EFAULT;
+		}
+		fp++;
+		count--;
+	}
+	*frameUsed += used * 4;
+	return stereo? used * 4: used * 2;
+}
+
+static ssize_t pmac_ct_s16be_read(const u_char *userPtr, size_t userCount,
 			   u_char frame[], ssize_t *frameUsed,
 			   ssize_t frameLeft)
 {
@@ -539,12 +746,47 @@
 	return stereo? used * 4: used * 2;
 }
 
-static ssize_t pmac_ct_u16_read(const u_char *userPtr, size_t userCount,
+static ssize_t pmac_ct_u16le_read(const u_char *userPtr, size_t userCount,
 			   u_char frame[], ssize_t *frameUsed,
 			   ssize_t frameLeft)
 {
 	ssize_t count, used;
-	int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
+	int mask = 0x0080;
+	int stereo = dmasound.soft.stereo;
+	short *fp = (short *) &frame[*frameUsed];
+	short *up = (short *) userPtr;
+
+	frameLeft >>= 2;
+	userCount >>= (stereo? 2: 1);
+	used = count = min(userCount, frameLeft);
+	while (count > 0) {
+		short data;
+
+		data = *fp++;
+		data ^= mask;
+		__arch__swab16s(&data);
+		if (put_user(data, up++))
+			return -EFAULT;
+		if (stereo) {
+			data = *fp;
+			data ^= mask;
+			__arch__swab16s(&data);
+			if (put_user(data, up++))
+				return -EFAULT;
+		}
+		fp++;
+		count--;
+	}
+	*frameUsed += used * 4;
+	return stereo? used * 4: used * 2;
+}
+
+static ssize_t pmac_ct_u16be_read(const u_char *userPtr, size_t userCount,
+			   u_char frame[], ssize_t *frameUsed,
+			   ssize_t frameLeft)
+{
+	ssize_t count, used;
+	int mask = 0x8000;
 	int stereo = dmasound.soft.stereo;
 	short *fp = (short *) &frame[*frameUsed];
 	short *up = (short *) userPtr;
@@ -553,7 +795,7 @@
 	userCount >>= (stereo? 2: 1);
 	used = count = min(userCount, frameLeft);
 	while (count > 0) {
-		int data;
+		short data;
 
 		data = *fp++;
 		data ^= mask;
@@ -577,10 +819,10 @@
 	ct_alaw:	pmac_ct_law,
 	ct_s8:		pmac_ct_s8,
 	ct_u8:		pmac_ct_u8,
-	ct_s16be:	pmac_ct_s16,
-	ct_u16be:	pmac_ct_u16,
-	ct_s16le:	pmac_ct_s16,
-	ct_u16le:	pmac_ct_u16,
+	ct_s16be:	pmac_ct_s16be,
+	ct_u16be:	pmac_ct_u16be,
+	ct_s16le:	pmac_ct_s16le,
+	ct_u16le:	pmac_ct_u16le,
 };
 
 TRANS transAwacsExpand = {
@@ -588,19 +830,19 @@
 	ct_alaw:	pmac_ctx_law,
 	ct_s8:		pmac_ctx_s8,
 	ct_u8:		pmac_ctx_u8,
-	ct_s16be:	pmac_ctx_s16,
-	ct_u16be:	pmac_ctx_u16,
-	ct_s16le:	pmac_ctx_s16,
-	ct_u16le:	pmac_ctx_u16,
+	ct_s16be:	pmac_ctx_s16be,
+	ct_u16be:	pmac_ctx_u16be,
+	ct_s16le:	pmac_ctx_s16le,
+	ct_u16le:	pmac_ctx_u16le,
 };
 
 TRANS transAwacsNormalRead = {
 	ct_s8:		pmac_ct_s8_read,
 	ct_u8:		pmac_ct_u8_read,
-	ct_s16be:	pmac_ct_s16_read,
-	ct_u16be:	pmac_ct_u16_read,
-	ct_s16le:	pmac_ct_s16_read,
-	ct_u16le:	pmac_ct_u16_read,
+	ct_s16be:	pmac_ct_s16be_read,
+	ct_u16be:	pmac_ct_u16be_read,
+	ct_s16le:	pmac_ct_s16le_read,
+	ct_u16le:	pmac_ct_u16le_read,
 };
 
 /* translation tables */


More information about the Linuxppc-dev mailing list