Commit 44f06103 authored by Dmitry Torokhov's avatar Dmitry Torokhov Committed by Linus Torvalds

[PATCH] Sonypi: convert to the new platform device interface

Do not use platform_device_register_simple() as it is going away, implement
->probe() and -remove() functions so manual binding and unbinding will work
with this driver.
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
Cc: Stelian Pop <stelian@popies.net>
Cc: Mattia Dongili <malattia@linux.it>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fee781e6
...@@ -471,7 +471,6 @@ struct sonypi_keypress { ...@@ -471,7 +471,6 @@ struct sonypi_keypress {
static struct sonypi_device { static struct sonypi_device {
struct pci_dev *dev; struct pci_dev *dev;
struct platform_device *pdev;
u16 irq; u16 irq;
u16 bits; u16 bits;
u16 ioport1; u16 ioport1;
...@@ -1165,45 +1164,12 @@ static int sonypi_disable(void) ...@@ -1165,45 +1164,12 @@ static int sonypi_disable(void)
return 0; return 0;
} }
#ifdef CONFIG_PM
static int old_camera_power;
static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
{
old_camera_power = sonypi_device.camera_power;
sonypi_disable();
return 0;
}
static int sonypi_resume(struct platform_device *dev)
{
sonypi_enable(old_camera_power);
return 0;
}
#endif
static void sonypi_shutdown(struct platform_device *dev)
{
sonypi_disable();
}
static struct platform_driver sonypi_driver = {
#ifdef CONFIG_PM
.suspend = sonypi_suspend,
.resume = sonypi_resume,
#endif
.shutdown = sonypi_shutdown,
.driver = {
.name = "sonypi",
},
};
static int __devinit sonypi_create_input_devices(void) static int __devinit sonypi_create_input_devices(void)
{ {
struct input_dev *jog_dev; struct input_dev *jog_dev;
struct input_dev *key_dev; struct input_dev *key_dev;
int i; int i;
int error;
sonypi_device.input_jog_dev = jog_dev = input_allocate_device(); sonypi_device.input_jog_dev = jog_dev = input_allocate_device();
if (!jog_dev) if (!jog_dev)
...@@ -1219,9 +1185,8 @@ static int __devinit sonypi_create_input_devices(void) ...@@ -1219,9 +1185,8 @@ static int __devinit sonypi_create_input_devices(void)
sonypi_device.input_key_dev = key_dev = input_allocate_device(); sonypi_device.input_key_dev = key_dev = input_allocate_device();
if (!key_dev) { if (!key_dev) {
input_free_device(jog_dev); error = -ENOMEM;
sonypi_device.input_jog_dev = NULL; goto err_free_jogdev;
return -ENOMEM;
} }
key_dev->name = "Sony Vaio Keys"; key_dev->name = "Sony Vaio Keys";
...@@ -1234,56 +1199,122 @@ static int __devinit sonypi_create_input_devices(void) ...@@ -1234,56 +1199,122 @@ static int __devinit sonypi_create_input_devices(void)
if (sonypi_inputkeys[i].inputev) if (sonypi_inputkeys[i].inputev)
set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit); set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit);
input_register_device(jog_dev); error = input_register_device(jog_dev);
input_register_device(key_dev); if (error)
goto err_free_keydev;
error = input_register_device(key_dev);
if (error)
goto err_unregister_jogdev;
return 0; return 0;
err_unregister_jogdev:
input_unregister_device(jog_dev);
/* Set to NULL so we don't free it again below */
jog_dev = NULL;
err_free_keydev:
input_free_device(key_dev);
sonypi_device.input_key_dev = NULL;
err_free_jogdev:
input_free_device(jog_dev);
sonypi_device.input_jog_dev = NULL;
return error;
} }
static int __devinit sonypi_probe(void) static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
const struct sonypi_ioport_list *ioport_list)
{ {
int i, ret; while (ioport_list->port1) {
struct sonypi_ioport_list *ioport_list;
struct sonypi_irq_list *irq_list;
struct pci_dev *pcidev;
if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, if (request_region(ioport_list->port1,
PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) sonypi_device.region_size,
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; "Sony Programable I/O Device")) {
else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, dev->ioport1 = ioport_list->port1;
PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) dev->ioport2 = ioport_list->port2;
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; return 0;
else }
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; ioport_list++;
}
sonypi_device.dev = pcidev; return -EBUSY;
}
static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
const struct sonypi_irq_list *irq_list)
{
while (irq_list->irq) {
if (!request_irq(irq_list->irq, sonypi_irq,
SA_SHIRQ, "sonypi", sonypi_irq)) {
dev->irq = irq_list->irq;
dev->bits = irq_list->bits;
return 0;
}
irq_list++;
}
return -EBUSY;
}
static void __devinit sonypi_display_info(void)
{
printk(KERN_INFO "sonypi: detected type%d model, "
"verbose = %d, fnkeyinit = %s, camera = %s, "
"compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n",
sonypi_device.model,
verbose,
fnkeyinit ? "on" : "off",
camera ? "on" : "off",
compat ? "on" : "off",
mask,
useinput ? "on" : "off",
SONYPI_ACPI_ACTIVE ? "on" : "off");
printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
sonypi_device.irq,
sonypi_device.ioport1, sonypi_device.ioport2);
if (minor == -1)
printk(KERN_INFO "sonypi: device allocated minor is %d\n",
sonypi_misc_device.minor);
}
static int __devinit sonypi_probe(struct platform_device *dev)
{
const struct sonypi_ioport_list *ioport_list;
const struct sonypi_irq_list *irq_list;
struct pci_dev *pcidev;
int error;
spin_lock_init(&sonypi_device.fifo_lock); spin_lock_init(&sonypi_device.fifo_lock);
sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
&sonypi_device.fifo_lock); &sonypi_device.fifo_lock);
if (IS_ERR(sonypi_device.fifo)) { if (IS_ERR(sonypi_device.fifo)) {
printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
ret = PTR_ERR(sonypi_device.fifo); return PTR_ERR(sonypi_device.fifo);
goto out_fifo;
} }
init_waitqueue_head(&sonypi_device.fifo_proc_list); init_waitqueue_head(&sonypi_device.fifo_proc_list);
init_MUTEX(&sonypi_device.lock); init_MUTEX(&sonypi_device.lock);
sonypi_device.bluetooth_power = -1; sonypi_device.bluetooth_power = -1;
if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1;
else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
else
sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
if (pcidev && pci_enable_device(pcidev)) { if (pcidev && pci_enable_device(pcidev)) {
printk(KERN_ERR "sonypi: pci_enable_device failed\n"); printk(KERN_ERR "sonypi: pci_enable_device failed\n");
ret = -EIO; error = -EIO;
goto out_pcienable; goto err_put_pcidev;
}
if (minor != -1)
sonypi_misc_device.minor = minor;
if ((ret = misc_register(&sonypi_misc_device))) {
printk(KERN_ERR "sonypi: misc_register failed\n");
goto out_miscreg;
} }
sonypi_device.dev = pcidev;
if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) { if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) {
ioport_list = sonypi_type1_ioport_list; ioport_list = sonypi_type1_ioport_list;
...@@ -1302,43 +1333,36 @@ static int __devinit sonypi_probe(void) ...@@ -1302,43 +1333,36 @@ static int __devinit sonypi_probe(void)
irq_list = sonypi_type3_irq_list; irq_list = sonypi_type3_irq_list;
} }
for (i = 0; ioport_list[i].port1; i++) { error = sonypi_setup_ioports(&sonypi_device, ioport_list);
if (request_region(ioport_list[i].port1, if (error) {
sonypi_device.region_size, printk(KERN_ERR "sonypi: failed to request ioports\n");
"Sony Programable I/O Device")) { goto err_disable_pcidev;
/* get the ioport */
sonypi_device.ioport1 = ioport_list[i].port1;
sonypi_device.ioport2 = ioport_list[i].port2;
break;
} }
}
if (!sonypi_device.ioport1) {
printk(KERN_ERR "sonypi: request_region failed\n");
ret = -ENODEV;
goto out_reqreg;
}
for (i = 0; irq_list[i].irq; i++) {
sonypi_device.irq = irq_list[i].irq; error = sonypi_setup_irq(&sonypi_device, irq_list);
sonypi_device.bits = irq_list[i].bits; if (error) {
printk(KERN_ERR "sonypi: request_irq failed\n");
if (!request_irq(sonypi_device.irq, sonypi_irq, goto err_free_ioports;
SA_SHIRQ, "sonypi", sonypi_irq))
break;
} }
if (!irq_list[i].irq) { if (minor != -1)
printk(KERN_ERR "sonypi: request_irq failed\n"); sonypi_misc_device.minor = minor;
ret = -ENODEV; error = misc_register(&sonypi_misc_device);
goto out_reqirq; if (error) {
printk(KERN_ERR "sonypi: misc_register failed\n");
goto err_free_irq;
} }
sonypi_display_info();
if (useinput) { if (useinput) {
ret = sonypi_create_input_devices(); error = sonypi_create_input_devices();
if (ret) if (error) {
goto out_inputdevices; printk(KERN_ERR
"sonypi: failed to create input devices\n");
goto err_miscdev_unregister;
}
spin_lock_init(&sonypi_device.input_fifo_lock); spin_lock_init(&sonypi_device.input_fifo_lock);
sonypi_device.input_fifo = sonypi_device.input_fifo =
...@@ -1346,91 +1370,104 @@ static int __devinit sonypi_probe(void) ...@@ -1346,91 +1370,104 @@ static int __devinit sonypi_probe(void)
&sonypi_device.input_fifo_lock); &sonypi_device.input_fifo_lock);
if (IS_ERR(sonypi_device.input_fifo)) { if (IS_ERR(sonypi_device.input_fifo)) {
printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
ret = PTR_ERR(sonypi_device.input_fifo); error = PTR_ERR(sonypi_device.input_fifo);
goto out_infifo; goto err_inpdev_unregister;
} }
INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL);
} }
sonypi_device.pdev = platform_device_register_simple("sonypi", -1,
NULL, 0);
if (IS_ERR(sonypi_device.pdev)) {
ret = PTR_ERR(sonypi_device.pdev);
goto out_platformdev;
}
sonypi_enable(0); sonypi_enable(0);
printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver"
"v%s.\n", SONYPI_DRIVER_VERSION);
printk(KERN_INFO "sonypi: detected type%d model, "
"verbose = %d, fnkeyinit = %s, camera = %s, "
"compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n",
sonypi_device.model,
verbose,
fnkeyinit ? "on" : "off",
camera ? "on" : "off",
compat ? "on" : "off",
mask,
useinput ? "on" : "off",
SONYPI_ACPI_ACTIVE ? "on" : "off");
printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
sonypi_device.irq,
sonypi_device.ioport1, sonypi_device.ioport2);
if (minor == -1)
printk(KERN_INFO "sonypi: device allocated minor is %d\n",
sonypi_misc_device.minor);
return 0; return 0;
out_platformdev: err_inpdev_unregister:
kfifo_free(sonypi_device.input_fifo);
out_infifo:
input_unregister_device(sonypi_device.input_key_dev); input_unregister_device(sonypi_device.input_key_dev);
input_unregister_device(sonypi_device.input_jog_dev); input_unregister_device(sonypi_device.input_jog_dev);
out_inputdevices: err_miscdev_unregister:
misc_deregister(&sonypi_misc_device);
err_free_irq:
free_irq(sonypi_device.irq, sonypi_irq); free_irq(sonypi_device.irq, sonypi_irq);
out_reqirq: err_free_ioports:
release_region(sonypi_device.ioport1, sonypi_device.region_size); release_region(sonypi_device.ioport1, sonypi_device.region_size);
out_reqreg: err_disable_pcidev:
misc_deregister(&sonypi_misc_device);
out_miscreg:
if (pcidev) if (pcidev)
pci_disable_device(pcidev); pci_disable_device(pcidev);
out_pcienable: err_put_pcidev:
pci_dev_put(pcidev);
kfifo_free(sonypi_device.fifo); kfifo_free(sonypi_device.fifo);
out_fifo:
pci_dev_put(sonypi_device.dev); return error;
return ret;
} }
static void __devexit sonypi_remove(void) static int __devexit sonypi_remove(struct platform_device *dev)
{ {
sonypi_disable(); sonypi_disable();
synchronize_sched(); /* Allow sonypi interrupt to complete. */ synchronize_sched(); /* Allow sonypi interrupt to complete. */
flush_scheduled_work(); flush_scheduled_work();
platform_device_unregister(sonypi_device.pdev);
if (useinput) { if (useinput) {
input_unregister_device(sonypi_device.input_key_dev); input_unregister_device(sonypi_device.input_key_dev);
input_unregister_device(sonypi_device.input_jog_dev); input_unregister_device(sonypi_device.input_jog_dev);
kfifo_free(sonypi_device.input_fifo); kfifo_free(sonypi_device.input_fifo);
} }
misc_deregister(&sonypi_misc_device);
free_irq(sonypi_device.irq, sonypi_irq); free_irq(sonypi_device.irq, sonypi_irq);
release_region(sonypi_device.ioport1, sonypi_device.region_size); release_region(sonypi_device.ioport1, sonypi_device.region_size);
misc_deregister(&sonypi_misc_device);
if (sonypi_device.dev) if (sonypi_device.dev) {
pci_disable_device(sonypi_device.dev); pci_disable_device(sonypi_device.dev);
kfifo_free(sonypi_device.fifo);
pci_dev_put(sonypi_device.dev); pci_dev_put(sonypi_device.dev);
printk(KERN_INFO "sonypi: removed.\n"); }
kfifo_free(sonypi_device.fifo);
return 0;
}
#ifdef CONFIG_PM
static int old_camera_power;
static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
{
old_camera_power = sonypi_device.camera_power;
sonypi_disable();
return 0;
}
static int sonypi_resume(struct platform_device *dev)
{
sonypi_enable(old_camera_power);
return 0;
}
#else
#define sonypi_suspend NULL
#define sonypi_resume NULL
#endif
static void sonypi_shutdown(struct platform_device *dev)
{
sonypi_disable();
} }
static struct platform_driver sonypi_driver = {
.driver = {
.name = "sonypi",
.owner = THIS_MODULE,
},
.probe = sonypi_probe,
.remove = __devexit_p(sonypi_remove),
.shutdown = sonypi_shutdown,
.suspend = sonypi_suspend,
.resume = sonypi_resume,
};
static struct platform_device *sonypi_platform_device;
static struct dmi_system_id __initdata sonypi_dmi_table[] = { static struct dmi_system_id __initdata sonypi_dmi_table[] = {
{ {
.ident = "Sony Vaio", .ident = "Sony Vaio",
...@@ -1451,26 +1488,43 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = { ...@@ -1451,26 +1488,43 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = {
static int __init sonypi_init(void) static int __init sonypi_init(void)
{ {
int ret; int error;
printk(KERN_INFO
"sonypi: Sony Programmable I/O Controller Driver v%s.\n",
SONYPI_DRIVER_VERSION);
if (!dmi_check_system(sonypi_dmi_table)) if (!dmi_check_system(sonypi_dmi_table))
return -ENODEV; return -ENODEV;
ret = platform_driver_register(&sonypi_driver); error = platform_driver_register(&sonypi_driver);
if (ret) if (error)
return ret; return error;
ret = sonypi_probe(); sonypi_platform_device = platform_device_alloc("sonypi", -1);
if (ret) if (!sonypi_platform_device) {
platform_driver_unregister(&sonypi_driver); error = -ENOMEM;
goto err_driver_unregister;
}
return ret; error = platform_device_add(sonypi_platform_device);
if (error)
goto err_free_device;
return 0;
err_free_device:
platform_device_put(sonypi_platform_device);
err_driver_unregister:
platform_driver_unregister(&sonypi_driver);
return error;
} }
static void __exit sonypi_exit(void) static void __exit sonypi_exit(void)
{ {
platform_device_unregister(sonypi_platform_device);
platform_driver_unregister(&sonypi_driver); platform_driver_unregister(&sonypi_driver);
sonypi_remove(); printk(KERN_INFO "sonypi: removed.\n");
} }
module_init(sonypi_init); module_init(sonypi_init);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment