diff options
Diffstat (limited to 'drivers/char/sonypi.c')
-rw-r--r-- | drivers/char/sonypi.c | 381 |
1 files changed, 240 insertions, 141 deletions
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 51a07370e636..f8dd8527c6aa 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
@@ -471,7 +471,6 @@ struct sonypi_keypress { | |||
471 | 471 | ||
472 | static struct sonypi_device { | 472 | static struct sonypi_device { |
473 | struct pci_dev *dev; | 473 | struct pci_dev *dev; |
474 | struct platform_device *pdev; | ||
475 | u16 irq; | 474 | u16 irq; |
476 | u16 bits; | 475 | u16 bits; |
477 | u16 ioport1; | 476 | u16 ioport1; |
@@ -511,6 +510,11 @@ static struct sonypi_device { | |||
511 | #define SONYPI_ACPI_ACTIVE 0 | 510 | #define SONYPI_ACPI_ACTIVE 0 |
512 | #endif /* CONFIG_ACPI */ | 511 | #endif /* CONFIG_ACPI */ |
513 | 512 | ||
513 | #ifdef CONFIG_ACPI | ||
514 | static struct acpi_device *sonypi_acpi_device; | ||
515 | static int acpi_enabled; | ||
516 | #endif | ||
517 | |||
514 | static int sonypi_ec_write(u8 addr, u8 value) | 518 | static int sonypi_ec_write(u8 addr, u8 value) |
515 | { | 519 | { |
516 | #ifdef CONFIG_ACPI_EC | 520 | #ifdef CONFIG_ACPI_EC |
@@ -864,6 +868,11 @@ found: | |||
864 | if (useinput) | 868 | if (useinput) |
865 | sonypi_report_input_event(event); | 869 | sonypi_report_input_event(event); |
866 | 870 | ||
871 | #ifdef CONFIG_ACPI | ||
872 | if (acpi_enabled) | ||
873 | acpi_bus_generate_event(sonypi_acpi_device, 1, event); | ||
874 | #endif | ||
875 | |||
867 | kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); | 876 | kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); |
868 | kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); | 877 | kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); |
869 | wake_up_interruptible(&sonypi_device.fifo_proc_list); | 878 | wake_up_interruptible(&sonypi_device.fifo_proc_list); |
@@ -1165,45 +1174,38 @@ static int sonypi_disable(void) | |||
1165 | return 0; | 1174 | return 0; |
1166 | } | 1175 | } |
1167 | 1176 | ||
1168 | #ifdef CONFIG_PM | 1177 | #ifdef CONFIG_ACPI |
1169 | static int old_camera_power; | 1178 | static int sonypi_acpi_add(struct acpi_device *device) |
1170 | |||
1171 | static int sonypi_suspend(struct platform_device *dev, pm_message_t state) | ||
1172 | { | 1179 | { |
1173 | old_camera_power = sonypi_device.camera_power; | 1180 | sonypi_acpi_device = device; |
1174 | sonypi_disable(); | 1181 | strcpy(acpi_device_name(device), "Sony laptop hotkeys"); |
1175 | 1182 | strcpy(acpi_device_class(device), "sony/hotkey"); | |
1176 | return 0; | 1183 | return 0; |
1177 | } | 1184 | } |
1178 | 1185 | ||
1179 | static int sonypi_resume(struct platform_device *dev) | 1186 | static int sonypi_acpi_remove(struct acpi_device *device, int type) |
1180 | { | 1187 | { |
1181 | sonypi_enable(old_camera_power); | 1188 | sonypi_acpi_device = NULL; |
1182 | return 0; | 1189 | return 0; |
1183 | } | 1190 | } |
1184 | #endif | ||
1185 | |||
1186 | static void sonypi_shutdown(struct platform_device *dev) | ||
1187 | { | ||
1188 | sonypi_disable(); | ||
1189 | } | ||
1190 | 1191 | ||
1191 | static struct platform_driver sonypi_driver = { | 1192 | static struct acpi_driver sonypi_acpi_driver = { |
1192 | #ifdef CONFIG_PM | 1193 | .name = "sonypi", |
1193 | .suspend = sonypi_suspend, | 1194 | .class = "hkey", |
1194 | .resume = sonypi_resume, | 1195 | .ids = "SNY6001", |
1195 | #endif | 1196 | .ops = { |
1196 | .shutdown = sonypi_shutdown, | 1197 | .add = sonypi_acpi_add, |
1197 | .driver = { | 1198 | .remove = sonypi_acpi_remove, |
1198 | .name = "sonypi", | ||
1199 | }, | 1199 | }, |
1200 | }; | 1200 | }; |
1201 | #endif | ||
1201 | 1202 | ||
1202 | static int __devinit sonypi_create_input_devices(void) | 1203 | static int __devinit sonypi_create_input_devices(void) |
1203 | { | 1204 | { |
1204 | struct input_dev *jog_dev; | 1205 | struct input_dev *jog_dev; |
1205 | struct input_dev *key_dev; | 1206 | struct input_dev *key_dev; |
1206 | int i; | 1207 | int i; |
1208 | int error; | ||
1207 | 1209 | ||
1208 | sonypi_device.input_jog_dev = jog_dev = input_allocate_device(); | 1210 | sonypi_device.input_jog_dev = jog_dev = input_allocate_device(); |
1209 | if (!jog_dev) | 1211 | if (!jog_dev) |
@@ -1219,9 +1221,8 @@ static int __devinit sonypi_create_input_devices(void) | |||
1219 | 1221 | ||
1220 | sonypi_device.input_key_dev = key_dev = input_allocate_device(); | 1222 | sonypi_device.input_key_dev = key_dev = input_allocate_device(); |
1221 | if (!key_dev) { | 1223 | if (!key_dev) { |
1222 | input_free_device(jog_dev); | 1224 | error = -ENOMEM; |
1223 | sonypi_device.input_jog_dev = NULL; | 1225 | goto err_free_jogdev; |
1224 | return -ENOMEM; | ||
1225 | } | 1226 | } |
1226 | 1227 | ||
1227 | key_dev->name = "Sony Vaio Keys"; | 1228 | key_dev->name = "Sony Vaio Keys"; |
@@ -1234,56 +1235,122 @@ static int __devinit sonypi_create_input_devices(void) | |||
1234 | if (sonypi_inputkeys[i].inputev) | 1235 | if (sonypi_inputkeys[i].inputev) |
1235 | set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit); | 1236 | set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit); |
1236 | 1237 | ||
1237 | input_register_device(jog_dev); | 1238 | error = input_register_device(jog_dev); |
1238 | input_register_device(key_dev); | 1239 | if (error) |
1240 | goto err_free_keydev; | ||
1241 | |||
1242 | error = input_register_device(key_dev); | ||
1243 | if (error) | ||
1244 | goto err_unregister_jogdev; | ||
1239 | 1245 | ||
1240 | return 0; | 1246 | return 0; |
1247 | |||
1248 | err_unregister_jogdev: | ||
1249 | input_unregister_device(jog_dev); | ||
1250 | /* Set to NULL so we don't free it again below */ | ||
1251 | jog_dev = NULL; | ||
1252 | err_free_keydev: | ||
1253 | input_free_device(key_dev); | ||
1254 | sonypi_device.input_key_dev = NULL; | ||
1255 | err_free_jogdev: | ||
1256 | input_free_device(jog_dev); | ||
1257 | sonypi_device.input_jog_dev = NULL; | ||
1258 | |||
1259 | return error; | ||
1241 | } | 1260 | } |
1242 | 1261 | ||
1243 | static int __devinit sonypi_probe(void) | 1262 | static int __devinit sonypi_setup_ioports(struct sonypi_device *dev, |
1263 | const struct sonypi_ioport_list *ioport_list) | ||
1244 | { | 1264 | { |
1245 | int i, ret; | 1265 | while (ioport_list->port1) { |
1246 | struct sonypi_ioport_list *ioport_list; | ||
1247 | struct sonypi_irq_list *irq_list; | ||
1248 | struct pci_dev *pcidev; | ||
1249 | 1266 | ||
1250 | if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1267 | if (request_region(ioport_list->port1, |
1251 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) | 1268 | sonypi_device.region_size, |
1252 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; | 1269 | "Sony Programable I/O Device")) { |
1253 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1270 | dev->ioport1 = ioport_list->port1; |
1254 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) | 1271 | dev->ioport2 = ioport_list->port2; |
1255 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; | 1272 | return 0; |
1256 | else | 1273 | } |
1257 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; | 1274 | ioport_list++; |
1275 | } | ||
1258 | 1276 | ||
1259 | sonypi_device.dev = pcidev; | 1277 | return -EBUSY; |
1278 | } | ||
1279 | |||
1280 | static int __devinit sonypi_setup_irq(struct sonypi_device *dev, | ||
1281 | const struct sonypi_irq_list *irq_list) | ||
1282 | { | ||
1283 | while (irq_list->irq) { | ||
1284 | |||
1285 | if (!request_irq(irq_list->irq, sonypi_irq, | ||
1286 | SA_SHIRQ, "sonypi", sonypi_irq)) { | ||
1287 | dev->irq = irq_list->irq; | ||
1288 | dev->bits = irq_list->bits; | ||
1289 | return 0; | ||
1290 | } | ||
1291 | irq_list++; | ||
1292 | } | ||
1293 | |||
1294 | return -EBUSY; | ||
1295 | } | ||
1296 | |||
1297 | static void __devinit sonypi_display_info(void) | ||
1298 | { | ||
1299 | printk(KERN_INFO "sonypi: detected type%d model, " | ||
1300 | "verbose = %d, fnkeyinit = %s, camera = %s, " | ||
1301 | "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", | ||
1302 | sonypi_device.model, | ||
1303 | verbose, | ||
1304 | fnkeyinit ? "on" : "off", | ||
1305 | camera ? "on" : "off", | ||
1306 | compat ? "on" : "off", | ||
1307 | mask, | ||
1308 | useinput ? "on" : "off", | ||
1309 | SONYPI_ACPI_ACTIVE ? "on" : "off"); | ||
1310 | printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n", | ||
1311 | sonypi_device.irq, | ||
1312 | sonypi_device.ioport1, sonypi_device.ioport2); | ||
1313 | |||
1314 | if (minor == -1) | ||
1315 | printk(KERN_INFO "sonypi: device allocated minor is %d\n", | ||
1316 | sonypi_misc_device.minor); | ||
1317 | } | ||
1318 | |||
1319 | static int __devinit sonypi_probe(struct platform_device *dev) | ||
1320 | { | ||
1321 | const struct sonypi_ioport_list *ioport_list; | ||
1322 | const struct sonypi_irq_list *irq_list; | ||
1323 | struct pci_dev *pcidev; | ||
1324 | int error; | ||
1260 | 1325 | ||
1261 | spin_lock_init(&sonypi_device.fifo_lock); | 1326 | spin_lock_init(&sonypi_device.fifo_lock); |
1262 | sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, | 1327 | sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, |
1263 | &sonypi_device.fifo_lock); | 1328 | &sonypi_device.fifo_lock); |
1264 | if (IS_ERR(sonypi_device.fifo)) { | 1329 | if (IS_ERR(sonypi_device.fifo)) { |
1265 | printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); | 1330 | printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); |
1266 | ret = PTR_ERR(sonypi_device.fifo); | 1331 | return PTR_ERR(sonypi_device.fifo); |
1267 | goto out_fifo; | ||
1268 | } | 1332 | } |
1269 | 1333 | ||
1270 | init_waitqueue_head(&sonypi_device.fifo_proc_list); | 1334 | init_waitqueue_head(&sonypi_device.fifo_proc_list); |
1271 | init_MUTEX(&sonypi_device.lock); | 1335 | init_MUTEX(&sonypi_device.lock); |
1272 | sonypi_device.bluetooth_power = -1; | 1336 | sonypi_device.bluetooth_power = -1; |
1273 | 1337 | ||
1338 | if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1339 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) | ||
1340 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; | ||
1341 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1342 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) | ||
1343 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; | ||
1344 | else | ||
1345 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; | ||
1346 | |||
1274 | if (pcidev && pci_enable_device(pcidev)) { | 1347 | if (pcidev && pci_enable_device(pcidev)) { |
1275 | printk(KERN_ERR "sonypi: pci_enable_device failed\n"); | 1348 | printk(KERN_ERR "sonypi: pci_enable_device failed\n"); |
1276 | ret = -EIO; | 1349 | error = -EIO; |
1277 | goto out_pcienable; | 1350 | goto err_put_pcidev; |
1278 | } | ||
1279 | |||
1280 | if (minor != -1) | ||
1281 | sonypi_misc_device.minor = minor; | ||
1282 | if ((ret = misc_register(&sonypi_misc_device))) { | ||
1283 | printk(KERN_ERR "sonypi: misc_register failed\n"); | ||
1284 | goto out_miscreg; | ||
1285 | } | 1351 | } |
1286 | 1352 | ||
1353 | sonypi_device.dev = pcidev; | ||
1287 | 1354 | ||
1288 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) { | 1355 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) { |
1289 | ioport_list = sonypi_type1_ioport_list; | 1356 | ioport_list = sonypi_type1_ioport_list; |
@@ -1302,43 +1369,36 @@ static int __devinit sonypi_probe(void) | |||
1302 | irq_list = sonypi_type3_irq_list; | 1369 | irq_list = sonypi_type3_irq_list; |
1303 | } | 1370 | } |
1304 | 1371 | ||
1305 | for (i = 0; ioport_list[i].port1; i++) { | 1372 | error = sonypi_setup_ioports(&sonypi_device, ioport_list); |
1306 | if (request_region(ioport_list[i].port1, | 1373 | if (error) { |
1307 | sonypi_device.region_size, | 1374 | printk(KERN_ERR "sonypi: failed to request ioports\n"); |
1308 | "Sony Programable I/O Device")) { | 1375 | goto err_disable_pcidev; |
1309 | /* get the ioport */ | ||
1310 | sonypi_device.ioport1 = ioport_list[i].port1; | ||
1311 | sonypi_device.ioport2 = ioport_list[i].port2; | ||
1312 | break; | ||
1313 | } | ||
1314 | } | ||
1315 | if (!sonypi_device.ioport1) { | ||
1316 | printk(KERN_ERR "sonypi: request_region failed\n"); | ||
1317 | ret = -ENODEV; | ||
1318 | goto out_reqreg; | ||
1319 | } | 1376 | } |
1320 | 1377 | ||
1321 | for (i = 0; irq_list[i].irq; i++) { | 1378 | error = sonypi_setup_irq(&sonypi_device, irq_list); |
1322 | 1379 | if (error) { | |
1323 | sonypi_device.irq = irq_list[i].irq; | 1380 | printk(KERN_ERR "sonypi: request_irq failed\n"); |
1324 | sonypi_device.bits = irq_list[i].bits; | 1381 | goto err_free_ioports; |
1325 | |||
1326 | if (!request_irq(sonypi_device.irq, sonypi_irq, | ||
1327 | SA_SHIRQ, "sonypi", sonypi_irq)) | ||
1328 | break; | ||
1329 | } | 1382 | } |
1330 | 1383 | ||
1331 | if (!irq_list[i].irq) { | 1384 | if (minor != -1) |
1332 | printk(KERN_ERR "sonypi: request_irq failed\n"); | 1385 | sonypi_misc_device.minor = minor; |
1333 | ret = -ENODEV; | 1386 | error = misc_register(&sonypi_misc_device); |
1334 | goto out_reqirq; | 1387 | if (error) { |
1388 | printk(KERN_ERR "sonypi: misc_register failed\n"); | ||
1389 | goto err_free_irq; | ||
1335 | } | 1390 | } |
1336 | 1391 | ||
1392 | sonypi_display_info(); | ||
1393 | |||
1337 | if (useinput) { | 1394 | if (useinput) { |
1338 | 1395 | ||
1339 | ret = sonypi_create_input_devices(); | 1396 | error = sonypi_create_input_devices(); |
1340 | if (ret) | 1397 | if (error) { |
1341 | goto out_inputdevices; | 1398 | printk(KERN_ERR |
1399 | "sonypi: failed to create input devices\n"); | ||
1400 | goto err_miscdev_unregister; | ||
1401 | } | ||
1342 | 1402 | ||
1343 | spin_lock_init(&sonypi_device.input_fifo_lock); | 1403 | spin_lock_init(&sonypi_device.input_fifo_lock); |
1344 | sonypi_device.input_fifo = | 1404 | sonypi_device.input_fifo = |
@@ -1346,91 +1406,104 @@ static int __devinit sonypi_probe(void) | |||
1346 | &sonypi_device.input_fifo_lock); | 1406 | &sonypi_device.input_fifo_lock); |
1347 | if (IS_ERR(sonypi_device.input_fifo)) { | 1407 | if (IS_ERR(sonypi_device.input_fifo)) { |
1348 | printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); | 1408 | printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); |
1349 | ret = PTR_ERR(sonypi_device.input_fifo); | 1409 | error = PTR_ERR(sonypi_device.input_fifo); |
1350 | goto out_infifo; | 1410 | goto err_inpdev_unregister; |
1351 | } | 1411 | } |
1352 | 1412 | ||
1353 | INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); | 1413 | INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); |
1354 | } | 1414 | } |
1355 | 1415 | ||
1356 | sonypi_device.pdev = platform_device_register_simple("sonypi", -1, | ||
1357 | NULL, 0); | ||
1358 | if (IS_ERR(sonypi_device.pdev)) { | ||
1359 | ret = PTR_ERR(sonypi_device.pdev); | ||
1360 | goto out_platformdev; | ||
1361 | } | ||
1362 | |||
1363 | sonypi_enable(0); | 1416 | sonypi_enable(0); |
1364 | 1417 | ||
1365 | printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver" | ||
1366 | "v%s.\n", SONYPI_DRIVER_VERSION); | ||
1367 | printk(KERN_INFO "sonypi: detected type%d model, " | ||
1368 | "verbose = %d, fnkeyinit = %s, camera = %s, " | ||
1369 | "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", | ||
1370 | sonypi_device.model, | ||
1371 | verbose, | ||
1372 | fnkeyinit ? "on" : "off", | ||
1373 | camera ? "on" : "off", | ||
1374 | compat ? "on" : "off", | ||
1375 | mask, | ||
1376 | useinput ? "on" : "off", | ||
1377 | SONYPI_ACPI_ACTIVE ? "on" : "off"); | ||
1378 | printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n", | ||
1379 | sonypi_device.irq, | ||
1380 | sonypi_device.ioport1, sonypi_device.ioport2); | ||
1381 | |||
1382 | if (minor == -1) | ||
1383 | printk(KERN_INFO "sonypi: device allocated minor is %d\n", | ||
1384 | sonypi_misc_device.minor); | ||
1385 | |||
1386 | return 0; | 1418 | return 0; |
1387 | 1419 | ||
1388 | out_platformdev: | 1420 | err_inpdev_unregister: |
1389 | kfifo_free(sonypi_device.input_fifo); | ||
1390 | out_infifo: | ||
1391 | input_unregister_device(sonypi_device.input_key_dev); | 1421 | input_unregister_device(sonypi_device.input_key_dev); |
1392 | input_unregister_device(sonypi_device.input_jog_dev); | 1422 | input_unregister_device(sonypi_device.input_jog_dev); |
1393 | out_inputdevices: | 1423 | err_miscdev_unregister: |
1424 | misc_deregister(&sonypi_misc_device); | ||
1425 | err_free_irq: | ||
1394 | free_irq(sonypi_device.irq, sonypi_irq); | 1426 | free_irq(sonypi_device.irq, sonypi_irq); |
1395 | out_reqirq: | 1427 | err_free_ioports: |
1396 | release_region(sonypi_device.ioport1, sonypi_device.region_size); | 1428 | release_region(sonypi_device.ioport1, sonypi_device.region_size); |
1397 | out_reqreg: | 1429 | err_disable_pcidev: |
1398 | misc_deregister(&sonypi_misc_device); | ||
1399 | out_miscreg: | ||
1400 | if (pcidev) | 1430 | if (pcidev) |
1401 | pci_disable_device(pcidev); | 1431 | pci_disable_device(pcidev); |
1402 | out_pcienable: | 1432 | err_put_pcidev: |
1433 | pci_dev_put(pcidev); | ||
1403 | kfifo_free(sonypi_device.fifo); | 1434 | kfifo_free(sonypi_device.fifo); |
1404 | out_fifo: | 1435 | |
1405 | pci_dev_put(sonypi_device.dev); | 1436 | return error; |
1406 | return ret; | ||
1407 | } | 1437 | } |
1408 | 1438 | ||
1409 | static void __devexit sonypi_remove(void) | 1439 | static int __devexit sonypi_remove(struct platform_device *dev) |
1410 | { | 1440 | { |
1411 | sonypi_disable(); | 1441 | sonypi_disable(); |
1412 | 1442 | ||
1413 | synchronize_sched(); /* Allow sonypi interrupt to complete. */ | 1443 | synchronize_sched(); /* Allow sonypi interrupt to complete. */ |
1414 | flush_scheduled_work(); | 1444 | flush_scheduled_work(); |
1415 | 1445 | ||
1416 | platform_device_unregister(sonypi_device.pdev); | ||
1417 | |||
1418 | if (useinput) { | 1446 | if (useinput) { |
1419 | input_unregister_device(sonypi_device.input_key_dev); | 1447 | input_unregister_device(sonypi_device.input_key_dev); |
1420 | input_unregister_device(sonypi_device.input_jog_dev); | 1448 | input_unregister_device(sonypi_device.input_jog_dev); |
1421 | kfifo_free(sonypi_device.input_fifo); | 1449 | kfifo_free(sonypi_device.input_fifo); |
1422 | } | 1450 | } |
1423 | 1451 | ||
1452 | misc_deregister(&sonypi_misc_device); | ||
1453 | |||
1424 | free_irq(sonypi_device.irq, sonypi_irq); | 1454 | free_irq(sonypi_device.irq, sonypi_irq); |
1425 | release_region(sonypi_device.ioport1, sonypi_device.region_size); | 1455 | release_region(sonypi_device.ioport1, sonypi_device.region_size); |
1426 | misc_deregister(&sonypi_misc_device); | 1456 | |
1427 | if (sonypi_device.dev) | 1457 | if (sonypi_device.dev) { |
1428 | pci_disable_device(sonypi_device.dev); | 1458 | pci_disable_device(sonypi_device.dev); |
1459 | pci_dev_put(sonypi_device.dev); | ||
1460 | } | ||
1461 | |||
1429 | kfifo_free(sonypi_device.fifo); | 1462 | kfifo_free(sonypi_device.fifo); |
1430 | pci_dev_put(sonypi_device.dev); | 1463 | |
1431 | printk(KERN_INFO "sonypi: removed.\n"); | 1464 | return 0; |
1432 | } | 1465 | } |
1433 | 1466 | ||
1467 | #ifdef CONFIG_PM | ||
1468 | static int old_camera_power; | ||
1469 | |||
1470 | static int sonypi_suspend(struct platform_device *dev, pm_message_t state) | ||
1471 | { | ||
1472 | old_camera_power = sonypi_device.camera_power; | ||
1473 | sonypi_disable(); | ||
1474 | |||
1475 | return 0; | ||
1476 | } | ||
1477 | |||
1478 | static int sonypi_resume(struct platform_device *dev) | ||
1479 | { | ||
1480 | sonypi_enable(old_camera_power); | ||
1481 | return 0; | ||
1482 | } | ||
1483 | #else | ||
1484 | #define sonypi_suspend NULL | ||
1485 | #define sonypi_resume NULL | ||
1486 | #endif | ||
1487 | |||
1488 | static void sonypi_shutdown(struct platform_device *dev) | ||
1489 | { | ||
1490 | sonypi_disable(); | ||
1491 | } | ||
1492 | |||
1493 | static struct platform_driver sonypi_driver = { | ||
1494 | .driver = { | ||
1495 | .name = "sonypi", | ||
1496 | .owner = THIS_MODULE, | ||
1497 | }, | ||
1498 | .probe = sonypi_probe, | ||
1499 | .remove = __devexit_p(sonypi_remove), | ||
1500 | .shutdown = sonypi_shutdown, | ||
1501 | .suspend = sonypi_suspend, | ||
1502 | .resume = sonypi_resume, | ||
1503 | }; | ||
1504 | |||
1505 | static struct platform_device *sonypi_platform_device; | ||
1506 | |||
1434 | static struct dmi_system_id __initdata sonypi_dmi_table[] = { | 1507 | static struct dmi_system_id __initdata sonypi_dmi_table[] = { |
1435 | { | 1508 | { |
1436 | .ident = "Sony Vaio", | 1509 | .ident = "Sony Vaio", |
@@ -1451,26 +1524,52 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = { | |||
1451 | 1524 | ||
1452 | static int __init sonypi_init(void) | 1525 | static int __init sonypi_init(void) |
1453 | { | 1526 | { |
1454 | int ret; | 1527 | int error; |
1528 | |||
1529 | printk(KERN_INFO | ||
1530 | "sonypi: Sony Programmable I/O Controller Driver v%s.\n", | ||
1531 | SONYPI_DRIVER_VERSION); | ||
1455 | 1532 | ||
1456 | if (!dmi_check_system(sonypi_dmi_table)) | 1533 | if (!dmi_check_system(sonypi_dmi_table)) |
1457 | return -ENODEV; | 1534 | return -ENODEV; |
1458 | 1535 | ||
1459 | ret = platform_driver_register(&sonypi_driver); | 1536 | error = platform_driver_register(&sonypi_driver); |
1460 | if (ret) | 1537 | if (error) |
1461 | return ret; | 1538 | return error; |
1462 | 1539 | ||
1463 | ret = sonypi_probe(); | 1540 | sonypi_platform_device = platform_device_alloc("sonypi", -1); |
1464 | if (ret) | 1541 | if (!sonypi_platform_device) { |
1465 | platform_driver_unregister(&sonypi_driver); | 1542 | error = -ENOMEM; |
1543 | goto err_driver_unregister; | ||
1544 | } | ||
1466 | 1545 | ||
1467 | return ret; | 1546 | error = platform_device_add(sonypi_platform_device); |
1547 | if (error) | ||
1548 | goto err_free_device; | ||
1549 | |||
1550 | #ifdef CONFIG_ACPI | ||
1551 | if (acpi_bus_register_driver(&sonypi_acpi_driver) > 0) | ||
1552 | acpi_enabled = 1; | ||
1553 | #endif | ||
1554 | |||
1555 | return 0; | ||
1556 | |||
1557 | err_free_device: | ||
1558 | platform_device_put(sonypi_platform_device); | ||
1559 | err_driver_unregister: | ||
1560 | platform_driver_unregister(&sonypi_driver); | ||
1561 | return error; | ||
1468 | } | 1562 | } |
1469 | 1563 | ||
1470 | static void __exit sonypi_exit(void) | 1564 | static void __exit sonypi_exit(void) |
1471 | { | 1565 | { |
1566 | #ifdef CONFIG_ACPI | ||
1567 | if (acpi_enabled) | ||
1568 | acpi_bus_unregister_driver(&sonypi_acpi_driver); | ||
1569 | #endif | ||
1570 | platform_device_unregister(sonypi_platform_device); | ||
1472 | platform_driver_unregister(&sonypi_driver); | 1571 | platform_driver_unregister(&sonypi_driver); |
1473 | sonypi_remove(); | 1572 | printk(KERN_INFO "sonypi: removed.\n"); |
1474 | } | 1573 | } |
1475 | 1574 | ||
1476 | module_init(sonypi_init); | 1575 | module_init(sonypi_init); |