root/sound/isa/es1688/es1688.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_es1688_match
  2. snd_es1688_legacy_create
  3. snd_es1688_probe
  4. snd_es1688_isa_probe
  5. snd_es1688_isa_remove
  6. snd_card_es968_pnp
  7. snd_es968_pnp_detect
  8. snd_es968_pnp_remove
  9. snd_es968_pnp_suspend
  10. snd_es968_pnp_resume
  11. alsa_card_es1688_init
  12. alsa_card_es1688_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  Driver for generic ESS AudioDrive ESx688 soundcards
   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/isapnp.h>
  11 #include <linux/time.h>
  12 #include <linux/wait.h>
  13 #include <linux/module.h>
  14 #include <asm/dma.h>
  15 #include <sound/core.h>
  16 #include <sound/es1688.h>
  17 #include <sound/mpu401.h>
  18 #include <sound/opl3.h>
  19 #define SNDRV_LEGACY_FIND_FREE_IRQ
  20 #define SNDRV_LEGACY_FIND_FREE_DMA
  21 #include <sound/initval.h>
  22 
  23 #define CRD_NAME "Generic ESS ES1688/ES688 AudioDrive"
  24 #define DEV_NAME "es1688"
  25 
  26 MODULE_DESCRIPTION(CRD_NAME);
  27 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
  28 MODULE_LICENSE("GPL");
  29 MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100},"
  30                 "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102},"
  31                 "{ESS,ES688 AudioDrive,pnp:ESS6881},"
  32                 "{ESS,ES1688 AudioDrive,pnp:ESS1681}}");
  33 
  34 MODULE_ALIAS("snd_es968");
  35 
  36 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;      /* Index 0-MAX */
  37 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* ID for this card */
  38 #ifdef CONFIG_PNP
  39 static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
  40 #endif
  41 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
  42 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;     /* 0x220,0x240,0x260 */
  43 static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;  /* Usually 0x388 */
  44 static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1};
  45 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;        /* 5,7,9,10 */
  46 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;    /* 5,7,9,10 */
  47 static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;       /* 0,1,3 */
  48 
  49 module_param_array(index, int, NULL, 0444);
  50 MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
  51 module_param_array(id, charp, NULL, 0444);
  52 MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
  53 module_param_array(enable, bool, NULL, 0444);
  54 #ifdef CONFIG_PNP
  55 module_param_array(isapnp, bool, NULL, 0444);
  56 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
  57 #endif
  58 MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
  59 module_param_hw_array(port, long, ioport, NULL, 0444);
  60 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
  61 module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
  62 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
  63 module_param_hw_array(irq, int, irq, NULL, 0444);
  64 module_param_hw_array(fm_port, long, ioport, NULL, 0444);
  65 MODULE_PARM_DESC(fm_port, "FM port # for ES1688 driver.");
  66 MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
  67 module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
  68 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
  69 module_param_hw_array(dma8, int, dma, NULL, 0444);
  70 MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
  71 
  72 #ifdef CONFIG_PNP
  73 #define is_isapnp_selected(dev)         isapnp[dev]
  74 #else
  75 #define is_isapnp_selected(dev)         0
  76 #endif
  77 
  78 static int snd_es1688_match(struct device *dev, unsigned int n)
  79 {
  80         return enable[n] && !is_isapnp_selected(n);
  81 }
  82 
  83 static int snd_es1688_legacy_create(struct snd_card *card,
  84                                     struct device *dev, unsigned int n)
  85 {
  86         struct snd_es1688 *chip = card->private_data;
  87         static long possible_ports[] = {0x220, 0x240, 0x260};
  88         static int possible_irqs[] = {5, 9, 10, 7, -1};
  89         static int possible_dmas[] = {1, 3, 0, -1};
  90 
  91         int i, error;
  92 
  93         if (irq[n] == SNDRV_AUTO_IRQ) {
  94                 irq[n] = snd_legacy_find_free_irq(possible_irqs);
  95                 if (irq[n] < 0) {
  96                         dev_err(dev, "unable to find a free IRQ\n");
  97                         return -EBUSY;
  98                 }
  99         }
 100         if (dma8[n] == SNDRV_AUTO_DMA) {
 101                 dma8[n] = snd_legacy_find_free_dma(possible_dmas);
 102                 if (dma8[n] < 0) {
 103                         dev_err(dev, "unable to find a free DMA\n");
 104                         return -EBUSY;
 105                 }
 106         }
 107 
 108         if (port[n] != SNDRV_AUTO_PORT)
 109                 return snd_es1688_create(card, chip, port[n], mpu_port[n],
 110                                 irq[n], mpu_irq[n], dma8[n], ES1688_HW_AUTO);
 111 
 112         i = 0;
 113         do {
 114                 port[n] = possible_ports[i];
 115                 error = snd_es1688_create(card, chip, port[n], mpu_port[n],
 116                                 irq[n], mpu_irq[n], dma8[n], ES1688_HW_AUTO);
 117         } while (error < 0 && ++i < ARRAY_SIZE(possible_ports));
 118 
 119         return error;
 120 }
 121 
 122 static int snd_es1688_probe(struct snd_card *card, unsigned int n)
 123 {
 124         struct snd_es1688 *chip = card->private_data;
 125         struct snd_opl3 *opl3;
 126         int error;
 127 
 128         error = snd_es1688_pcm(card, chip, 0);
 129         if (error < 0)
 130                 return error;
 131 
 132         error = snd_es1688_mixer(card, chip);
 133         if (error < 0)
 134                 return error;
 135 
 136         strlcpy(card->driver, "ES1688", sizeof(card->driver));
 137         strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
 138         snprintf(card->longname, sizeof(card->longname),
 139                 "%s at 0x%lx, irq %i, dma %i", chip->pcm->name, chip->port,
 140                  chip->irq, chip->dma8);
 141 
 142         if (fm_port[n] == SNDRV_AUTO_PORT)
 143                 fm_port[n] = port[n];   /* share the same port */
 144 
 145         if (fm_port[n] > 0) {
 146                 if (snd_opl3_create(card, fm_port[n], fm_port[n] + 2,
 147                                 OPL3_HW_OPL3, 0, &opl3) < 0)
 148                         dev_warn(card->dev,
 149                                  "opl3 not detected at 0x%lx\n", fm_port[n]);
 150                 else {
 151                         error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
 152                         if (error < 0)
 153                                 return error;
 154                 }
 155         }
 156 
 157         if (mpu_irq[n] >= 0 && mpu_irq[n] != SNDRV_AUTO_IRQ &&
 158                         chip->mpu_port > 0) {
 159                 error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
 160                                 chip->mpu_port, 0,
 161                                 mpu_irq[n], NULL);
 162                 if (error < 0)
 163                         return error;
 164         }
 165 
 166         return snd_card_register(card);
 167 }
 168 
 169 static int snd_es1688_isa_probe(struct device *dev, unsigned int n)
 170 {
 171         struct snd_card *card;
 172         int error;
 173 
 174         error = snd_card_new(dev, index[n], id[n], THIS_MODULE,
 175                              sizeof(struct snd_es1688), &card);
 176         if (error < 0)
 177                 return error;
 178 
 179         error = snd_es1688_legacy_create(card, dev, n);
 180         if (error < 0)
 181                 goto out;
 182 
 183         error = snd_es1688_probe(card, n);
 184         if (error < 0)
 185                 goto out;
 186 
 187         dev_set_drvdata(dev, card);
 188 
 189         return 0;
 190 out:
 191         snd_card_free(card);
 192         return error;
 193 }
 194 
 195 static int snd_es1688_isa_remove(struct device *dev, unsigned int n)
 196 {
 197         snd_card_free(dev_get_drvdata(dev));
 198         return 0;
 199 }
 200 
 201 static struct isa_driver snd_es1688_driver = {
 202         .match          = snd_es1688_match,
 203         .probe          = snd_es1688_isa_probe,
 204         .remove         = snd_es1688_isa_remove,
 205 #if 0   /* FIXME */
 206         .suspend        = snd_es1688_suspend,
 207         .resume         = snd_es1688_resume,
 208 #endif
 209         .driver         = {
 210                 .name   = DEV_NAME
 211         }
 212 };
 213 
 214 static int snd_es968_pnp_is_probed;
 215 
 216 #ifdef CONFIG_PNP
 217 static int snd_card_es968_pnp(struct snd_card *card, unsigned int n,
 218                               struct pnp_card_link *pcard,
 219                               const struct pnp_card_device_id *pid)
 220 {
 221         struct snd_es1688 *chip = card->private_data;
 222         struct pnp_dev *pdev;
 223         int error;
 224 
 225         pdev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
 226         if (pdev == NULL)
 227                 return -ENODEV;
 228 
 229         error = pnp_activate_dev(pdev);
 230         if (error < 0) {
 231                 snd_printk(KERN_ERR "ES968 pnp configure failure\n");
 232                 return error;
 233         }
 234         port[n] = pnp_port_start(pdev, 0);
 235         dma8[n] = pnp_dma(pdev, 0);
 236         irq[n] = pnp_irq(pdev, 0);
 237 
 238         return snd_es1688_create(card, chip, port[n], mpu_port[n], irq[n],
 239                                  mpu_irq[n], dma8[n], ES1688_HW_AUTO);
 240 }
 241 
 242 static int snd_es968_pnp_detect(struct pnp_card_link *pcard,
 243                                 const struct pnp_card_device_id *pid)
 244 {
 245         struct snd_card *card;
 246         static unsigned int dev;
 247         int error;
 248 
 249         if (snd_es968_pnp_is_probed)
 250                 return -EBUSY;
 251         for ( ; dev < SNDRV_CARDS; dev++) {
 252                 if (enable[dev] && isapnp[dev])
 253                         break;
 254         }
 255         if (dev == SNDRV_CARDS)
 256                 return -ENODEV;
 257 
 258         error = snd_card_new(&pcard->card->dev,
 259                              index[dev], id[dev], THIS_MODULE,
 260                              sizeof(struct snd_es1688), &card);
 261         if (error < 0)
 262                 return error;
 263 
 264         error = snd_card_es968_pnp(card, dev, pcard, pid);
 265         if (error < 0) {
 266                 snd_card_free(card);
 267                 return error;
 268         }
 269         error = snd_es1688_probe(card, dev);
 270         if (error < 0) {
 271                 snd_card_free(card);
 272                 return error;
 273         }
 274         pnp_set_card_drvdata(pcard, card);
 275         snd_es968_pnp_is_probed = 1;
 276         return 0;
 277 }
 278 
 279 static void snd_es968_pnp_remove(struct pnp_card_link *pcard)
 280 {
 281         snd_card_free(pnp_get_card_drvdata(pcard));
 282         pnp_set_card_drvdata(pcard, NULL);
 283         snd_es968_pnp_is_probed = 0;
 284 }
 285 
 286 #ifdef CONFIG_PM
 287 static int snd_es968_pnp_suspend(struct pnp_card_link *pcard,
 288                                  pm_message_t state)
 289 {
 290         struct snd_card *card = pnp_get_card_drvdata(pcard);
 291 
 292         snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 293         return 0;
 294 }
 295 
 296 static int snd_es968_pnp_resume(struct pnp_card_link *pcard)
 297 {
 298         struct snd_card *card = pnp_get_card_drvdata(pcard);
 299         struct snd_es1688 *chip = card->private_data;
 300 
 301         snd_es1688_reset(chip);
 302         snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 303         return 0;
 304 }
 305 #endif
 306 
 307 static const struct pnp_card_device_id snd_es968_pnpids[] = {
 308         { .id = "ESS0968", .devs = { { "@@@0968" }, } },
 309         { .id = "ESS0968", .devs = { { "ESS0968" }, } },
 310         { .id = "", } /* end */
 311 };
 312 
 313 MODULE_DEVICE_TABLE(pnp_card, snd_es968_pnpids);
 314 
 315 static struct pnp_card_driver es968_pnpc_driver = {
 316         .flags          = PNP_DRIVER_RES_DISABLE,
 317         .name           = DEV_NAME " PnP",
 318         .id_table       = snd_es968_pnpids,
 319         .probe          = snd_es968_pnp_detect,
 320         .remove         = snd_es968_pnp_remove,
 321 #ifdef CONFIG_PM
 322         .suspend        = snd_es968_pnp_suspend,
 323         .resume         = snd_es968_pnp_resume,
 324 #endif
 325 };
 326 #endif
 327 
 328 static int __init alsa_card_es1688_init(void)
 329 {
 330 #ifdef CONFIG_PNP
 331         pnp_register_card_driver(&es968_pnpc_driver);
 332         if (snd_es968_pnp_is_probed)
 333                 return 0;
 334         pnp_unregister_card_driver(&es968_pnpc_driver);
 335 #endif
 336         return isa_register_driver(&snd_es1688_driver, SNDRV_CARDS);
 337 }
 338 
 339 static void __exit alsa_card_es1688_exit(void)
 340 {
 341         if (!snd_es968_pnp_is_probed) {
 342                 isa_unregister_driver(&snd_es1688_driver);
 343                 return;
 344         }
 345 #ifdef CONFIG_PNP
 346         pnp_unregister_card_driver(&es968_pnpc_driver);
 347 #endif
 348 }
 349 
 350 module_init(alsa_card_es1688_init);
 351 module_exit(alsa_card_es1688_exit);

/* [<][>][^][v][top][bottom][index][help] */