2 * Driver for generic MPU-401 boards (UART mode only)
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
5 * ACPI PnP Copyright (c) 2004 by Clemens Ladisch <clemens@ladisch.de>
7 * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard
8 * Copyright (C) 2004 Hewlett-Packard Co
9 * Bjorn Helgaas <bjorn.helgaas@hp.com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <sound/driver.h>
29 #include <linux/init.h>
30 #ifdef CONFIG_ACPI_BUS
31 #include <linux/acpi.h>
33 #include <linux/moduleparam.h>
34 #include <sound/core.h>
35 #include <sound/mpu401.h>
36 #include <sound/initval.h>
38 #ifdef CONFIG_ACPI_BUS
42 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
43 MODULE_DESCRIPTION("MPU-401 UART");
44 MODULE_LICENSE("GPL");
46 static int index
[SNDRV_CARDS
] = SNDRV_DEFAULT_IDX
; /* Index 0-MAX */
47 static char *id
[SNDRV_CARDS
] = SNDRV_DEFAULT_STR
; /* ID for this card */
48 static int enable
[SNDRV_CARDS
] = SNDRV_DEFAULT_ENABLE
; /* Enable this card */
50 static int acpipnp
[SNDRV_CARDS
] = { [0 ... (SNDRV_CARDS
-1)] = 1 };
52 static long port
[SNDRV_CARDS
] = SNDRV_DEFAULT_PORT
; /* MPU-401 port number */
53 static int irq
[SNDRV_CARDS
] = SNDRV_DEFAULT_IRQ
; /* MPU-401 IRQ */
56 module_param_array(index
, int, boot_devs
, 0444);
57 MODULE_PARM_DESC(index
, "Index value for MPU-401 device.");
58 module_param_array(id
, charp
, boot_devs
, 0444);
59 MODULE_PARM_DESC(id
, "ID string for MPU-401 device.");
60 module_param_array(enable
, bool, boot_devs
, 0444);
61 MODULE_PARM_DESC(enable
, "Enable MPU-401 device.");
63 module_param_array(acpipnp
, bool, boot_devs
, 0444);
64 MODULE_PARM_DESC(acpipnp
, "ACPI PnP detection for MPU-401 device.");
66 module_param_array(port
, long, boot_devs
, 0444);
67 MODULE_PARM_DESC(port
, "Port # for MPU-401 device.");
68 module_param_array(irq
, int, boot_devs
, 0444);
69 MODULE_PARM_DESC(irq
, "IRQ # for MPU-401 device.");
71 #ifndef CONFIG_ACPI_BUS
75 static snd_card_t
*snd_mpu401_legacy_cards
[SNDRV_CARDS
] = SNDRV_DEFAULT_PTR
;
80 static int acpi_driver_registered
;
82 struct mpu401_resources
{
87 static acpi_status __devinit
snd_mpu401_acpi_resource(struct acpi_resource
*res
,
90 struct mpu401_resources
*resources
= (struct mpu401_resources
*)data
;
92 if (res
->id
== ACPI_RSTYPE_IRQ
) {
93 if (res
->data
.irq
.number_of_interrupts
> 0) {
94 resources
->irq
= acpi_register_gsi(res
->data
.irq
.interrupts
[0],
95 res
->data
.irq
.edge_level
,
96 res
->data
.irq
.active_high_low
);
98 } else if (res
->id
== ACPI_RSTYPE_IO
) {
99 if (res
->data
.io
.range_length
>= 2) {
100 resources
->port
= res
->data
.io
.min_base_address
;
106 static int __devinit
snd_mpu401_acpi_pnp(int dev
, struct acpi_device
*device
)
108 struct mpu401_resources res
;
111 res
.port
= SNDRV_AUTO_PORT
;
112 res
.irq
= SNDRV_AUTO_IRQ
;
113 status
= acpi_walk_resources(device
->handle
, METHOD_NAME__CRS
,
114 snd_mpu401_acpi_resource
, &res
);
115 if (ACPI_FAILURE(status
))
117 if (res
.port
== SNDRV_AUTO_PORT
|| res
.irq
== SNDRV_AUTO_IRQ
) {
118 snd_printk(KERN_ERR
"no port or irq in %s _CRS\n",
119 acpi_device_bid(device
));
122 port
[dev
] = res
.port
;
127 #endif /* USE_ACPI_PNP */
129 static int __devinit
snd_card_mpu401_probe(int dev
, struct acpi_device
*device
)
137 if (port
[dev
] == SNDRV_AUTO_PORT
) {
138 snd_printk(KERN_ERR
"specify port\n");
141 if (irq
[dev
] == SNDRV_AUTO_IRQ
) {
142 snd_printk(KERN_ERR
"specify or disable IRQ port\n");
150 if (device
&& (err
= snd_mpu401_acpi_pnp(dev
, device
)) < 0)
154 card
= snd_card_new(index
[dev
], id
[dev
], THIS_MODULE
, 0);
157 strcpy(card
->driver
, "MPU-401 UART");
158 strcpy(card
->shortname
, card
->driver
);
159 sprintf(card
->longname
, "%s at 0x%lx, ", card
->shortname
, port
[dev
]);
161 sprintf(card
->longname
+ strlen(card
->longname
), "IRQ %d", irq
[dev
]);
163 strcat(card
->longname
, "polled");
167 strcat(card
->longname
, ", ACPI id ");
168 strlcat(card
->longname
, acpi_device_bid(device
), sizeof(card
->longname
));
171 if (snd_mpu401_uart_new(card
, 0,
174 irq
[dev
], irq
[dev
] >= 0 ? SA_INTERRUPT
: 0, NULL
) < 0) {
175 printk(KERN_ERR
"MPU401 not detected at 0x%lx\n", port
[dev
]);
179 if ((err
= snd_card_register(card
)) < 0) {
185 acpi_driver_data(device
) = card
;
188 snd_mpu401_legacy_cards
[dev
] = card
;
195 static int __devinit
snd_mpu401_acpi_add(struct acpi_device
*device
)
200 for ( ; dev
< SNDRV_CARDS
; ++dev
) {
201 if (!enable
[dev
] || !acpipnp
[dev
])
203 err
= snd_card_mpu401_probe(dev
, device
);
212 static int __devexit
snd_mpu401_acpi_remove(struct acpi_device
*device
,
219 card
= (snd_card_t
*)acpi_driver_data(device
);
223 snd_card_disconnect(card
);
224 snd_card_free_in_thread(card
);
225 acpi_driver_data(device
) = NULL
;
229 static struct acpi_driver snd_mpu401_acpi_driver
= {
230 .name
= "MPU-401 Driver",
234 .add
= snd_mpu401_acpi_add
,
235 .remove
= __devexit_p(snd_mpu401_acpi_remove
),
239 #endif /* USE_ACPI_PNP */
241 static int __init
alsa_card_mpu401_init(void)
246 if (acpi_bus_register_driver(&snd_mpu401_acpi_driver
) >= 0)
247 acpi_driver_registered
= 1;
249 for (dev
= 0; dev
< SNDRV_CARDS
; dev
++) {
253 if (acpipnp
[dev
] && acpi_driver_registered
)
256 snd_card_mpu401_probe(dev
, NULL
);
260 printk(KERN_ERR
"MPU-401 device not found or device busy\n");
263 if (acpi_driver_registered
)
264 acpi_bus_unregister_driver(&snd_mpu401_acpi_driver
);
271 static void __exit
alsa_card_mpu401_exit(void)
276 if (acpi_driver_registered
)
277 acpi_bus_unregister_driver(&snd_mpu401_acpi_driver
);
279 for (idx
= 0; idx
< SNDRV_CARDS
; idx
++)
280 snd_card_free(snd_mpu401_legacy_cards
[idx
]);
283 module_init(alsa_card_mpu401_init
)
284 module_exit(alsa_card_mpu401_exit
)