aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/sonypi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/sonypi.c')
-rw-r--r--drivers/char/sonypi.c358
1 files changed, 206 insertions, 152 deletions
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 51a07370e636..6a9e23dc4897 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -471,7 +471,6 @@ struct sonypi_keypress {
471 471
472static struct sonypi_device { 472static 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;
@@ -1165,45 +1164,12 @@ static int sonypi_disable(void)
1165 return 0; 1164 return 0;
1166} 1165}
1167 1166
1168#ifdef CONFIG_PM
1169static int old_camera_power;
1170
1171static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
1172{
1173 old_camera_power = sonypi_device.camera_power;
1174 sonypi_disable();
1175
1176 return 0;
1177}
1178
1179static int sonypi_resume(struct platform_device *dev)
1180{
1181 sonypi_enable(old_camera_power);
1182 return 0;
1183}
1184#endif
1185
1186static void sonypi_shutdown(struct platform_device *dev)
1187{
1188 sonypi_disable();
1189}
1190
1191static struct platform_driver sonypi_driver = {
1192#ifdef CONFIG_PM
1193 .suspend = sonypi_suspend,
1194 .resume = sonypi_resume,
1195#endif
1196 .shutdown = sonypi_shutdown,
1197 .driver = {
1198 .name = "sonypi",
1199 },
1200};
1201
1202static int __devinit sonypi_create_input_devices(void) 1167static int __devinit sonypi_create_input_devices(void)
1203{ 1168{
1204 struct input_dev *jog_dev; 1169 struct input_dev *jog_dev;
1205 struct input_dev *key_dev; 1170 struct input_dev *key_dev;
1206 int i; 1171 int i;
1172 int error;
1207 1173
1208 sonypi_device.input_jog_dev = jog_dev = input_allocate_device(); 1174 sonypi_device.input_jog_dev = jog_dev = input_allocate_device();
1209 if (!jog_dev) 1175 if (!jog_dev)
@@ -1219,9 +1185,8 @@ static int __devinit sonypi_create_input_devices(void)
1219 1185
1220 sonypi_device.input_key_dev = key_dev = input_allocate_device(); 1186 sonypi_device.input_key_dev = key_dev = input_allocate_device();
1221 if (!key_dev) { 1187 if (!key_dev) {
1222 input_free_device(jog_dev); 1188 error = -ENOMEM;
1223 sonypi_device.input_jog_dev = NULL; 1189 goto err_free_jogdev;
1224 return -ENOMEM;
1225 } 1190 }
1226 1191
1227 key_dev->name = "Sony Vaio Keys"; 1192 key_dev->name = "Sony Vaio Keys";
@@ -1234,56 +1199,122 @@ static int __devinit sonypi_create_input_devices(void)
1234 if (sonypi_inputkeys[i].inputev) 1199 if (sonypi_inputkeys[i].inputev)
1235 set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit); 1200 set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit);
1236 1201
1237 input_register_device(jog_dev); 1202 error = input_register_device(jog_dev);
1238 input_register_device(key_dev); 1203 if (error)
1204 goto err_free_keydev;
1205
1206 error = input_register_device(key_dev);
1207 if (error)
1208 goto err_unregister_jogdev;
1239 1209
1240 return 0; 1210 return 0;
1211
1212 err_unregister_jogdev:
1213 input_unregister_device(jog_dev);
1214 /* Set to NULL so we don't free it again below */
1215 jog_dev = NULL;
1216 err_free_keydev:
1217 input_free_device(key_dev);
1218 sonypi_device.input_key_dev = NULL;
1219 err_free_jogdev:
1220 input_free_device(jog_dev);
1221 sonypi_device.input_jog_dev = NULL;
1222
1223 return error;
1241} 1224}
1242 1225
1243static int __devinit sonypi_probe(void) 1226static int __devinit sonypi_setup_ioports(struct sonypi_device *dev,
1227 const struct sonypi_ioport_list *ioport_list)
1244{ 1228{
1245 int i, ret; 1229 while (ioport_list->port1) {
1246 struct sonypi_ioport_list *ioport_list;
1247 struct sonypi_irq_list *irq_list;
1248 struct pci_dev *pcidev;
1249 1230
1250 if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1231 if (request_region(ioport_list->port1,
1251 PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) 1232 sonypi_device.region_size,
1252 sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; 1233 "Sony Programable I/O Device")) {
1253 else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1234 dev->ioport1 = ioport_list->port1;
1254 PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) 1235 dev->ioport2 = ioport_list->port2;
1255 sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; 1236 return 0;
1256 else 1237 }
1257 sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; 1238 ioport_list++;
1239 }
1258 1240
1259 sonypi_device.dev = pcidev; 1241 return -EBUSY;
1242}
1243
1244static int __devinit sonypi_setup_irq(struct sonypi_device *dev,
1245 const struct sonypi_irq_list *irq_list)
1246{
1247 while (irq_list->irq) {
1248
1249 if (!request_irq(irq_list->irq, sonypi_irq,
1250 SA_SHIRQ, "sonypi", sonypi_irq)) {
1251 dev->irq = irq_list->irq;
1252 dev->bits = irq_list->bits;
1253 return 0;
1254 }
1255 irq_list++;
1256 }
1257
1258 return -EBUSY;
1259}
1260
1261static void __devinit sonypi_display_info(void)
1262{
1263 printk(KERN_INFO "sonypi: detected type%d model, "
1264 "verbose = %d, fnkeyinit = %s, camera = %s, "
1265 "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n",
1266 sonypi_device.model,
1267 verbose,
1268 fnkeyinit ? "on" : "off",
1269 camera ? "on" : "off",
1270 compat ? "on" : "off",
1271 mask,
1272 useinput ? "on" : "off",
1273 SONYPI_ACPI_ACTIVE ? "on" : "off");
1274 printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n",
1275 sonypi_device.irq,
1276 sonypi_device.ioport1, sonypi_device.ioport2);
1277
1278 if (minor == -1)
1279 printk(KERN_INFO "sonypi: device allocated minor is %d\n",
1280 sonypi_misc_device.minor);
1281}
1282
1283static int __devinit sonypi_probe(struct platform_device *dev)
1284{
1285 const struct sonypi_ioport_list *ioport_list;
1286 const struct sonypi_irq_list *irq_list;
1287 struct pci_dev *pcidev;
1288 int error;
1260 1289
1261 spin_lock_init(&sonypi_device.fifo_lock); 1290 spin_lock_init(&sonypi_device.fifo_lock);
1262 sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, 1291 sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL,
1263 &sonypi_device.fifo_lock); 1292 &sonypi_device.fifo_lock);
1264 if (IS_ERR(sonypi_device.fifo)) { 1293 if (IS_ERR(sonypi_device.fifo)) {
1265 printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); 1294 printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
1266 ret = PTR_ERR(sonypi_device.fifo); 1295 return PTR_ERR(sonypi_device.fifo);
1267 goto out_fifo;
1268 } 1296 }
1269 1297
1270 init_waitqueue_head(&sonypi_device.fifo_proc_list); 1298 init_waitqueue_head(&sonypi_device.fifo_proc_list);
1271 init_MUTEX(&sonypi_device.lock); 1299 init_MUTEX(&sonypi_device.lock);
1272 sonypi_device.bluetooth_power = -1; 1300 sonypi_device.bluetooth_power = -1;
1273 1301
1302 if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1303 PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
1304 sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1;
1305 else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1306 PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
1307 sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
1308 else
1309 sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
1310
1274 if (pcidev && pci_enable_device(pcidev)) { 1311 if (pcidev && pci_enable_device(pcidev)) {
1275 printk(KERN_ERR "sonypi: pci_enable_device failed\n"); 1312 printk(KERN_ERR "sonypi: pci_enable_device failed\n");
1276 ret = -EIO; 1313 error = -EIO;
1277 goto out_pcienable; 1314 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 } 1315 }
1286 1316
1317 sonypi_device.dev = pcidev;
1287 1318
1288 if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) { 1319 if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) {
1289 ioport_list = sonypi_type1_ioport_list; 1320 ioport_list = sonypi_type1_ioport_list;
@@ -1302,43 +1333,36 @@ static int __devinit sonypi_probe(void)
1302 irq_list = sonypi_type3_irq_list; 1333 irq_list = sonypi_type3_irq_list;
1303 } 1334 }
1304 1335
1305 for (i = 0; ioport_list[i].port1; i++) { 1336 error = sonypi_setup_ioports(&sonypi_device, ioport_list);
1306 if (request_region(ioport_list[i].port1, 1337 if (error) {
1307 sonypi_device.region_size, 1338 printk(KERN_ERR "sonypi: failed to request ioports\n");
1308 "Sony Programable I/O Device")) { 1339 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 } 1340 }
1320 1341
1321 for (i = 0; irq_list[i].irq; i++) { 1342 error = sonypi_setup_irq(&sonypi_device, irq_list);
1322 1343 if (error) {
1323 sonypi_device.irq = irq_list[i].irq; 1344 printk(KERN_ERR "sonypi: request_irq failed\n");
1324 sonypi_device.bits = irq_list[i].bits; 1345 goto err_free_ioports;
1325
1326 if (!request_irq(sonypi_device.irq, sonypi_irq,
1327 SA_SHIRQ, "sonypi", sonypi_irq))
1328 break;
1329 } 1346 }
1330 1347
1331 if (!irq_list[i].irq) { 1348 if (minor != -1)
1332 printk(KERN_ERR "sonypi: request_irq failed\n"); 1349 sonypi_misc_device.minor = minor;
1333 ret = -ENODEV; 1350 error = misc_register(&sonypi_misc_device);
1334 goto out_reqirq; 1351 if (error) {
1352 printk(KERN_ERR "sonypi: misc_register failed\n");
1353 goto err_free_irq;
1335 } 1354 }
1336 1355
1356 sonypi_display_info();
1357
1337 if (useinput) { 1358 if (useinput) {
1338 1359
1339 ret = sonypi_create_input_devices(); 1360 error = sonypi_create_input_devices();
1340 if (ret) 1361 if (error) {
1341 goto out_inputdevices; 1362 printk(KERN_ERR
1363 "sonypi: failed to create input devices\n");
1364 goto err_miscdev_unregister;
1365 }
1342 1366
1343 spin_lock_init(&sonypi_device.input_fifo_lock); 1367 spin_lock_init(&sonypi_device.input_fifo_lock);
1344 sonypi_device.input_fifo = 1368 sonypi_device.input_fifo =
@@ -1346,91 +1370,104 @@ static int __devinit sonypi_probe(void)
1346 &sonypi_device.input_fifo_lock); 1370 &sonypi_device.input_fifo_lock);
1347 if (IS_ERR(sonypi_device.input_fifo)) { 1371 if (IS_ERR(sonypi_device.input_fifo)) {
1348 printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); 1372 printk(KERN_ERR "sonypi: kfifo_alloc failed\n");
1349 ret = PTR_ERR(sonypi_device.input_fifo); 1373 error = PTR_ERR(sonypi_device.input_fifo);
1350 goto out_infifo; 1374 goto err_inpdev_unregister;
1351 } 1375 }
1352 1376
1353 INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); 1377 INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL);
1354 } 1378 }
1355 1379
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); 1380 sonypi_enable(0);
1364 1381
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; 1382 return 0;
1387 1383
1388out_platformdev: 1384 err_inpdev_unregister:
1389 kfifo_free(sonypi_device.input_fifo);
1390out_infifo:
1391 input_unregister_device(sonypi_device.input_key_dev); 1385 input_unregister_device(sonypi_device.input_key_dev);
1392 input_unregister_device(sonypi_device.input_jog_dev); 1386 input_unregister_device(sonypi_device.input_jog_dev);
1393out_inputdevices: 1387 err_miscdev_unregister:
1388 misc_deregister(&sonypi_misc_device);
1389 err_free_irq:
1394 free_irq(sonypi_device.irq, sonypi_irq); 1390 free_irq(sonypi_device.irq, sonypi_irq);
1395out_reqirq: 1391 err_free_ioports:
1396 release_region(sonypi_device.ioport1, sonypi_device.region_size); 1392 release_region(sonypi_device.ioport1, sonypi_device.region_size);
1397out_reqreg: 1393 err_disable_pcidev:
1398 misc_deregister(&sonypi_misc_device);
1399out_miscreg:
1400 if (pcidev) 1394 if (pcidev)
1401 pci_disable_device(pcidev); 1395 pci_disable_device(pcidev);
1402out_pcienable: 1396 err_put_pcidev:
1397 pci_dev_put(pcidev);
1403 kfifo_free(sonypi_device.fifo); 1398 kfifo_free(sonypi_device.fifo);
1404out_fifo: 1399
1405 pci_dev_put(sonypi_device.dev); 1400 return error;
1406 return ret;
1407} 1401}
1408 1402
1409static void __devexit sonypi_remove(void) 1403static int __devexit sonypi_remove(struct platform_device *dev)
1410{ 1404{
1411 sonypi_disable(); 1405 sonypi_disable();
1412 1406
1413 synchronize_sched(); /* Allow sonypi interrupt to complete. */ 1407 synchronize_sched(); /* Allow sonypi interrupt to complete. */
1414 flush_scheduled_work(); 1408 flush_scheduled_work();
1415 1409
1416 platform_device_unregister(sonypi_device.pdev);
1417
1418 if (useinput) { 1410 if (useinput) {
1419 input_unregister_device(sonypi_device.input_key_dev); 1411 input_unregister_device(sonypi_device.input_key_dev);
1420 input_unregister_device(sonypi_device.input_jog_dev); 1412 input_unregister_device(sonypi_device.input_jog_dev);
1421 kfifo_free(sonypi_device.input_fifo); 1413 kfifo_free(sonypi_device.input_fifo);
1422 } 1414 }
1423 1415
1416 misc_deregister(&sonypi_misc_device);
1417
1424 free_irq(sonypi_device.irq, sonypi_irq); 1418 free_irq(sonypi_device.irq, sonypi_irq);
1425 release_region(sonypi_device.ioport1, sonypi_device.region_size); 1419 release_region(sonypi_device.ioport1, sonypi_device.region_size);
1426 misc_deregister(&sonypi_misc_device); 1420
1427 if (sonypi_device.dev) 1421 if (sonypi_device.dev) {
1428 pci_disable_device(sonypi_device.dev); 1422 pci_disable_device(sonypi_device.dev);
1423 pci_dev_put(sonypi_device.dev);
1424 }
1425
1429 kfifo_free(sonypi_device.fifo); 1426 kfifo_free(sonypi_device.fifo);
1430 pci_dev_put(sonypi_device.dev); 1427
1431 printk(KERN_INFO "sonypi: removed.\n"); 1428 return 0;
1429}
1430
1431#ifdef CONFIG_PM
1432static int old_camera_power;
1433
1434static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
1435{
1436 old_camera_power = sonypi_device.camera_power;
1437 sonypi_disable();
1438
1439 return 0;
1440}
1441
1442static int sonypi_resume(struct platform_device *dev)
1443{
1444 sonypi_enable(old_camera_power);
1445 return 0;
1446}
1447#else
1448#define sonypi_suspend NULL
1449#define sonypi_resume NULL
1450#endif
1451
1452static void sonypi_shutdown(struct platform_device *dev)
1453{
1454 sonypi_disable();
1432} 1455}
1433 1456
1457static struct platform_driver sonypi_driver = {
1458 .driver = {
1459 .name = "sonypi",
1460 .owner = THIS_MODULE,
1461 },
1462 .probe = sonypi_probe,
1463 .remove = __devexit_p(sonypi_remove),
1464 .shutdown = sonypi_shutdown,
1465 .suspend = sonypi_suspend,
1466 .resume = sonypi_resume,
1467};
1468
1469static struct platform_device *sonypi_platform_device;
1470
1434static struct dmi_system_id __initdata sonypi_dmi_table[] = { 1471static struct dmi_system_id __initdata sonypi_dmi_table[] = {
1435 { 1472 {
1436 .ident = "Sony Vaio", 1473 .ident = "Sony Vaio",
@@ -1451,26 +1488,43 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = {
1451 1488
1452static int __init sonypi_init(void) 1489static int __init sonypi_init(void)
1453{ 1490{
1454 int ret; 1491 int error;
1492
1493 printk(KERN_INFO
1494 "sonypi: Sony Programmable I/O Controller Driver v%s.\n",
1495 SONYPI_DRIVER_VERSION);
1455 1496
1456 if (!dmi_check_system(sonypi_dmi_table)) 1497 if (!dmi_check_system(sonypi_dmi_table))
1457 return -ENODEV; 1498 return -ENODEV;
1458 1499
1459 ret = platform_driver_register(&sonypi_driver); 1500 error = platform_driver_register(&sonypi_driver);
1460 if (ret) 1501 if (error)
1461 return ret; 1502 return error;
1462 1503
1463 ret = sonypi_probe(); 1504 sonypi_platform_device = platform_device_alloc("sonypi", -1);
1464 if (ret) 1505 if (!sonypi_platform_device) {
1465 platform_driver_unregister(&sonypi_driver); 1506 error = -ENOMEM;
1507 goto err_driver_unregister;
1508 }
1466 1509
1467 return ret; 1510 error = platform_device_add(sonypi_platform_device);
1511 if (error)
1512 goto err_free_device;
1513
1514 return 0;
1515
1516 err_free_device:
1517 platform_device_put(sonypi_platform_device);
1518 err_driver_unregister:
1519 platform_driver_unregister(&sonypi_driver);
1520 return error;
1468} 1521}
1469 1522
1470static void __exit sonypi_exit(void) 1523static void __exit sonypi_exit(void)
1471{ 1524{
1525 platform_device_unregister(sonypi_platform_device);
1472 platform_driver_unregister(&sonypi_driver); 1526 platform_driver_unregister(&sonypi_driver);
1473 sonypi_remove(); 1527 printk(KERN_INFO "sonypi: removed.\n");
1474} 1528}
1475 1529
1476module_init(sonypi_init); 1530module_init(sonypi_init);