aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ovcamchip
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/ovcamchip
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/ovcamchip')
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_core.c203
-rw-r--r--drivers/media/video/ovcamchip/ovcamchip_priv.h7
2 files changed, 92 insertions, 118 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;