diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2009-03-08 09:19:44 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:43:11 -0400 |
commit | 3160fbc556aa2e60404fa4da35b3e13dd741a5a2 (patch) | |
tree | 51ea0abb1bfbda94749b7b088950942e52a085e5 /drivers/media | |
parent | 4e06839fc7221872d7868855c05659f08d1c9f3d (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.c | 203 | ||||
-rw-r--r-- | drivers/media/video/ovcamchip/ovcamchip_priv.h | 7 | ||||
-rw-r--r-- | drivers/media/video/w9968cf.c | 114 | ||||
-rw-r--r-- | drivers/media/video/w9968cf.h | 8 |
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); | |||
44 | MODULE_DESCRIPTION(DRIVER_DESC); | 47 | MODULE_DESCRIPTION(DRIVER_DESC); |
45 | MODULE_LICENSE("GPL"); | 48 | MODULE_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 */ | ||
65 | static struct i2c_driver driver; | ||
66 | static struct i2c_client client_template; | ||
67 | |||
68 | /* ----------------------------------------------------------------------- */ | 68 | /* ----------------------------------------------------------------------- */ |
69 | 69 | ||
70 | int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals) | 70 | int 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 | ||
281 | static int ovcamchip_attach(struct i2c_adapter *adap) | 277 | static 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; | ||
329 | error: | ||
330 | kfree(ov); | ||
331 | no_ov: | ||
332 | kfree(c); | ||
333 | no_client: | ||
334 | PDEBUG(1, "returning %d", rc); | ||
335 | return rc; | ||
336 | } | ||
337 | |||
338 | static 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 | |||
354 | static 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 | ||
325 | static 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 | ||
403 | static struct i2c_driver driver = { | 332 | static 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 | ||
413 | static struct i2c_client client_template = { | 336 | static const struct v4l2_subdev_ops ovcamchip_ops = { |
414 | .name = "(unset)", | 337 | .core = &ovcamchip_core_ops, |
415 | .driver = &driver, | ||
416 | }; | 338 | }; |
417 | 339 | ||
418 | static int __init ovcamchip_init(void) | 340 | static 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; | ||
365 | error: | ||
366 | kfree(ov); | ||
367 | no_ov: | ||
368 | PDEBUG(1, "returning %d", rc); | ||
369 | return rc; | ||
426 | } | 370 | } |
427 | 371 | ||
428 | static void __exit ovcamchip_exit(void) | 372 | static 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 | ||
433 | module_init(ovcamchip_init); | 387 | /* ----------------------------------------------------------------------- */ |
434 | module_exit(ovcamchip_exit); | 388 | |
389 | static const struct i2c_device_id ovcamchip_id[] = { | ||
390 | { "ovcamchip", 0 }, | ||
391 | { } | ||
392 | }; | ||
393 | MODULE_DEVICE_TABLE(i2c, ovcamchip_id); | ||
394 | |||
395 | static 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 | ||
48 | struct ovcamchip { | 49 | struct 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 | ||
58 | static inline struct ovcamchip *to_ovcamchip(struct v4l2_subdev *sd) | ||
59 | { | ||
60 | return container_of(sd, struct ovcamchip, sd); | ||
61 | } | ||
62 | |||
56 | extern struct ovcamchip_ops ov6x20_ops; | 63 | extern struct ovcamchip_ops ov6x20_ops; |
57 | extern struct ovcamchip_ops ov6x30_ops; | 64 | extern struct ovcamchip_ops ov6x30_ops; |
58 | extern struct ovcamchip_ops ov7x10_ops; | 65 | extern 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); | |||
68 | MODULE_LICENSE(W9968CF_MODULE_LICENSE); | 68 | MODULE_LICENSE(W9968CF_MODULE_LICENSE); |
69 | MODULE_SUPPORTED_DEVICE("Video"); | 69 | MODULE_SUPPORTED_DEVICE("Video"); |
70 | 70 | ||
71 | static int ovmod_load = W9968CF_OVMOD_LOAD; | ||
72 | static unsigned short simcams = W9968CF_SIMCAMS; | 71 | static unsigned short simcams = W9968CF_SIMCAMS; |
73 | static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/ | 72 | static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/ |
74 | static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = | 73 | static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] = |
@@ -111,9 +110,6 @@ static int specific_debug = W9968CF_SPECIFIC_DEBUG; | |||
111 | 110 | ||
112 | static unsigned int param_nv[24]; /* number of values per parameter */ | 111 | static unsigned int param_nv[24]; /* number of values per parameter */ |
113 | 112 | ||
114 | #ifdef CONFIG_MODULES | ||
115 | module_param(ovmod_load, bool, 0644); | ||
116 | #endif | ||
117 | module_param(simcams, ushort, 0644); | 113 | module_param(simcams, ushort, 0644); |
118 | module_param_array(video_nr, short, ¶m_nv[0], 0444); | 114 | module_param_array(video_nr, short, ¶m_nv[0], 0444); |
119 | module_param_array(packet_size, uint, ¶m_nv[1], 0444); | 115 | module_param_array(packet_size, uint, ¶m_nv[1], 0444); |
@@ -144,18 +140,6 @@ module_param(debug, ushort, 0644); | |||
144 | module_param(specific_debug, bool, 0644); | 140 | module_param(specific_debug, bool, 0644); |
145 | #endif | 141 | #endif |
146 | 142 | ||
147 | #ifdef CONFIG_MODULES | ||
148 | MODULE_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 | ||
159 | MODULE_PARM_DESC(simcams, | 143 | MODULE_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*); |
445 | static u32 w9968cf_i2c_func(struct i2c_adapter*); | 429 | static u32 w9968cf_i2c_func(struct i2c_adapter*); |
446 | static int w9968cf_i2c_attach_inform(struct i2c_client*); | ||
447 | static int w9968cf_i2c_detach_inform(struct i2c_client*); | ||
448 | 430 | ||
449 | /* Memory management */ | 431 | /* Memory management */ |
450 | static void* rvmalloc(unsigned long size); | 432 | static 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 | ||
1507 | static 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 | |||
1532 | static 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 | |||
1545 | static int w9968cf_i2c_init(struct w9968cf_device* cam) | 1489 | static 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) | |||
2165 | static int | 2107 | static int |
2166 | w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg) | 2108 | w9968cf_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 | ||
3589 | fail: /* Free unused memory */ | 3534 | fail: /* 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 | ||
279 | static 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 * |