mpu401.c (6461B)
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)