linux/sound/isa/gus/gusclassic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Driver for Gravis UltraSound Classic soundcard
   4 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   5 */
   6
   7#include <linux/init.h>
   8#include <linux/err.h>
   9#include <linux/isa.h>
  10#include <linux/delay.h>
  11#include <linux/time.h>
  12#include <linux/module.h>
  13#include <asm/dma.h>
  14#include <sound/core.h>
  15#include <sound/gus.h>
  16#define SNDRV_LEGACY_FIND_FREE_IRQ
  17#define SNDRV_LEGACY_FIND_FREE_DMA
  18#include <sound/initval.h>
  19
  20#define CRD_NAME "Gravis UltraSound Classic"
  21#define DEV_NAME "gusclassic"
  22
  23MODULE_DESCRIPTION(CRD_NAME);
  24MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
  25MODULE_LICENSE("GPL");
  26
  27static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;      /* Index 0-MAX */
  28static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* ID for this card */
  29static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
  30static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;     /* 0x220,0x230,0x240,0x250,0x260 */
  31static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;        /* 3,5,9,11,12,15 */
  32static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;       /* 1,3,5,6,7 */
  33static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;       /* 1,3,5,6,7 */
  34static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29};
  35                                /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */
  36static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24};
  37static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
  38
  39module_param_array(index, int, NULL, 0444);
  40MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
  41module_param_array(id, charp, NULL, 0444);
  42MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
  43module_param_array(enable, bool, NULL, 0444);
  44MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
  45module_param_hw_array(port, long, ioport, NULL, 0444);
  46MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
  47module_param_hw_array(irq, int, irq, NULL, 0444);
  48MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
  49module_param_hw_array(dma1, int, dma, NULL, 0444);
  50MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
  51module_param_hw_array(dma2, int, dma, NULL, 0444);
  52MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
  53module_param_array(joystick_dac, int, NULL, 0444);
  54MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver.");
  55module_param_array(channels, int, NULL, 0444);
  56MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
  57module_param_array(pcm_channels, int, NULL, 0444);
  58MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
  59
  60static int snd_gusclassic_match(struct device *dev, unsigned int n)
  61{
  62        return enable[n];
  63}
  64
  65static int snd_gusclassic_create(struct snd_card *card,
  66                                 struct device *dev, unsigned int n,
  67                                 struct snd_gus_card **rgus)
  68{
  69        static const long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260};
  70        static const int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
  71        static const int possible_dmas[] = {5, 6, 7, 1, 3, -1};
  72
  73        int i, error;
  74
  75        if (irq[n] == SNDRV_AUTO_IRQ) {
  76                irq[n] = snd_legacy_find_free_irq(possible_irqs);
  77                if (irq[n] < 0) {
  78                        dev_err(dev, "unable to find a free IRQ\n");
  79                        return -EBUSY;
  80                }
  81        }
  82        if (dma1[n] == SNDRV_AUTO_DMA) {
  83                dma1[n] = snd_legacy_find_free_dma(possible_dmas);
  84                if (dma1[n] < 0) {
  85                        dev_err(dev, "unable to find a free DMA1\n");
  86                        return -EBUSY;
  87                }
  88        }
  89        if (dma2[n] == SNDRV_AUTO_DMA) {
  90                dma2[n] = snd_legacy_find_free_dma(possible_dmas);
  91                if (dma2[n] < 0) {
  92                        dev_err(dev, "unable to find a free DMA2\n");
  93                        return -EBUSY;
  94                }
  95        }
  96
  97        if (port[n] != SNDRV_AUTO_PORT)
  98                return snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n],
  99                                0, channels[n], pcm_channels[n], 0, rgus);
 100
 101        i = 0;
 102        do {
 103                port[n] = possible_ports[i];
 104                error = snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n],
 105                                0, channels[n], pcm_channels[n], 0, rgus);
 106        } while (error < 0 && ++i < ARRAY_SIZE(possible_ports));
 107
 108        return error;
 109}
 110
 111static int snd_gusclassic_detect(struct snd_gus_card *gus)
 112{
 113        unsigned char d;
 114
 115        snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0);   /* reset GF1 */
 116        d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET);
 117        if ((d & 0x07) != 0) {
 118                snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
 119                return -ENODEV;
 120        }
 121        udelay(160);
 122        snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1);   /* release reset */
 123        udelay(160);
 124        d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET);
 125        if ((d & 0x07) != 1) {
 126                snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
 127                return -ENODEV;
 128        }
 129        return 0;
 130}
 131
 132static int snd_gusclassic_probe(struct device *dev, unsigned int n)
 133{
 134        struct snd_card *card;
 135        struct snd_gus_card *gus;
 136        int error;
 137
 138        error = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
 139        if (error < 0)
 140                return error;
 141
 142        if (pcm_channels[n] < 2)
 143                pcm_channels[n] = 2;
 144
 145        error = snd_gusclassic_create(card, dev, n, &gus);
 146        if (error < 0)
 147                return error;
 148
 149        error = snd_gusclassic_detect(gus);
 150        if (error < 0)
 151                return error;
 152
 153        gus->joystick_dac = joystick_dac[n];
 154
 155        error = snd_gus_initialize(gus);
 156        if (error < 0)
 157                return error;
 158
 159        error = -ENODEV;
 160        if (gus->max_flag || gus->ess_flag) {
 161                dev_err(dev, "GUS Classic or ACE soundcard was "
 162                        "not detected at 0x%lx\n", gus->gf1.port);
 163                return error;
 164        }
 165
 166        error = snd_gf1_new_mixer(gus);
 167        if (error < 0)
 168                return error;
 169
 170        error = snd_gf1_pcm_new(gus, 0, 0);
 171        if (error < 0)
 172                return error;
 173
 174        if (!gus->ace_flag) {
 175                error = snd_gf1_rawmidi_new(gus, 0);
 176                if (error < 0)
 177                        return error;
 178        }
 179
 180        sprintf(card->longname + strlen(card->longname),
 181                " at 0x%lx, irq %d, dma %d",
 182                gus->gf1.port, gus->gf1.irq, gus->gf1.dma1);
 183
 184        if (gus->gf1.dma2 >= 0)
 185                sprintf(card->longname + strlen(card->longname),
 186                        "&%d", gus->gf1.dma2);
 187
 188        error = snd_card_register(card);
 189        if (error < 0)
 190                return error;
 191
 192        dev_set_drvdata(dev, card);
 193        return 0;
 194}
 195
 196static struct isa_driver snd_gusclassic_driver = {
 197        .match          = snd_gusclassic_match,
 198        .probe          = snd_gusclassic_probe,
 199#if 0   /* FIXME */
 200        .suspend        = snd_gusclassic_suspend,
 201#endif
 202        .driver         = {
 203                .name   = DEV_NAME
 204        }
 205};
 206
 207module_isa_driver(snd_gusclassic_driver, SNDRV_CARDS);
 208