--- linux-2.4.0-test11/drivers/sound/maestro.c Sat Nov 11 18:33:13 2000 +++ linux/drivers/sound/maestro.c Wed Nov 15 22:25:42 2000 @@ -243,7 +243,6 @@ #include #include -static int maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d); #include "maestro.h" @@ -355,6 +354,51 @@ TYPE_MAESTRO2E }; +static struct pci_device_id maestro_pci_ids[] __devinitdata = { + { + vendor: PCI_VENDOR_ESS, + device: PCI_DEVICE_ID_ESS_ESS1968, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + driver_data: TYPE_MAESTRO2 + }, + { + vendor: PCI_VENDOR_ESS, + device: PCI_DEVICE_ID_ESS_ESS1978, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + driver_data: TYPE_MAESTRO2E + }, + { + vendor: PCI_VENDOR_ESS_OLD, + device: PCI_DEVICE_ID_ESS_ESS0100, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + driver_data: TYPE_MAESTRO + }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(pci, maestro_pci_ids); + +static int __devinit maestro_probe(struct pci_dev *pcidev, + const struct pci_device_id *id); +static void __devexit maestro_remove(struct pci_dev *pdev); +static void maestro_suspend(struct pci_dev *pcidev); +static void maestro_resume(struct pci_dev *pcidev); + +static struct pci_driver maestro_driver = { + name: "maestro", + id_table: maestro_pci_ids, + probe: maestro_probe, + remove: maestro_remove, +#ifdef CONFIG_PM + suspend: maestro_suspend, + resume: maestro_resume, +#endif /* PM */ +}; + + static const char *card_names[]={ [TYPE_MAESTRO] = "ESS Maestro", [TYPE_MAESTRO2] = "ESS Maestro 2", @@ -1958,6 +2002,7 @@ static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long arg) { int i, val=0; + unsigned long flags; VALIDATE_CARD(card); if (cmd == SOUND_MIXER_INFO) { @@ -1990,9 +2035,9 @@ if(!card->mix.recmask_io) { val = 0; } else { - spin_lock(&card->lock); + spin_lock_irqsave(&card->lock, flags); val = card->mix.recmask_io(card,1,0); - spin_unlock(&card->lock); + spin_unlock_irqrestore(&card->lock, flags); } break; @@ -2019,9 +2064,9 @@ return -EINVAL; /* do we ever want to touch the hardware? */ -/* spin_lock(&card->lock); +/* spin_lock_irqsave(&card->lock, flags); val = card->mix.read_mixer(card,i); - spin_unlock(&card->lock);*/ + spin_unlock_irqrestore(&card->lock, flags);*/ val = card->mix.mixer_state[i]; /* M_printk("returned 0x%x for mixer %d\n",val,i);*/ @@ -2046,9 +2091,9 @@ if(!val) return 0; if(! (val &= card->mix.record_sources)) return -EINVAL; - spin_lock(&card->lock); + spin_lock_irqsave(&card->lock, flags); card->mix.recmask_io(card,0,val); - spin_unlock(&card->lock); + spin_unlock_irqrestore(&card->lock, flags); return 0; default: @@ -2057,9 +2102,9 @@ if ( ! supported_mixer(card,i)) return -EINVAL; - spin_lock(&card->lock); + spin_lock_irqsave(&card->lock, flags); set_mixer(card,i,val); - spin_unlock(&card->lock); + spin_unlock_irqrestore(&card->lock, flags); return 0; } @@ -3292,15 +3337,15 @@ return card->power_regs ? 1 : 0; } -static int __init -maestro_install(struct pci_dev *pcidev, int card_type) +static int __devinit +maestro_probe(struct pci_dev *pcidev, const struct pci_device_id *id) { + const int card_type = id->driver_data; u32 n; int iobase; int i; struct ess_card *card; struct ess_state *ess; - struct pm_dev *pmdev; int num = 0; /* don't pick up weird modem maestros */ @@ -3334,11 +3379,6 @@ memset(card, 0, sizeof(*card)); card->pcidev = pcidev; - pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), - maestro_pm_callback); - if (pmdev) - pmdev->data = card; - if (register_reboot_notifier(&maestro_nb)) { printk(KERN_WARNING "maestro: reboot notifier registration failed; may not reboot properly.\n"); } @@ -3350,6 +3390,7 @@ card->magic = ESS_CARD_MAGIC; spin_lock_init(&card->lock); init_waitqueue_head(&card->suspend_queue); + pcidev->driver_data = card; devs = card; /* init our groups of 6 apus */ @@ -3465,15 +3506,8 @@ int __init init_maestro(void) { - struct pci_dev *pcidev = NULL; - int foundone = 0; - - if (!pci_present()) /* No PCI bus in this machine! */ - return -ENODEV; printk(KERN_INFO "maestro: version " DRIVER_VERSION " time " __TIME__ " " __DATE__ "\n"); - pcidev = NULL; - if (dsps_order < 0) { dsps_order = 1; printk(KERN_WARNING "maestro: clipping dsps_order to %d\n",dsps_order); @@ -3483,74 +3517,43 @@ printk(KERN_WARNING "maestro: clipping dsps_order to %d\n",dsps_order); } - /* - * Find the ESS Maestro 2. - */ - - while( (pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1968, pcidev))!=NULL ) { - if (maestro_install(pcidev, TYPE_MAESTRO2)) - foundone=1; - } - - /* - * Find the ESS Maestro 2E - */ - - while( (pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1978, pcidev))!=NULL) { - if (maestro_install(pcidev, TYPE_MAESTRO2E)) - foundone=1; - } - - /* - * ESS Maestro 1 - */ - - while((pcidev = pci_find_device(PCI_VENDOR_ESS_OLD, PCI_DEVICE_ID_ESS_ESS0100, pcidev))!=NULL) { - if (maestro_install(pcidev, TYPE_MAESTRO)) - foundone=1; - } - if( ! foundone ) { - printk("maestro: no devices found.\n"); - return -ENODEV; - } - return 0; + return pci_module_init(&maestro_driver); } -static void nuke_maestros(void) +static void __devexit +maestro_remove(struct pci_dev *pdev) { - struct ess_card *card; - - /* we do these unconditionally, which is probably wrong */ - pm_unregister_all(maestro_pm_callback); - unregister_reboot_notifier(&maestro_nb); + struct ess_card *card = pdev->driver_data; + struct ess_card **pCard; + int i; - while ((card = devs)) { - int i; - devs = devs->next; - - /* XXX maybe should force stop bob, but should be all - stopped by _release by now */ - free_irq(card->irq, card); - unregister_sound_mixer(card->dev_mixer); - for(i=0;ichannels[i]; - if(ess->dev_audio != -1) - unregister_sound_dsp(ess->dev_audio); - } - /* Goodbye, Mr. Bond. */ - maestro_power(card,ACPI_D3); - release_region(card->iobase, 256); - kfree(card); - } - devs = NULL; + /* Remove this card from the list. */ + for (pCard = &devs; *pCard != NULL && *pCard != card; + pCard = &(*pCard)->next) + ; + *pCard = (*pCard)->next; + + /* XXX maybe should force stop bob, but should be all + stopped by _release by now */ + free_irq(card->irq, card); + unregister_sound_mixer(card->dev_mixer); + for(i=0;ichannels[i]; + if(ess->dev_audio != -1) + unregister_sound_dsp(ess->dev_audio); + } + /* Goodbye, Mr. Bond. */ + maestro_power(card,ACPI_D3); + release_region(card->iobase, 256); + kfree(card); } static int maestro_notifier(struct notifier_block *nb, unsigned long event, void *buf) { /* this notifier is called when the kernel is really shut down. */ M_printk("maestro: shutting down\n"); - nuke_maestros(); + pci_unregister_driver (&maestro_driver); return NOTIFY_OK; } @@ -3564,12 +3567,6 @@ #endif MODULE_PARM(dsps_order,"i"); MODULE_PARM(use_pm,"i"); - -void cleanup_module(void) { - M_printk("maestro: unloading\n"); - nuke_maestros(); -} - #endif /* --------------------------------------------------------------------- */ @@ -3589,9 +3586,10 @@ current->state = TASK_RUNNING; } -static int -maestro_suspend(struct ess_card *card) +static void +maestro_suspend(struct pci_dev *pcidev) { + struct ess_card *card = pcidev->driver_data; unsigned long flags; int i,j; @@ -3630,11 +3628,12 @@ * XXX I'm also not sure that in_suspend will protect * against all reg accesses from here on out. */ - return 0; } -static int -maestro_resume(struct ess_card *card) + +static void +maestro_resume(struct pci_dev *pcidev) { + struct ess_card *card = pcidev->driver_data; unsigned long flags; int i; @@ -3698,35 +3697,14 @@ wake up people who were using the device when we suspended */ wake_up(&(card->suspend_queue)); - - return 0; } -int -maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +static void __exit exit_maestro (void) { - struct ess_card *card = (struct ess_card*) dev->data; - - if ( ! card ) goto out; - - M_printk("maestro: pm event 0x%x received for card %p\n", rqst, card); - - switch (rqst) { - case PM_SUSPEND: - maestro_suspend(card); - break; - case PM_RESUME: - maestro_resume(card); - break; - /* - * we'd also like to find out about - * power level changes because some biosen - * do mean things to the maestro when they - * change their power state. - */ - } -out: - return 0; + /* we do these unconditionally, which is probably wrong */ + unregister_reboot_notifier(&maestro_nb); + pci_unregister_driver (&maestro_driver); } module_init(init_maestro); +module_exit(exit_maestro);