summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2003-10-12 11:33:39 +0000
committerdes <des@FreeBSD.org>2003-10-12 11:33:39 +0000
commit7526d14d4828dfdc5a80f50fc0900618fc053e1d (patch)
tree352573868c01dcc3f16fdb2fb9ed3733e1f63d33 /sys/dev/sound
parentefae2cbb66643c1b8e0794e29d308b83930b8e64 (diff)
downloadFreeBSD-src-7526d14d4828dfdc5a80f50fc0900618fc053e1d.zip
FreeBSD-src-7526d14d4828dfdc5a80f50fc0900618fc053e1d.tar.gz
A couple of months' worth of back-burner hacking: restructure to better
handle the minor (but significant) differences between the various Vortex chips; add (incomplete) support for playback.
Diffstat (limited to 'sys/dev/sound')
-rw-r--r--sys/dev/sound/pci/au88x0.c168
-rw-r--r--sys/dev/sound/pci/au88x0.h110
2 files changed, 189 insertions, 89 deletions
diff --git a/sys/dev/sound/pci/au88x0.c b/sys/dev/sound/pci/au88x0.c
index 53905c8..d5191b2 100644
--- a/sys/dev/sound/pci/au88x0.c
+++ b/sys/dev/sound/pci/au88x0.c
@@ -40,6 +40,103 @@
/***************************************************************************\
* *
+ * SUPPORTED CHIPSETS *
+ * *
+\***************************************************************************/
+
+static struct au88x0_chipset au88x0_chipsets[] = {
+ {
+ .auc_name = "Aureal Vortex (8820)",
+ .auc_pci_id = 0x000112eb,
+
+ .auc_control = 0x1280c,
+
+ .auc_irq_source = 0x12800,
+ .auc_irq_mask = 0x12804,
+ .auc_irq_control = 0x12808,
+ .auc_irq_status = 0x1199c,
+
+ .auc_dma_control = 0x1060c,
+
+ .auc_fifo_size = 0x20,
+ .auc_wt_fifos = 32,
+ .auc_wt_fifo_base = 0x0e800,
+ .auc_wt_fifo_ctl = 0x0f800,
+ .auc_wt_dma_ctl = 0x10500,
+ .auc_adb_fifos = 16,
+ .auc_adb_fifo_base = 0x0e000,
+ .auc_adb_fifo_ctl = 0x0f840,
+ .auc_adb_dma_ctl = 0x10580,
+
+ .auc_adb_route_base = 0x10800,
+ .auc_adb_route_bits = 7,
+ .auc_adb_codec_in = 0x48,
+ .auc_adb_codec_out = 0x58,
+ },
+ {
+ .auc_name = "Aureal Vortex 2 (8830)",
+ .auc_pci_id = 0x000212eb,
+
+ .auc_control = 0x2a00c,
+
+ .auc_irq_source = 0x2a000,
+ .auc_irq_mask = 0x2a004,
+ .auc_irq_control = 0x2a008,
+ .auc_irq_status = 0x2919c,
+
+ .auc_dma_control = 0x27ae8,
+
+ .auc_fifo_size = 0x40,
+ .auc_wt_fifos = 64,
+ .auc_wt_fifo_base = 0x10000,
+ .auc_wt_fifo_ctl = 0x16000,
+ .auc_wt_dma_ctl = 0x27900,
+ .auc_adb_fifos = 32,
+ .auc_adb_fifo_base = 0x14000,
+ .auc_adb_fifo_ctl = 0x16100,
+ .auc_adb_dma_ctl = 0x27a00,
+
+ .auc_adb_route_base = 0x28000,
+ .auc_adb_route_bits = 8,
+ .auc_adb_codec_in = 0x70,
+ .auc_adb_codec_out = 0x88,
+ },
+ {
+ .auc_name = "Aureal Vortex Advantage (8810)",
+ .auc_pci_id = 0x000312eb,
+
+ .auc_control = 0x2a00c,
+
+ .auc_irq_source = 0x2a000,
+ .auc_irq_mask = 0x2a004,
+ .auc_irq_control = 0x2a008,
+ .auc_irq_status = 0x2919c,
+
+ .auc_dma_control = 0x27ae8,
+
+ .auc_fifo_size = 0x20,
+ .auc_wt_fifos = 32,
+ .auc_wt_fifo_base = 0x10000,
+ .auc_wt_fifo_ctl = 0x16000,
+ .auc_wt_dma_ctl = 0x27fd8,
+ .auc_adb_fifos = 16,
+ .auc_adb_fifo_base = 0x14000,
+ .auc_adb_fifo_ctl = 0x16100,
+ .auc_adb_dma_ctl = 0x27180,
+
+ .auc_adb_route_base = 0x28000,
+ .auc_adb_route_bits = 8,
+ .auc_adb_codec_in = 0x70,
+ .auc_adb_codec_out = 0x88,
+ },
+ {
+ .auc_pci_id = 0,
+ }
+};
+
+
+/***************************************************************************\
+ * *
* FORMATS AND CAPABILITIES *
* *
\***************************************************************************/
@@ -343,12 +440,13 @@ static void
au88x0_intr(void *arg)
{
struct au88x0_info *aui = arg;
+ struct au88x0_chipset *auc = aui->aui_chipset;
int pending, source;
- pending = au88x0_read(aui, AU88X0_IRQ_PENDING, 4);
+ pending = au88x0_read(aui, auc->auc_irq_control, 4);
if ((pending & AU88X0_IRQ_PENDING_BIT) == 0)
return;
- source = au88x0_read(aui, AU88X0_IRQ_SOURCE, 4);
+ source = au88x0_read(aui, auc->auc_irq_source, 4);
if (source & AU88X0_IRQ_FATAL_ERR)
device_printf(aui->aui_dev,
"fatal error interrupt received\n");
@@ -358,8 +456,8 @@ au88x0_intr(void *arg)
/* XXX handle the others... */
/* acknowledge the interrupts we just handled */
- au88x0_write(aui, AU88X0_IRQ_SOURCE, source, 4);
- au88x0_read(aui, AU88X0_IRQ_SOURCE, 4);
+ au88x0_write(aui, auc->auc_irq_source, source, 4);
+ au88x0_read(aui, auc->auc_irq_source, 4);
}
@@ -377,19 +475,20 @@ au88x0_intr(void *arg)
static void
au88x0_fifo_init(struct au88x0_info *aui)
{
+ struct au88x0_chipset *auc = aui->aui_chipset;
int i;
/* reset, then clear the ADB FIFOs */
- for (i = 0; i < AU88X0_ADB_FIFOS; ++i)
- au88x0_write(aui, AU88X0_ADB_FIFO_CTL + i * 4, 0x42000, 4);
- for (i = 0; i < AU88X0_ADB_FIFOS * AU88X0_ADB_FIFO_SIZE; ++i)
- au88x0_write(aui, AU88X0_ADB_FIFO_BASE + i * 4, 0, 4);
+ for (i = 0; i < auc->auc_adb_fifos; ++i)
+ au88x0_write(aui, auc->auc_adb_fifo_ctl + i * 4, 0x42000, 4);
+ for (i = 0; i < auc->auc_adb_fifos * auc->auc_fifo_size; ++i)
+ au88x0_write(aui, auc->auc_adb_fifo_base + i * 4, 0, 4);
/* reset, then clear the WT FIFOs */
- for (i = 0; i < AU88X0_WT_FIFOS; ++i)
- au88x0_write(aui, AU88X0_WT_FIFO_CTL + i * 4, 0x42000, 4);
- for (i = 0; i < AU88X0_WT_FIFOS * AU88X0_WT_FIFO_SIZE; ++i)
- au88x0_write(aui, AU88X0_WT_FIFO_BASE + i * 4, 0, 4);
+ for (i = 0; i < auc->auc_wt_fifos; ++i)
+ au88x0_write(aui, auc->auc_wt_fifo_ctl + i * 4, 0x42000, 4);
+ for (i = 0; i < auc->auc_wt_fifos * auc->auc_fifo_size; ++i)
+ au88x0_write(aui, auc->auc_wt_fifo_base + i * 4, 0, 4);
}
/*
@@ -398,15 +497,16 @@ au88x0_fifo_init(struct au88x0_info *aui)
static void
au88x0_init(struct au88x0_info *aui)
{
+ struct au88x0_chipset *auc = aui->aui_chipset;
/* reset the chip */
- au88x0_write(aui, AU88X0_CONTROL, 0xffffffff, 4);
+ au88x0_write(aui, auc->auc_control, 0xffffffff, 4);
DELAY(10000);
/* clear all interrupts */
- au88x0_write(aui, AU88X0_IRQ_SOURCE, 0xffffffff, 4);
- au88x0_read(aui, AU88X0_IRQ_SOURCE, 4);
- au88x0_read(aui, AU88X0_IRQ_STATUS, 4);
+ au88x0_write(aui, auc->auc_irq_source, 0xffffffff, 4);
+ au88x0_read(aui, auc->auc_irq_source, 4);
+ au88x0_read(aui, auc->auc_irq_status, 4);
/* initialize the codec */
au88x0_codec_init(aui);
@@ -416,7 +516,7 @@ au88x0_init(struct au88x0_info *aui)
/* initialize the DMA engine */
/* XXX chicken-waving! */
- au88x0_write(aui, AU88X0_DMA_CONTROL, 0x1380000, 4);
+ au88x0_write(aui, auc->auc_dma_control, 0x1380000, 4);
}
/*
@@ -448,18 +548,17 @@ au88x0_set_status(device_t dev)
static int
au88x0_pci_probe(device_t dev)
{
+ struct au88x0_chipset *auc;
+ uint32_t pci_id;
- switch (pci_get_devid(dev)) {
- case AUREAL_VORTEX_2:
- device_set_desc(dev, "Aureal Vortex 2");
- return (0);
- case AUREAL_VORTEX_ADVANTAGE:
- device_set_desc(dev, "Aureal Vortex Advantage");
- return (0);
- default:
- return (ENXIO);
+ pci_id = pci_get_devid(dev);
+ for (auc = au88x0_chipsets; auc->auc_pci_id; ++auc) {
+ if (auc->auc_pci_id == pci_id) {
+ device_set_desc(dev, auc->auc_name);
+ return (0);
+ }
}
- return (0);
+ return (ENXIO);
}
/*
@@ -468,6 +567,7 @@ au88x0_pci_probe(device_t dev)
static int
au88x0_pci_attach(device_t dev)
{
+ struct au88x0_chipset *auc;
struct au88x0_info *aui = NULL;
uint32_t config;
int error;
@@ -480,15 +580,11 @@ au88x0_pci_attach(device_t dev)
/* Model-specific parameters */
aui->aui_model = pci_get_devid(dev);
- switch (aui->aui_model) {
- case AUREAL_VORTEX_1:
- break;
- case AUREAL_VORTEX_2:
- case AUREAL_VORTEX_ADVANTAGE:
- break;
- default:
+ for (auc = au88x0_chipsets; auc->auc_pci_id; ++auc)
+ if (auc->auc_pci_id == aui->aui_model)
+ aui->aui_chipset = auc;
+ if (aui->aui_chipset == NULL)
panic("%s() called for non-au88x0 device", __func__);
- }
/* enable pio, mmio, bus-mastering dma */
config = pci_read_config(dev, PCIR_COMMAND, 2);
@@ -567,8 +663,8 @@ au88x0_pci_attach(device_t dev)
/* register with the pcm driver */
if (pcm_register(dev, aui, 0, 0))
goto failed;
-#if 0
pcm_addchan(dev, PCMDIR_PLAY, &au88x0_chan_class, aui);
+#if 0
pcm_addchan(dev, PCMDIR_REC, &au88x0_chan_class, aui);
#endif
au88x0_set_status(dev);
diff --git a/sys/dev/sound/pci/au88x0.h b/sys/dev/sound/pci/au88x0.h
index 4b442ee..15f7b76 100644
--- a/sys/dev/sound/pci/au88x0.h
+++ b/sys/dev/sound/pci/au88x0.h
@@ -32,6 +32,56 @@
#define _AU88X0_H_INCLUDED
/*
+ * Chipset parameters
+ */
+struct au88x0_chipset {
+ const char *auc_name;
+ uint32_t auc_pci_id;
+
+ /* General control register */
+ uint32_t auc_control;
+#define AU88X0_CTL_MIDI_ENABLE 0x0001
+#define AU88X0_CTL_GAME_ENABLE 0x0008
+#define AU88X0_CTL_IRQ_ENABLE 0x4000
+
+ /* IRQ control register */
+ uint32_t auc_irq_source;
+#define AU88X0_IRQ_FATAL_ERR 0x0001
+#define AU88X0_IRQ_PARITY_ERR 0x0002
+#define AU88X0_IRQ_REG_ERR 0x0004
+#define AU88X0_IRQ_FIFO_ERR 0x0008
+#define AU88X0_IRQ_DMA_ERR 0x0010
+#define AU88X0_IRQ_PCMOUT 0x0020
+#define AU88X0_IRQ_TIMER 0x1000
+#define AU88X0_IRQ_MIDI 0x2000
+#define AU88X0_IRQ_MODEM 0x4000
+ uint32_t auc_irq_mask;
+ uint32_t auc_irq_control;
+#define AU88X0_IRQ_PENDING_BIT 0x0001
+ uint32_t auc_irq_status;
+
+ /* DMA control registers */
+ uint32_t auc_dma_control;
+
+ /* FIFOs */
+ int auc_fifo_size;
+ int auc_wt_fifos;
+ uint32_t auc_wt_fifo_base;
+ uint32_t auc_wt_fifo_ctl;
+ uint32_t auc_wt_dma_ctl;
+ int auc_adb_fifos;
+ uint32_t auc_adb_fifo_base;
+ uint32_t auc_adb_fifo_ctl;
+ uint32_t auc_adb_dma_ctl;
+
+ /* Routing */
+ uint32_t auc_adb_route_base;
+ int auc_adb_route_bits;
+ int auc_adb_codec_in;
+ int auc_adb_codec_out;
+};
+
+/*
* Channel information
*/
struct au88x0_chan_info {
@@ -48,9 +98,16 @@ struct au88x0_info {
/* the device we're associated with */
device_t aui_dev;
uint32_t aui_model;
+ struct au88x0_chipset *aui_chipset;
/* parameters */
bus_size_t aui_bufsize;
+ int aui_wt_fifos;
+ int aui_wt_fifo_ctl;
+ int aui_adb_fifos;
+ int aui_adb_fifo_ctl;
+ int aui_fifo_size;
+ uint32_t aui_chanbase;
/* bus_space tag and handle */
bus_space_tag_t aui_spct;
@@ -78,13 +135,6 @@ struct au88x0_info {
};
/*
- * PCI IDs of supported cards
- */
-#define AUREAL_VORTEX_1 0x000112eb /* 8820 (not supported) */
-#define AUREAL_VORTEX_2 0x000212eb /* 8830 */
-#define AUREAL_VORTEX_ADVANTAGE 0x000312eb /* 8810 */
-
-/*
* Common parameters
*/
#define AU88X0_SETTLE_DELAY 1000
@@ -94,30 +144,6 @@ struct au88x0_info {
#define AU88X0_BUFSIZE_MAX 0x4000
/*
- * General control registers
- */
-#define AU88X0_CONTROL 0x2a00c
-#define AU88X0_CTL_MIDI_ENABLE 0x0001
-#define AU88X0_CTL_GAME_ENABLE 0x0008
-#define AU88X0_CTL_IRQ_ENABLE 0x4000
-
-#define AU88X0_IRQ_SOURCE 0x2a000
-#define AU88X0_IRQ_MASK 0x2a004
-#define AU88X0_IRQ_FATAL_ERR 0x0001
-#define AU88X0_IRQ_PARITY_ERR 0x0002
-#define AU88X0_IRQ_REG_ERR 0x0004
-#define AU88X0_IRQ_FIFO_ERR 0x0008
-#define AU88X0_IRQ_DMA_ERR 0x0010
-#define AU88X0_IRQ_PCMOUT 0x0020
-#define AU88X0_IRQ_TIMER 0x1000
-#define AU88X0_IRQ_MIDI 0x2000
-#define AU88X0_IRQ_MODEM 0x4000
-#define AU88X0_IRQ_PENDING 0x2a008
-#define AU88X0_IRQ_PENDING_BIT 0x0001
-#define AU88X0_IRQ_STATUS 0x2919c
-#define AU88X0_DMA_CONTROL 0x27ae8
-
-/*
* Codec control registers
*
* AU88X0_CODEC_CHANNEL array of 32 32-bit words
@@ -149,26 +175,4 @@ struct au88x0_info {
(((d) << AU88X0_CDIO_DATA_SHIFT) & AU88X0_CDIO_DATA_MASK))
#define AU88X0_CODEC_ENABLE 0x29190
-/*
- * FIFO and DMA contorl registers
- *
- * There are two sets of these, one for PCM audio (ADB) and one for
- * wavetables (WT).
- */
-#define AU88X0_ADB_FIFOS 32
-#define AU88X0_ADB_FIFO_CTL 0x16100
-#define AU88X0_ADB_FIFO_BASE 0x14000
-#define AU88X0_ADB_FIFO_SIZE 0x40
-#define AU8810_ADB_DMA_CTL 0x27180
-#define AU8820_ADB_DMA_CTL 0x10580
-#define AU8830_ADB_DMA_CTL 0x27a00
-
-#define AU88X0_WT_FIFOS 32
-#define AU88X0_WT_FIFO_CTL 0x16000
-#define AU88X0_WT_FIFO_BASE 0x10000
-#define AU88X0_WT_FIFO_SIZE 0x40
-#define AU8810_WT_DMA_CTL 0x27fd8
-#define AU8820_WT_DMA_CTL 0x10500
-#define AU8830_WT_DMA_CTL 0x27900
-
#endif
OpenPOWER on IntegriCloud