aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
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
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')
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c203
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_priv.h7
-rw-r--r--drivers/media/video/w9968cf.c114
-rw-r--r--drivers/media/video/w9968cf.h8
4 files changed, 126 insertions, 206 deletions
diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index c841f4e4fbe4..21ec1dd2e1e5 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -15,6 +15,9 @@
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/i2c.h>
19#include <media/v4l2-device.h>
20#include <media/v4l2-i2c-drv.h>
18#include "ovcamchip_priv.h" 21#include "ovcamchip_priv.h"
19 22
20#define DRIVER_VERSION "v2.27 for Linux 2.6" 23#define DRIVER_VERSION "v2.27 for Linux 2.6"
@@ -44,6 +47,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
44MODULE_DESCRIPTION(DRIVER_DESC); 47MODULE_DESCRIPTION(DRIVER_DESC);
45MODULE_LICENSE("GPL"); 48MODULE_LICENSE("GPL");
46 49
50
47/* Registers common to all chips, that are needed for detection */ 51/* Registers common to all chips, that are needed for detection */
48#define GENERIC_REG_ID_HIGH 0x1C /* manufacturer ID MSB */ 52#define GENERIC_REG_ID_HIGH 0x1C /* manufacturer ID MSB */
49#define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */ 53#define GENERIC_REG_ID_LOW 0x1D /* manufacturer ID LSB */
@@ -61,10 +65,6 @@ static char *chip_names[NUM_CC_TYPES] = {
61 [CC_OV6630AF] = "OV6630AF", 65 [CC_OV6630AF] = "OV6630AF",
62}; 66};
63 67
64/* Forward declarations */
65static struct i2c_driver driver;
66static struct i2c_client client_template;
67
68/* ----------------------------------------------------------------------- */ 68/* ----------------------------------------------------------------------- */
69 69
70int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals) 70int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals)
@@ -253,112 +253,36 @@ static int ovcamchip_detect(struct i2c_client *c)
253 253
254 /* Test for 7xx0 */ 254 /* Test for 7xx0 */
255 PDEBUG(3, "Testing for 0V7xx0"); 255 PDEBUG(3, "Testing for 0V7xx0");
256 c->addr = OV7xx0_SID; 256 if (init_camchip(c) < 0)
257 if (init_camchip(c) < 0) { 257 return -ENODEV;
258 /* Test for 6xx0 */ 258 /* 7-bit addresses with bit 0 set are for the OV7xx0 */
259 PDEBUG(3, "Testing for 0V6xx0"); 259 if (c->addr & 1) {
260 c->addr = OV6xx0_SID;
261 if (init_camchip(c) < 0) {
262 return -ENODEV;
263 } else {
264 if (ov6xx0_detect(c) < 0) {
265 PERROR("Failed to init OV6xx0");
266 return -EIO;
267 }
268 }
269 } else {
270 if (ov7xx0_detect(c) < 0) { 260 if (ov7xx0_detect(c) < 0) {
271 PERROR("Failed to init OV7xx0"); 261 PERROR("Failed to init OV7xx0");
272 return -EIO; 262 return -EIO;
273 } 263 }
264 return 0;
265 }
266 /* Test for 6xx0 */
267 PDEBUG(3, "Testing for 0V6xx0");
268 if (ov6xx0_detect(c) < 0) {
269 PERROR("Failed to init OV6xx0");
270 return -EIO;
274 } 271 }
275
276 return 0; 272 return 0;
277} 273}
278 274
279/* ----------------------------------------------------------------------- */ 275/* ----------------------------------------------------------------------- */
280 276
281static int ovcamchip_attach(struct i2c_adapter *adap) 277static long ovcamchip_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
282{
283 int rc = 0;
284 struct ovcamchip *ov;
285 struct i2c_client *c;
286
287 /* I2C is not a PnP bus, so we can never be certain that we're talking
288 * to the right chip. To prevent damage to EEPROMS and such, only
289 * attach to adapters that are known to contain OV camera chips. */
290
291 switch (adap->id) {
292 case I2C_HW_SMBUS_OV511:
293 case I2C_HW_SMBUS_OV518:
294 case I2C_HW_SMBUS_W9968CF:
295 PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id);
296 break;
297 default:
298 PDEBUG(1, "Adapter ID 0x%06x rejected", adap->id);
299 return -ENODEV;
300 }
301
302 c = kmalloc(sizeof *c, GFP_KERNEL);
303 if (!c) {
304 rc = -ENOMEM;
305 goto no_client;
306 }
307 memcpy(c, &client_template, sizeof *c);
308 c->adapter = adap;
309 strcpy(c->name, "OV????");
310
311 ov = kzalloc(sizeof *ov, GFP_KERNEL);
312 if (!ov) {
313 rc = -ENOMEM;
314 goto no_ov;
315 }
316 i2c_set_clientdata(c, ov);
317
318 rc = ovcamchip_detect(c);
319 if (rc < 0)
320 goto error;
321
322 strcpy(c->name, chip_names[ov->subtype]);
323
324 PDEBUG(1, "Camera chip detection complete");
325
326 i2c_attach_client(c);
327
328 return rc;
329error:
330 kfree(ov);
331no_ov:
332 kfree(c);
333no_client:
334 PDEBUG(1, "returning %d", rc);
335 return rc;
336}
337
338static int ovcamchip_detach(struct i2c_client *c)
339{ 278{
340 struct ovcamchip *ov = i2c_get_clientdata(c); 279 struct ovcamchip *ov = to_ovcamchip(sd);
341 int rc; 280 struct i2c_client *c = v4l2_get_subdevdata(sd);
342
343 rc = ov->sops->free(c);
344 if (rc < 0)
345 return rc;
346
347 i2c_detach_client(c);
348
349 kfree(ov);
350 kfree(c);
351 return 0;
352}
353
354static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
355{
356 struct ovcamchip *ov = i2c_get_clientdata(c);
357 281
358 if (!ov->initialized && 282 if (!ov->initialized &&
359 cmd != OVCAMCHIP_CMD_Q_SUBTYPE && 283 cmd != OVCAMCHIP_CMD_Q_SUBTYPE &&
360 cmd != OVCAMCHIP_CMD_INITIALIZE) { 284 cmd != OVCAMCHIP_CMD_INITIALIZE) {
361 dev_err(&c->dev, "ERROR: Camera chip not initialized yet!\n"); 285 v4l2_err(sd, "Camera chip not initialized yet!\n");
362 return -EPERM; 286 return -EPERM;
363 } 287 }
364 288
@@ -379,10 +303,10 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
379 303
380 if (ov->mono) { 304 if (ov->mono) {
381 if (ov->subtype != CC_OV7620) 305 if (ov->subtype != CC_OV7620)
382 dev_warn(&c->dev, "Warning: Monochrome not " 306 v4l2_warn(sd, "Monochrome not "
383 "implemented for this chip\n"); 307 "implemented for this chip\n");
384 else 308 else
385 dev_info(&c->dev, "Initializing chip as " 309 v4l2_info(sd, "Initializing chip as "
386 "monochrome\n"); 310 "monochrome\n");
387 } 311 }
388 312
@@ -398,37 +322,80 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
398 } 322 }
399} 323}
400 324
325static int ovcamchip_command(struct i2c_client *client, unsigned cmd, void *arg)
326{
327 return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
328}
329
401/* ----------------------------------------------------------------------- */ 330/* ----------------------------------------------------------------------- */
402 331
403static struct i2c_driver driver = { 332static const struct v4l2_subdev_core_ops ovcamchip_core_ops = {
404 .driver = { 333 .ioctl = ovcamchip_ioctl,
405 .name = "ovcamchip",
406 },
407 .id = I2C_DRIVERID_OVCAMCHIP,
408 .attach_adapter = ovcamchip_attach,
409 .detach_client = ovcamchip_detach,
410 .command = ovcamchip_command,
411}; 334};
412 335
413static struct i2c_client client_template = { 336static const struct v4l2_subdev_ops ovcamchip_ops = {
414 .name = "(unset)", 337 .core = &ovcamchip_core_ops,
415 .driver = &driver,
416}; 338};
417 339
418static int __init ovcamchip_init(void) 340static int ovcamchip_probe(struct i2c_client *client,
341 const struct i2c_device_id *id)
419{ 342{
420#ifdef DEBUG 343 struct ovcamchip *ov;
421 ovcamchip_debug = debug; 344 struct v4l2_subdev *sd;
422#endif 345 int rc = 0;
423 346
424 PINFO(DRIVER_VERSION " : " DRIVER_DESC); 347 ov = kzalloc(sizeof *ov, GFP_KERNEL);
425 return i2c_add_driver(&driver); 348 if (!ov) {
349 rc = -ENOMEM;
350 goto no_ov;
351 }
352 sd = &ov->sd;
353 v4l2_i2c_subdev_init(sd, client, &ovcamchip_ops);
354
355 rc = ovcamchip_detect(client);
356 if (rc < 0)
357 goto error;
358
359 v4l_info(client, "%s found @ 0x%02x (%s)\n",
360 chip_names[ov->subtype], client->addr << 1, client->adapter->name);
361
362 PDEBUG(1, "Camera chip detection complete");
363
364 return rc;
365error:
366 kfree(ov);
367no_ov:
368 PDEBUG(1, "returning %d", rc);
369 return rc;
426} 370}
427 371
428static void __exit ovcamchip_exit(void) 372static int ovcamchip_remove(struct i2c_client *client)
429{ 373{
430 i2c_del_driver(&driver); 374 struct v4l2_subdev *sd = i2c_get_clientdata(client);
375 struct ovcamchip *ov = to_ovcamchip(sd);
376 int rc;
377
378 v4l2_device_unregister_subdev(sd);
379 rc = ov->sops->free(client);
380 if (rc < 0)
381 return rc;
382
383 kfree(ov);
384 return 0;
431} 385}
432 386
433module_init(ovcamchip_init); 387/* ----------------------------------------------------------------------- */
434module_exit(ovcamchip_exit); 388
389static const struct i2c_device_id ovcamchip_id[] = {
390 { "ovcamchip", 0 },
391 { }
392};
393MODULE_DEVICE_TABLE(i2c, ovcamchip_id);
394
395static struct v4l2_i2c_driver_data v4l2_i2c_data = {
396 .name = "ovcamchip",
397 .command = ovcamchip_command,
398 .probe = ovcamchip_probe,
399 .remove = ovcamchip_remove,
400 .id_table = ovcamchip_id,
401};
diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h
index a05650faedda..4f07b78c88bc 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_priv.h
+++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h
@@ -16,6 +16,7 @@
16#define __LINUX_OVCAMCHIP_PRIV_H 16#define __LINUX_OVCAMCHIP_PRIV_H
17 17
18#include <linux/i2c.h> 18#include <linux/i2c.h>
19#include <media/v4l2-subdev.h>
19#include <media/ovcamchip.h> 20#include <media/ovcamchip.h>
20 21
21#ifdef DEBUG 22#ifdef DEBUG
@@ -46,6 +47,7 @@ struct ovcamchip_ops {
46}; 47};
47 48
48struct ovcamchip { 49struct ovcamchip {
50 struct v4l2_subdev sd;
49 struct ovcamchip_ops *sops; 51 struct ovcamchip_ops *sops;
50 void *spriv; /* Private data for OV7x10.c etc... */ 52 void *spriv; /* Private data for OV7x10.c etc... */
51 int subtype; /* = SEN_OV7610 etc... */ 53 int subtype; /* = SEN_OV7610 etc... */
@@ -53,6 +55,11 @@ struct ovcamchip {
53 int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */ 55 int initialized; /* OVCAMCHIP_CMD_INITIALIZE was successful */
54}; 56};
55 57
58static inline struct ovcamchip *to_ovcamchip(struct v4l2_subdev *sd)
59{
60 return container_of(sd, struct ovcamchip, sd);
61}
62
56extern struct ovcamchip_ops ov6x20_ops; 63extern struct ovcamchip_ops ov6x20_ops;
57extern struct ovcamchip_ops ov6x30_ops; 64extern struct ovcamchip_ops ov6x30_ops;
58extern struct ovcamchip_ops ov7x10_ops; 65extern struct ovcamchip_ops ov7x10_ops;
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
diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h
index c59883552545..fdfc6a4e1c8f 100644
--- a/drivers/media/video/w9968cf.h
+++ b/drivers/media/video/w9968cf.h
@@ -43,7 +43,6 @@
43 * Default values * 43 * Default values *
44 ****************************************************************************/ 44 ****************************************************************************/
45 45
46#define W9968CF_OVMOD_LOAD 1 /* automatic 'ovcamchip' module loading */
47#define W9968CF_VPPMOD_LOAD 1 /* automatic 'w9968cf-vpp' module loading */ 46#define W9968CF_VPPMOD_LOAD 1 /* automatic 'w9968cf-vpp' module loading */
48 47
49/* Comment/uncomment the following line to enable/disable debugging messages */ 48/* Comment/uncomment the following line to enable/disable debugging messages */
@@ -265,7 +264,7 @@ struct w9968cf_device {
265 264
266 /* I2C interface to kernel */ 265 /* I2C interface to kernel */
267 struct i2c_adapter i2c_adapter; 266 struct i2c_adapter i2c_adapter;
268 struct i2c_client* sensor_client; 267 struct v4l2_subdev *sensor_sd;
269 268
270 /* Locks */ 269 /* Locks */
271 struct mutex dev_mutex, /* for probe, disconnect,open and close */ 270 struct mutex dev_mutex, /* for probe, disconnect,open and close */
@@ -277,6 +276,11 @@ struct w9968cf_device {
277 char command[16]; /* name of the program holding the device */ 276 char command[16]; /* name of the program holding the device */
278}; 277};
279 278
279static inline struct w9968cf_device *to_cam(struct v4l2_device *v4l2_dev)
280{
281 return container_of(v4l2_dev, struct w9968cf_device, v4l2_dev);
282}
283
280 284
281/**************************************************************************** 285/****************************************************************************
282 * Macros for debugging * 286 * Macros for debugging *