Re: alsa on 2.6 kernels, spdif patch
David Pye <[email protected]>
| Newsgroups | gmane.linux.ports.xbox.devel |
|---|---|
| Message-ID | <[email protected]> |
Whoops, found my first bug in the patch. Try the attached instead (Probably still won't work, but one step closer :) ) David
diff
(text/x-diff, 6.2 KB)
diff -urN alsa-driver-1.0.5/alsa-kernel/pci/ac97/ac97_codec.c alsa-xbox-1.0.5/alsa-kernel/pci/ac97/ac97_codec.c
--- alsa-driver-1.0.5/alsa-kernel/pci/ac97/ac97_codec.c 2004-05-28 10:27:09.000000000 +0100
+++ alsa-xbox-1.0.5/alsa-kernel/pci/ac97/ac97_codec.c 2004-11-24 00:52:24.000000000 +0000
@@ -1866,8 +1866,9 @@
ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
if (ac97->id == 0x00000000 || ac97->id == 0xffffffff) {
snd_printk(KERN_ERR "AC'97 %d access is not valid [0x%x], removing mixer.\n", ac97->num, ac97->id);
- snd_ac97_free(ac97);
- return -EIO;
+ //XBOX
+ //snd_ac97_free(ac97);
+ //return -EIO;
}
/* test for AC'97 */
@@ -1896,8 +1897,9 @@
if (!ac97_is_audio(ac97) && !ac97_is_modem(ac97)) {
if (!(ac97->scaps & (AC97_SCAP_SKIP_AUDIO|AC97_SCAP_SKIP_MODEM)))
snd_printk(KERN_ERR "AC'97 %d access error (not audio or modem codec)\n", ac97->num);
- snd_ac97_free(ac97);
- return -EACCES;
+ //XBOX
+ //snd_ac97_free(ac97);
+ //return -EACCES;
}
if (bus->reset) // FIXME: always skipping?
diff -urN alsa-driver-1.0.5/alsa-kernel/pci/intel8x0.c alsa-xbox-1.0.5/alsa-kernel/pci/intel8x0.c
--- alsa-driver-1.0.5/alsa-kernel/pci/intel8x0.c 2004-04-26 08:47:09.000000000 +0100
+++ alsa-xbox-1.0.5/alsa-kernel/pci/intel8x0.c 2004-11-24 00:54:42.000000000 +0000
@@ -25,6 +25,7 @@
*
*/
+#define XBOX
#include <sound/driver.h>
#include <asm/io.h>
@@ -393,6 +394,9 @@
unsigned int int_sta_mask; /* interrupt status mask */
unsigned int ali_slot; /* ALI DMA slot */
struct ac97_pcm *pcm;
+#ifdef XBOX
+ unsigned int lastRetiredDescriptorIndex;
+#endif
int pcm_open_flag;
} ichdev_t;
@@ -748,7 +752,12 @@
ichdev->lvi_frag, ichdev->frags, ichdev->fragsize, ichdev->fragsize1);
#endif
/* clear interrupts */
+#ifdef XBOX
+ ichdev->lastRetiredDescriptorIndex=0xffffffff;
+ iputbyte(chip,port+0x06,0xff);
+#else
iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
+#endif
}
#ifdef __i386__
@@ -774,6 +783,45 @@
static inline void snd_intel8x0_update(intel8x0_t *chip, ichdev_t *ichdev)
{
+#ifdef XBOX
+ unsigned long port = ichdev->reg_offset;
+ int ack = 0;
+
+ printk("Running snd_intel8x0_update on BMDMA %u\n", ichdev->ichd);
+ spin_lock(&chip->reg_lock);
+ ichdev->lastRetiredDescriptorIndex++; // track last used up buffer
+ if(ichdev->lastRetiredDescriptorIndex==0x7fffffff) ichdev->lastRetiredDescriptorIndex=2;
+ iputbyte(chip, ichdev->reg_offset + ICH_REG_OFF_LVI, (chip->ichd[ICHD_PCMOUT].lvi+1)& ICH_REG_LVI_MASK);
+ if(ichdev->lastRetiredDescriptorIndex>1) {
+ if(chip->ichd[ICHD_PCMOUT].lastRetiredDescriptorIndex
+ == chip->ichd[NVD_SPBAR].lastRetiredDescriptorIndex) {
+ chip->ichd[NVD_PCMOUT].position += chip->ichd[NVD_PCMOUT].fragsize1;
+ chip->ichd[NVD_PCMOUT].position %= chip->ichd[NVD_PCMOUT].size;
+ chip->ichd[NVD_PCMOUT].lvi++;
+ chip->ichd[NVD_PCMOUT].lvi &= ICH_REG_LVI_MASK;
+ chip->ichd[NVD_PCMOUT].lvi_frag++;
+ chip->ichd[NVD_PCMOUT].lvi_frag %= chip->ichd[NVD_PCMOUT].frags;
+ ichdev->bdbar[chip->ichd[NVD_PCMOUT].lvi * 2] =
+ cpu_to_le32(chip->ichd[NVD_PCMOUT].physbuf +
+ chip->ichd[NVD_PCMOUT].lvi_frag *
+ chip->ichd[NVD_PCMOUT].fragsize1
+ );
+
+ if ((ack = (--chip->ichd[NVD_PCMOUT].ack == 0))) {
+ chip->ichd[NVD_PCMOUT].ack =
+ chip->ichd[NVD_PCMOUT].ack_reload;
+ }
+
+ if (ack && chip->ichd[NVD_PCMOUT].substream) {
+ snd_pcm_period_elapsed(chip->ichd[NVD_PCMOUT].substream);
+ }
+ }
+ }
+
+ // clear interrupt from this DMA channel
+ iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
+ spin_unlock(&chip->reg_lock);
+#else
unsigned long port = ichdev->reg_offset;
int status, civ, i, step;
int ack = 0;
@@ -818,6 +866,7 @@
}
iputbyte(chip, port + ichdev->roff_sr,
status & (ICH_FIFOE | ICH_BCIS | ICH_LVBCI));
+#endif
}
static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -829,6 +878,8 @@
spin_lock(&chip->reg_lock);
status = igetdword(chip, chip->int_sta_reg);
+#ifndef XBOX
+ //Xbox S/PDIF IRQ not in normal SR, defeat check for Xbox
if ((status & chip->int_sta_mask) == 0) {
if (status) {
/* ack */
@@ -842,17 +893,26 @@
spin_unlock(&chip->reg_lock);
return IRQ_RETVAL(status);
}
-
+#endif
for (i = 0; i < chip->bdbars_count; i++) {
+ unsigned char b;
ichdev = &chip->ichd[i];
+#ifdef XBOX
+ b=igetbyte(chip, ichdev->reg_offset + 0x06);
+ if (b&0x10) {
+ printk("FIFO underrun ch %d\n",i);
+ }
+ if (b&8)
+#else
if (status & ichdev->int_sta_mask)
+#endif
snd_intel8x0_update(chip, ichdev);
}
/* ack them */
iputdword(chip, chip->int_sta_reg, status & chip->int_sta_mask);
spin_unlock(&chip->reg_lock);
-
+
return IRQ_HANDLED;
}
@@ -886,9 +946,20 @@
return -EINVAL;
}
iputbyte(chip, port + ICH_REG_OFF_CR, val);
+#ifdef XBOX
+ if (ichdev->ichd == NVD_PCMOUT) {
+ //LOCKSTEP the SPDIF
+ iputbyte(chip,chip->ichd[NVD_SPBAR].reg_offset + ICH_REG_OFF_CR,val);
+ }
+#endif
+
+
if (cmd == SNDRV_PCM_TRIGGER_STOP) {
/* wait until DMA stopped */
+#ifndef XBOX
+ //Seems to hard freeze it!
while (!(igetbyte(chip, port + ichdev->roff_sr) & ICH_DCH)) ;
+#endif
/* reset whole DMA things */
iputbyte(chip, port + ICH_REG_OFF_CR, ICH_RESETREGS);
}
@@ -1051,6 +1122,16 @@
}
}
snd_intel8x0_setup_periods(chip, ichdev);
+#ifdef XBOX
+ if (ichdev->ichd == NVD_PCMOUT) {
+ //Lockstep SPDIF again
+ printk("snd_intel8x0_pcm_prepare doing S/PDIF lockstep\n");
+ chip->ichd[NVD_SPBAR].physbuf = runtime->dma_addr;
+ chip->ichd[NVD_SPBAR].size = snd_pcm_lib_buffer_bytes(substream);
+ chip->ichd[NVD_SPBAR].fragsize = snd_pcm_lib_period_bytes(substream);
+ snd_intel8x0_setup_periods(chip, &chip->ichd[NVD_SPBAR]);
+ }
+#endif
return 0;
}
@@ -2339,8 +2420,12 @@
printk(KERN_INFO "intel8x0: measured clock %ld rejected\n", pos);
else if (pos < 47500 || pos > 48500)
/* not 48000Hz, tuning the clock.. */
+#ifdef XBOX
+ chip->ac97_bus->clock=48000;
+#else
chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos;
- printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock);
+#endif
+ printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock);
}
static void snd_intel8x0_proc_read(snd_info_entry_t * entry,