Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Driver for Gravis UltraSound MAX soundcard
0004  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
0005  */
0006 
0007 #include <linux/init.h>
0008 #include <linux/err.h>
0009 #include <linux/isa.h>
0010 #include <linux/delay.h>
0011 #include <linux/time.h>
0012 #include <linux/module.h>
0013 #include <asm/dma.h>
0014 #include <sound/core.h>
0015 #include <sound/gus.h>
0016 #include <sound/wss.h>
0017 #define SNDRV_LEGACY_FIND_FREE_IRQ
0018 #define SNDRV_LEGACY_FIND_FREE_DMA
0019 #include <sound/initval.h>
0020 
0021 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
0022 MODULE_DESCRIPTION("Gravis UltraSound MAX");
0023 MODULE_LICENSE("GPL");
0024 
0025 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;  /* Index 0-MAX */
0026 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;   /* ID for this card */
0027 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
0028 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x230,0x240,0x250,0x260 */
0029 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;    /* 2,3,5,9,11,12,15 */
0030 static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;   /* 1,3,5,6,7 */
0031 static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;   /* 1,3,5,6,7 */
0032 static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29};
0033                 /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */
0034 static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24};
0035 static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
0036 
0037 module_param_array(index, int, NULL, 0444);
0038 MODULE_PARM_DESC(index, "Index value for GUS MAX soundcard.");
0039 module_param_array(id, charp, NULL, 0444);
0040 MODULE_PARM_DESC(id, "ID string for GUS MAX soundcard.");
0041 module_param_array(enable, bool, NULL, 0444);
0042 MODULE_PARM_DESC(enable, "Enable GUS MAX soundcard.");
0043 module_param_hw_array(port, long, ioport, NULL, 0444);
0044 MODULE_PARM_DESC(port, "Port # for GUS MAX driver.");
0045 module_param_hw_array(irq, int, irq, NULL, 0444);
0046 MODULE_PARM_DESC(irq, "IRQ # for GUS MAX driver.");
0047 module_param_hw_array(dma1, int, dma, NULL, 0444);
0048 MODULE_PARM_DESC(dma1, "DMA1 # for GUS MAX driver.");
0049 module_param_hw_array(dma2, int, dma, NULL, 0444);
0050 MODULE_PARM_DESC(dma2, "DMA2 # for GUS MAX driver.");
0051 module_param_array(joystick_dac, int, NULL, 0444);
0052 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS MAX driver.");
0053 module_param_array(channels, int, NULL, 0444);
0054 MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver.");
0055 module_param_array(pcm_channels, int, NULL, 0444);
0056 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver.");
0057 
0058 struct snd_gusmax {
0059     int irq;
0060     struct snd_card *card;
0061     struct snd_gus_card *gus;
0062     struct snd_wss *wss;
0063     unsigned short gus_status_reg;
0064     unsigned short pcm_status_reg;
0065 };
0066 
0067 #define PFX "gusmax: "
0068 
0069 static int snd_gusmax_detect(struct snd_gus_card *gus)
0070 {
0071     unsigned char d;
0072 
0073     snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 0);   /* reset GF1 */
0074     d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET);
0075     if ((d & 0x07) != 0) {
0076         snd_printdd("[0x%lx] check 1 failed - 0x%x\n", gus->gf1.port, d);
0077         return -ENODEV;
0078     }
0079     udelay(160);
0080     snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1);   /* release reset */
0081     udelay(160);
0082     d = snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET);
0083     if ((d & 0x07) != 1) {
0084         snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
0085         return -ENODEV;
0086     }
0087 
0088     return 0;
0089 }
0090 
0091 static irqreturn_t snd_gusmax_interrupt(int irq, void *dev_id)
0092 {
0093     struct snd_gusmax *maxcard = dev_id;
0094     int loop, max = 5;
0095     int handled = 0;
0096 
0097     do {
0098         loop = 0;
0099         if (inb(maxcard->gus_status_reg)) {
0100             handled = 1;
0101             snd_gus_interrupt(irq, maxcard->gus);
0102             loop++;
0103         }
0104         if (inb(maxcard->pcm_status_reg) & 0x01) { /* IRQ bit is set? */
0105             handled = 1;
0106             snd_wss_interrupt(irq, maxcard->wss);
0107             loop++;
0108         }
0109     } while (loop && --max > 0);
0110     return IRQ_RETVAL(handled);
0111 }
0112 
0113 static void snd_gusmax_init(int dev, struct snd_card *card,
0114                 struct snd_gus_card *gus)
0115 {
0116     gus->equal_irq = 1;
0117     gus->codec_flag = 1;
0118     gus->joystick_dac = joystick_dac[dev];
0119     /* init control register */
0120     gus->max_cntrl_val = (gus->gf1.port >> 4) & 0x0f;
0121     if (gus->gf1.dma1 > 3)
0122         gus->max_cntrl_val |= 0x10;
0123     if (gus->gf1.dma2 > 3)
0124         gus->max_cntrl_val |= 0x20;
0125     gus->max_cntrl_val |= 0x40;
0126     outb(gus->max_cntrl_val, GUSP(gus, MAXCNTRLPORT));
0127 }
0128 
0129 static int snd_gusmax_mixer(struct snd_wss *chip)
0130 {
0131     struct snd_card *card = chip->card;
0132     struct snd_ctl_elem_id id1, id2;
0133     int err;
0134     
0135     memset(&id1, 0, sizeof(id1));
0136     memset(&id2, 0, sizeof(id2));
0137     id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
0138     /* reassign AUXA to SYNTHESIZER */
0139     strcpy(id1.name, "Aux Playback Switch");
0140     strcpy(id2.name, "Synth Playback Switch");
0141     err = snd_ctl_rename_id(card, &id1, &id2);
0142     if (err < 0)
0143         return err;
0144     strcpy(id1.name, "Aux Playback Volume");
0145     strcpy(id2.name, "Synth Playback Volume");
0146     err = snd_ctl_rename_id(card, &id1, &id2);
0147     if (err < 0)
0148         return err;
0149     /* reassign AUXB to CD */
0150     strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
0151     strcpy(id2.name, "CD Playback Switch");
0152     err = snd_ctl_rename_id(card, &id1, &id2);
0153     if (err < 0)
0154         return err;
0155     strcpy(id1.name, "Aux Playback Volume");
0156     strcpy(id2.name, "CD Playback Volume");
0157     err = snd_ctl_rename_id(card, &id1, &id2);
0158     if (err < 0)
0159         return err;
0160 #if 0
0161     /* reassign Mono Input to MIC */
0162     if (snd_mixer_group_rename(mixer,
0163                 SNDRV_MIXER_IN_MONO, 0,
0164                 SNDRV_MIXER_IN_MIC, 0) < 0)
0165         goto __error;
0166     if (snd_mixer_elem_rename(mixer,
0167                 SNDRV_MIXER_IN_MONO, 0, SNDRV_MIXER_ETYPE_INPUT,
0168                 SNDRV_MIXER_IN_MIC, 0) < 0)
0169         goto __error;
0170     if (snd_mixer_elem_rename(mixer,
0171                 "Mono Capture Volume", 0, SNDRV_MIXER_ETYPE_VOLUME1,
0172                 "Mic Capture Volume", 0) < 0)
0173         goto __error;
0174     if (snd_mixer_elem_rename(mixer,
0175                 "Mono Capture Switch", 0, SNDRV_MIXER_ETYPE_SWITCH1,
0176                 "Mic Capture Switch", 0) < 0)
0177         goto __error;
0178 #endif
0179     return 0;
0180 }
0181 
0182 static int snd_gusmax_match(struct device *pdev, unsigned int dev)
0183 {
0184     return enable[dev];
0185 }
0186 
0187 static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
0188 {
0189     static const int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
0190     static const int possible_dmas[] = {5, 6, 7, 1, 3, -1};
0191     int xirq, xdma1, xdma2, err;
0192     struct snd_card *card;
0193     struct snd_gus_card *gus = NULL;
0194     struct snd_wss *wss;
0195     struct snd_gusmax *maxcard;
0196 
0197     err = snd_devm_card_new(pdev, index[dev], id[dev], THIS_MODULE,
0198                 sizeof(struct snd_gusmax), &card);
0199     if (err < 0)
0200         return err;
0201     maxcard = card->private_data;
0202     maxcard->card = card;
0203     maxcard->irq = -1;
0204     
0205     xirq = irq[dev];
0206     if (xirq == SNDRV_AUTO_IRQ) {
0207         xirq = snd_legacy_find_free_irq(possible_irqs);
0208         if (xirq < 0) {
0209             snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
0210             return -EBUSY;
0211         }
0212     }
0213     xdma1 = dma1[dev];
0214     if (xdma1 == SNDRV_AUTO_DMA) {
0215         xdma1 = snd_legacy_find_free_dma(possible_dmas);
0216         if (xdma1 < 0) {
0217             snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
0218             return -EBUSY;
0219         }
0220     }
0221     xdma2 = dma2[dev];
0222     if (xdma2 == SNDRV_AUTO_DMA) {
0223         xdma2 = snd_legacy_find_free_dma(possible_dmas);
0224         if (xdma2 < 0) {
0225             snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
0226             return -EBUSY;
0227         }
0228     }
0229 
0230     if (port[dev] != SNDRV_AUTO_PORT) {
0231         err = snd_gus_create(card,
0232                      port[dev],
0233                      -xirq, xdma1, xdma2,
0234                      0, channels[dev],
0235                      pcm_channels[dev],
0236                      0, &gus);
0237     } else {
0238         static const unsigned long possible_ports[] = {
0239             0x220, 0x230, 0x240, 0x250, 0x260
0240         };
0241         int i;
0242         for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
0243             err = snd_gus_create(card,
0244                          possible_ports[i],
0245                          -xirq, xdma1, xdma2,
0246                          0, channels[dev],
0247                          pcm_channels[dev],
0248                          0, &gus);
0249             if (err >= 0) {
0250                 port[dev] = possible_ports[i];
0251                 break;
0252             }
0253         }
0254     }
0255     if (err < 0)
0256         return err;
0257 
0258     err = snd_gusmax_detect(gus);
0259     if (err < 0)
0260         return err;
0261 
0262     maxcard->gus_status_reg = gus->gf1.reg_irqstat;
0263     maxcard->pcm_status_reg = gus->gf1.port + 0x10c + 2;
0264     snd_gusmax_init(dev, card, gus);
0265     err = snd_gus_initialize(gus);
0266     if (err < 0)
0267         return err;
0268 
0269     if (!gus->max_flag) {
0270         snd_printk(KERN_ERR PFX "GUS MAX soundcard was not detected at 0x%lx\n", gus->gf1.port);
0271         return -ENODEV;
0272     }
0273 
0274     if (devm_request_irq(card->dev, xirq, snd_gusmax_interrupt, 0,
0275                  "GUS MAX", (void *)maxcard)) {
0276         snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
0277         return -EBUSY;
0278     }
0279     maxcard->irq = xirq;
0280     card->sync_irq = maxcard->irq;
0281 
0282     err = snd_wss_create(card,
0283                  gus->gf1.port + 0x10c, -1, xirq,
0284                  xdma2 < 0 ? xdma1 : xdma2, xdma1,
0285                  WSS_HW_DETECT,
0286                  WSS_HWSHARE_IRQ |
0287                  WSS_HWSHARE_DMA1 |
0288                  WSS_HWSHARE_DMA2,
0289                  &wss);
0290     if (err < 0)
0291         return err;
0292 
0293     err = snd_wss_pcm(wss, 0);
0294     if (err < 0)
0295         return err;
0296 
0297     err = snd_wss_mixer(wss);
0298     if (err < 0)
0299         return err;
0300 
0301     err = snd_wss_timer(wss, 2);
0302     if (err < 0)
0303         return err;
0304 
0305     if (pcm_channels[dev] > 0) {
0306         err = snd_gf1_pcm_new(gus, 1, 1);
0307         if (err < 0)
0308             return err;
0309     }
0310     err = snd_gusmax_mixer(wss);
0311     if (err < 0)
0312         return err;
0313 
0314     err = snd_gf1_rawmidi_new(gus, 0);
0315     if (err < 0)
0316         return err;
0317 
0318     sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %i, dma %i", gus->gf1.port, xirq, xdma1);
0319     if (xdma2 >= 0)
0320         sprintf(card->longname + strlen(card->longname), "&%i", xdma2);
0321 
0322     err = snd_card_register(card);
0323     if (err < 0)
0324         return err;
0325         
0326     maxcard->gus = gus;
0327     maxcard->wss = wss;
0328 
0329     dev_set_drvdata(pdev, card);
0330     return 0;
0331 }
0332 
0333 #define DEV_NAME "gusmax"
0334 
0335 static struct isa_driver snd_gusmax_driver = {
0336     .match      = snd_gusmax_match,
0337     .probe      = snd_gusmax_probe,
0338     /* FIXME: suspend/resume */
0339     .driver     = {
0340         .name   = DEV_NAME
0341     },
0342 };
0343 
0344 module_isa_driver(snd_gusmax_driver, SNDRV_CARDS);