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: