[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Unlucky kernel upgrade on Ultra 5/10



I'll try that again :)

On Mon, Sep 26, 2005 at 12:03:52PM +0100, Martin Habets wrote:
> > You mean this one : FYI: Fixes to ALSA DBRI driver ?
> > Does it apply also to the CS4231 chipset ?
> 
> Could not see the patch from Christopher Zimmermann in the sparclinux archives.
> Maybe because sparclinux only was on the cc. I've attached it below.
> DBRI are not relevant to CS4231.
--- linux-2.6.13.1/sound/sparc/cs4231.c	2005-09-10 04:42:58.000000000 +0200
+++ linux-2.6.13.1_patched/sound/sparc/cs4231.c	2005-09-14 17:09:49.000000000 +0200
@@ -173,7 +173,7 @@
 
 #define CS4231_GLOBALIRQ	0x01	/* IRQ is active */
 
-/* definitions for codec irq status */
+/* definitions for codec irq status - CS4231_IRQ_STATUS	*/
 
 #define CS4231_PLAYBACK_IRQ	0x10
 #define CS4231_RECORD_IRQ	0x20
@@ -402,7 +402,7 @@
 	     	udelay(100);
 #ifdef CONFIG_SND_DEBUG
 	if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-		snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+		snd_printdd("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
 #endif
 	if (chip->calibrate_mute) {
 		chip->image[reg] &= mask;
@@ -425,6 +425,10 @@
 	     timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
 	     timeout--)
 	     	udelay(100);
+#ifdef CONFIG_SND_DEBUG
+	if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
+		snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+#endif
 	__cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
 	__cs4231_writeb(chip, value, CS4231P(chip, REG));
 	mb();
@@ -440,14 +444,14 @@
 	     	udelay(100);
 #ifdef CONFIG_SND_DEBUG
 	if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-		snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
+		snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
 #endif
 	__cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
 	__cs4231_writeb(chip, value, CS4231P(chip, REG));
 	chip->image[reg] = value;
 	mb();
 #if 0
-	printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value);
+	snd_printdd("codec out - reg 0x%x = 0x%x | timeout = %d\n", chip->mce_bit | reg, value, timeout);
 #endif
 }
 
@@ -462,13 +466,13 @@
 	     	udelay(100);
 #ifdef CONFIG_SND_DEBUG
 	if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-		snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
+		snd_printdd("in: auto calibration time out - reg = 0x%x\n", reg);
 #endif
 	__cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
 	mb();
 	ret = __cs4231_readb(chip, CS4231P(chip, REG));
 #if 0
-	printk("codec in - reg 0x%x = 0x%x\n", chip->mce_bit | reg, ret);
+	snd_printdd("codec in - reg 0x%x = 0x%x\n", chip->mce_bit | reg, ret);
 #endif
 	return ret;
 }
@@ -477,42 +481,42 @@
 
 static void snd_cs4231_debug(cs4231_t *chip)
 {
-	printk("CS4231 REGS:      INDEX = 0x%02x  ",
+	snd_printdd("CS4231 REGS:      INDEX = 0x%02x\n",
 	       __cs4231_readb(chip, CS4231P(chip, REGSEL)));
-	printk("                 STATUS = 0x%02x\n",
+	snd_printdd("                 STATUS = 0x%02x\n",
 	       __cs4231_readb(chip, CS4231P(chip, STATUS)));
-	printk("  0x00: left input      = 0x%02x  ", snd_cs4231_in(chip, 0x00));
-	printk("  0x10: alt 1 (CFIG 2)  = 0x%02x\n", snd_cs4231_in(chip, 0x10));
-	printk("  0x01: right input     = 0x%02x  ", snd_cs4231_in(chip, 0x01));
-	printk("  0x11: alt 2 (CFIG 3)  = 0x%02x\n", snd_cs4231_in(chip, 0x11));
-	printk("  0x02: GF1 left input  = 0x%02x  ", snd_cs4231_in(chip, 0x02));
-	printk("  0x12: left line in    = 0x%02x\n", snd_cs4231_in(chip, 0x12));
-	printk("  0x03: GF1 right input = 0x%02x  ", snd_cs4231_in(chip, 0x03));
-	printk("  0x13: right line in   = 0x%02x\n", snd_cs4231_in(chip, 0x13));
-	printk("  0x04: CD left input   = 0x%02x  ", snd_cs4231_in(chip, 0x04));
-	printk("  0x14: timer low       = 0x%02x\n", snd_cs4231_in(chip, 0x14));
-	printk("  0x05: CD right input  = 0x%02x  ", snd_cs4231_in(chip, 0x05));
-	printk("  0x15: timer high      = 0x%02x\n", snd_cs4231_in(chip, 0x15));
-	printk("  0x06: left output     = 0x%02x  ", snd_cs4231_in(chip, 0x06));
-	printk("  0x16: left MIC (PnP)  = 0x%02x\n", snd_cs4231_in(chip, 0x16));
-	printk("  0x07: right output    = 0x%02x  ", snd_cs4231_in(chip, 0x07));
-	printk("  0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17));
-	printk("  0x08: playback format = 0x%02x  ", snd_cs4231_in(chip, 0x08));
-	printk("  0x18: IRQ status      = 0x%02x\n", snd_cs4231_in(chip, 0x18));
-	printk("  0x09: iface (CFIG 1)  = 0x%02x  ", snd_cs4231_in(chip, 0x09));
-	printk("  0x19: left line out   = 0x%02x\n", snd_cs4231_in(chip, 0x19));
-	printk("  0x0a: pin control     = 0x%02x  ", snd_cs4231_in(chip, 0x0a));
-	printk("  0x1a: mono control    = 0x%02x\n", snd_cs4231_in(chip, 0x1a));
-	printk("  0x0b: init & status   = 0x%02x  ", snd_cs4231_in(chip, 0x0b));
-	printk("  0x1b: right line out  = 0x%02x\n", snd_cs4231_in(chip, 0x1b));
-	printk("  0x0c: revision & mode = 0x%02x  ", snd_cs4231_in(chip, 0x0c));
-	printk("  0x1c: record format   = 0x%02x\n", snd_cs4231_in(chip, 0x1c));
-	printk("  0x0d: loopback        = 0x%02x  ", snd_cs4231_in(chip, 0x0d));
-	printk("  0x1d: var freq (PnP)  = 0x%02x\n", snd_cs4231_in(chip, 0x1d));
-	printk("  0x0e: ply upr count   = 0x%02x  ", snd_cs4231_in(chip, 0x0e));
-	printk("  0x1e: rec upr count   = 0x%02x\n", snd_cs4231_in(chip, 0x1e));
-	printk("  0x0f: ply lwr count   = 0x%02x  ", snd_cs4231_in(chip, 0x0f));
-	printk("  0x1f: rec lwr count   = 0x%02x\n", snd_cs4231_in(chip, 0x1f));
+	snd_printdd("  0x00: left input      = 0x%02x\n", snd_cs4231_in(chip, 0x00));
+	snd_printdd("  0x10: alt 1 (CFIG 2)  = 0x%02x\n", snd_cs4231_in(chip, 0x10));
+	snd_printdd("  0x01: right input     = 0x%02x\n", snd_cs4231_in(chip, 0x01));
+	snd_printdd("  0x11: alt 2 (CFIG 3)  = 0x%02x\n", snd_cs4231_in(chip, 0x11));
+	snd_printdd("  0x02: GF1 left input  = 0x%02x\n", snd_cs4231_in(chip, 0x02));
+	snd_printdd("  0x12: left line in    = 0x%02x\n", snd_cs4231_in(chip, 0x12));
+	snd_printdd("  0x03: GF1 right input = 0x%02x\n", snd_cs4231_in(chip, 0x03));
+	snd_printdd("  0x13: right line in   = 0x%02x\n", snd_cs4231_in(chip, 0x13));
+	snd_printdd("  0x04: CD left input   = 0x%02x\n", snd_cs4231_in(chip, 0x04));
+	snd_printdd("  0x14: timer low       = 0x%02x\n", snd_cs4231_in(chip, 0x14));
+	snd_printdd("  0x05: CD right input  = 0x%02x\n", snd_cs4231_in(chip, 0x05));
+	snd_printdd("  0x15: timer high      = 0x%02x\n", snd_cs4231_in(chip, 0x15));
+	snd_printdd("  0x06: left output     = 0x%02x\n", snd_cs4231_in(chip, 0x06));
+	snd_printdd("  0x16: left MIC (PnP)  = 0x%02x\n", snd_cs4231_in(chip, 0x16));
+	snd_printdd("  0x07: right output    = 0x%02x\n", snd_cs4231_in(chip, 0x07));
+	snd_printdd("  0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17));
+	snd_printdd("  0x08: playback format = 0x%02x\n", snd_cs4231_in(chip, 0x08));
+	snd_printdd("  0x18: IRQ status      = 0x%02x\n", snd_cs4231_in(chip, 0x18));
+	snd_printdd("  0x09: iface (CFIG 1)  = 0x%02x\n", snd_cs4231_in(chip, 0x09));
+	snd_printdd("  0x19: left line out   = 0x%02x\n", snd_cs4231_in(chip, 0x19));
+	snd_printdd("  0x0a: pin control     = 0x%02x\n", snd_cs4231_in(chip, 0x0a));
+	snd_printdd("  0x1a: mono control    = 0x%02x\n", snd_cs4231_in(chip, 0x1a));
+	snd_printdd("  0x0b: init & status   = 0x%02x\n", snd_cs4231_in(chip, 0x0b));
+	snd_printdd("  0x1b: right line out  = 0x%02x\n", snd_cs4231_in(chip, 0x1b));
+	snd_printdd("  0x0c: revision & mode = 0x%02x\n", snd_cs4231_in(chip, 0x0c));
+	snd_printdd("  0x1c: record format   = 0x%02x\n", snd_cs4231_in(chip, 0x1c));
+	snd_printdd("  0x0d: loopback        = 0x%02x\n", snd_cs4231_in(chip, 0x0d));
+	snd_printdd("  0x1d: var freq (PnP)  = 0x%02x\n", snd_cs4231_in(chip, 0x1d));
+	snd_printdd("  0x0e: ply upr count   = 0x%02x\n", snd_cs4231_in(chip, 0x0e));
+	snd_printdd("  0x1e: rec upr count   = 0x%02x\n", snd_cs4231_in(chip, 0x1e));
+	snd_printdd("  0x0f: ply lwr count   = 0x%02x\n", snd_cs4231_in(chip, 0x0f));
+	snd_printdd("  0x1f: rec lwr count   = 0x%02x\n", snd_cs4231_in(chip, 0x1f));
 }
 
 #endif
@@ -528,11 +532,17 @@
 	/* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
 	for (timeout = 5; timeout > 0; timeout--)
 		__cs4231_readb(chip, CS4231P(chip, REGSEL));
+#if 0
+	snd_printdd("(0) timeout = %i\n", timeout);
+#endif
 	/* end of cleanup sequence */
-	for (timeout = 250;
+	for (timeout = 500;
 	     timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
 	     timeout--)
-	     	udelay(100);
+	     	udelay(1000);
+#if 0
+	snd_printdd("(1) timeout = %i\n", timeout);
+#endif
 }
 
 static void snd_cs4231_mce_up(cs4231_t *chip)
@@ -545,12 +555,12 @@
 		udelay(100);
 #ifdef CONFIG_SND_DEBUG
 	if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-		snd_printk("mce_up - auto calibration time out (0)\n");
+		snd_printdd("mce_up - auto calibration time out (0)\n");
 #endif
 	chip->mce_bit |= CS4231_MCE;
 	timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
 	if (timeout == 0x80)
-		snd_printk("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
+		snd_printdd("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
 	if (!(timeout & CS4231_MCE))
 		__cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
 	spin_unlock_irqrestore(&chip->lock, flags);
@@ -568,13 +578,13 @@
 #endif
 #ifdef CONFIG_SND_DEBUG
 	if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
-		snd_printk("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
+		snd_printdd("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
 #endif
 	chip->mce_bit &= ~CS4231_MCE;
 	timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
 	__cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
 	if (timeout == 0x80)
-		snd_printk("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
+		snd_printdd("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
 	if ((timeout & CS4231_MCE) == 0) {
 		spin_unlock_irqrestore(&chip->lock, flags);
 		return;
@@ -591,7 +601,7 @@
 		return;
 	}
 #if 0
-	printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
+	snd_printdd("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
 #endif
 	/* in 10ms increments, check condition, up to 250ms */
 	timeout = 25;
@@ -605,7 +615,7 @@
 		spin_lock_irqsave(&chip->lock, flags);
 	}
 #if 0
-	printk("(3) jiffies = %li\n", jiffies);
+	snd_printdd("(3) jiffies = %li\n", jiffies);
 #endif
 	/* in 10ms increments, check condition, up to 100ms */
 	timeout = 10;
@@ -620,8 +630,8 @@
 	}
 	spin_unlock_irqrestore(&chip->lock, flags);
 #if 0
-	printk("(4) jiffies = %li\n", jiffies);
-	snd_printk("mce_down - exit = 0x%x\n", __cs4231_readb(chip, CS4231P(chip, REGSEL)));
+	snd_printdd("(4) jiffies = %li\n", jiffies);
+	snd_printdd("mce_down - exit = 0x%x\n", __cs4231_readb(chip, CS4231P(chip, REGSEL)));
 #endif
 }
 
@@ -648,25 +658,59 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 
 	while (1) {
-		unsigned int dma_size = snd_pcm_lib_period_bytes(substream);
-		unsigned int offset = dma_size * (*periods_sent);
+		unsigned int period_size = snd_pcm_lib_period_bytes(substream);
+		unsigned int offset = period_size * (*periods_sent);
 
-		if (dma_size >= (1 << 24))
+		if (period_size >= (1 << 24))
 			BUG();
 
-		if (ebus_dma_request(p, runtime->dma_addr + offset, dma_size))
+		if (ebus_dma_request(p, runtime->dma_addr + offset, period_size))
 			return;
 #if 0
-		printk("ebus_advance: Sent period %u (size[%x] offset[%x])\n",
-		       (*periods_sent), dma_size, offset);
+		snd_printdd("ebus_advance: Sent period %u (size[%x] offset[%x])\n",
+		       (*periods_sent), period_size, offset);
 #endif
 		(*periods_sent) = ((*periods_sent) + 1) % runtime->periods;
 	}
 }
 #endif
 
-static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on)
+#ifdef SBUS_SUPPORT
+static void snd_cs4231_sbus_advance_dma(snd_pcm_substream_t *substream, unsigned int *periods_sent)
+{
+	cs4231_t *chip = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+
+	unsigned int period_size = snd_pcm_lib_period_bytes(substream);
+	unsigned int offset = period_size * (*periods_sent % runtime->periods);
+
+	if(runtime->period_size > 0xffff + 1)
+		BUG();
+
+#if 0
+	snd_printdd("sbus_advance: period_size: %#x | runtime->dma_addr: %#x | offset: %#x | total: %#x\n",
+			period_size, runtime->dma_addr, offset, runtime->dma_addr + offset);
+#endif
+
+	switch(substream->stream) {
+	case SNDRV_PCM_STREAM_PLAYBACK:
+		sbus_writel(runtime->dma_addr + offset, chip->port + APCPNVA);
+		sbus_writel(period_size, chip->port + APCPNC);
+		break;
+	case SNDRV_PCM_STREAM_CAPTURE:
+		sbus_writel(runtime->dma_addr + offset, chip->port + APCCNVA);
+		sbus_writel(period_size, chip->port + APCCNC);
+		break;
+	}
+
+	(*periods_sent) = (*periods_sent + 1) % runtime->periods;
+}
+#endif
+
+static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on)
 {
+	cs4231_t *chip = snd_pcm_substream_chip(substream);
+
 #ifdef EBUS_SUPPORT
 	if (chip->flags & CS4231_FLAG_EBUS) {
 		if (what & CS4231_PLAYBACK_ENABLE) {
@@ -694,6 +738,64 @@
 	} else {
 #endif
 #ifdef SBUS_SUPPORT
+	u32 csr = sbus_readl(chip->port + APCCSR);
+	/* I don't know why, but on sbus the period counter must
+	 * only start counting after the first period is sent.
+	 * Therefore this dummy thing. */
+	unsigned int dummy = 0;
+#if 0
+	snd_printdd("cs4231: DMA trigger\n");
+#endif
+
+	switch(what) {
+	case CS4231_PLAYBACK_ENABLE:
+		if(on) {
+			csr &= ~APC_XINT_PLAY;
+			sbus_writel(csr, chip->port + APCCSR);
+
+			csr &= ~APC_PPAUSE;
+			sbus_writel(csr, chip->port + APCCSR);
+
+			snd_cs4231_sbus_advance_dma(substream, &dummy);
+
+			csr |=  APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA |
+				APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL |
+				APC_XINT_PENA | APC_PDMA_READY;
+			sbus_writel(csr, chip->port + APCCSR);
+		}
+		else {
+			csr |= APC_PPAUSE;
+			sbus_writel(csr, chip->port + APCCSR);
+
+			csr &= ~APC_PDMA_READY;
+			sbus_writel(csr, chip->port + APCCSR);
+		}
+		break;
+	case CS4231_RECORD_ENABLE:
+		if(on) {
+			csr &= ~APC_XINT_CAPT;
+			sbus_writel(csr, chip->port + APCCSR);
+
+			csr &= ~APC_CPAUSE;
+			sbus_writel(csr, chip->port + APCCSR);
+
+			snd_cs4231_sbus_advance_dma(substream, &dummy);
+
+			csr |=  APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA |
+				APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL |
+				APC_CDMA_READY;
+
+			sbus_writel(csr, chip->port + APCCSR);
+		}
+		else {
+			csr |= APC_CPAUSE;
+			sbus_writel(csr, chip->port + APCCSR);
+
+			csr &= ~APC_CDMA_READY;
+			sbus_writel(csr, chip->port + APCCSR);
+		}
+		break;
+	}
 #endif
 #ifdef EBUS_SUPPORT
 	}
@@ -705,6 +807,10 @@
 	cs4231_t *chip = snd_pcm_substream_chip(substream);
 	int result = 0;
 
+#if 0
+	snd_printdd("cs4231: snd_cs4231_trigger.\n");
+#endif
+
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_STOP:
@@ -726,24 +832,16 @@
 		}
 
 #if 0
-		printk("TRIGGER: what[%x] on(%d)\n",
+		snd_printdd("TRIGGER: what[%x] on(%d)\n",
 		       what, (cmd == SNDRV_PCM_TRIGGER_START));
 #endif
 
 		spin_lock_irqsave(&chip->lock, flags);
 		if (cmd == SNDRV_PCM_TRIGGER_START) {
-			cs4231_dma_trigger(chip, what, 1);
+			cs4231_dma_trigger(substream, what, 1);
 			chip->image[CS4231_IFACE_CTRL] |= what;
-			if (what & CS4231_PLAYBACK_ENABLE) {
-				snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, 0xff);
-				snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, 0xff);
-			}
-			if (what & CS4231_RECORD_ENABLE) {
-				snd_cs4231_out(chip, CS4231_REC_LWR_CNT, 0xff);
-				snd_cs4231_out(chip, CS4231_REC_UPR_CNT, 0xff);
-			}
 		} else {
-			cs4231_dma_trigger(chip, what, 0);
+			cs4231_dma_trigger(substream, what, 0);
 			chip->image[CS4231_IFACE_CTRL] &= ~what;
 		}
 		snd_cs4231_out(chip, CS4231_IFACE_CTRL,
@@ -791,7 +889,7 @@
 	if (channels > 1)
 		rformat |= CS4231_STEREO;
 #if 0
-	snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
+	snd_printdd("get_format: 0x%x\n", format);
 #endif
 	return rformat;
 }
@@ -944,7 +1042,7 @@
 	snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-	snd_printk("init: (1)\n");
+	snd_printdd("init: (1)\n");
 #endif
 	snd_cs4231_mce_up(chip);
 	spin_lock_irqsave(&chip->lock, flags);
@@ -957,7 +1055,7 @@
 	snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-	snd_printk("init: (2)\n");
+	snd_printdd("init: (2)\n");
 #endif
 
 	snd_cs4231_mce_up(chip);
@@ -967,7 +1065,7 @@
 	snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-	snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
+	snd_printdd("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
 #endif
 
 	spin_lock_irqsave(&chip->lock, flags);
@@ -981,7 +1079,7 @@
 	snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-	snd_printk("init: (4)\n");
+	snd_printdd("init: (4)\n");
 #endif
 
 	snd_cs4231_mce_up(chip);
@@ -991,7 +1089,7 @@
 	snd_cs4231_mce_down(chip);
 
 #ifdef SNDRV_DEBUG_MCE
-	snd_printk("init: (5)\n");
+	snd_printdd("init: (5)\n");
 #endif
 }
 
@@ -999,6 +1097,10 @@
 {
 	unsigned long flags;
 
+#if 0
+	snd_printdd("cs4231: snd_cs4231_open.\n");
+#endif
+
 	down(&chip->open_mutex);
 	if ((chip->mode & mode)) {
 		up(&chip->open_mutex);
@@ -1022,6 +1124,11 @@
 		       CS4231_RECORD_IRQ |
 		       CS4231_TIMER_IRQ);
 	snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
+
+#if 0
+	snd_cs4231_debug(chip);
+#endif
+
 	spin_unlock_irqrestore(&chip->lock, flags);
 
 	chip->mode = mode;
@@ -1117,6 +1224,10 @@
 	unsigned char new_pdfr;
 	int err;
 
+#if 0
+	snd_printdd("cs4231: snd_cs4231_playback_hw_params.\n");
+#endif
+
 	if ((err = snd_pcm_lib_malloc_pages(substream,
 					    params_buffer_bytes(hw_params))) < 0)
 		return err;
@@ -1136,11 +1247,29 @@
 static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream)
 {
 	cs4231_t *chip = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned long flags;
 
+#if 0
+	snd_printdd("cs4231: snd_cs4231_playback_prepare.\n");
+#endif
+
 	spin_lock_irqsave(&chip->lock, flags);
+
 	chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
 					    CS4231_PLAYBACK_PIO);
+
+	if(runtime->period_size > 0xffff + 1)
+		BUG();
+
+	snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (runtime->period_size - 1) & 0x00ff);
+	snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff);
+	chip->p_periods_sent = 0;
+
+#if 0
+	snd_cs4231_debug(chip);
+#endif
+
 	spin_unlock_irqrestore(&chip->lock, flags);
 
 	return 0;
@@ -1172,12 +1301,16 @@
 static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream)
 {
 	cs4231_t *chip = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->lock, flags);
 	chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE |
 					    CS4231_RECORD_PIO);
 
+	snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) & 0x00ff);
+	snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff);
+
 	spin_unlock_irqrestore(&chip->lock, flags);
 
 	return 0;
@@ -1196,53 +1329,91 @@
 		chip->capture_substream->runtime->overrange++;
 }
 
-static void snd_cs4231_generic_interrupt(cs4231_t *chip)
+static irqreturn_t snd_cs4231_generic_interrupt(cs4231_t *chip)
 {
 	unsigned long flags;
 	unsigned char status;
 
+	/*This is IRQ is not raised by the cs4231*/
+	if(!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ))
+		return IRQ_NONE;
+
 	status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
-	if (!status)
-		return;
 
-	if (status & CS4231_TIMER_IRQ) {
+#if 0
+	snd_printdd("cs4231: snd_cs4231_generic_interruptIRQ, status=%#.2x.\n", status);
+#endif
+
+	if(status & CS4231_TIMER_IRQ) {
 		if (chip->timer)
 			snd_timer_interrupt(chip->timer, chip->timer->sticks);
 	}		
-	if (status & CS4231_PLAYBACK_IRQ)
-		snd_pcm_period_elapsed(chip->playback_substream);
-	if (status & CS4231_RECORD_IRQ) {
+
+#if 0
+	if(status & 0x0f)
+		snd_printdd("cs4231: snd_cs4231_generic_interruptIRQ under- or overrun, status=%#.2x.\n", status);
+#endif
+	
+#if 0
+	if(status & CS4231_PLAYBACK_IRQ)
+		;
+#endif
+
+	if(status & CS4231_RECORD_IRQ)
 		snd_cs4231_overrange(chip);
-		snd_pcm_period_elapsed(chip->capture_substream);
-	}
 
 	/* ACK the CS4231 interrupt. */
 	spin_lock_irqsave(&chip->lock, flags);
 	snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
 	spin_unlock_irqrestore(&chip->lock, flags);
+
+	return 0;
 }
 
 #ifdef SBUS_SUPPORT
 static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	cs4231_t *chip = dev_id;
-	u32 csr;
-
-	csr = sbus_readl(chip->port + APCCSR);
-	if (!(csr & (APC_INT_PENDING |
-		     APC_PLAY_INT |
-		     APC_CAPT_INT |
-		     APC_GENL_INT |
-		     APC_XINT_PEMP |
-		     APC_XINT_CEMP)))
-		return IRQ_NONE;
 
 	/* ACK the APC interrupt. */
+	u32 csr = sbus_readl(chip->port + APCCSR);
+#if 0
+	static unsigned int irqcount;
+	snd_printdd("cs4231: snd_cs4231_sbus_interruptIRQ No%u, csr=%#.8x.\n", irqcount++, csr);
+	/*snd_cs4231_debug(chip);*/
+#endif
 	sbus_writel(csr, chip->port + APCCSR);
 
-	snd_cs4231_generic_interrupt(chip);
+#if 0
+	if(csr & APC_XINT_PEMP || csr & APC_XINT_PEMP)
+		snd_printdd("cs4231: snd_cs4231_sbus_interruptIRQ DMA underrun, csr=%#.8x.\n", csr);
+#endif
 
-	return IRQ_HANDLED;
+	if(
+		chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE &&
+		csr & APC_PLAY_INT &&
+		csr & APC_XINT_PNVA &&
+		!(csr & APC_XINT_EMPT))
+	{
+		snd_cs4231_sbus_advance_dma(chip->playback_substream, &chip->p_periods_sent);
+		snd_pcm_period_elapsed(chip->playback_substream);
+	}
+
+	if(
+		chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE &&
+		csr & APC_CAPT_INT &&
+		csr & APC_XINT_CNVA)
+	{
+		snd_cs4231_sbus_advance_dma(chip->capture_substream, &chip->c_periods_sent);
+		snd_pcm_period_elapsed(chip->capture_substream);
+	}
+
+#if 0
+	if(csr & APC_XINT_CEMP)
+		;
+#endif
+
+	return snd_cs4231_generic_interrupt(chip);
 }
 #endif
 
@@ -1290,7 +1461,17 @@
 #ifdef EBUS_SUPPORT
 	}
 #endif
-	ptr += (period_bytes - residue);
+#if 0
+	snd_printdd("Residue: %u\n", (unsigned)residue);
+#endif
+	ptr += period_bytes - residue;
+
+#if 0
+	snd_printdd("cs4231: snd_cs4231_playback_pointer: residue: %#x | ptr: %#x\n",
+			(unsigned)bytes_to_frames(substream->runtime, residue),
+			(unsigned)bytes_to_frames(substream->runtime, ptr));
+#endif
+
 	return bytes_to_frames(substream->runtime, ptr);
 }
 
@@ -1314,7 +1495,10 @@
 #ifdef EBUS_SUPPORT
 	}
 #endif
-	ptr += (period_bytes - residue);
+	ptr += period_bytes - residue;
+#if 0
+	snd_cs4231_debug(chip);
+#endif
 	return bytes_to_frames(substream->runtime, ptr);
 }
 
@@ -1458,6 +1642,10 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	int err;
 
+#if 0
+	snd_printdd("cs4231: snd_cs4231_playback_open.\n");
+#endif
+
 	runtime->hw = snd_cs4231_playback;
 
 	if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) {
@@ -1496,6 +1684,10 @@
 {
 	cs4231_t *chip = snd_pcm_substream_chip(substream);
 
+#if 0
+	snd_printdd("cs4231: snd_cs4231_playback_close.\n");
+#endif
+
 	chip->playback_substream = NULL;
 	snd_cs4231_close(chip, CS4231_MODE_PLAY);
 
@@ -1982,13 +2174,13 @@
 	chip->port = sbus_ioremap(&sdev->resource[0], 0,
 				  chip->regs_size, "cs4231");
 	if (!chip->port) {
-		snd_printk("cs4231-%d: Unable to map chip registers.\n", dev);
+		snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev);
 		return -EIO;
 	}
 
 	if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt,
 			SA_SHIRQ, "cs4231", chip)) {
-		snd_printk("cs4231-%d: Unable to grab SBUS IRQ %s\n",
+		snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n",
 			   dev,
 			   __irq_itoa(sdev->irqs[0]));
 		snd_cs4231_sbus_free(chip);
@@ -2110,29 +2302,29 @@
 	chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10);
 	if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) {
 		snd_cs4231_ebus_free(chip);
-		snd_printk("cs4231-%d: Unable to map chip registers.\n", dev);
+		snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev);
 		return -EIO;
 	}
 
 	if (ebus_dma_register(&chip->eb2c)) {
 		snd_cs4231_ebus_free(chip);
-		snd_printk("cs4231-%d: Unable to register EBUS capture DMA\n", dev);
+		snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev);
 		return -EBUSY;
 	}
 	if (ebus_dma_irq_enable(&chip->eb2c, 1)) {
 		snd_cs4231_ebus_free(chip);
-		snd_printk("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev);
+		snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev);
 		return -EBUSY;
 	}
 
 	if (ebus_dma_register(&chip->eb2p)) {
 		snd_cs4231_ebus_free(chip);
-		snd_printk("cs4231-%d: Unable to register EBUS play DMA\n", dev);
+		snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev);
 		return -EBUSY;
 	}
 	if (ebus_dma_irq_enable(&chip->eb2p, 1)) {
 		snd_cs4231_ebus_free(chip);
-		snd_printk("cs4231-%d: Unable to enable EBUS play IRQ\n", dev);
+		snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev);
 		return -EBUSY;
 	}
 
@@ -2190,6 +2382,10 @@
 
 	found = 0;
 
+#if 0
+	snd_printdd("cs4231: XXX\n");
+#endif
+
 #ifdef SBUS_SUPPORT
 	for_all_sbusdev(sdev, sbus) {
 		if (!strcmp(sdev->prom_name, "SUNW,CS4231")) {

Reply to: