linux/sound/pci/au88x0/au88x0.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * ALSA driver for the Aureal Vortex family of soundprocessors.
   4 * Author: Manuel Jander (mjander@embedded.cl)
   5 *
   6 *   This driver is the result of the OpenVortex Project from Savannah
   7 * (savannah.nongnu.org/projects/openvortex). I would like to thank
   8 * the developers of OpenVortex, Jeff Muizelaar and Kester Maddock, from
   9 * whom i got plenty of help, and their codebase was invaluable.
  10 *   Thanks to the ALSA developers, they helped a lot working out
  11 * the ALSA part.
  12 *   Thanks also to Sourceforge for maintaining the old binary drivers,
  13 * and the forum, where developers could comunicate.
  14 *
  15 * Now at least i can play Legacy DOOM with MIDI music :-)
  16 */
  17
  18#include "au88x0.h"
  19#include <linux/init.h>
  20#include <linux/pci.h>
  21#include <linux/slab.h>
  22#include <linux/interrupt.h>
  23#include <linux/module.h>
  24#include <linux/dma-mapping.h>
  25#include <sound/initval.h>
  26
  27// module parameters (see "Module Parameters")
  28static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
  29static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
  30static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
  31static int pcifix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 255 };
  32
  33module_param_array(index, int, NULL, 0444);
  34MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
  35module_param_array(id, charp, NULL, 0444);
  36MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
  37module_param_array(enable, bool, NULL, 0444);
  38MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
  39module_param_array(pcifix, int, NULL, 0444);
  40MODULE_PARM_DESC(pcifix, "Enable VIA-workaround for " CARD_NAME " soundcard.");
  41
  42MODULE_DESCRIPTION("Aureal vortex");
  43MODULE_LICENSE("GPL");
  44MODULE_SUPPORTED_DEVICE("{{Aureal Semiconductor Inc., Aureal Vortex Sound Processor}}");
  45
  46MODULE_DEVICE_TABLE(pci, snd_vortex_ids);
  47
  48static void vortex_fix_latency(struct pci_dev *vortex)
  49{
  50        int rc;
  51        if (!(rc = pci_write_config_byte(vortex, 0x40, 0xff))) {
  52                        dev_info(&vortex->dev, "vortex latency is 0xff\n");
  53        } else {
  54                dev_warn(&vortex->dev,
  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                dev_info(&via->dev, "bridge config is 0x%x\n", value | 0x10);
  74        } else {
  75                dev_warn(&via->dev,
  76                         "could not set vortex latency: pci error 0x%x\n", rc);
  77        }
  78}
  79
  80static void snd_vortex_workaround(struct pci_dev *vortex, int fix)
  81{
  82        struct pci_dev *via = NULL;
  83
  84        /* autodetect if workarounds are required */
  85        if (fix == 255) {
  86                /* VIA KT133 */
  87                via = pci_get_device(PCI_VENDOR_ID_VIA,
  88                        PCI_DEVICE_ID_VIA_8365_1, NULL);
  89                /* VIA Apollo */
  90                if (via == NULL) {
  91                        via = pci_get_device(PCI_VENDOR_ID_VIA,
  92                                PCI_DEVICE_ID_VIA_82C598_1, NULL);
  93                        /* AMD Irongate */
  94                        if (via == NULL)
  95                                via = pci_get_device(PCI_VENDOR_ID_AMD,
  96                                        PCI_DEVICE_ID_AMD_FE_GATE_7007, NULL);
  97                }
  98                if (via) {
  99                        dev_info(&vortex->dev,
 100                                 "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
 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 (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
 155            dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
 156                dev_err(card->dev, "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                dev_err(card->dev, "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                dev_err(card->dev, "hw core init failed\n");
 195                goto core_out;
 196        }
 197
 198        if ((err = request_irq(pci->irq, vortex_interrupt,
 199                               IRQF_SHARED, KBUILD_MODNAME,
 200                               chip)) != 0) {
 201                dev_err(card->dev, "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        *rchip = chip;
 215
 216        return 0;
 217
 218      alloc_out:
 219        free_irq(chip->irq, chip);
 220      irq_out:
 221        vortex_core_shutdown(chip);
 222      core_out:
 223        iounmap(chip->mmio);
 224      ioremap_out:
 225        pci_release_regions(chip->pci_dev);
 226      regions_out:
 227        pci_disable_device(chip->pci_dev);
 228        //FIXME: this not the right place to unregister the gameport
 229        vortex_gameport_unregister(chip);
 230        kfree(chip);
 231        return err;
 232}
 233
 234// constructor -- see "Constructor" sub-section
 235static int
 236snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 237{
 238        static int dev;
 239        struct snd_card *card;
 240        vortex_t *chip;
 241        int err;
 242
 243        // (1)
 244        if (dev >= SNDRV_CARDS)
 245                return -ENODEV;
 246        if (!enable[dev]) {
 247                dev++;
 248                return -ENOENT;
 249        }
 250        // (2)
 251        err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
 252                           0, &card);
 253        if (err < 0)
 254                return err;
 255
 256        // (3)
 257        if ((err = snd_vortex_create(card, pci, &chip)) < 0) {
 258                snd_card_free(card);
 259                return err;
 260        }
 261        snd_vortex_workaround(pci, pcifix[dev]);
 262
 263        // Card details needed in snd_vortex_midi
 264        strcpy(card->driver, CARD_NAME_SHORT);
 265        sprintf(card->shortname, "Aureal Vortex %s", CARD_NAME_SHORT);
 266        sprintf(card->longname, "%s at 0x%lx irq %i",
 267                card->shortname, chip->io, chip->irq);
 268
 269        // (4) Alloc components.
 270        err = snd_vortex_mixer(chip);
 271        if (err < 0) {
 272                snd_card_free(card);
 273                return err;
 274        }
 275        // ADB pcm.
 276        err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_PCM);
 277        if (err < 0) {
 278                snd_card_free(card);
 279                return err;
 280        }
 281#ifndef CHIP_AU8820
 282        // ADB SPDIF
 283        if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1)) < 0) {
 284                snd_card_free(card);
 285                return err;
 286        }
 287        // A3D
 288        if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D)) < 0) {
 289                snd_card_free(card);
 290                return err;
 291        }
 292#endif
 293        /*
 294           // ADB I2S
 295           if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_I2S, 1)) < 0) {
 296           snd_card_free(card);
 297           return err;
 298           }
 299         */
 300#ifndef CHIP_AU8810
 301        // WT pcm.
 302        if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT)) < 0) {
 303                snd_card_free(card);
 304                return err;
 305        }
 306#endif
 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                dev_err(card->dev, "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                dev_alert(card->dev,
 346                          "The revision (%x) of your card has not been seen before.\n",
 347                       chip->rev);
 348                dev_alert(card->dev,
 349                          "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 snd_vortex_remove(struct pci_dev *pci)
 371{
 372        snd_card_free(pci_get_drvdata(pci));
 373}
 374
 375// pci_driver definition
 376static struct pci_driver vortex_driver = {
 377        .name = KBUILD_MODNAME,
 378        .id_table = snd_vortex_ids,
 379        .probe = snd_vortex_probe,
 380        .remove = snd_vortex_remove,
 381};
 382
 383module_pci_driver(vortex_driver);
 384