From: Christopher Zimmermann <madroach@zakweb.de>
To: sparclinux@vger.kernel.org
Subject: CS4231 for sbus
Date: Sun, 11 Sep 2005 20:54:57 +0000 [thread overview]
Message-ID: <20050911205457.GA1978@sparc> (raw)
[-- Attachment #1: Type: text/plain, Size: 738 bytes --]
Hi,
I completed the CS4231 for SBus. Playback does work on my Ultra2.
capture doesn't (yet). I hope my patch doesn't break support on EBus.
Unfortunatelly I have no access to any EBus based system.
I had a problem with the p_periods_sent counter. I worked around this by
passing only a dummy pointer to snd_cs4231_sbus_advance_dma in
cs4231_dma_trigger. Another option would be to change
ptr = period_bytes * (chip->p_periods_sent % substream->runtime->periods);
to
ptr = period_bytes * ((chip->p_periods_sent - 1) % substream->runtime->periods);
in snd_cs4231_playback_pointer, but I was afraid this could break the
EBus support. Any suggestions??
the driver works also without the '% substream->runtime->periods'. Why??
Christopher
[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 25606 bytes --]
--- linux-2.6.12.5/sound/sparc/cs4231.c 2005-08-15 02:20:18.000000000 +0200
+++ linux-2.6.12.5_patched/sound/sparc/cs4231.c 2005-09-11 22:34:47.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);
@@ -563,18 +573,15 @@
spin_lock_irqsave(&chip->lock, flags);
snd_cs4231_busy_wait(chip);
-#if 0
- printk("(1) timeout = %i\n", timeout);
-#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;
@@ -586,12 +593,12 @@
for (timeout = 500; timeout > 0 && (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0; timeout--)
udelay(100);
if ((snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0) {
- snd_printd("cs4231_mce_down - auto calibration time out (1)\n");
+ snd_printd("cs4231_mce_down - auto calibration time out (1): %d\n", timeout);
spin_unlock_irqrestore(&chip->lock, flags);
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 +612,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 +627,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 +655,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 +735,61 @@
} else {
#endif
#ifdef SBUS_SUPPORT
+ u32 csr = sbus_readl(chip->port + APCCSR);
+ unsigned int dummy;
+#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 +801,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 +826,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 +883,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 (mode=0x\%x)\n", format, 0);
#endif
return rformat;
}
@@ -944,7 +1036,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 +1049,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 +1059,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 +1073,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 +1083,7 @@
snd_cs4231_mce_down(chip);
#ifdef SNDRV_DEBUG_MCE
- snd_printk("init: (5)\n");
+ snd_printdd("init: (5)\n");
#endif
}
@@ -999,6 +1091,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 +1118,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 +1218,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 +1241,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 +1295,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 +1323,76 @@
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(status & 0x0f)
+ snd_printdd("cs4231: snd_cs4231_generic_interruptIRQ under- or overrun, status=%#.2x.\n", status);
+
+#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(csr & APC_XINT_PEMP || csr & APC_XINT_PEMP)
+ snd_printdd("cs4231: snd_cs4231_sbus_interruptIRQ DMA underrun, csr=%#.8x.\n", csr);
+
+ if(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(csr & APC_CAPT_INT && csr & APC_XINT_CNVA) {
+ snd_cs4231_sbus_advance_dma(chip->playback_substream, &chip->c_periods_sent);
+ snd_pcm_period_elapsed(chip->capture_substream);
+ }
+
+ if(csr & APC_XINT_CEMP)
+ ;
- return IRQ_HANDLED;
+ return snd_cs4231_generic_interrupt(chip);
}
#endif
@@ -1278,7 +1428,7 @@
if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
return 0;
period_bytes = snd_pcm_lib_period_bytes(substream);
- ptr = period_bytes * chip->p_periods_sent;
+ ptr = period_bytes * (chip->p_periods_sent % substream->runtime->periods);
#ifdef EBUS_SUPPORT
if (chip->flags & CS4231_FLAG_EBUS) {
residue = ebus_dma_residue(&chip->eb2p);
@@ -1290,7 +1440,17 @@
#ifdef EBUS_SUPPORT
}
#endif
+#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);
}
@@ -1315,6 +1475,9 @@
}
#endif
ptr += (period_bytes - residue);
+#if 0
+ snd_cs4231_debug(chip);
+#endif
return bytes_to_frames(substream->runtime, ptr);
}
@@ -1458,6 +1621,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 +1663,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 +2153,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 +2281,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 +2361,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 other threads:[~2005-09-11 20:54 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20050911205457.GA1978@sparc \
--to=madroach@zakweb.de \
--cc=sparclinux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.