*
* This driver is the result of the OpenVortex Project from Savannah
* (savannah.nongnu.org/projects/openvortex). I would like to thank
- * the developers of OpenVortex, Jeff Muizelar and Kester Maddock, from
+ * the developers of OpenVortex, Jeff Muizelaar and Kester Maddock, from
* whom i got plenty of help, and their codebase was invaluable.
* Thanks to the ALSA developers, they helped a lot working out
* the ALSA part.
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
-#define SNDRV_GET_ID
+#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/initval.h>
// module parameters (see "Module Parameters")
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static int pcifix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 255 };
-MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC);
-MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
+module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC);
-MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
+module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC);
-MODULE_PARM(pcifix, "1-255i");
+module_param_array(pcifix, int, NULL, 0444);
MODULE_PARM_DESC(pcifix, "Enable VIA-workaround for " CARD_NAME " soundcard.");
-MODULE_PARM_SYNTAX(pcifix,
- SNDRV_ENABLED
- ",allows:{{0,Disabled},{1,Latency},{2,Bridge},{3,Both},{255,Auto}},default:4,dialog:check");
MODULE_DESCRIPTION("Aureal vortex");
-MODULE_CLASSES("{sound}");
MODULE_LICENSE("GPL");
-MODULE_DEVICES("{{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}}");
-
-#ifndef MODULE
-/* format is: snd-mychip=enable,index,id */
-static int __init alsa_card_vortex_setup(char *str)
-{
- static unsigned __initdata nr_dev = 0;
-
- if (nr_dev >= SNDRV_CARDS)
- return 0;
- (void)(get_option(&str, &enable[nr_dev]) == 2 &&
- get_option(&str, &index[nr_dev]) == 2 &&
- get_id(&str, &id[nr_dev]) == 2);
- nr_dev++;
- return 1;
-}
-
-__setup("snd-au88x0=", alsa_card_vortex_setup);
-#endif /* ifndef MODULE */
+MODULE_SUPPORTED_DEVICE("{{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}}");
MODULE_DEVICE_TABLE(pci, snd_vortex_ids);
-static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
+static void vortex_fix_latency(struct pci_dev *vortex)
{
- struct pci_dev *via = NULL;
int rc;
-
- /* autodetect if workarounds are required */
- while ((via = pci_find_device(PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_8365_1, via))) {
- if (fix == 255) {
- printk(KERN_INFO CARD_NAME
- ": detected VIA KT133/KM133. activating workaround...\n");
- fix = 3; // do latency and via bridge workaround
- }
- break;
- }
-
- /* do not do anything if autodetection was enabled and found no VIA */
- if (fix == 255)
- return;
-
- /* fix vortex latency */
- if (fix & 0x01) {
- if (!(rc = pci_write_config_byte(vortex, 0x40, 0xff))) {
+ if (!(rc = pci_write_config_byte(vortex, 0x40, 0xff))) {
printk(KERN_INFO CARD_NAME
": vortex latency is 0xff\n");
- } else {
- printk(KERN_WARNING CARD_NAME
- ": could not set vortex latency: pci error 0x%x\n",
- rc);
- }
+ } else {
+ printk(KERN_WARNING CARD_NAME
+ ": could not set vortex latency: pci error 0x%x\n", rc);
}
+}
- /* fix via agp bridge */
- if (via && (fix & 0x02)) {
- u8 value;
+static void vortex_fix_agp_bridge(struct pci_dev *via)
+{
+ int rc;
+ u8 value;
- /*
- * only set the bit (Extend PCI#2 Internal Master for
- * Efficient Handling of Dummy Requests) if the can
- * read the config and it is not already set
- */
+ /*
+ * only set the bit (Extend PCI#2 Internal Master for
+ * Efficient Handling of Dummy Requests) if the can
+ * read the config and it is not already set
+ */
- if (!(rc = pci_read_config_byte(via, 0x42, &value))
- && ((value & 0x10)
- || !(rc =
- pci_write_config_byte(via, 0x42, value | 0x10)))) {
+ if (!(rc = pci_read_config_byte(via, 0x42, &value))
+ && ((value & 0x10)
+ || !(rc = pci_write_config_byte(via, 0x42, value | 0x10)))) {
+ printk(KERN_INFO CARD_NAME
+ ": bridge config is 0x%x\n", value | 0x10);
+ } else {
+ printk(KERN_WARNING CARD_NAME
+ ": could not set vortex latency: pci error 0x%x\n", rc);
+ }
+}
- printk(KERN_INFO CARD_NAME
- ": bridge config is 0x%x\n", value | 0x10);
- } else {
- printk(KERN_WARNING CARD_NAME
- ": could not set vortex latency: pci error 0x%x\n",
- rc);
+static void __devinit snd_vortex_workaround(struct pci_dev *vortex, int fix)
+{
+ struct pci_dev *via = NULL;
+
+ /* autodetect if workarounds are required */
+ if (fix == 255) {
+ /* VIA KT133 */
+ via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_8365_1, NULL);
+ /* VIA Apollo */
+ if (via == NULL) {
+ via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C598_1, NULL);
+ /* AMD Irongate */
+ if (via == NULL)
+ via = pci_get_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL);
+ }
+ if (via) {
+ printk(KERN_INFO CARD_NAME ": Activating latency workaround...\n");
+ vortex_fix_latency(vortex);
+ vortex_fix_agp_bridge(via);
}
+ } else {
+ if (fix & 0x1)
+ vortex_fix_latency(vortex);
+ if ((fix & 0x2) && (via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_8365_1, NULL)))
+ vortex_fix_agp_bridge(via);
+ if ((fix & 0x4) && (via = pci_get_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C598_1, NULL)))
+ vortex_fix_agp_bridge(via);
+ if ((fix & 0x8) && (via = pci_get_device(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL)))
+ vortex_fix_agp_bridge(via);
}
+ pci_dev_put(via);
}
// component-destructor
// (see "Management of Cards and Components")
-static int snd_vortex_dev_free(snd_device_t * device)
+static int snd_vortex_dev_free(struct snd_device *device)
{
- vortex_t *vortex = snd_magic_cast(vortex_t, device->device_data,
- return -ENXIO);
+ vortex_t *vortex = device->device_data;
vortex_gameport_unregister(vortex);
vortex_core_shutdown(vortex);
// Take down PCI interface.
synchronize_irq(vortex->irq);
free_irq(vortex->irq, vortex);
+ iounmap(vortex->mmio);
pci_release_regions(vortex->pci_dev);
pci_disable_device(vortex->pci_dev);
- snd_magic_kfree(vortex);
+ kfree(vortex);
return 0;
}
// chip-specific constructor
// (see "Management of Cards and Components")
static int __devinit
-snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
+snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
{
vortex_t *chip;
int err;
- static snd_device_ops_t ops = {
+ static struct snd_device_ops ops = {
.dev_free = snd_vortex_dev_free,
};
// check PCI availability (DMA).
if ((err = pci_enable_device(pci)) < 0)
return err;
- if (!pci_dma_supported(pci, VORTEX_DMA_MASK)) {
+ if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
printk(KERN_ERR "error to set DMA mask\n");
+ pci_disable_device(pci);
return -ENXIO;
}
- pci_set_dma_mask(pci, VORTEX_DMA_MASK);
- chip = snd_magic_kcalloc(vortex_t, 0, GFP_KERNEL);
- if (chip == NULL)
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ pci_disable_device(pci);
return -ENOMEM;
+ }
chip->card = card;
if ((err = pci_request_regions(pci, CARD_NAME_SHORT)) != 0)
goto regions_out;
- chip->mmio =
- ioremap_nocache(pci_resource_start(pci, 0),
- pci_resource_len(pci, 0));
+ chip->mmio = ioremap_nocache(pci_resource_start(pci, 0),
+ pci_resource_len(pci, 0));
if (!chip->mmio) {
printk(KERN_ERR "MMIO area remap failed.\n");
err = -ENOMEM;
goto core_out;
}
- if ((err =
- request_irq(pci->irq, vortex_interrupt,
- SA_INTERRUPT | SA_SHIRQ, CARD_NAME_SHORT,
- (void *)chip)) != 0) {
+ if ((err = request_irq(pci->irq, vortex_interrupt,
+ IRQF_SHARED, CARD_NAME_SHORT,
+ chip)) != 0) {
printk(KERN_ERR "cannot grab irq\n");
goto irq_out;
}
goto alloc_out;
}
+ snd_card_set_dev(card, &pci->dev);
+
*rchip = chip;
return 0;
irq_out:
vortex_core_shutdown(chip);
core_out:
- //FIXME: the type of chip->mmio might need to be changed??
- iounmap((void *)chip->mmio);
+ iounmap(chip->mmio);
ioremap_out:
pci_release_regions(chip->pci_dev);
regions_out:
snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
- snd_card_t *card;
+ struct snd_card *card;
vortex_t *chip;
int err;
return err;
}
snd_vortex_workaround(pci, pcifix[dev]);
+
+ // Card details needed in snd_vortex_midi
+ strcpy(card->driver, CARD_NAME_SHORT);
+ sprintf(card->shortname, "Aureal Vortex %s", CARD_NAME_SHORT);
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ card->shortname, chip->io, chip->irq);
+
// (4) Alloc components.
// ADB pcm.
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) {
snd_card_free(card);
return err;
}
- if ((err = vortex_gameport_register(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ vortex_gameport_register(chip);
+
#if 0
if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_VORTEX_SYNTH,
sizeof(snd_vortex_synth_arg_t), &wave) < 0
|| wave == NULL) {
- snd_printk("Can't initialize Aureal wavetable synth\n");
+ snd_printk(KERN_ERR "Can't initialize Aureal wavetable synth\n");
} else {
snd_vortex_synth_arg_t *arg;
#endif
// (5)
- strcpy(card->driver, "Aureal Vortex");
- strcpy(card->shortname, CARD_NAME_SHORT);
- sprintf(card->longname, "%s at 0x%lx irq %i",
- card->shortname, chip->io, chip->irq);
-
if ((err = pci_read_config_word(pci, PCI_DEVICE_ID,
&(chip->device))) < 0) {
snd_card_free(card);
return err;
}
// (7)
- pci_set_drvdata(pci, chip);
+ pci_set_drvdata(pci, card);
dev++;
vortex_connect_default(chip, 1);
vortex_enable_int(chip);
// destructor -- see "Destructor" sub-section
static void __devexit snd_vortex_remove(struct pci_dev *pci)
{
- vortex_t *vortex = snd_magic_cast(vortex_t,
- pci_get_drvdata(pci), return);
-
- if (vortex) {
- // Release ALSA stuff.
- snd_card_free(vortex->card);
- // Free Vortex struct.
- pci_set_drvdata(pci, NULL);
- } else
- printk("snd_vortex_remove called more than one time!\n");
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
}
// pci_driver definition
// initialization of the module
static int __init alsa_card_vortex_init(void)
{
- int err;
-
- if ((err = pci_module_init(&driver)) < 0) {
-#ifdef MODULE
- printk(KERN_ERR "Aureal soundcard not found "
- "or device busy\n");
-#endif
- return err;
- }
- return 0;
+ return pci_register_driver(&driver);
}
// clean up the module