fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / sound / pci / au88x0 / au88x0.c
index f8bf476..238154b 100644 (file)
@@ -4,7 +4,7 @@
  *
  *   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.
@@ -19,7 +19,8 @@
 #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")
@@ -28,118 +29,109 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
 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;
 }
@@ -147,11 +139,11 @@ static int snd_vortex_dev_free(snd_device_t * device)
 // 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,
        };
 
@@ -160,15 +152,18 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
        // 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;
 
@@ -186,9 +181,8 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
        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;
@@ -203,10 +197,9 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
                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;
        }
@@ -220,6 +213,8 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
                goto alloc_out;
        }
 
+       snd_card_set_dev(card, &pci->dev);
+
        *rchip = chip;
 
        return 0;
@@ -230,8 +225,7 @@ snd_vortex_create(snd_card_t * card, struct pci_dev *pci, vortex_t ** rchip)
       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:
@@ -246,7 +240,7 @@ static int __devinit
 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;
 
@@ -268,6 +262,13 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                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) {
@@ -309,15 +310,14 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                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;
 
@@ -331,11 +331,6 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 #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);
@@ -370,7 +365,7 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
                return err;
        }
        // (7)
-       pci_set_drvdata(pci, chip);
+       pci_set_drvdata(pci, card);
        dev++;
        vortex_connect_default(chip, 1);
        vortex_enable_int(chip);
@@ -380,16 +375,8 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 // 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
@@ -403,16 +390,7 @@ static struct pci_driver driver = {
 // 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