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