aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/w9968cf.c
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2009-03-08 09:19:44 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:11 -0400
commit3160fbc556aa2e60404fa4da35b3e13dd741a5a2 (patch)
tree51ea0abb1bfbda94749b7b088950942e52a085e5 /drivers/media/video/w9968cf.c
parent4e06839fc7221872d7868855c05659f08d1c9f3d (diff)
V4L/DVB (10874): w9968cf/ovcamchip: convert to v4l2_subdev.
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/w9968cf.c')
-rw-r--r--drivers/media/video/w9968cf.c114
1 files changed, 28 insertions, 86 deletions
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 3318be5688c9..fd5c4c87a73b 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -68,7 +68,6 @@ MODULE_VERSION(W9968CF_MODULE_VERSION);
68MODULE_LICENSE(W9968CF_MODULE_LICENSE); 68MODULE_LICENSE(W9968CF_MODULE_LICENSE);
69MODULE_SUPPORTED_DEVICE("Video"); 69MODULE_SUPPORTED_DEVICE("Video");
70 70
71static int ovmod_load = W9968CF_OVMOD_LOAD;
72static unsigned short simcams = W9968CF_SIMCAMS; 71static unsigned short simcams = W9968CF_SIMCAMS;
73static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/ 72static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/
74static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = 73static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] =
@@ -111,9 +110,6 @@ static int specific_debug = W9968CF_SPECIFIC_DEBUG;
111 110
112static unsigned int param_nv[24]; /* number of values per parameter */ 111static unsigned int param_nv[24]; /* number of values per parameter */
113 112
114#ifdef CONFIG_MODULES
115module_param(ovmod_load, bool, 0644);
116#endif
117module_param(simcams, ushort, 0644); 113module_param(simcams, ushort, 0644);
118module_param_array(video_nr, short, &param_nv[0], 0444); 114module_param_array(video_nr, short, &param_nv[0], 0444);
119module_param_array(packet_size, uint, &param_nv[1], 0444); 115module_param_array(packet_size, uint, &param_nv[1], 0444);
@@ -144,18 +140,6 @@ module_param(debug, ushort, 0644);
144module_param(specific_debug, bool, 0644); 140module_param(specific_debug, bool, 0644);
145#endif 141#endif
146 142
147#ifdef CONFIG_MODULES
148MODULE_PARM_DESC(ovmod_load,
149 "\n<0|1> Automatic 'ovcamchip' module loading."
150 "\n0 disabled, 1 enabled."
151 "\nIf enabled,'insmod' searches for the required 'ovcamchip'"
152 "\nmodule in the system, according to its configuration, and"
153 "\nattempts to load that module automatically. This action is"
154 "\nperformed once as soon as the 'w9968cf' module is loaded"
155 "\ninto memory."
156 "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"."
157 "\n");
158#endif
159MODULE_PARM_DESC(simcams, 143MODULE_PARM_DESC(simcams,
160 "\n<n> Number of cameras allowed to stream simultaneously." 144 "\n<n> Number of cameras allowed to stream simultaneously."
161 "\nn may vary from 0 to " 145 "\nn may vary from 0 to "
@@ -443,8 +427,6 @@ static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr,
443 unsigned short flags, char read_write, 427 unsigned short flags, char read_write,
444 u8 command, int size, union i2c_smbus_data*); 428 u8 command, int size, union i2c_smbus_data*);
445static u32 w9968cf_i2c_func(struct i2c_adapter*); 429static u32 w9968cf_i2c_func(struct i2c_adapter*);
446static int w9968cf_i2c_attach_inform(struct i2c_client*);
447static int w9968cf_i2c_detach_inform(struct i2c_client*);
448 430
449/* Memory management */ 431/* Memory management */
450static void* rvmalloc(unsigned long size); 432static void* rvmalloc(unsigned long size);
@@ -1443,19 +1425,11 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
1443 unsigned short flags, char read_write, u8 command, 1425 unsigned short flags, char read_write, u8 command,
1444 int size, union i2c_smbus_data *data) 1426 int size, union i2c_smbus_data *data)
1445{ 1427{
1446 struct w9968cf_device* cam = i2c_get_adapdata(adapter); 1428 struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter);
1429 struct w9968cf_device *cam = to_cam(v4l2_dev);
1447 u8 i; 1430 u8 i;
1448 int err = 0; 1431 int err = 0;
1449 1432
1450 switch (addr) {
1451 case OV6xx0_SID:
1452 case OV7xx0_SID:
1453 break;
1454 default:
1455 DBG(4, "Rejected slave ID 0x%04X", addr)
1456 return -EINVAL;
1457 }
1458
1459 if (size == I2C_SMBUS_BYTE) { 1433 if (size == I2C_SMBUS_BYTE) {
1460 /* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */ 1434 /* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */
1461 addr <<= 1; 1435 addr <<= 1;
@@ -1463,8 +1437,17 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
1463 if (read_write == I2C_SMBUS_WRITE) 1437 if (read_write == I2C_SMBUS_WRITE)
1464 err = w9968cf_i2c_adap_write_byte(cam, addr, command); 1438 err = w9968cf_i2c_adap_write_byte(cam, addr, command);
1465 else if (read_write == I2C_SMBUS_READ) 1439 else if (read_write == I2C_SMBUS_READ)
1466 err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte); 1440 for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) {
1467 1441 err = w9968cf_i2c_adap_read_byte(cam, addr,
1442 &data->byte);
1443 if (err) {
1444 if (w9968cf_smbus_refresh_bus(cam)) {
1445 err = -EIO;
1446 break;
1447 }
1448 } else
1449 break;
1450 }
1468 } else if (size == I2C_SMBUS_BYTE_DATA) { 1451 } else if (size == I2C_SMBUS_BYTE_DATA) {
1469 addr <<= 1; 1452 addr <<= 1;
1470 1453
@@ -1491,7 +1474,6 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
1491 DBG(4, "Unsupported I2C transfer mode (%d)", size) 1474 DBG(4, "Unsupported I2C transfer mode (%d)", size)
1492 return -EINVAL; 1475 return -EINVAL;
1493 } 1476 }
1494
1495 return err; 1477 return err;
1496} 1478}
1497 1479
@@ -1504,44 +1486,6 @@ static u32 w9968cf_i2c_func(struct i2c_adapter* adap)
1504} 1486}
1505 1487
1506 1488
1507static int w9968cf_i2c_attach_inform(struct i2c_client* client)
1508{
1509 struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
1510 int id = client->driver->id, err = 0;
1511
1512 if (id == I2C_DRIVERID_OVCAMCHIP) {
1513 cam->sensor_client = client;
1514 err = w9968cf_sensor_init(cam);
1515 if (err) {
1516 cam->sensor_client = NULL;
1517 return err;
1518 }
1519 } else {
1520 DBG(4, "Rejected client [%s] with driver [%s]",
1521 client->name, client->driver->driver.name)
1522 return -EINVAL;
1523 }
1524
1525 DBG(5, "I2C attach client [%s] with driver [%s]",
1526 client->name, client->driver->driver.name)
1527
1528 return 0;
1529}
1530
1531
1532static int w9968cf_i2c_detach_inform(struct i2c_client* client)
1533{
1534 struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
1535
1536 if (cam->sensor_client == client)
1537 cam->sensor_client = NULL;
1538
1539 DBG(5, "I2C detach client [%s]", client->name)
1540
1541 return 0;
1542}
1543
1544
1545static int w9968cf_i2c_init(struct w9968cf_device* cam) 1489static int w9968cf_i2c_init(struct w9968cf_device* cam)
1546{ 1490{
1547 int err = 0; 1491 int err = 0;
@@ -1554,15 +1498,13 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam)
1554 static struct i2c_adapter adap = { 1498 static struct i2c_adapter adap = {
1555 .id = I2C_HW_SMBUS_W9968CF, 1499 .id = I2C_HW_SMBUS_W9968CF,
1556 .owner = THIS_MODULE, 1500 .owner = THIS_MODULE,
1557 .client_register = w9968cf_i2c_attach_inform,
1558 .client_unregister = w9968cf_i2c_detach_inform,
1559 .algo = &algo, 1501 .algo = &algo,
1560 }; 1502 };
1561 1503
1562 memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter)); 1504 memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter));
1563 strcpy(cam->i2c_adapter.name, "w9968cf"); 1505 strcpy(cam->i2c_adapter.name, "w9968cf");
1564 cam->i2c_adapter.dev.parent = &cam->usbdev->dev; 1506 cam->i2c_adapter.dev.parent = &cam->usbdev->dev;
1565 i2c_set_adapdata(&cam->i2c_adapter, cam); 1507 i2c_set_adapdata(&cam->i2c_adapter, &cam->v4l2_dev);
1566 1508
1567 DBG(6, "Registering I2C adapter with kernel...") 1509 DBG(6, "Registering I2C adapter with kernel...")
1568 1510
@@ -2165,13 +2107,9 @@ w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int* val)
2165static int 2107static int
2166w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg) 2108w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg)
2167{ 2109{
2168 struct i2c_client* c = cam->sensor_client; 2110 int rc;
2169 int rc = 0;
2170 2111
2171 if (!c || !c->driver || !c->driver->command) 2112 rc = v4l2_subdev_call(cam->sensor_sd, core, ioctl, cmd, arg);
2172 return -EINVAL;
2173
2174 rc = c->driver->command(c, cmd, arg);
2175 /* The I2C driver returns -EPERM on non-supported controls */ 2113 /* The I2C driver returns -EPERM on non-supported controls */
2176 return (rc < 0 && rc != -EPERM) ? rc : 0; 2114 return (rc < 0 && rc != -EPERM) ? rc : 0;
2177} 2115}
@@ -2346,7 +2284,7 @@ static int w9968cf_sensor_init(struct w9968cf_device* cam)
2346 goto error; 2284 goto error;
2347 2285
2348 /* NOTE: Make sure width and height are a multiple of 16 */ 2286 /* NOTE: Make sure width and height are a multiple of 16 */
2349 switch (cam->sensor_client->addr) { 2287 switch (v4l2_i2c_subdev_addr(cam->sensor_sd)) {
2350 case OV6xx0_SID: 2288 case OV6xx0_SID:
2351 cam->maxwidth = 352; 2289 cam->maxwidth = 352;
2352 cam->maxheight = 288; 2290 cam->maxheight = 288;
@@ -2651,6 +2589,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam)
2651 w9968cf_deallocate_memory(cam); 2589 w9968cf_deallocate_memory(cam);
2652 kfree(cam->control_buffer); 2590 kfree(cam->control_buffer);
2653 kfree(cam->data_buffer); 2591 kfree(cam->data_buffer);
2592 v4l2_device_unregister(&cam->v4l2_dev);
2654 2593
2655 mutex_unlock(&w9968cf_devlist_mutex); 2594 mutex_unlock(&w9968cf_devlist_mutex);
2656} 2595}
@@ -3480,6 +3419,11 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3480 struct list_head* ptr; 3419 struct list_head* ptr;
3481 u8 sc = 0; /* number of simultaneous cameras */ 3420 u8 sc = 0; /* number of simultaneous cameras */
3482 static unsigned short dev_nr; /* 0 - we are handling device number n */ 3421 static unsigned short dev_nr; /* 0 - we are handling device number n */
3422 static unsigned short addrs[] = {
3423 OV7xx0_SID,
3424 OV6xx0_SID,
3425 I2C_CLIENT_END
3426 };
3483 3427
3484 if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor && 3428 if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor &&
3485 le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct) 3429 le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct)
@@ -3578,12 +3522,13 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
3578 w9968cf_turn_on_led(cam); 3522 w9968cf_turn_on_led(cam);
3579 3523
3580 w9968cf_i2c_init(cam); 3524 w9968cf_i2c_init(cam);
3525 cam->sensor_sd = v4l2_i2c_new_probed_subdev(&cam->i2c_adapter,
3526 "ovcamchip", "ovcamchip", addrs);
3581 3527
3582 usb_set_intfdata(intf, cam); 3528 usb_set_intfdata(intf, cam);
3583 mutex_unlock(&cam->dev_mutex); 3529 mutex_unlock(&cam->dev_mutex);
3584 3530
3585 if (ovmod_load) 3531 err = w9968cf_sensor_init(cam);
3586 request_module("ovcamchip");
3587 return 0; 3532 return 0;
3588 3533
3589fail: /* Free unused memory */ 3534fail: /* Free unused memory */
@@ -3604,9 +3549,8 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf)
3604 struct w9968cf_device* cam = 3549 struct w9968cf_device* cam =
3605 (struct w9968cf_device*)usb_get_intfdata(intf); 3550 (struct w9968cf_device*)usb_get_intfdata(intf);
3606 3551
3607 down_write(&w9968cf_disconnect);
3608
3609 if (cam) { 3552 if (cam) {
3553 down_write(&w9968cf_disconnect);
3610 /* Prevent concurrent accesses to data */ 3554 /* Prevent concurrent accesses to data */
3611 mutex_lock(&cam->dev_mutex); 3555 mutex_lock(&cam->dev_mutex);
3612 3556
@@ -3628,14 +3572,12 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf)
3628 w9968cf_release_resources(cam); 3572 w9968cf_release_resources(cam);
3629 3573
3630 mutex_unlock(&cam->dev_mutex); 3574 mutex_unlock(&cam->dev_mutex);
3575 up_write(&w9968cf_disconnect);
3631 3576
3632 if (!cam->users) { 3577 if (!cam->users) {
3633 v4l2_device_unregister(&cam->v4l2_dev);
3634 kfree(cam); 3578 kfree(cam);
3635 } 3579 }
3636 } 3580 }
3637
3638 up_write(&w9968cf_disconnect);
3639} 3581}
3640 3582
3641 3583