diff --git a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
index c841f4e4fbe4903d45f1877e982c9aaebda7e73e..21ec1dd2e1e5ff972bf77c87e3400624f8970a63 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c
@@ -15,6 +15,9 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-i2c-drv.h>
 #include "ovcamchip_priv.h"
 
 #define DRIVER_VERSION "v2.27 for Linux 2.6"
@@ -44,6 +47,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
+
 /* Registers common to all chips, that are needed for detection */
 #define GENERIC_REG_ID_HIGH       0x1C	/* manufacturer ID MSB */
 #define GENERIC_REG_ID_LOW        0x1D	/* manufacturer ID LSB */
@@ -61,10 +65,6 @@ static char *chip_names[NUM_CC_TYPES] = {
 	[CC_OV6630AF]	= "OV6630AF",
 };
 
-/* Forward declarations */
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
 /* ----------------------------------------------------------------------- */
 
 int ov_write_regvals(struct i2c_client *c, struct ovcamchip_regvals *rvals)
@@ -253,112 +253,36 @@ static int ovcamchip_detect(struct i2c_client *c)
 
 	/* Test for 7xx0 */
 	PDEBUG(3, "Testing for 0V7xx0");
-	c->addr = OV7xx0_SID;
-	if (init_camchip(c) < 0) {
-		/* Test for 6xx0 */
-		PDEBUG(3, "Testing for 0V6xx0");
-		c->addr = OV6xx0_SID;
-		if (init_camchip(c) < 0) {
-			return -ENODEV;
-		} else {
-			if (ov6xx0_detect(c) < 0) {
-				PERROR("Failed to init OV6xx0");
-				return -EIO;
-			}
-		}
-	} else {
+	if (init_camchip(c) < 0)
+		return -ENODEV;
+	/* 7-bit addresses with bit 0 set are for the OV7xx0 */
+	if (c->addr & 1) {
 		if (ov7xx0_detect(c) < 0) {
 			PERROR("Failed to init OV7xx0");
 			return -EIO;
 		}
+		return 0;
+	}
+	/* Test for 6xx0 */
+	PDEBUG(3, "Testing for 0V6xx0");
+	if (ov6xx0_detect(c) < 0) {
+		PERROR("Failed to init OV6xx0");
+		return -EIO;
 	}
-
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
-static int ovcamchip_attach(struct i2c_adapter *adap)
-{
-	int rc = 0;
-	struct ovcamchip *ov;
-	struct i2c_client *c;
-
-	/* I2C is not a PnP bus, so we can never be certain that we're talking
-	 * to the right chip. To prevent damage to EEPROMS and such, only
-	 * attach to adapters that are known to contain OV camera chips. */
-
-	switch (adap->id) {
-	case I2C_HW_SMBUS_OV511:
-	case I2C_HW_SMBUS_OV518:
-	case I2C_HW_SMBUS_W9968CF:
-		PDEBUG(1, "Adapter ID 0x%06x accepted", adap->id);
-		break;
-	default:
-		PDEBUG(1, "Adapter ID 0x%06x rejected", adap->id);
-		return -ENODEV;
-	}
-
-	c = kmalloc(sizeof *c, GFP_KERNEL);
-	if (!c) {
-		rc = -ENOMEM;
-		goto no_client;
-	}
-	memcpy(c, &client_template, sizeof *c);
-	c->adapter = adap;
-	strcpy(c->name, "OV????");
-
-	ov = kzalloc(sizeof *ov, GFP_KERNEL);
-	if (!ov) {
-		rc = -ENOMEM;
-		goto no_ov;
-	}
-	i2c_set_clientdata(c, ov);
-
-	rc = ovcamchip_detect(c);
-	if (rc < 0)
-		goto error;
-
-	strcpy(c->name, chip_names[ov->subtype]);
-
-	PDEBUG(1, "Camera chip detection complete");
-
-	i2c_attach_client(c);
-
-	return rc;
-error:
-	kfree(ov);
-no_ov:
-	kfree(c);
-no_client:
-	PDEBUG(1, "returning %d", rc);
-	return rc;
-}
-
-static int ovcamchip_detach(struct i2c_client *c)
+static long ovcamchip_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
-	struct ovcamchip *ov = i2c_get_clientdata(c);
-	int rc;
-
-	rc = ov->sops->free(c);
-	if (rc < 0)
-		return rc;
-
-	i2c_detach_client(c);
-
-	kfree(ov);
-	kfree(c);
-	return 0;
-}
-
-static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
-{
-	struct ovcamchip *ov = i2c_get_clientdata(c);
+	struct ovcamchip *ov = to_ovcamchip(sd);
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
 
 	if (!ov->initialized &&
 	    cmd != OVCAMCHIP_CMD_Q_SUBTYPE &&
 	    cmd != OVCAMCHIP_CMD_INITIALIZE) {
-		dev_err(&c->dev, "ERROR: Camera chip not initialized yet!\n");
+		v4l2_err(sd, "Camera chip not initialized yet!\n");
 		return -EPERM;
 	}
 
@@ -379,10 +303,10 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
 
 		if (ov->mono) {
 			if (ov->subtype != CC_OV7620)
-				dev_warn(&c->dev, "Warning: Monochrome not "
+				v4l2_warn(sd, "Monochrome not "
 					"implemented for this chip\n");
 			else
-				dev_info(&c->dev, "Initializing chip as "
+				v4l2_info(sd, "Initializing chip as "
 					"monochrome\n");
 		}
 
@@ -398,37 +322,80 @@ static int ovcamchip_command(struct i2c_client *c, unsigned int cmd, void *arg)
 	}
 }
 
+static int ovcamchip_command(struct i2c_client *client, unsigned cmd, void *arg)
+{
+	return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
+}
+
 /* ----------------------------------------------------------------------- */
 
-static struct i2c_driver driver = {
-	.driver = {
-		.name =		"ovcamchip",
-	},
-	.id =			I2C_DRIVERID_OVCAMCHIP,
-	.attach_adapter =	ovcamchip_attach,
-	.detach_client =	ovcamchip_detach,
-	.command =		ovcamchip_command,
+static const struct v4l2_subdev_core_ops ovcamchip_core_ops = {
+	.ioctl = ovcamchip_ioctl,
 };
 
-static struct i2c_client client_template = {
-	.name =		"(unset)",
-	.driver =	&driver,
+static const struct v4l2_subdev_ops ovcamchip_ops = {
+	.core = &ovcamchip_core_ops,
 };
 
-static int __init ovcamchip_init(void)
+static int ovcamchip_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
 {
-#ifdef DEBUG
-	ovcamchip_debug = debug;
-#endif
+	struct ovcamchip *ov;
+	struct v4l2_subdev *sd;
+	int rc = 0;
 
-	PINFO(DRIVER_VERSION " : " DRIVER_DESC);
-	return i2c_add_driver(&driver);
+	ov = kzalloc(sizeof *ov, GFP_KERNEL);
+	if (!ov) {
+		rc = -ENOMEM;
+		goto no_ov;
+	}
+	sd = &ov->sd;
+	v4l2_i2c_subdev_init(sd, client, &ovcamchip_ops);
+
+	rc = ovcamchip_detect(client);
+	if (rc < 0)
+		goto error;
+
+	v4l_info(client, "%s found @ 0x%02x (%s)\n",
+			chip_names[ov->subtype], client->addr << 1, client->adapter->name);
+
+	PDEBUG(1, "Camera chip detection complete");
+
+	return rc;
+error:
+	kfree(ov);
+no_ov:
+	PDEBUG(1, "returning %d", rc);
+	return rc;
 }
 
-static void __exit ovcamchip_exit(void)
+static int ovcamchip_remove(struct i2c_client *client)
 {
-	i2c_del_driver(&driver);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ovcamchip *ov = to_ovcamchip(sd);
+	int rc;
+
+	v4l2_device_unregister_subdev(sd);
+	rc = ov->sops->free(client);
+	if (rc < 0)
+		return rc;
+
+	kfree(ov);
+	return 0;
 }
 
-module_init(ovcamchip_init);
-module_exit(ovcamchip_exit);
+/* ----------------------------------------------------------------------- */
+
+static const struct i2c_device_id ovcamchip_id[] = {
+	{ "ovcamchip", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ovcamchip_id);
+
+static struct v4l2_i2c_driver_data v4l2_i2c_data = {
+	.name = "ovcamchip",
+	.command = ovcamchip_command,
+	.probe = ovcamchip_probe,
+	.remove = ovcamchip_remove,
+	.id_table = ovcamchip_id,
+};
diff --git a/drivers/media/video/ovcamchip/ovcamchip_priv.h b/drivers/media/video/ovcamchip/ovcamchip_priv.h
index a05650faedda435363e6bfeb5339b51fe896541e..4f07b78c88bc347f8fd5c7ef7214dc748074f9d3 100644
--- a/drivers/media/video/ovcamchip/ovcamchip_priv.h
+++ b/drivers/media/video/ovcamchip/ovcamchip_priv.h
@@ -16,6 +16,7 @@
 #define __LINUX_OVCAMCHIP_PRIV_H
 
 #include <linux/i2c.h>
+#include <media/v4l2-subdev.h>
 #include <media/ovcamchip.h>
 
 #ifdef DEBUG
@@ -46,6 +47,7 @@ struct ovcamchip_ops {
 };
 
 struct ovcamchip {
+	struct v4l2_subdev sd;
 	struct ovcamchip_ops *sops;
 	void *spriv;               /* Private data for OV7x10.c etc... */
 	int subtype;               /* = SEN_OV7610 etc... */
@@ -53,6 +55,11 @@ struct ovcamchip {
 	int initialized;           /* OVCAMCHIP_CMD_INITIALIZE was successful */
 };
 
+static inline struct ovcamchip *to_ovcamchip(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ovcamchip, sd);
+}
+
 extern struct ovcamchip_ops ov6x20_ops;
 extern struct ovcamchip_ops ov6x30_ops;
 extern struct ovcamchip_ops ov7x10_ops;
diff --git a/drivers/media/video/w9968cf.c b/drivers/media/video/w9968cf.c
index 3318be5688c9aa65cdca3686ae4b8c9ff1f9ff1a..fd5c4c87a73b4b30204acb54c75390f40e3a1b05 100644
--- a/drivers/media/video/w9968cf.c
+++ b/drivers/media/video/w9968cf.c
@@ -68,7 +68,6 @@ MODULE_VERSION(W9968CF_MODULE_VERSION);
 MODULE_LICENSE(W9968CF_MODULE_LICENSE);
 MODULE_SUPPORTED_DEVICE("Video");
 
-static int ovmod_load = W9968CF_OVMOD_LOAD;
 static unsigned short simcams = W9968CF_SIMCAMS;
 static short video_nr[]={[0 ... W9968CF_MAX_DEVICES-1] = -1}; /*-1=first free*/
 static unsigned int packet_size[] = {[0 ... W9968CF_MAX_DEVICES-1] =
@@ -111,9 +110,6 @@ static int specific_debug = W9968CF_SPECIFIC_DEBUG;
 
 static unsigned int param_nv[24]; /* number of values per parameter */
 
-#ifdef CONFIG_MODULES
-module_param(ovmod_load, bool, 0644);
-#endif
 module_param(simcams, ushort, 0644);
 module_param_array(video_nr, short, &param_nv[0], 0444);
 module_param_array(packet_size, uint, &param_nv[1], 0444);
@@ -144,18 +140,6 @@ module_param(debug, ushort, 0644);
 module_param(specific_debug, bool, 0644);
 #endif
 
-#ifdef CONFIG_MODULES
-MODULE_PARM_DESC(ovmod_load,
-		 "\n<0|1> Automatic 'ovcamchip' module loading."
-		 "\n0 disabled, 1 enabled."
-		 "\nIf enabled,'insmod' searches for the required 'ovcamchip'"
-		 "\nmodule in the system, according to its configuration, and"
-		 "\nattempts to load that module automatically. This action is"
-		 "\nperformed once as soon as the 'w9968cf' module is loaded"
-		 "\ninto memory."
-		 "\nDefault value is "__MODULE_STRING(W9968CF_OVMOD_LOAD)"."
-		 "\n");
-#endif
 MODULE_PARM_DESC(simcams,
 		 "\n<n> Number of cameras allowed to stream simultaneously."
 		 "\nn may vary from 0 to "
@@ -443,8 +427,6 @@ static int w9968cf_i2c_smbus_xfer(struct i2c_adapter*, u16 addr,
 				  unsigned short flags, char read_write,
 				  u8 command, int size, union i2c_smbus_data*);
 static u32 w9968cf_i2c_func(struct i2c_adapter*);
-static int w9968cf_i2c_attach_inform(struct i2c_client*);
-static int w9968cf_i2c_detach_inform(struct i2c_client*);
 
 /* Memory management */
 static void* rvmalloc(unsigned long size);
@@ -1443,19 +1425,11 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
 		       unsigned short flags, char read_write, u8 command,
 		       int size, union i2c_smbus_data *data)
 {
-	struct w9968cf_device* cam = i2c_get_adapdata(adapter);
+	struct v4l2_device *v4l2_dev = i2c_get_adapdata(adapter);
+	struct w9968cf_device *cam = to_cam(v4l2_dev);
 	u8 i;
 	int err = 0;
 
-	switch (addr) {
-		case OV6xx0_SID:
-		case OV7xx0_SID:
-			break;
-		default:
-			DBG(4, "Rejected slave ID 0x%04X", addr)
-			return -EINVAL;
-	}
-
 	if (size == I2C_SMBUS_BYTE) {
 		/* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */
 		addr <<= 1;
@@ -1463,8 +1437,17 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
 		if (read_write == I2C_SMBUS_WRITE)
 			err = w9968cf_i2c_adap_write_byte(cam, addr, command);
 		else if (read_write == I2C_SMBUS_READ)
-			err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte);
-
+			for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) {
+				err = w9968cf_i2c_adap_read_byte(cam, addr,
+							 &data->byte);
+				if (err) {
+					if (w9968cf_smbus_refresh_bus(cam)) {
+						err = -EIO;
+						break;
+					}
+				} else
+					break;
+			}
 	} else if (size == I2C_SMBUS_BYTE_DATA) {
 		addr <<= 1;
 
@@ -1491,7 +1474,6 @@ w9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
 		DBG(4, "Unsupported I2C transfer mode (%d)", size)
 		return -EINVAL;
 	}
-
 	return err;
 }
 
@@ -1504,44 +1486,6 @@ static u32 w9968cf_i2c_func(struct i2c_adapter* adap)
 }
 
 
-static int w9968cf_i2c_attach_inform(struct i2c_client* client)
-{
-	struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
-	int id = client->driver->id, err = 0;
-
-	if (id == I2C_DRIVERID_OVCAMCHIP) {
-		cam->sensor_client = client;
-		err = w9968cf_sensor_init(cam);
-		if (err) {
-			cam->sensor_client = NULL;
-			return err;
-		}
-	} else {
-		DBG(4, "Rejected client [%s] with driver [%s]",
-		    client->name, client->driver->driver.name)
-		return -EINVAL;
-	}
-
-	DBG(5, "I2C attach client [%s] with driver [%s]",
-	    client->name, client->driver->driver.name)
-
-	return 0;
-}
-
-
-static int w9968cf_i2c_detach_inform(struct i2c_client* client)
-{
-	struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);
-
-	if (cam->sensor_client == client)
-		cam->sensor_client = NULL;
-
-	DBG(5, "I2C detach client [%s]", client->name)
-
-	return 0;
-}
-
-
 static int w9968cf_i2c_init(struct w9968cf_device* cam)
 {
 	int err = 0;
@@ -1554,15 +1498,13 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam)
 	static struct i2c_adapter adap = {
 		.id =                I2C_HW_SMBUS_W9968CF,
 		.owner =             THIS_MODULE,
-		.client_register =   w9968cf_i2c_attach_inform,
-		.client_unregister = w9968cf_i2c_detach_inform,
 		.algo =              &algo,
 	};
 
 	memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter));
 	strcpy(cam->i2c_adapter.name, "w9968cf");
 	cam->i2c_adapter.dev.parent = &cam->usbdev->dev;
-	i2c_set_adapdata(&cam->i2c_adapter, cam);
+	i2c_set_adapdata(&cam->i2c_adapter, &cam->v4l2_dev);
 
 	DBG(6, "Registering I2C adapter with kernel...")
 
@@ -2165,13 +2107,9 @@ w9968cf_sensor_get_control(struct w9968cf_device* cam, int cid, int* val)
 static int
 w9968cf_sensor_cmd(struct w9968cf_device* cam, unsigned int cmd, void* arg)
 {
-	struct i2c_client* c = cam->sensor_client;
-	int rc = 0;
+	int rc;
 
-	if (!c || !c->driver || !c->driver->command)
-		return -EINVAL;
-
-	rc = c->driver->command(c, cmd, arg);
+	rc = v4l2_subdev_call(cam->sensor_sd, core, ioctl, cmd, arg);
 	/* The I2C driver returns -EPERM on non-supported controls */
 	return (rc < 0 && rc != -EPERM) ? rc : 0;
 }
@@ -2346,7 +2284,7 @@ static int w9968cf_sensor_init(struct w9968cf_device* cam)
 		goto error;
 
 	/* NOTE: Make sure width and height are a multiple of 16 */
-	switch (cam->sensor_client->addr) {
+	switch (v4l2_i2c_subdev_addr(cam->sensor_sd)) {
 		case OV6xx0_SID:
 			cam->maxwidth = 352;
 			cam->maxheight = 288;
@@ -2651,6 +2589,7 @@ static void w9968cf_release_resources(struct w9968cf_device* cam)
 	w9968cf_deallocate_memory(cam);
 	kfree(cam->control_buffer);
 	kfree(cam->data_buffer);
+	v4l2_device_unregister(&cam->v4l2_dev);
 
 	mutex_unlock(&w9968cf_devlist_mutex);
 }
@@ -3480,6 +3419,11 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
 	struct list_head* ptr;
 	u8 sc = 0; /* number of simultaneous cameras */
 	static unsigned short dev_nr; /* 0 - we are handling device number n */
+	static unsigned short addrs[] = {
+		OV7xx0_SID,
+		OV6xx0_SID,
+		I2C_CLIENT_END
+	};
 
 	if (le16_to_cpu(udev->descriptor.idVendor)  == winbond_id_table[0].idVendor &&
 	    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)
 	w9968cf_turn_on_led(cam);
 
 	w9968cf_i2c_init(cam);
+	cam->sensor_sd = v4l2_i2c_new_probed_subdev(&cam->i2c_adapter,
+			"ovcamchip", "ovcamchip", addrs);
 
 	usb_set_intfdata(intf, cam);
 	mutex_unlock(&cam->dev_mutex);
 
-	if (ovmod_load)
-		request_module("ovcamchip");
+	err = w9968cf_sensor_init(cam);
 	return 0;
 
 fail: /* Free unused memory */
@@ -3604,9 +3549,8 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf)
 	struct w9968cf_device* cam =
 	   (struct w9968cf_device*)usb_get_intfdata(intf);
 
-	down_write(&w9968cf_disconnect);
-
 	if (cam) {
+		down_write(&w9968cf_disconnect);
 		/* Prevent concurrent accesses to data */
 		mutex_lock(&cam->dev_mutex);
 
@@ -3628,14 +3572,12 @@ static void w9968cf_usb_disconnect(struct usb_interface* intf)
 			w9968cf_release_resources(cam);
 
 		mutex_unlock(&cam->dev_mutex);
+		up_write(&w9968cf_disconnect);
 
 		if (!cam->users) {
-			v4l2_device_unregister(&cam->v4l2_dev);
 			kfree(cam);
 		}
 	}
-
-	up_write(&w9968cf_disconnect);
 }
 
 
diff --git a/drivers/media/video/w9968cf.h b/drivers/media/video/w9968cf.h
index c5988355254525577f024b1997c1069987b74ea9..fdfc6a4e1c8f92b703f137102404cd81177c5076 100644
--- a/drivers/media/video/w9968cf.h
+++ b/drivers/media/video/w9968cf.h
@@ -43,7 +43,6 @@
  * Default values                                                           *
  ****************************************************************************/
 
-#define W9968CF_OVMOD_LOAD      1  /* automatic 'ovcamchip' module loading */
 #define W9968CF_VPPMOD_LOAD     1  /* automatic 'w9968cf-vpp' module loading */
 
 /* Comment/uncomment the following line to enable/disable debugging messages */
@@ -265,7 +264,7 @@ struct w9968cf_device {
 
 	/* I2C interface to kernel */
 	struct i2c_adapter i2c_adapter;
-	struct i2c_client* sensor_client;
+	struct v4l2_subdev *sensor_sd;
 
 	/* Locks */
 	struct mutex dev_mutex,    /* for probe, disconnect,open and close */
@@ -277,6 +276,11 @@ struct w9968cf_device {
 	char command[16]; /* name of the program holding the device */
 };
 
+static inline struct w9968cf_device *to_cam(struct v4l2_device *v4l2_dev)
+{
+	return container_of(v4l2_dev, struct w9968cf_device, v4l2_dev);
+}
+
 
 /****************************************************************************
  * Macros for debugging                                                     *