~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/usb/ov511.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * OmniVision OV511 Camera-to-USB Bridge Driver
  3  *
  4  * Copyright (c) 1999-2000 Mark W. McClelland
  5  * Many improvements by Bret Wallach <bwallac1@san.rr.com>
  6  * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
  7  * Snapshot code by Kevin Moore
  8  * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
  9  * Changes by Claudio Matsuoka <claudio@conectiva.com>
 10  * 
 11  * Based on the Linux CPiA driver written by Peter Pregler,
 12  * Scott J. Bertin and Johannes Erdfelt.
 13  * 
 14  * Please see the file: linux/Documentation/usb/ov511.txt 
 15  * and the website at:  http://alpha.dyndns.org/ov511
 16  * for more info.
 17  *
 18  * This program is free software; you can redistribute it and/or modify it
 19  * under the terms of the GNU General Public License as published by the
 20  * Free Software Foundation; either version 2 of the License, or (at your
 21  * option) any later version.
 22  *
 23  * This program is distributed in the hope that it will be useful, but
 24  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 25  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 26  * for more details.
 27  *
 28  * You should have received a copy of the GNU General Public License
 29  * along with this program; if not, write to the Free Software Foundation,
 30  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 31  */
 32 
 33 static const char version[] = "1.28";
 34 
 35 #define __NO_VERSION__
 36 
 37 #include <linux/config.h>
 38 #include <linux/module.h>
 39 #include <linux/version.h>
 40 #include <linux/init.h>
 41 #include <linux/fs.h>
 42 #include <linux/vmalloc.h>
 43 #include <linux/slab.h>
 44 #include <linux/proc_fs.h>
 45 #include <linux/ctype.h>
 46 #include <linux/pagemap.h>
 47 #include <linux/usb.h>
 48 #include <asm/io.h>
 49 #include <asm/semaphore.h>
 50 #include <linux/wrapper.h>
 51 
 52 #include "ov511.h"
 53 
 54 #define OV511_I2C_RETRIES 3
 55 
 56 /* Video Size 640 x 480 x 3 bytes for RGB */
 57 #define MAX_FRAME_SIZE (640 * 480 * 3)
 58 #define MAX_DATA_SIZE (MAX_FRAME_SIZE + sizeof(struct timeval))
 59 
 60 #define GET_SEGSIZE(p) ((p) == VIDEO_PALETTE_GREY ? 256 : 384)
 61 
 62 /* PARAMETER VARIABLES: */
 63 static int autoadjust = 1;    /* CCD dynamically changes exposure, etc... */
 64 
 65 /* 0=no debug messages
 66  * 1=init/detection/unload and other significant messages,
 67  * 2=some warning messages
 68  * 3=config/control function calls
 69  * 4=most function calls and data parsing messages
 70  * 5=highly repetitive mesgs
 71  * NOTE: This should be changed to 0, 1, or 2 for production kernels
 72  */
 73 static int debug = 0;
 74 
 75 /* Fix vertical misalignment of red and blue at 640x480 */
 76 static int fix_rgb_offset = 0;
 77 
 78 /* Snapshot mode enabled flag */
 79 static int snapshot = 0;
 80 
 81 /* Sensor detection override (global for all attached cameras) */
 82 static int sensor = 0;
 83 
 84 /* Increase this if you are getting "Failed to read sensor ID..." */
 85 static int i2c_detect_tries = 5;
 86 
 87 /* For legal values, see the OV7610/7620 specs under register Common F,
 88  * upper nybble  (set to 0-F) */
 89 static int aperture = -1;
 90 
 91 /* Force image to be read in RGB instead of BGR. This option allow
 92  * programs that expect RGB data (e.g. gqcam) to work with this driver. */
 93 static int force_rgb = 0;
 94 
 95 /* Number of seconds before inactive buffers are deallocated */
 96 static int buf_timeout = 5;
 97 
 98 /* Number of cameras to stream from simultaneously */
 99 static int cams = 1;
100 
101 /* Prevent apps from timing out if frame is not done in time */
102 static int retry_sync = 0;
103 
104 /* Enable compression. This is for experimentation only; compressed images
105  * still cannot be decoded yet. */
106 static int compress = 0;
107 
108 /* Display test pattern - doesn't work yet either */
109 static int testpat = 0;
110 
111 /* Setting this to 1 will make the sensor output GBR422 instead on YUV420. Only
112  * affects RGB24 mode. */
113 static int sensor_gbr = 0;
114 
115 /* Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details. */
116 static int dumppix = 0;
117 
118 MODULE_PARM(autoadjust, "i");
119 MODULE_PARM_DESC(autoadjust, "CCD dynamically changes exposure");
120 MODULE_PARM(debug, "i");
121 MODULE_PARM_DESC(debug, "Debug level: 0=none, 1=init/detection, 2=warning, 3=config/control, 4=function call, 5=max");
122 MODULE_PARM(fix_rgb_offset, "i");
123 MODULE_PARM_DESC(fix_rgb_offset, "Fix vertical misalignment of red and blue at 640x480");
124 MODULE_PARM(snapshot, "i");
125 MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
126 MODULE_PARM(sensor, "i");
127 MODULE_PARM_DESC(sensor, "Override sensor detection");
128 MODULE_PARM(i2c_detect_tries, "i");
129 MODULE_PARM_DESC(i2c_detect_tries, "Number of tries to detect sensor");
130 MODULE_PARM(aperture, "i");
131 MODULE_PARM_DESC(aperture, "Read the OV7610/7620 specs");
132 MODULE_PARM(force_rgb, "i");
133 MODULE_PARM_DESC(force_rgb, "Read RGB instead of BGR");
134 MODULE_PARM(buf_timeout, "i");
135 MODULE_PARM_DESC(buf_timeout, "Number of seconds before buffer deallocation");
136 MODULE_PARM(cams, "i");
137 MODULE_PARM_DESC(cams, "Number of simultaneous cameras");
138 MODULE_PARM(retry_sync, "i");
139 MODULE_PARM_DESC(retry_sync, "Prevent apps from timing out");
140 MODULE_PARM(compress, "i");
141 MODULE_PARM_DESC(compress, "Turn on compression (not functional yet)");
142 MODULE_PARM(testpat, "i");
143 MODULE_PARM_DESC(testpat, "Replace image with vertical bar testpattern (only partially working)");
144 MODULE_PARM(sensor_gbr, "i");
145 MODULE_PARM_DESC(sensor_gbr, "Make sensor output GBR422 rather than YUV420");
146 MODULE_PARM(dumppix, "i");
147 MODULE_PARM_DESC(dumppix, "Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details");
148 
149 MODULE_AUTHOR("Mark McClelland <mwm@i.am> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>");
150 MODULE_DESCRIPTION("OV511 USB Camera Driver");
151 
152 char kernel_version[] = UTS_RELEASE;
153 
154 static struct usb_driver ov511_driver;
155 
156 /* I know, I know, global variables suck. This is only a temporary hack */
157 int output_offset;
158 
159 /**********************************************************************
160  * List of known OV511-based cameras
161  **********************************************************************/
162 
163 static struct cam_list clist[] = {
164         {   0, "generic model (no ID)" },
165         {   3, "D-Link DSB-C300" },
166         {   4, "generic OV511/OV7610" },
167         {   5, "Puretek PT-6007" },
168         {  21, "Creative Labs WebCam 3" },
169         {  36, "Koala-Cam" },
170         {  38, "Lifeview USB Life TV" },        /* No support yet! */
171         { 100, "Lifeview RoboCam" },
172         { 102, "AverMedia InterCam Elite" },
173         { 112, "MediaForte MV300" },    /* or OV7110 evaluation kit */
174         {  -1, NULL }
175 };
176 
177 static __devinitdata struct usb_device_id device_table [] = {
178         { USB_DEVICE(0x05a9, 0x0511) },  /* OV511 */
179         { USB_DEVICE(0x05a9, 0xA511) },  /* OV511+ */
180         { USB_DEVICE(0x0813, 0x0002) },  /* Intel Play Me2Cam OV511+ */
181         { }  /* Terminating entry */
182 };
183 
184 MODULE_DEVICE_TABLE (usb, device_table);
185 
186 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
187 static struct palette_list plist[] = {
188         { VIDEO_PALETTE_GREY,   "GREY" },
189         { VIDEO_PALETTE_HI240,  "HI240" },
190         { VIDEO_PALETTE_RGB565, "RGB565" },
191         { VIDEO_PALETTE_RGB24,  "RGB24" },
192         { VIDEO_PALETTE_RGB32,  "RGB32" },
193         { VIDEO_PALETTE_RGB555, "RGB555" },
194         { VIDEO_PALETTE_YUV422, "YUV422" },
195         { VIDEO_PALETTE_YUYV,   "YUYV" },
196         { VIDEO_PALETTE_UYVY,   "UYVY" },
197         { VIDEO_PALETTE_YUV420, "YUV420" },
198         { VIDEO_PALETTE_YUV411, "YUV411" },
199         { VIDEO_PALETTE_RAW,    "RAW" },
200         { VIDEO_PALETTE_YUV422P,"YUV422P" },
201         { VIDEO_PALETTE_YUV411P,"YUV411P" },
202         { VIDEO_PALETTE_YUV420P,"YUV420P" },
203         { VIDEO_PALETTE_YUV410P,"YUV410P" },
204         { -1, NULL }
205 };
206 #endif
207 
208 /**********************************************************************
209  *
210  * Memory management
211  *
212  * This is a shameless copy from the USB-cpia driver (linux kernel
213  * version 2.3.29 or so, I have no idea what this code actually does ;).
214  * Actually it seems to be a copy of a shameless copy of the bttv-driver.
215  * Or that is a copy of a shameless copy of ... (To the powers: is there
216  * no generic kernel-function to do this sort of stuff?)
217  *
218  * Yes, it was a shameless copy from the bttv-driver. IIRC, Alan says
219  * there will be one, but apparentely not yet -jerdfelt
220  *
221  * So I copied it again for the OV511 driver -claudio
222  **********************************************************************/
223 
224 /* Given PGD from the address space's page table, return the kernel
225  * virtual mapping of the physical memory mapped at ADR.
226  */
227 static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
228 {
229         unsigned long ret = 0UL;
230         pmd_t *pmd;
231         pte_t *ptep, pte;
232 
233         if (!pgd_none(*pgd)) {
234                 pmd = pmd_offset(pgd, adr);
235                 if (!pmd_none(*pmd)) {
236                         ptep = pte_offset(pmd, adr);
237                         pte = *ptep;
238                         if (pte_present(pte)) {
239                                 ret = (unsigned long) page_address(pte_page(pte));
240                                 ret |= (adr & (PAGE_SIZE - 1));
241                         }
242                 }
243         }
244 
245         return ret;
246 }
247 
248 /* Here we want the physical address of the memory.
249  * This is used when initializing the contents of the
250  * area and marking the pages as reserved.
251  */
252 static inline unsigned long kvirt_to_pa(unsigned long adr)
253 {
254         unsigned long va, kva, ret;
255 
256         va = VMALLOC_VMADDR(adr);
257         kva = uvirt_to_kva(pgd_offset_k(va), va);
258         ret = __pa(kva);
259         return ret;
260 }
261 
262 static void *rvmalloc(unsigned long size)
263 {
264         void *mem;
265         unsigned long adr, page;
266 
267         /* Round it off to PAGE_SIZE */
268         size += (PAGE_SIZE - 1);
269         size &= ~(PAGE_SIZE - 1);
270 
271         mem = vmalloc_32(size);
272         if (!mem)
273                 return NULL;
274 
275         memset(mem, 0, size); /* Clear the ram out, no junk to the user */
276         adr = (unsigned long) mem;
277         while (size > 0) {
278                 page = kvirt_to_pa(adr);
279                 mem_map_reserve(virt_to_page(__va(page)));
280                 adr += PAGE_SIZE;
281                 if (size > PAGE_SIZE)
282                         size -= PAGE_SIZE;
283                 else
284                         size = 0;
285         }
286 
287         return mem;
288 }
289 
290 static void rvfree(void *mem, unsigned long size)
291 {
292         unsigned long adr, page;
293 
294         if (!mem)
295                 return;
296 
297         size += (PAGE_SIZE - 1);
298         size &= ~(PAGE_SIZE - 1);
299 
300         adr=(unsigned long) mem;
301         while (size > 0) {
302                 page = kvirt_to_pa(adr);
303                 mem_map_unreserve(virt_to_page(__va(page)));
304                 adr += PAGE_SIZE;
305                 if (size > PAGE_SIZE)
306                         size -= PAGE_SIZE;
307                 else
308                         size = 0;
309         }
310         vfree(mem);
311 }
312 
313 /**********************************************************************
314  * /proc interface
315  * Based on the CPiA driver version 0.7.4 -claudio
316  **********************************************************************/
317 
318 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
319 
320 static struct proc_dir_entry *ov511_proc_entry = NULL;
321 extern struct proc_dir_entry *video_proc_entry;
322 
323 #define YES_NO(x) ((x) ? "yes" : "no")
324 
325 static int ov511_read_proc(char *page, char **start, off_t off,
326                           int count, int *eof, void *data)
327 {
328         char *out = page;
329         int i, j, len;
330         struct usb_ov511 *ov511 = data;
331 
332         /* IMPORTANT: This output MUST be kept under PAGE_SIZE
333          *            or we need to get more sophisticated. */
334 
335         out += sprintf (out, "driver_version  : %s\n", version);
336         out += sprintf (out, "custom_id       : %d\n", ov511->customid);
337         out += sprintf (out, "model           : %s\n", ov511->desc ?
338                 clist[ov511->desc].description : "unknown");
339         out += sprintf (out, "streaming       : %s\n", YES_NO (ov511->streaming));
340         out += sprintf (out, "grabbing        : %s\n", YES_NO (ov511->grabbing));
341         out += sprintf (out, "compress        : %s\n", YES_NO (ov511->compress));
342         out += sprintf (out, "subcapture      : %s\n", YES_NO (ov511->sub_flag));
343         out += sprintf (out, "sub_size        : %d %d %d %d\n",
344                 ov511->subx, ov511->suby, ov511->subw, ov511->subh);
345         out += sprintf (out, "data_format     : %s\n", force_rgb ? "RGB" : "BGR");
346         out += sprintf (out, "brightness      : %d\n", ov511->brightness >> 8);
347         out += sprintf (out, "colour          : %d\n", ov511->colour >> 8);
348         out += sprintf (out, "contrast        : %d\n", ov511->contrast >> 8);
349         out += sprintf (out, "num_frames      : %d\n", OV511_NUMFRAMES);
350         for (i = 0; i < OV511_NUMFRAMES; i++) {
351                 out += sprintf (out, "frame           : %d\n", i);
352                 out += sprintf (out, "  depth         : %d\n",
353                         ov511->frame[i].depth);
354                 out += sprintf (out, "  size          : %d %d\n",
355                         ov511->frame[i].width, ov511->frame[i].height);
356                 out += sprintf (out, "  format        : ");
357                 for (j = 0; plist[j].num >= 0; j++) {
358                         if (plist[j].num == ov511->frame[i].format) {
359                                 out += sprintf (out, "%s\n", plist[j].name);
360                                 break;
361                         }
362                 }
363                 if (plist[j].num < 0)
364                         out += sprintf (out, "unknown\n");
365                 out += sprintf (out, "  segsize       : %d\n",
366                         ov511->frame[i].segsize);
367                 out += sprintf (out, "  data_buffer   : 0x%p\n",
368                         ov511->frame[i].data);
369         }
370         out += sprintf (out, "snap_enabled    : %s\n", YES_NO (ov511->snap_enabled));
371         out += sprintf (out, "bridge          : %s\n",
372                 ov511->bridge == BRG_OV511 ? "OV511" :
373                 ov511->bridge == BRG_OV511PLUS ? "OV511+" :
374                 "unknown");
375         out += sprintf (out, "sensor          : %s\n",
376                 ov511->sensor == SEN_OV6620 ? "OV6620" :
377                 ov511->sensor == SEN_OV7610 ? "OV7610" :
378                 ov511->sensor == SEN_OV7620 ? "OV7620" :
379                 ov511->sensor == SEN_OV7620AE ? "OV7620AE" :
380                 "unknown");
381         out += sprintf (out, "packet_size     : %d\n", ov511->packet_size);
382         out += sprintf (out, "framebuffer     : 0x%p\n", ov511->fbuf);
383         
384         len = out - page;
385         len -= off;
386         if (len < count) {
387                 *eof = 1;
388                 if (len <= 0) return 0;
389         } else
390                 len = count;
391 
392         *start = page + off;
393 
394         return len;
395 }
396 
397 static int ov511_write_proc(struct file *file, const char *buffer,
398                            unsigned long count, void *data)
399 {
400         return -EINVAL;
401 }
402 
403 static void create_proc_ov511_cam (struct usb_ov511 *ov511)
404 {
405         char name[7];
406         struct proc_dir_entry *ent;
407         
408         if (!ov511_proc_entry || !ov511)
409                 return;
410 
411         sprintf(name, "video%d", ov511->vdev.minor);
412         PDEBUG (4, "creating /proc/video/ov511/%s", name);
413         
414         ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_entry);
415 
416         if (!ent)
417                 return;
418 
419         ent->data = ov511;
420         ent->read_proc = ov511_read_proc;
421         ent->write_proc = ov511_write_proc;
422         ov511->proc_entry = ent;
423 }
424 
425 static void destroy_proc_ov511_cam (struct usb_ov511 *ov511)
426 {
427         char name[7];
428         
429         if (!ov511 || !ov511->proc_entry)
430                 return;
431         
432         sprintf(name, "video%d", ov511->vdev.minor);
433         PDEBUG (4, "destroying %s", name);
434         remove_proc_entry(name, ov511_proc_entry);
435         ov511->proc_entry = NULL;
436 }
437 
438 static void proc_ov511_create(void)
439 {
440         /* No current standard here. Alan prefers /proc/video/ as it keeps
441          * /proc "less cluttered than /proc/randomcardifoundintheshed/"
442          * -claudio
443          */
444         if (video_proc_entry == NULL) {
445                 err("Unable to initialise /proc/video/ov511");
446                 return;
447         }
448 
449         ov511_proc_entry = create_proc_entry("ov511", S_IFDIR, video_proc_entry);
450 
451         if (ov511_proc_entry)
452                 ov511_proc_entry->owner = THIS_MODULE;
453         else
454                 err("Unable to initialise /proc/ov511");
455 }
456 
457 static void proc_ov511_destroy(void)
458 {
459         PDEBUG (3, "removing /proc/video/ov511");
460 
461         if (ov511_proc_entry == NULL)
462                 return;
463 
464         remove_proc_entry("ov511", video_proc_entry);
465 }
466 #endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */
467 
468 /**********************************************************************
469  *
470  * Camera interface
471  *
472  **********************************************************************/
473 
474 static int ov511_reg_write(struct usb_device *dev,
475                            unsigned char reg,
476                            unsigned char value)
477 {
478         int rc;
479 
480         rc = usb_control_msg(dev,
481                 usb_sndctrlpipe(dev, 0),
482                 2 /* REG_IO */,
483                 USB_TYPE_CLASS | USB_RECIP_DEVICE,
484                 0, (__u16)reg, &value, 1, HZ);  
485 
486         PDEBUG(5, "reg write: 0x%02X:0x%02X, 0x%x", reg, value, rc);
487 
488         if (rc < 0)
489                 err("reg write: error %d", rc);
490 
491         return rc;
492 }
493 
494 /* returns: negative is error, pos or zero is data */
495 static int ov511_reg_read(struct usb_device *dev, unsigned char reg)
496 {
497         int rc;
498         unsigned char buffer[1];
499 
500         rc = usb_control_msg(dev,
501                 usb_rcvctrlpipe(dev, 0),
502                 2 /* REG_IO */,
503                 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
504                 0, (__u16)reg, buffer, 1, HZ);
505                                
506         PDEBUG(5, "reg read: 0x%02X:0x%02X", reg, buffer[0]);
507         
508         if (rc < 0) {
509                 err("reg read: error %d", rc);
510                 return rc;
511         } else {
512                 return buffer[0];       
513         }
514 }
515 
516 static int ov511_i2c_write(struct usb_device *dev,
517                            unsigned char reg,
518                            unsigned char value)
519 {
520         int rc, retries;
521 
522         PDEBUG(5, "i2c write: 0x%02X:0x%02X", reg, value);
523 
524         /* Three byte write cycle */
525         for (retries = OV511_I2C_RETRIES; ; ) {
526                 /* Select camera register */
527                 rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);
528                 if (rc < 0) goto error;
529 
530                 /* Write "value" to I2C data port of OV511 */
531                 rc = ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value);      
532                 if (rc < 0) goto error;
533 
534                 /* Initiate 3-byte write cycle */
535                 rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x01);
536                 if (rc < 0) goto error;
537 
538                 do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
539                 while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
540                 if (rc < 0) goto error;
541 
542                 if ((rc&2) == 0) /* Ack? */
543                         break;
544 #if 0
545                 /* I2C abort */ 
546                 ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
547 #endif
548                 if (--retries < 0) {
549                         err("i2c write retries exhausted");
550                         rc = -1;
551                         goto error;
552                 }
553         }
554 
555         return 0;
556 
557 error:
558         err("i2c write: error %d", rc);
559         return rc;
560 }
561 
562 /* returns: negative is error, pos or zero is data */
563 static int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
564 {
565         int rc, value, retries;
566 
567         /* Two byte write cycle */
568         for (retries = OV511_I2C_RETRIES; ; ) {
569                 /* Select camera register */
570                 rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);
571                 if (rc < 0) goto error;
572 
573                 /* Initiate 2-byte write cycle */
574                 rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x03);
575                 if (rc < 0) goto error;
576 
577                 do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
578                 while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
579                 if (rc < 0) goto error;
580 
581                 if ((rc&2) == 0) /* Ack? */
582                         break;
583 
584                 /* I2C abort */ 
585                 ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
586 
587                 if (--retries < 0) {
588                         err("i2c write retries exhausted");
589                         rc = -1;
590                         goto error;
591                 }
592         }
593 
594         /* Two byte read cycle */
595         for (retries = OV511_I2C_RETRIES; ; ) {
596                 /* Initiate 2-byte read cycle */
597                 rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
598                 if (rc < 0) goto error;
599 
600                 do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);
601                 while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
602                 if (rc < 0) goto error;
603 
604                 if ((rc&2) == 0) /* Ack? */
605                         break;
606 
607                 /* I2C abort */ 
608                 rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);
609                 if (rc < 0) goto error;
610 
611                 if (--retries < 0) {
612                         err("i2c read retries exhausted");
613                         rc = -1;
614                         goto error;
615                 }
616         }
617 
618         value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
619 
620         PDEBUG(5, "i2c read: 0x%02X:0x%02X", reg, value);
621                 
622         /* This is needed to make ov511_i2c_write() work */
623         rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
624         if (rc < 0)
625                 goto error;
626         
627         return value;
628 
629 error:
630         err("i2c read: error %d", rc);
631         return rc;
632 }
633 
634 static int ov511_write_regvals(struct usb_device *dev,
635                                struct ov511_regvals * pRegvals)
636 {
637         int rc;
638 
639         while (pRegvals->bus != OV511_DONE_BUS) {
640                 if (pRegvals->bus == OV511_REG_BUS) {
641                         if ((rc = ov511_reg_write(dev, pRegvals->reg,
642                                                    pRegvals->val)) < 0)
643                                 goto error;
644                 } else if (pRegvals->bus == OV511_I2C_BUS) {
645                         if ((rc = ov511_i2c_write(dev, pRegvals->reg, 
646                                                    pRegvals->val)) < 0)
647                                 goto error;
648                 } else {
649                         err("Bad regval array");
650                         rc = -1;
651                         goto error;
652                 }
653                 pRegvals++;
654         }
655         return 0;
656 
657 error:
658         err("write regvals: error %d", rc);
659         return rc;
660 }
661 
662 #ifdef OV511_DEBUG 
663 static void ov511_dump_i2c_range(struct usb_device *dev, int reg1, int regn)
664 {
665         int i;
666         int rc;
667         for(i = reg1; i <= regn; i++) {
668                 rc = ov511_i2c_read(dev, i);
669                 PDEBUG(1, "OV7610[0x%X] = 0x%X", i, rc);
670         }
671 }
672 
673 static void ov511_dump_i2c_regs(struct usb_device *dev)
674 {
675         PDEBUG(3, "I2C REGS");
676         ov511_dump_i2c_range(dev, 0x00, 0x7C);
677 }
678 
679 #if 0
680 static void ov511_dump_reg_range(struct usb_device *dev, int reg1, int regn)
681 {
682         int i;
683         int rc;
684         for(i = reg1; i <= regn; i++) {
685           rc = ov511_reg_read(dev, i);
686           PDEBUG(1, "OV511[0x%X] = 0x%X", i, rc);
687         }
688 }
689 
690 static void ov511_dump_regs(struct usb_device *dev)
691 {
692         PDEBUG(1, "CAMERA INTERFACE REGS");
693         ov511_dump_reg_range(dev, 0x10, 0x1f);
694         PDEBUG(1, "DRAM INTERFACE REGS");
695         ov511_dump_reg_range(dev, 0x20, 0x23);
696         PDEBUG(1, "ISO FIFO REGS");
697         ov511_dump_reg_range(dev, 0x30, 0x31);
698         PDEBUG(1, "PIO REGS");
699         ov511_dump_reg_range(dev, 0x38, 0x39);
700         ov511_dump_reg_range(dev, 0x3e, 0x3e);
701         PDEBUG(1, "I2C REGS");
702         ov511_dump_reg_range(dev, 0x40, 0x49);
703         PDEBUG(1, "SYSTEM CONTROL REGS");
704         ov511_dump_reg_range(dev, 0x50, 0x55);
705         ov511_dump_reg_range(dev, 0x5e, 0x5f);
706         PDEBUG(1, "OmniCE REGS");
707         ov511_dump_reg_range(dev, 0x70, 0x79);
708         ov511_dump_reg_range(dev, 0x80, 0x9f);
709         ov511_dump_reg_range(dev, 0xa0, 0xbf);
710 
711 }
712 #endif
713 #endif
714 
715 static int ov511_reset(struct usb_device *dev, unsigned char reset_type)
716 {
717         int rc;
718         
719         PDEBUG(4, "Reset: type=0x%X", reset_type);
720         rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type);
721         rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0);
722 
723         if (rc < 0)
724                 err("reset: command failed");
725 
726         return rc;
727 }
728 
729 /* Temporarily stops OV511 from functioning. Must do this before changing
730  * registers while the camera is streaming */
731 static inline int ov511_stop(struct usb_device *dev)
732 {
733         PDEBUG(4, "stopping");
734         return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d));
735 }
736 
737 /* Restarts OV511 after ov511_stop() is called */
738 static inline int ov511_restart(struct usb_device *dev)
739 {
740         PDEBUG(4, "restarting");
741         return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00));
742 }
743 
744 static int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
745 {
746         int alt, mult;
747 
748         if (ov511_stop(ov511->dev) < 0)
749                 return -EIO;
750 
751         mult = size >> 5;
752 
753         if (ov511->bridge == BRG_OV511) {
754                 if (size == 0) alt = OV511_ALT_SIZE_0;
755                 else if (size == 257) alt = OV511_ALT_SIZE_257;
756                 else if (size == 513) alt = OV511_ALT_SIZE_513;
757                 else if (size == 769) alt = OV511_ALT_SIZE_769;
758                 else if (size == 993) alt = OV511_ALT_SIZE_993;
759                 else {
760                         err("Set packet size: invalid size (%d)", size);
761                         return -EINVAL;
762                 }
763         } else if (ov511->bridge == BRG_OV511PLUS) {
764                 if (size == 0) alt = OV511PLUS_ALT_SIZE_0;
765                 else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;
766                 else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;
767                 else if (size == 257) alt = OV511PLUS_ALT_SIZE_257;
768                 else if (size == 385) alt = OV511PLUS_ALT_SIZE_385;
769                 else if (size == 513) alt = OV511PLUS_ALT_SIZE_513;
770                 else if (size == 769) alt = OV511PLUS_ALT_SIZE_769;
771                 else if (size == 961) alt = OV511PLUS_ALT_SIZE_961;
772                 else {
773                         err("Set packet size: invalid size (%d)", size);
774                         return -EINVAL;
775                 }
776         } else {
777                 err("Set packet size: Invalid bridge type");
778                 return -EINVAL;
779         }
780 
781         PDEBUG(3, "set packet size: %d, mult=%d, alt=%d", size, mult, alt);
782 
783         if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE, mult) < 0)
784                 return -ENOMEM;
785         
786         if (usb_set_interface(ov511->dev, ov511->iface, alt) < 0) {
787                 err("Set packet size: set interface error");
788                 return -EBUSY;
789         }
790 
791         // FIXME - Should we only reset the FIFO?
792         if (ov511_reset(ov511->dev, OV511_RESET_NOREGS) < 0)
793                 return -ENOMEM;
794 
795         ov511->packet_size = size;
796 
797         if (ov511_restart(ov511->dev) < 0)
798                 return -EIO;
799 
800         return 0;
801 }
802 
803 
804 static inline int
805 ov7610_set_picture(struct usb_ov511 *ov511, struct video_picture *p)
806 {
807         int ret;
808         struct usb_device *dev = ov511->dev;
809 
810         PDEBUG(4, "ov511_set_picture");
811 
812         if (ov511_stop(dev) < 0)
813                 return -EIO;
814 
815         ov511->contrast = p->contrast;
816         ov511->brightness = p->brightness;
817         ov511->colour = p->colour;
818         ov511->hue = p->hue;
819         ov511->whiteness = p->whiteness;
820 
821         if ((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0)
822                 return -EIO;
823 #if 0
824         /* disable auto adjust mode */
825         if (ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0)
826                 return -EIO;
827 #endif
828         if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV7620AE
829                 || ov511->sensor == SEN_OV6620)
830                 if (ov511_i2c_write(dev, OV7610_REG_SAT, p->colour >> 8) < 0)
831                         return -EIO;
832 
833         if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV6620) {
834                 if (ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
835                         return -EIO;
836 
837                 if (ov511_i2c_write(dev, OV7610_REG_RED, 0xFF - (p->hue >> 8)) < 0)
838                         return -EIO;
839 
840                 if (ov511_i2c_write(dev, OV7610_REG_BLUE, p->hue >> 8) < 0)
841                         return -EIO;
842 
843                 if (ov511_i2c_write(dev, OV7610_REG_BRT, p->brightness >> 8) < 0)
844                         return -EIO;
845         } else if ((ov511->sensor == SEN_OV7620) 
846                  || (ov511->sensor == SEN_OV7620AE)) {
847 #if 0
848                 int cur_sat, new_sat, tmp;
849 
850                 cur_sat = ov511_i2c_read(dev, OV7610_REG_BLUE);
851 
852                 tmp = (p->hue >> 8) - cur_sat;
853                 new_sat = (tmp < 0) ? (-tmp) | 0x80 : tmp;
854 
855                 PDEBUG(1, "cur=%d target=%d diff=%d", cur_sat, p->hue >> 8, tmp); 
856 
857                 if (ov511_i2c_write(dev, OV7610_REG_BLUE, new_sat) < 0)
858                         return -EIO;
859 
860                 // DEBUG_CODE
861                 PDEBUG(1, "hue=%d", ov511_i2c_read(dev, OV7610_REG_BLUE)); 
862 
863 #endif
864         }
865 
866         if (ov511_restart(dev) < 0)
867                 return -EIO;
868 
869         return 0;
870 }
871 
872 static inline int
873 ov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p)
874 {
875         int ret;
876         struct usb_device *dev = ov511->dev;
877 
878         PDEBUG(4, "ov511_get_picture");
879 
880         if (ov511_stop(dev) < 0)
881                 return -EIO;
882 
883         if ((ret = ov511_i2c_read(dev, OV7610_REG_SAT)) < 0) return -EIO;
884         p->colour = ret << 8;
885 
886         if ((ret = ov511_i2c_read(dev, OV7610_REG_CNT)) < 0) return -EIO;
887         p->contrast = ret << 8;
888 
889         if ((ret = ov511_i2c_read(dev, OV7610_REG_BRT)) < 0) return -EIO;
890         p->brightness = ret << 8;
891 
892         /* This may not be the best way to do it */
893         if ((ret = ov511_i2c_read(dev, OV7610_REG_BLUE)) < 0) return -EIO;
894         p->hue = ret << 8;
895 
896         p->whiteness = 105 << 8;
897 
898         /* Can we get these from frame[0]? -claudio? */
899         p->depth = ov511->frame[0].depth;
900         p->palette = ov511->frame[0].format;
901 
902         if (ov511_restart(dev) < 0)
903                 return -EIO;
904 
905         return 0;
906 }
907 
908 /* Returns number of bits per pixel (regardless of where they are located; planar or
909  * not), or zero for unsupported format.
910  */
911 static int ov511_get_depth(int palette)
912 {
913         switch (palette) {
914         case VIDEO_PALETTE_GREY:    return 8;
915         case VIDEO_PALETTE_RGB565:  return 16;
916         case VIDEO_PALETTE_RGB24:   return 24;  
917         case VIDEO_PALETTE_YUV422:  return 16;
918         case VIDEO_PALETTE_YUYV:    return 16;
919         case VIDEO_PALETTE_YUV420:  return 24;
920         case VIDEO_PALETTE_YUV422P: return 24; /* Planar */
921         default:                    return 0;  /* Invalid format */
922         }
923 }
924 
925 /* LNCNT values fixed by Lawrence Glaister <lg@jfm.bc.ca> */
926 static struct mode_list mlist[] = {
927         /* W    H   C  PXCNT LNCNT PXDIV LNDIV M420  COMA  COML */
928         { 640, 480, 0, 0x4f, 0x3b, 0x00, 0x00, 0x03, 0x24, 0x9e },
929         { 640, 480, 1, 0x4f, 0x3b, 0x00, 0x00, 0x03, 0x24, 0x9e },
930         { 320, 240, 0, 0x27, 0x1d, 0x00, 0x00, 0x03, 0x04, 0x1e },
931         { 320, 240, 1, 0x27, 0x1d, 0x00, 0x00, 0x03, 0x04, 0x1e },
932         { 352, 288, 0, 0x2b, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
933         { 352, 288, 1, 0x2b, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
934         { 384, 288, 0, 0x2f, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
935         { 384, 288, 1, 0x2f, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },
936         { 448, 336, 0, 0x37, 0x29, 0x00, 0x00, 0x03, 0x04, 0x1e },
937         { 448, 336, 1, 0x37, 0x29, 0x00, 0x00, 0x03, 0x04, 0x1e },
938         { 176, 144, 0, 0x15, 0x12, 0x00, 0x00, 0x03, 0x04, 0x1e },
939         { 176, 144, 1, 0x15, 0x12, 0x00, 0x00, 0x03, 0x04, 0x1e },
940         { 160, 120, 0, 0x13, 0x0e, 0x00, 0x00, 0x03, 0x04, 0x1e },
941         { 160, 120, 1, 0x13, 0x0e, 0x00, 0x00, 0x03, 0x04, 0x1e },
942         { 0, 0 }
943 };
944 
945 static int
946 ov511_mode_init_regs(struct usb_ov511 *ov511,
947                      int width, int height, int mode, int sub_flag)
948 {
949         int i;
950         struct usb_device *dev = ov511->dev;
951         int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; 
952         int hwscale = 0, vwscale = 0;
953 
954         PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
955                width, height, mode, sub_flag);
956 
957         if (ov511_stop(ov511->dev) < 0)
958                 return -EIO;
959 
960         /* Dumppix only works with RGB24 */
961         if (dumppix && (mode != VIDEO_PALETTE_RGB24)) {
962                 err("dumppix only supported with RGB 24");
963                 return -EINVAL;
964         }
965 
966         if (mode == VIDEO_PALETTE_GREY) {
967                 ov511_reg_write(dev, 0x16, 0x00);
968                 if (ov511->sensor == SEN_OV7610
969                     || ov511->sensor == SEN_OV7620AE) {
970                         /* these aren't valid on the OV6620/OV7620 */
971                         ov511_i2c_write(dev, 0x0e, 0x44);
972                 }
973                 ov511_i2c_write(dev, 0x13, autoadjust ? 0x21 : 0x20);
974 
975                 /* For snapshot */
976                 ov511_reg_write(dev, 0x1e, 0x00);
977                 ov511_reg_write(dev, 0x1f, 0x01);
978         } else {
979                 ov511_reg_write(dev, 0x16, 0x01);
980                 if (ov511->sensor == SEN_OV7610
981                     || ov511->sensor == SEN_OV7620AE) {
982                         /* not valid on the OV6620/OV7620 */
983                         ov511_i2c_write(dev, 0x0e, 0x04);
984                 }
985                 ov511_i2c_write(dev, 0x13, autoadjust ? 0x01 : 0x00);
986 
987                 /* For snapshot */
988                 ov511_reg_write(dev, 0x1e, 0x01);
989                 ov511_reg_write(dev, 0x1f, 0x03);
990         }
991 
992         /* The different sensor ICs handle setting up of window differently */
993         switch (ov511->sensor) {
994         case SEN_OV7610:
995         case SEN_OV7620AE:
996                 hwsbase = 0x38;
997                 hwebase = 0x3a;
998                 vwsbase = vwebase = 0x05;
999                 break;
1000         case SEN_OV6620:
1001                 hwsbase = 0x38;
1002                 hwebase = 0x3a;
1003                 vwsbase = 0x05;
1004                 vwebase = 0x06;
1005                 break;
1006         case SEN_OV7620:
1007                 hwsbase = 0x2c;
1008                 hwebase = 0x2d;
1009                 vwsbase = vwebase = 0x05;
1010                 break;
1011         default:
1012                 err("Invalid sensor");
1013                 return -EINVAL;
1014         }
1015 
1016         /* Bit 5 of COM C register varies with sensor */ 
1017         if (ov511->sensor == SEN_OV6620) {
1018                 if (width > 176 && height > 144) {  /* CIF */
1019                         ov511_i2c_write(dev, 0x14, 0x04);
1020                         hwscale = 1;
1021                         vwscale = 1;  /* The datasheet says 0; it's wrong */
1022                         hwsize = 352;
1023                         vwsize = 288;
1024                 } else {                            /* QCIF */
1025                         ov511_i2c_write(dev, 0x14, 0x24);
1026                         hwsize = 176;
1027                         vwsize = 144;
1028                 }
1029         }
1030         else {
1031                 if (width > 320 && height > 240) {  /* VGA */
1032                         ov511_i2c_write(dev, 0x14, 0x04);
1033                         hwscale = 2;
1034                         vwscale = 1;
1035                         hwsize = 640;
1036                         vwsize = 480;
1037                 } else {                            /* QVGA */
1038                         ov511_i2c_write(dev, 0x14, 0x24);
1039                         hwscale = 1;
1040                         hwsize = 320;
1041                         vwsize = 240;
1042                 }       
1043         }
1044 
1045         /* FIXME! - This needs to be changed to support 160x120 and 6620!!! */
1046         if (sub_flag) {
1047                 ov511_i2c_write(dev, 0x17, hwsbase+(ov511->subx>>hwscale));
1048                 ov511_i2c_write(dev, 0x18, hwebase+((ov511->subx+ov511->subw)>>hwscale));
1049                 ov511_i2c_write(dev, 0x19, vwsbase+(ov511->suby>>vwscale));
1050                 ov511_i2c_write(dev, 0x1a, vwebase+((ov511->suby+ov511->subh)>>vwscale));
1051         } else {
1052                 ov511_i2c_write(dev, 0x17, hwsbase);
1053                 ov511_i2c_write(dev, 0x18, hwebase + (hwsize>>hwscale));
1054                 ov511_i2c_write(dev, 0x19, vwsbase);
1055                 ov511_i2c_write(dev, 0x1a, vwebase + (vwsize>>vwscale));
1056         }
1057 
1058         for (i = 0; mlist[i].width; i++) {
1059                 int lncnt, pxcnt, clock;
1060 
1061                 if (width != mlist[i].width || height != mlist[i].height)
1062                         continue;
1063 
1064                 if (!mlist[i].color && mode != VIDEO_PALETTE_GREY)
1065                         continue;
1066 
1067                 /* Here I'm assuming that snapshot size == image size.
1068                  * I hope that's always true. --claudio
1069                  */
1070                 pxcnt = sub_flag ? (ov511->subw >> 3) - 1 : mlist[i].pxcnt;
1071                 lncnt = sub_flag ? (ov511->subh >> 3) - 1 : mlist[i].lncnt;
1072 
1073                 ov511_reg_write(dev, 0x12, pxcnt);
1074                 ov511_reg_write(dev, 0x13, lncnt);
1075                 ov511_reg_write(dev, 0x14, mlist[i].pxdv);
1076                 ov511_reg_write(dev, 0x15, mlist[i].lndv);
1077                 ov511_reg_write(dev, 0x18, mlist[i].m420);
1078 
1079                 /* Snapshot additions */
1080                 ov511_reg_write(dev, 0x1a, pxcnt);
1081                 ov511_reg_write(dev, 0x1b, lncnt);
1082                 ov511_reg_write(dev, 0x1c, mlist[i].pxdv);
1083                 ov511_reg_write(dev, 0x1d, mlist[i].lndv);
1084 
1085                 /* Calculate and set the clock divisor */
1086                 clock = ((sub_flag ? ov511->subw * ov511->subh : width * height)
1087                         * (mlist[i].color ? 3 : 2) / 2) / 66000;
1088 #if 0
1089                 clock *= cams;
1090 #endif
1091                 ov511_i2c_write(dev, 0x11, clock);
1092 
1093                 /* We only have code to convert GBR -> RGB24 */
1094                 if ((mode == VIDEO_PALETTE_RGB24) && sensor_gbr)
1095                         ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x0a:0x08));
1096                 else
1097                         ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x02:0x00));
1098 
1099                 /* 7620/6620 don't have register 0x35, so play it safe */
1100                 if (ov511->sensor == SEN_OV7610 ||
1101                     ov511->sensor == SEN_OV7620AE)
1102                         ov511_i2c_write(dev, 0x35, mlist[i].common_L);
1103 
1104                 break;
1105         }
1106 
1107         if (compress) {
1108                 ov511_reg_write(dev, 0x78, 0x03); // Turn on Y compression
1109                 ov511_reg_write(dev, 0x79, 0x00); // Disable LUTs
1110         }
1111 
1112         if (ov511_restart(ov511->dev) < 0)
1113                 return -EIO;
1114 
1115         if (mlist[i].width == 0) {
1116                 err("Unknown mode (%d, %d): %d", width, height, mode);
1117                 return -EINVAL;
1118         }
1119 
1120 #ifdef OV511_DEBUG
1121         if (debug >= 5)
1122                 ov511_dump_i2c_regs(dev);
1123 #endif
1124 
1125         return 0;
1126 }
1127 
1128 /**********************************************************************
1129  *
1130  * Color correction functions
1131  *
1132  **********************************************************************/
1133 
1134 /*
1135  * Turn a YUV4:2:0 block into an RGB block
1136  *
1137  * Video4Linux seems to use the blue, green, red channel
1138  * order convention-- rgb[0] is blue, rgb[1] is green, rgb[2] is red.
1139  *
1140  * Color space conversion coefficients taken from the excellent
1141  * http://www.inforamp.net/~poynton/ColorFAQ.html
1142  * In his terminology, this is a CCIR 601.1 YCbCr -> RGB.
1143  * Y values are given for all 4 pixels, but the U (Pb)
1144  * and V (Pr) are assumed constant over the 2x2 block.
1145  *
1146  * To avoid floating point arithmetic, the color conversion
1147  * coefficients are scaled into 16.16 fixed-point integers.
1148  * They were determined as follows:
1149  *
1150  *      double brightness = 1.0;  (0->black; 1->full scale) 
1151  *      double saturation = 1.0;  (0->greyscale; 1->full color)
1152  *      double fixScale = brightness * 256 * 256;
1153  *      int rvScale = (int)(1.402 * saturation * fixScale);
1154  *      int guScale = (int)(-0.344136 * saturation * fixScale);
1155  *      int gvScale = (int)(-0.714136 * saturation * fixScale);
1156  *      int buScale = (int)(1.772 * saturation * fixScale);
1157  *      int yScale = (int)(fixScale);   
1158  */
1159 
1160 /* LIMIT: convert a 16.16 fixed-point value to a byte, with clipping. */
1161 #define LIMIT(x) ((x)>0xffffff?0xff: ((x)<=0xffff?0:((x)>>16)))
1162 
1163 static inline void
1164 ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, 
1165         int rowPixels, unsigned char * rgb, int bits)
1166 {
1167         const int rvScale = 91881;
1168         const int guScale = -22553;
1169         const int gvScale = -46801;
1170         const int buScale = 116129;
1171         const int yScale  = 65536;
1172         int r, g, b;
1173 
1174         g = guScale * u + gvScale * v;
1175         if (force_rgb) {
1176                 r = buScale * u;
1177                 b = rvScale * v;
1178         } else {
1179                 r = rvScale * v;
1180                 b = buScale * u;
1181         }
1182 
1183         yTL *= yScale; yTR *= yScale;
1184         yBL *= yScale; yBR *= yScale;
1185 
1186         if (bits == 24) {
1187                 /* Write out top two pixels */
1188                 rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL);
1189                 rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR);
1190 
1191                 /* Skip down to next line to write out bottom two pixels */
1192                 rgb += 3 * rowPixels;
1193                 rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL);
1194                 rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR);
1195         } else if (bits == 16) {
1196                 /* Write out top two pixels */
1197                 rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F) | ((LIMIT(g+yTL) << 3) & 0xE0);
1198                 rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07) | (LIMIT(r+yTL) & 0xF8);
1199 
1200                 rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F) | ((LIMIT(g+yTR) << 3) & 0xE0);
1201                 rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07) | (LIMIT(r+yTR) & 0xF8);
1202 
1203                 /* Skip down to next line to write out bottom two pixels */
1204                 rgb += 2 * rowPixels;
1205 
1206                 rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F) | ((LIMIT(g+yBL) << 3) & 0xE0);
1207                 rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07) | (LIMIT(r+yBL) & 0xF8);
1208 
1209                 rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F) | ((LIMIT(g+yBR) << 3) & 0xE0);
1210                 rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07) | (LIMIT(r+yBR) & 0xF8);
1211         }
1212 }
1213 
1214 /*
1215  * For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments.
1216  * The first 64 bytes of each segment are U, the next 64 are V.  The U and
1217  * V are arranged as follows:
1218  *
1219  *      0  1 ...  7
1220  *      8  9 ... 15
1221  *           ...   
1222  *     56 57 ... 63
1223  *
1224  * U and V are shipped at half resolution (1 U,V sample -> one 2x2 block).
1225  *
1226  * The next 256 bytes are full resolution Y data and represent 4 squares
1227  * of 8x8 pixels as follows:
1228  *
1229  *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
1230  *      8  9 ... 15    72  73 ...  79        200 201 ... 207
1231  *           ...              ...                    ...
1232  *     56 57 ... 63   120 121 ... 127   ...  248 249 ... 255
1233  *
1234  * Note that the U and V data in one segment represents a 16 x 16 pixel
1235  * area, but the Y data represents a 32 x 8 pixel area.
1236  *
1237  * If dumppix module param is set, _parse_data just dumps the incoming segments,
1238  * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480
1239  * this puts the data on the standard output and can be analyzed with the
1240  * parseppm.c utility I wrote.  That's a much faster way for figuring out how
1241  * this data is scrambled.
1242  */
1243 
1244 #define HDIV 8
1245 #define WDIV (256/HDIV)
1246 
1247 static void
1248 ov511_parse_gbr422_to_rgb24(unsigned char *pIn0, unsigned char *pOut0,
1249                        int iOutY, int iOutUV, int iHalf, int iWidth)
1250 {
1251         int k, l, m;
1252         unsigned char *pIn;
1253         unsigned char *pOut, *pOut1;
1254 
1255         pIn = pIn0;
1256         pOut = pOut0 + iOutUV + (force_rgb ? 2 : 0);
1257                 
1258         for (k = 0; k < 8; k++) {
1259                 pOut1 = pOut;
1260                 for (l = 0; l < 8; l++) {
1261                         *pOut1 = *(pOut1 + 3) = *(pOut1 + iWidth*3) =
1262                                 *(pOut1 + iWidth*3 + 3) = *pIn++;
1263                         pOut1 += 6;
1264                 }
1265                 pOut += iWidth*3*2;
1266         }
1267 
1268         pIn = pIn0 + 64;
1269         pOut = pOut0 + iOutUV + (force_rgb ? 0 : 2);
1270         for (k = 0; k < 8; k++) {
1271                 pOut1 = pOut;
1272                 for (l = 0; l < 8; l++) {
1273                         *pOut1 = *(pOut1 + 3) = *(pOut1 + iWidth*3) =
1274                                 *(pOut1 + iWidth*3 + 3) = *pIn++;
1275                         pOut1 += 6;
1276                 }
1277                 pOut += iWidth*3*2;
1278         }
1279 
1280         pIn = pIn0 + 128;
1281         pOut = pOut0 + iOutY + 1;
1282         for (k = 0; k < 4; k++) {
1283                 pOut1 = pOut;
1284                 for (l = 0; l < 8; l++) {
1285                         for (m = 0; m < 8; m++) {
1286                                 *pOut1 = *pIn++;
1287                                 pOut1 += 3;
1288                         }
1289                         pOut1 += (iWidth - 8) * 3;
1290                 }
1291                 pOut += 8 * 3;
1292         }
1293 }
1294 
1295 static void
1296 ov511_parse_yuv420_to_rgb(unsigned char *pIn0, unsigned char *pOut0,
1297                        int iOutY, int iOutUV, int iHalf, int iWidth, int bits)
1298 {
1299         int k, l, m;
1300         int bytes = bits >> 3;
1301         unsigned char *pIn;
1302         unsigned char *pOut, *pOut1;
1303 
1304         /* Just copy the Y's if in the first stripe */
1305         if (!iHalf) {
1306                 pIn = pIn0 + 128;
1307                 pOut = pOut0 + iOutY;
1308                 for (k = 0; k < 4; k++) {
1309                         pOut1 = pOut;
1310                         for (l = 0; l < 8; l++) {
1311                                 for (m = 0; m < 8; m++) {
1312                                         *pOut1 = *pIn++;
1313                                         pOut1 += bytes;
1314                                 }
1315                                 pOut1 += (iWidth - 8) * bytes;
1316                         }
1317                         pOut += 8 * bytes;
1318                 }
1319         }
1320 
1321         /* Use the first half of VUs to calculate value */
1322         pIn = pIn0;
1323         pOut = pOut0 + iOutUV;
1324         for (l = 0; l < 4; l++) {
1325                 for (m=0; m<8; m++) {
1326                         int y00 = *(pOut);
1327                         int y01 = *(pOut+bytes);
1328                         int y10 = *(pOut+iWidth*bytes);
1329                         int y11 = *(pOut+iWidth*bytes+bytes);
1330                         int v   = *(pIn+64) - 128;
1331                         int u   = *pIn++ - 128;
1332                         ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth,
1333                                 pOut, bits);
1334                         pOut += 2 * bytes;
1335                 }
1336                 pOut += (iWidth*2 - 16) * bytes;
1337         }
1338 
1339         /* Just copy the other UV rows */
1340         for (l = 0; l < 4; l++) {
1341                 for (m = 0; m < 8; m++) {
1342                         *pOut++ = *(pIn + 64);
1343                         *pOut = *pIn++;
1344                         pOut += 2 * bytes - 1;
1345                 }
1346                 pOut += (iWidth*2 - 16) * bytes;
1347         }
1348 
1349         /* Calculate values if it's the second half */
1350         if (iHalf) {
1351                 pIn = pIn0 + 128;
1352                 pOut = pOut0 + iOutY;
1353                 for (k = 0; k < 4; k++) {
1354                         pOut1 = pOut;
1355                         for (l=0; l<4; l++) {
1356                                 for (m=0; m<4; m++) {
1357                                         int y10 = *(pIn+8);
1358                                         int y00 = *pIn++;
1359                                         int y11 = *(pIn+8);
1360                                         int y01 = *pIn++;
1361                                         int v   = *pOut1 - 128;
1362                                         int u   = *(pOut1+1) - 128;
1363                                         ov511_move_420_block(y00, y01, y10,
1364                                                 y11, u, v, iWidth, pOut1, bits);
1365                                         pOut1 += 2 * bytes;
1366                                 }
1367                                 pOut1 += (iWidth*2 - 8) * bytes;
1368                                 pIn += 8;
1369                         }
1370                         pOut += 8 * bytes;
1371                 }
1372         }
1373 }
1374 
1375 static void
1376 ov511_dumppix(unsigned char *pIn0, unsigned char *pOut0,
1377               int iOutY, int iOutUV, int iHalf, int iWidth)
1378 {
1379         int i, j, k;
1380         unsigned char *pIn, *pOut, *pOut1;
1381 
1382         switch (dumppix) {
1383         case 1: /* Just dump YUV data straight out for debug */
1384                 pOut0 += iOutY;
1385                 for (i = 0; i < HDIV; i++) {
1386                         for (j = 0; j < WDIV; j++) {
1387                                 *pOut0++ = *pIn0++;
1388                                 *pOut0++ = *pIn0++;
1389                                 *pOut0++ = *pIn0++;
1390                         }
1391                         pOut0 += (iWidth - WDIV) * 3;
1392                 }
1393                 break;
1394         case 2: /* This converts the Y data to "black-and-white" RGB data */
1395                 /* Useful for experimenting with compression */
1396                 pIn = pIn0 + 128;
1397                 pOut = pOut0 + iOutY;
1398                 for (i = 0; i < 4; i++) {
1399                         pOut1 = pOut;
1400                         for (j = 0; j < 8; j++) {
1401                                 for (k = 0; k < 8; k++) {
1402                                         *pOut1++ = *pIn;
1403                                         *pOut1++ = *pIn;
1404                                         *pOut1++ = *pIn++;
1405                                 }
1406                                 pOut1 += (iWidth - 8) * 3;
1407                         }
1408                         pOut += 8 * 3;
1409                 }
1410                 break;
1411         case 3: /* This will dump only the Y channel data stream as-is */
1412                 pIn = pIn0 + 128;
1413                 pOut = pOut0 + output_offset;
1414                 for (i = 0; i < 256; i++) {
1415                         *pOut++ = *pIn;
1416                         *pOut++ = *pIn;
1417                         *pOut++ = *pIn++;
1418                         output_offset += 3;
1419                 }
1420                 break;
1421         } /* End switch (dumppix) */
1422 }
1423 
1424 /* This converts YUV420 segments to YUYV */
1425 static void
1426 ov511_parse_data_yuv422(unsigned char *pIn0, unsigned char *pOut0,
1427                         int iOutY, int iOutUV, int iWidth)
1428 {
1429         int k, l, m;
1430         unsigned char *pIn, *pOut, *pOut1;
1431 
1432         pIn = pIn0 + 128;
1433         pOut = pOut0 + iOutY;
1434         for (k = 0; k < 4; k++) {
1435                 pOut1 = pOut;
1436                 for (l = 0; l < 8; l++) {
1437                         for (m = 0; m < 8; m++) {
1438                                 *pOut1 = (*pIn++);
1439                                 pOut1 += 2;
1440                         }
1441                         pOut1 += (iWidth - 8) * 2;
1442                 }
1443                 pOut += 8 * 2;
1444         }
1445 
1446         pIn = pIn0;
1447         pOut = pOut0 + iOutUV + 1;
1448         for (l = 0; l < 8; l++) {
1449                 for (m=0; m<8; m++) {
1450                         int v   = *(pIn+64);
1451                         int u   = *pIn++;
1452                         
1453                         *pOut = u;
1454                         *(pOut+2) = v;
1455                         *(pOut+iWidth) = u;
1456                         *(pOut+iWidth+2) = v;
1457                         pOut += 4;
1458                 }
1459                 pOut += (iWidth*4 - 32);
1460         }
1461 }
1462 
1463 static void
1464 ov511_parse_data_yuv420(unsigned char *pIn0, unsigned char *pOut0,
1465                         int iOutY, int iOutUV, int iWidth, int iHeight)
1466 {
1467         int k, l, m;
1468         unsigned char *pIn;
1469         unsigned char *pOut, *pOut1;
1470         unsigned a = iWidth * iHeight;
1471         unsigned w = iWidth / 2;
1472 
1473         pIn = pIn0;
1474         pOut = pOut0 + iOutUV + a;
1475         for (k = 0; k < 8; k++) {
1476                 pOut1 = pOut;
1477                 for (l = 0; l < 8; l++) *pOut1++ = *pIn++;
1478                 pOut += w;
1479         }
1480 
1481         pIn = pIn0 + 64;
1482         pOut = pOut0 + iOutUV + a + a/4;
1483         for (k = 0; k < 8; k++) {
1484                 pOut1 = pOut;
1485                 for (l = 0; l < 8; l++) *pOut1++ = *pIn++;
1486                 pOut += w;
1487         }
1488 
1489         pIn = pIn0 + 128;
1490         pOut = pOut0 + iOutY;
1491         for (k = 0; k < 4; k++) {
1492                 pOut1 = pOut;
1493                 for (l = 0; l < 8; l++) {
1494                         for (m = 0; m < 8; m++)
1495                                 *pOut1++ =*pIn++;
1496                         pOut1 += iWidth - 8;
1497                 }
1498                 pOut += 8;
1499         }
1500 }
1501 
1502 static void
1503 ov511_parse_data_yuv422p(unsigned char *pIn0, unsigned char *pOut0,
1504                        int iOutY, int iOutUV, int iWidth, int iHeight)
1505 {
1506         int k, l, m;
1507         unsigned char *pIn;
1508         unsigned char *pOut, *pOut1;
1509         unsigned a = iWidth * iHeight;
1510         unsigned w = iWidth / 2;
1511 
1512         pIn = pIn0;
1513         pOut = pOut0 + iOutUV + a;
1514         for (k = 0; k < 8; k++) {
1515                 pOut1 = pOut;
1516                 for (l = 0; l < 8; l++) {
1517                         *pOut1 = *(pOut1 + w) = *pIn++;
1518                         pOut1++;
1519                 }
1520                 pOut += iWidth;
1521         }
1522 
1523         pIn = pIn0 + 64;
1524         pOut = pOut0 + iOutUV + a + a/2;
1525         for (k = 0; k < 8; k++) {
1526                 pOut1 = pOut;
1527                 for (l = 0; l < 8; l++) {
1528                         *pOut1 = *(pOut1 + w) = *pIn++;
1529                         pOut1++;
1530                 }
1531                 pOut += iWidth;
1532         }
1533 
1534         pIn = pIn0 + 128;
1535         pOut = pOut0 + iOutY;
1536         for (k = 0; k < 4; k++) {
1537                 pOut1 = pOut;
1538                 for (l = 0; l < 8; l++) {
1539                         for (m = 0; m < 8; m++)
1540                                 *pOut1++ =*pIn++;
1541                         pOut1 += iWidth - 8;
1542                 }
1543                 pOut += 8;
1544         }
1545 }
1546 
1547 /*
1548  * For 640x480 RAW BW images, data shows up in 1200 256 byte segments.
1549  * The segments represent 4 squares of 8x8 pixels as follows:
1550  *
1551  *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
1552  *      8  9 ... 15    72  73 ...  79        200 201 ... 207
1553  *           ...              ...                    ...
1554  *     56 57 ... 63   120 121 ... 127        248 249 ... 255
1555  *
1556  */ 
1557 static void
1558 ov511_parse_data_grey(unsigned char *pIn0, unsigned char *pOut0,
1559                       int iOutY, int iWidth)                
1560 {
1561         int k, l, m;
1562         unsigned char *pIn;
1563         unsigned char *pOut, *pOut1;
1564 
1565         pIn = pIn0;
1566         pOut = pOut0 + iOutY;
1567         for (k = 0; k < 4; k++) {
1568                 pOut1 = pOut;
1569                 for (l = 0; l < 8; l++) {
1570                         for (m = 0; m < 8; m++) {
1571                                 *pOut1++ = *pIn++;
1572                         }
1573                         pOut1 += iWidth - 8;
1574                 }
1575                 pOut += 8;
1576         }
1577 }
1578 
1579 /*
1580  * fixFrameRGBoffset--
1581  * My camera seems to return the red channel about 1 pixel
1582  * low, and the blue channel about 1 pixel high. After YUV->RGB
1583  * conversion, we can correct this easily. OSL 2/24/2000.
1584  */
1585 static void fixFrameRGBoffset(struct ov511_frame *frame)
1586 {
1587         int x, y;
1588         int rowBytes = frame->width*3, w = frame->width;
1589         unsigned char *rgb = frame->data;
1590         const int shift = 1;  /* Distance to shift pixels by, vertically */
1591 
1592         /* Don't bother with little images */
1593         if (frame->width < 400) 
1594                 return;
1595 
1596         /* Shift red channel up */
1597         for (y = shift; y < frame->height; y++) {
1598                 int lp = (y-shift)*rowBytes;     /* Previous line offset */
1599                 int lc = y*rowBytes;             /* Current line offset */
1600                 for (x = 0; x < w; x++)
1601                         rgb[lp+x*3+2] = rgb[lc+x*3+2]; /* Shift red up */
1602         }
1603 
1604         /* Shift blue channel down */
1605         for (y = frame->height-shift-1; y >= 0; y--) {
1606                 int ln = (y + shift) * rowBytes;  /* Next line offset */
1607                 int lc = y * rowBytes;            /* Current line offset */
1608                 for (x = 0; x < w; x++)
1609                         rgb[ln+x*3+0] = rgb[lc+x*3+0]; /* Shift blue down */
1610         }
1611 }
1612 
1613 /**********************************************************************
1614  *
1615  * OV511 data transfer, IRQ handler
1616  *
1617  **********************************************************************/
1618 
1619 static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
1620 {
1621         unsigned char *cdata;
1622         int i, totlen = 0;
1623         int aPackNum[10];
1624         struct ov511_frame *frame;
1625         unsigned char *pData;
1626         int iPix;
1627 
1628         PDEBUG (4, "Moving %d packets", urb->number_of_packets);
1629 
1630         for (i = 0; i < urb->number_of_packets; i++) {
1631                 int n = urb->iso_frame_desc[i].actual_length;
1632                 int st = urb->iso_frame_desc[i].status;
1633 
1634                 urb->iso_frame_desc[i].actual_length = 0;
1635                 urb->iso_frame_desc[i].status = 0;
1636 
1637                 cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
1638 
1639                 aPackNum[i] = n ? cdata[ov511->packet_size - 1] : -1;
1640 
1641                 if (!n || ov511->curframe == -1)
1642                         continue;
1643 
1644                 if (st)
1645                         PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st);
1646 
1647                 frame = &ov511->frame[ov511->curframe];
1648                 
1649                 /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
1650                  * byte non-zero. The EOF packet has image width/height in the
1651                  * 10th and 11th packets. The 9th bit is given as follows:
1652                  *
1653                  * bit 7: EOF
1654                  *     6: compression enabled
1655                  *     5: 422/420/400 modes
1656                  *     4: 422/420/400 modes
1657                  *     3: 1
1658                  *     2: snapshot bottom on
1659                  *     1: snapshot frame
1660                  *     0: even/odd field
1661                  */
1662 
1663                 /* Check for SOF/EOF packet */
1664                 if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | 
1665                      cdata[4] | cdata[5] | cdata[6] | cdata[7]) ||
1666                      (~cdata[8] & 0x08))
1667                         goto check_middle;
1668 
1669                 /* Frame end */
1670                 if (cdata[8] & 0x80) {
1671                         struct timeval *ts;
1672 
1673                         ts = (struct timeval *)(frame->data + MAX_FRAME_SIZE);
1674                         do_gettimeofday (ts);
1675 
1676                         PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d",
1677                                 ov511->curframe, (int)(cdata[ov511->packet_size - 1]),
1678                                 (int)(cdata[9]), (int)(cdata[10]));
1679 
1680                         if (frame->scanstate == STATE_LINES) {
1681                                 int iFrameNext;
1682 
1683                                 if (fix_rgb_offset)
1684                                         fixFrameRGBoffset(frame);
1685                                 frame->grabstate = FRAME_DONE;
1686 
1687                                 if (waitqueue_active(&frame->wq)) {
1688                                         frame->grabstate = FRAME_DONE;
1689                                         wake_up_interruptible(&frame->wq);
1690                                 }
1691 
1692                                 /* If next frame is ready or grabbing,
1693                                  * point to it */
1694                                 iFrameNext = (ov511->curframe + 1) % OV511_NUMFRAMES;
1695                                 if (ov511->frame[iFrameNext].grabstate == FRAME_READY
1696                                     || ov511->frame[iFrameNext].grabstate == FRAME_GRABBING) {
1697                                         ov511->curframe = iFrameNext;
1698                                         ov511->frame[iFrameNext].scanstate = STATE_SCANNING;
1699                                 } else {
1700                                         if (frame->grabstate == FRAME_DONE) {
1701                                                 PDEBUG(4, "Frame done! congratulations");
1702                                         } else {
1703                                                 PDEBUG(4, "Frame not ready? state = %d",
1704                                                         ov511->frame[iFrameNext].grabstate);
1705                                         }
1706 
1707                                         ov511->curframe = -1;
1708                                 }
1709                         }
1710                         /* Image corruption caused by misplaced frame->segment = 0
1711                          * fixed by carlosf@conectiva.com.br
1712                          */
1713                 } else {
1714                         /* Frame start */
1715                         PDEBUG(4, "Frame start, framenum = %d", ov511->curframe);
1716 
1717 #if 0
1718                         /* Make sure no previous data carries over; necessary
1719                          * for compression experimentation */
1720                         memset(frame->data, 0, MAX_DATA_SIZE);
1721 #endif
1722                         output_offset = 0;
1723 
1724                         /* Check to see if it's a snapshot frame */
1725                         /* FIXME?? Should the snapshot reset go here? Performance? */
1726                         if (cdata[8] & 0x02) {
1727                                 frame->snapshot = 1;
1728                                 PDEBUG(3, "snapshot detected");
1729                         }
1730 
1731                         frame->scanstate = STATE_LINES;
1732                         frame->segment = 0;
1733                 }
1734 
1735 check_middle:
1736                 /* Are we in a frame? */
1737                 if (frame->scanstate != STATE_LINES)
1738                         continue;
1739 
1740                 /* Deal with leftover from last segment, if any */
1741                 if (frame->segment) {
1742                         pData = ov511->scratch;
1743                         iPix = -ov511->scratchlen;
1744                         memmove(pData + ov511->scratchlen, cdata,
1745                                 iPix+frame->segsize);
1746                 } else {
1747                         pData = &cdata[iPix = 9];
1748                 }
1749 
1750                 /* Parse the segments */
1751                 while (iPix <= (ov511->packet_size - 1) - frame->segsize &&
1752                     frame->segment < frame->width * frame->height / 256) {
1753                         int iSegY, iSegUV;
1754                         int iY, jY, iUV, jUV;
1755                         int iOutY, iOutYP, iOutUV, iOutUVP;
1756                         unsigned char *pOut;
1757 
1758                         iSegY = iSegUV = frame->segment;
1759                         pOut = frame->data;
1760                         frame->segment++;
1761                         iPix += frame->segsize;
1762 
1763                         /* Handle subwindow */
1764                         if (frame->sub_flag) {
1765                                 int iSeg1;
1766 
1767                                 iSeg1 = iSegY / (ov511->subw / 32);
1768                                 iSeg1 *= frame->width / 32;
1769                                 iSegY = iSeg1 + (iSegY % (ov511->subw / 32));
1770                                 if (iSegY >= frame->width * ov511->subh / 256)
1771                                         break;
1772 
1773                                 iSeg1 = iSegUV / (ov511->subw / 16);
1774                                 iSeg1 *= frame->width / 16;
1775                                 iSegUV = iSeg1 + (iSegUV % (ov511->subw / 16));
1776 
1777                                 pOut += (ov511->subx + ov511->suby * frame->width) *
1778                                         (frame->depth >> 3);
1779                         }
1780 
1781                         /* 
1782                          * i counts segment lines
1783                          * j counts segment columns
1784                          * iOut is the offset (in bytes) of the upper left corner
1785                          */
1786                         iY = iSegY / (frame->width / WDIV);
1787                         jY = iSegY - iY * (frame->width / WDIV);
1788                         iOutYP = iY*HDIV*frame->width + jY*WDIV;
1789                         iOutY = iOutYP * (frame->depth >> 3);
1790                         iUV = iSegUV / (frame->width / WDIV * 2);
1791                         jUV = iSegUV - iUV * (frame->width / WDIV * 2);
1792                         iOutUVP = iUV*HDIV*2*frame->width + jUV*WDIV/2;
1793                         iOutUV = iOutUVP * (frame->depth >> 3);
1794 
1795                         switch (frame->format) {
1796                         case VIDEO_PALETTE_GREY:
1797                                 ov511_parse_data_grey (pData, pOut, iOutY, frame->width);
1798                                 break;
1799                         case VIDEO_PALETTE_RGB24:
1800                                 if (dumppix)
1801                                         ov511_dumppix(pData, pOut, iOutY, iOutUV,
1802                                                 iY & 1, frame->width);
1803                                 else if (sensor_gbr)
1804                                         ov511_parse_gbr422_to_rgb24(pData, pOut, iOutY, iOutUV,
1805                                                 iY & 1, frame->width);
1806                                 else
1807                                         ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV,
1808                                                 iY & 1, frame->width, 24);
1809                                 break;
1810                         case VIDEO_PALETTE_RGB565:
1811                                 ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV,
1812                                         iY & 1, frame->width, 16);
1813                                 break;
1814                         case VIDEO_PALETTE_YUV422:
1815                         case VIDEO_PALETTE_YUYV:
1816                                 ov511_parse_data_yuv422(pData, pOut, iOutY, iOutUV, frame->width);
1817                                 break;
1818                         case VIDEO_PALETTE_YUV420:
1819                                 ov511_parse_data_yuv420 (pData, pOut, iOutYP, iUV*HDIV*frame->width/2 + jUV*WDIV/4,
1820                                         frame->width, frame->height);
1821                                 break;
1822                         case VIDEO_PALETTE_YUV422P:
1823                                 ov511_parse_data_yuv422p (pData, pOut, iOutYP, iOutUVP/2,
1824                                         frame->width, frame->height);
1825                                 break;
1826                         default:
1827                                 err("Unsupported format: %d", frame->format);
1828                         }
1829 
1830                         pData = &cdata[iPix];
1831                 }
1832 
1833                 /* Save extra data for next time */
1834                 if (frame->segment < frame->width * frame->height / 256) {
1835                         ov511->scratchlen = (ov511->packet_size - 1) - iPix;
1836                         if (ov511->scratchlen < frame->segsize)
1837                                 memmove(ov511->scratch, pData, ov511->scratchlen);
1838                         else
1839                                 ov511->scratchlen = 0;
1840                 }
1841         }
1842 
1843         PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d",
1844                aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],
1845                aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);
1846 
1847         return totlen;
1848 }
1849 
1850 static void ov511_isoc_irq(struct urb *urb)
1851 {
1852         int len;
1853         struct usb_ov511 *ov511;
1854         struct ov511_sbuf *sbuf;
1855 
1856         if (!urb->context) {
1857                 PDEBUG(4, "no context");
1858                 return;
1859         }
1860 
1861         ov511 = (struct usb_ov511 *) urb->context;
1862 
1863         if (!ov511->dev || !ov511->user) {
1864                 PDEBUG(4, "no device, or not open");
1865                 return;
1866         }
1867 
1868         if (!ov511->streaming) {
1869                 PDEBUG(4, "hmmm... not streaming, but got interrupt");
1870                 return;
1871         }
1872         
1873         sbuf = &ov511->sbuf[ov511->cursbuf];
1874 
1875         /* Copy the data received into our scratch buffer */
1876         if (ov511->curframe >= 0) {
1877                 len = ov511_move_data(ov511, urb);
1878         } else if (waitqueue_active(&ov511->wq)) {
1879                 wake_up_interruptible(&ov511->wq);
1880         }
1881 
1882         /* Move to the next sbuf */
1883         ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF;
1884 
1885         urb->dev = ov511->dev;
1886 
1887         return;
1888 }
1889 
1890 static int ov511_init_isoc(struct usb_ov511 *ov511)
1891 {
1892         urb_t *urb;
1893         int fx, err, n, size;
1894 
1895         PDEBUG(3, "*** Initializing capture ***");
1896 
1897         ov511->compress = 0;
1898         ov511->curframe = -1;
1899         ov511->cursbuf = 0;
1900         ov511->scratchlen = 0;
1901 
1902         if (ov511->bridge == BRG_OV511)
1903                 if (cams == 1)                   size = 993;
1904                 else if (cams == 2)              size = 513;
1905                 else if (cams == 3 || cams == 4) size = 257;
1906                 else {
1907                         err("\"cams\" parameter too high!");
1908                         return -1;
1909                 }
1910         else if (ov511->bridge == BRG_OV511PLUS)
1911                 if (cams == 1)                      size = 961;
1912                 else if (cams == 2)                 size = 513;
1913                 else if (cams == 3 || cams == 4) size = 257;
1914                 else if (cams >= 5 && cams <= 8)    size = 129;
1915                 else if (cams >= 9 && cams <= 31)   size = 33;
1916                 else {
1917                         err("\"cams\" parameter too high!");
1918                         return -1;
1919                 }
1920         else {
1921                 err("invalid bridge type");
1922                 return -1;
1923         }
1924 
1925         ov511_set_packet_size(ov511, size);
1926 
1927         for (n = 0; n < OV511_NUMSBUF; n++) {
1928                 urb = usb_alloc_urb(FRAMES_PER_DESC);
1929         
1930                 if (!urb) {
1931                         err("init isoc: usb_alloc_urb ret. NULL");
1932                         return -ENOMEM;
1933                 }
1934                 ov511->sbuf[n].urb = urb;
1935                 urb->dev = ov511->dev;
1936                 urb->context = ov511;
1937                 urb->pipe = usb_rcvisocpipe(ov511->dev, OV511_ENDPOINT_ADDRESS);
1938                 urb->transfer_flags = USB_ISO_ASAP;
1939                 urb->transfer_buffer = ov511->sbuf[n].data;
1940                 urb->complete = ov511_isoc_irq;
1941                 urb->number_of_packets = FRAMES_PER_DESC;
1942                 urb->transfer_buffer_length = ov511->packet_size * FRAMES_PER_DESC;
1943                 for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
1944                         urb->iso_frame_desc[fx].offset = ov511->packet_size * fx;
1945                         urb->iso_frame_desc[fx].length = ov511->packet_size;
1946                 }
1947         }
1948 
1949         ov511->sbuf[OV511_NUMSBUF - 1].urb->next = ov511->sbuf[0].urb;
1950         for (n = 0; n < OV511_NUMSBUF - 1; n++)
1951                 ov511->sbuf[n].urb->next = ov511->sbuf[n+1].urb;
1952 
1953         for (n = 0; n < OV511_NUMSBUF; n++) {
1954                 ov511->sbuf[n].urb->dev = ov511->dev;
1955                 err = usb_submit_urb(ov511->sbuf[n].urb);
1956                 if (err)
1957                         err("init isoc: usb_submit_urb(%d) ret %d", n, err);
1958         }
1959 
1960         ov511->streaming = 1;
1961 
1962         return 0;
1963 }
1964 
1965 static void ov511_stop_isoc(struct usb_ov511 *ov511)
1966 {
1967         int n;
1968 
1969         if (!ov511->streaming || !ov511->dev)
1970                 return;
1971 
1972         PDEBUG (3, "*** Stopping capture ***");
1973 
1974         ov511_set_packet_size(ov511, 0);
1975 
1976         ov511->streaming = 0;
1977 
1978         /* Unschedule all of the iso td's */
1979         for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
1980                 if (ov511->sbuf[n].urb) {
1981                         ov511->sbuf[n].urb->next = NULL;
1982                         usb_unlink_urb(ov511->sbuf[n].urb);
1983                         usb_free_urb(ov511->sbuf[n].urb);
1984                         ov511->sbuf[n].urb = NULL;
1985                 }
1986         }
1987 }
1988 
1989 static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
1990 {
1991         struct ov511_frame *frame;
1992 
1993         PDEBUG(4, "ov511->curframe = %d, framenum = %d", ov511->curframe,
1994                 framenum);
1995         if (!ov511->dev)
1996                 return -1;
1997 
1998         /* If we're not grabbing a frame right now and the other frame is */
1999         /* ready to be grabbed into, then use it instead */
2000         if (ov511->curframe == -1) {
2001                 if (ov511->frame[(framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES].grabstate == FRAME_READY)
2002                         framenum = (framenum - 1 + OV511_NUMFRAMES) % OV511_NUMFRAMES;
2003         } else
2004                 return 0;
2005 
2006         frame = &ov511->frame[framenum];
2007 
2008         PDEBUG (4, "framenum = %d, width = %d, height = %d", framenum, 
2009                 frame->width, frame->height);
2010 
2011         frame->grabstate = FRAME_GRABBING;
2012         frame->scanstate = STATE_SCANNING;
2013         frame->scanlength = 0;          /* accumulated in ov511_parse_data() */
2014         frame->snapshot = 0;
2015 
2016         ov511->curframe = framenum;
2017 
2018         /* Make sure it's not too big */
2019         if (frame->width > ov511->maxwidth)
2020                 frame->width = ov511->maxwidth;
2021 
2022         frame->width &= ~7L;            /* Multiple of 8 */
2023 
2024         if (frame->height > ov511->maxheight)
2025                 frame->height = ov511->maxheight;
2026 
2027         frame->height &= ~3L;           /* Multiple of 4 */
2028 
2029         return 0;
2030 }
2031 
2032 /****************************************************************************
2033  *
2034  * Buffer management
2035  *
2036  ***************************************************************************/
2037 static int ov511_alloc(struct usb_ov511 *ov511)
2038 {
2039         int i;
2040 
2041         PDEBUG(4, "entered");
2042         down(&ov511->buf_lock);
2043 
2044         if (ov511->buf_state == BUF_PEND_DEALLOC) {
2045                 ov511->buf_state = BUF_ALLOCATED;
2046                 del_timer(&ov511->buf_timer);
2047         }
2048 
2049         if (ov511->buf_state == BUF_ALLOCATED)
2050                 goto out;
2051 
2052         ov511->fbuf = rvmalloc(OV511_NUMFRAMES * MAX_DATA_SIZE);
2053         if (!ov511->fbuf)
2054                 goto error;
2055 
2056         for (i = 0; i < OV511_NUMFRAMES; i++) {
2057                 ov511->frame[i].grabstate = FRAME_UNUSED;
2058                 ov511->frame[i].data = ov511->fbuf + i * MAX_DATA_SIZE;
2059                 PDEBUG(4, "frame[%d] @ %p", i, ov511->frame[i].data);
2060 
2061                 ov511->sbuf[i].data = kmalloc(FRAMES_PER_DESC *
2062                         MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
2063                 if (!ov511->sbuf[i].data) {
2064                         while (--i) {
2065                                 kfree(ov511->sbuf[i].data);
2066                                 ov511->sbuf[i].data = NULL;
2067                         }
2068                         rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE);
2069                         ov511->fbuf = NULL;
2070                         goto error;
2071                 }
2072                 PDEBUG(4, "sbuf[%d] @ %p", i, ov511->sbuf[i].data);
2073         }
2074         ov511->buf_state = BUF_ALLOCATED;
2075 out:
2076         up(&ov511->buf_lock);
2077         PDEBUG(4, "leaving");
2078         return 0;
2079 error:
2080         ov511->buf_state = BUF_NOT_ALLOCATED;
2081         up(&ov511->buf_lock);
2082         PDEBUG(4, "errored");
2083         return -ENOMEM;
2084 }
2085 
2086 /* 
2087  * - You must acquire buf_lock before entering this function.
2088  * - Because this code will free any non-null pointer, you must be sure to null
2089  *   them if you explicitly free them somewhere else!
2090  */
2091 static void ov511_do_dealloc(struct usb_ov511 *ov511)
2092 {
2093         int i;
2094         PDEBUG(4, "entered");
2095 
2096         if (ov511->fbuf) {
2097                 rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE);
2098                 ov511->fbuf = NULL;
2099         }
2100 
2101         for (i = 0; i < OV511_NUMFRAMES; i++) {
2102                 if (ov511->sbuf[i].data) {
2103                         kfree(ov511->sbuf[i].data);
2104                         ov511->sbuf[i].data = NULL;
2105                 }
2106         }
2107 
2108         PDEBUG(4, "buffer memory deallocated");
2109         ov511->buf_state = BUF_NOT_ALLOCATED;
2110         PDEBUG(4, "leaving");
2111 }
2112 
2113 static void ov511_buf_callback(unsigned long data)
2114 {
2115         struct usb_ov511 *ov511 = (struct usb_ov511 *)data;
2116         PDEBUG(4, "entered");
2117         down(&ov511->buf_lock);
2118 
2119         if (ov511->buf_state == BUF_PEND_DEALLOC)
2120                 ov511_do_dealloc(ov511);
2121 
2122         up(&ov511->buf_lock);
2123         PDEBUG(4, "leaving");
2124 }
2125 
2126 static void ov511_dealloc(struct usb_ov511 *ov511, int now)
2127 {
2128         struct timer_list *bt = &(ov511->buf_timer);
2129         PDEBUG(4, "entered");
2130         down(&ov511->buf_lock);
2131 
2132         PDEBUG(4, "deallocating buffer memory %s", now ? "now" : "later");
2133 
2134         if (ov511->buf_state == BUF_PEND_DEALLOC) {
2135                 ov511->buf_state = BUF_ALLOCATED;
2136                 del_timer(bt);
2137         }
2138 
2139         if (now)
2140                 ov511_do_dealloc(ov511);
2141         else {
2142                 ov511->buf_state = BUF_PEND_DEALLOC;
2143                 init_timer(bt);
2144                 bt->function = ov511_buf_callback;
2145                 bt->data = (unsigned long)ov511;
2146                 bt->expires = jiffies + buf_timeout * HZ;
2147                 add_timer(bt);
2148         }
2149         up(&ov511->buf_lock);
2150         PDEBUG(4, "leaving");
2151 }
2152 
2153 /****************************************************************************
2154  *
2155  * V4L API
2156  *
2157  ***************************************************************************/
2158 
2159 static int ov511_open(struct video_device *dev, int flags)
2160 {
2161         struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
2162         int err;
2163 
2164         MOD_INC_USE_COUNT;
2165         PDEBUG(4, "opening");
2166         down(&ov511->lock);
2167 
2168         err = -EBUSY;
2169         if (ov511->user) 
2170                 goto out;
2171 
2172         err = -ENOMEM;
2173         if (ov511_alloc(ov511))
2174                 goto out;
2175 
2176         ov511->sub_flag = 0;
2177 
2178         err = ov511_init_isoc(ov511);
2179         if (err) {
2180                 ov511_dealloc(ov511, 0);
2181                 goto out;
2182         }
2183 
2184         ov511->user++;
2185 
2186 out:
2187         up(&ov511->lock);
2188 
2189         if (err)
2190                 MOD_DEC_USE_COUNT;
2191 
2192         return err;
2193 }
2194 
2195 static void ov511_close(struct video_device *dev)
2196 {
2197         struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
2198 
2199         PDEBUG(4, "ov511_close");
2200         
2201         down(&ov511->lock);
2202 
2203         ov511->user--;
2204         ov511_stop_isoc(ov511);
2205 
2206         if (ov511->dev)
2207                 ov511_dealloc(ov511, 0);
2208 
2209         up(&ov511->lock);
2210 
2211         if (!ov511->dev) {
2212                 ov511_dealloc(ov511, 1);
2213                 video_unregister_device(&ov511->vdev);
2214                 kfree(ov511);
2215                 ov511 = NULL;
2216         }
2217 
2218         MOD_DEC_USE_COUNT;
2219 }
2220 
2221 static int ov511_init_done(struct video_device *dev)
2222 {
2223 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
2224         create_proc_ov511_cam((struct usb_ov511 *)dev);
2225 #endif
2226 
2227         return 0;
2228 }
2229 
2230 static long ov511_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
2231 {
2232         return -EINVAL;
2233 }
2234 
2235 static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
2236 {
2237         struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
2238 
2239         PDEBUG(4, "IOCtl: 0x%X", cmd);
2240 
2241         if (!ov511->dev)
2242                 return -EIO;    
2243 
2244         switch (cmd) {
2245         case VIDIOCGCAP:
2246         {
2247                 struct video_capability b;
2248 
2249                 PDEBUG (4, "VIDIOCGCAP");
2250 
2251                 strcpy(b.name, "OV511 USB Camera");
2252                 b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
2253                 b.channels = 1;
2254                 b.audios = 0;
2255                 b.maxwidth = ov511->maxwidth;
2256                 b.maxheight = ov511->maxheight;
2257                 b.minwidth = 160;
2258                 b.minheight = 120;
2259 
2260                 if (copy_to_user(arg, &b, sizeof(b)))
2261                         return -EFAULT;
2262                                 
2263                 return 0;
2264         }
2265         case VIDIOCGCHAN:
2266         {
2267                 struct video_channel v;
2268 
2269                 if (copy_from_user(&v, arg, sizeof(v)))
2270                         return -EFAULT;
2271                 if (v.channel != 0)
2272                         return -EINVAL;
2273 
2274                 v.flags = 0;
2275                 v.tuners = 0;
2276                 v.type = VIDEO_TYPE_CAMERA;
2277                 strcpy(v.name, "Camera");
2278 
2279                 if (copy_to_user(arg, &v, sizeof(v)))
2280                         return -EFAULT;
2281                                 
2282                 return 0;
2283         }
2284         case VIDIOCSCHAN:
2285         {
2286                 int v;
2287 
2288                 if (copy_from_user(&v, arg, sizeof(v)))
2289                         return -EFAULT;
2290 
2291                 if (v != 0)
2292                         return -EINVAL;
2293 
2294                 return 0;
2295         }
2296         case VIDIOCGPICT:
2297         {
2298                 struct video_picture p;
2299 
2300                 PDEBUG (4, "VIDIOCGPICT");
2301 
2302                 if (ov7610_get_picture(ov511, &p))
2303                         return -EIO;
2304                                                         
2305                 if (copy_to_user(arg, &p, sizeof(p)))
2306                         return -EFAULT;
2307 
2308                 return 0;
2309         }
2310         case VIDIOCSPICT:
2311         {
2312                 struct video_picture p;
2313                 int i;
2314 
2315                 PDEBUG (4, "VIDIOCSPICT");
2316 
2317                 if (copy_from_user(&p, arg, sizeof(p)))
2318                         return -EFAULT;
2319 
2320                 if (!ov511_get_depth(p.palette))
2321                         return -EINVAL;
2322                         
2323                 if (ov7610_set_picture(ov511, &p))
2324                         return -EIO;
2325 
2326                 PDEBUG(4, "Setting depth=%d, palette=%d", p.depth, p.palette);
2327                 for (i = 0; i < OV511_NUMFRAMES; i++) {
2328                         ov511->frame[i].depth = p.depth;
2329                         ov511->frame[i].format = p.palette;
2330                         ov511->frame[i].segsize = GET_SEGSIZE(p.palette);
2331                 }
2332 
2333                 return 0;
2334         }
2335         case VIDIOCGCAPTURE:
2336         {
2337                 int vf;
2338 
2339                 PDEBUG (4, "VIDIOCGCAPTURE");
2340 
2341                 if (copy_from_user(&vf, arg, sizeof(vf)))
2342                         return -EFAULT;
2343                 ov511->sub_flag = vf;
2344                 return 0;
2345         }
2346         case VIDIOCSCAPTURE:
2347         {
2348                 struct video_capture vc;
2349 
2350                 if (copy_from_user(&vc, arg, sizeof(vc)))
2351                         return -EFAULT;
2352                 if (vc.flags)
2353                         return -EINVAL;
2354                 if (vc.decimation)
2355                         return -EINVAL;
2356 
2357                 vc.x &= ~3L;
2358                 vc.y &= ~1L;
2359                 vc.y &= ~31L;
2360 
2361                 if (vc.width == 0)
2362                         vc.width = 32;
2363 
2364                 vc.height /= 16;
2365                 vc.height *= 16;
2366                 if (vc.height == 0)
2367                         vc.height = 16;
2368 
2369                 ov511->subx = vc.x;
2370                 ov511->suby = vc.y;
2371                 ov511->subw = vc.width;
2372                 ov511->subh = vc.height;
2373 
2374                 return 0;
2375         }
2376         case VIDIOCSWIN:
2377         {
2378                 struct video_window vw;
2379                 int i, result;
2380 
2381                 if (copy_from_user(&vw, arg, sizeof(vw)))
2382                         return -EFAULT;
2383 
2384                 PDEBUG (4, "VIDIOCSWIN: width=%d, height=%d",
2385                         vw.width, vw.height);
2386 
2387 #if 0
2388                 if (vw.flags)
2389                         return -EINVAL;
2390                 if (vw.clipcount)
2391                         return -EINVAL;
2392                 if (vw.height != ov511->maxheight)
2393                         return -EINVAL;
2394                 if (vw.width != ov511->maxwidth)
2395                         return -EINVAL;
2396 #endif
2397 
2398                 /* If we're collecting previous frame wait
2399                    before changing modes */
2400                 interruptible_sleep_on(&ov511->wq);
2401                 if (signal_pending(current)) return -EINTR;
2402 
2403                 result = ov511_mode_init_regs(ov511, vw.width, vw.height,
2404                         ov511->frame[0].format, ov511->sub_flag);
2405                 if (result < 0)
2406                         return result;
2407 
2408                 for (i = 0; i < OV511_NUMFRAMES; i++) {
2409                         ov511->frame[i].width = vw.width;
2410                         ov511->frame[i].height = vw.height;
2411                 }
2412 
2413                 return 0;
2414         }
2415         case VIDIOCGWIN:
2416         {
2417                 struct video_window vw;
2418 
2419                 vw.x = 0;               /* FIXME */
2420                 vw.y = 0;
2421                 vw.width = ov511->frame[0].width;
2422                 vw.height = ov511->frame[0].height;
2423                 vw.chromakey = 0;
2424                 vw.flags = 30;
2425 
2426                 PDEBUG (4, "VIDIOCGWIN: %dx%d", vw.width, vw.height);
2427 
2428                 if (copy_to_user(arg, &vw, sizeof(vw)))
2429                         return -EFAULT;
2430 
2431                 return 0;
2432         }
2433         case VIDIOCGMBUF:
2434         {
2435                 struct video_mbuf vm;
2436 
2437                 memset(&vm, 0, sizeof(vm));
2438                 vm.size = OV511_NUMFRAMES * MAX_DATA_SIZE;
2439                 vm.frames = OV511_NUMFRAMES;
2440                 vm.offsets[0] = 0;
2441                 vm.offsets[1] = MAX_FRAME_SIZE + sizeof (struct timeval);
2442 
2443                 if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
2444                         return -EFAULT;
2445 
2446                 return 0;
2447         }
2448         case VIDIOCMCAPTURE:
2449         {
2450                 struct video_mmap vm;
2451                 int ret, depth;
2452 
2453                 if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
2454                         return -EFAULT;
2455 
2456                 PDEBUG(4, "CMCAPTURE");
2457                 PDEBUG(4, "frame: %d, size: %dx%d, format: %d",
2458                         vm.frame, vm.width, vm.height, vm.format);
2459 
2460                 depth = ov511_get_depth(vm.format);
2461                 if (!depth) {
2462                         err("VIDIOCMCAPTURE: invalid format (%d)", vm.format);
2463                         return -EINVAL;
2464                 }
2465 
2466                 if ((vm.frame != 0) && (vm.frame != 1)) {
2467                         err("VIDIOCMCAPTURE: invalid frame (%d)", vm.frame);
2468                         return -EINVAL;
2469                 }
2470 
2471                 if (vm.width > ov511->maxwidth || vm.height > ov511->maxheight) {
2472                         err("VIDIOCMCAPTURE: requested dimensions too big");
2473                         return -EINVAL;
2474                 }
2475 
2476                 if (ov511->frame[vm.frame].grabstate == FRAME_GRABBING)
2477                         return -EBUSY;
2478 
2479                 /* Don't compress if the size changed */
2480                 if ((ov511->frame[vm.frame].width != vm.width) ||
2481                     (ov511->frame[vm.frame].height != vm.height) ||
2482                     (ov511->frame[vm.frame].format != vm.format) ||
2483                     (ov511->frame[vm.frame].sub_flag !=
2484                      ov511->sub_flag)) {
2485                         /* If we're collecting previous frame wait
2486                            before changing modes */
2487                         interruptible_sleep_on(&ov511->wq);
2488                         if (signal_pending(current)) return -EINTR;
2489                         ret = ov511_mode_init_regs(ov511, vm.width, vm.height,
2490                                 vm.format, ov511->sub_flag);
2491 #if 0
2492                         if (ret < 0)
2493                                 return ret;
2494 #endif
2495                 }
2496 
2497                 ov511->frame[vm.frame].width = vm.width;
2498                 ov511->frame[vm.frame].height = vm.height;
2499                 ov511->frame[vm.frame].format = vm.format;
2500                 ov511->frame[vm.frame].sub_flag = ov511->sub_flag;
2501                 ov511->frame[vm.frame].segsize = GET_SEGSIZE(vm.format);
2502                 ov511->frame[vm.frame].depth = depth;
2503 
2504                 /* Mark it as ready */
2505                 ov511->frame[vm.frame].grabstate = FRAME_READY;
2506 
2507                 return ov511_new_frame(ov511, vm.frame);
2508         }
2509         case VIDIOCSYNC:
2510         {
2511                 int frame;
2512 
2513                 if (copy_from_user((void *)&frame, arg, sizeof(int)))
2514                         return -EFAULT;
2515 
2516                 PDEBUG(4, "syncing to frame %d, grabstate = %d", frame,
2517                        ov511->frame[frame].grabstate);
2518 
2519                 switch (ov511->frame[frame].grabstate) {
2520                 case FRAME_UNUSED:
2521                         return -EINVAL;
2522                 case FRAME_READY:
2523                 case FRAME_GRABBING:
2524                 case FRAME_ERROR:
2525 redo:
2526                         if (!ov511->dev)
2527                                 return -EIO;
2528 
2529                         do {
2530 #if 0
2531                                 init_waitqueue_head(&ov511->frame[frame].wq);
2532 #endif
2533                                 interruptible_sleep_on(&ov511->frame[frame].wq);
2534                                 if (signal_pending(current)) {
2535                                         if (retry_sync) {
2536                                                 PDEBUG(3, "***retry sync***");
2537 
2538                                                 /* Polling apps will destroy frames with that! */
2539                                                 ov511_new_frame(ov511, frame);
2540                                                 ov511->curframe = -1;
2541 
2542                                                 /* This will request another frame. */
2543                                                 if (waitqueue_active(&ov511->frame[frame].wq))
2544                                                         wake_up_interruptible(&ov511->frame[frame].wq);
2545 
2546                                                 return 0;
2547                                         } else {
2548                                                 return -EINTR;
2549                                         }
2550                                 }
2551                         } while (ov511->frame[frame].grabstate == FRAME_GRABBING);
2552 
2553                         if (ov511->frame[frame].grabstate == FRAME_ERROR) {
2554                                 int ret;
2555 
2556                                 if ((ret = ov511_new_frame(ov511, frame)) < 0)
2557                                         return ret;
2558                                 goto redo;
2559                         }                       
2560                 case FRAME_DONE:
2561                         if (ov511->snap_enabled && !ov511->frame[frame].snapshot) {
2562                                 int ret;
2563                                 if ((ret = ov511_new_frame(ov511, frame)) < 0)
2564                                         return ret;
2565                                 goto redo;
2566                         }
2567 
2568                         ov511->frame[frame].grabstate = FRAME_UNUSED;
2569 
2570                         /* Reset the hardware snapshot button */
2571                         /* FIXME - Is this the best place for this? */
2572                         if ((ov511->snap_enabled) &&
2573                             (ov511->frame[frame].snapshot)) {
2574                                 ov511->frame[frame].snapshot = 0;
2575                                 ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
2576                                 ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03);
2577                                 ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
2578                         }
2579                         break;
2580                 } /* end switch */
2581 
2582                 return 0;
2583         }
2584         case VIDIOCGFBUF:
2585         {
2586                 struct video_buffer vb;
2587 
2588                 memset(&vb, 0, sizeof(vb));
2589                 vb.base = NULL; /* frame buffer not supported, not used */
2590 
2591                 if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
2592                         return -EFAULT;
2593 
2594                 return 0;
2595         }
2596         case VIDIOCKEY:
2597                 return 0;
2598         case VIDIOCCAPTURE:
2599                 return -EINVAL;
2600         case VIDIOCSFBUF:
2601                 return -EINVAL;
2602         case VIDIOCGTUNER:
2603         case VIDIOCSTUNER:
2604                 return -EINVAL;
2605         case VIDIOCGFREQ:
2606         case VIDIOCSFREQ:
2607                 return -EINVAL;
2608         case VIDIOCGAUDIO:
2609         case VIDIOCSAUDIO:
2610                 return -EINVAL;
2611         default:
2612                 return -ENOIOCTLCMD;
2613         } /* end switch */
2614 
2615         return 0;
2616 }
2617 
2618 static long ov511_read(struct video_device *dev, char *buf, unsigned long count, int noblock)
2619 {
2620         struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
2621         int i;
2622         int frmx = -1;
2623         volatile struct ov511_frame *frame;
2624 
2625         PDEBUG(4, "%ld bytes, noblock=%d", count, noblock);
2626 
2627         if (!dev || !buf)
2628                 return -EFAULT;
2629 
2630         if (!ov511->dev)
2631                 return -EIO;
2632 
2633         /* See if a frame is completed, then use it. */
2634         if (ov511->frame[0].grabstate >= FRAME_DONE)    /* _DONE or _ERROR */
2635                 frmx = 0;
2636         else if (ov511->frame[1].grabstate >= FRAME_DONE)/* _DONE or _ERROR */
2637                 frmx = 1;
2638 
2639         /* If nonblocking we return immediately */
2640         if (noblock && (frmx == -1))
2641                 return -EAGAIN;
2642 
2643         /* If no FRAME_DONE, look for a FRAME_GRABBING state. */
2644         /* See if a frame is in process (grabbing), then use it. */
2645         if (frmx == -1) {
2646                 if (ov511->frame[0].grabstate == FRAME_GRABBING)
2647                         frmx = 0;
2648                 else if (ov511->frame[1].grabstate == FRAME_GRABBING)
2649                         frmx = 1;
2650         }
2651 
2652         /* If no frame is active, start one. */
2653         if (frmx == -1)
2654                 ov511_new_frame(ov511, frmx = 0);
2655 
2656         frame = &ov511->frame[frmx];
2657 
2658 restart:
2659         if (!ov511->dev)
2660                 return -EIO;
2661 
2662         /* Wait while we're grabbing the image */
2663         PDEBUG(4, "Waiting image grabbing");
2664         while (frame->grabstate == FRAME_GRABBING) {
2665                 interruptible_sleep_on(&ov511->frame[frmx].wq);
2666                 if (signal_pending(current))
2667                         return -EINTR;
2668         }
2669         PDEBUG(4, "Got image, frame->grabstate = %d", frame->grabstate);
2670 
2671         if (frame->grabstate == FRAME_ERROR) {
2672                 frame->bytes_read = 0;
2673                 err("** ick! ** Errored frame %d", ov511->curframe);
2674                 if (ov511_new_frame(ov511, frmx))
2675                         err("read: ov511_new_frame error");
2676                 goto restart;
2677         }
2678 
2679 
2680         /* Repeat until we get a snapshot frame */
2681         if (ov511->snap_enabled)
2682                 PDEBUG (4, "Waiting snapshot frame");
2683         if (ov511->snap_enabled && !frame->snapshot) {
2684                 frame->bytes_read = 0;
2685                 if (ov511_new_frame(ov511, frmx))
2686                         err("ov511_new_frame error");
2687                 goto restart;
2688         }
2689 
2690         /* Clear the snapshot */
2691         if (ov511->snap_enabled && frame->snapshot) {
2692                 frame->snapshot = 0;
2693                 ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
2694                 ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03);
2695                 ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
2696         }
2697 
2698         PDEBUG(4, "frmx=%d, bytes_read=%ld, scanlength=%ld", frmx,
2699                 frame->bytes_read, frame->scanlength);
2700 
2701         /* copy bytes to user space; we allow for partials reads */
2702 //      if ((count + frame->bytes_read) > frame->scanlength)
2703 //              count = frame->scanlength - frame->bytes_read;
2704 
2705         /* FIXME - count hardwired to be one frame... */
2706         count = frame->width * frame->height * (frame->depth >> 3);
2707 
2708         PDEBUG(4, "Copy to user space: %ld bytes", count);
2709         if ((i = copy_to_user(buf, frame->data + frame->bytes_read, count))) {
2710                 PDEBUG(4, "Copy failed! %d bytes not copied", i);
2711                 return -EFAULT;
2712         }
2713 
2714         frame->bytes_read += count;
2715         PDEBUG(4, "{copy} count used=%ld, new bytes_read=%ld",
2716                 count, frame->bytes_read);
2717 
2718         if (frame->bytes_read >= frame->scanlength) { /* All data has been read */
2719                 frame->bytes_read = 0;
2720 
2721                 /* Mark it as available to be used again. */
2722                 ov511->frame[frmx].grabstate = FRAME_UNUSED;
2723                 if (ov511_new_frame(ov511, !frmx))
2724                         err("ov511_new_frame returned error");
2725         }
2726 
2727         PDEBUG(4, "read finished, returning %ld (sweet)", count);
2728 
2729         return count;
2730 }
2731 
2732 static int ov511_mmap(struct video_device *dev, const char *adr,
2733         unsigned long size)
2734 {
2735         struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
2736         unsigned long start = (unsigned long)adr;
2737         unsigned long page, pos;
2738 
2739         if (ov511->dev == NULL)
2740                 return -EIO;
2741 
2742         PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
2743 
2744         if (size > (((OV511_NUMFRAMES * MAX_DATA_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
2745                 return -EINVAL;
2746 
2747         pos = (unsigned long)ov511->fbuf;
2748         while (size > 0) {
2749                 page = kvirt_to_pa(pos);
2750                 if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
2751                         return -EAGAIN;
2752                 start += PAGE_SIZE;
2753                 pos += PAGE_SIZE;
2754                 if (size > PAGE_SIZE)
2755                         size -= PAGE_SIZE;
2756                 else
2757                         size = 0;
2758         }
2759 
2760         return 0;
2761 }
2762 
2763 static struct video_device ov511_template = {
2764         name:           "OV511 USB Camera",
2765         type:           VID_TYPE_CAPTURE,
2766         hardware:       VID_HARDWARE_OV511,
2767         open:           ov511_open,
2768         close:          ov511_close,
2769         read:           ov511_read,
2770         write:          ov511_write,
2771         ioctl:          ov511_ioctl,
2772         mmap:           ov511_mmap,
2773         initialize:     ov511_init_done,
2774 };
2775 
2776 /****************************************************************************
2777  *
2778  * OV511/OV7610 configuration
2779  *
2780  ***************************************************************************/
2781 
2782 static int ov76xx_configure(struct usb_ov511 *ov511)
2783 {
2784         struct usb_device *dev = ov511->dev;
2785         int i, success;
2786         int rc;
2787 
2788         /* Lawrence Glaister <lg@jfm.bc.ca> reports:
2789          *
2790          * Register 0x0f in the 7610 has the following effects:
2791          *
2792          * 0x85 (AEC method 1): Best overall, good contrast range
2793          * 0x45 (AEC method 2): Very overexposed
2794          * 0xa5 (spec sheet default): Ok, but the black level is
2795          *      shifted resulting in loss of contrast
2796          * 0x05 (old driver setting): very overexposed, too much
2797          *      contrast
2798          */
2799         static struct ov511_regvals aRegvalsNorm7610[] = {
2800                 { OV511_I2C_BUS, 0x10, 0xff },
2801                 { OV511_I2C_BUS, 0x16, 0x06 },
2802                 { OV511_I2C_BUS, 0x28, 0x24 },
2803                 { OV511_I2C_BUS, 0x2b, 0xac },
2804                 { OV511_I2C_BUS, 0x12, 0x00 },
2805                 { OV511_I2C_BUS, 0x38, 0x81 },
2806                 { OV511_I2C_BUS, 0x28, 0x24 },  /* 0c */
2807                 { OV511_I2C_BUS, 0x0f, 0x85 },  /* lg's setting */
2808                 { OV511_I2C_BUS, 0x15, 0x01 },
2809                 { OV511_I2C_BUS, 0x20, 0x1c },
2810                 { OV511_I2C_BUS, 0x23, 0x2a },
2811                 { OV511_I2C_BUS, 0x24, 0x10 },
2812                 { OV511_I2C_BUS, 0x25, 0x8a },
2813                 { OV511_I2C_BUS, 0x27, 0xc2 },
2814                 { OV511_I2C_BUS, 0x2a, 0x04 },
2815                 { OV511_I2C_BUS, 0x2c, 0xfe },
2816                 { OV511_I2C_BUS, 0x30, 0x71 },
2817                 { OV511_I2C_BUS, 0x31, 0x60 },
2818                 { OV511_I2C_BUS, 0x32, 0x26 },
2819                 { OV511_I2C_BUS, 0x33, 0x20 },
2820                 { OV511_I2C_BUS, 0x34, 0x48 },
2821                 { OV511_I2C_BUS, 0x12, 0x24 },
2822                 { OV511_I2C_BUS, 0x11, 0x01 },
2823                 { OV511_I2C_BUS, 0x0c, 0x24 },
2824                 { OV511_I2C_BUS, 0x0d, 0x24 },
2825                 { OV511_DONE_BUS, 0x0, 0x00 },
2826         };
2827 
2828         static struct ov511_regvals aRegvalsNorm7620[] = {
2829                 { OV511_I2C_BUS, 0x10, 0xff },
2830                 { OV511_I2C_BUS, 0x16, 0x06 },
2831                 { OV511_I2C_BUS, 0x28, 0x24 },
2832                 { OV511_I2C_BUS, 0x2b, 0xac },
2833                 { OV511_I2C_BUS, 0x12, 0x00 },
2834                 { OV511_I2C_BUS, 0x28, 0x24 },
2835                 { OV511_I2C_BUS, 0x0f, 0x85 },  /* lg's setting */
2836                 { OV511_I2C_BUS, 0x15, 0x01 },
2837                 { OV511_I2C_BUS, 0x23, 0x00 },
2838                 { OV511_I2C_BUS, 0x24, 0x10 },
2839                 { OV511_I2C_BUS, 0x25, 0x8a },
2840                 { OV511_I2C_BUS, 0x27, 0xe2 },
2841                 { OV511_I2C_BUS, 0x2a, 0x00 },
2842                 { OV511_I2C_BUS, 0x2c, 0xfe },
2843                 { OV511_I2C_BUS, 0x30, 0x71 },
2844                 { OV511_I2C_BUS, 0x31, 0x60 },
2845                 { OV511_I2C_BUS, 0x32, 0x26 },
2846                 { OV511_I2C_BUS, 0x33, 0x20 },
2847                 { OV511_I2C_BUS, 0x34, 0x48 },
2848                 { OV511_I2C_BUS, 0x12, 0x24 },
2849                 { OV511_I2C_BUS, 0x11, 0x01 },
2850                 { OV511_I2C_BUS, 0x0c, 0x24 },
2851                 { OV511_I2C_BUS, 0x0d, 0x24 },
2852                 { OV511_DONE_BUS, 0x0, 0x00 },
2853         };
2854 
2855         PDEBUG (4, "starting configuration");
2856 
2857         /* This looks redundant, but is necessary for WebCam 3 */
2858         if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
2859                             OV7610_I2C_WRITE_ID) < 0)
2860                 return -1;
2861 
2862         if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
2863                             OV7610_I2C_READ_ID) < 0)
2864                 return -1;
2865 
2866         if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
2867                 return -1;
2868 
2869         /* Reset the 76xx */ 
2870         if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
2871 
2872         /* Wait for it to initialize */ 
2873         schedule_timeout (1 + 150 * HZ / 1000);
2874 
2875         for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
2876                 if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
2877                     (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) {
2878                         success = 1;
2879                         continue;
2880                 }
2881 
2882                 /* Reset the 76xx */ 
2883                 if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
2884                 /* Wait for it to initialize */ 
2885                 schedule_timeout (1 + 150 * HZ / 1000);
2886                 /* Dummy read to sync I2C */
2887                 if (ov511_i2c_read(dev, 0x00) < 0) return -1;
2888         }
2889 
2890         if (success) {
2891                 PDEBUG(1, "I2C synced in %d attempt(s) (method 1)", i);
2892         } else {
2893                 /* Reset the 76xx */
2894                 if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
2895 
2896                 /* Wait for it to initialize */
2897                 schedule_timeout (1 + 150 * HZ / 1000);
2898 
2899                 i = 0;
2900                 success = 0;
2901                 while (i <= i2c_detect_tries) {
2902                         if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
2903                             (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) {
2904                                 success = 1;
2905                                 break;
2906                         } else {
2907                                 i++;
2908                         }
2909                 }
2910 
2911                 if ((i == i2c_detect_tries) && (success == 0)) {
2912                         err("Failed to read sensor ID. You might not have an OV7610/20,");
2913                         err("or it may be not responding. Report this to");
2914                         err("mwm@i.am");
2915                         return -1;
2916                 } else {
2917                         PDEBUG(1, "I2C synced in %d attempt(s) (method 2)", i+1);
2918                 }
2919         }
2920 
2921         /* Detect sensor if user didn't use override param */
2922         if (sensor == 0) {
2923                 rc = ov511_i2c_read(dev, OV7610_REG_COM_I);
2924 
2925                 if (rc < 0) {
2926                         err("Error detecting sensor type");
2927                         return -1;
2928                 } else if((rc & 3) == 3) {
2929                         info("Sensor is an OV7610");
2930                         ov511->sensor = SEN_OV7610;
2931                 } else if((rc & 3) == 1) {
2932                         info("Sensor is an OV7620AE");
2933                         ov511->sensor = SEN_OV7620AE;
2934                 } else if((rc & 3) == 0) {
2935                         info("Sensor is an OV7620");
2936                         ov511->sensor = SEN_OV7620;
2937                 } else {
2938                         err("Unknown image sensor version: %d", rc & 3);
2939                         return -1;
2940                 }
2941         } else {        /* sensor != 0; user overrode detection */
2942                 ov511->sensor = sensor;
2943                 info("Sensor set to type %d", ov511->sensor);
2944         }
2945 
2946         if (ov511->sensor == SEN_OV7620) {
2947                 PDEBUG(4, "Writing 7620 registers");
2948                 if (ov511_write_regvals(dev, aRegvalsNorm7620))
2949                         return -1;
2950         } else {
2951                 PDEBUG(4, "Writing 7610 registers");
2952                 if (ov511_write_regvals(dev, aRegvalsNorm7610))
2953                         return -1;
2954         }
2955 
2956         /* Set sensor-specific vars */
2957         ov511->maxwidth = 640;
2958         ov511->maxheight = 480;
2959 
2960         if (aperture < 0) {          /* go with the default */
2961                 if (ov511_i2c_write(dev, 0x26, 0xa2) < 0) return -1;
2962         } else if (aperture <= 0xf) {  /* user overrode default */
2963                 if (ov511_i2c_write(dev, 0x26, (aperture << 4) + 2) < 0)
2964                         return -1;
2965         } else {
2966                 err("Invalid setting for aperture; legal value: 0 - 15");
2967                 return -1;
2968         }
2969 
2970         if (autoadjust) {
2971                 if (ov511_i2c_write(dev, 0x13, 0x01) < 0) return -1;
2972                 if (ov511_i2c_write(dev, 0x2d, 
2973                      ov511->sensor==SEN_OV7620?0x91:0x93) < 0) return -1;
2974         } else {
2975                 if (ov511_i2c_write(dev, 0x13, 0x00) < 0) return -1;
2976                 if (ov511_i2c_write(dev, 0x2d, 
2977                      ov511->sensor==SEN_OV7620?0x81:0x83) < 0) return -1;
2978                 ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
2979         }
2980 
2981         return 0;
2982 }
2983 
2984 static int ov6xx0_configure(struct usb_ov511 *ov511)
2985 {
2986         struct usb_device *dev = ov511->dev;
2987         int i, success, rc;
2988 
2989         static struct ov511_regvals aRegvalsNorm6x20[] = {
2990                 { OV511_I2C_BUS, 0x12, 0x80 },  /* reset */
2991                 { OV511_I2C_BUS, 0x11, 0x01 },
2992                 { OV511_I2C_BUS, 0x03, 0xd0 },
2993                 { OV511_I2C_BUS, 0x05, 0x7f },
2994                 { OV511_I2C_BUS, 0x07, 0xa8 },
2995                 { OV511_I2C_BUS, 0x0c, 0x24 },
2996                 { OV511_I2C_BUS, 0x0d, 0x24 },
2997                 { OV511_I2C_BUS, 0x10, 0xff },  /* ? */
2998                 { OV511_I2C_BUS, 0x14, 0x04 },
2999                 { OV511_I2C_BUS, 0x16, 0x06 },  /* ? */
3000                 { OV511_I2C_BUS, 0x19, 0x04 },
3001                 { OV511_I2C_BUS, 0x1a, 0x93 },
3002                 { OV511_I2C_BUS, 0x20, 0x28 },
3003                 { OV511_I2C_BUS, 0x27, 0xa2 },
3004                 { OV511_I2C_BUS, 0x28, 0x24 },
3005                 { OV511_I2C_BUS, 0x2a, 0x04 },  /* 84? */
3006                 { OV511_I2C_BUS, 0x2b, 0xac },  /* a8? */
3007                 { OV511_I2C_BUS, 0x2d, 0x95 },
3008                 { OV511_I2C_BUS, 0x33, 0x28 },
3009                 { OV511_I2C_BUS, 0x34, 0xc7 },
3010                 { OV511_I2C_BUS, 0x38, 0x8b },
3011                 { OV511_I2C_BUS, 0x3c, 0x5c },
3012                 { OV511_I2C_BUS, 0x3d, 0x80 },
3013                 { OV511_I2C_BUS, 0x3f, 0x00 },
3014                 { OV511_I2C_BUS, 0x4a, 0x80 }, /* undocumented */
3015                 { OV511_I2C_BUS, 0x4b, 0x80 }, /* undocumented */
3016                 { OV511_I2C_BUS, 0x4d, 0xd2 },
3017                 { OV511_I2C_BUS, 0x4e, 0xc1 },
3018                 { OV511_I2C_BUS, 0x4f, 0x04 },
3019                 { OV511_DONE_BUS, 0x0, 0x00 },
3020         };
3021 
3022         PDEBUG (4, "starting sensor configuration");
3023         
3024         /* Reset the 6xx0 */ 
3025         if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
3026 
3027         /* Wait for it to initialize */ 
3028         schedule_timeout (1 + 150 * HZ / 1000);
3029 
3030         for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
3031                 if ((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) == 0x7F) &&
3032                     (ov511_i2c_read(dev, OV7610_REG_ID_LOW) == 0xA2)) {
3033                         success = 1;
3034                         continue;
3035                 }
3036 
3037                 /* Reset the 6xx0 */ 
3038                 if (ov511_i2c_write(dev, 0x12, 0x80) < 0) return -1;
3039                 /* Wait for it to initialize */ 
3040                 schedule_timeout (1 + 150 * HZ / 1000);
3041                 /* Dummy read to sync I2C */
3042                 if (ov511_i2c_read(dev, 0x00) < 0) return -1;
3043         }
3044 
3045         if (success) {
3046                 PDEBUG(1, "I2C synced in %d attempt(s)", i);
3047         } else {
3048                 err("Failed to read sensor ID. You might not have an OV6xx0,");
3049                 err("or it may be not responding. Report this to");
3050                 err("mwm@i.am");
3051                 return -1;
3052         }
3053 
3054         /* Detect sensor if user didn't use override param */
3055         if (sensor == 0) {
3056                 rc = ov511_i2c_read(dev, OV7610_REG_COM_I);
3057 
3058                 if (rc < 0) {
3059                         err("Error detecting sensor type");
3060                         return -1;
3061                 } else {
3062                         info("Sensor is an OV6xx0 (version %d)", rc & 3);
3063                         ov511->sensor = SEN_OV6620;
3064                 }
3065         } else {        /* sensor != 0; user overrode detection */
3066                 ov511->sensor = sensor;
3067                 info("Sensor set to type %d", ov511->sensor);
3068         }
3069 
3070         /* Set sensor-specific vars */
3071         ov511->maxwidth = 352;
3072         ov511->maxheight = 288;
3073 
3074         PDEBUG(4, "Writing 6x20 registers");
3075         if (ov511_write_regvals(dev, aRegvalsNorm6x20))
3076                 return -1;
3077 
3078         if (aperture < 0) {          /* go with the default */
3079                 if (ov511_i2c_write(dev, 0x26, 0xa2) < 0) return -1;
3080         } else if (aperture <= 0xf) {  /* user overrode default */
3081                 if (ov511_i2c_write(dev, 0x26, (aperture << 4) + 2) < 0)
3082                         return -1;
3083         } else {
3084                 err("Invalid setting for aperture; legal value: 0 - 15");
3085                 return -1;
3086         }
3087 
3088         if (autoadjust) {
3089                 if (ov511_i2c_write(dev, 0x13, 0x01) < 0) return -1;
3090                 if (ov511_i2c_write(dev, 0x2d, 
3091                      ov511->sensor==SEN_OV7620?0x91:0x93) < 0) return -1;
3092         } else {
3093                 if (ov511_i2c_write(dev, 0x13, 0x00) < 0) return -1;
3094                 if (ov511_i2c_write(dev, 0x2d, 
3095                      ov511->sensor==SEN_OV7620?0x81:0x83) < 0) return -1;
3096                 ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
3097         }
3098 
3099         return 0;
3100 }
3101 
3102 
3103 static int ov511_configure(struct usb_ov511 *ov511)
3104 {
3105         struct usb_device *dev = ov511->dev;
3106         int i;
3107 
3108         static struct ov511_regvals aRegvalsInit[] = {
3109                 { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f },
3110                 { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
3111                 { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f },
3112                 { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
3113                 { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3f },
3114                 { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
3115                 { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3d },
3116                 { OV511_DONE_BUS, 0x0, 0x00},
3117         };
3118 
3119         static struct ov511_regvals aRegvalsNorm511[] = {
3120                 { OV511_REG_BUS, OV511_REG_DRAM_ENABLE_FLOW_CONTROL, 0x01 },
3121                 { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x02 },
3122                 { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x00 },
3123                 { OV511_REG_BUS, OV511_REG_FIFO_BITMASK, 0x1f },
3124                 { OV511_REG_BUS, OV511_OMNICE_PREDICTION_HORIZ_Y, 0x08 },
3125                 { OV511_REG_BUS, OV511_OMNICE_PREDICTION_HORIZ_UV, 0x01 },
3126                 { OV511_REG_BUS, OV511_OMNICE_PREDICTION_VERT_Y, 0x08 },
3127                 { OV511_REG_BUS, OV511_OMNICE_PREDICTION_VERT_UV, 0x01 },
3128                 { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_HORIZ_Y, 0x01 },
3129                 { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_HORIZ_UV, 0x01 },
3130                 { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_VERT_Y, 0x01 },
3131                 { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_VERT_UV, 0x01 },
3132                 { OV511_REG_BUS, OV511_OMNICE_ENABLE, 0x06 },
3133                 { OV511_REG_BUS, OV511_OMNICE_LUT_ENABLE, 0x03 },
3134                 { OV511_DONE_BUS, 0x0, 0x00 },
3135         };
3136 
3137         memcpy(&ov511->vdev, &ov511_template, sizeof(ov511_template));
3138 
3139         for (i = 0; i < OV511_NUMFRAMES; i++)
3140                 init_waitqueue_head(&ov511->frame[i].wq);
3141 
3142         init_waitqueue_head(&ov511->wq);
3143 
3144         if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) < 0) {
3145                 err("video_register_device failed");
3146                 return -EBUSY;
3147         }
3148 
3149         if (ov511_write_regvals(dev, aRegvalsInit)) goto error;
3150         if (ov511_write_regvals(dev, aRegvalsNorm511)) goto error;
3151 
3152         ov511_set_packet_size(ov511, 0);
3153 
3154         ov511->snap_enabled = snapshot; 
3155 
3156         /* Test for 76xx */
3157         if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
3158                            OV7610_I2C_WRITE_ID) < 0)
3159                 goto error;
3160 
3161         if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
3162                            OV7610_I2C_READ_ID) < 0)
3163                 goto error;
3164 
3165         if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
3166                 goto error;
3167 
3168         if (ov511_i2c_write(dev, 0x12, 0x80) < 0) {
3169                 /* Test for 6xx0 */
3170                 if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
3171                                     OV6xx0_I2C_WRITE_ID) < 0)
3172                         goto error;
3173 
3174                 if (ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
3175                                     OV6xx0_I2C_READ_ID) < 0)
3176                         goto error;
3177 
3178                 if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
3179                         goto error;
3180 
3181                 if (ov511_i2c_write(dev, 0x12, 0x80) < 0) {
3182                         err("Can't determine sensor slave IDs");
3183                         goto error;
3184                 }
3185                 
3186                 if(ov6xx0_configure(ov511) < 0) {
3187                         err("failed to configure OV6xx0");
3188                         goto error;
3189                 }
3190         } else {
3191                 if(ov76xx_configure(ov511) < 0) {
3192                         err("failed to configure OV76xx");
3193                         goto error;
3194                 }
3195         }
3196         
3197         /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
3198          * (using read() instead). */
3199         for (i = 0; i < OV511_NUMFRAMES; i++) {
3200                 ov511->frame[i].width = ov511->maxwidth;
3201                 ov511->frame[i].height = ov511->maxheight;
3202                 ov511->frame[i].depth = 24;
3203                 ov511->frame[i].bytes_read = 0;
3204                 ov511->frame[i].segment = 0;
3205                 ov511->frame[i].format = VIDEO_PALETTE_RGB24;
3206                 ov511->frame[i].segsize = GET_SEGSIZE(ov511->frame[i].format);
3207         }
3208 
3209         /* Initialize to max width/height, RGB24 */
3210         if (ov511_mode_init_regs(ov511, ov511->maxwidth, ov511->maxheight,
3211                                  VIDEO_PALETTE_RGB24, 0) < 0)
3212                 goto error;
3213 
3214         return 0;
3215         
3216 error:
3217         video_unregister_device(&ov511->vdev);
3218         usb_driver_release_interface(&ov511_driver,
3219                 &dev->actconfig->interface[ov511->iface]);
3220 
3221         return -EBUSY;  
3222 }
3223 
3224 
3225 /****************************************************************************
3226  *
3227  *  USB routines
3228  *
3229  ***************************************************************************/
3230 
3231 static void *
3232 ov511_probe(struct usb_device *dev, unsigned int ifnum,
3233         const struct usb_device_id *id)
3234 {
3235         struct usb_interface_descriptor *interface;
3236         struct usb_ov511 *ov511;
3237         int i;
3238 
3239         PDEBUG(1, "probing for device...");
3240 
3241         /* We don't handle multi-config cameras */
3242         if (dev->descriptor.bNumConfigurations != 1)
3243                 return NULL;
3244 
3245         interface = &dev->actconfig->interface[ifnum].altsetting[0];
3246 
3247         /* Checking vendor/product should be enough, but what the hell */
3248         if (interface->bInterfaceClass != 0xFF)
3249                 return NULL;
3250         if (interface->bInterfaceSubClass != 0x00)
3251                 return NULL;
3252 
3253         /* Since code below may sleep, we use this as a lock */
3254         MOD_INC_USE_COUNT;
3255 
3256         if ((ov511 = kmalloc(sizeof(*ov511), GFP_KERNEL)) == NULL) {
3257                 err("couldn't kmalloc ov511 struct");
3258                 goto error;
3259         }
3260 
3261         memset(ov511, 0, sizeof(*ov511));
3262 
3263         ov511->dev = dev;
3264         ov511->iface = interface->bInterfaceNumber;
3265 
3266         switch (dev->descriptor.idProduct) {
3267         case 0x0511:
3268                 info("USB OV511 camera found");
3269                 ov511->bridge = BRG_OV511;
3270                 break;
3271         case 0xA511:
3272                 info("USB OV511+ camera found");
3273                 ov511->bridge = BRG_OV511PLUS;
3274                 break;
3275         case 0x0002:
3276                 if (dev->descriptor.idVendor != 0x0813)
3277                         goto error;
3278                 info("Intel Play Me2Cam (OV511+) found");
3279                 ov511->bridge = BRG_OV511PLUS;
3280                 break;
3281         default:
3282                 err("Unknown product ID");
3283                 goto error;
3284         }
3285 
3286         ov511->customid = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
3287         if (ov511->customid < 0) {
3288                 err("Unable to read camera bridge registers");
3289                 goto error;
3290         }
3291 
3292         ov511->desc = -1;
3293         PDEBUG (4, "CustomID = %d", ov511->customid);
3294         for (i = 0; clist[i].id >= 0; i++) {
3295                 if (ov511->customid == clist[i].id) {
3296                         info("camera: %s", clist[i].description);
3297                         ov511->desc = i;
3298                         break;
3299                 }
3300         }
3301 
3302         /* Lifeview USB Life TV not supported */
3303         if (clist[i].id == 38) {
3304                 err("This device is not supported yet.");
3305                 goto error;
3306         }
3307 
3308         if (clist[i].id == -1) {
3309                 err("Camera type (%d) not recognized", ov511->customid);
3310                 err("Please contact mwm@i.am to request");
3311                 err("support for your camera.");
3312         }
3313 
3314         /* Workaround for some applications that want data in RGB
3315          * instead of BGR */
3316         if (force_rgb)
3317                 info("data format set to RGB");
3318 
3319         if (!ov511_configure(ov511)) {
3320                 ov511->user = 0;
3321                 init_MUTEX(&ov511->lock);       /* to 1 == available */
3322                 init_MUTEX(&ov511->buf_lock);
3323                 ov511->buf_state = BUF_NOT_ALLOCATED;
3324         } else {
3325                 err("Failed to configure camera");
3326                 goto error;
3327         }
3328 
3329         MOD_DEC_USE_COUNT;
3330         return ov511;
3331 
3332 error:
3333         if (ov511) {
3334                 kfree(ov511);
3335                 ov511 = NULL;
3336         }
3337 
3338         MOD_DEC_USE_COUNT;
3339         return NULL;
3340 }
3341 
3342 
3343 static void
3344 ov511_disconnect(struct usb_device *dev, void *ptr)
3345 {
3346         struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr;
3347         int n;
3348 
3349         MOD_INC_USE_COUNT;
3350 
3351         PDEBUG(3, "");
3352 
3353         /* We don't want people trying to open up the device */
3354         if (!ov511->user)
3355                 video_unregister_device(&ov511->vdev);
3356         else
3357                 PDEBUG(3, "Device open...deferring video_unregister_device");
3358 
3359         for (n = 0; n < OV511_NUMFRAMES; n++)
3360                 ov511->frame[n].grabstate = FRAME_ERROR;
3361 
3362         ov511->curframe = -1;
3363 
3364         /* This will cause the process to request another frame */
3365         for (n = 0; n < OV511_NUMFRAMES; n++)
3366                 if (waitqueue_active(&ov511->frame[n].wq))
3367                         wake_up_interruptible(&ov511->frame[n].wq);
3368         if (waitqueue_active(&ov511->wq))
3369                 wake_up_interruptible(&ov511->wq);
3370 
3371         ov511->streaming = 0;
3372 
3373         /* Unschedule all of the iso td's */
3374         for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
3375                 if (ov511->sbuf[n].urb) {
3376                         ov511->sbuf[n].urb->next = NULL;
3377                         usb_unlink_urb(ov511->sbuf[n].urb);
3378                         usb_free_urb(ov511->sbuf[n].urb);
3379                         ov511->sbuf[n].urb = NULL;
3380                 }
3381         }
3382 
3383         usb_driver_release_interface(&ov511_driver,
3384                 &ov511->dev->actconfig->interface[ov511->iface]);
3385         ov511->dev = NULL;
3386 
3387 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
3388         destroy_proc_ov511_cam(ov511);
3389 #endif
3390 
3391         /* Free the memory */
3392         if (ov511 && !ov511->user) {
3393                 ov511_dealloc(ov511, 1);
3394                 kfree(ov511);
3395                 ov511 = NULL;
3396         }
3397 
3398         MOD_DEC_USE_COUNT;
3399 }
3400 
3401 static struct usb_driver ov511_driver = {
3402         name:           "ov511",
3403         id_table:       device_table,
3404         probe:          ov511_probe,
3405         disconnect:     ov511_disconnect
3406 };
3407 
3408 
3409 /****************************************************************************
3410  *
3411  *  Module routines
3412  *
3413  ***************************************************************************/
3414 
3415 static int __init usb_ov511_init(void)
3416 {
3417 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
3418         proc_ov511_create();
3419 #endif
3420 
3421         if (usb_register(&ov511_driver) < 0)
3422                 return -1;
3423 
3424         info("ov511 driver version %s registered", version);
3425 
3426         return 0;
3427 }
3428 
3429 static void __exit usb_ov511_exit(void)
3430 {
3431         usb_deregister(&ov511_driver);
3432         info("driver deregistered");
3433 
3434 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
3435         proc_ov511_destroy();
3436 #endif 
3437 }
3438 
3439 module_init(usb_ov511_init);
3440 module_exit(usb_ov511_exit);
3441 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.