This is against 2.3.99-pre4-4. The biggest change is working
OV511+/OV7620 support (thanks to Charl P. Botha.)

CHANGES:
- ov511_move_data() updated to handle all packet sizes (except even
ones)
- Packet sizes 512, 768, and 992 removed, since they don't support
packet numbering
- Added many function call debug messages
- in ov511_mode_init_regs():
   - I2C reg 0x0E and 0x35 are no longer set on the OV7620
   - Windowing different on OV7610/OV7620AE and OV7620 - fixed
- aRegvalsNorm[] separated into aRegvalsNorm7610[] and
aRegvalsNorm7620[]
- in ov511_configure, I2C reg 0x2D is set differently depending on
sensor

-- 
Mark McClelland
[EMAIL PROTECTED]
diff -Naur linux-orig/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt
--- linux-orig/Documentation/usb/ov511.txt      Wed Apr  5 03:24:33 2000
+++ linux/Documentation/usb/ov511.txt   Wed Apr  5 02:58:23 2000
@@ -5,44 +5,17 @@
 Author: Mark McClelland
 Homepage: http://alpha.dyndns.org/ov511
 
+NEW IN THIS VERSION:
+ o Support for OV511+
+ o Support for OV7620
+
 INTRODUCTION:
 
 This is a preliminary version of my OV511 Linux device driver. Currently, it can
 grab a frame in color (YUV420) at 640x480 or 320x240 using either vidcat or
 xawtv. Other utilities may work but have not yet been tested.
 
-NEW IN THIS VERSION:
- o Autoadjust disable works, but is not perfect yet
- o Partial support for OV511+
- o Detection and support for OV7610, OV7620, and OV7620AE sensors
- o Various code cleanups and improvements
-
-KNOWN CAMERAS:
-____________________________________________________________________
-Manufacturer  | Model           | ID  | Bridge | Sensor   | Status
---------------+-----------------+-----+--------+----------+-----------
-MediaForte    | MV300           | 0   | OV511  | OV7610 * | Working
-Aiptek        | HyperVCam ?     | 0   | OV511  | OV7610 * | Working
-NetView       | NV300M          | 0   | OV511  | OV7610 * | Working
-D-Link        | DSB-C300        | 3   | OV511  | OV7620AE | Working
-Hawking Tech. | ???             | 3   | OV511  | OV7610 * | Working
-???           | Generic         | 4   | OV511  | OV7610 * | Untested
-Puretek       | PT-6007         | 5   | OV511  | OV7610 * | Working
-Creative Labs | WebCam 3        | 21  | OV511  | OV7610 * | Working 
-???           | Koala-Cam       | 36  | OV511  | OV7610 * | Untested
-Lifeview      | USB Life TV     | 38  | OV511  | N/A      | Unsupported
-Lifeview      | RoboCam         | 100 | OV511  | OV7610 * | Untested
-AverMedia     | InterCam Elite  | 102 | OV511  | OV7610 * | Working
-MediaForte    | MV300           | 112 | OV511  | OV7610 * | Working
-Omnivision    | OV7110 EV board | 112 | OV511  | OV7110   | Working
----------------------------------------------------------------------
-
-(*) These have not been verified. If you have one of these, please report
-    the sensor type to me.
-
-NOTE - the OV511+ is not yet supported
-
-Any camera using the OV511 and the OV7610 or OV7620AE CCD should work. The
+Any camera using the OV511/OV511+ and the OV7610/20/20AE CCD should work. The
 driver only detects known cameras though, based on their custom id number. If
 you have a currently unsupported camera, the ID number should be reported to you
 in the kernel logs. Please send me the model, manufacturer and ID number and I 
@@ -183,7 +156,6 @@
  o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and
    corrupted frames.
  o Snapshot mode (only works with some read() based apps; see below for more)
- o OV511+ support; not complete yet.
 
 TODO:
  o Fix the noise / grainy image problem.
@@ -201,7 +173,6 @@
  o Get hue (red/blue channel balance) adjustment working (in ov511_get_picture()
    and ov511_set_picture())
  o Get autoadjust disable working
- o OV7620 support
  o V4L2 support (Probably not until it goes into the kernel)
  o Fix I2C initialization. Some people are reporting problems with reading the
    7610 registers. This could be due to timing differences, an excessive I2C
diff -Naur linux-orig/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- linux-orig/drivers/usb/ov511.c      Wed Apr  5 03:24:52 2000
+++ linux/drivers/usb/ov511.c   Wed Apr  5 02:58:06 2000
@@ -4,12 +4,13 @@
  * Many improvements by Bret Wallach
  * Color fixes by by Orion Sky Lawlor, [EMAIL PROTECTED], 2/26/2000
  * Snapshot code by Kevin Moore
+ * OV7620 fixes by Charl P. Botha <[EMAIL PROTECTED]>
  * 
  * Based on the Linux CPiA driver.
  * 
  * Released under GPL v.2 license.
  *
- * Version: 1.10
+ * Version: 1.11
  *
  * Please see the file: linux/Documentation/usb/ov511.txt 
  * and the website at:  http://alpha.dyndns.org/ov511 
@@ -468,14 +469,14 @@
  * registers while the camera is streaming */
 static inline int ov511_stop(struct usb_device *dev)
 {
-       PDEBUG(5, "ov511_stop()");
+       PDEBUG(4, "ov511_stop()");
        return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d));
 }
 
 /* Restarts OV511 after ov511_stop() is called */
 static inline int ov511_restart(struct usb_device *dev)
 {
-       PDEBUG(5, "ov511_restart()");
+       PDEBUG(4, "ov511_restart()");
        return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00));
 }
 
@@ -491,11 +492,11 @@
        if (ov511->bridge == BRG_OV511) {
                if (size == 0) alt = OV511_ALT_SIZE_0;
                else if (size == 257) alt = OV511_ALT_SIZE_257;
-               else if (size == 512) alt = OV511_ALT_SIZE_512;
+//             else if (size == 512) alt = OV511_ALT_SIZE_512;
                else if (size == 513) alt = OV511_ALT_SIZE_513;
-               else if (size == 768) alt = OV511_ALT_SIZE_768;
+//             else if (size == 768) alt = OV511_ALT_SIZE_768;
                else if (size == 769) alt = OV511_ALT_SIZE_769;
-               else if (size == 992) alt = OV511_ALT_SIZE_992;
+//             else if (size == 992) alt = OV511_ALT_SIZE_992;
                else if (size == 993) alt = OV511_ALT_SIZE_993;
                else {
                        err("Set packet size: invalid size (%d)", size);
@@ -550,6 +551,8 @@
        int ret;
        struct usb_device *dev = ov511->dev;
 
+       PDEBUG(4, "ov511_set_picture");
+
        if (ov511_stop(dev) < 0)
                return -EIO;
 
@@ -569,6 +572,17 @@
 
                if(ov511_i2c_write(dev, OV7610_REG_BRT, p->brightness >> 8) < 0)
                        return -EIO;
+       }               
+       else if ((ov511->sensor == SEN_OV7620) 
+                || (ov511->sensor == SEN_OV7620AE)) {
+//             cur_con = ov511_i2c_read(dev, OV7610_REG_CNT);
+//             cur_brt = ov511_i2c_read(dev, OV7610_REG_BRT);
+//             // DEBUG_CODE
+//             PDEBUG(1, "con=%d brt=%d", ov511_i2c_read(dev, OV7610_REG_CNT),
+//                                        ov511_i2c_read(dev, OV7610_REG_BRT)); 
+//
+//             if(ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
+//                     return -EIO;
        }
 
        if (ov511_restart(dev) < 0)
@@ -583,6 +597,8 @@
        int ret;
        struct usb_device *dev = ov511->dev;
 
+       PDEBUG(4, "ov511_get_picture");
+
        if (ov511_stop(dev) < 0)
                return -EIO;
 
@@ -611,7 +627,9 @@
 {
        int rc = 0;
        struct usb_device *dev = ov511->dev;
-
+        int hwsbase = 0;
+        int hwebase = 0;
+
        PDEBUG(3, "ov511_mode_init_regs(ov511, w:%d, h:%d, mode:%d, sub:%d)",
               width, height, mode, sub_flag);
 
@@ -620,30 +638,57 @@
 
        if (mode == VIDEO_PALETTE_GREY) {
                ov511_reg_write(dev, 0x16, 0x00);
-               ov511_i2c_write(dev, 0x0e, 0x44);
+               if (ov511->sensor == SEN_OV7610
+                   || ov511->sensor == SEN_OV7620AE) {
+                       /* these aren't valid on the OV7620 */
+                       ov511_i2c_write(dev, 0x0e, 0x44);
+               }
                ov511_i2c_write(dev, 0x13, autoadjust ? 0x21 : 0x20);
                /* For snapshot */
                ov511_reg_write(dev, 0x1e, 0x00);
                ov511_reg_write(dev, 0x1f, 0x01);
        } else {
                ov511_reg_write(dev, 0x16, 0x01);
-               ov511_i2c_write(dev, 0x0e, 0x04);
+               if (ov511->sensor == SEN_OV7610
+                   || ov511->sensor == SEN_OV7620AE) {
+                  /* not valid on the OV7620 */
+                  ov511_i2c_write(dev, 0x0e, 0x04);
+               }
                ov511_i2c_write(dev, 0x13, autoadjust ? 0x01 : 0x00);
                /* For snapshot */
                ov511_reg_write(dev, 0x1e, 0x01);
                ov511_reg_write(dev, 0x1f, 0x03);
        }
 
+       /* The different sensor ICs handle setting up of window differently */
+        switch (ov511->sensor) {
+        case SEN_OV7610:
+        case SEN_OV7620AE:
+          hwsbase = 0x38;
+          hwebase = 0x3a; break;
+        case SEN_OV7620:
+          hwsbase = 0x2c;
+          hwebase = 0x2d; break;
+        default:
+          hwsbase = 0;
+          hwebase = 0; break;
+       }
+
        if (width == 640 && height == 480) {
                if (sub_flag) {
-                       ov511_i2c_write(dev, 0x17, 0x38+(ov511->subx>>2));
+                       /* horizontal window start */
+                       ov511_i2c_write(dev, 0x17, hwsbase+(ov511->subx>>2));
+                       /* horizontal window end */
                        ov511_i2c_write(dev, 0x18,
-                                       0x3a+((ov511->subx+ov511->subw)>>2));
-                       ov511_i2c_write(dev, 0x19, 0x5+(ov511->suby>>1));
-                       ov511_i2c_write(dev, 0x1a,
+                                       hwebase+((ov511->subx+ov511->subw)>>2));
+                       /* vertical window start */
+                       ov511_i2c_write(dev, 0x19, 0x5+(ov511->suby>>1));
+                       /* vertical window end */
+                   ov511_i2c_write(dev, 0x1a,
                                        0x5+((ov511->suby+ov511->subh)>>1));
                        ov511_reg_write(dev, 0x12, (ov511->subw>>3)-1);
                        ov511_reg_write(dev, 0x13, (ov511->subh>>3)-1);
+                       /* clock rate control */
                        ov511_i2c_write(dev, 0x11, 0x01);
 
                        /* Snapshot additions */
@@ -652,8 +697,8 @@
                        ov511_reg_write(dev, 0x1c, 0x00);
                        ov511_reg_write(dev, 0x1d, 0x00);
                } else {
-                       ov511_i2c_write(dev, 0x17, 0x38);
-                       ov511_i2c_write(dev, 0x18, 0x3a + (640>>2));
+                       ov511_i2c_write(dev, 0x17, hwsbase);
+                       ov511_i2c_write(dev, 0x18, hwebase + (640>>2));
                        ov511_i2c_write(dev, 0x19, 0x5);
                        ov511_i2c_write(dev, 0x1a, 5 + (480>>1));
                        ov511_reg_write(dev, 0x12, 0x4f);
@@ -666,9 +711,9 @@
                        ov511_reg_write(dev, 0x1d, 0x00);
 
                        if (mode == VIDEO_PALETTE_GREY) {
-                         ov511_i2c_write(dev, 0x11, 4); /* check */
+                               ov511_i2c_write(dev, 0x11, 4); /* check */
                        } else {
-                         ov511_i2c_write(dev, 0x11, 6); /* check */
+                               ov511_i2c_write(dev, 0x11, 6); /* check */
                        }
                }
 
@@ -680,7 +725,10 @@
 
                ov511_i2c_write(dev, 0x12, 0x24);
                ov511_i2c_write(dev, 0x14, 0x04);
-               ov511_i2c_write(dev, 0x35, 0x9e);
+
+               /* 7620 doesn't have register 0x35, so play it safe */
+               if (ov511->sensor != SEN_OV7620)
+                       ov511_i2c_write(dev, 0x35, 0x9e);
        } else if (width == 320 && height == 240) {
                ov511_reg_write(dev, 0x12, 0x27);
                ov511_reg_write(dev, 0x13, 0x1f);
@@ -970,6 +1018,8 @@
        int aPackNum[10];
        struct ov511_frame *frame;
 
+       PDEBUG(4, "ov511_move_data");
+
        for (i = 0; i < urb->number_of_packets; i++) {
                int n = urb->iso_frame_desc[i].actual_length;
                int st = urb->iso_frame_desc[i].status;
@@ -977,7 +1027,7 @@
                urb->iso_frame_desc[i].status = 0;
                cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
 
-               aPackNum[i] = n ? cdata[992] : -1;
+               aPackNum[i] = n ? cdata[ov511->packet_size - 1] : -1;
 
                if (!n || ov511->curframe == -1) continue;
 
@@ -996,7 +1046,7 @@
                    do_gettimeofday(ts);
 
                    PDEBUG(4, "Frame End, curframe = %d, packnum=%d, hw=%d, vw=%d",
-                          ov511->curframe, (int)(cdata[992]),
+                          ov511->curframe, (int)(cdata[ov511->packet_size - 1]),
                           (int)(cdata[9]), (int)(cdata[10]));
 
                    if (frame->scanstate == STATE_LINES) {
@@ -1059,7 +1109,7 @@
                        }
 
                        /* Parse the segments */
-                       while(iPix <= 992 - frame->segsize &&
+                       while(iPix <= (ov511->packet_size - 1) - frame->segsize &&
                              frame->segment < frame->width * frame->height / 256) {
                          int iSegY;
                          int iSegUV;
@@ -1107,7 +1157,7 @@
 
                        /* Save extra data for next time */
                        if (frame->segment < frame->width * frame->height / 256) {
-                         ov511->scratchlen = 992 - iPix;
+                         ov511->scratchlen = (ov511->packet_size - 1) - iPix;
                          if (ov511->scratchlen < frame->segsize) {
                            memmove(ov511->scratch, pData, ov511->scratchlen);
                          } else {
@@ -1157,13 +1207,20 @@
 {
        urb_t *urb;
        int fx, err;
-       
+
+       PDEBUG(4, "ov511_init_isoc");
+
        ov511->compress = 0;
        ov511->curframe = -1;
        ov511->cursbuf = 0;
        ov511->scratchlen = 0;
 
-       ov511_set_packet_size(ov511, 993);
+       if (ov511->bridge == BRG_OV511)
+               ov511_set_packet_size(ov511, 993);
+       else if (ov511->bridge == BRG_OV511PLUS)
+               ov511_set_packet_size(ov511, 961);
+       else
+               err("invalid bridge type");
 
        /* We double buffer the Iso lists */
        urb = usb_alloc_urb(FRAMES_PER_DESC);
@@ -1223,6 +1280,7 @@
 
 static void ov511_stop_isoc(struct usb_ov511 *ov511)
 {
+       PDEBUG(4, "ov511_stop_isoc");
        if (!ov511->streaming || !ov511->dev)
                return;
 
@@ -1247,10 +1305,11 @@
 
 static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
 {
-#if 1
        struct ov511_frame *frame;
        int width, height;
 
+       PDEBUG(4, "ov511_new_frame");
+
        if (!ov511->dev)
                return -1;
 
@@ -1285,7 +1344,6 @@
 //     /* We want a fresh frame every 30 we get */
 //     ov511->compress = (ov511->compress + 1) % 30;
 
-#endif
        return 0;
 }
 
@@ -1876,7 +1934,7 @@
        }
        
        if (tries == 1) {
-               err("Failed to read OV7610 ID. You might not have an OV7610,");
+               err("Failed to read sensor ID. You might not have an OV7610/20,");
                err("or it may be not responding. Report this to");
                err("[EMAIL PROTECTED]");
                return -1;
@@ -1929,9 +1987,9 @@
         {OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x3d},
         {OV511_DONE_BUS, 0x0, 0x00},
        };
-       static struct ov511_regvals aRegvalsNorm[] =
-       {{OV511_REG_BUS, 0x20, 1},
-#if 1
+
+       static struct ov511_regvals aRegvalsNorm7610[] =
+       {{OV511_REG_BUS, 0x20, 0x01},
         {OV511_REG_BUS, 0x52, 0x02},
         {OV511_REG_BUS, 0x52, 0x00},
         {OV511_REG_BUS, 0x31, 0x1f}, /* 0f */
@@ -1946,16 +2004,14 @@
         {OV511_REG_BUS, 0x78, 0x06},
         {OV511_REG_BUS, 0x79, 0x03},
 
-
         {OV511_I2C_BUS, 0x10, 0xff},
         {OV511_I2C_BUS, 0x16, 0x06},
-        {OV511_I2C_BUS, 0x28, 0x24}, /* 24 */
+        {OV511_I2C_BUS, 0x28, 0x24},
         {OV511_I2C_BUS, 0x2b, 0xac},
         {OV511_I2C_BUS, 0x05, 0x00},
         {OV511_I2C_BUS, 0x06, 0x00},
 
         {OV511_I2C_BUS, 0x12, 0x00},
-//      {OV511_I2C_BUS, 0x13, 0x00},
         {OV511_I2C_BUS, 0x38, 0x81},
         {OV511_I2C_BUS, 0x28, 0x24}, /* 0c */
         {OV511_I2C_BUS, 0x05, 0x00},
@@ -1970,18 +2026,62 @@
         {OV511_I2C_BUS, 0x29, 0x03}, /* 91 */
         {OV511_I2C_BUS, 0x2a, 0x04},
         {OV511_I2C_BUS, 0x2c, 0xfe},
-//      {OV511_I2C_BUS, 0x2d, 0x93}, /* d7 */
         {OV511_I2C_BUS, 0x30, 0x71},
         {OV511_I2C_BUS, 0x31, 0x60},
         {OV511_I2C_BUS, 0x32, 0x26},
         {OV511_I2C_BUS, 0x33, 0x20},
         {OV511_I2C_BUS, 0x34, 0x48},
         {OV511_I2C_BUS, 0x12, 0x24},
-//      {OV511_I2C_BUS, 0x13, 0x01},
         {OV511_I2C_BUS, 0x11, 0x01},
         {OV511_I2C_BUS, 0x0c, 0x24},
         {OV511_I2C_BUS, 0x0d, 0x24},
-#endif
+        {OV511_DONE_BUS, 0x0, 0x00},
+       };
+
+       static struct ov511_regvals aRegvalsNorm7620[] =
+       {{OV511_REG_BUS, 0x20, 0x01},
+        {OV511_REG_BUS, 0x52, 0x02},
+        {OV511_REG_BUS, 0x52, 0x00},
+        {OV511_REG_BUS, 0x31, 0x1f},
+        {OV511_REG_BUS, 0x70, 0x3f},
+        {OV511_REG_BUS, 0x71, 0x3f},
+        {OV511_REG_BUS, 0x72, 0x01},
+        {OV511_REG_BUS, 0x73, 0x01},
+        {OV511_REG_BUS, 0x74, 0x01},
+        {OV511_REG_BUS, 0x75, 0x01},
+        {OV511_REG_BUS, 0x76, 0x01},
+        {OV511_REG_BUS, 0x77, 0x01},
+        {OV511_REG_BUS, 0x78, 0x06},
+        {OV511_REG_BUS, 0x79, 0x03},
+
+        {OV511_I2C_BUS, 0x10, 0xff},
+        {OV511_I2C_BUS, 0x16, 0x06},
+        {OV511_I2C_BUS, 0x28, 0x24},
+        {OV511_I2C_BUS, 0x2b, 0xac},
+
+        {OV511_I2C_BUS, 0x12, 0x00},
+
+        {OV511_I2C_BUS, 0x28, 0x24},
+        {OV511_I2C_BUS, 0x05, 0x00},
+        {OV511_I2C_BUS, 0x0f, 0x05},
+        {OV511_I2C_BUS, 0x15, 0x01},
+        {OV511_I2C_BUS, 0x23, 0x00},
+        {OV511_I2C_BUS, 0x24, 0x10},
+        {OV511_I2C_BUS, 0x25, 0x8a},
+        {OV511_I2C_BUS, 0x26, 0xa2},
+        {OV511_I2C_BUS, 0x27, 0xe2},
+        {OV511_I2C_BUS, 0x29, 0x03},
+        {OV511_I2C_BUS, 0x2a, 0x00},
+        {OV511_I2C_BUS, 0x2c, 0xfe},
+        {OV511_I2C_BUS, 0x30, 0x71},
+        {OV511_I2C_BUS, 0x31, 0x60},
+        {OV511_I2C_BUS, 0x32, 0x26},
+        {OV511_I2C_BUS, 0x33, 0x20},
+        {OV511_I2C_BUS, 0x34, 0x48},
+        {OV511_I2C_BUS, 0x12, 0x24},
+        {OV511_I2C_BUS, 0x11, 0x01},
+        {OV511_I2C_BUS, 0x0c, 0x24},
+        {OV511_I2C_BUS, 0x0d, 0x24},
         {OV511_DONE_BUS, 0x0, 0x00},
        };
 
@@ -2022,17 +2122,26 @@
        ov511->frame[1].bytes_read = 0;
 
        /* Initialize to DEFAULT_WIDTH, DEFAULT_HEIGHT, YUV4:2:0 */
-       if ((rc = ov511_write_regvals(dev, aRegvalsNorm))) goto error;
-       if ((rc = ov511_mode_init_regs(ov511, DEFAULT_WIDTH, DEFAULT_HEIGHT,
-                                      VIDEO_PALETTE_RGB24, 0)) < 0) goto error;
+
+       if (ov511->sensor == SEN_OV7620) {
+               if (ov511_write_regvals(dev, aRegvalsNorm7620)) goto error;
+       }
+       else {
+               if (ov511_write_regvals(dev, aRegvalsNorm7610)) goto error;
+       }
+
+       if (ov511_mode_init_regs(ov511, DEFAULT_WIDTH, DEFAULT_HEIGHT,
+                                      VIDEO_PALETTE_RGB24, 0) < 0) goto error;
 
        if (autoadjust) {
                if (ov511_i2c_write(dev, 0x13, 0x01) < 0) goto error;
-               if (ov511_i2c_write(dev, 0x2d, 0x93) < 0) goto error;
+               if (ov511_i2c_write(dev, 0x2d, 
+                    ov511->sensor==SEN_OV7620?0x91:0x93) < 0) goto error;
        }
        else {
                if (ov511_i2c_write(dev, 0x13, 0x00) < 0) goto error;
-               if (ov511_i2c_write(dev, 0x2d, 0x83) < 0) goto error;
+               if (ov511_i2c_write(dev, 0x2d, 
+                    ov511->sensor==SEN_OV7620?0x81:0x83) < 0) goto error;
                ov511_i2c_write(dev, 0x28, ov511_i2c_read(dev, 0x28) | 8);
        }
 
@@ -2207,7 +2316,7 @@
                usb_unlink_urb(ov511->sbuf[0].urb);
                usb_free_urb(ov511->sbuf[0].urb);
                ov511->sbuf[0].urb = NULL;
-       }       
+       }
 
        /* Free the memory */
        if (!ov511->user) {

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to