^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * ALSA driver for the Aureal Vortex family of soundprocessors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Manuel Jander (mjander@embedded.cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This driver is the result of the OpenVortex Project from Savannah
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (savannah.nongnu.org/projects/openvortex). I would like to thank
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * the developers of OpenVortex, Jeff Muizelaar and Kester Maddock, from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * whom i got plenty of help, and their codebase was invaluable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Thanks to the ALSA developers, they helped a lot working out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * the ALSA part.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Thanks also to Sourceforge for maintaining the old binary drivers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * and the forum, where developers could comunicate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Now at least i can play Legacy DOOM with MIDI music :-)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "au88x0.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) // module parameters (see "Module Parameters")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int pcifix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 255 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) module_param_array(index, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) module_param_array(id, charp, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) module_param_array(enable, bool, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) module_param_array(pcifix, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) MODULE_PARM_DESC(pcifix, "Enable VIA-workaround for " CARD_NAME " soundcard.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MODULE_DESCRIPTION("Aureal vortex");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MODULE_SUPPORTED_DEVICE("{{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}}");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) MODULE_DEVICE_TABLE(pci, snd_vortex_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static void vortex_fix_latency(struct pci_dev *vortex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (!(rc = pci_write_config_byte(vortex, 0x40, 0xff))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) dev_info(&vortex->dev, "vortex latency is 0xff\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) dev_warn(&vortex->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) "could not set vortex latency: pci error 0x%x\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static void vortex_fix_agp_bridge(struct pci_dev *via)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) u8 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * only set the bit (Extend PCI#2 Internal Master for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * Efficient Handling of Dummy Requests) if the can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * read the config and it is not already set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (!(rc = pci_read_config_byte(via, 0x42, &value))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) && ((value & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) || !(rc = pci_write_config_byte(via, 0x42, value | 0x10)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) dev_info(&via->dev, "bridge config is 0x%x\n", value | 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) dev_warn(&via->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) "could not set vortex latency: pci error 0x%x\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void snd_vortex_workaround(struct pci_dev *vortex, int fix)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct pci_dev *via = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* autodetect if workarounds are required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (fix == 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* VIA KT133 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) via = pci_get_device(PCI_VENDOR_ID_VIA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) PCI_DEVICE_ID_VIA_8365_1, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) /* VIA Apollo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (via == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) via = pci_get_device(PCI_VENDOR_ID_VIA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) PCI_DEVICE_ID_VIA_82C598_1, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) /* AMD Irongate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (via == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) via = pci_get_device(PCI_VENDOR_ID_AMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (via) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) dev_info(&vortex->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) "Activating latency workaround...\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) vortex_fix_latency(vortex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) vortex_fix_agp_bridge(via);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (fix & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) vortex_fix_latency(vortex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if ((fix & 0x2) && (via = pci_get_device(PCI_VENDOR_ID_VIA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) PCI_DEVICE_ID_VIA_8365_1, NULL)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) vortex_fix_agp_bridge(via);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if ((fix & 0x4) && (via = pci_get_device(PCI_VENDOR_ID_VIA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) PCI_DEVICE_ID_VIA_82C598_1, NULL)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) vortex_fix_agp_bridge(via);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if ((fix & 0x8) && (via = pci_get_device(PCI_VENDOR_ID_AMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) vortex_fix_agp_bridge(via);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) pci_dev_put(via);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) // component-destructor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) // (see "Management of Cards and Components")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int snd_vortex_dev_free(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) vortex_t *vortex = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) vortex_gameport_unregister(vortex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) vortex_core_shutdown(vortex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) // Take down PCI interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) free_irq(vortex->irq, vortex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) iounmap(vortex->mmio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) pci_release_regions(vortex->pci_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) pci_disable_device(vortex->pci_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) kfree(vortex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) // chip-specific constructor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) // (see "Management of Cards and Components")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) vortex_t *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .dev_free = snd_vortex_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) *rchip = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) // check PCI availability (DMA).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if ((err = pci_enable_device(pci)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) dev_err(card->dev, "error to set DMA mask\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) chip = kzalloc(sizeof(*chip), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (chip == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) chip->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) // initialize the stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) chip->pci_dev = pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) chip->io = pci_resource_start(pci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) chip->vendor = pci->vendor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) chip->device = pci->device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) chip->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) chip->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) // (1) PCI resource allocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) // Get MMIO area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if ((err = pci_request_regions(pci, CARD_NAME_SHORT)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) goto regions_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) chip->mmio = pci_ioremap_bar(pci, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (!chip->mmio) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) dev_err(card->dev, "MMIO area remap failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) goto ioremap_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* Init audio core.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * This must be done before we do request_irq otherwise we can get spurious
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) * interrupts that we do not handle properly and make a mess of things */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if ((err = vortex_core_init(chip)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) dev_err(card->dev, "hw core init failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) goto core_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if ((err = request_irq(pci->irq, vortex_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) IRQF_SHARED, KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) chip)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) dev_err(card->dev, "cannot grab irq\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) goto irq_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) chip->irq = pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) card->sync_irq = chip->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) // End of PCI setup.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) // Register alsa root device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) goto alloc_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) *rchip = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) alloc_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) free_irq(chip->irq, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) irq_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) vortex_core_shutdown(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) core_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) iounmap(chip->mmio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) ioremap_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) pci_release_regions(chip->pci_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) regions_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) pci_disable_device(chip->pci_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) //FIXME: this not the right place to unregister the gameport
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) vortex_gameport_unregister(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) kfree(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) // constructor -- see "Constructor" sub-section
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) static int dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) vortex_t *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) // (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (dev >= SNDRV_CARDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (!enable[dev]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) dev++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) // (2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 0, &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) // (3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if ((err = snd_vortex_create(card, pci, &chip)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) snd_vortex_workaround(pci, pcifix[dev]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) // Card details needed in snd_vortex_midi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) strcpy(card->driver, CARD_NAME_SHORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) sprintf(card->shortname, "Aureal Vortex %s", CARD_NAME_SHORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) sprintf(card->longname, "%s at 0x%lx irq %i",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) card->shortname, chip->io, chip->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) // (4) Alloc components.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) err = snd_vortex_mixer(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) // ADB pcm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_PCM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #ifndef CHIP_AU8820
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) // ADB SPDIF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) // A3D
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) // ADB I2S
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_I2S, 1)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) #ifndef CHIP_AU8810
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) // WT pcm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if ((err = snd_vortex_midi(chip)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) vortex_gameport_register(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_VORTEX_SYNTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) sizeof(snd_vortex_synth_arg_t), &wave) < 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) || wave == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) dev_err(card->dev, "Can't initialize Aureal wavetable synth\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) snd_vortex_synth_arg_t *arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) arg = SNDRV_SEQ_DEVICE_ARGPTR(wave);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) strcpy(wave->name, "Aureal Synth");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) arg->hwptr = vortex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) arg->index = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) arg->seq_ports = seq_ports[dev];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) arg->max_voices = max_synth_voices[dev];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) // (5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if ((err = pci_read_config_word(pci, PCI_DEVICE_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) &(chip->device))) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if ((err = pci_read_config_word(pci, PCI_VENDOR_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) &(chip->vendor))) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) chip->rev = pci->revision;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) #ifdef CHIP_AU8830
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if ((chip->rev) != 0xfe && (chip->rev) != 0xfa) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) dev_alert(card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) "The revision (%x) of your card has not been seen before.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) chip->rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) dev_alert(card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) "Please email the results of 'lspci -vv' to openvortex-dev@nongnu.org.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) // (6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if ((err = snd_card_register(card)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) // (7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) pci_set_drvdata(pci, card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) dev++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) vortex_connect_default(chip, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) vortex_enable_int(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) // destructor -- see "Destructor" sub-section
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) static void snd_vortex_remove(struct pci_dev *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) snd_card_free(pci_get_drvdata(pci));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) // pci_driver definition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) static struct pci_driver vortex_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) .id_table = snd_vortex_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) .probe = snd_vortex_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .remove = snd_vortex_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) module_pci_driver(vortex_driver);