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