linux/sound/drivers/mpu401/mpu401.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Driver for generic MPU-401 boards (UART mode only)
   4 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   5 *  Copyright (c) 2004 by Castet Matthieu <castet.matthieu@free.fr>
   6 */
   7
   8#include <linux/init.h>
   9#include <linux/pnp.h>
  10#include <linux/err.h>
  11#include <linux/platform_device.h>
  12#include <linux/module.h>
  13#include <sound/core.h>
  14#include <sound/mpu401.h>
  15#include <sound/initval.h>
  16
  17MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
  18MODULE_DESCRIPTION("MPU-401 UART");
  19MODULE_LICENSE("GPL");
  20
  21static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* exclude the first card */
  22static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* ID for this card */
  23static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
  24#ifdef CONFIG_PNP
  25static bool pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
  26#endif
  27static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;     /* MPU-401 port number */
  28static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;        /* MPU-401 IRQ */
  29static bool uart_enter[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
  30
  31module_param_array(index, int, NULL, 0444);
  32MODULE_PARM_DESC(index, "Index value for MPU-401 device.");
  33module_param_array(id, charp, NULL, 0444);
  34MODULE_PARM_DESC(id, "ID string for MPU-401 device.");
  35module_param_array(enable, bool, NULL, 0444);
  36MODULE_PARM_DESC(enable, "Enable MPU-401 device.");
  37#ifdef CONFIG_PNP
  38module_param_array(pnp, bool, NULL, 0444);
  39MODULE_PARM_DESC(pnp, "PnP detection for MPU-401 device.");
  40#endif
  41module_param_hw_array(port, long, ioport, NULL, 0444);
  42MODULE_PARM_DESC(port, "Port # for MPU-401 device.");
  43module_param_hw_array(irq, int, irq, NULL, 0444);
  44MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
  45module_param_array(uart_enter, bool, NULL, 0444);
  46MODULE_PARM_DESC(uart_enter, "Issue UART_ENTER command at open.");
  47
  48static struct platform_device *platform_devices[SNDRV_CARDS];
  49static int pnp_registered;
  50static unsigned int snd_mpu401_devices;
  51
  52static int snd_mpu401_create(struct device *devptr, int dev,
  53                             struct snd_card **rcard)
  54{
  55        struct snd_card *card;
  56        int err;
  57
  58        if (!uart_enter[dev])
  59                snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n");
  60
  61        *rcard = NULL;
  62        err = snd_devm_card_new(devptr, index[dev], id[dev], THIS_MODULE,
  63                                0, &card);
  64        if (err < 0)
  65                return err;
  66        strcpy(card->driver, "MPU-401 UART");
  67        strcpy(card->shortname, card->driver);
  68        sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]);
  69        if (irq[dev] >= 0) {
  70                sprintf(card->longname + strlen(card->longname), "irq %d", irq[dev]);
  71        } else {
  72                strcat(card->longname, "polled");
  73        }
  74
  75        err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0,
  76                                  irq[dev], NULL);
  77        if (err < 0) {
  78                printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
  79                return err;
  80        }
  81
  82        *rcard = card;
  83        return 0;
  84}
  85
  86static int snd_mpu401_probe(struct platform_device *devptr)
  87{
  88        int dev = devptr->id;
  89        int err;
  90        struct snd_card *card;
  91
  92        if (port[dev] == SNDRV_AUTO_PORT) {
  93                snd_printk(KERN_ERR "specify port\n");
  94                return -EINVAL;
  95        }
  96        if (irq[dev] == SNDRV_AUTO_IRQ) {
  97                snd_printk(KERN_ERR "specify or disable IRQ\n");
  98                return -EINVAL;
  99        }
 100        err = snd_mpu401_create(&devptr->dev, dev, &card);
 101        if (err < 0)
 102                return err;
 103        err = snd_card_register(card);
 104        if (err < 0)
 105                return err;
 106        platform_set_drvdata(devptr, card);
 107        return 0;
 108}
 109
 110#define SND_MPU401_DRIVER       "snd_mpu401"
 111
 112static struct platform_driver snd_mpu401_driver = {
 113        .probe          = snd_mpu401_probe,
 114        .driver         = {
 115                .name   = SND_MPU401_DRIVER,
 116        },
 117};
 118
 119
 120#ifdef CONFIG_PNP
 121
 122#define IO_EXTENT 2
 123
 124static const struct pnp_device_id snd_mpu401_pnpids[] = {
 125        { .id = "PNPb006" },
 126        { .id = "" }
 127};
 128
 129MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids);
 130
 131static int snd_mpu401_pnp(int dev, struct pnp_dev *device,
 132                          const struct pnp_device_id *id)
 133{
 134        if (!pnp_port_valid(device, 0) ||
 135            pnp_port_flags(device, 0) & IORESOURCE_DISABLED) {
 136                snd_printk(KERN_ERR "no PnP port\n");
 137                return -ENODEV;
 138        }
 139        if (pnp_port_len(device, 0) < IO_EXTENT) {
 140                snd_printk(KERN_ERR "PnP port length is %llu, expected %d\n",
 141                           (unsigned long long)pnp_port_len(device, 0),
 142                           IO_EXTENT);
 143                return -ENODEV;
 144        }
 145        port[dev] = pnp_port_start(device, 0);
 146
 147        if (!pnp_irq_valid(device, 0) ||
 148            pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) {
 149                snd_printk(KERN_WARNING "no PnP irq, using polling\n");
 150                irq[dev] = -1;
 151        } else {
 152                irq[dev] = pnp_irq(device, 0);
 153        }
 154        return 0;
 155}
 156
 157static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
 158                                const struct pnp_device_id *id)
 159{
 160        static int dev;
 161        struct snd_card *card;
 162        int err;
 163
 164        for ( ; dev < SNDRV_CARDS; ++dev) {
 165                if (!enable[dev] || !pnp[dev])
 166                        continue;
 167                err = snd_mpu401_pnp(dev, pnp_dev, id);
 168                if (err < 0)
 169                        return err;
 170                err = snd_mpu401_create(&pnp_dev->dev, dev, &card);
 171                if (err < 0)
 172                        return err;
 173                err = snd_card_register(card);
 174                if (err < 0)
 175                        return err;
 176                pnp_set_drvdata(pnp_dev, card);
 177                snd_mpu401_devices++;
 178                ++dev;
 179                return 0;
 180        }
 181        return -ENODEV;
 182}
 183
 184static struct pnp_driver snd_mpu401_pnp_driver = {
 185        .name = "mpu401",
 186        .id_table = snd_mpu401_pnpids,
 187        .probe = snd_mpu401_pnp_probe,
 188};
 189#else
 190static struct pnp_driver snd_mpu401_pnp_driver;
 191#endif
 192
 193static void snd_mpu401_unregister_all(void)
 194{
 195        int i;
 196
 197        if (pnp_registered)
 198                pnp_unregister_driver(&snd_mpu401_pnp_driver);
 199        for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
 200                platform_device_unregister(platform_devices[i]);
 201        platform_driver_unregister(&snd_mpu401_driver);
 202}
 203
 204static int __init alsa_card_mpu401_init(void)
 205{
 206        int i, err;
 207
 208        err = platform_driver_register(&snd_mpu401_driver);
 209        if (err < 0)
 210                return err;
 211
 212        for (i = 0; i < SNDRV_CARDS; i++) {
 213                struct platform_device *device;
 214                if (! enable[i])
 215                        continue;
 216#ifdef CONFIG_PNP
 217                if (pnp[i])
 218                        continue;
 219#endif
 220                device = platform_device_register_simple(SND_MPU401_DRIVER,
 221                                                         i, NULL, 0);
 222                if (IS_ERR(device))
 223                        continue;
 224                if (!platform_get_drvdata(device)) {
 225                        platform_device_unregister(device);
 226                        continue;
 227                }
 228                platform_devices[i] = device;
 229                snd_mpu401_devices++;
 230        }
 231        err = pnp_register_driver(&snd_mpu401_pnp_driver);
 232        if (!err)
 233                pnp_registered = 1;
 234
 235        if (!snd_mpu401_devices) {
 236#ifdef MODULE
 237                printk(KERN_ERR "MPU-401 device not found or device busy\n");
 238#endif
 239                snd_mpu401_unregister_all();
 240                return -ENODEV;
 241        }
 242        return 0;
 243}
 244
 245static void __exit alsa_card_mpu401_exit(void)
 246{
 247        snd_mpu401_unregister_all();
 248}
 249
 250module_init(alsa_card_mpu401_init)
 251module_exit(alsa_card_mpu401_exit)
 252