Update of /cvsroot/alsa/alsa-kernel/drivers/mpu401 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv7964/drivers/mpu401
Modified Files: mpu401.c Log Message: integrate MPU-401 ACPI PnP from alsa-driver Index: mpu401.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/drivers/mpu401/mpu401.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- mpu401.c 14 Oct 2003 13:08:13 -0000 1.12 +++ mpu401.c 15 Mar 2004 08:07:51 -0000 1.13 @@ -2,6 +2,12 @@ * Driver for generic MPU-401 boards (UART mode only) * Copyright (c) by Jaroslav Kysela <[EMAIL PROTECTED]> * + * ACPI PnP Copyright (c) 2004 by Clemens Ladisch <[EMAIL PROTECTED]> + * based on 8250_acpi.c + * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard + * Copyright (C) 2004 Hewlett-Packard Co + * Bjorn Helgaas <[EMAIL PROTECTED]> + * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,14 +27,17 @@ #include <sound/driver.h> #include <linux/init.h> -#include <linux/wait.h> -#include <linux/sched.h> -#include <linux/slab.h> +#ifdef CONFIG_ACPI_BUS +#include <acpi/acpi_bus.h> +#endif #include <sound/core.h> #include <sound/mpu401.h> #define SNDRV_GET_ID #include <sound/initval.h> -#include <linux/delay.h> + +#ifdef CONFIG_ACPI_BUS +#define USE_ACPI_PNP +#endif MODULE_AUTHOR("Jaroslav Kysela <[EMAIL PROTECTED]>"); MODULE_DESCRIPTION("MPU-401 UART"); @@ -38,6 +47,9 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ +#ifdef USE_ACPI_PNP +static int acpipnp[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 }; +#endif static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */ static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */ #ifdef CONFIG_X86_PC9800 @@ -53,6 +65,11 @@ MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); MODULE_PARM_DESC(enable, "Enable MPU-401 device."); MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC); +#ifdef USE_ACPI_PNP +MODULE_PARM(acpipnp, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +MODULE_PARM_DESC(acpipnp, "ACPI PnP detection for MPU-401 device."); +MODULE_PARM_SYNTAX(acpipnp, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC); +#endif MODULE_PARM(port, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); MODULE_PARM_DESC(port, "Port # for MPU-401 device."); MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC); @@ -65,25 +82,107 @@ MODULE_PARM_SYNTAX(pc98ii, SNDRV_BOOLEAN_FALSE_DESC); #endif -static snd_card_t *snd_mpu401_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; +#ifndef CONFIG_ACPI_BUS +struct acpi_device; +#endif + +static snd_card_t *snd_mpu401_legacy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; + +#ifdef USE_ACPI_PNP + +struct mpu401_resources { + unsigned long port; + int irq; +}; -static int __init snd_card_mpu401_probe(int dev) +static acpi_status __devinit snd_mpu401_acpi_resource(struct acpi_resource *res, + void *data) +{ + struct mpu401_resources *resources = (struct mpu401_resources *)data; + + if (res->id == ACPI_RSTYPE_IRQ) { + if (res->data.irq.number_of_interrupts > 0) { +#ifdef CONFIG_IA64 + resources->irq = acpi_register_irq(res->data.irq.interrupts[0], + res->data.irq.active_high_low, + res->data.irq.edge_level); +#else + resources->irq = res->data.irq.interrupts[0]; +#endif + } + } else if (res->id == ACPI_RSTYPE_IO) { + if (res->data.io.range_length >= 2) { + resources->port = res->data.io.min_base_address; + } + } + return AE_OK; +} + +static int __devinit snd_mpu401_acpi_pnp(int dev, struct acpi_device *device) +{ + struct mpu401_resources res; + acpi_status status; + + res.port = SNDRV_AUTO_PORT; + res.irq = SNDRV_AUTO_IRQ; + status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, + snd_mpu401_acpi_resource, &res); + if (ACPI_FAILURE(status)) + return -ENODEV; + if (res.port == SNDRV_AUTO_PORT || res.irq == SNDRV_AUTO_IRQ) { + snd_printk(KERN_ERR "no port or irq in %s _CRS\n", + acpi_device_bid(device)); + return -ENODEV; + } + port[dev] = res.port; + irq[dev] = res.irq; + return 0; +} + +#endif /* USE_ACPI_PNP */ + +static int __devinit snd_card_mpu401_probe(int dev, struct acpi_device *device) { snd_card_t *card; int err; - if (port[dev] == SNDRV_AUTO_PORT) { - snd_printk("specify port\n"); - return -EINVAL; - } - if (irq[dev] == SNDRV_AUTO_IRQ) { - snd_printk("specify or disable IRQ port\n"); - return -EINVAL; +#ifdef USE_ACPI_PNP + if (!device) { +#endif + if (port[dev] == SNDRV_AUTO_PORT) { + snd_printk(KERN_ERR "specify port\n"); + return -EINVAL; + } + if (irq[dev] == SNDRV_AUTO_IRQ) { + snd_printk(KERN_ERR "specify or disable IRQ port\n"); + return -EINVAL; + } +#ifdef USE_ACPI_PNP } +#endif + +#ifdef USE_ACPI_PNP + if (device && (err = snd_mpu401_acpi_pnp(dev, device)) < 0) + return err; +#endif card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); if (card == NULL) return -ENOMEM; + strcpy(card->driver, "MPU-401 UART"); + strcpy(card->shortname, card->driver); + sprintf(card->longname, "%s at 0x%lx, ", card->shortname, port[dev]); + if (irq[dev] >= 0) { + sprintf(card->longname + strlen(card->longname), "IRQ %d", irq[dev]); + } else { + strcat(card->longname, "polled"); + } +#ifdef USE_ACPI_PNP + if (device) { + strcat(card->longname, ", bus id "); + strlcat(card->longname, acpi_device_bid(device), sizeof(card->longname)); + } +#endif if (snd_mpu401_uart_new(card, 0, #ifdef CONFIG_X86_PC9800 pc98ii[dev] ? MPU401_HW_PC98II : @@ -95,22 +194,67 @@ snd_card_free(card); return -ENODEV; } - strcpy(card->driver, "MPU-401 UART"); - strcpy(card->shortname, card->driver); - sprintf(card->longname, "%s at 0x%lx, ", card->shortname, port[dev]); - if (irq[dev] >= 0) { - sprintf(card->longname + strlen(card->longname), "IRQ %d", irq[dev]); - } else { - strcat(card->longname, "polled"); - } if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } - snd_mpu401_cards[dev] = card; +#ifdef USE_ACPI_PNP + if (device) + acpi_driver_data(device) = card; + else +#endif + snd_mpu401_legacy_cards[dev] = card; return 0; } +#ifdef USE_ACPI_PNP + +static int __devinit snd_mpu401_acpi_add(struct acpi_device *device) +{ + static int dev; + int err; + + for ( ; dev < SNDRV_CARDS; ++dev) { + if (!enable[dev] || !acpipnp[dev]) + continue; + err = snd_card_mpu401_probe(dev, device); + if (err < 0) + return err; + ++dev; + return 0; + } + return -ENODEV; +} + +static int __devexit snd_mpu401_acpi_remove(struct acpi_device *device, + int type) +{ + snd_card_t *card; + + if (!device) + return -EINVAL; + card = (snd_card_t *)acpi_driver_data(device); + if (!card) + return -EINVAL; + + snd_card_disconnect(card); + snd_card_free_in_thread(card); + acpi_driver_data(device) = NULL; + return 0; +} + +static struct acpi_driver snd_mpu401_acpi_driver = { + .name = "MPU-401 Driver", + .class = "mpu401", + .ids = "PNPB006", + .ops = { + .add = snd_mpu401_acpi_add, + .remove = __devexit_p(snd_mpu401_acpi_remove), + }, +}; + +#endif /* USE_ACPI_PNP */ + static int __init alsa_card_mpu401_init(void) { int dev, cards = 0; @@ -118,13 +262,25 @@ for (dev = 0; dev < SNDRV_CARDS; dev++) { if (!enable[dev]) continue; - if (snd_card_mpu401_probe(dev) >= 0) +#ifdef USE_ACPI_PNP + if (acpipnp[dev] && !acpi_disabled) + continue; +#endif + if (snd_card_mpu401_probe(dev, NULL) >= 0) cards++; } +#ifdef USE_ACPI_PNP + if (!acpi_disabled) + cards += acpi_bus_register_driver(&snd_mpu401_acpi_driver); +#endif if (!cards) { #ifdef MODULE printk(KERN_ERR "MPU-401 device not found or device busy\n"); #endif +#ifdef USE_ACPI_PNP + if (!acpi_disabled) + acpi_bus_unregister_driver(&snd_mpu401_acpi_driver); +#endif return -ENODEV; } return 0; @@ -134,8 +290,12 @@ { int idx; +#ifdef USE_ACPI_PNP + if (!acpi_disabled) + acpi_bus_unregister_driver(&snd_mpu401_acpi_driver); +#endif for (idx = 0; idx < SNDRV_CARDS; idx++) - snd_card_free(snd_mpu401_cards[idx]); + snd_card_free(snd_mpu401_legacy_cards[idx]); } module_init(alsa_card_mpu401_init) @@ -143,22 +303,28 @@ #ifndef MODULE -/* format is: snd-mpu401=enable,index,id,port,irq */ +/* format is: snd-mpu401=enable,index,id,acpipnp[,pc98ii],port,irq */ static int __init alsa_card_mpu401_setup(char *str) { static unsigned __initdata nr_dev = 0; + int __attribute__ ((__unused__)) pnp = INT_MAX; if (nr_dev >= SNDRV_CARDS) return 0; (void)(get_option(&str,&enable[nr_dev]) == 2 && get_option(&str,&index[nr_dev]) == 2 && get_id(&str,&id[nr_dev]) == 2 && + get_option(&str,&pnp) == 2 && #ifdef CONFIG_X86_PC9800 get_option(&str,&pc98ii[nr_dev]) == 2 && #endif get_option_long(&str,&port[nr_dev]) == 2 && get_option(&str,&irq[nr_dev]) == 2); +#ifdef USE_ACPI_PNP + if (pnp != INT_MAX) + acpipnp[nr_dev] = pnp; +#endif nr_dev++; return 1; } ------------------------------------------------------- This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click _______________________________________________ Alsa-cvslog mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/alsa-cvslog