diff options
author | des <des@FreeBSD.org> | 2003-10-12 11:33:39 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2003-10-12 11:33:39 +0000 |
commit | 7526d14d4828dfdc5a80f50fc0900618fc053e1d (patch) | |
tree | 352573868c01dcc3f16fdb2fb9ed3733e1f63d33 /sys/dev/sound/pci | |
parent | efae2cbb66643c1b8e0794e29d308b83930b8e64 (diff) | |
download | FreeBSD-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/pci')
-rw-r--r-- | sys/dev/sound/pci/au88x0.c | 168 | ||||
-rw-r--r-- | sys/dev/sound/pci/au88x0.h | 110 |
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 |