diff options
Diffstat (limited to 'drivers/media/video/via-camera.c')
-rw-r--r-- | drivers/media/video/via-camera.c | 147 |
1 files changed, 101 insertions, 46 deletions
diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c index 2f973cd56408..8c780c2d937b 100644 --- a/drivers/media/video/via-camera.c +++ b/drivers/media/video/via-camera.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/via-core.h> | 25 | #include <linux/via-core.h> |
26 | #include <linux/via-gpio.h> | 26 | #include <linux/via-gpio.h> |
27 | #include <linux/via_i2c.h> | 27 | #include <linux/via_i2c.h> |
28 | #include <asm/olpc.h> | ||
28 | 29 | ||
29 | #include "via-camera.h" | 30 | #include "via-camera.h" |
30 | 31 | ||
@@ -38,14 +39,12 @@ MODULE_PARM_DESC(flip_image, | |||
38 | "If set, the sensor will be instructed to flip the image " | 39 | "If set, the sensor will be instructed to flip the image " |
39 | "vertically."); | 40 | "vertically."); |
40 | 41 | ||
41 | #ifdef CONFIG_OLPC_XO_1_5 | ||
42 | static int override_serial; | 42 | static int override_serial; |
43 | module_param(override_serial, bool, 0444); | 43 | module_param(override_serial, bool, 0444); |
44 | MODULE_PARM_DESC(override_serial, | 44 | MODULE_PARM_DESC(override_serial, |
45 | "The camera driver will normally refuse to load if " | 45 | "The camera driver will normally refuse to load if " |
46 | "the XO 1.5 serial port is enabled. Set this option " | 46 | "the XO 1.5 serial port is enabled. Set this option " |
47 | "to force the issue."); | 47 | "to force-enable the camera."); |
48 | #endif | ||
49 | 48 | ||
50 | /* | 49 | /* |
51 | * Basic window sizes. | 50 | * Basic window sizes. |
@@ -1246,6 +1245,62 @@ static const struct v4l2_ioctl_ops viacam_ioctl_ops = { | |||
1246 | /* | 1245 | /* |
1247 | * Power management. | 1246 | * Power management. |
1248 | */ | 1247 | */ |
1248 | #ifdef CONFIG_PM | ||
1249 | |||
1250 | static int viacam_suspend(void *priv) | ||
1251 | { | ||
1252 | struct via_camera *cam = priv; | ||
1253 | enum viacam_opstate state = cam->opstate; | ||
1254 | |||
1255 | if (cam->opstate != S_IDLE) { | ||
1256 | viacam_stop_engine(cam); | ||
1257 | cam->opstate = state; /* So resume restarts */ | ||
1258 | } | ||
1259 | |||
1260 | return 0; | ||
1261 | } | ||
1262 | |||
1263 | static int viacam_resume(void *priv) | ||
1264 | { | ||
1265 | struct via_camera *cam = priv; | ||
1266 | int ret = 0; | ||
1267 | |||
1268 | /* | ||
1269 | * Get back to a reasonable operating state. | ||
1270 | */ | ||
1271 | via_write_reg_mask(VIASR, 0x78, 0, 0x80); | ||
1272 | via_write_reg_mask(VIASR, 0x1e, 0xc0, 0xc0); | ||
1273 | viacam_int_disable(cam); | ||
1274 | set_bit(CF_CONFIG_NEEDED, &cam->flags); | ||
1275 | /* | ||
1276 | * Make sure the sensor's power state is correct | ||
1277 | */ | ||
1278 | if (cam->users > 0) | ||
1279 | via_sensor_power_up(cam); | ||
1280 | else | ||
1281 | via_sensor_power_down(cam); | ||
1282 | /* | ||
1283 | * If it was operating, try to restart it. | ||
1284 | */ | ||
1285 | if (cam->opstate != S_IDLE) { | ||
1286 | mutex_lock(&cam->lock); | ||
1287 | ret = viacam_configure_sensor(cam); | ||
1288 | if (!ret) | ||
1289 | ret = viacam_config_controller(cam); | ||
1290 | mutex_unlock(&cam->lock); | ||
1291 | if (!ret) | ||
1292 | viacam_start_engine(cam); | ||
1293 | } | ||
1294 | |||
1295 | return ret; | ||
1296 | } | ||
1297 | |||
1298 | static struct viafb_pm_hooks viacam_pm_hooks = { | ||
1299 | .suspend = viacam_suspend, | ||
1300 | .resume = viacam_resume | ||
1301 | }; | ||
1302 | |||
1303 | #endif /* CONFIG_PM */ | ||
1249 | 1304 | ||
1250 | /* | 1305 | /* |
1251 | * Setup stuff. | 1306 | * Setup stuff. |
@@ -1261,6 +1316,37 @@ static struct video_device viacam_v4l_template = { | |||
1261 | .release = video_device_release_empty, /* Check this */ | 1316 | .release = video_device_release_empty, /* Check this */ |
1262 | }; | 1317 | }; |
1263 | 1318 | ||
1319 | /* | ||
1320 | * The OLPC folks put the serial port on the same pin as | ||
1321 | * the camera. They also get grumpy if we break the | ||
1322 | * serial port and keep them from using it. So we have | ||
1323 | * to check the serial enable bit and not step on it. | ||
1324 | */ | ||
1325 | #define VIACAM_SERIAL_DEVFN 0x88 | ||
1326 | #define VIACAM_SERIAL_CREG 0x46 | ||
1327 | #define VIACAM_SERIAL_BIT 0x40 | ||
1328 | |||
1329 | static __devinit bool viacam_serial_is_enabled(void) | ||
1330 | { | ||
1331 | struct pci_bus *pbus = pci_find_bus(0, 0); | ||
1332 | u8 cbyte; | ||
1333 | |||
1334 | pci_bus_read_config_byte(pbus, VIACAM_SERIAL_DEVFN, | ||
1335 | VIACAM_SERIAL_CREG, &cbyte); | ||
1336 | if ((cbyte & VIACAM_SERIAL_BIT) == 0) | ||
1337 | return false; /* Not enabled */ | ||
1338 | if (override_serial == 0) { | ||
1339 | printk(KERN_NOTICE "Via camera: serial port is enabled, " \ | ||
1340 | "refusing to load.\n"); | ||
1341 | printk(KERN_NOTICE "Specify override_serial=1 to force " \ | ||
1342 | "module loading.\n"); | ||
1343 | return true; | ||
1344 | } | ||
1345 | printk(KERN_NOTICE "Via camera: overriding serial port\n"); | ||
1346 | pci_bus_write_config_byte(pbus, VIACAM_SERIAL_DEVFN, | ||
1347 | VIACAM_SERIAL_CREG, cbyte & ~VIACAM_SERIAL_BIT); | ||
1348 | return false; | ||
1349 | } | ||
1264 | 1350 | ||
1265 | static __devinit int viacam_probe(struct platform_device *pdev) | 1351 | static __devinit int viacam_probe(struct platform_device *pdev) |
1266 | { | 1352 | { |
@@ -1292,6 +1378,10 @@ static __devinit int viacam_probe(struct platform_device *pdev) | |||
1292 | printk(KERN_ERR "viacam: No I/O memory, so no pictures\n"); | 1378 | printk(KERN_ERR "viacam: No I/O memory, so no pictures\n"); |
1293 | return -ENOMEM; | 1379 | return -ENOMEM; |
1294 | } | 1380 | } |
1381 | |||
1382 | if (machine_is_olpc() && viacam_serial_is_enabled()) | ||
1383 | return -EBUSY; | ||
1384 | |||
1295 | /* | 1385 | /* |
1296 | * Basic structure initialization. | 1386 | * Basic structure initialization. |
1297 | */ | 1387 | */ |
@@ -1369,6 +1459,14 @@ static __devinit int viacam_probe(struct platform_device *pdev) | |||
1369 | goto out_irq; | 1459 | goto out_irq; |
1370 | video_set_drvdata(&cam->vdev, cam); | 1460 | video_set_drvdata(&cam->vdev, cam); |
1371 | 1461 | ||
1462 | #ifdef CONFIG_PM | ||
1463 | /* | ||
1464 | * Hook into PM events | ||
1465 | */ | ||
1466 | viacam_pm_hooks.private = cam; | ||
1467 | viafb_pm_register(&viacam_pm_hooks); | ||
1468 | #endif | ||
1469 | |||
1372 | /* Power the sensor down until somebody opens the device */ | 1470 | /* Power the sensor down until somebody opens the device */ |
1373 | via_sensor_power_down(cam); | 1471 | via_sensor_power_down(cam); |
1374 | return 0; | 1472 | return 0; |
@@ -1395,7 +1493,6 @@ static __devexit int viacam_remove(struct platform_device *pdev) | |||
1395 | return 0; | 1493 | return 0; |
1396 | } | 1494 | } |
1397 | 1495 | ||
1398 | |||
1399 | static struct platform_driver viacam_driver = { | 1496 | static struct platform_driver viacam_driver = { |
1400 | .driver = { | 1497 | .driver = { |
1401 | .name = "viafb-camera", | 1498 | .name = "viafb-camera", |
@@ -1404,50 +1501,8 @@ static struct platform_driver viacam_driver = { | |||
1404 | .remove = viacam_remove, | 1501 | .remove = viacam_remove, |
1405 | }; | 1502 | }; |
1406 | 1503 | ||
1407 | |||
1408 | #ifdef CONFIG_OLPC_XO_1_5 | ||
1409 | /* | ||
1410 | * The OLPC folks put the serial port on the same pin as | ||
1411 | * the camera. They also get grumpy if we break the | ||
1412 | * serial port and keep them from using it. So we have | ||
1413 | * to check the serial enable bit and not step on it. | ||
1414 | */ | ||
1415 | #define VIACAM_SERIAL_DEVFN 0x88 | ||
1416 | #define VIACAM_SERIAL_CREG 0x46 | ||
1417 | #define VIACAM_SERIAL_BIT 0x40 | ||
1418 | |||
1419 | static __devinit int viacam_check_serial_port(void) | ||
1420 | { | ||
1421 | struct pci_bus *pbus = pci_find_bus(0, 0); | ||
1422 | u8 cbyte; | ||
1423 | |||
1424 | pci_bus_read_config_byte(pbus, VIACAM_SERIAL_DEVFN, | ||
1425 | VIACAM_SERIAL_CREG, &cbyte); | ||
1426 | if ((cbyte & VIACAM_SERIAL_BIT) == 0) | ||
1427 | return 0; /* Not enabled */ | ||
1428 | if (override_serial == 0) { | ||
1429 | printk(KERN_NOTICE "Via camera: serial port is enabled, " \ | ||
1430 | "refusing to load.\n"); | ||
1431 | printk(KERN_NOTICE "Specify override_serial=1 to force " \ | ||
1432 | "module loading.\n"); | ||
1433 | return -EBUSY; | ||
1434 | } | ||
1435 | printk(KERN_NOTICE "Via camera: overriding serial port\n"); | ||
1436 | pci_bus_write_config_byte(pbus, VIACAM_SERIAL_DEVFN, | ||
1437 | VIACAM_SERIAL_CREG, cbyte & ~VIACAM_SERIAL_BIT); | ||
1438 | return 0; | ||
1439 | } | ||
1440 | #endif | ||
1441 | |||
1442 | |||
1443 | |||
1444 | |||
1445 | static int viacam_init(void) | 1504 | static int viacam_init(void) |
1446 | { | 1505 | { |
1447 | #ifdef CONFIG_OLPC_XO_1_5 | ||
1448 | if (viacam_check_serial_port()) | ||
1449 | return -EBUSY; | ||
1450 | #endif | ||
1451 | return platform_driver_register(&viacam_driver); | 1506 | return platform_driver_register(&viacam_driver); |
1452 | } | 1507 | } |
1453 | module_init(viacam_init); | 1508 | module_init(viacam_init); |