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