Patch is attached. This flags the FireWire iBook as also being an iBook,
and indicates that KeyLargo revisions later than 2 (since the FireWire
iBook has a rev. 3) cannot reorder little-endian samples on their own. I
also have added code in drivers/sound/dmasound/trans_16.c to do the
necessary byte reordering in little-endian samples, so that the audio
output will be correct.

Derrik Pates      |   Sysadmin, Douglas School   |    #linuxOS on EFnet
[EMAIL PROTECTED] |     District (dsdk12.net)    |    #linuxOS on OPN
--- /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 */

Reply via email to