]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] ov511 1.62 for 2.5.34
authorMark W. McClelland <mark@alpha.dyndns.org>
Mon, 16 Sep 2002 06:28:01 +0000 (23:28 -0700)
committerGreg Kroah-Hartman <greg@kroah.com>
Mon, 16 Sep 2002 06:28:01 +0000 (23:28 -0700)
 Update the ov511 driver to version 1.62:
 o Update email address
 o Remove some dead code and fix some harmless typos
 o New device: Alpha Vision Tech. AlphaCam SE
 o Fix assignment of ov->proc_button->owner to not cause
   NULL pointer deref (credit: Oleg K.)
 o Support I2C read/write ioctl()s via V4L (credit: Oleg K.)
 o Add OV518-specific register dump code
 o New snapshot reset sequence; old one was causing
   erroneous I2C writes (credit: Oleg K.)
 o OV6630 needs different register 0x14 settings than OV6620
 o Don't print palette errors by default
 o Detect OV518 cameras that have packet numbering enabled
   by default and set ov->packet_numbering accordingly. This
   should fix the problems some users were having with babble
   (USB error -75) and cameras not working at all.

Documentation/usb/ov511.txt
drivers/usb/media/ov511.c
drivers/usb/media/ov511.h

index 4c33f949dfb0a99873ef2cd8c8aca3cab63c59fe..8c36ebe503fb7a64cf9ba52b0f762d3f746e89cc 100644 (file)
@@ -105,15 +105,6 @@ MODULE PARAMETERS:
           4=most function calls and data parsing messages
           5=highly repetitive mesgs
 
-  NAME: fix_rgb_offset
-  TYPE: integer (Boolean)
-  DEFAULT: 0
-  DESC: Some people have reported that the blue component of the image is one
-        or so lines higher than the red component. This is only apparent in 
-        images with white objects on black backgrounds at 640x480. Setting this
-        to 1 will realign the color planes correctly. NOTE: You will likely
-        need a fast (500 MHz) CPU.
-
   NAME: snapshot
   TYPE: integer (Boolean)
   DEFAULT: 0
@@ -121,13 +112,6 @@ MODULE PARAMETERS:
        the snapshot button is pressed. Note: enabling this mode disables
        /proc/video/ov511/<minor#>/button
 
-  NAME: force_rgb      (Deprecated; may be removed in the future)
-  TYPE: integer (Boolean)
-  DEFAULT: 0
-  DESC: Force image to be read in RGB instead of BGR. This option allow
-        programs that expect RGB data (e.g. gqcam) to work with this driver. If
-        your colors look VERY wrong, you may want to change this.
-
   NAME: cams
   TYPE: integer (1-4 for OV511, 1-31 for OV511+)
   DEFAULT: 1
@@ -234,12 +218,7 @@ MODULE PARAMETERS:
        greyscale mode with a color camera, for example. Supported modes are:
                0                           (Allows all the following formats)
                1   VIDEO_PALETTE_GREY      (Linear greyscale)
-               3   VIDEO_PALETTE_RGB565    (565 16 bit RGB)
-               4   VIDEO_PALETTE_RGB24     (24bit RGB)
-               7   VIDEO_PALETTE_YUV422    (YUV422 capture)
-               8   VIDEO_PALETTE_YUYV      (YUV422 capture; same as 7)
                10  VIDEO_PALETTE_YUV420    (YUV 4:2:0 Planar)
-               13  VIDEO_PALETTE_YUV422P   (YUV 4:2:2 Planar)
                15  VIDEO_PALETTE_YUV420P   (YUV 4:2:0 Planar, same as 10)
 
   NAME: backlight
@@ -278,29 +257,17 @@ MODULE PARAMETERS:
 
 WORKING FEATURES:
  o Color streaming/capture at most widths and heights that are multiples of 8.
- o RGB24, RGB565, YUV420/YUV420P, YUV422/YUYV, and YUV422P color
  o Monochrome (use force_palette=1 to enable)
  o Setting/getting of saturation, contrast, brightness, and hue (only some of
    them work the OV7620 and OV7620AE)
  o /proc status reporting
  o SAA7111A video capture support at 320x240 and 640x480
  o Compression support
-
-EXPERIMENTAL FEATURES:
- o OV518/OV518+ support
- o OV6630 sensor support
- o Banding filter
  o SMP compatibility
 
-TO-DO:
- o V4L2 support (This will be done after the next kernel patch release)
- o Setting of hue not working with OV7620
- o Setting of contrast and hue not working with OV7620AE
- o OV8600 sensor support (Not used in anything yet)
-
 HOW TO CONTACT ME:
 
-You can email me at mmcclell@bigfoot.com . Please prefix the subject line
+You can email me at mark@alpha.dyndns.org . Please prefix the subject line
 with "OV511: " so that I am certain to notice your message.
 
 CREDITS:
index 9dff57ad4f38e1f7a82ef2443ed316d50a596b69..b98c6c4292b34990602607292a016292e728ee9a 100644 (file)
@@ -60,9 +60,9 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.61 for Linux 2.5"
-#define EMAIL "mmcclell@bigfoot.com"
-#define DRIVER_AUTHOR "Mark McClelland <mmcclell@bigfoot.com> & Bret Wallach \
+#define DRIVER_VERSION "v1.62 for Linux 2.5"
+#define EMAIL "mark@alpha.dyndns.org"
+#define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org> & Bret Wallach \
        & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \
        <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"
 #define DRIVER_DESC "ov511 USB Camera Driver"
@@ -97,7 +97,6 @@ static int snapshot;
 static int cams                        = 1;
 static int compress;
 static int testpat;
-static int sensor_gbr;
 static int dumppix;
 static int led                         = 1;
 static int dump_bridge;
@@ -113,16 +112,9 @@ static int qvy                     = 0x04;
 static int qvuv                        = 0x04;
 static int lightfreq;
 static int bandingfilter;
-
-/* Pixel clock divisor */
 static int clockdiv            = -1;
-
-/* Isoc packet size */
 static int packetsize          = -1;
-
-/* Frame drop register (16h) */
 static int framedrop           = -1;
-
 static int fastset;
 static int force_palette;
 static int backlight;
@@ -268,6 +260,7 @@ static struct symbolic_list camlist[] = {
        { 102, "AverMedia InterCam Elite" },
        { 112, "MediaForte MV300" },    /* or OV7110 evaluation kit */
        { 192, "Webeye 2000B" },
+       { 253, "Alpha Vision Tech. AlphaCam SE" },
        {  -1, NULL }
 };
 
@@ -558,8 +551,8 @@ create_proc_ov511_cam(struct usb_ov511 *ov)
                        ov511_read_proc_button, ov);
                if (!ov->proc_button)
                        return;
+               ov->proc_button->owner = THIS_MODULE;
        }
-       ov->proc_button->owner = THIS_MODULE;
 
        /* Create "control" entry (ioctl() interface) */
        PDEBUG(4, "creating /proc/video/ov511/%s/control", dirname);
@@ -1137,8 +1130,6 @@ i2c_set_slave_internal(struct usb_ov511 *ov, unsigned char slave)
        return 0;
 }
 
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-
 /* Write to a specific I2C slave ID and register, using the specified mask */
 static int
 i2c_w_slave(struct usb_ov511 *ov,
@@ -1194,8 +1185,6 @@ out:
        return rc;
 }
 
-#endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) */
-
 /* Sets I2C read and write slave IDs. Returns <0 for error */
 static int
 ov51x_set_slave_ids(struct usb_ov511 *ov, unsigned char sid)
@@ -1241,8 +1230,7 @@ write_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals)
 static void
 dump_i2c_range(struct usb_ov511 *ov, int reg1, int regn)
 {
-       int i;
-       int rc;
+       int i, rc;
 
        for (i = reg1; i <= regn; i++) {
                rc = i2c_r(ov, i);
@@ -1260,8 +1248,7 @@ dump_i2c_regs(struct usb_ov511 *ov)
 static void
 dump_reg_range(struct usb_ov511 *ov, int reg1, int regn)
 {
-       int i;
-       int rc;
+       int i, rc;
 
        for (i = reg1; i <= regn; i++) {
                rc = reg_r(ov, i);
@@ -1269,7 +1256,6 @@ dump_reg_range(struct usb_ov511 *ov, int reg1, int regn)
        }
 }
 
-/* FIXME: Should there be an OV518 version of this? */
 static void
 ov511_dump_regs(struct usb_ov511 *ov)
 {
@@ -1295,6 +1281,31 @@ ov511_dump_regs(struct usb_ov511 *ov)
        dump_reg_range(ov, 0xa0, 0xbf);
 
 }
+
+static void
+ov518_dump_regs(struct usb_ov511 *ov)
+{
+       info("VIDEO MODE REGS");
+       dump_reg_range(ov, 0x20, 0x2f);
+       info("DATA PUMP AND SNAPSHOT REGS");
+       dump_reg_range(ov, 0x30, 0x3f);
+       info("I2C REGS");
+       dump_reg_range(ov, 0x40, 0x4f);
+       info("SYSTEM CONTROL AND VENDOR REGS");
+       dump_reg_range(ov, 0x50, 0x5f);
+       info("60 - 6F");
+       dump_reg_range(ov, 0x60, 0x6f);
+       info("70 - 7F");
+       dump_reg_range(ov, 0x70, 0x7f);
+       info("Y QUANTIZATION TABLE");
+       dump_reg_range(ov, 0x80, 0x8f);
+       info("UV QUANTIZATION TABLE");
+       dump_reg_range(ov, 0x90, 0x9f);
+       info("A0 - BF");
+       dump_reg_range(ov, 0xa0, 0xbf);
+       info("CBR");
+       dump_reg_range(ov, 0xc0, 0xcf);
+}
 #endif
 
 /*****************************************************************************/
@@ -1336,9 +1347,9 @@ static void
 ov51x_clear_snapshot(struct usb_ov511 *ov)
 {
        if (ov->bclass == BCL_OV511) {
-               reg_w(ov, R51x_SYS_SNAP, 0x01);
-               reg_w(ov, R51x_SYS_SNAP, 0x03);
-               reg_w(ov, R51x_SYS_SNAP, 0x01);
+               reg_w(ov, R51x_SYS_SNAP, 0x00);
+               reg_w(ov, R51x_SYS_SNAP, 0x02);
+               reg_w(ov, R51x_SYS_SNAP, 0x00);
        } else if (ov->bclass == BCL_OV518) {
                warn("snapshot reset not supported yet on OV518(+)");
        } else {
@@ -1383,7 +1394,7 @@ init_ov_sensor(struct usb_ov511 *ov)
        if (i2c_w(ov, 0x12, 0x80) < 0) return -EIO;
 
        /* Wait for it to initialize */
-       schedule_timeout (1 + 150 * HZ / 1000);
+       schedule_timeout(1 + 150 * HZ / 1000);
 
        for (i = 0, success = 0; i < i2c_detect_tries && !success; i++) {
                if ((i2c_r(ov, OV7610_REG_ID_HIGH) == 0x7F) &&
@@ -2018,10 +2029,6 @@ sensor_get_picture(struct usb_ov511 *ov, struct video_picture *p)
 
        p->whiteness = 105 << 8;
 
-       /* Can we get these from frame[0]? -claudio? */
-       p->depth = ov->frame[0].depth;
-       p->palette = ov->frame[0].format;
-
        return 0;
 }
 
@@ -2424,9 +2431,10 @@ mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height,
 #endif
                break;
        case SEN_OV6620:
-       case SEN_OV6630:
                i2c_w(ov, 0x14, qvga?0x24:0x04);
-               /* No special settings yet */
+               break;
+       case SEN_OV6630:
+               i2c_w(ov, 0x14, qvga?0xa4:0x84);
                break;
        default:
                err("Invalid sensor");
@@ -2504,19 +2512,11 @@ mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height,
        if (framedrop >= 0)
                i2c_w(ov, 0x16, framedrop);
 
-       if (sensor_gbr)
-               i2c_w_mask(ov, 0x12, 0x08, 0x08);
-       else
-               i2c_w_mask(ov, 0x12, 0x00, 0x08);
-
        /* Test Pattern */
        i2c_w_mask(ov, 0x12, (testpat?0x02:0x00), 0x02);
 
-       /* Auto white balance */
-//     if (awb)
-               i2c_w_mask(ov, 0x12, 0x04, 0x04);
-//     else
-//             i2c_w_mask(ov, 0x12, 0x00, 0x04);
+       /* Enable auto white balance */
+       i2c_w_mask(ov, 0x12, 0x04, 0x04);
 
        // This will go away as soon as ov51x_mode_init_sensor_regs()
        // is fully tested.
@@ -2705,7 +2705,7 @@ ov511_mode_init_regs(struct usb_ov511 *ov,
        reg_w(ov, R511_CAM_PXDIV, 0x00);
        reg_w(ov, R511_CAM_LNDIV, 0x00);
 
-       /* YUV420, low pass filer on */
+       /* YUV420, low pass filter on */
        reg_w(ov, R511_CAM_OPTS, 0x03);
 
        /* Snapshot additions */
@@ -4120,11 +4120,6 @@ ov51x_alloc(struct usb_ov511 *ov)
        PDEBUG(4, "entered");
        down(&ov->buf_lock);
 
-       if (ov->buf_state == BUF_PEND_DEALLOC) {
-               ov->buf_state = BUF_ALLOCATED;
-               del_timer(&ov->buf_timer);
-       }
-
        if (ov->buf_state == BUF_ALLOCATED)
                goto out;
 
@@ -4394,6 +4389,10 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
                if (sensor_get_picture(ov, p))
                        return -EIO;
 
+               /* Can we get these from frame[0]? -claudio? */
+               p->depth = ov->frame[0].depth;
+               p->palette = ov->frame[0].format;
+
                return 0;
        }
        case VIDIOCSPICT:
@@ -4558,8 +4557,8 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
 
                depth = get_depth(vm->format);
                if (!depth) {
-                       err("VIDIOCMCAPTURE: invalid format (%s)",
-                           symbolic(v4l1_plist, vm->format));
+                       PDEBUG(2, "VIDIOCMCAPTURE: invalid format (%s)",
+                              symbolic(v4l1_plist, vm->format));
                        return -EINVAL;
                }
 
@@ -4580,8 +4579,8 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
                }
 
                if (force_palette && (vm->format != force_palette)) {
-                       info("palette rejected (%s)",
-                            symbolic(v4l1_plist, vm->format));
+                       PDEBUG(2, "palette rejected (%s)",
+                              symbolic(v4l1_plist, vm->format));
                        return -EINVAL;
                }
 
@@ -4710,6 +4709,24 @@ redo:
 
                return 0;
        }
+       case OV511IOC_WI2C:
+       {
+               struct ov511_i2c_struct *w = arg;
+
+               return i2c_w_slave(ov, w->slave, w->reg, w->value, w->mask);
+       }
+       case OV511IOC_RI2C:
+       {
+               struct ov511_i2c_struct *r = arg;
+               int rc;
+
+               rc = i2c_r_slave(ov, r->slave, r->reg);
+               if (rc < 0)
+                       return rc;
+
+               r->value = rc;
+               return 0;
+       }
        default:
                PDEBUG(3, "Unsupported IOCtl: 0x%X", cmd);
                return -ENOIOCTLCMD;
@@ -4934,11 +4951,11 @@ ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma)
 static struct file_operations ov511_fops = {
        .owner =        THIS_MODULE,
        .open =         ov51x_v4l1_open,
-       .release =      ov51x_v4l1_close,
+       .release =      ov51x_v4l1_close,
        .read =         ov51x_v4l1_read,
        .mmap =         ov51x_v4l1_mmap,
-       .ioctl =        ov51x_v4l1_ioctl,
-       .llseek =       no_llseek,
+       .ioctl =        ov51x_v4l1_ioctl,
+       .llseek =       no_llseek,
 };
 
 static struct video_device vdev_template = {
@@ -4946,7 +4963,7 @@ static struct video_device vdev_template = {
        .name =         "OV511 USB Camera",
        .type =         VID_TYPE_CAPTURE,
        .hardware =     VID_HARDWARE_OV511,
-       .fops =         &ov511_fops,
+       .fops =         &ov511_fops,
 };
 
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
@@ -5136,8 +5153,7 @@ ov51x_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                if (copy_from_user(&w, arg, sizeof(w)))
                        return -EFAULT;
 
-               return i2c_w_slave(ov, w.slave, w.reg, w.value,
-                       w.mask);
+               return i2c_w_slave(ov, w.slave, w.reg, w.value, w.mask);
        }
        case OV511IOC_RI2C:
        {
@@ -5343,17 +5359,16 @@ ov7xx0_configure(struct usb_ov511 *ov)
                ov->sensor = SEN_OV7610;
        } else if ((rc & 3) == 1) {
                /* I don't know what's different about the 76BE yet. */
-               if (i2c_r(ov, 0x15) & 1) {
+               if (i2c_r(ov, 0x15) & 1)
                        info("Sensor is an OV7620AE");
-               } else {
+               else
                        info("Sensor is an OV76BE");
-               }
 
                /* OV511+ will return all zero isoc data unless we
                 * configure the sensor as a 7620. Someone needs to
                 * find the exact reg. setting that causes this. */
                if (ov->bridge == BRG_OV511PLUS) {
-                       info("Enabling 511+/76BE workaround");
+                       info("Enabling 511+/7620AE workaround");
                        ov->sensor = SEN_OV7620;
                } else {
                        ov->sensor = SEN_OV76BE;
@@ -5745,9 +5760,9 @@ ov511_configure(struct usb_ov511 *ov)
 
        static struct ov511_regvals aRegvalsNorm511[] = {
                { OV511_REG_BUS, R511_DRAM_FLOW_CTL,    0x01 },
-               { OV511_REG_BUS, R51x_SYS_SNAP,         0x01 },
-               { OV511_REG_BUS, R51x_SYS_SNAP,         0x03 },
-               { OV511_REG_BUS, R51x_SYS_SNAP,         0x01 },
+               { OV511_REG_BUS, R51x_SYS_SNAP,         0x00 },
+               { OV511_REG_BUS, R51x_SYS_SNAP,         0x02 },
+               { OV511_REG_BUS, R51x_SYS_SNAP,         0x00 },
                { OV511_REG_BUS, R511_FIFO_OPTS,        0x1f },
                { OV511_REG_BUS, R511_COMP_EN,          0x00 },
                { OV511_REG_BUS, R511_COMP_LUT_EN,      0x03 },
@@ -5756,9 +5771,9 @@ ov511_configure(struct usb_ov511 *ov)
 
        static struct ov511_regvals aRegvalsNorm511Plus[] = {
                { OV511_REG_BUS, R511_DRAM_FLOW_CTL,    0xff },
-               { OV511_REG_BUS, R51x_SYS_SNAP,         0x01 },
-               { OV511_REG_BUS, R51x_SYS_SNAP,         0x03 },
-               { OV511_REG_BUS, R51x_SYS_SNAP,         0x01 },
+               { OV511_REG_BUS, R51x_SYS_SNAP,         0x00 },
+               { OV511_REG_BUS, R51x_SYS_SNAP,         0x02 },
+               { OV511_REG_BUS, R51x_SYS_SNAP,         0x00 },
                { OV511_REG_BUS, R511_FIFO_OPTS,        0xff },
                { OV511_REG_BUS, R511_COMP_EN,          0x00 },
                { OV511_REG_BUS, R511_COMP_LUT_EN,      0x03 },
@@ -5970,11 +5985,20 @@ ov518_configure(struct usb_ov511 *ov)
 
        if (ov518_init_compression(ov)) goto error;
 
-       /* OV518+ has packet numbering turned on by default */
        if (ov->bridge == BRG_OV518)
-               ov->packet_numbering = 0;
-       else
+       {
+               struct usb_interface *ifp = &ov->dev->config[0].interface[0];
+               __u16 mxps = ifp->altsetting[7].endpoint[0].wMaxPacketSize;
+
+               /* Some OV518s have packet numbering by default, some don't */
+               if (mxps == 897)
+                       ov->packet_numbering = 1;
+               else
+                       ov->packet_numbering = 0;
+       } else {
+               /* OV518+ has packet numbering turned on by default */
                ov->packet_numbering = 1;
+       }
 
        ov518_set_packet_size(ov, 0);
 
@@ -6126,7 +6150,8 @@ ov51x_probe(struct usb_device *dev, unsigned int ifnum,
 
        ov->buf_state = BUF_NOT_ALLOCATED;
 
-       /* Must be kmalloc()'ed, for DMA accessibility */
+       /* Allocate control transfer buffer. */
+       /* Must be kmalloc()'ed, for DMA compatibility */
        ov->cbuf = kmalloc(OV511_CBUF_SIZE, GFP_KERNEL);
        if (!ov->cbuf)
                goto error;
@@ -6156,8 +6181,12 @@ ov51x_probe(struct usb_device *dev, unsigned int ifnum,
                goto error;
 
 #ifdef OV511_DEBUG
-       if (dump_bridge)
-               ov511_dump_regs(ov);
+       if (dump_bridge) {
+               if (ov->bclass == BCL_OV511)
+                       ov511_dump_regs(ov);
+               else
+                       ov518_dump_regs(ov);
+       }
 #endif
 
        memcpy(&ov->vdev, &vdev_template, sizeof(vdev_template));
@@ -6259,12 +6288,14 @@ ov51x_disconnect(struct usb_device *dev, void *ptr)
                kfree(ov);
                ov = NULL;
        }
+
+       PDEBUG(3, "Disconnect complete");
 }
 
 static struct usb_driver ov511_driver = {
        .owner =        THIS_MODULE,
        .name =         "ov511",
-       .id_table =     device_table,
+       .id_table =     device_table,
        .probe =        ov51x_probe,
        .disconnect =   ov51x_disconnect
 };
index 20e4011b1794f9fab513ef584929524eb81349cb..9fa16de5bb317571dfe13b99337035c3836cc5c2 100644 (file)
@@ -286,21 +286,6 @@ enum {
        SEN_SAA7111A,
 };
 
-// Not implemented yet
-#if 0
-/* Sensor classes */
-enum {
-       SCL_UNKNOWN,
-       SCL_OV7610,     /* 7610, 76BE, 7620AE (for now) */
-       SCL_OV7620,
-       SCL_OV6620,     
-       SCL_OV6630,     /* 6630, 6630AE, 6630AF */
-       SCL_OV8600,
-       SCL_KS0127,     /* SEN_KS0127, SEN_KS0127B */
-       SCL_SAA7111A,
-};
-#endif
-
 enum {
        STATE_SCANNING,         /* Scanning for start */
        STATE_HEADER,           /* Parsing header */
@@ -311,7 +296,6 @@ enum {
 enum {
        BUF_NOT_ALLOCATED,
        BUF_ALLOCATED,
-       BUF_PEND_DEALLOC,       /* ov511->buf_timer is set */
 };
 
 /* --------- Definition of ioctl interface --------- */
@@ -521,7 +505,6 @@ struct usb_ov511 {
        int bridge;             /* Type of bridge (BRG_*) */
        int bclass;             /* Class of bridge (BCL_*) */
        int sensor;             /* Type of image sensor chip (SEN_*) */
-       int sclass;             /* Type of image sensor chip (SCL_*) */
 
        int packet_size;        /* Frame size per isoc desc */
        int packet_numbering;   /* Is ISO frame numbering enabled? */
@@ -537,7 +520,6 @@ struct usb_ov511 {
        /* Framebuffer/sbuf management */
        int buf_state;
        struct semaphore buf_lock;
-       struct timer_list buf_timer;
 
        struct ov51x_decomp_ops *decomp_ops;