patch-2.2.4 linux/drivers/sbus/audio/cs4231.c
Next file: linux/drivers/sbus/audio/cs4231.h
Previous file: linux/drivers/sbus/audio/cs4215.h
Back to the patch index
Back to the overall index
- Lines: 1268
- Date:
Mon Mar 15 16:11:30 1999
- Orig file:
v2.2.3/linux/drivers/sbus/audio/cs4231.c
- Orig date:
Fri Nov 27 13:09:24 1998
diff -u --recursive --new-file v2.2.3/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c
@@ -14,6 +14,7 @@
* The APC DMA controller support unfortunately is not documented. Thanks, Sun
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -24,6 +25,7 @@
#include <linux/delay.h>
#include <linux/soundcard.h>
#include <linux/version.h>
+#include <linux/ioport.h>
#include <asm/openprom.h>
#include <asm/oplib.h>
#include <asm/system.h>
@@ -31,6 +33,10 @@
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/sbus.h>
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff && defined(CONFIG_PCI)
+#define EB4231_SUPPORT
+#include <asm/ebus.h>
+#endif
#include <asm/audioio.h>
#include "cs4231.h"
@@ -120,6 +126,7 @@
tprintk(("enabling play\n"));
save_flags(flags);
cli();
+
cs4231_chip->regs->iar = 0x9;
cs4231_chip->regs->idr |= PEN_ENABLE;
restore_flags(flags);
@@ -261,14 +268,14 @@
if (value != 0) {
set_bits = cs4231_encoding_to_bits(drv, value);
if (set_bits >= 0) {
- cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8;
- tmp_bits = cs4231_chip->regs->idr;
- cs4231_chip->regs->idr = CHANGE_ENCODING(tmp_bits, set_bits);
+ cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8;
+ tmp_bits = cs4231_chip->regs->idr;
+ cs4231_chip->regs->idr = CHANGE_ENCODING(tmp_bits, set_bits);
- CHIP_READY
+ CHIP_READY
- cs4231_chip->perchip_info.play.encoding = value;
- return 0;
+ cs4231_chip->perchip_info.play.encoding = value;
+ return 0;
}
}
dprintk(("output enc failed\n"));
@@ -291,14 +298,14 @@
if (value != 0) {
set_bits = cs4231_encoding_to_bits(drv, value);
if (set_bits >= 0) {
- cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
- tmp_bits = cs4231_chip->regs->idr;
- cs4231_chip->regs->idr = CHANGE_ENCODING(tmp_bits, set_bits);
+ cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
+ tmp_bits = cs4231_chip->regs->idr;
+ cs4231_chip->regs->idr = CHANGE_ENCODING(tmp_bits, set_bits);
- CHIP_READY
+ CHIP_READY
- cs4231_chip->perchip_info.record.encoding = value;
- return 0;
+ cs4231_chip->perchip_info.record.encoding = value;
+ return 0;
}
}
dprintk(("input enc failed\n"));
@@ -321,14 +328,14 @@
if (value != 0) {
set_bits = cs4231_rate_to_bits(drv, value);
if (set_bits >= 0) {
- cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8;
- tmp_bits = cs4231_chip->regs->idr;
- cs4231_chip->regs->idr = CHANGE_DFR(tmp_bits, set_bits);
+ cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8;
+ tmp_bits = cs4231_chip->regs->idr;
+ cs4231_chip->regs->idr = CHANGE_DFR(tmp_bits, set_bits);
- CHIP_READY
+ CHIP_READY
- cs4231_chip->perchip_info.play.sample_rate = value;
- return 0;
+ cs4231_chip->perchip_info.play.sample_rate = value;
+ return 0;
}
}
dprintk(("output rate failed\n"));
@@ -351,14 +358,14 @@
if (value != 0) {
set_bits = cs4231_rate_to_bits(drv, value);
if (set_bits >= 0) {
- cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
- tmp_bits = cs4231_chip->regs->idr;
- cs4231_chip->regs->idr = CHANGE_DFR(tmp_bits, set_bits);
+ cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
+ tmp_bits = cs4231_chip->regs->idr;
+ cs4231_chip->regs->idr = CHANGE_DFR(tmp_bits, set_bits);
- CHIP_READY
+ CHIP_READY
- cs4231_chip->perchip_info.record.sample_rate = value;
- return 0;
+ cs4231_chip->perchip_info.record.sample_rate = value;
+ return 0;
}
}
dprintk(("input rate failed\n"));
@@ -383,14 +390,14 @@
tmp_bits = cs4231_chip->regs->idr;
switch (value) {
case 1:
- cs4231_chip->regs->idr = CS4231_MONO_ON(tmp_bits);
- break;
+ cs4231_chip->regs->idr = CS4231_MONO_ON(tmp_bits);
+ break;
case 2:
- cs4231_chip->regs->idr = CS4231_STEREO_ON(tmp_bits);
- break;
+ cs4231_chip->regs->idr = CS4231_STEREO_ON(tmp_bits);
+ break;
default:
- dprintk(("input chan failed\n"));
- return -(EINVAL);
+ dprintk(("input chan failed\n"));
+ return -(EINVAL);
}
CHIP_READY
@@ -417,14 +424,14 @@
tmp_bits = cs4231_chip->regs->idr;
switch (value) {
case 1:
- cs4231_chip->regs->idr = CS4231_MONO_ON(tmp_bits);
- break;
+ cs4231_chip->regs->idr = CS4231_MONO_ON(tmp_bits);
+ break;
case 2:
- cs4231_chip->regs->idr = CS4231_STEREO_ON(tmp_bits);
- break;
+ cs4231_chip->regs->idr = CS4231_STEREO_ON(tmp_bits);
+ break;
default:
- dprintk(("output chan failed\n"));
- return -(EINVAL);
+ dprintk(("output chan failed\n"));
+ return -(EINVAL);
}
CHIP_READY
@@ -477,7 +484,7 @@
unsigned int x = 0;
cs4231_chip->regs->iar = IAR_AUTOCAL_END;
- while (cs4231_chip->regs->iar == IAR_NOT_READY && x <= CS_TIMEOUT) {
+ while (cs4231_chip->regs->idr == IAR_NOT_READY && x <= CS_TIMEOUT) {
x++;
}
@@ -494,17 +501,17 @@
struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
tprintk(("in cs4231_output_muted: %d\n", value));
if (!value) {
- cs4231_chip->regs->iar = 0x7;
- cs4231_chip->regs->idr &= OUTCR_UNMUTE;
- cs4231_chip->regs->iar = 0x6;
- cs4231_chip->regs->idr &= OUTCR_UNMUTE;
- cs4231_chip->perchip_info.output_muted = 0;
+ cs4231_chip->regs->iar = 0x7;
+ cs4231_chip->regs->idr &= OUTCR_UNMUTE;
+ cs4231_chip->regs->iar = 0x6;
+ cs4231_chip->regs->idr &= OUTCR_UNMUTE;
+ cs4231_chip->perchip_info.output_muted = 0;
} else {
- cs4231_chip->regs->iar = 0x7;
- cs4231_chip->regs->idr |= OUTCR_MUTE;
- cs4231_chip->regs->iar = 0x6;
- cs4231_chip->regs->idr |= OUTCR_MUTE;
- cs4231_chip->perchip_info.output_muted = 1;
+ cs4231_chip->regs->iar = 0x7;
+ cs4231_chip->regs->idr |= OUTCR_MUTE;
+ cs4231_chip->regs->iar = 0x6;
+ cs4231_chip->regs->idr |= OUTCR_MUTE;
+ cs4231_chip->perchip_info.output_muted = 1;
}
return 0;
}
@@ -555,21 +562,21 @@
cs4231_chip->regs->idr |= PINCR_HDPH_MUTE;
if (value & AUDIO_SPEAKER) {
- cs4231_chip->regs->iar = 0x1a;
- cs4231_chip->regs->idr &= ~MONO_IOCR_MUTE;
- retval |= AUDIO_SPEAKER;
+ cs4231_chip->regs->iar = 0x1a;
+ cs4231_chip->regs->idr &= ~MONO_IOCR_MUTE;
+ retval |= AUDIO_SPEAKER;
}
if (value & AUDIO_HEADPHONE) {
- cs4231_chip->regs->iar = 0x0a;
- cs4231_chip->regs->idr &= ~PINCR_HDPH_MUTE;
- retval |= AUDIO_HEADPHONE;
+ cs4231_chip->regs->iar = 0x0a;
+ cs4231_chip->regs->idr &= ~PINCR_HDPH_MUTE;
+ retval |= AUDIO_HEADPHONE;
}
if (value & AUDIO_LINE_OUT) {
- cs4231_chip->regs->iar = 0x0a;
- cs4231_chip->regs->idr &= ~PINCR_LINE_MUTE;
- retval |= AUDIO_LINE_OUT;
+ cs4231_chip->regs->iar = 0x0a;
+ cs4231_chip->regs->idr &= ~PINCR_LINE_MUTE;
+ retval |= AUDIO_LINE_OUT;
}
cs4231_chip->perchip_info.play.port = retval;
@@ -600,31 +607,31 @@
/* This apparently applies only to APC ultras, not ebus ultras */
if (!cs4231_chip->status & CS_STATUS_IS_ULTRA) {
if (value & AUDIO_INTERNAL_CD_IN) {
- cs4231_chip->regs->iar = 0x1;
- cs4231_chip->regs->idr = CDROM_ENABLE(cs4231_chip->regs->idr);
- cs4231_chip->regs->iar = 0x0;
- cs4231_chip->regs->idr = CDROM_ENABLE(cs4231_chip->regs->idr);
- retval = AUDIO_INTERNAL_CD_IN;
+ cs4231_chip->regs->iar = 0x1;
+ cs4231_chip->regs->idr = CDROM_ENABLE(cs4231_chip->regs->idr);
+ cs4231_chip->regs->iar = 0x0;
+ cs4231_chip->regs->idr = CDROM_ENABLE(cs4231_chip->regs->idr);
+ retval = AUDIO_INTERNAL_CD_IN;
}
}
if ((value & AUDIO_LINE_IN)) {
- cs4231_chip->regs->iar = 0x1;
- cs4231_chip->regs->idr = LINE_ENABLE(cs4231_chip->regs->idr);
- cs4231_chip->regs->iar = 0x0;
- cs4231_chip->regs->idr = LINE_ENABLE(cs4231_chip->regs->idr);
- retval = AUDIO_LINE_IN;
+ cs4231_chip->regs->iar = 0x1;
+ cs4231_chip->regs->idr = LINE_ENABLE(cs4231_chip->regs->idr);
+ cs4231_chip->regs->iar = 0x0;
+ cs4231_chip->regs->idr = LINE_ENABLE(cs4231_chip->regs->idr);
+ retval = AUDIO_LINE_IN;
} else if (value & AUDIO_MICROPHONE) {
- cs4231_chip->regs->iar = 0x1;
- cs4231_chip->regs->idr = MIC_ENABLE(cs4231_chip->regs->idr);
- cs4231_chip->regs->iar = 0x0;
- cs4231_chip->regs->idr = MIC_ENABLE(cs4231_chip->regs->idr);
- retval = AUDIO_MICROPHONE;
+ cs4231_chip->regs->iar = 0x1;
+ cs4231_chip->regs->idr = MIC_ENABLE(cs4231_chip->regs->idr);
+ cs4231_chip->regs->iar = 0x0;
+ cs4231_chip->regs->idr = MIC_ENABLE(cs4231_chip->regs->idr);
+ retval = AUDIO_MICROPHONE;
} else if (value & AUDIO_ANALOG_LOOPBACK) {
- cs4231_chip->regs->iar = 0x1;
- cs4231_chip->regs->idr = OUTPUTLOOP_ENABLE(cs4231_chip->regs->idr);
- cs4231_chip->regs->iar = 0x0;
- cs4231_chip->regs->idr = OUTPUTLOOP_ENABLE(cs4231_chip->regs->idr);
- retval = AUDIO_ANALOG_LOOPBACK;
+ cs4231_chip->regs->iar = 0x1;
+ cs4231_chip->regs->idr = OUTPUTLOOP_ENABLE(cs4231_chip->regs->idr);
+ cs4231_chip->regs->iar = 0x0;
+ cs4231_chip->regs->idr = OUTPUTLOOP_ENABLE(cs4231_chip->regs->idr);
+ retval = AUDIO_ANALOG_LOOPBACK;
}
cs4231_chip->perchip_info.record.port = retval;
@@ -654,9 +661,9 @@
cs4231_chip->regs->iar = 0x0d;
if (a >= CS4231_MON_MAX_ATEN)
- cs4231_chip->regs->idr = LOOPB_OFF;
+ cs4231_chip->regs->idr = LOOPB_OFF;
else
- cs4231_chip->regs->idr = ((a << 2) | LOOPB_ON);
+ cs4231_chip->regs->idr = ((a << 2) | LOOPB_ON);
if (value == AUDIO_MAX_GAIN)
cs4231_chip->perchip_info.monitor_gain = AUDIO_MAX_GAIN;
@@ -689,6 +696,32 @@
return (int)cs4231_chip->perchip_info.record.error;
}
+#ifdef EB4231_SUPPORT
+static int eb4231_get_output_samples(struct sparcaudio_driver *drv)
+{
+ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+ int count =
+ cs4231_length_to_samplecount(&cs4231_chip->perchip_info.play,
+ readl(&cs4231_chip->eb2p->dbcr));
+
+ return (cs4231_chip->perchip_info.play.samples -
+ ((count > cs4231_chip->perchip_info.play.samples)
+ ? 0 : count));
+}
+
+static int eb4231_get_input_samples(struct sparcaudio_driver *drv)
+{
+ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+ int count =
+ cs4231_length_to_samplecount(&cs4231_chip->perchip_info.record,
+ readl(&cs4231_chip->eb2c->dbcr));
+
+ return (cs4231_chip->perchip_info.record.samples -
+ ((count > cs4231_chip->perchip_info.record.samples) ?
+ 0 : count));
+}
+#endif
+
static int cs4231_get_output_samples(struct sparcaudio_driver *drv)
{
struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
@@ -890,13 +923,21 @@
tprintk(("in cs4231_chip_reset\n"));
- cs4231_chip->regs->dmacsr = CS_CHIP_RESET;
- cs4231_chip->regs->dmacsr = 0x00;
- cs4231_chip->regs->dmacsr |= CS_CDC_RESET;
+ if (cs4231_chip->status & CS_STATUS_IS_EBUS) {
+#ifdef EB4231_SUPPORT
+ writel(EBUS_DCSR_RESET, &cs4231_chip->eb2p->dcsr);
+ writel(EBUS_DCSR_RESET, &cs4231_chip->eb2c->dcsr);
+#endif
+ } else {
+ cs4231_chip->regs->dmacsr = APC_CHIP_RESET;
+ cs4231_chip->regs->dmacsr = 0x00;
+ cs4231_chip->regs->dmacsr |= APC_CDC_RESET;
- udelay(20);
+ udelay(20);
- cs4231_chip->regs->dmacsr &= ~(CS_CDC_RESET);
+ cs4231_chip->regs->dmacsr &= ~(APC_CDC_RESET);
+ }
+
cs4231_chip->regs->iar |= IAR_AUTOCAL_BEGIN;
CHIP_READY
@@ -928,9 +969,9 @@
cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x11;
if (cs4231_chip->status & CS_STATUS_REV_A)
- cs4231_chip->regs->idr = (HPF_ON | XTALE_ON);
+ cs4231_chip->regs->idr = (HPF_ON | XTALE_ON);
else
- cs4231_chip->regs->idr = (HPF_ON);
+ cs4231_chip->regs->idr = HPF_ON;
cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1a;
cs4231_chip->regs->idr = 0x00;
@@ -990,6 +1031,36 @@
return count;
}
+#ifdef EB4231_SUPPORT
+static void eb4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int direction)
+{
+ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+ struct audio_prinfo *thisdir;
+ unsigned int count, nextcount, curcount;
+
+ if (direction == 1) /* record */
+ {
+ thisdir = &cs4231_chip->perchip_info.record;
+ curcount =
+ cs4231_length_to_samplecount(thisdir, readl(&cs4231_chip->eb2c->dbcr));
+ nextcount =
+ cs4231_length_to_samplecount(thisdir, 0/*cs4231_chip->regs->dmacnc*/);
+ }
+ else /* play */
+ {
+ thisdir = &cs4231_chip->perchip_info.play;
+ curcount =
+ cs4231_length_to_samplecount(thisdir, readl(&cs4231_chip->eb2p->dbcr));
+ nextcount =
+ cs4231_length_to_samplecount(thisdir, 0/*cs4231_chip->regs->dmapnc*/);
+ }
+ count = thisdir->samples;
+ length = cs4231_length_to_samplecount(thisdir, length);
+ /* normalize for where we are. */
+ thisdir->samples = ((count - nextcount) + (length - curcount));
+}
+#endif
+
static void cs4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int direction)
{
struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
@@ -1060,14 +1131,18 @@
/* stop capture here or midlevel? */
cs4231_chip->perchip_info.record.open = 0;
if (cs4231_chip->input_dma_handle) {
- mmu_release_scsi_one((u32)((unsigned long)cs4231_chip->input_dma_handle),
+#if 0
+ mmu_release_scsi_one(cs4231_chip->input_dma_handle,
cs4231_chip->input_dma_size, drv->dev->my_bus);
+#endif
cs4231_chip->input_dma_handle = 0;
cs4231_chip->input_dma_size = 0;
}
if (cs4231_chip->input_next_dma_handle) {
- mmu_release_scsi_one((u32) ((unsigned long)cs4231_chip->input_next_dma_handle),
+#if 0
+ mmu_release_scsi_one(cs4231_chip->input_next_dma_handle,
cs4231_chip->input_next_dma_size, drv->dev->my_bus);
+#endif
cs4231_chip->input_next_dma_handle = 0;
cs4231_chip->input_next_dma_size = 0;
}
@@ -1077,15 +1152,19 @@
cs4231_chip->perchip_info.play.active =
cs4231_chip->perchip_info.play.open = 0;
if (cs4231_chip->output_dma_handle) {
- mmu_release_scsi_one((u32) ((unsigned long)cs4231_chip->output_dma_handle),
+#if 0
+ mmu_release_scsi_one(cs4231_chip->output_dma_handle,
cs4231_chip->output_dma_size, drv->dev->my_bus);
+#endif
cs4231_chip->output_dma_handle = 0;
cs4231_chip->output_dma_size = 0;
}
if (cs4231_chip->output_next_dma_handle) {
- mmu_release_scsi_one((u32) ((unsigned long)cs4231_chip->output_next_dma_handle),
+#if 0
+ mmu_release_scsi_one(cs4231_chip->output_next_dma_handle,
cs4231_chip->output_next_dma_size,
drv->dev->my_bus);
+#endif
cs4231_chip->output_next_dma_handle = 0;
cs4231_chip->output_next_dma_size = 0;
}
@@ -1110,7 +1189,7 @@
cs4231_chip->playlen = cs4231_chip->output_size;
if (cs4231_chip->output_dma_handle) {
- mmu_release_scsi_one((u32) ((unsigned long)cs4231_chip->output_dma_handle),
+ mmu_release_scsi_one(cs4231_chip->output_dma_handle,
cs4231_chip->output_dma_size, drv->dev->my_bus);
cs4231_chip->output_dma_handle = 0;
cs4231_chip->output_dma_size = 0;
@@ -1126,11 +1205,10 @@
if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) &&
!(cs4231_chip->perchip_info.play.pause)) {
- cs4231_chip->output_next_dma_handle = (u32 *) (unsigned long)
+ cs4231_chip->output_next_dma_handle =
mmu_get_scsi_one((char *) cs4231_chip->output_ptr,
cs4231_chip->output_size, drv->dev->my_bus);
- cs4231_chip->regs->dmapnva = (u32) (unsigned long)
- cs4231_chip->output_next_dma_handle;
+ cs4231_chip->regs->dmapnva = cs4231_chip->output_next_dma_handle;
cs4231_chip->output_next_dma_size = cs4231_chip->regs->dmapnc =
cs4231_chip->output_size;
cs4231_chip->output_size = 0;
@@ -1147,6 +1225,62 @@
return;
}
+#ifdef EB4231_SUPPORT
+static void eb4231_playintr(struct sparcaudio_driver *drv)
+{
+ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+ int status = 0;
+ unsigned int dcsr;
+
+ dcsr = readl(&cs4231_chip->eb2p->dcsr);
+
+ printk("pintr\ncsr 0x%x acr 0x%x bcr %d\n", readl(&cs4231_chip->eb2p->dcsr), readl(&cs4231_chip->eb2p->dacr), readl(&cs4231_chip->eb2p->dbcr));
+ if (cs4231_chip->playlen == 0 && cs4231_chip->output_size > 0)
+ cs4231_chip->playlen = cs4231_chip->output_size;
+
+ if (cs4231_chip->output_dma_handle) {
+ cs4231_chip->output_dma_handle = 0;
+ cs4231_chip->output_dma_size = 0;
+ cs4231_chip->playing_count--;
+ status++;
+ }
+
+#if 0
+ if (cs4231_chip->output_next_dma_handle) {
+ cs4231_chip->output_dma_handle = cs4231_chip->output_next_dma_handle;
+ cs4231_chip->output_dma_size = cs4231_chip->output_next_dma_size;
+ cs4231_chip->output_next_dma_size = 0;
+ cs4231_chip->output_next_dma_handle = 0;
+ }
+#endif
+
+ if ((cs4231_chip->output_ptr && cs4231_chip->output_size > 0) &&
+ !(cs4231_chip->perchip_info.play.pause)) {
+#if 0
+ if (dcsr & EBUS_DCSR_A_LOADED) {
+ cs4231_chip->output_next_dma_handle = virt_to_bus(cs4231_chip->output_ptr);
+ cs4231_chip->output_next_dma_size = cs4231_chip->output_size;
+ } else {
+#endif
+ cs4231_chip->output_dma_handle = virt_to_bus(cs4231_chip->output_ptr);
+ cs4231_chip->output_dma_size = cs4231_chip->output_size;
+#if 0
+ }
+#endif
+ writel(virt_to_bus(cs4231_chip->output_ptr), &cs4231_chip->eb2p->dacr);
+ writel(cs4231_chip->output_size, &cs4231_chip->eb2p->dbcr);
+ cs4231_chip->output_size = 0;
+ cs4231_chip->output_ptr = NULL;
+ cs4231_chip->playing_count++;
+ status+=2;
+ }
+
+ sparcaudio_output_done(drv, status);
+
+ return;
+}
+#endif
+
static void cs4231_recclear(int fmt, char *dmabuf, int length)
{
switch (fmt) {
@@ -1174,7 +1308,7 @@
}
if (cs4231_chip->input_dma_handle) {
- mmu_release_scsi_one((u32) ((unsigned long)cs4231_chip->input_dma_handle),
+ mmu_release_scsi_one(cs4231_chip->input_dma_handle,
cs4231_chip->input_dma_size, drv->dev->my_bus);
cs4231_chip->input_dma_handle = 0;
cs4231_chip->input_dma_size = 0;
@@ -1192,11 +1326,10 @@
!(cs4231_chip->perchip_info.record.pause)) {
cs4231_recclear(cs4231_chip->perchip_info.record.encoding,
(char *)cs4231_chip->input_ptr, cs4231_chip->input_size);
- cs4231_chip->input_next_dma_handle = (u32*) (unsigned long)
+ cs4231_chip->input_next_dma_handle =
mmu_get_scsi_one((char *) cs4231_chip->input_ptr,
cs4231_chip->input_size, drv->dev->my_bus);
- cs4231_chip->regs->dmacnva = (u32) (unsigned long)
- cs4231_chip->input_next_dma_handle;
+ cs4231_chip->regs->dmacnva = cs4231_chip->input_next_dma_handle;
cs4231_chip->input_next_dma_size = cs4231_chip->regs->dmacnc =
cs4231_chip->input_size;
cs4231_chip->input_size = 0;
@@ -1213,6 +1346,107 @@
return 1;
}
+#ifdef EB4231_SUPPORT
+static int eb4231_recintr(struct sparcaudio_driver *drv)
+{
+ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+ int status = 0;
+
+ if (cs4231_chip->perchip_info.record.active == 0) {
+ dprintk(("going inactive\n"));
+ cs4231_disable_rec(drv);
+ }
+
+ if (cs4231_chip->input_dma_handle) {
+#if 0
+ mmu_release_scsi_one(cs4231_chip->input_dma_handle,
+ cs4231_chip->input_dma_size, drv->dev->my_bus);
+#endif
+ cs4231_chip->input_dma_handle = 0;
+ cs4231_chip->input_dma_size = 0;
+ cs4231_chip->recording_count--;
+ status++;
+ }
+ if (cs4231_chip->input_next_dma_handle) {
+ cs4231_chip->input_dma_handle = cs4231_chip->input_next_dma_handle;
+ cs4231_chip->input_dma_size = cs4231_chip->input_next_dma_size;
+ cs4231_chip->input_next_dma_size = 0;
+ cs4231_chip->input_next_dma_handle = 0;
+ }
+
+ if ((cs4231_chip->input_ptr && cs4231_chip->input_size > 0) &&
+ !(cs4231_chip->perchip_info.record.pause)) {
+ cs4231_recclear(cs4231_chip->perchip_info.record.encoding,
+ (char *)cs4231_chip->input_ptr, cs4231_chip->input_size);
+#if 0
+ cs4231_chip->input_next_dma_handle =
+ mmu_get_scsi_one((char *) cs4231_chip->input_ptr,
+ cs4231_chip->input_size, drv->dev->my_bus);
+ cs4231_chip->regs->dmacnva = cs4231_chip->input_next_dma_handle;
+ cs4231_chip->input_next_dma_size = cs4231_chip->regs->dmacnc =
+ cs4231_chip->input_size;
+#else
+ cs4231_chip->input_next_dma_handle = cs4231_chip->eb2c->dacr = virt_to_bus(cs4231_chip->input_ptr);
+ cs4231_chip->input_next_dma_size = cs4231_chip->eb2c->dbcr = cs4231_chip->input_size;
+#endif
+ cs4231_chip->input_size = 0;
+ cs4231_chip->input_ptr = NULL;
+ cs4231_chip->recording_count++;
+ status += 2;
+ } else {
+#if 0
+ cs4231_chip->regs->dmacnva = 0;
+ cs4231_chip->regs->dmacnc = 0;
+#else
+ cs4231_chip->eb2c->dacr = 0;
+ cs4231_chip->eb2c->dbcr = 0;
+#endif
+ }
+
+ sparcaudio_input_done(drv, 1);
+
+ return 1;
+}
+#endif
+
+#ifdef EB4231_SUPPORT
+static void eb4231_start_output(struct sparcaudio_driver *drv, __u8 * buffer,
+ unsigned long count)
+{
+ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+ unsigned int dcsr;
+
+ dprintk(("in eb4231 start output act %d pau %d\n", cs4231_chip->perchip_info.play.active, cs4231_chip->perchip_info.play.pause));
+ cs4231_chip->output_ptr = buffer;
+ cs4231_chip->output_size = count;
+
+ if (cs4231_chip->perchip_info.play.active ||
+ (cs4231_chip->perchip_info.play.pause))
+ return;
+
+ cs4231_ready(drv);
+
+ cs4231_chip->perchip_info.play.active = 1;
+ cs4231_chip->playing_count = 0;
+
+ dcsr = readl(&cs4231_chip->eb2p->dcsr);
+ if (!(dcsr & EBUS_DCSR_EN_DMA)) {
+ dprintk(("about to go setup\n"));
+
+ dcsr = EB2_PLAY_SETUP;
+ writel(dcsr, (unsigned long)&cs4231_chip->eb2p->dcsr);
+ eb4231_playintr(drv);
+ dprintk(("enabling\n"));
+ cs4231_enable_play(drv);
+
+ cs4231_ready(drv);
+ } else {
+ dprintk(("playing next block\n"));
+ eb4231_playintr(drv);
+ }
+}
+#endif
+
static void cs4231_start_output(struct sparcaudio_driver *drv, __u8 * buffer,
unsigned long count)
{
@@ -1231,14 +1465,14 @@
cs4231_chip->perchip_info.play.active = 1;
cs4231_chip->playing_count = 0;
- if ((cs4231_chip->regs->dmacsr & CS_PPAUSE) ||
- !(cs4231_chip->regs->dmacsr & PDMA_READY)) {
- cs4231_chip->regs->dmacsr &= ~CS_XINT_PLAY;
- cs4231_chip->regs->dmacsr &= ~CS_PPAUSE;
+ if ((cs4231_chip->regs->dmacsr & APC_PPAUSE) ||
+ !(cs4231_chip->regs->dmacsr & APC_PDMA_READY)) {
+ cs4231_chip->regs->dmacsr &= ~APC_XINT_PLAY;
+ cs4231_chip->regs->dmacsr &= ~APC_PPAUSE;
cs4231_playintr(drv);
- cs4231_chip->regs->dmacsr |= CS_PLAY_SETUP;
+ cs4231_chip->regs->dmacsr |= APC_PLAY_SETUP;
cs4231_enable_play(drv);
cs4231_ready(drv);
@@ -1246,6 +1480,28 @@
cs4231_playintr(drv);
}
+#ifdef EB4231_SUPPORT
+static void eb4231_stop_output(struct sparcaudio_driver *drv)
+{
+ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
+ dprintk(("in cs4231_stop_output\n"));
+ dprintk(("csr 0x%x acr 0x%x bcr %d\n", readl(&cs4231_chip->eb2p->dcsr), readl(&cs4231_chip->eb2p->dacr), readl(&cs4231_chip->eb2p->dbcr)));
+ cs4231_chip->output_ptr = NULL;
+ cs4231_chip->output_size = 0;
+ if (cs4231_chip->output_dma_handle) {
+ cs4231_chip->output_dma_handle = 0;
+ cs4231_chip->output_dma_size = 0;
+ }
+#if 0
+ if (cs4231_chip->output_next_dma_handle) {
+ cs4231_chip->output_next_dma_handle = 0;
+ cs4231_chip->output_next_dma_size = 0;
+ }
+#endif
+}
+#endif
+
static void cs4231_stop_output(struct sparcaudio_driver *drv)
{
struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
@@ -1254,13 +1510,13 @@
cs4231_chip->output_ptr = NULL;
cs4231_chip->output_size = 0;
if (cs4231_chip->output_dma_handle) {
- mmu_release_scsi_one((u32) ((unsigned long)cs4231_chip->output_dma_handle),
+ mmu_release_scsi_one(cs4231_chip->output_dma_handle,
cs4231_chip->output_dma_size, drv->dev->my_bus);
cs4231_chip->output_dma_handle = 0;
cs4231_chip->output_dma_size = 0;
}
if (cs4231_chip->output_next_dma_handle) {
- mmu_release_scsi_one((u32) ((unsigned long)cs4231_chip->output_next_dma_handle),
+ mmu_release_scsi_one(cs4231_chip->output_next_dma_handle,
cs4231_chip->output_next_dma_size, drv->dev->my_bus);
cs4231_chip->output_next_dma_handle = 0;
cs4231_chip->output_next_dma_size = 0;
@@ -1272,10 +1528,10 @@
struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
int x = 0;
- while (!(cs4231_chip->regs->dmacsr & CS_XINT_COVF) && x <= CS_TIMEOUT) {
+ while (!(cs4231_chip->regs->dmacsr & APC_XINT_COVF) && x <= CS_TIMEOUT) {
x++;
}
- cs4231_chip->regs->dmacsr |= CS_XINT_CEMP;
+ cs4231_chip->regs->dmacsr |= APC_XINT_CEMP;
}
static void cs4231_start_input(struct sparcaudio_driver *drv, __u8 * buffer,
@@ -1295,14 +1551,14 @@
cs4231_chip->perchip_info.record.active = 1;
cs4231_chip->recording_count = 0;
- if ((cs4231_chip->regs->dmacsr & CS_CPAUSE) ||
- !(cs4231_chip->regs->dmacsr & CDMA_READY)) {
- cs4231_chip->regs->dmacsr &= ~CS_XINT_CAPT;
- cs4231_chip->regs->dmacsr &= ~CS_CPAUSE;
+ if ((cs4231_chip->regs->dmacsr & APC_CPAUSE) ||
+ !(cs4231_chip->regs->dmacsr & APC_CDMA_READY)) {
+ cs4231_chip->regs->dmacsr &= ~APC_XINT_CAPT;
+ cs4231_chip->regs->dmacsr &= ~APC_CPAUSE;
cs4231_recintr(drv);
- cs4231_chip->regs->dmacsr |= CS_CAPT_SETUP;
+ cs4231_chip->regs->dmacsr |= APC_CAPT_SETUP;
cs4231_enable_rec(drv);
cs4231_ready(drv);
@@ -1315,18 +1571,18 @@
struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
cs4231_chip->perchip_info.record.active = 0;
- cs4231_chip->regs->dmacsr |= (CS_CPAUSE);
+ cs4231_chip->regs->dmacsr |= (APC_CPAUSE);
cs4231_chip->input_ptr = NULL;
cs4231_chip->input_size = 0;
if (cs4231_chip->input_dma_handle) {
- mmu_release_scsi_one((u32) ((unsigned long)cs4231_chip->input_dma_handle),
+ mmu_release_scsi_one(cs4231_chip->input_dma_handle,
cs4231_chip->input_dma_size, drv->dev->my_bus);
cs4231_chip->input_dma_handle = 0;
cs4231_chip->input_dma_size = 0;
}
if (cs4231_chip->input_next_dma_handle) {
- mmu_release_scsi_one((u32) ((unsigned long)cs4231_chip->input_next_dma_handle),
+ mmu_release_scsi_one(cs4231_chip->input_next_dma_handle,
cs4231_chip->input_next_dma_size, drv->dev->my_bus);
cs4231_chip->input_next_dma_handle = 0;
cs4231_chip->input_next_dma_size = 0;
@@ -1408,7 +1664,11 @@
struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
strncpy(audinfo->name, "SUNW,CS4231", sizeof(audinfo->name) - 1);
- /* versions: SPARCstation 4/5=a, Ultra=b */
+ /* versions */
+ /* a: SPARCstation 4/5 b: Ultra 1/2 (electron) */
+ /* c: Ultra 1/2 PCI? (positron) d: ppc */
+ /* e: x86 f: Ultra Enterprise? (tazmo) */
+ /* g: Ultra 30? (quark) h: Ultra 5/10? (darwin) */
/* apparently Ultra 1, Ultra 2 don't have internal CD input */
if (cs4231_chip->status & CS_STATUS_IS_ULTRA)
strncpy(audinfo->version, "b", sizeof(audinfo->version) - 1);
@@ -1450,6 +1710,114 @@
return retval;
}
+#ifdef EB4231_SUPPORT
+/* ebus audio capture interrupt handler. */
+void eb4231_cinterrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id;
+ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+ int dummy1, dummy2;
+
+ printk("in eb4231_interrupt\n");
+
+ /* Clear the interrupt. */
+ dummy1 = readl(&cs4231_chip->eb2p->dcsr);
+ dummy2 = readl(&cs4231_chip->eb2c->dcsr);
+
+ printk("play csr 0x%x capt csr 0x%x\n", dummy1, dummy2);
+
+ cs4231_chip->eb2p->dcsr = dummy1;
+ cs4231_chip->eb2c->dcsr = dummy2;
+#if 0
+ if (dummy & APC_PLAY_INT) {
+ if (dummy & APC_XINT_PNVA) {
+ cs4231_chip->perchip_info.play.samples +=
+ cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play),
+ cs4231_chip->playlen);
+ eb4231_playintr(drv);
+ }
+ /* Any other conditions we need worry about? */
+ }
+
+ if (dummy & APC_CAPT_INT) {
+ if (dummy & APC_XINT_CNVA) {
+ cs4231_chip->perchip_info.record.samples +=
+ cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record),
+ cs4231_chip->reclen);
+ eb4231_recintr(drv);
+ }
+ /* Any other conditions we need worry about? */
+ }
+
+
+ if (dummy & APC_XINT_CEMP) {
+ if (cs4231_chip->perchip_info.record.active == 0) {
+ /* Fix me */
+ cs4231_chip->perchip_info.record.active = 0;
+ cs4231_chip->perchip_info.record.error = 1;
+ eb4231_recintr(drv);
+ }
+ }
+
+ if (dummy & APC_XINT_EMPT) {
+ if (!cs4231_chip->output_next_dma_handle) {
+ cs4231_chip->regs->dmacsr |= (APC_PPAUSE);
+ cs4231_disable_play(drv);
+ cs4231_chip->perchip_info.play.error = 1;
+ }
+ cs4231_chip->perchip_info.play.active = 0;
+ eb4231_playintr(drv);
+
+ eb4231_getsamplecount(drv, cs4231_chip->playlen, 0);
+ }
+#endif
+}
+
+/* ebus audio play interrupt handler. */
+void eb4231_pinterrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id;
+ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+ unsigned int dummy;
+
+ dprintk(("in eb4231_interrupt2\n"));
+
+ /* Clear the interrupt. */
+ dummy = readl(&cs4231_chip->eb2p->dcsr);
+ dprintk(("play csr 0x%x\n", dummy));
+
+ if (dummy & EBUS_DCSR_INT_PEND) {
+#if 0
+ if (!(dummy & EBUS_DCSR_NA_LOADED)) {
+#endif
+ cs4231_chip->perchip_info.play.samples +=
+ cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play),
+ cs4231_chip->playlen);
+ eb4231_playintr(drv);
+#if 0
+ }
+#endif
+ }
+
+ if (!(dummy & EBUS_DCSR_A_LOADED)) {
+#if 0
+ if (!cs4231_chip->output_next_dma_handle) {
+#endif
+ writel((dummy & ~EBUS_DCSR_EN_DMA), &cs4231_chip->eb2p->dcsr);
+ cs4231_disable_play(drv);
+ cs4231_chip->perchip_info.play.error = 1;
+#if 0
+ }
+#endif
+ cs4231_chip->perchip_info.play.active = 0;
+#if 0
+ eb4231_playintr(drv);
+#endif
+ eb4231_getsamplecount(drv, cs4231_chip->playlen, 0);
+ }
+
+}
+#endif
/* Audio interrupt handler. */
void cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -1458,7 +1826,7 @@
struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
__u32 dummy;
- tprintk(("in cs4231_interrupt\n"));
+ dprintk(("in cs4231_interrupt\n"));
/* Clear the interrupt. */
dummy = cs4231_chip->regs->dmacsr;
@@ -1468,8 +1836,8 @@
* if anything since we may be doing shared interrupts
*/
- if (dummy & CS_PLAY_INT) {
- if (dummy & CS_XINT_PNVA) {
+ if (dummy & APC_PLAY_INT) {
+ if (dummy & APC_XINT_PNVA) {
cs4231_chip->perchip_info.play.samples +=
cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play),
cs4231_chip->playlen);
@@ -1478,8 +1846,8 @@
/* Any other conditions we need worry about? */
}
- if (dummy & CS_CAPT_INT) {
- if (dummy & CS_XINT_CNVA) {
+ if (dummy & APC_CAPT_INT) {
+ if (dummy & APC_XINT_CNVA) {
cs4231_chip->perchip_info.record.samples +=
cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record),
cs4231_chip->reclen);
@@ -1489,7 +1857,7 @@
}
- if (dummy & CS_XINT_CEMP) {
+ if (dummy & APC_XINT_CEMP) {
if (cs4231_chip->perchip_info.record.active == 0) {
/* Fix me */
cs4231_chip->perchip_info.record.active = 0;
@@ -1498,9 +1866,9 @@
}
}
- if (dummy & CS_XINT_EMPT) {
+ if (dummy & APC_XINT_EMPT) {
if (!cs4231_chip->output_next_dma_handle) {
- cs4231_chip->regs->dmacsr |= (CS_PPAUSE);
+ cs4231_chip->regs->dmacsr |= (APC_PPAUSE);
cs4231_disable_play(drv);
cs4231_chip->perchip_info.play.error = 1;
}
@@ -1510,7 +1878,7 @@
cs4231_getsamplecount(drv, cs4231_chip->playlen, 0);
}
- if (dummy & CS_GENL_INT) {
+ if (dummy & APC_GENL_INT) {
/* If we get here we must be sharing an interrupt, but I haven't code
to handle this right now */
}
@@ -1576,6 +1944,67 @@
cs4231_get_formats,
};
+#ifdef EB4231_SUPPORT
+static struct sparcaudio_operations eb4231_ops = {
+ cs4231_open,
+ cs4231_release,
+ cs4231_ioctl,
+ eb4231_start_output,
+ eb4231_stop_output,
+ cs4231_start_input,
+ cs4231_stop_input,
+ cs4231_audio_getdev,
+ cs4231_set_output_volume,
+ cs4231_get_output_volume,
+ cs4231_set_input_volume,
+ cs4231_get_input_volume,
+ cs4231_set_monitor_volume,
+ cs4231_get_monitor_volume,
+ cs4231_set_output_balance,
+ cs4231_get_output_balance,
+ cs4231_set_input_balance,
+ cs4231_get_input_balance,
+ cs4231_set_output_channels,
+ cs4231_get_output_channels,
+ cs4231_set_input_channels,
+ cs4231_get_input_channels,
+ cs4231_set_output_precision,
+ cs4231_get_output_precision,
+ cs4231_set_input_precision,
+ cs4231_get_input_precision,
+ cs4231_set_output_port,
+ cs4231_get_output_port,
+ cs4231_set_input_port,
+ cs4231_get_input_port,
+ cs4231_set_output_encoding,
+ cs4231_get_output_encoding,
+ cs4231_set_input_encoding,
+ cs4231_get_input_encoding,
+ cs4231_set_output_rate,
+ cs4231_get_output_rate,
+ cs4231_set_input_rate,
+ cs4231_get_input_rate,
+ cs4231_audio_getdev_sunos,
+ cs4231_get_output_ports,
+ cs4231_get_input_ports,
+ cs4231_output_muted,
+ cs4231_get_output_muted,
+ cs4231_set_output_pause,
+ cs4231_get_output_pause,
+ cs4231_set_input_pause,
+ cs4231_get_input_pause,
+ cs4231_set_output_samples,
+ eb4231_get_output_samples,
+ cs4231_set_input_samples,
+ eb4231_get_input_samples,
+ cs4231_set_output_error,
+ cs4231_get_output_error,
+ cs4231_set_input_error,
+ cs4231_get_input_error,
+ cs4231_get_formats,
+};
+#endif
+
/* Attach to an cs4231 chip given its PROM node. */
static int cs4231_attach(struct sparcaudio_driver *drv,
struct linux_sbus_device *sdev)
@@ -1642,6 +2071,8 @@
enable_irq(cs4231_chip->irq);
+ cs4231_chip->nirqs = 1;
+
cs4231_enable_interrupts(drv);
/* Reset the audio chip. */
@@ -1676,13 +2107,149 @@
AUDIO_ANALOG_LOOPBACK);
/* Announce the hardware to the user. */
- printk(KERN_INFO "audio%d: cs4231%c at 0x%lx irq %d\n",
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20100
+ printk(KERN_INFO "audio%d: cs4231%c at 0x%x irq %d\n",
drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ',
(unsigned long)cs4231_chip->regs, cs4231_chip->irq);
+#else
+ printk(KERN_INFO "audio%d: cs4231%c at %p irq %s\n",
+ drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ',
+ cs4231_chip->regs, __irq_itoa(cs4231_chip->irq));
+#endif
+
+ /* Success! */
+ return 0;
+}
+
+#ifdef EB4231_SUPPORT
+/* Attach to an cs4231 chip given its PROM node. */
+static int eb4231_attach(struct sparcaudio_driver *drv,
+ struct linux_ebus_device *edev)
+{
+ struct cs4231_chip *cs4231_chip;
+ int len, err, nregs;
+ struct linux_prom_registers regs[4];
+
+ /* Allocate our private information structure. */
+ drv->private = kmalloc(sizeof(struct cs4231_chip), GFP_KERNEL);
+ if (!drv->private)
+ return -ENOMEM;
+
+ /* Point at the information structure and initialize it. */
+ drv->ops = &eb4231_ops;
+ cs4231_chip = (struct cs4231_chip *)drv->private;
+ cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL;
+ cs4231_chip->input_size = cs4231_chip->output_size = 0;
+ cs4231_chip->status = 0;
+
+ len = prom_getproperty(edev->prom_node, "reg", (void *)regs, sizeof(regs));
+
+ if ((len % sizeof(regs[0])) != 0) {
+ printk("eb4231: Strange reg property size %d\n", len);
+ return -ENODEV;
+ }
+
+ nregs = len / sizeof(regs[0]);
+
+ /* Make sure we can map the registers first */
+ if (check_region(edev->base_address[0],
+ sizeof(struct cs4231_regs))) {
+ printk("eb4231_attach: can't get region at %016lx\n",
+ edev->base_address[0]);
+ goto cleanup;
+ }
+ if (check_region(edev->base_address[1],
+ sizeof(struct linux_ebus_dma))) {
+ printk("eb4231_attach: can't get region at %016lx\n",
+ edev->base_address[1]);
+ goto cleanup;
+ }
+ if (check_region(edev->base_address[2],
+ sizeof(struct linux_ebus_dma))) {
+ printk("eb4231_attach: can't get region at %016lx\n",
+ edev->base_address[2]);
+ goto cleanup;
+ }
+
+ cs4231_chip->regs = (struct cs4231_regs *)edev->base_address[0];
+ cs4231_chip->eb2p = (struct linux_ebus_dma *)edev->base_address[1];
+ cs4231_chip->eb2c = (struct linux_ebus_dma *)edev->base_address[2];
+
+ request_region((unsigned long)cs4231_chip->regs,
+ sizeof(struct cs4231_regs), "cs4231 regs");
+ request_region((unsigned long)cs4231_chip->eb2c,
+ sizeof(struct linux_ebus_dma), "4231 capture DMA");
+ request_region((unsigned long)cs4231_chip->eb2p,
+ sizeof(struct linux_ebus_dma), "4231 playback DMA");
+
+ cs4231_chip->status |= CS_STATUS_IS_EBUS;
+
+ /* Attach the interrupt handler to the audio interrupt. */
+ cs4231_chip->irq = edev->irqs[0];
+ cs4231_chip->irq2 = edev->irqs[1];
+
+ request_irq(cs4231_chip->irq, eb4231_cinterrupt, SA_SHIRQ, "cs4231", drv);
+#if 0
+ enable_irq(cs4231_chip->irq);
+#endif
+
+ request_irq(cs4231_chip->irq2, eb4231_pinterrupt, SA_SHIRQ, "cs4231", drv);
+ enable_irq(cs4231_chip->irq2);
+
+ cs4231_chip->nirqs = 2;
+
+ cs4231_enable_interrupts(drv);
+
+ /* Reset the audio chip. */
+ cs4231_chip_reset(drv);
+
+ /* Register ourselves with the midlevel audio driver. */
+ err = register_sparcaudio_driver(drv, 1);
+
+ if (err < 0) {
+ printk(KERN_ERR "cs4231: unable to register\n");
+ cs4231_disable_interrupts(drv);
+ disable_irq(cs4231_chip->irq);
+ free_irq(cs4231_chip->irq, drv);
+ if (cs4231_chip->nirqs == 2) {
+ disable_irq(cs4231_chip->irq2);
+ free_irq(cs4231_chip->irq2, drv);
+ }
+ release_region((unsigned long)cs4231_chip->regs,
+ sizeof(struct cs4231_regs));
+ release_region((unsigned long)cs4231_chip->eb2c,
+ sizeof(struct linux_ebus_dma));
+ release_region((unsigned long)cs4231_chip->eb2p,
+ sizeof(struct linux_ebus_dma));
+ cleanup:
+ kfree(drv->private);
+ return -EIO;
+ }
+
+ cs4231_chip->perchip_info.play.active =
+ cs4231_chip->perchip_info.play.pause = 0;
+
+ cs4231_chip->perchip_info.record.active =
+ cs4231_chip->perchip_info.record.pause = 0;
+
+ cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE |
+ AUDIO_SPEAKER |
+ AUDIO_LINE_OUT);
+
+ cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN |
+ AUDIO_LINE_IN |
+ AUDIO_MICROPHONE |
+ AUDIO_ANALOG_LOOPBACK);
+
+ /* Announce the hardware to the user. */
+ printk(KERN_INFO "audio%d: cs4231%c(eb2) at %p irq %s\n",
+ drv->index, (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ',
+ cs4231_chip->regs, __irq_itoa(cs4231_chip->irq));
/* Success! */
return 0;
}
+#endif
/* Probe for the cs4231 chip and then attach the driver. */
#ifdef MODULE
@@ -1691,13 +2258,17 @@
__initfunc(int cs4231_init(void))
#endif
{
- struct linux_sbus *bus;
+ struct linux_sbus *sbus;
struct linux_sbus_device *sdev;
-
+#ifdef EB4231_SUPPORT
+ struct linux_ebus *ebus;
+ struct linux_ebus_device *edev;
+#endif
+
num_drivers = 0;
/* Probe each SBUS for cs4231 chips. */
- for_all_sbusdev(sdev,bus) {
+ for_all_sbusdev(sdev,sbus) {
if (!strcmp(sdev->prom_name, "SUNW,CS4231")) {
/* Don't go over the max number of drivers. */
if (num_drivers >= MAX_DRIVERS)
@@ -1708,6 +2279,21 @@
}
}
+#ifdef EB4231_SUPPORT
+ for_each_ebus(ebus) {
+ for_each_ebusdev(edev, ebus) {
+ if (!strcmp(edev->prom_name, "SUNW,CS4231")) {
+ /* Don't go over the max number of drivers. */
+ if (num_drivers >= MAX_DRIVERS)
+ continue;
+
+ if (eb4231_attach(&drivers[num_drivers], edev) == 0)
+ num_drivers++;
+ }
+ }
+ }
+#endif
+
/* Only return success if we found some cs4231 chips. */
return (num_drivers > 0) ? 0 : -EIO;
}
@@ -1716,13 +2302,21 @@
/* Detach from an cs4231 chip given the device structure. */
static void cs4231_detach(struct sparcaudio_driver *drv)
{
- struct cs4231_chip *info = (struct cs4231_chip *)drv->private;
+ struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
cs4231_disable_interrupts(drv);
unregister_sparcaudio_driver(drv, 1);
- disable_irq(info->irq);
- free_irq(info->irq, drv);
- sparc_free_io(info->regs, info->regs_size);
+ disable_irq(cs4231_chip->irq);
+ free_irq(cs4231_chip->irq, drv);
+ if (!(cs4231_chip->status & CS_STATUS_IS_EBUS)) {
+ sparc_free_io(cs4231_chip->regs, cs4231_chip->regs_size);
+ } else {
+#ifdef EB4231_SUPPORT
+ release_region(cs4231_chip->regs, sizeof(struct cs4231_regs));
+ release_region(cs4231_chip->eb2c, sizeof(struct linux_ebus_dma));
+ release_region(cs4231_chip->eb2p, sizeof(struct linux_ebus_dma));
+#endif
+ }
kfree(drv->private);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)