|
@@ -173,7 +173,7 @@ static cs4231_t *cs4231_list;
|
|
|
|
|
|
#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 @@ static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
|
|
|
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 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val
|
|
|
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,15 +444,12 @@ static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char valu
|
|
|
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);
|
|
|
-#endif
|
|
|
}
|
|
|
|
|
|
static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
|
|
@@ -462,61 +463,14 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
|
|
|
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);
|
|
|
-#endif
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-#if 0
|
|
|
-
|
|
|
-static void snd_cs4231_debug(cs4231_t *chip)
|
|
|
-{
|
|
|
- printk("CS4231 REGS: INDEX = 0x%02x ",
|
|
|
- __cs4231_readb(chip, CS4231P(chip, REGSEL)));
|
|
|
- printk(" 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));
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
-
|
|
|
/*
|
|
|
* CS4231 detection / MCE routines
|
|
|
*/
|
|
@@ -528,11 +482,12 @@ static void snd_cs4231_busy_wait(cs4231_t *chip)
|
|
|
/* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
|
|
|
for (timeout = 5; timeout > 0; timeout--)
|
|
|
__cs4231_readb(chip, CS4231P(chip, REGSEL));
|
|
|
+
|
|
|
/* 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);
|
|
|
}
|
|
|
|
|
|
static void snd_cs4231_mce_up(cs4231_t *chip)
|
|
@@ -545,12 +500,12 @@ static void snd_cs4231_mce_up(cs4231_t *chip)
|
|
|
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 +518,15 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
|
|
|
|
|
|
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;
|
|
@@ -590,9 +542,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
|
|
|
spin_unlock_irqrestore(&chip->lock, flags);
|
|
|
return;
|
|
|
}
|
|
|
-#if 0
|
|
|
- printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
|
|
|
-#endif
|
|
|
+
|
|
|
/* in 10ms increments, check condition, up to 250ms */
|
|
|
timeout = 25;
|
|
|
while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) {
|
|
@@ -604,9 +554,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
|
|
|
msleep(10);
|
|
|
spin_lock_irqsave(&chip->lock, flags);
|
|
|
}
|
|
|
-#if 0
|
|
|
- printk("(3) jiffies = %li\n", jiffies);
|
|
|
-#endif
|
|
|
+
|
|
|
/* in 10ms increments, check condition, up to 100ms */
|
|
|
timeout = 10;
|
|
|
while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) {
|
|
@@ -619,54 +567,58 @@ static void snd_cs4231_mce_down(cs4231_t *chip)
|
|
|
spin_lock_irqsave(&chip->lock, flags);
|
|
|
}
|
|
|
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)));
|
|
|
-#endif
|
|
|
}
|
|
|
|
|
|
-#if 0 /* Unused for now... */
|
|
|
-static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size)
|
|
|
-{
|
|
|
- switch (format & 0xe0) {
|
|
|
- case CS4231_LINEAR_16:
|
|
|
- case CS4231_LINEAR_16_BIG:
|
|
|
- size >>= 1;
|
|
|
- break;
|
|
|
- case CS4231_ADPCM_16:
|
|
|
- return size >> 2;
|
|
|
- }
|
|
|
- if (format & CS4231_STEREO)
|
|
|
- size >>= 1;
|
|
|
- return size;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
#ifdef EBUS_SUPPORT
|
|
|
static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent)
|
|
|
{
|
|
|
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);
|
|
|
-#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();
|
|
|
+
|
|
|
+ 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 +646,60 @@ static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on)
|
|
|
} 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;
|
|
|
+
|
|
|
+ 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
|
|
|
}
|
|
@@ -725,25 +731,12 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#if 0
|
|
|
- printk("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,
|
|
@@ -755,9 +748,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
|
|
|
result = -EINVAL;
|
|
|
break;
|
|
|
}
|
|
|
-#if 0
|
|
|
- snd_cs4231_debug(chip);
|
|
|
-#endif
|
|
|
+
|
|
|
return result;
|
|
|
}
|
|
|
|
|
@@ -790,9 +781,6 @@ static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int chann
|
|
|
}
|
|
|
if (channels > 1)
|
|
|
rformat |= CS4231_STEREO;
|
|
|
-#if 0
|
|
|
- snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
|
|
|
-#endif
|
|
|
return rformat;
|
|
|
}
|
|
|
|
|
@@ -944,7 +932,7 @@ static void snd_cs4231_init(cs4231_t *chip)
|
|
|
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 +945,7 @@ static void snd_cs4231_init(cs4231_t *chip)
|
|
|
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 +955,7 @@ static void snd_cs4231_init(cs4231_t *chip)
|
|
|
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 +969,7 @@ static void snd_cs4231_init(cs4231_t *chip)
|
|
|
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 +979,7 @@ static void snd_cs4231_init(cs4231_t *chip)
|
|
|
snd_cs4231_mce_down(chip);
|
|
|
|
|
|
#ifdef SNDRV_DEBUG_MCE
|
|
|
- snd_printk("init: (5)\n");
|
|
|
+ snd_printdd("init: (5)\n");
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -1022,6 +1010,7 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
|
|
|
CS4231_RECORD_IRQ |
|
|
|
CS4231_TIMER_IRQ);
|
|
|
snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
|
|
|
+
|
|
|
spin_unlock_irqrestore(&chip->lock, flags);
|
|
|
|
|
|
chip->mode = mode;
|
|
@@ -1136,11 +1125,21 @@ static int snd_cs4231_playback_hw_free(snd_pcm_substream_t *substream)
|
|
|
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;
|
|
|
|
|
|
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;
|
|
|
+
|
|
|
spin_unlock_irqrestore(&chip->lock, flags);
|
|
|
|
|
|
return 0;
|
|
@@ -1172,12 +1171,16 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream)
|
|
|
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 +1199,61 @@ static void snd_cs4231_overrange(cs4231_t *chip)
|
|
|
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 (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 & 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);
|
|
|
+
|
|
|
sbus_writel(csr, chip->port + APCCSR);
|
|
|
|
|
|
- snd_cs4231_generic_interrupt(chip);
|
|
|
+ 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);
|
|
|
+ }
|
|
|
|
|
|
- return IRQ_HANDLED;
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ return snd_cs4231_generic_interrupt(chip);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -1290,7 +1301,8 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substr
|
|
|
#ifdef EBUS_SUPPORT
|
|
|
}
|
|
|
#endif
|
|
|
- ptr += (period_bytes - residue);
|
|
|
+ ptr += period_bytes - residue;
|
|
|
+
|
|
|
return bytes_to_frames(substream->runtime, ptr);
|
|
|
}
|
|
|
|
|
@@ -1314,7 +1326,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr
|
|
|
#ifdef EBUS_SUPPORT
|
|
|
}
|
|
|
#endif
|
|
|
- ptr += (period_bytes - residue);
|
|
|
+ ptr += period_bytes - residue;
|
|
|
return bytes_to_frames(substream->runtime, ptr);
|
|
|
}
|
|
|
|
|
@@ -1328,9 +1340,6 @@ static int snd_cs4231_probe(cs4231_t *chip)
|
|
|
int i, id, vers;
|
|
|
unsigned char *ptr;
|
|
|
|
|
|
-#if 0
|
|
|
- snd_cs4231_debug(chip);
|
|
|
-#endif
|
|
|
id = vers = 0;
|
|
|
for (i = 0; i < 50; i++) {
|
|
|
mb();
|
|
@@ -1985,13 +1994,13 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card,
|
|
|
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);
|
|
@@ -2113,29 +2122,29 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card,
|
|
|
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;
|
|
|
}
|
|
|
|