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,
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.