Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 
0003 /*
0004     card-als100.c - driver for Avance Logic ALS100 based soundcards.
0005     Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it>
0006     Copyright (C) 1999-2002 by Massimo Piccioni <dafastidio@libero.it>
0007 
0008     Thanks to Pierfrancesco 'qM2' Passerini.
0009 
0010     Generalised for soundcards based on DT-0196 and ALS-007 chips
0011     by Jonathan Woithe <jwoithe@just42.net>: June 2002.
0012 
0013 */
0014 
0015 #include <linux/init.h>
0016 #include <linux/wait.h>
0017 #include <linux/time.h>
0018 #include <linux/pnp.h>
0019 #include <linux/module.h>
0020 #include <sound/core.h>
0021 #include <sound/initval.h>
0022 #include <sound/mpu401.h>
0023 #include <sound/opl3.h>
0024 #include <sound/sb.h>
0025 
0026 #define PFX "als100: "
0027 
0028 MODULE_DESCRIPTION("Avance Logic ALS007/ALS1X0");
0029 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
0030 MODULE_LICENSE("GPL");
0031 
0032 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;  /* Index 0-MAX */
0033 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;   /* ID for this card */
0034 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
0035 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
0036 static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
0037 static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;  /* PnP setup */
0038 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;    /* PnP setup */
0039 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;    /* PnP setup */
0040 static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;   /* PnP setup */
0041 static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;  /* PnP setup */
0042 
0043 module_param_array(index, int, NULL, 0444);
0044 MODULE_PARM_DESC(index, "Index value for Avance Logic based soundcard.");
0045 module_param_array(id, charp, NULL, 0444);
0046 MODULE_PARM_DESC(id, "ID string for Avance Logic based soundcard.");
0047 module_param_array(enable, bool, NULL, 0444);
0048 MODULE_PARM_DESC(enable, "Enable Avance Logic based soundcard.");
0049 
0050 MODULE_ALIAS("snd-dt019x");
0051 
0052 struct snd_card_als100 {
0053     struct pnp_dev *dev;
0054     struct pnp_dev *devmpu;
0055     struct pnp_dev *devopl;
0056     struct snd_sb *chip;
0057 };
0058 
0059 static const struct pnp_card_device_id snd_als100_pnpids[] = {
0060     /* DT197A30 */
0061     { .id = "RWB1688",
0062       .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } },
0063       .driver_data = SB_HW_DT019X },
0064     /* DT0196 / ALS-007 */
0065     { .id = "ALS0007",
0066       .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } },
0067       .driver_data = SB_HW_DT019X },
0068     /* ALS100 - PRO16PNP */
0069     { .id = "ALS0001",
0070       .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } },
0071       .driver_data = SB_HW_ALS100 },
0072     /* ALS110 - MF1000 - Digimate 3D Sound */
0073     { .id = "ALS0110",
0074       .devs = { { "@@@1001" }, { "@X@1001" }, { "@H@1001" } },
0075       .driver_data = SB_HW_ALS100 },
0076     /* ALS120 */
0077     { .id = "ALS0120",
0078       .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } },
0079       .driver_data = SB_HW_ALS100 },
0080     /* ALS200 */
0081     { .id = "ALS0200",
0082       .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" } },
0083       .driver_data = SB_HW_ALS100 },
0084     /* ALS200 OEM */
0085     { .id = "ALS0200",
0086       .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0020" } },
0087       .driver_data = SB_HW_ALS100 },
0088     /* RTL3000 */
0089     { .id = "RTL3000",
0090       .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } },
0091       .driver_data = SB_HW_ALS100 },
0092     { .id = "" } /* end */
0093 };
0094 
0095 MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids);
0096 
0097 static int snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
0098                    struct pnp_card_link *card,
0099                    const struct pnp_card_device_id *id)
0100 {
0101     struct pnp_dev *pdev;
0102     int err;
0103 
0104     acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
0105     if (acard->dev == NULL)
0106         return -ENODEV;
0107 
0108     acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev);
0109     acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->dev);
0110 
0111     pdev = acard->dev;
0112 
0113     err = pnp_activate_dev(pdev);
0114     if (err < 0) {
0115         snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
0116         return err;
0117     }
0118     port[dev] = pnp_port_start(pdev, 0);
0119     if (id->driver_data == SB_HW_DT019X)
0120         dma8[dev] = pnp_dma(pdev, 0);
0121     else {
0122         dma8[dev] = pnp_dma(pdev, 1);
0123         dma16[dev] = pnp_dma(pdev, 0);
0124     }
0125     irq[dev] = pnp_irq(pdev, 0);
0126 
0127     pdev = acard->devmpu;
0128     if (pdev != NULL) {
0129         err = pnp_activate_dev(pdev);
0130         if (err < 0)
0131             goto __mpu_error;
0132         mpu_port[dev] = pnp_port_start(pdev, 0);
0133         mpu_irq[dev] = pnp_irq(pdev, 0);
0134     } else {
0135          __mpu_error:
0136             if (pdev) {
0137                 pnp_release_card_device(pdev);
0138                 snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n");
0139             }
0140             acard->devmpu = NULL;
0141             mpu_port[dev] = -1;
0142     }
0143 
0144     pdev = acard->devopl;
0145     if (pdev != NULL) {
0146         err = pnp_activate_dev(pdev);
0147         if (err < 0)
0148             goto __fm_error;
0149         fm_port[dev] = pnp_port_start(pdev, 0);
0150     } else {
0151           __fm_error:
0152             if (pdev) {
0153                 pnp_release_card_device(pdev);
0154                 snd_printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n");
0155             }
0156             acard->devopl = NULL;
0157             fm_port[dev] = -1;
0158     }
0159 
0160     return 0;
0161 }
0162 
0163 static int snd_card_als100_probe(int dev,
0164                  struct pnp_card_link *pcard,
0165                  const struct pnp_card_device_id *pid)
0166 {
0167     int error;
0168     struct snd_sb *chip;
0169     struct snd_card *card;
0170     struct snd_card_als100 *acard;
0171     struct snd_opl3 *opl3;
0172 
0173     error = snd_devm_card_new(&pcard->card->dev,
0174                   index[dev], id[dev], THIS_MODULE,
0175                   sizeof(struct snd_card_als100), &card);
0176     if (error < 0)
0177         return error;
0178     acard = card->private_data;
0179 
0180     error = snd_card_als100_pnp(dev, acard, pcard, pid);
0181     if (error)
0182         return error;
0183 
0184     if (pid->driver_data == SB_HW_DT019X)
0185         dma16[dev] = -1;
0186 
0187     error = snd_sbdsp_create(card, port[dev], irq[dev],
0188                   snd_sb16dsp_interrupt,
0189                   dma8[dev], dma16[dev],
0190                   pid->driver_data,
0191                   &chip);
0192     if (error < 0)
0193         return error;
0194     acard->chip = chip;
0195 
0196     if (pid->driver_data == SB_HW_DT019X) {
0197         strcpy(card->driver, "DT-019X");
0198         strcpy(card->shortname, "Diamond Tech. DT-019X");
0199         snprintf(card->longname, sizeof(card->longname),
0200              "Diamond Tech. DT-019X, %s at 0x%lx, irq %d, dma %d",
0201              chip->name, chip->port, irq[dev], dma8[dev]);
0202     } else {
0203         strcpy(card->driver, "ALS100");
0204         strcpy(card->shortname, "Avance Logic ALS100");
0205         snprintf(card->longname, sizeof(card->longname),
0206              "Avance Logic ALS100, %s at 0x%lx, irq %d, dma %d&%d",
0207              chip->name, chip->port, irq[dev], dma8[dev],
0208              dma16[dev]);
0209     }
0210 
0211     error = snd_sb16dsp_pcm(chip, 0);
0212     if (error < 0)
0213         return error;
0214 
0215     error = snd_sbmixer_new(chip);
0216     if (error < 0)
0217         return error;
0218 
0219     if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
0220         int mpu_type = MPU401_HW_ALS100;
0221 
0222         if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
0223             mpu_irq[dev] = -1;
0224 
0225         if (pid->driver_data == SB_HW_DT019X)
0226             mpu_type = MPU401_HW_MPU401;
0227 
0228         if (snd_mpu401_uart_new(card, 0,
0229                     mpu_type,
0230                     mpu_port[dev], 0, 
0231                     mpu_irq[dev],
0232                     NULL) < 0)
0233             snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
0234     }
0235 
0236     if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
0237         if (snd_opl3_create(card,
0238                     fm_port[dev], fm_port[dev] + 2,
0239                     OPL3_HW_AUTO, 0, &opl3) < 0) {
0240             snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
0241                    fm_port[dev], fm_port[dev] + 2);
0242         } else {
0243             error = snd_opl3_timer_new(opl3, 0, 1);
0244             if (error < 0)
0245                 return error;
0246             error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
0247             if (error < 0)
0248                 return error;
0249         }
0250     }
0251 
0252     error = snd_card_register(card);
0253     if (error < 0)
0254         return error;
0255     pnp_set_card_drvdata(pcard, card);
0256     return 0;
0257 }
0258 
0259 static unsigned int als100_devices;
0260 
0261 static int snd_als100_pnp_detect(struct pnp_card_link *card,
0262                  const struct pnp_card_device_id *id)
0263 {
0264     static int dev;
0265     int res;
0266 
0267     for ( ; dev < SNDRV_CARDS; dev++) {
0268         if (!enable[dev])
0269             continue;
0270         res = snd_card_als100_probe(dev, card, id);
0271         if (res < 0)
0272             return res;
0273         dev++;
0274         als100_devices++;
0275         return 0;
0276     }
0277     return -ENODEV;
0278 }
0279 
0280 #ifdef CONFIG_PM
0281 static int snd_als100_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
0282 {
0283     struct snd_card *card = pnp_get_card_drvdata(pcard);
0284     struct snd_card_als100 *acard = card->private_data;
0285     struct snd_sb *chip = acard->chip;
0286 
0287     snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
0288     snd_sbmixer_suspend(chip);
0289     return 0;
0290 }
0291 
0292 static int snd_als100_pnp_resume(struct pnp_card_link *pcard)
0293 {
0294     struct snd_card *card = pnp_get_card_drvdata(pcard);
0295     struct snd_card_als100 *acard = card->private_data;
0296     struct snd_sb *chip = acard->chip;
0297 
0298     snd_sbdsp_reset(chip);
0299     snd_sbmixer_resume(chip);
0300     snd_power_change_state(card, SNDRV_CTL_POWER_D0);
0301     return 0;
0302 }
0303 #endif
0304 
0305 static struct pnp_card_driver als100_pnpc_driver = {
0306     .flags          = PNP_DRIVER_RES_DISABLE,
0307     .name       = "als100",
0308         .id_table       = snd_als100_pnpids,
0309         .probe          = snd_als100_pnp_detect,
0310 #ifdef CONFIG_PM
0311     .suspend    = snd_als100_pnp_suspend,
0312     .resume     = snd_als100_pnp_resume,
0313 #endif
0314 };
0315 
0316 static int __init alsa_card_als100_init(void)
0317 {
0318     int err;
0319 
0320     err = pnp_register_card_driver(&als100_pnpc_driver);
0321     if (err)
0322         return err;
0323 
0324     if (!als100_devices) {
0325         pnp_unregister_card_driver(&als100_pnpc_driver);
0326 #ifdef MODULE
0327         snd_printk(KERN_ERR "no Avance Logic based soundcards found\n");
0328 #endif
0329         return -ENODEV;
0330     }
0331     return 0;
0332 }
0333 
0334 static void __exit alsa_card_als100_exit(void)
0335 {
0336     pnp_unregister_card_driver(&als100_pnpc_driver);
0337 }
0338 
0339 module_init(alsa_card_als100_init)
0340 module_exit(alsa_card_als100_exit)