diff -Naur linux-2.3.99-pre6-orig/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt
--- linux-2.3.99-pre6-orig/Documentation/usb/ov511.txt	Thu Apr 13 23:23:28 2000
+++ linux/Documentation/usb/ov511.txt	Fri May  5 14:34:20 2000
@@ -6,8 +6,11 @@
 Homepage: http://alpha.dyndns.org/ov511
 
 NEW IN THIS VERSION:
- o Support for OV511+
- o Support for OV7620
+ o Improvements to sensor detection code
+ o Added "i2c_detect_tries" and "aperture" parameters
+ o proc filesystem status support
+ o read() fixed partially
+ o code cleanups and minor fixes
 
 INTRODUCTION:
 
@@ -151,11 +154,13 @@
  o Monochrome
  o Setting/getting of saturation, contrast and brightness (no hue yet; only
    works with OV7610, not the OV7620 or OV7620AE)
+ o proc status reporting
 
 EXPERIMENTAL FEATURES:
  o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and
    corrupted frames.
  o Snapshot mode (only works with some read() based apps; see below for more)
+ o read() support
 
 TODO:
  o Fix the noise / grainy image problem.
@@ -180,6 +185,8 @@
  o Get rid of the memory management functions (put them in videodev.c??)
  o Setting of contrast and brightness not working with 7620
  o Driver/camera state save/restore for when USB supports suspend/resume
+ o Multiple cameras reportedly do not work simultaneously
+ o Problems with OHCI
 
 HOW TO CONTACT ME:
 
diff -Naur linux-2.3.99-pre6-orig/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- linux-2.3.99-pre6-orig/drivers/usb/ov511.c	Thu Apr 13 23:23:44 2000
+++ linux/drivers/usb/ov511.c	Fri May  5 14:34:33 2000
@@ -1,23 +1,20 @@
 /*
  * OmniVision OV511 Camera-to-USB Bridge Driver
- * Copyright (c) 1999/2000 Mark W. McClelland
+ *
+ * Copyright (c) 1999-2000 Mark W. McClelland
  * Many improvements by Bret Wallach
  * Color fixes by by Orion Sky Lawlor, olawlor@acm.org, 2/26/2000
  * Snapshot code by Kevin Moore
  * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
+ * Changes by Claudio Matsuoka, claudio@conectiva.com, 3/26/2000
  * 
- * Based on the Linux CPiA driver.
+ * Based on the Linux CPiA driver written by Peter Pregler,
+ * Scott J. Bertin and Johannes Erdfelt.
  * 
- * Released under GPL v.2 license.
- *
- * Version: 1.11
- *
  * Please see the file: linux/Documentation/usb/ov511.txt 
- * and the website at:  http://alpha.dyndns.org/ov511 
+ * and the website at:  http://alpha.dyndns.org/ov511
  * for more info.
- */
-
-/*
+ *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
@@ -33,23 +30,28 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+static const char version[] = "1.12";
+
 #define __NO_VERSION__
 
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-#include <linux/smp_lock.h>
-#include <linux/videodev.h>
-#include <linux/vmalloc.h>
-#include <linux/wrapper.h>
+#include <linux/config.h>
 #include <linux/module.h>
+#include <linux/version.h>
 #include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/time.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/pagemap.h>
 #include <linux/usb.h>
 #include <asm/io.h>
+#include <asm/semaphore.h>
+#include <linux/wrapper.h>
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
 
 #include "ov511.h"
 
@@ -59,11 +61,10 @@
 #define MAX_FRAME_SIZE (640 * 480 * 3)
 #define MAX_DATA_SIZE (MAX_FRAME_SIZE + sizeof(struct timeval))
 
-// FIXME - Should find a better way to do this.
 #define DEFAULT_WIDTH 640
 #define DEFAULT_HEIGHT 480
 
-// PARAMETER VARIABLES:
+/* PARAMETER VARIABLES: */
 static int autoadjust = 1;    /* CCD dynamically changes exposure, etc... */
 
 /* 0=no debug messages
@@ -85,24 +86,89 @@
 /* Sensor detection override (global for all attached cameras) */
 static int sensor = 0;
 
+/* Increase this if you are getting "Failed to read sensor ID..." */
+static int i2c_detect_tries = 5;
+
+/* For legal values, see the OV7610/7620 specs under register Common F,
+   upper nybble  (set to 0-F) */
+static int aperture = -1;
+
 MODULE_PARM(autoadjust, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(fix_rgb_offset, "i");
 MODULE_PARM(snapshot, "i");
 MODULE_PARM(sensor, "i");
+MODULE_PARM(i2c_detect_tries, "i");
+MODULE_PARM(aperture, "i");
 
 MODULE_AUTHOR("Mark McClelland (and others)");
 MODULE_DESCRIPTION("OV511 USB Camera Driver");
 
 char kernel_version[] = UTS_RELEASE;
 
-/*******************************/
-/* Memory management functions */
-/*******************************/
+static struct usb_driver ov511_driver;
 
-#define MDEBUG(x)	do { } while(0)		/* Debug memory management */
+/**********************************************************************
+ * List of known OV511-based cameras
+ **********************************************************************/
+
+static struct cam_list clist[] = {
+	{   0, "generic model (no ID)" },
+	{   3, "D-Link DSB-C300" },
+	{   4, "generic OV511/OV7610" },
+	{   5, "Puretek PT-6007" },
+	{  21, "Creative Labs WebCam 3" },
+	{  36, "Koala-Cam" },
+	{  38, "Lifeview USB Life TV" },	/* No support yet! */
+	{ 100, "Lifeview RoboCam" },
+	{ 102, "AverMedia InterCam Elite" },
+	{ 112, "MediaForte MV300" },	/* or OV7110 evaluation kit */
+	{  -1, NULL }
+};
 
-static struct usb_driver ov511_driver;
+/**********************************************************************
+ *
+ * Memory management
+ *
+ * This is a shameless copy from the USB-cpia driver (linux kernel
+ * version 2.3.29 or so, I have no idea what this code actually does ;).
+ * Actually it seems to be a copy of a shameless copy of the bttv-driver.
+ * Or that is a copy of a shameless copy of ... (To the powers: is there
+ * no generic kernel-function to do this sort of stuff?)
+ *
+ * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
+ * there will be one, but apparentely not yet -jerdfelt
+ *
+ * So I copied it again for the OV511 driver -claudio
+ **********************************************************************/
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+
+static inline unsigned long uvirt_to_phys(unsigned long adr)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *ptep, pte;
+
+	pgd = pgd_offset(current->mm, adr);
+	if (pgd_none(*pgd))
+		return 0;
+	pmd = pmd_offset(pgd, adr);
+	if (pmd_none(*pmd))
+		return 0;
+	ptep = pte_offset(pmd, adr/*&(~PGDIR_MASK)*/);
+	pte = *ptep;
+	if (pte_present(pte))
+		return virt_to_phys((void *)(pte_page(pte)|(adr&(PAGE_SIZE-1))));
+	return 0;
+}
+
+static inline unsigned long kvirt_to_pa(unsigned long adr) 
+{
+	return uvirt_to_phys(VMALLOC_VMADDR(adr));
+}
+
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) */
 
 /* Given PGD from the address space's page table, return the kernel
  * virtual mapping of the physical memory mapped at ADR.
@@ -119,31 +185,11 @@
 			ptep = pte_offset(pmd, adr);
 			pte = *ptep;
 			if (pte_present(pte))
-				ret = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1));
+				ret = page_address(pte_page(pte)) |
+				      (adr & (PAGE_SIZE-1));
 		}
 	}
-	MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
-	return ret;
-}
-
-static inline unsigned long uvirt_to_bus(unsigned long adr)
-{
-	unsigned long kva, ret;
 
-	kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
-	ret = virt_to_bus((void *)kva);
-	MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
-	return ret;
-}
-
-static inline unsigned long kvirt_to_bus(unsigned long adr)
-{
-	unsigned long va, kva, ret;
-
-	va = VMALLOC_VMADDR(adr);
-	kva = uvirt_to_kva(pgd_offset_k(va), va);
-	ret = virt_to_bus((void *)kva);
-	MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
 	return ret;
 }
 
@@ -158,9 +204,10 @@
 	va = VMALLOC_VMADDR(adr);
 	kva = uvirt_to_kva(pgd_offset_k(va), va);
 	ret = __pa(kva);
-	MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
 	return ret;
 }
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) */
+
 
 static void *rvmalloc(unsigned long size)
 {
@@ -179,7 +226,11 @@
 	adr = (unsigned long) mem;
 	while (size > 0) {
 		page = kvirt_to_pa(adr);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		mem_map_reserve(MAP_NR(phys_to_virt(page)));
+#else
 		mem_map_reserve(MAP_NR(__va(page)));
+#endif
 		adr += PAGE_SIZE;
 		if (size > PAGE_SIZE)
 			size -= PAGE_SIZE;
@@ -203,7 +254,11 @@
 	adr=(unsigned long) mem;
 	while (size > 0) {
 		page = kvirt_to_pa(adr);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		mem_map_unreserve(MAP_NR(phys_to_virt(page)));
+#else
 		mem_map_unreserve(MAP_NR(__va(page)));
+#endif
 		adr += PAGE_SIZE;
 		if (size > PAGE_SIZE)
 			size -= PAGE_SIZE;
@@ -213,9 +268,290 @@
 	vfree(mem);
 }
 
+/**********************************************************************
+ * /proc interface
+ * Based on the CPiA driver version 0.7.4 -claudio
+ **********************************************************************/
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *ov511_proc_root = NULL;
+
+#define YES_NO(x) (x ? "yes" : "no")
+
+static int ov511_read_proc(char *page, char **start, off_t off,
+                          int count, int *eof, void *data)
+{
+	char *out = page;
+	int i, len;
+	struct usb_ov511 *ov511 = data;
+
+	/* IMPORTANT: This output MUST be kept under PAGE_SIZE
+	 *            or we need to get more sophisticated. */
+
+	out += sprintf (out, "custom_id       : %d\n", ov511->customid);
+	out += sprintf (out, "model           : %s\n", ov511->desc ?
+		clist[ov511->desc].description : "unknown");
+	out += sprintf (out, "streaming       : %s\n", YES_NO (ov511->streaming));
+	out += sprintf (out, "grabbing        : %s\n", YES_NO (ov511->grabbing));
+	out += sprintf (out, "compress        : %s\n", YES_NO (ov511->compress));
+	out += sprintf (out, "subcapture      : %s\n", YES_NO (ov511->sub_flag));
+	out += sprintf (out, "sub_size        : %d %d %d %d\n",
+		ov511->subx, ov511->suby, ov511->subw, ov511->subh);
+	out += sprintf (out, "num_frames      : %d\n", OV511_NUMFRAMES);
+	for (i = 0; i < OV511_NUMFRAMES; i++) {
+		out += sprintf (out, "frame           : %d\n", i);
+		out += sprintf (out, "  depth         : %d\n",
+			ov511->frame[i].depth);
+		out += sprintf (out, "  size          : %d %d\n",
+			ov511->frame[i].width, ov511->frame[i].height);
+		out += sprintf (out, "  hdr_size      : %d %d\n",
+			ov511->frame[i].hdrwidth, ov511->frame[i].hdrheight);
+		out += sprintf (out, "  format        : %d\n",
+			ov511->frame[i].format);
+		out += sprintf (out, "  segsize       : %d\n",
+			ov511->frame[i].segsize);
+#if 0
+		out += sprintf (out, "  curline       : %d\n",
+			ov511->frame[i].curline);
+		out += sprintf (out, "  segment       : %d\n",
+			ov511->frame[i].segment);
+		out += sprintf (out, "  scanlength    : %ld\n",
+			ov511->frame[i].scanlength);
+		out += sprintf (out, "  bytesread     : %ld\n",
+			ov511->frame[i].bytes_read);
+#endif
+	}
+	out += sprintf (out, "snap_enabled    : %s\n", YES_NO (ov511->snap_enabled));
+	out += sprintf (out, "bridge          : %d\n", ov511->bridge);
+	out += sprintf (out, "sensor          : %d\n", ov511->sensor);
+	out += sprintf (out, "packet_size     : %d\n", ov511->packet_size);
+	
+	len = out - page;
+	len -= off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0) return 0;
+	} else
+		len = count;
+
+	*start = page + off;
+	return len;
+}
+
+static int ov511_write_proc(struct file *file, const char *buffer,
+                           unsigned long count, void *data)
+{
+	int retval = -EINVAL;
+
+#if 0
+	/* struct cam_data *cam = data; */
+	struct usb_ov511 new_params;
+	int size = count;
+	int find_colon;
+	unsigned long val;
+	u32 command_flags = 0;
+	u8 new_mains;
+	
+	if (down_interruptible(&cam->param_lock))
+		return -ERESTARTSYS;
+	
+	/*
+	 * Skip over leading whitespace
+	 */
+	while (count && isspace(*buffer)) {
+		--count;
+		++buffer;
+	}
+	
+	
+#define MATCH(x) \
+	({ \
+		int _len = strlen(x), _ret, _colon_found; \
+		_ret = (_len <= count && strncmp(buffer, x, _len) == 0); \
+		if (_ret) { \
+			buffer += _len; \
+			count -= _len; \
+			if (find_colon) { \
+				_colon_found = 0; \
+				while (count && (*buffer == ' ' || *buffer == '\t' || \
+				       (!_colon_found && *buffer == ':'))) { \
+					if (*buffer == ':')  \
+						_colon_found = 1; \
+					--count; \
+					++buffer; \
+				} \
+				if (!count || !_colon_found) \
+					retval = -EINVAL; \
+				find_colon = 0; \
+			} \
+		} \
+		_ret; \
+	})
+
+#define VALUE \
+	({ \
+		char *_p; \
+		unsigned long int _ret; \
+		_ret = simple_strtoul(buffer, &_p, 0); \
+		if (_p == buffer) \
+			retval = -EINVAL; \
+		else { \
+			count -= _p - buffer; \
+			buffer = _p; \
+		} \
+		_ret; \
+	})
+
+
+	retval = 0;
+	while (count && !retval) {
+		find_colon = 1;
+
+		if (MATCH("")) {
+			if (!retval)
+				val = VALUE;
+
+			if (!retval) {
+				if (val <= 0xff)
+					/* ... = val */ ;
+				else
+					retval = -EINVAL;
+			}
+		} else {
+			DBG("No match found\n");
+			retval = -EINVAL;
+		}
+
+		if (!retval) {
+			while (count && isspace(*buffer) && *buffer != '\n') {
+				--count;
+				++buffer;
+			}
+			if (count) {
+				if (*buffer != '\n' && *buffer != ';')
+					retval = -EINVAL;
+				else {
+					--count;
+					++buffer;
+				}
+			}
+		}
+	}
+
+#undef MATCH	
+#undef FIRMWARE_VERSION
+#undef VALUE
+#undef FIND_VALUE
+#undef FIND_END
+	if (!retval) {
+		if (command_flags & COMMAND_SETCOLOURPARAMS) {
+			/* Adjust cam->vp to reflect these changes */
+			cam->vp.brightness =
+				new_params.colourParams.brightness*65535/100;
+			cam->vp.contrast =
+				new_params.colourParams.contrast*65535/100;
+			cam->vp.colour =
+				new_params.colourParams.saturation*65535/100;
+		}
+		
+		memcpy(&cam->params, &new_params, sizeof(struct cam_params));
+		cam->mainsFreq = new_mains;
+		cam->cmd_queue |= command_flags;
+		retval = size;
+	} else
+		PDEBUG(3, "error: %d\n", retval);
+	
+	up(&cam->param_lock);
+#endif
+	
+	return retval;
+}
+
+static void create_proc_ov511_cam (struct usb_ov511 *ov511)
+{
+	char name[7];
+	struct proc_dir_entry *ent;
+	
+	PDEBUG (4, "***************");
+	if (!ov511_proc_root || !ov511)
+		return;
+
+	sprintf(name, "video%d", ov511->vdev.minor);
+	PDEBUG (4, "==== name: %s", name);
+	
+	ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_root);
+	if (!ent)
+		return;
+
+	ent->data = ov511;
+	ent->read_proc = ov511_read_proc;
+	ent->write_proc = ov511_write_proc;
+	ent->size = 3626;	/* FIXME */
+	ov511->proc_entry = ent;
+}
+
+static void destroy_proc_ov511_cam (struct usb_ov511 *ov511)
+{
+	char name[7];
+	
+	if (!ov511 || !ov511->proc_entry)
+		return;
+	
+	sprintf(name, "video%d", ov511->vdev.minor);
+	PDEBUG (4, "==== name: %s", name);
+#if 0
+	remove_proc_entry(name, ov511_proc_root);
+	ov511->proc_entry = NULL;
+#endif
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+/*
+ * This is called as the fill_inode function when an inode
+ * is going into (fill = 1) or out of service (fill = 0).
+ * We use it here to manage the module use counts.
+ */
+static void proc_ov511_modcount(struct inode *inode, int fill)
+{
+#ifdef MODULE
+	if (fill)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+#endif
+}
+#endif
+
+static void proc_ov511_create(void)
+{
+	ov511_proc_root = create_proc_entry("ov511", S_IFDIR, 0);
+
+	if (ov511_proc_root) {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		ov511_proc_root->fill_inode = &proc_ov511_modcount;
+#else
+		ov511_proc_root->owner = THIS_MODULE;
+#endif
+	} else
+		printk("Unable to initialise /proc/ov511\n");	/***********/
+}
+
+static void proc_ov511_destroy(void)
+{
+	remove_proc_entry("ov511", 0);
+}
+#endif /* CONFIG_PROC_FS */
+
+
+/**********************************************************************
+ *
+ * Camera interface
+ *
+ **********************************************************************/
+
 static int ov511_reg_write(struct usb_device *dev,
-                           unsigned char reg,
-                           unsigned char value)
+			   unsigned char reg,
+			   unsigned char value)
 {
 	int rc;
 
@@ -233,6 +569,7 @@
 	return rc;
 }
 
+
 /* returns: negative is error, pos or zero is data */
 static int ov511_reg_read(struct usb_device *dev, unsigned char reg)
 {
@@ -247,24 +584,25 @@
                                
 	PDEBUG(5, "reg read: 0x%02X:0x%02X", reg, buffer[0]);
 	
-	if(rc < 0) {
+	if (rc < 0) {
 		err("ov511_reg_read: error %d", rc);
 		return rc;
-	}
-	else
+	} else {
 		return buffer[0];	
+	}
 }
 
+
 static int ov511_i2c_write(struct usb_device *dev,
-                           unsigned char reg,
-                           unsigned char value)
+			   unsigned char reg,
+			   unsigned char value)
 {
 	int rc, retries;
 
 	PDEBUG(5, "i2c write: 0x%02X:0x%02X", reg, value);
 
 	/* Three byte write cycle */
-	for(retries = OV511_I2C_RETRIES;;) {
+	for (retries = OV511_I2C_RETRIES; ; ) {
 		/* Select camera register */
 		rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);
 		if (rc < 0) goto error;
@@ -278,10 +616,10 @@
 		if (rc < 0) goto error;
 
 		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
-		while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
 		if (rc < 0) goto error;
 
-		if((rc&2) == 0) /* Ack? */
+		if ((rc&2) == 0) /* Ack? */
 			break;
 #if 0
 		/* I2C abort */	
@@ -301,13 +639,14 @@
 	return rc;
 }
 
+
 /* returns: negative is error, pos or zero is data */
 static int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
 {
 	int rc, value, retries;
 
 	/* Two byte write cycle */
-	for(retries = OV511_I2C_RETRIES;;) {
+	for (retries = OV511_I2C_RETRIES; ; ) {
 		/* Select camera register */
 		rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);
 		if (rc < 0) goto error;
@@ -317,10 +656,10 @@
 		if (rc < 0) goto error;
 
 		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
-		while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
 		if (rc < 0) goto error;
 
-		if((rc&2) == 0) /* Ack? */
+		if ((rc&2) == 0) /* Ack? */
 			break;
 
 		/* I2C abort */	
@@ -334,16 +673,16 @@
 	}
 
 	/* Two byte read cycle */
-	for(retries = OV511_I2C_RETRIES;;) {
+	for (retries = OV511_I2C_RETRIES; ; ) {
 		/* Initiate 2-byte read cycle */
 		rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
 		if (rc < 0) goto error;
 
 		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
-		while(rc > 0 && ((rc&1) == 0)); /* Retry until idle */
+		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
 		if (rc < 0) goto error;
 
-		if((rc&2) == 0) /* Ack? */
+		if ((rc&2) == 0) /* Ack? */
 			break;
 
 		/* I2C abort */	
@@ -363,7 +702,8 @@
 		
 	/* This is needed to make ov511_i2c_write() work */
 	rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
-	if (rc < 0) goto error;
+	if (rc < 0)
+		goto error;
 	
 	return value;
 
@@ -372,12 +712,13 @@
 	return rc;
 }
 
+
 static int ov511_write_regvals(struct usb_device *dev,
 			       struct ov511_regvals * pRegvals)
 {
 	int rc;
 
-	while(pRegvals->bus != OV511_DONE_BUS) {
+	while (pRegvals->bus != OV511_DONE_BUS) {
 		if (pRegvals->bus == OV511_REG_BUS) {
 			if ((rc = ov511_reg_write(dev, pRegvals->reg,
 			                           pRegvals->val)) < 0)
@@ -400,6 +741,7 @@
 	return rc;
 }
 
+
 #if 0
 static void ov511_dump_i2c_range( struct usb_device *dev, int reg1, int regn)
 {
@@ -411,12 +753,14 @@
 	}
 }
 
+
 static void ov511_dump_i2c_regs( struct usb_device *dev)
 {
 	PDEBUG(3, "I2C REGS");
 	ov511_dump_i2c_range(dev, 0x00, 0x38);
 }
 
+
 static void ov511_dump_reg_range( struct usb_device *dev, int reg1, int regn)
 {
 	int i;
@@ -427,6 +771,7 @@
 	}
 }
 
+
 static void ov511_dump_regs( struct usb_device *dev)
 {
 	PDEBUG(1, "CAMERA INTERFACE REGS");
@@ -451,6 +796,7 @@
 }
 #endif
 
+
 static int ov511_reset(struct usb_device *dev, unsigned char reset_type)
 {
 	int rc;
@@ -465,6 +811,7 @@
 	return rc;
 }
 
+
 /* Temporarily stops OV511 from functioning. Must do this before changing
  * registers while the camera is streaming */
 static inline int ov511_stop(struct usb_device *dev)
@@ -473,6 +820,7 @@
 	return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d));
 }
 
+
 /* Restarts OV511 after ov511_stop() is called */
 static inline int ov511_restart(struct usb_device *dev)
 {
@@ -480,6 +828,7 @@
 	return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00));
 }
 
+
 static int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
 {
 	int alt, mult;
@@ -487,7 +836,7 @@
 	if (ov511_stop(ov511->dev) < 0)
 		return -EIO;
 
-	mult = size / 32;
+	mult = size >> 5;
 
 	if (ov511->bridge == BRG_OV511) {
 		if (size == 0) alt = OV511_ALT_SIZE_0;
@@ -502,8 +851,7 @@
 			err("Set packet size: invalid size (%d)", size);
 			return -EINVAL;
 		}
-	}
-	else if (ov511->bridge == BRG_OV511PLUS) {
+	} else if (ov511->bridge == BRG_OV511PLUS) {
 		if (size == 0) alt = OV511PLUS_ALT_SIZE_0;
 		else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;
 		else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;
@@ -516,16 +864,14 @@
 			err("Set packet size: invalid size (%d)", size);
 			return -EINVAL;
 		}
-	}
-	else {
+	} else {
 		err("Set packet size: Invalid bridge type");
 		return -EINVAL;
 	}
 
 	PDEBUG(3, "set packet size: %d, mult=%d, alt=%d", size, mult, alt);
 
-	if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE,
-	                     mult) < 0)
+	if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE, mult) < 0)
 		return -ENOMEM;
 	
 	if (usb_set_interface(ov511->dev, ov511->iface, alt) < 0) {
@@ -545,8 +891,9 @@
 	return 0;
 }
 
-static inline int ov7610_set_picture(struct usb_ov511 *ov511,
-                                     struct video_picture *p)
+
+static inline int
+ov7610_set_picture(struct usb_ov511 *ov511, struct video_picture *p)
 {
 	int ret;
 	struct usb_device *dev = ov511->dev;
@@ -556,10 +903,10 @@
 	if (ov511_stop(dev) < 0)
 		return -EIO;
 
-	if((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0)
+	if ((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0)
 		return -EIO;
 #if 0
-	if(ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0)
+	if (ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0)
 		return -EIO;
 #endif
 	if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV7620AE)
@@ -572,17 +919,18 @@
 
 		if(ov511_i2c_write(dev, OV7610_REG_BRT, p->brightness >> 8) < 0)
 			return -EIO;
-	}		
-	else if ((ov511->sensor == SEN_OV7620) 
+	} else if ((ov511->sensor == SEN_OV7620) 
 	         || (ov511->sensor == SEN_OV7620AE)) {
-//		cur_con = ov511_i2c_read(dev, OV7610_REG_CNT);
-//		cur_brt = ov511_i2c_read(dev, OV7610_REG_BRT);
-//	        // DEBUG_CODE
-//	        PDEBUG(1, "con=%d brt=%d", ov511_i2c_read(dev, OV7610_REG_CNT),
-//	                                   ov511_i2c_read(dev, OV7610_REG_BRT)); 
-//
-//		if(ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
-//			return -EIO;
+#if 0
+		cur_con = ov511_i2c_read(dev, OV7610_REG_CNT);
+		cur_brt = ov511_i2c_read(dev, OV7610_REG_BRT);
+	        // DEBUG_CODE
+	        PDEBUG(1, "con=%d brt=%d", ov511_i2c_read(dev, OV7610_REG_CNT),
+	         ov511_i2c_read(dev, OV7610_REG_BRT)); 
+
+		if(ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
+			return -EIO;
+#endif
 	}
 
 	if (ov511_restart(dev) < 0)
@@ -591,8 +939,9 @@
 	return 0;
 }
 
-static inline int ov7610_get_picture(struct usb_ov511 *ov511,
-                                     struct video_picture *p)
+
+static inline int
+ov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p)
 {
 	int ret;
 	struct usb_device *dev = ov511->dev;
@@ -613,7 +962,11 @@
 
 	p->hue = 0x8000;
 	p->whiteness = 105 << 8;
+#if 0
 	p->depth = 3;  /* Don't know if this is right */
+#else
+	p->depth = 24;
+#endif
 	p->palette = VIDEO_PALETTE_RGB24;
 
 	if (ov511_restart(dev) < 0)
@@ -622,15 +975,17 @@
 	return 0;
 }
 
-static int ov511_mode_init_regs(struct usb_ov511 *ov511,
-				int width, int height, int mode, int sub_flag)
+
+static int
+ov511_mode_init_regs(struct usb_ov511 *ov511,
+		     int width, int height, int mode, int sub_flag)
 {
 	int rc = 0;
 	struct usb_device *dev = ov511->dev;
-        int hwsbase = 0;
-        int hwebase = 0;
+	int hwsbase = 0;
+	int hwebase = 0;
 
-	PDEBUG(3, "ov511_mode_init_regs(ov511, w:%d, h:%d, mode:%d, sub:%d)",
+	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
 	       width, height, mode, sub_flag);
 
 	if (ov511_stop(ov511->dev) < 0)
@@ -644,34 +999,39 @@
 			ov511_i2c_write(dev, 0x0e, 0x44);
 		}
 		ov511_i2c_write(dev, 0x13, autoadjust ? 0x21 : 0x20);
+
 		/* For snapshot */
 		ov511_reg_write(dev, 0x1e, 0x00);
 		ov511_reg_write(dev, 0x1f, 0x01);
 	} else {
 		ov511_reg_write(dev, 0x16, 0x01);
-	   	if (ov511->sensor == SEN_OV7610
+		if (ov511->sensor == SEN_OV7610
 		    || ov511->sensor == SEN_OV7620AE) {
-		   /* not valid on the OV7620 */
-		   ov511_i2c_write(dev, 0x0e, 0x04);
+			/* not valid on the OV7620 */
+			ov511_i2c_write(dev, 0x0e, 0x04);
 		}
 		ov511_i2c_write(dev, 0x13, autoadjust ? 0x01 : 0x00);
+
 		/* For snapshot */
 		ov511_reg_write(dev, 0x1e, 0x01);
 		ov511_reg_write(dev, 0x1f, 0x03);
 	}
 
 	/* The different sensor ICs handle setting up of window differently */
-        switch (ov511->sensor) {
-	 case SEN_OV7610:
-	 case SEN_OV7620AE:
-	   hwsbase = 0x38;
-	   hwebase = 0x3a; break;
-	 case SEN_OV7620:
-	   hwsbase = 0x2c;
-	   hwebase = 0x2d; break;
-	 default:
-	   hwsbase = 0;
-	   hwebase = 0; break;
+	switch (ov511->sensor) {
+	case SEN_OV7610:
+	case SEN_OV7620AE:
+		hwsbase = 0x38;
+		hwebase = 0x3a;
+		break;
+	case SEN_OV7620:
+		hwsbase = 0x2c;
+		hwebase = 0x2d;
+		break;
+	default:
+		hwsbase = 0;
+		hwebase = 0;
+		break;
 	}
 
 	if (width == 640 && height == 480) {
@@ -680,12 +1040,12 @@
 			ov511_i2c_write(dev, 0x17, hwsbase+(ov511->subx>>2));
 			/* horizontal window end */
 			ov511_i2c_write(dev, 0x18,
-					hwebase+((ov511->subx+ov511->subw)>>2));
+				hwebase+((ov511->subx+ov511->subw)>>2));
 			/* vertical window start */
-		   	ov511_i2c_write(dev, 0x19, 0x5+(ov511->suby>>1));
+			ov511_i2c_write(dev, 0x19, 0x5+(ov511->suby>>1));
 			/* vertical window end */
-		    ov511_i2c_write(dev, 0x1a,
-					0x5+((ov511->suby+ov511->subh)>>1));
+			ov511_i2c_write(dev, 0x1a,
+				0x5+((ov511->suby+ov511->subh)>>1));
 			ov511_reg_write(dev, 0x12, (ov511->subw>>3)-1);
 			ov511_reg_write(dev, 0x13, (ov511->subh>>3)-1);
 			/* clock rate control */
@@ -762,255 +1122,267 @@
 	return rc;
 }
 
-	
-/*************************************************************
-
-Turn a YUV4:2:0 block into an RGB block
-
-Video4Linux seems to use the blue, green, red channel
-order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
 
-Color space conversion coefficients taken from the excellent
-http://www.inforamp.net/~poynton/ColorFAQ.html
-In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
-Y values are given for all 4 pixels, but the U (Pb)
-and V (Pr) are assumed constant over the 2x2 block.
+/**********************************************************************
+ *
+ * Color correction functions
+ *
+ **********************************************************************/
 
-To avoid floating point arithmetic, the color conversion
-coefficients are scaled into 16.16 fixed-point integers.
+/*
+ * Turn a YUV4:2:0 block into an RGB block
+ *
+ * Video4Linux seems to use the blue, green, red channel
+ * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
+ *
+ * Color space conversion coefficients taken from the excellent
+ * http://www.inforamp.net/~poynton/ColorFAQ.html
+ * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
+ * Y values are given for all 4 pixels, but the U (Pb)
+ * and V (Pr) are assumed constant over the 2x2 block.
+ *
+ * To avoid floating point arithmetic, the color conversion
+ * coefficients are scaled into 16.16 fixed-point integers.
+ */
 
-*************************************************************/
-// LIMIT: convert a 16.16 fixed-point value to a byte, with clipping.
+/* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
 #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
-static inline void ov511_move_420_block(
-	                int yTL, int yTR, int yBL, int yBR,
-					int u, int v, 
-					int rowPixels, unsigned char * rgb)
-{
-	const double brightness=1.0;//0->black; 1->full scale
-	const double saturation=1.0;//0->greyscale; 1->full color
-	const double fixScale=brightness*256*256;
-	const int rvScale=(int)(1.402*saturation*fixScale);
-	const int guScale=(int)(-0.344136*saturation*fixScale);
-	const int gvScale=(int)(-0.714136*saturation*fixScale);
-	const int buScale=(int)(1.772*saturation*fixScale);
-	const int yScale=(int)(fixScale);	
-
-	int r    =               rvScale * v;
-	int g    = guScale * u + gvScale * v;
-	int b    = buScale * u;
+
+static inline void
+ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, 
+	int rowPixels, unsigned char * rgb)
+{
+	const double brightness = 1.0; // 0->black; 1->full scale
+	const double saturation = 1.0; // 0->greyscale; 1->full color
+	const double fixScale = brightness * 256 * 256;
+	const int rvScale = (int)(1.402 * saturation * fixScale);
+	const int guScale = (int)(-0.344136 * saturation * fixScale);
+	const int gvScale = (int)(-0.714136 * saturation * fixScale);
+	const int buScale = (int)(1.772 * saturation * fixScale);
+	const int yScale = (int)(fixScale);	
+
+	int r = rvScale * v;
+	int g = guScale * u + gvScale * v;
+	int b = buScale * u;
 	yTL *= yScale; yTR *= yScale;
 	yBL *= yScale; yBR *= yScale;
 
 	//Write out top two pixels
-	rgb[0]=LIMIT(b+yTL); rgb[1]=LIMIT(g+yTL); rgb[2]=LIMIT(r+yTL);
-	rgb[3]=LIMIT(b+yTR); rgb[4]=LIMIT(g+yTR); rgb[5]=LIMIT(r+yTR);
-	rgb+=3*rowPixels;//Skip down to next line to write out bottom two pixels
-	rgb[0]=LIMIT(b+yBL); rgb[1]=LIMIT(g+yBL); rgb[2]=LIMIT(r+yBL);
-	rgb[3]=LIMIT(b+yBR); rgb[4]=LIMIT(g+yBR); rgb[5]=LIMIT(r+yBR);
-}
-
+	rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL);
+	rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR);
 
-/***************************************************************
-
-For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments.  The
-first 64 bytes of each segment are U, the next 64 are V.  The U and
-V are arranged as follows:
-
-  0  1 ...  7
-  8  9 ... 15
-       ...   
- 56 57 ... 63
-
-U and V are shipped at half resolution (1 U,V sample -> one 2x2 block).
-
-The next 256 bytes are full resolution Y data and represent 4 
-squares of 8x8 pixels as follows:
-
-  0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
-  8  9 ... 15    72  73 ...  79        200 201 ... 207
-       ...              ...                    ...
- 56 57 ... 63   120 121     127        248 249 ... 255
+	//Skip down to next line to write out bottom two pixels
+	rgb += 3 * rowPixels;
+	rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL);
+	rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR);
+}
 
-Note that the U and V data in one segment represents a 16 x 16 pixel
-area, but the Y data represents a 32 x 8 pixel area.
 
-If OV511_DUMPPIX is defined, _parse_data just dumps the
-incoming segments, verbatim, in order, into the frame.
-When used with vidcat -f ppm -s 640x480 this puts the data
-on the standard output and can be analyzed with the parseppm.c
-utility I wrote.  That's a much faster way for figuring out how
-this data is scrambled.
+/*
+ * For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments.
+ * The first 64 bytes of each segment are U, the next 64 are V.  The U and
+ * V are arranged as follows:
+ *
+ *      0  1 ...  7
+ *      8  9 ... 15
+ *           ...   
+ *     56 57 ... 63
+ *
+ * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block).
+ *
+ * The next 256 bytes are full resolution Y data and represent 4 squares
+ * of 8x8 pixels as follows:
+ *
+ *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
+ *      8  9 ... 15    72  73 ...  79        200 201 ... 207
+ *           ...              ...                    ...
+ *     56 57 ... 63   120 121     127        248 249 ... 255
+ *
+ * Note that the U and V data in one segment represents a 16 x 16 pixel
+ * area, but the Y data represents a 32 x 8 pixel area.
+ *
+ * If OV511_DUMPPIX is defined, _parse_data just dumps the incoming segments,
+ * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480
+ * this puts the data on the standard output and can be analyzed with the
+ * parseppm.c utility I wrote.  That's a much faster way for figuring out how
+ * this data is scrambled.
+ */
 
-****************************************************************/ 
 #define HDIV 8
 #define WDIV (256/HDIV)
 
+#undef OV511_DUMPPIX
 
-static void ov511_parse_data_rgb24(unsigned char * pIn0,
-				   unsigned char * pOut0,
-				   int iOutY,
-				   int iOutUV,
-				   int iHalf,
-				   int iWidth)
- 			    			    
+static void
+ov511_parse_data_rgb24(unsigned char * pIn0, unsigned char * pOut0,
+		       int iOutY, int iOutUV, int iHalf, int iWidth)    			    
 {
 #ifndef OV511_DUMPPIX
-    int k, l, m;
-    unsigned char * pIn;
-    unsigned char * pOut, * pOut1;
-
-    /* Just copy the Y's if in the first stripe */
-    if (!iHalf) {
-	pIn = pIn0 + 128;
-	pOut = pOut0 + iOutY;
-	for(k=0; k<4; k++) {
-	    pOut1 = pOut;
-	    for(l=0; l<8; l++) {
-	      for(m=0; m<8; m++) {
-		*pOut1 = *pIn++;
-		pOut1 += 3;
-	      }
-	      pOut1 += (iWidth - 8) * 3;
-	    }
-	    pOut += 8 * 3;
-	}
-    }
-
-    /* Use the first half of VUs to calculate value */
-    pIn = pIn0;
-    pOut = pOut0 + iOutUV;
-    for(l=0; l<4; l++) {
-	for(m=0; m<8; m++) {
-	    int y00 = *(pOut);
-	    int y01 = *(pOut+3);
-	    int y10 = *(pOut+iWidth*3);
-	    int y11 = *(pOut+iWidth*3+3);
-	    int v   = *(pIn+64) - 128;
-	    int u   = *pIn++ - 128;
-	    ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, pOut);
-	    pOut += 6;
-	}
-	pOut += (iWidth*2 - 16) * 3;
-    }
-
-    /* Just copy the other UV rows */
-    for(l=0; l<4; l++) {
-	for(m=0; m<8; m++) {
-	  *pOut++ = *(pIn + 64);
-	  *pOut = *pIn++;
-	  pOut += 5;
-	}
-	pOut += (iWidth*2 - 16) * 3;
-    }
-
-    /* Calculate values if it's the second half */
-    if (iHalf) {
-	pIn = pIn0 + 128;
-	pOut = pOut0 + iOutY;
-	for(k=0; k<4; k++) {
-	    pOut1 = pOut;
-	    for(l=0; l<4; l++) {
-	      for(m=0; m<4; m++) {
-		int y10 = *(pIn+8);
-		int y00 = *pIn++;
-		int y11 = *(pIn+8);
-		int y01 = *pIn++;
-		int v   = *pOut1 - 128;
-		int u   = *(pOut1+1) - 128;
-		ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, pOut1);
-		pOut1 += 6;
-	      }
-	      pOut1 += (iWidth*2 - 8) * 3;
-	      pIn += 8;
-	    }
-	    pOut += 8 * 3;
+	int k, l, m;
+	unsigned char * pIn;
+	unsigned char * pOut, * pOut1;
+
+	/* Just copy the Y's if in the first stripe */
+	if (!iHalf) {
+		pIn = pIn0 + 128;
+		pOut = pOut0 + iOutY;
+		for (k = 0; k < 4; k++) {
+			pOut1 = pOut;
+			for (l = 0; l < 8; l++) {
+				for (m = 0; m < 8; m++) {
+					*pOut1 = *pIn++;
+					pOut1 += 3;
+				}
+				pOut1 += (iWidth - 8) * 3;
+			}
+			pOut += 8 * 3;
+		}
+	}
+
+	/* Use the first half of VUs to calculate value */
+	pIn = pIn0;
+	pOut = pOut0 + iOutUV;
+	for (l = 0; l < 4; l++) {
+		for (m=0; m<8; m++) {
+			int y00 = *(pOut);
+			int y01 = *(pOut+3);
+			int y10 = *(pOut+iWidth*3);
+			int y11 = *(pOut+iWidth*3+3);
+			int v   = *(pIn+64) - 128;
+			int u   = *pIn++ - 128;
+			ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth,
+				pOut);
+			pOut += 6;
+		}
+		pOut += (iWidth*2 - 16) * 3;
+	}
+
+	/* Just copy the other UV rows */
+	for (l = 0; l < 4; l++) {
+		for (m = 0; m < 8; m++) {
+			*pOut++ = *(pIn + 64);
+			*pOut = *pIn++;
+			pOut += 5;
+		}
+		pOut += (iWidth*2 - 16) * 3;
+	}
+
+	/* Calculate values if it's the second half */
+	if (iHalf) {
+		pIn = pIn0 + 128;
+		pOut = pOut0 + iOutY;
+		for (k = 0; k < 4; k++) {
+			pOut1 = pOut;
+			for (l=0; l<4; l++) {
+				for (m=0; m<4; m++) {
+					int y10 = *(pIn+8);
+					int y00 = *pIn++;
+					int y11 = *(pIn+8);
+					int y01 = *pIn++;
+					int v   = *pOut1 - 128;
+					int u   = *(pOut1+1) - 128;
+					ov511_move_420_block(y00, y01, y10,
+						y11, u, v, iWidth, pOut1);
+					pOut1 += 6;
+				}
+				pOut1 += (iWidth*2 - 8) * 3;
+				pIn += 8;
+			}
+			pOut += 8 * 3;
+		}
 	}
-    }
 
 #else
 	/* Just dump pix data straight out for debug */
-	int i;
-	pOut0 += iSegmentY * 384;
-	for(i=0; i<384; i++) {
-	  *pOut0++ = *pIn0++;
+	int i, j;
+
+	pOut0 += iOutY;
+	for (i = 0; i < HDIV; i++) {
+		for (j = 0; j < WDIV; j++) {
+			*pOut0++ = *pIn0++;
+			*pOut0++ = *pIn0++;
+			*pOut0++ = *pIn0++;
+		}
+		pOut0 += (iWidth - WDIV) * 3;
 	}
 #endif
 }
 
-/***************************************************************
 
-For 640x480 RAW BW images, data shows up in 1200 256 byte segments.
-The segments represent 4 squares of 8x8 pixels as
-follows:
-
-  0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
-  8  9 ... 15    72  73 ...  79        200 201 ... 207
-       ...              ...                    ...
- 56 57 ... 63   120 121     127        248 249 ... 255
-
-****************************************************************/ 
-static void ov511_parse_data_grey(unsigned char * pIn0,
-				  unsigned char * pOut0,
-				  int iOutY,
-				  int iWidth)
-			    
-{
-    int k, l, m;
-    unsigned char * pIn;
-    unsigned char * pOut, * pOut1;
+/*
+ * For 640x480 RAW BW images, data shows up in 1200 256 byte segments.
+ * The segments represent 4 squares of 8x8 pixels as follows:
+ *
+ *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
+ *      8  9 ... 15    72  73 ...  79        200 201 ... 207
+ *           ...              ...                    ...
+ *     56 57 ... 63   120 121     127        248 249 ... 255
+ *
+ */ 
+static void
+ov511_parse_data_grey(unsigned char * pIn0, unsigned char * pOut0,
+		      int iOutY, int iWidth)		    
+{
+	int k, l, m;
+	unsigned char *pIn;
+	unsigned char *pOut, *pOut1;
 
-    pIn = pIn0;
-    pOut = pOut0 + iOutY;
-    for(k=0; k<4; k++) {
-      pOut1 = pOut;
-      for(l=0; l<8; l++) {
-	for(m=0; m<8; m++) {
-	  *pOut1++ = *pIn++;
+	pIn = pIn0;
+	pOut = pOut0 + iOutY;
+	for (k = 0; k < 4; k++) {
+		pOut1 = pOut;
+		for (l = 0; l < 8; l++) {
+			for (m = 0; m < 8; m++) {
+				*pOut1++ = *pIn++;
+			}
+			pOut1 += iWidth - 8;
+		}
+		pOut += 8;
 	}
-	pOut1 += iWidth - 8;
-      }
-      pOut += 8;
-    }
 }
 
 
-/**************************************************************
+/*
  * fixFrameRGBoffset--
  * My camera seems to return the red channel about 1 pixel
  * low, and the blue channel about 1 pixel high. After YUV->RGB
  * conversion, we can correct this easily. OSL 2/24/2000.
- *************************************************************/
+ */
 static void fixFrameRGBoffset(struct ov511_frame *frame)
 {
-  int x, y;
-  int rowBytes = frame->width*3, w = frame->width;
-  unsigned char *rgb = frame->data;
-  const int shift = 1;   //Distance to shift pixels by, vertically
-
-  if (frame->width < 400) 
-	   return;     //Don't bother with little images
-
-  //Shift red channel up
-  for (y = shift; y < frame->height; y++)
-  {
-    int lp = (y-shift)*rowBytes;     //Previous line offset
-    int lc = y*rowBytes;             //Current line offset
-    for (x = 0; x < w; x++)
-      rgb[lp+x*3+2] = rgb[lc+x*3+2]; //Shift red up
-  }
-
-  //Shift blue channel down
-  for (y=frame->height-shift-1; y >= 0; y--)
-  {
-    int ln = (y+shift)*rowBytes;   //Next line offset
-    int lc = y*rowBytes;           //Current line offset
-    for (x = 0; x < w; x++)
-      rgb[ln+x*3+0] = rgb[lc+x*3+0]; //Shift blue down
-  }
+	int x, y;
+	int rowBytes = frame->width*3, w = frame->width;
+	unsigned char *rgb = frame->data;
+	const int shift = 1;  /* Distance to shift pixels by, vertically */
+
+	/* Don't bother with little images */
+	if (frame->width < 400) 
+		return;
+
+	/* Shift red channel up */
+	for (y = shift; y < frame->height; y++)	{
+		int lp = (y-shift)*rowBytes;     /* Previous line offset */
+		int lc = y*rowBytes;             /* Current line offset */
+		for (x = 0; x < w; x++)
+			rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */
+	}
+
+	/* Shift blue channel down */
+	for (y = frame->height-shift-1; y >= 0; y--) {
+		int ln = (y + shift) * rowBytes;  /* Next line offset */
+		int lc = y * rowBytes;            /* Current line offset */
+		for (x = 0; x < w; x++)
+			rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */
+	}
 }
 
 
+/**********************************************************************
+ *
+ * OV511 data transfer, IRQ handler
+ *
+ **********************************************************************/
+
 static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
 {
 	unsigned char *cdata;
@@ -1175,6 +1547,7 @@
 	return totlen;
 }
 
+
 static void ov511_isoc_irq(struct urb *urb)
 {
 	int len;
@@ -1187,28 +1560,32 @@
 	if (!ov511->streaming) {
 		PDEBUG(2, "hmmm... not streaming, but got interrupt");
 		return;
+	} else {
+		PDEBUG(5, "streaming. got interrupt");
 	}
 	
 	sbuf = &ov511->sbuf[ov511->cursbuf];
 
 	/* Copy the data received into our scratch buffer */
-	if (ov511->curframe >= 0)
-	  len = ov511_move_data(ov511, urb);
-	else if (waitqueue_active(&ov511->wq))
-	  wake_up_interruptible(&ov511->wq);
-	
+	if (ov511->curframe >= 0) {
+		len = ov511_move_data(ov511, urb);
+	} else if (waitqueue_active(&ov511->wq)) {
+		wake_up_interruptible(&ov511->wq);
+	}
+
 	/* Move to the next sbuf */
 	ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF;
 
 	return;
 }
 
+
 static int ov511_init_isoc(struct usb_ov511 *ov511)
 {
 	urb_t *urb;
 	int fx, err;
 
-	PDEBUG(4, "ov511_init_isoc");
+	PDEBUG(3, "*** Initializing capture ***");
 
 	ov511->compress = 0;
 	ov511->curframe = -1;
@@ -1235,11 +1612,11 @@
 	urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS);
 	urb->transfer_flags = USB_ISO_ASAP;
 	urb->transfer_buffer = ov511->sbuf[0].data;
- 	urb->complete = ov511_isoc_irq;
- 	urb->number_of_packets = FRAMES_PER_DESC;
- 	urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
- 	for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
- 		urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
+	urb->complete = ov511_isoc_irq;
+	urb->number_of_packets = FRAMES_PER_DESC;
+	urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
+	for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
+		urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
 		urb->iso_frame_desc[fx].length = ov511->packet_size;
 	}
 
@@ -1254,11 +1631,11 @@
 	urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS);
 	urb->transfer_flags = USB_ISO_ASAP;
 	urb->transfer_buffer = ov511->sbuf[1].data;
- 	urb->complete = ov511_isoc_irq;
- 	urb->number_of_packets = FRAMES_PER_DESC;
- 	urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
- 	for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
- 		urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
+	urb->complete = ov511_isoc_irq;
+	urb->number_of_packets = FRAMES_PER_DESC;
+	urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
+	for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
+		urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
 		urb->iso_frame_desc[fx].length = ov511->packet_size;
 	}
 
@@ -1280,10 +1657,11 @@
 
 static void ov511_stop_isoc(struct usb_ov511 *ov511)
 {
-	PDEBUG(4, "ov511_stop_isoc");
 	if (!ov511->streaming || !ov511->dev)
 		return;
 
+	PDEBUG (3, "*** Stopping capture ***");
+
 	ov511_set_packet_size(ov511, 0);
 
 	ov511->streaming = 0;
@@ -1303,18 +1681,19 @@
 	}
 }
 
+
 static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
 {
 	struct ov511_frame *frame;
 	int width, height;
 
-	PDEBUG(4, "ov511_new_frame");
-
+	PDEBUG(4, "ov511->curframe = %d, framenum = %d", ov511->curframe,
+		framenum);
 	if (!ov511->dev)
 		return -1;
 
 	/* If we're not grabbing a frame right now and the other frame is */
-	/*  ready to be grabbed into, then use it instead */
+	/* ready to be grabbed into, then use it instead */
 	if (ov511->curframe == -1) {
 		if (ov511->frame[(framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES].grabstate == FRAME_READY)
 			framenum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;
@@ -1325,6 +1704,9 @@
 	width = frame->width;
 	height = frame->height;
 
+	PDEBUG (4, "framenum = %d, width = %d, height = %d", framenum, width,
+		height);
+
 	frame->grabstate = FRAME_GRABBING;
 	frame->scanstate = STATE_SCANNING;
 	frame->scanlength = 0;		/* accumulated in ov511_parse_data() */
@@ -1335,11 +1717,17 @@
 	/* Make sure it's not too big */
 	if (width > DEFAULT_WIDTH)
 		width = DEFAULT_WIDTH;
+#if 0
 	width = (width / 8) * 8;	/* Multiple of 8 */
+#endif
+	width &= ~7L;
 
 	if (height > DEFAULT_HEIGHT)
 		height = DEFAULT_HEIGHT;
+#if 0
 	height = (height / 4) * 4;	/* Multiple of 4 */
+#endif
+	width &= ~3L;
 
 //	/* We want a fresh frame every 30 we get */
 //	ov511->compress = (ov511->compress + 1) % 30;
@@ -1348,7 +1736,12 @@
 }
 
 
-/* Video 4 Linux API */
+/****************************************************************************
+ *
+ * V4L API
+ *
+ ***************************************************************************/
+
 static int ov511_open(struct video_device *dev, int flags)
 {
 	int err = -EBUSY;
@@ -1409,9 +1802,9 @@
 out_unlock:
 	up(&ov511->lock);
 	return err;
-
 }
 
+
 static void ov511_close(struct video_device *dev)
 {
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
@@ -1438,16 +1831,23 @@
 	}
 }
 
+
 static int ov511_init_done(struct video_device *dev)
 {
+#ifdef CONFIG_PROC_FS
+	create_proc_ov511_cam((struct usb_ov511 *)dev);
+#endif
+
 	return 0;
 }
 
+
 static long ov511_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
 {
 	return -EINVAL;
 }
 
+
 static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
 {
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
@@ -1756,13 +2156,15 @@
 	return 0;
 }
 
+
 static long ov511_read(struct video_device *dev, char *buf, unsigned long count, int noblock)
 {
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
+	int i;
 	int frmx = -1;
 	volatile struct ov511_frame *frame;
 
-	PDEBUG(4, "ov511_read: %ld bytes, noblock=%d", count, noblock);
+	PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
 
 	if (!dev || !buf)
 		return -EFAULT;
@@ -1776,6 +2178,7 @@
 	else if (ov511->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */
 		frmx = 1;
 
+	/* If nonblocking we return immediately */
 	if (noblock && (frmx == -1))
 		return -EAGAIN;
 
@@ -1794,19 +2197,26 @@
 
 	frame = &ov511->frame[frmx];
 
+	/* FIXME */
+	frame->segsize = frame->format == VIDEO_PALETTE_RGB24 ? 384 : 256;
+	frame->depth = frame->format == VIDEO_PALETTE_RGB24 ? 24 : 8;
+
 restart:
 	if (!ov511->dev)
 		return -EIO;
 
+	/* Wait while we're grabbing the image */
+	PDEBUG(4, "Waiting image grabbing");
 	while (frame->grabstate == FRAME_GRABBING) {
 		interruptible_sleep_on(&ov511->frame[frmx].wq);
 		if (signal_pending(current))
 			return -EINTR;
 	}
+	PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate);
 
 	if (frame->grabstate == FRAME_ERROR) {
 		frame->bytes_read = 0;
-		err("ov511_read: errored frame %d", ov511->curframe);
+		err("** ick! ** Errored frame %d", ov511->curframe);
 		if (ov511_new_frame(ov511, frmx))
 			err("ov511_read: ov511_new_frame error");
 		goto restart;
@@ -1814,14 +2224,21 @@
 
 
 	/* Repeat until we get a snapshot frame */
+	if (!ov511->snap_enabled) {
+		PDEBUG (4, "snap disabled");
+	} else {
+		PDEBUG (4, "Waiting snapshot frame");
+	}
 	if (ov511->snap_enabled && !frame->snapshot) {
 		frame->bytes_read = 0;
 		if (ov511_new_frame(ov511, frmx))
-			err("ov511_read: ov511_new_frame error");
+			err("ov511_new_frame error");
 		goto restart;
 	}
 
 	/* Clear the snapshot */
+	if (ov511->snap_enabled)
+		PDEBUG (4, "Clear snapshot");
 	if (ov511->snap_enabled && frame->snapshot) {
 		frame->snapshot = 0;
 		ov511_reg_write(ov511->dev, 0x52, 0x01);
@@ -1829,20 +2246,24 @@
 		ov511_reg_write(ov511->dev, 0x52, 0x01);
 	}
 
-	PDEBUG(4, "ov511_read: frmx=%d, bytes_read=%ld, scanlength=%ld", frmx,
+	PDEBUG(4, "frmx=%d, bytes_read=%ld, scanlength=%ld", frmx,
 		frame->bytes_read, frame->scanlength);
 
 	/* copy bytes to user space; we allow for partials reads */
 //	if ((count + frame->bytes_read) > frame->scanlength)
 //		count = frame->scanlength - frame->bytes_read;
+
 	/* FIXME - count hardwired to be one frame... */
-	count = frame->width * frame->height * frame->depth;
+	count = frame->width * frame->height * (frame->depth >> 3);
 
-	if (copy_to_user(buf, frame->data + frame->bytes_read, count))
+	PDEBUG(4, "Copy to user space: %ld bytes", count);
+	if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) {
+		PDEBUG(4, "Copy failed! %d bytes not copied", i);
 		return -EFAULT;
+	}
 
 	frame->bytes_read += count;
-	PDEBUG(4, "ov511_read: {copy} count used=%ld, new bytes_read=%ld",
+	PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld",
 		count, frame->bytes_read);
 
 	if (frame->bytes_read >= frame->scanlength) { /* All data has been read */
@@ -1851,13 +2272,17 @@
 		/* Mark it as available to be used again. */
 		ov511->frame[frmx].grabstate = FRAME_UNUSED;
 		if (ov511_new_frame(ov511, frmx ? 0 : 1))
-			err("ov511_read: ov511_new_frame returned error");
+			err("ov511_new_frame returned error");
 	}
 
+	PDEBUG(4, "read finished, returning %ld (sweet)", count);
+
 	return count;
 }
 
-static int ov511_mmap(struct video_device *dev, const char *adr, unsigned long size)
+
+static int ov511_mmap(struct video_device *dev, const char *adr,
+	unsigned long size)
 {
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
 	unsigned long start = (unsigned long)adr;
@@ -1888,6 +2313,7 @@
 	return 0;
 }
 
+
 static struct video_device ov511_template = {
 	name:		"OV511 USB Camera",
 	type:		VID_TYPE_CAPTURE,
@@ -1901,12 +2327,81 @@
 	initialize:	ov511_init_done,
 };
 
-static int ov7610_configure(struct usb_ov511 *ov511)
+
+/****************************************************************************
+ *
+ * OV511/OV7610 configuration
+ *
+ ***************************************************************************/
+
+static int ov76xx_configure(struct usb_ov511 *ov511)
 {
 	struct usb_device *dev = ov511->dev;
-	int tries;
+	int i, success;
 	int rc;
 
+	static struct ov511_regvals aRegvalsNorm7610[] =
+	{{OV511_I2C_BUS, 0x10, 0xff},
+	 {OV511_I2C_BUS, 0x16, 0x06},
+	 {OV511_I2C_BUS, 0x28, 0x24},
+	 {OV511_I2C_BUS, 0x2b, 0xac},
+	 {OV511_I2C_BUS, 0x05, 0x00},
+	 {OV511_I2C_BUS, 0x06, 0x00},
+	 {OV511_I2C_BUS, 0x12, 0x00},
+	 {OV511_I2C_BUS, 0x38, 0x81},
+	 {OV511_I2C_BUS, 0x28, 0x24}, /* 0c */
+	 {OV511_I2C_BUS, 0x05, 0x00},
+	 {OV511_I2C_BUS, 0x0f, 0x05},
+	 {OV511_I2C_BUS, 0x15, 0x01},
+	 {OV511_I2C_BUS, 0x20, 0x1c},
+	 {OV511_I2C_BUS, 0x23, 0x2a},
+	 {OV511_I2C_BUS, 0x24, 0x10},
+	 {OV511_I2C_BUS, 0x25, 0x8a},
+	 {OV511_I2C_BUS, 0x27, 0xc2},
+	 {OV511_I2C_BUS, 0x29, 0x03}, /* 91 */
+	 {OV511_I2C_BUS, 0x2a, 0x04},
+	 {OV511_I2C_BUS, 0x2c, 0xfe},
+	 {OV511_I2C_BUS, 0x30, 0x71},
+	 {OV511_I2C_BUS, 0x31, 0x60},
+	 {OV511_I2C_BUS, 0x32, 0x26},
+	 {OV511_I2C_BUS, 0x33, 0x20},
+	 {OV511_I2C_BUS, 0x34, 0x48},
+	 {OV511_I2C_BUS, 0x12, 0x24},
+	 {OV511_I2C_BUS, 0x11, 0x01},
+	 {OV511_I2C_BUS, 0x0c, 0x24},
+	 {OV511_I2C_BUS, 0x0d, 0x24},
+	 {OV511_DONE_BUS, 0x0, 0x00},
+	};
+
+	static struct ov511_regvals aRegvalsNorm7620[] =
+	{{OV511_I2C_BUS, 0x10, 0xff},
+	 {OV511_I2C_BUS, 0x16, 0x06},
+	 {OV511_I2C_BUS, 0x28, 0x24},
+	 {OV511_I2C_BUS, 0x2b, 0xac},
+	 {OV511_I2C_BUS, 0x12, 0x00},
+	 {OV511_I2C_BUS, 0x28, 0x24},
+	 {OV511_I2C_BUS, 0x05, 0x00},
+	 {OV511_I2C_BUS, 0x0f, 0x05},
+	 {OV511_I2C_BUS, 0x15, 0x01},
+	 {OV511_I2C_BUS, 0x23, 0x00},
+	 {OV511_I2C_BUS, 0x24, 0x10},
+	 {OV511_I2C_BUS, 0x25, 0x8a},
+	 {OV511_I2C_BUS, 0x27, 0xe2},
+	 {OV511_I2C_BUS, 0x29, 0x03},
+	 {OV511_I2C_BUS, 0x2a, 0x00},
+	 {OV511_I2C_BUS, 0x2c, 0xfe},
+	 {OV511_I2C_BUS, 0x30, 0x71},
+	 {OV511_I2C_BUS, 0x31, 0x60},
+	 {OV511_I2C_BUS, 0x32, 0x26},
+	 {OV511_I2C_BUS, 0x33, 0x20},
+	 {OV511_I2C_BUS, 0x34, 0x48},
+	 {OV511_I2C_BUS, 0x12, 0x24},
+	 {OV511_I2C_BUS, 0x11, 0x01},
+	 {OV511_I2C_BUS, 0x0c, 0x24},
+	 {OV511_I2C_BUS, 0x0d, 0x24},
+	 {OV511_DONE_BUS, 0x0, 0x00},
+	};
+
 	if(ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
 	                        OV7610_I2C_WRITE_ID) < 0)
 		return -1;
@@ -1918,64 +2413,90 @@
 	if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
 		return -1;
 	
-	/* Reset the 7610 and wait a bit for it to initialize */ 
+	/* Reset the 76xx */ 
 	if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
-	schedule_timeout (1 + 150 * HZ / 1000);
 
-	/* Dummy read to sync I2C */
-	if(ov511_i2c_read(dev, 0x00) < 0)
-		return -1;
- 
-	tries = 5;
-	while((tries > 0) &&
-	      ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) != 0x7F) ||
-	       (ov511_i2c_read(dev, OV7610_REG_ID_LOW) != 0xA2))) {
-		--tries;
+	for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
+		if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
+		    (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2))
+			success = 1;
+
+		/* Dummy read to sync I2C */
+		if (ov511_i2c_read(dev, 0x00) < 0) return -1;
+		/* Wait for it to initialize */ 
+		schedule_timeout (1 + 150 * HZ / 1000);
 	}
-	
-	if (tries == 1) {
-		err("Failed to read sensor ID. You might not have an OV7610/20,");
+
+	if (success) {
+		PDEBUG(1, "I2C synced in %d attempt(s)", i);
+	} else {
+		err("Failed to read sensor ID. You might not have an OV76xx,");
 		err("or it may be not responding. Report this to");
 		err("mmcclelland@delphi.com");
 		return -1;
 	}
 
+	/* Detect sensor if user didn't use override param */
 	if (sensor == 0) {
 		rc = ov511_i2c_read(dev, OV7610_REG_COM_I);
 
 		if (rc < 0) {
 			err("Error detecting sensor type");
 			return -1;
-		}
-		else if((rc & 3) == 3) {
+		} else if((rc & 3) == 3) {
 			printk("ov511: Sensor is an OV7610\n");
 			ov511->sensor = SEN_OV7610;
-		}
-		else if((rc & 3) == 1) {
+		} else if((rc & 3) == 1) {
 			printk("ov511: Sensor is an OV7620AE\n");
 			ov511->sensor = SEN_OV7620AE;
-		}
-		else if((rc & 3) == 0) {
+		} else if((rc & 3) == 0) {
 			printk("ov511: Sensor is an OV7620\n");
 			ov511->sensor = SEN_OV7620;
-		}
-		else {
+		} else {
 			err("Unknown image sensor version: %d", rc & 3);
 			return -1;
 		}
-	}
-	else {  /* sensor != 0; user overrode detection */
+	} else {	/* sensor != 0; user overrode detection */
 		ov511->sensor = sensor;
 		printk("ov511: Sensor set to type %d\n", ov511->sensor);
 	}
 
+	if (ov511->sensor == SEN_OV7620) {
+		if (ov511_write_regvals(dev, aRegvalsNorm7620))
+			return -1;
+	} else {
+		if (ov511_write_regvals(dev, aRegvalsNorm7610))
+			return -1;
+	}
+
+	if (aperture < 0) {          /* go with the default */
+		if (ov511_i2c_write(dev, 0x26, 0xa2) < 0) return -1;
+	} else if (aperture <= 0xf) {  /* user overrode default */
+		if (ov511_i2c_write(dev, 0x26, (aperture << 4) + 2) < 0)
+			return -1;
+	} else {
+		err("Invalid setting for aperture; legal value: 0 - 15");
+		return -1;
+	}
+
+	if (autoadjust) {
+		if (ov511_i2c_write(dev, 0x13, 0x01) < 0) return -1;
+		if (ov511_i2c_write(dev, 0x2d, 
+		     ov511->sensor==SEN_OV7620?0x91:0x93) < 0) return -1;
+	} else {
+		if (ov511_i2c_write(dev, 0x13, 0x00) < 0) return -1;
+		if (ov511_i2c_write(dev, 0x2d, 
+		     ov511->sensor==SEN_OV7620?0x81:0x83) < 0) return -1;
+		ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
+	}
+
 	return 0;
 }
 
+
 static int ov511_configure(struct usb_ov511 *ov511)
 {
 	struct usb_device *dev = ov511->dev;
-	int rc;
 
 	static struct ov511_regvals aRegvalsInit[] =
 	{{OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x7f},
@@ -1988,7 +2509,7 @@
 	 {OV511_DONE_BUS, 0x0, 0x00},
 	};
 
-	static struct ov511_regvals aRegvalsNorm7610[] =
+	static struct ov511_regvals aRegvalsNorm511[] =
 	{{OV511_REG_BUS, 0x20, 0x01},
 	 {OV511_REG_BUS, 0x52, 0x02},
 	 {OV511_REG_BUS, 0x52, 0x00},
@@ -2003,85 +2524,6 @@
 	 {OV511_REG_BUS, 0x77, 0x01},
 	 {OV511_REG_BUS, 0x78, 0x06},
 	 {OV511_REG_BUS, 0x79, 0x03},
-
-	 {OV511_I2C_BUS, 0x10, 0xff},
-	 {OV511_I2C_BUS, 0x16, 0x06},
-	 {OV511_I2C_BUS, 0x28, 0x24},
-	 {OV511_I2C_BUS, 0x2b, 0xac},
-	 {OV511_I2C_BUS, 0x05, 0x00},
-	 {OV511_I2C_BUS, 0x06, 0x00},
-
-	 {OV511_I2C_BUS, 0x12, 0x00},
-	 {OV511_I2C_BUS, 0x38, 0x81},
-	 {OV511_I2C_BUS, 0x28, 0x24}, /* 0c */
-	 {OV511_I2C_BUS, 0x05, 0x00},
-	 {OV511_I2C_BUS, 0x0f, 0x05},
-	 {OV511_I2C_BUS, 0x15, 0x01},
-	 {OV511_I2C_BUS, 0x20, 0x1c},
-	 {OV511_I2C_BUS, 0x23, 0x2a},
-	 {OV511_I2C_BUS, 0x24, 0x10},
-	 {OV511_I2C_BUS, 0x25, 0x8a},
-	 {OV511_I2C_BUS, 0x26, 0x90},
-	 {OV511_I2C_BUS, 0x27, 0xc2},
-	 {OV511_I2C_BUS, 0x29, 0x03}, /* 91 */
-	 {OV511_I2C_BUS, 0x2a, 0x04},
-	 {OV511_I2C_BUS, 0x2c, 0xfe},
-	 {OV511_I2C_BUS, 0x30, 0x71},
-	 {OV511_I2C_BUS, 0x31, 0x60},
-	 {OV511_I2C_BUS, 0x32, 0x26},
-	 {OV511_I2C_BUS, 0x33, 0x20},
-	 {OV511_I2C_BUS, 0x34, 0x48},
-	 {OV511_I2C_BUS, 0x12, 0x24},
-	 {OV511_I2C_BUS, 0x11, 0x01},
-	 {OV511_I2C_BUS, 0x0c, 0x24},
-	 {OV511_I2C_BUS, 0x0d, 0x24},
-	 {OV511_DONE_BUS, 0x0, 0x00},
-	};
-
-	static struct ov511_regvals aRegvalsNorm7620[] =
-	{{OV511_REG_BUS, 0x20, 0x01},
-	 {OV511_REG_BUS, 0x52, 0x02},
-	 {OV511_REG_BUS, 0x52, 0x00},
-	 {OV511_REG_BUS, 0x31, 0x1f},
-	 {OV511_REG_BUS, 0x70, 0x3f},
-	 {OV511_REG_BUS, 0x71, 0x3f},
-	 {OV511_REG_BUS, 0x72, 0x01},
-	 {OV511_REG_BUS, 0x73, 0x01},
-	 {OV511_REG_BUS, 0x74, 0x01},
-	 {OV511_REG_BUS, 0x75, 0x01},
-	 {OV511_REG_BUS, 0x76, 0x01},
-	 {OV511_REG_BUS, 0x77, 0x01},
-	 {OV511_REG_BUS, 0x78, 0x06},
-	 {OV511_REG_BUS, 0x79, 0x03},
-
-	 {OV511_I2C_BUS, 0x10, 0xff},
-	 {OV511_I2C_BUS, 0x16, 0x06},
-	 {OV511_I2C_BUS, 0x28, 0x24},
-	 {OV511_I2C_BUS, 0x2b, 0xac},
-
-	 {OV511_I2C_BUS, 0x12, 0x00},
-
-	 {OV511_I2C_BUS, 0x28, 0x24},
-	 {OV511_I2C_BUS, 0x05, 0x00},
-	 {OV511_I2C_BUS, 0x0f, 0x05},
-	 {OV511_I2C_BUS, 0x15, 0x01},
-	 {OV511_I2C_BUS, 0x23, 0x00},
-	 {OV511_I2C_BUS, 0x24, 0x10},
-	 {OV511_I2C_BUS, 0x25, 0x8a},
-	 {OV511_I2C_BUS, 0x26, 0xa2},
-	 {OV511_I2C_BUS, 0x27, 0xe2},
-	 {OV511_I2C_BUS, 0x29, 0x03},
-	 {OV511_I2C_BUS, 0x2a, 0x00},
-	 {OV511_I2C_BUS, 0x2c, 0xfe},
-	 {OV511_I2C_BUS, 0x30, 0x71},
-	 {OV511_I2C_BUS, 0x31, 0x60},
-	 {OV511_I2C_BUS, 0x32, 0x26},
-	 {OV511_I2C_BUS, 0x33, 0x20},
-	 {OV511_I2C_BUS, 0x34, 0x48},
-	 {OV511_I2C_BUS, 0x12, 0x24},
-	 {OV511_I2C_BUS, 0x11, 0x01},
-	 {OV511_I2C_BUS, 0x0c, 0x24},
-	 {OV511_I2C_BUS, 0x0d, 0x24},
 	 {OV511_DONE_BUS, 0x0, 0x00},
 	};
 
@@ -2096,54 +2538,36 @@
 		return -EBUSY;
 	}
 
-	if ((rc = ov511_write_regvals(dev, aRegvalsInit)))
-		return rc;
-
-	if(ov7610_configure(ov511) < 0) {
-		err("failed to configure OV7610");
- 		goto error;	
-	}
+	if (ov511_write_regvals(dev, aRegvalsInit)) goto error;
+	if (ov511_write_regvals(dev, aRegvalsNorm511)) goto error;
 
 	ov511_set_packet_size(ov511, 0);
 
-	/* Disable compression */
-	if (ov511_reg_write(dev, OV511_OMNICE_ENABLE, 0x00) < 0)
-		goto error;
-
 	ov511->snap_enabled = snapshot;	
 
 	/* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
 	 * (using read() instead). */
 	ov511->frame[0].width = DEFAULT_WIDTH;
 	ov511->frame[0].height = DEFAULT_HEIGHT;
+	ov511->frame[0].depth = 24;		/**************/
 	ov511->frame[0].bytes_read = 0;
+	ov511->frame[0].segment = 0;
 	ov511->frame[1].width = DEFAULT_WIDTH;
 	ov511->frame[1].height = DEFAULT_HEIGHT;
+	ov511->frame[1].depth = 24;
 	ov511->frame[1].bytes_read = 0;
+	ov511->frame[1].segment = 0;
 
 	/* Initialize to DEFAULT_WIDTH, DEFAULT_HEIGHT, YUV4:2:0 */
 
-	if (ov511->sensor == SEN_OV7620) {
-		if (ov511_write_regvals(dev, aRegvalsNorm7620)) goto error;
-	}
-	else {
-		if (ov511_write_regvals(dev, aRegvalsNorm7610)) goto error;
+	if(ov76xx_configure(ov511) < 0) {
+		err("failed to configure OV76xx");
+ 		goto error;	
 	}
 
 	if (ov511_mode_init_regs(ov511, DEFAULT_WIDTH, DEFAULT_HEIGHT,
-				       VIDEO_PALETTE_RGB24, 0) < 0) goto error;
-
-	if (autoadjust) {
-		if (ov511_i2c_write(dev, 0x13, 0x01) < 0) goto error;
-		if (ov511_i2c_write(dev, 0x2d, 
-		     ov511->sensor==SEN_OV7620?0x91:0x93) < 0) goto error;
-	}
-	else {
-		if (ov511_i2c_write(dev, 0x13, 0x00) < 0) goto error;
-		if (ov511_i2c_write(dev, 0x2d, 
-		     ov511->sensor==SEN_OV7620?0x81:0x83) < 0) goto error;
-		ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
-	}
+				 VIDEO_PALETTE_RGB24, 0) < 0)
+		goto error;
 
 	return 0;
 	
@@ -2158,11 +2582,18 @@
 	return -EBUSY;	
 }
 
+
+/****************************************************************************
+ *
+ *  USB routines
+ *
+ ***************************************************************************/
+
 static void* ov511_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_interface_descriptor *interface;
 	struct usb_ov511 *ov511;
-	int rc;
+	int i;
 
 	PDEBUG(1, "probing for device...");
 
@@ -2191,79 +2622,58 @@
 	}
 
 	memset(ov511, 0, sizeof(*ov511));
-	
+
 	ov511->dev = dev;
 	ov511->iface = interface->bInterfaceNumber;
 
-	if (dev->descriptor.idProduct == 0x0511) {
+	switch (dev->descriptor.idProduct) {
+	case 0x0511:
 		info("USB OV511 camera found");
 		ov511->bridge = BRG_OV511;
-	}
-	else if (dev->descriptor.idProduct == 0xA511) {
+		break;
+	case 0xA511:
 		info("USB OV511+ camera found");
 		ov511->bridge = BRG_OV511PLUS;
+		break;
 	}
 
-	rc = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
-	if (rc < 0) {
+	ov511->customid = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
+	if (ov511->customid < 0) {
 		err("Unable to read camera bridge registers");
 		goto error;
 	}
-	
-	switch(ov511->customid = rc) {
-	case 0: /* This also means that no custom ID was set */
-		printk("ov511: Camera is a generic model (no ID)\n");
-		break;
-	case 3:
-		printk("ov511: Camera is a D-Link DSB-C300\n");
-		break;
-	case 4:
-		printk("ov511: Camera is a generic OV511/OV7610\n");
-		break;
-	case 5:
-		printk("ov511: Camera is a Puretek PT-6007\n");
-		break;
-	case 21:
-		printk("ov511: Camera is a Creative Labs WebCam 3\n");
-		break;
-	case 36:
-		printk("ov511: Camera is a Koala-Cam\n");
-		break;
-	case 38:
-		printk("ov511: Camera is a Lifeview USB Life TV\n");
-		printk("ov511: This device is not supported, exiting...\n");
-		goto error;
-		break;
-	case 100:
-		printk("ov511: Camera is a Lifeview RoboCam\n");
-		break;
-	case 102:
-		printk("ov511: Camera is a AverMedia InterCam Elite\n");
-		break;
-	case 112: /* The OmniVision OV7110 evaluation kit uses this too */
-		printk("ov511: Camera is a MediaForte MV300\n");
-		break;
-	default:
-		err("Specific camera type (%d) not recognized", rc);
+
+	ov511->desc = -1;
+	PDEBUG (4, "CustomID = %d", ov511->customid);
+	for (i = 0; clist[i].id >= 0; i++) {
+		if (ov511->customid == clist[i].id) {
+			printk ("Camera: %s\n", clist[i].description);
+			ov511->desc = i;
+			break;
+		}
+	}
+
+	/* Lifeview USB Life TV not supported */
+	if (clist[i].id == 38) {
+		err("This device is not supported yet.");
+		return NULL;
+	}
+
+	if (clist[i].id == -1) {
+		err("Camera type (%d) not recognized", ov511->customid);
 		err("Please contact mmcclelland@delphi.com to request");
 		err("support for your camera.");
 	}
 
-//	if (ov511->bridge == BRG_OV511PLUS) {
-//		err("Sorry, the OV511+ chip is not supported yet");
-//		goto error;
-//	}
-
 	if (!ov511_configure(ov511)) {
-		ov511->user=0;
+		ov511->user = 0;
 		init_MUTEX(&ov511->lock);	/* to 1 == available */
 		return ov511;
-	}
-	else {
+	} else {
 		err("Failed to configure camera");
 		goto error;
 	}
-    	
+
      	return ov511;
 
 error:
@@ -2272,12 +2682,12 @@
 		ov511 = NULL;
 	}
 
-	return NULL;	
+	return NULL;
 }
 
+
 static void ov511_disconnect(struct usb_device *dev, void *ptr)
 {
-
 	struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr;
 
 //	video_unregister_device(&ov511->vdev);
@@ -2318,6 +2728,11 @@
 		ov511->sbuf[0].urb = NULL;
 	}
 
+#ifdef CONFIG_PROC_FS
+        PDEBUG(3, "destroying /proc/ov511/video%d", ov511->vdev.minor);
+        destroy_proc_ov511_cam(ov511);
+#endif
+
 	/* Free the memory */
 	if (!ov511->user) {
 		kfree(ov511);
@@ -2332,18 +2747,35 @@
 	{ NULL, NULL }
 };
 
+
+/****************************************************************************
+ *
+ *  Module routines
+ *
+ ***************************************************************************/
+
 static int __init usb_ov511_init(void)
 {
+#ifdef CONFIG_PROC_FS
+	PDEBUG(3, "creating /proc/ov511");
+        proc_ov511_create();
+#endif
+
 	if (usb_register(&ov511_driver) < 0)
 		return -1;
 
-	info("ov511 driver registered");
+	info("ov511 driver version %s registered", version);
 
 	return 0;
 }
 
 static void __exit usb_ov511_exit(void)
 {
+#ifdef CONFIG_PROC_FS
+	PDEBUG(3, "destroying /proc/ov511");
+        proc_ov511_destroy();
+#endif 
+
 	usb_deregister(&ov511_driver);
 	info("ov511 driver deregistered");
 }
diff -Naur linux-2.3.99-pre6-orig/drivers/usb/ov511.h linux/drivers/usb/ov511.h
--- linux-2.3.99-pre6-orig/drivers/usb/ov511.h	Thu Apr 13 23:23:45 2000
+++ linux/drivers/usb/ov511.h	Fri May  5 14:34:29 2000
@@ -1,34 +1,38 @@
 #ifndef __LINUX_OV511_H
 #define __LINUX_OV511_H
 
+#include <asm/uaccess.h>
+#include <linux/videodev.h>
+#include <linux/smp_lock.h>
+
 #define OV511_DEBUG	/* Turn on debug messages */
 
 #ifdef OV511_DEBUG
 #  define PDEBUG(level, fmt, args...) \
-if (debug >= level) printk("ov511: " fmt "\n" , ## args)
+if (debug >= level) printk("ov511: [" __PRETTY_FUNCTION__ ":%d] " fmt "\n", __LINE__ , ## args)
 #else
 #  define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
 
 /* Camera interface register numbers */
-#define OV511_REG_CAMERA_DELAY_MODE			0x10
-#define OV511_REG_CAMERA_EDGE_MODE			0x11
+#define OV511_REG_CAMERA_DELAY_MODE		0x10
+#define OV511_REG_CAMERA_EDGE_MODE		0x11
 #define OV511_REG_CAMERA_CLAMPED_PIXEL_NUM	0x12
 #define OV511_REG_CAMERA_CLAMPED_LINE_NUM	0x13
 #define OV511_REG_CAMERA_PIXEL_DIVISOR		0x14
 #define OV511_REG_CAMERA_LINE_DIVISOR		0x15
 #define OV511_REG_CAMERA_DATA_INPUT_SELECT	0x16
 #define OV511_REG_CAMERA_RESERVED_LINE_MODE	0x17
-#define OV511_REG_CAMERA_BITMASK			0x18
+#define OV511_REG_CAMERA_BITMASK		0x18
 
 /* Snapshot mode camera interface register numbers */
 #define OV511_REG_SNAP_CAPTURED_FRAME		0x19
 #define OV511_REG_SNAP_CLAMPED_PIXEL_NUM	0x1A
 #define OV511_REG_SNAP_CLAMPED_LINE_NUM		0x1B
 #define OV511_REG_SNAP_PIXEL_DIVISOR		0x1C
-#define OV511_REG_SNAP_LINE_DIVISOR			0x1D
+#define OV511_REG_SNAP_LINE_DIVISOR		0x1D
 #define OV511_REG_SNAP_DATA_INPUT_SELECT	0x1E
-#define OV511_REG_SNAP_BITMASK				0x1F
+#define OV511_REG_SNAP_BITMASK			0x1F
 
 /* DRAM register numbers */
 #define OV511_REG_DRAM_ENABLE_FLOW_CONTROL	0x20
@@ -37,21 +41,21 @@
 #define OV511_REG_DRAM_REFRESH_COUNTER		0x23
 
 /* ISO FIFO register numbers */
-#define OV511_REG_FIFO_PACKET_SIZE			0x30
-#define OV511_REG_FIFO_BITMASK				0x31
+#define OV511_REG_FIFO_PACKET_SIZE		0x30
+#define OV511_REG_FIFO_BITMASK			0x31
 
 /* PIO register numbers */
-#define OV511_REG_PIO_BITMASK				0x38
-#define OV511_REG_PIO_DATA_PORT				0x39
-#define OV511_REG_PIO_BIST					0x3E
+#define OV511_REG_PIO_BITMASK			0x38
+#define OV511_REG_PIO_DATA_PORT			0x39
+#define OV511_REG_PIO_BIST			0x3E
 
 /* I2C register numbers */
-#define OV511_REG_I2C_CONTROL				0x40
+#define OV511_REG_I2C_CONTROL			0x40
 #define OV511_REG_I2C_SLAVE_ID_WRITE		0x41
 #define OV511_REG_I2C_SUB_ADDRESS_3_BYTE	0x42
 #define OV511_REG_I2C_SUB_ADDRESS_2_BYTE	0x43
-#define OV511_REG_I2C_SLAVE_ID_READ			0x44
-#define OV511_REG_I2C_DATA_PORT				0x45
+#define OV511_REG_I2C_SLAVE_ID_READ		0x44
+#define OV511_REG_I2C_DATA_PORT			0x45
 #define OV511_REG_I2C_CLOCK_PRESCALER		0x46
 #define OV511_REG_I2C_TIME_OUT_COUNTER		0x47
 
@@ -60,39 +64,39 @@
 #define OV511_REG_I2C_SNAP_DATA_PORT		0x49
 
 /* System control register numbers */
-#define OV511_REG_SYSTEM_RESET				0x50
-#define 	OV511_RESET_UDC				0x01
-#define 	OV511_RESET_I2C				0x02
-#define 	OV511_RESET_FIFO			0x04
-#define 	OV511_RESET_OMNICE			0x08
+#define OV511_REG_SYSTEM_RESET			0x50
+#define 	OV511_RESET_UDC			0x01
+#define 	OV511_RESET_I2C			0x02
+#define 	OV511_RESET_FIFO		0x04
+#define 	OV511_RESET_OMNICE		0x08
 #define 	OV511_RESET_DRAM_INTF		0x10
 #define 	OV511_RESET_CAMERA_INTF		0x20
-#define		OV511_RESET_OV511			0x40
-#define		OV511_RESET_NOREGS			0x3F	/* All but OV511 & regs */
-#define 	OV511_RESET_ALL				0x7F
+#define 	OV511_RESET_OV511		0x40
+#define 	OV511_RESET_NOREGS		0x3F /* All but OV511 & regs */
+#define 	OV511_RESET_ALL			0x7F
 #define OV511_REG_SYSTEM_CLOCK_DIVISOR		0x51
-#define OV511_REG_SYSTEM_SNAPSHOT			0x52
+#define OV511_REG_SYSTEM_SNAPSHOT		0x52
 #define OV511_REG_SYSTEM_INIT         		0x53
-#define OV511_REG_SYSTEM_PWR_CLK      		0x54    /* OV511+ only */
-#define OV511_REG_SYSTEM_LED_CTL      		0x55    /* OV511+ only */
+#define OV511_REG_SYSTEM_PWR_CLK		0x54	/* OV511+ only */
+#define OV511_REG_SYSTEM_LED_CTL		0x55	/* OV511+ only */
 #define OV511_REG_SYSTEM_USER_DEFINED		0x5E
-#define OV511_REG_SYSTEM_CUSTOM_ID			0x5F
+#define OV511_REG_SYSTEM_CUSTOM_ID		0x5F
 
 /* OmniCE register numbers */
-#define OV511_OMNICE_PREDICTION_HORIZ_Y	0x70
+#define OV511_OMNICE_PREDICTION_HORIZ_Y		0x70
 #define OV511_OMNICE_PREDICTION_HORIZ_UV	0x71
 #define OV511_OMNICE_PREDICTION_VERT_Y		0x72
-#define OV511_OMNICE_PREDICTION_VERT_UV	0x73
+#define OV511_OMNICE_PREDICTION_VERT_UV		0x73
 #define OV511_OMNICE_QUANTIZATION_HORIZ_Y	0x74
 #define OV511_OMNICE_QUANTIZATION_HORIZ_UV	0x75
 #define OV511_OMNICE_QUANTIZATION_VERT_Y	0x76
 #define OV511_OMNICE_QUANTIZATION_VERT_UV	0x77
-#define OV511_OMNICE_ENABLE					0x78
-#define OV511_OMNICE_LUT_ENABLE				0x79		
-#define OV511_OMNICE_Y_LUT_BEGIN			0x80
-#define OV511_OMNICE_Y_LUT_END				0x9F
-#define OV511_OMNICE_UV_LUT_BEGIN			0xA0
-#define OV511_OMNICE_UV_LUT_END				0xBF
+#define OV511_OMNICE_ENABLE			0x78
+#define OV511_OMNICE_LUT_ENABLE			0x79		
+#define OV511_OMNICE_Y_LUT_BEGIN		0x80
+#define OV511_OMNICE_Y_LUT_END			0x9F
+#define OV511_OMNICE_UV_LUT_BEGIN		0xA0
+#define OV511_OMNICE_UV_LUT_END			0xBF
 
 /* Alternate numbers for various max packet sizes (OV511 only) */
 #define OV511_ALT_SIZE_992	0
@@ -114,7 +118,7 @@
 #define OV511PLUS_ALT_SIZE_769	6
 #define OV511PLUS_ALT_SIZE_961	7
 
-/* ov7610 registers */
+/* OV7610 registers */
 #define OV7610_REG_GAIN          0x00
 #define OV7610_REG_BLUE          0x01
 #define OV7610_REG_RED           0x02
@@ -163,12 +167,12 @@
 
 #define SCRATCH_BUF_SIZE 384
 
-#define FRAMES_PER_DESC		10  /* FIXME - What should this be? */
+#define FRAMES_PER_DESC		10	/* FIXME - What should this be? */
 #define FRAME_SIZE_PER_DESC	993	/* FIXME - Deprecated */
-#define MAX_FRAME_SIZE_PER_DESC	993  /* For statically allocated stuff */
+#define MAX_FRAME_SIZE_PER_DESC	993	/* For statically allocated stuff */
 
 // FIXME - should this be 0x81 (endpoint address) or 0x01 (endpoint number)?
-#define OV511_ENDPOINT_ADDRESS 0x81 /* Address of isoc endpoint */
+#define OV511_ENDPOINT_ADDRESS 0x81	/* Address of isoc endpoint */
 
 // CAMERA SPECIFIC
 // FIXME - these can vary between specific models
@@ -213,7 +217,7 @@
 	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
 	FRAME_READY,		/* Ready to start grabbing */
 	FRAME_GRABBING,		/* In the process of being grabbed into */
-	FRAME_DONE,			/* Finished grabbing, but not been synced yet */
+	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
 	FRAME_ERROR,		/* Something bad happened while processing */
 };
 
@@ -238,7 +242,7 @@
 	int hdrheight;		/* Height */
 
 	int sub_flag;		/* Sub-capture mode for this frame? */
-	int format;			/* Format for this frame */
+	int format;		/* Format for this frame */
 	int segsize;		/* How big is each segment from the camera? */
 
 	volatile int grabstate;	/* State of grabbing */
@@ -253,7 +257,7 @@
 
 	wait_queue_head_t wq;	/* Processes waiting */
 
-	int snapshot;			/* True if frame was a snapshot */
+	int snapshot;		/* True if frame was a snapshot */
 };
 
 #define OV511_NUMFRAMES	2
@@ -261,23 +265,28 @@
 
 struct usb_ov511 {
 	struct video_device vdev;
-	
+
 	/* Device structure */
 	struct usb_device *dev;
 
+#if 0
 	unsigned char customid; /* Type of camera */
+#else
+	int customid;
+	int desc;
+#endif
 
 	unsigned char iface;
-	
+
 	struct semaphore lock;
-	int user;			/* user count for exclusive use */
+	int user;		/* user count for exclusive use */
 
 	int streaming;		/* Are we streaming Isochronous? */
 	int grabbing;		/* Are we grabbing? */
 
 	int compress;		/* Should the next frame be compressed? */
 
-	char *fbuf;			/* Videodev buffer area */
+	char *fbuf;		/* Videodev buffer area */
 
 	int sub_flag;		/* Pix Array subcapture on flag */
 	int subx;		/* Pix Array subcapture x offset */
@@ -297,12 +306,22 @@
 
 	wait_queue_head_t wq;	/* Processes waiting */
 
-	int snap_enabled;   /* Snapshot mode enabled */
+	int snap_enabled;	/* Snapshot mode enabled */
 	
-	int bridge;         /* Type of bridge (OV511 or OV511+) */
-	int sensor;         /* Type of image sensor chip */
+	int bridge;		/* Type of bridge (OV511 or OV511+) */
+	int sensor;		/* Type of image sensor chip */
+
+	int packet_size;	/* Frame size per isoc desc */
+
+				/* proc interface */
+	struct semaphore param_lock;	/* params lock for this camera */
+	struct proc_dir_entry *proc_entry;	/* /proc/ov511/videoX */
+};
+
 
-	int packet_size;    /* Frame size per isoc desc */
+struct cam_list {
+	int id;
+	char *description;
 };
 
 #endif
