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 */