aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/via-camera.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/via-camera.c')
-rw-r--r--drivers/media/video/via-camera.c147
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
42static int override_serial; 42static int override_serial;
43module_param(override_serial, bool, 0444); 43module_param(override_serial, bool, 0444);
44MODULE_PARM_DESC(override_serial, 44MODULE_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
1250static 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
1263static 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
1298static 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
1329static __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
1265static __devinit int viacam_probe(struct platform_device *pdev) 1351static __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
1399static struct platform_driver viacam_driver = { 1496static 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
1419static __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
1445static int viacam_init(void) 1504static 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}
1453module_init(viacam_init); 1508module_init(viacam_init);