--- linux.old/drivers/input/misc/pcspkr.c 2006-04-30 18:16:09.000000000 +0200 +++ linux/drivers/input/misc/pcspkr.c 2006-05-02 19:35:09.000000000 +0200 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,7 @@ static struct platform_device *pcspkr_platform_device; static DEFINE_SPINLOCK(i8253_beep_lock); +static int pnp_registered; static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { @@ -64,7 +66,7 @@ return 0; } -static int __devinit pcspkr_probe(struct platform_device *dev) +static int __devinit pcspkr_probe(struct device *dev, struct input_dev **pcspkr_dev_pointer) { struct input_dev *pcspkr_dev; int err; @@ -79,7 +81,7 @@ pcspkr_dev->id.vendor = 0x001f; pcspkr_dev->id.product = 0x0001; pcspkr_dev->id.version = 0x0100; - pcspkr_dev->cdev.dev = &dev->dev; + pcspkr_dev->cdev.dev = dev; pcspkr_dev->evbit[0] = BIT(EV_SND); pcspkr_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); @@ -90,32 +92,48 @@ input_free_device(pcspkr_dev); return err; } + *pcspkr_dev_pointer = pcspkr_dev; - platform_set_drvdata(dev, pcspkr_dev); + return 0; +} + +static int __devexit pcspkr_remove(struct input_dev *pcspkr_dev) +{ + input_unregister_device(pcspkr_dev); + /* turn off the speaker */ + pcspkr_event(NULL, EV_SND, SND_BELL, 0); return 0; } -static int __devexit pcspkr_remove(struct platform_device *dev) +static int __devinit pcspkr_probe_platform(struct platform_device *dev) +{ + struct input_dev *pcspkr_dev; + int err; + err = pcspkr_probe(&dev->dev, &pcspkr_dev); + if (err == 0) + platform_set_drvdata(dev, pcspkr_dev); + return err; +} + +static int __devexit pcspkr_remove_platform(struct platform_device *dev) { struct input_dev *pcspkr_dev = platform_get_drvdata(dev); - input_unregister_device(pcspkr_dev); + pcspkr_remove(pcspkr_dev); platform_set_drvdata(dev, NULL); - /* turn off the speaker */ - pcspkr_event(NULL, EV_SND, SND_BELL, 0); return 0; } -static int pcspkr_suspend(struct platform_device *dev, pm_message_t state) +static int pcspkr_suspend_platform(struct platform_device *dev, pm_message_t state) { pcspkr_event(NULL, EV_SND, SND_BELL, 0); return 0; } -static void pcspkr_shutdown(struct platform_device *dev) +static void pcspkr_shutdown_platform(struct platform_device *dev) { /* turn off the speaker */ pcspkr_event(NULL, EV_SND, SND_BELL, 0); @@ -126,17 +144,80 @@ .name = "pcspkr", .owner = THIS_MODULE, }, - .probe = pcspkr_probe, - .remove = __devexit_p(pcspkr_remove), - .suspend = pcspkr_suspend, - .shutdown = pcspkr_shutdown, + .probe = pcspkr_probe_platform, + .remove = __devexit_p(pcspkr_remove_platform), + .suspend = pcspkr_suspend_platform, + .shutdown = pcspkr_shutdown_platform, +}; + +#ifdef CONFIG_PNP +static struct pnp_device_id pcspkr_pnpids[] = { + { .id = "PNP0800" }, + { .id = "" } +}; + +MODULE_DEVICE_TABLE(pnp, pcspkr_pnpids); + +static int __devinit pcspkr_pnp_probe(struct pnp_dev *pnp_dev, + const struct pnp_device_id *id) +{ + struct input_dev *pcspkr_dev; + int err; + err = pcspkr_probe(&pnp_dev->dev, &pcspkr_dev); + if (err == 0) { + pnp_set_drvdata(pnp_dev, pcspkr_dev); + pnp_registered++; + } + return err; +} + +static void __devexit pcspkr_pnp_remove(struct pnp_dev *dev) +{ + struct input_dev *pcspkr_dev = (struct input_dev *)pnp_get_drvdata(dev); + + pcspkr_remove(pcspkr_dev); + pnp_set_drvdata(dev, NULL); + + return; +} + +#ifdef CONFIG_PM +static int pcspkr_suspend_pnp(struct pnp_dev *pdev, pm_message_t state) +{ + pcspkr_event(NULL, EV_SND, SND_BELL, 0); + + return 0; +} +#endif + +static struct pnp_driver pcspkr_pnp_driver = { + .name = "pcspkr", + .id_table = pcspkr_pnpids, + .probe = pcspkr_pnp_probe, + .remove = __devexit_p(pcspkr_pnp_remove), +#ifdef CONFIG_PM + .suspend = pcspkr_suspend_pnp, +#endif }; +#else +static struct pnp_driver pcspkr_pnp_driver; +#endif static int __init pcspkr_init(void) { int err; + err = pnp_register_driver(&pcspkr_pnp_driver); + if (err < 0) + pnp_registered = 0; + if (err == 0 && pnp_registered == 0) + pnp_unregister_driver(&pcspkr_pnp_driver); + + if (pnp_registered) + return 0; + + /* Try platform driver if pnp failed or found nothing */ err = platform_driver_register(&pcspkr_platform_driver); if (err) return err; @@ -163,6 +244,10 @@ static void __exit pcspkr_exit(void) { + if (pnp_registered) { + pnp_unregister_driver(&pcspkr_pnp_driver); + return; + } platform_device_unregister(pcspkr_platform_device); platform_driver_unregister(&pcspkr_platform_driver); }