Back to home page

OSCL-LXR

 
 

    


0001 
0002 /*
0003  * jazz16.c - driver for Media Vision Jazz16 based soundcards.
0004  * Copyright (C) 2009 Krzysztof Helt <krzysztof.h1@wp.pl>
0005  * Based on patches posted by Rask Ingemann Lambertsen and Rene Herman.
0006  * Based on OSS Sound Blaster driver.
0007  *
0008  * This file is subject to the terms and conditions of the GNU General Public
0009  * License.  See the file COPYING in the main directory of this archive for
0010  * more details.
0011  *
0012  */
0013 
0014 #include <linux/init.h>
0015 #include <linux/module.h>
0016 #include <linux/io.h>
0017 #include <linux/delay.h>
0018 #include <asm/dma.h>
0019 #include <linux/isa.h>
0020 #include <sound/core.h>
0021 #include <sound/mpu401.h>
0022 #include <sound/opl3.h>
0023 #include <sound/sb.h>
0024 #define SNDRV_LEGACY_FIND_FREE_IRQ
0025 #define SNDRV_LEGACY_FIND_FREE_DMA
0026 #include <sound/initval.h>
0027 
0028 #define PFX "jazz16: "
0029 
0030 MODULE_DESCRIPTION("Media Vision Jazz16");
0031 MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>");
0032 MODULE_LICENSE("GPL");
0033 
0034 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;  /* Index 0-MAX */
0035 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;   /* ID for this card */
0036 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
0037 static unsigned long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0038 static unsigned long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0039 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
0040 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
0041 static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
0042 static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
0043 
0044 module_param_array(index, int, NULL, 0444);
0045 MODULE_PARM_DESC(index, "Index value for Media Vision Jazz16 based soundcard.");
0046 module_param_array(id, charp, NULL, 0444);
0047 MODULE_PARM_DESC(id, "ID string for Media Vision Jazz16 based soundcard.");
0048 module_param_array(enable, bool, NULL, 0444);
0049 MODULE_PARM_DESC(enable, "Enable Media Vision Jazz16 based soundcard.");
0050 module_param_hw_array(port, long, ioport, NULL, 0444);
0051 MODULE_PARM_DESC(port, "Port # for jazz16 driver.");
0052 module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
0053 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for jazz16 driver.");
0054 module_param_hw_array(irq, int, irq, NULL, 0444);
0055 MODULE_PARM_DESC(irq, "IRQ # for jazz16 driver.");
0056 module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
0057 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for jazz16 driver.");
0058 module_param_hw_array(dma8, int, dma, NULL, 0444);
0059 MODULE_PARM_DESC(dma8, "DMA8 # for jazz16 driver.");
0060 module_param_hw_array(dma16, int, dma, NULL, 0444);
0061 MODULE_PARM_DESC(dma16, "DMA16 # for jazz16 driver.");
0062 
0063 #define SB_JAZZ16_WAKEUP    0xaf
0064 #define SB_JAZZ16_SET_PORTS 0x50
0065 #define SB_DSP_GET_JAZZ_BRD_REV 0xfa
0066 #define SB_JAZZ16_SET_DMAINTR   0xfb
0067 #define SB_DSP_GET_JAZZ_MODEL   0xfe
0068 
0069 struct snd_card_jazz16 {
0070     struct snd_sb *chip;
0071 };
0072 
0073 static irqreturn_t jazz16_interrupt(int irq, void *chip)
0074 {
0075     return snd_sb8dsp_interrupt(chip);
0076 }
0077 
0078 static int jazz16_configure_ports(unsigned long port,
0079                   unsigned long mpu_port, int idx)
0080 {
0081     unsigned char val;
0082 
0083     if (!request_region(0x201, 1, "jazz16 config")) {
0084         snd_printk(KERN_ERR "config port region is already in use.\n");
0085         return -EBUSY;
0086     }
0087     outb(SB_JAZZ16_WAKEUP - idx, 0x201);
0088     udelay(100);
0089     outb(SB_JAZZ16_SET_PORTS + idx, 0x201);
0090     udelay(100);
0091     val = port & 0x70;
0092     val |= (mpu_port & 0x30) >> 4;
0093     outb(val, 0x201);
0094 
0095     release_region(0x201, 1);
0096     return 0;
0097 }
0098 
0099 static int jazz16_detect_board(unsigned long port,
0100                    unsigned long mpu_port)
0101 {
0102     int err;
0103     int val;
0104     struct snd_sb chip;
0105 
0106     if (!request_region(port, 0x10, "jazz16")) {
0107         snd_printk(KERN_ERR "I/O port region is already in use.\n");
0108         return -EBUSY;
0109     }
0110     /* just to call snd_sbdsp_command/reset/get_byte() */
0111     chip.port = port;
0112 
0113     err = snd_sbdsp_reset(&chip);
0114     if (err < 0)
0115         for (val = 0; val < 4; val++) {
0116             err = jazz16_configure_ports(port, mpu_port, val);
0117             if (err < 0)
0118                 break;
0119 
0120             err = snd_sbdsp_reset(&chip);
0121             if (!err)
0122                 break;
0123         }
0124     if (err < 0) {
0125         err = -ENODEV;
0126         goto err_unmap;
0127     }
0128     if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_BRD_REV)) {
0129         err = -EBUSY;
0130         goto err_unmap;
0131     }
0132     val = snd_sbdsp_get_byte(&chip);
0133     if (val >= 0x30)
0134         snd_sbdsp_get_byte(&chip);
0135 
0136     if ((val & 0xf0) != 0x10) {
0137         err = -ENODEV;
0138         goto err_unmap;
0139     }
0140     if (!snd_sbdsp_command(&chip, SB_DSP_GET_JAZZ_MODEL)) {
0141         err = -EBUSY;
0142         goto err_unmap;
0143     }
0144     snd_sbdsp_get_byte(&chip);
0145     err = snd_sbdsp_get_byte(&chip);
0146     snd_printd("Media Vision Jazz16 board detected: rev 0x%x, model 0x%x\n",
0147            val, err);
0148 
0149     err = 0;
0150 
0151 err_unmap:
0152     release_region(port, 0x10);
0153     return err;
0154 }
0155 
0156 static int jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
0157 {
0158     static const unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4,
0159                          0, 2, 5, 0, 0, 0, 0, 6 };
0160     static const unsigned char jazz_dma_bits[] = { 0, 1, 0, 2, 0, 3, 0, 4 };
0161 
0162     if (jazz_dma_bits[chip->dma8] == 0 ||
0163         jazz_dma_bits[chip->dma16] == 0 ||
0164         jazz_irq_bits[chip->irq] == 0)
0165         return -EINVAL;
0166 
0167     if (!snd_sbdsp_command(chip, SB_JAZZ16_SET_DMAINTR))
0168         return -EBUSY;
0169 
0170     if (!snd_sbdsp_command(chip,
0171                    jazz_dma_bits[chip->dma8] |
0172                    (jazz_dma_bits[chip->dma16] << 4)))
0173         return -EBUSY;
0174 
0175     if (!snd_sbdsp_command(chip,
0176                    jazz_irq_bits[chip->irq] |
0177                    (jazz_irq_bits[mpu_irq] << 4)))
0178         return -EBUSY;
0179 
0180     return 0;
0181 }
0182 
0183 static int snd_jazz16_match(struct device *devptr, unsigned int dev)
0184 {
0185     if (!enable[dev])
0186         return 0;
0187     if (port[dev] == SNDRV_AUTO_PORT) {
0188         snd_printk(KERN_ERR "please specify port\n");
0189         return 0;
0190     } else if (port[dev] == 0x200 || (port[dev] & ~0x270)) {
0191         snd_printk(KERN_ERR "incorrect port specified\n");
0192         return 0;
0193     }
0194     if (dma8[dev] != SNDRV_AUTO_DMA &&
0195         dma8[dev] != 1 && dma8[dev] != 3) {
0196         snd_printk(KERN_ERR "dma8 must be 1 or 3\n");
0197         return 0;
0198     }
0199     if (dma16[dev] != SNDRV_AUTO_DMA &&
0200         dma16[dev] != 5 && dma16[dev] != 7) {
0201         snd_printk(KERN_ERR "dma16 must be 5 or 7\n");
0202         return 0;
0203     }
0204     if (mpu_port[dev] != SNDRV_AUTO_PORT &&
0205         (mpu_port[dev] & ~0x030) != 0x300) {
0206         snd_printk(KERN_ERR "incorrect mpu_port specified\n");
0207         return 0;
0208     }
0209     if (mpu_irq[dev] != SNDRV_AUTO_DMA &&
0210         mpu_irq[dev] != 2 && mpu_irq[dev] != 3 &&
0211         mpu_irq[dev] != 5 && mpu_irq[dev] != 7) {
0212         snd_printk(KERN_ERR "mpu_irq must be 2, 3, 5 or 7\n");
0213         return 0;
0214     }
0215     return 1;
0216 }
0217 
0218 static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
0219 {
0220     struct snd_card *card;
0221     struct snd_card_jazz16 *jazz16;
0222     struct snd_sb *chip;
0223     struct snd_opl3 *opl3;
0224     static const int possible_irqs[] = {2, 3, 5, 7, 9, 10, 15, -1};
0225     static const int possible_dmas8[] = {1, 3, -1};
0226     static const int possible_dmas16[] = {5, 7, -1};
0227     int err, xirq, xdma8, xdma16, xmpu_port, xmpu_irq;
0228 
0229     err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
0230                 sizeof(struct snd_card_jazz16), &card);
0231     if (err < 0)
0232         return err;
0233 
0234     jazz16 = card->private_data;
0235 
0236     xirq = irq[dev];
0237     if (xirq == SNDRV_AUTO_IRQ) {
0238         xirq = snd_legacy_find_free_irq(possible_irqs);
0239         if (xirq < 0) {
0240             snd_printk(KERN_ERR "unable to find a free IRQ\n");
0241             return -EBUSY;
0242         }
0243     }
0244     xdma8 = dma8[dev];
0245     if (xdma8 == SNDRV_AUTO_DMA) {
0246         xdma8 = snd_legacy_find_free_dma(possible_dmas8);
0247         if (xdma8 < 0) {
0248             snd_printk(KERN_ERR "unable to find a free DMA8\n");
0249             return -EBUSY;
0250         }
0251     }
0252     xdma16 = dma16[dev];
0253     if (xdma16 == SNDRV_AUTO_DMA) {
0254         xdma16 = snd_legacy_find_free_dma(possible_dmas16);
0255         if (xdma16 < 0) {
0256             snd_printk(KERN_ERR "unable to find a free DMA16\n");
0257             return -EBUSY;
0258         }
0259     }
0260 
0261     xmpu_port = mpu_port[dev];
0262     if (xmpu_port == SNDRV_AUTO_PORT)
0263         xmpu_port = 0;
0264     err = jazz16_detect_board(port[dev], xmpu_port);
0265     if (err < 0) {
0266         printk(KERN_ERR "Media Vision Jazz16 board not detected\n");
0267         return err;
0268     }
0269     err = snd_sbdsp_create(card, port[dev], irq[dev],
0270                    jazz16_interrupt,
0271                    dma8[dev], dma16[dev],
0272                    SB_HW_JAZZ16,
0273                    &chip);
0274     if (err < 0)
0275         return err;
0276 
0277     xmpu_irq = mpu_irq[dev];
0278     if (xmpu_irq == SNDRV_AUTO_IRQ || mpu_port[dev] == SNDRV_AUTO_PORT)
0279         xmpu_irq = 0;
0280     err = jazz16_configure_board(chip, xmpu_irq);
0281     if (err < 0) {
0282         printk(KERN_ERR "Media Vision Jazz16 configuration failed\n");
0283         return err;
0284     }
0285 
0286     jazz16->chip = chip;
0287 
0288     strcpy(card->driver, "jazz16");
0289     strcpy(card->shortname, "Media Vision Jazz16");
0290     sprintf(card->longname,
0291         "Media Vision Jazz16 at 0x%lx, irq %d, dma8 %d, dma16 %d",
0292         port[dev], xirq, xdma8, xdma16);
0293 
0294     err = snd_sb8dsp_pcm(chip, 0);
0295     if (err < 0)
0296         return err;
0297     err = snd_sbmixer_new(chip);
0298     if (err < 0)
0299         return err;
0300 
0301     err = snd_opl3_create(card, chip->port, chip->port + 2,
0302                   OPL3_HW_AUTO, 1, &opl3);
0303     if (err < 0)
0304         snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n",
0305                chip->port, chip->port + 2);
0306     else {
0307         err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
0308         if (err < 0)
0309             return err;
0310     }
0311     if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
0312         if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
0313             mpu_irq[dev] = -1;
0314 
0315         if (snd_mpu401_uart_new(card, 0,
0316                     MPU401_HW_MPU401,
0317                     mpu_port[dev], 0,
0318                     mpu_irq[dev],
0319                     NULL) < 0)
0320             snd_printk(KERN_ERR "no MPU-401 device at 0x%lx\n",
0321                     mpu_port[dev]);
0322     }
0323 
0324     err = snd_card_register(card);
0325     if (err < 0)
0326         return err;
0327 
0328     dev_set_drvdata(devptr, card);
0329     return 0;
0330 }
0331 
0332 #ifdef CONFIG_PM
0333 static int snd_jazz16_suspend(struct device *pdev, unsigned int n,
0334                    pm_message_t state)
0335 {
0336     struct snd_card *card = dev_get_drvdata(pdev);
0337     struct snd_card_jazz16 *acard = card->private_data;
0338     struct snd_sb *chip = acard->chip;
0339 
0340     snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
0341     snd_sbmixer_suspend(chip);
0342     return 0;
0343 }
0344 
0345 static int snd_jazz16_resume(struct device *pdev, unsigned int n)
0346 {
0347     struct snd_card *card = dev_get_drvdata(pdev);
0348     struct snd_card_jazz16 *acard = card->private_data;
0349     struct snd_sb *chip = acard->chip;
0350 
0351     snd_sbdsp_reset(chip);
0352     snd_sbmixer_resume(chip);
0353     snd_power_change_state(card, SNDRV_CTL_POWER_D0);
0354     return 0;
0355 }
0356 #endif
0357 
0358 static struct isa_driver snd_jazz16_driver = {
0359     .match      = snd_jazz16_match,
0360     .probe      = snd_jazz16_probe,
0361 #ifdef CONFIG_PM
0362     .suspend    = snd_jazz16_suspend,
0363     .resume     = snd_jazz16_resume,
0364 #endif
0365     .driver     = {
0366         .name   = "jazz16"
0367     },
0368 };
0369 
0370 module_isa_driver(snd_jazz16_driver, SNDRV_CARDS);