Merge branch 'devicetree/merge' into spi/merge
[pandora-kernel.git] / drivers / media / video / gspca / ov519.c
index 6cf6855..8ab2c45 100644 (file)
@@ -75,14 +75,14 @@ struct sd {
 
        struct gspca_ctrl ctrls[NCTRL];
 
-       __u8 packet_nr;
+       u8 packet_nr;
 
        char bridge;
 #define BRIDGE_OV511           0
 #define BRIDGE_OV511PLUS       1
 #define BRIDGE_OV518           2
 #define BRIDGE_OV518PLUS       3
-#define BRIDGE_OV519           4
+#define BRIDGE_OV519           4               /* = ov530 */
 #define BRIDGE_OVFX2           5
 #define BRIDGE_W9968CF         6
 #define BRIDGE_MASK            7
@@ -94,42 +94,44 @@ struct sd {
        char snapshot_needs_reset;
 
        /* Determined by sensor type */
-       __u8 sif;
+       u8 sif;
 
-       __u8 quality;
+       u8 quality;
 #define QUALITY_MIN 50
 #define QUALITY_MAX 70
 #define QUALITY_DEF 50
 
-       __u8 stopped;           /* Streaming is temporarily paused */
-       __u8 first_frame;
-
-       __u8 frame_rate;        /* current Framerate */
-       __u8 clockdiv;          /* clockdiv override */
-
-       char sensor;            /* Type of image sensor chip (SEN_*) */
-#define SEN_UNKNOWN 0
-#define SEN_OV2610 1
-#define SEN_OV3610 2
-#define SEN_OV6620 3
-#define SEN_OV6630 4
-#define SEN_OV66308AF 5
-#define SEN_OV7610 6
-#define SEN_OV7620 7
-#define SEN_OV7620AE 8
-#define SEN_OV7640 9
-#define SEN_OV7648 10
-#define SEN_OV7670 11
-#define SEN_OV76BE 12
-#define SEN_OV8610 13
+       u8 stopped;             /* Streaming is temporarily paused */
+       u8 first_frame;
+
+       u8 frame_rate;          /* current Framerate */
+       u8 clockdiv;            /* clockdiv override */
+
+       s8 sensor;              /* Type of image sensor chip (SEN_*) */
 
        u8 sensor_addr;
-       int sensor_width;
-       int sensor_height;
-       int sensor_reg_cache[256];
+       u16 sensor_width;
+       u16 sensor_height;
+       s16 sensor_reg_cache[256];
 
        u8 jpeg_hdr[JPEG_HDR_SZ];
 };
+enum sensors {
+       SEN_OV2610,
+       SEN_OV3610,
+       SEN_OV6620,
+       SEN_OV6630,
+       SEN_OV66308AF,
+       SEN_OV7610,
+       SEN_OV7620,
+       SEN_OV7620AE,
+       SEN_OV7640,
+       SEN_OV7648,
+       SEN_OV7660,
+       SEN_OV7670,
+       SEN_OV76BE,
+       SEN_OV8610,
+};
 
 /* Note this is a bit of a hack, but the w9968cf driver needs the code for all
    the ov sensors which is already present here. When we have the time we
@@ -182,7 +184,7 @@ static const struct ctrl sd_ctrls[] = {
            },
            .set_control = setcolors,
        },
-/* The flip controls work with ov7670 only */
+/* The flip controls work for sensors ov7660 and ov7670 only */
 [HFLIP] = {
            {
                .id      = V4L2_CID_HFLIP,
@@ -225,7 +227,7 @@ static const struct ctrl sd_ctrls[] = {
                .type    = V4L2_CTRL_TYPE_MENU,
                .name    = "Light frequency filter",
                .minimum = 0,
-               .maximum = 2,   /* 0: 0, 1: 50Hz, 2:60Hz */
+               .maximum = 2,   /* 0: no flicker, 1: 50Hz, 2:60Hz, 3: auto */
                .step    = 1,
                .default_value = 0,
            },
@@ -233,6 +235,53 @@ static const struct ctrl sd_ctrls[] = {
        },
 };
 
+/* table of the disabled controls */
+static const unsigned ctrl_dis[] = {
+[SEN_OV2610] =         (1 << NCTRL) - 1,       /* no control */
+
+[SEN_OV3610] =         (1 << NCTRL) - 1,       /* no control */
+
+[SEN_OV6620] =         (1 << HFLIP) |
+                       (1 << VFLIP),
+
+[SEN_OV6630] =         (1 << HFLIP) |
+                       (1 << VFLIP),
+
+[SEN_OV66308AF] =      (1 << HFLIP) |
+                       (1 << VFLIP),
+
+[SEN_OV7610] =         (1 << HFLIP) |
+                       (1 << VFLIP),
+
+[SEN_OV7620] =         (1 << HFLIP) |
+                       (1 << VFLIP),
+
+[SEN_OV7620AE] =       (1 << HFLIP) |
+                       (1 << VFLIP),
+
+[SEN_OV7640] =         (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << AUTOBRIGHT) |
+                       (1 << CONTRAST),
+
+[SEN_OV7648] =         (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << AUTOBRIGHT) |
+                       (1 << CONTRAST),
+
+[SEN_OV7660] =         (1 << AUTOBRIGHT),
+
+[SEN_OV7670] =         (1 << COLORS) |
+                       (1 << AUTOBRIGHT),
+
+[SEN_OV76BE] =         (1 << HFLIP) |
+                       (1 << VFLIP),
+
+[SEN_OV8610] =         (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+};
+
 static const struct v4l2_pix_format ov519_vga_mode[] = {
        {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
                .bytesperline = 320,
@@ -412,7 +461,6 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
                .priv = 0},
 };
 
-
 /* Registers common to OV511 / OV518 */
 #define R51x_FIFO_PSIZE                        0x30    /* 2 bytes wide w/ OV518(+) */
 #define R51x_SYS_RESET                 0x50
@@ -420,7 +468,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
        #define OV511_RESET_OMNICE      0x08
 #define R51x_SYS_INIT                  0x53
 #define R51x_SYS_SNAP                  0x52
-#define R51x_SYS_CUST_ID               0x5F
+#define R51x_SYS_CUST_ID               0x5f
 #define R51x_COMP_LUT_BEGIN            0x80
 
 /* OV511 Camera interface register numbers */
@@ -435,13 +483,12 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
 #define R511_CAM_OPTS                  0x18
 
 #define R511_SNAP_FRAME                        0x19
-#define R511_SNAP_PXCNT                        0x1A
-#define R511_SNAP_LNCNT                        0x1B
-#define R511_SNAP_PXDIV                        0x1C
-#define R511_SNAP_LNDIV                        0x1D
-#define R511_SNAP_UV_EN                        0x1E
-#define R511_SNAP_UV_EN                        0x1E
-#define R511_SNAP_OPTS                 0x1F
+#define R511_SNAP_PXCNT                        0x1a
+#define R511_SNAP_LNCNT                        0x1b
+#define R511_SNAP_PXDIV                        0x1c
+#define R511_SNAP_LNDIV                        0x1d
+#define R511_SNAP_UV_EN                        0x1e
+#define R511_SNAP_OPTS                 0x1f
 
 #define R511_DRAM_FLOW_CTL             0x20
 #define R511_FIFO_OPTS                 0x31
@@ -466,13 +513,14 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
 #define OV519_R25_FORMAT               0x25
 
 /* OV519 System Controller register numbers */
-#define OV519_SYS_RESET1 0x51
-#define OV519_SYS_EN_CLK1 0x54
+#define OV519_R51_RESET1               0x51
+#define OV519_R54_EN_CLK1              0x54
+#define OV519_R57_SNAPSHOT             0x57
 
 #define OV519_GPIO_DATA_OUT0           0x71
 #define OV519_GPIO_IO_CTRL0            0x72
 
-#define OV511_ENDPOINT_ADDRESS  1      /* Isoc endpoint number */
+/*#define OV511_ENDPOINT_ADDRESS 1      * Isoc endpoint number */
 
 /*
  * The FX2 chip does not give us a zero length read at end of frame.
@@ -526,80 +574,81 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
 #define OV7610_REG_ID_LOW      0x1d    /* manufacturer ID LSB */
 #define OV7610_REG_COM_I       0x29    /* misc settings */
 
-/* OV7670 registers */
-#define OV7670_REG_GAIN        0x00    /* Gain lower 8 bits (rest in vref) */
-#define OV7670_REG_BLUE        0x01    /* blue gain */
-#define OV7670_REG_RED         0x02    /* red gain */
-#define OV7670_REG_VREF        0x03    /* Pieces of GAIN, VSTART, VSTOP */
-#define OV7670_REG_COM1        0x04    /* Control 1 */
-#define OV7670_REG_AECHH       0x07    /* AEC MS 5 bits */
-#define OV7670_REG_COM3        0x0c    /* Control 3 */
-#define OV7670_REG_COM4        0x0d    /* Control 4 */
-#define OV7670_REG_COM5        0x0e    /* All "reserved" */
-#define OV7670_REG_COM6        0x0f    /* Control 6 */
-#define OV7670_REG_AECH        0x10    /* More bits of AEC value */
-#define OV7670_REG_CLKRC       0x11    /* Clock control */
-#define OV7670_REG_COM7        0x12    /* Control 7 */
-#define   OV7670_COM7_FMT_VGA    0x00
-#define   OV7670_COM7_YUV        0x00    /* YUV */
-#define   OV7670_COM7_FMT_QVGA   0x10    /* QVGA format */
-#define   OV7670_COM7_FMT_MASK   0x38
-#define   OV7670_COM7_RESET      0x80    /* Register reset */
-#define OV7670_REG_COM8        0x13    /* Control 8 */
-#define   OV7670_COM8_AEC        0x01    /* Auto exposure enable */
-#define   OV7670_COM8_AWB        0x02    /* White balance enable */
-#define   OV7670_COM8_AGC        0x04    /* Auto gain enable */
-#define   OV7670_COM8_BFILT      0x20    /* Band filter enable */
-#define   OV7670_COM8_AECSTEP    0x40    /* Unlimited AEC step size */
-#define   OV7670_COM8_FASTAEC    0x80    /* Enable fast AGC/AEC */
-#define OV7670_REG_COM9        0x14    /* Control 9  - gain ceiling */
-#define OV7670_REG_COM10       0x15    /* Control 10 */
-#define OV7670_REG_HSTART      0x17    /* Horiz start high bits */
-#define OV7670_REG_HSTOP       0x18    /* Horiz stop high bits */
-#define OV7670_REG_VSTART      0x19    /* Vert start high bits */
-#define OV7670_REG_VSTOP       0x1a    /* Vert stop high bits */
-#define OV7670_REG_MVFP        0x1e    /* Mirror / vflip */
-#define   OV7670_MVFP_VFLIP     0x10    /* vertical flip */
-#define   OV7670_MVFP_MIRROR     0x20    /* Mirror image */
-#define OV7670_REG_AEW         0x24    /* AGC upper limit */
-#define OV7670_REG_AEB         0x25    /* AGC lower limit */
-#define OV7670_REG_VPT         0x26    /* AGC/AEC fast mode op region */
-#define OV7670_REG_HREF        0x32    /* HREF pieces */
-#define OV7670_REG_TSLB        0x3a    /* lots of stuff */
-#define OV7670_REG_COM11       0x3b    /* Control 11 */
-#define   OV7670_COM11_EXP       0x02
-#define   OV7670_COM11_HZAUTO    0x10    /* Auto detect 50/60 Hz */
-#define OV7670_REG_COM12       0x3c    /* Control 12 */
-#define OV7670_REG_COM13       0x3d    /* Control 13 */
-#define   OV7670_COM13_GAMMA     0x80    /* Gamma enable */
-#define   OV7670_COM13_UVSAT     0x40    /* UV saturation auto adjustment */
-#define OV7670_REG_COM14       0x3e    /* Control 14 */
-#define OV7670_REG_EDGE        0x3f    /* Edge enhancement factor */
-#define OV7670_REG_COM15       0x40    /* Control 15 */
-#define   OV7670_COM15_R00FF     0xc0    /*            00 to FF */
-#define OV7670_REG_COM16       0x41    /* Control 16 */
-#define   OV7670_COM16_AWBGAIN   0x08    /* AWB gain enable */
-#define OV7670_REG_BRIGHT      0x55    /* Brightness */
-#define OV7670_REG_CONTRAS     0x56    /* Contrast control */
-#define OV7670_REG_GFIX        0x69    /* Fix gain control */
-#define OV7670_REG_RGB444      0x8c    /* RGB 444 control */
-#define OV7670_REG_HAECC1      0x9f    /* Hist AEC/AGC control 1 */
-#define OV7670_REG_HAECC2      0xa0    /* Hist AEC/AGC control 2 */
-#define OV7670_REG_BD50MAX     0xa5    /* 50hz banding step limit */
-#define OV7670_REG_HAECC3      0xa6    /* Hist AEC/AGC control 3 */
-#define OV7670_REG_HAECC4      0xa7    /* Hist AEC/AGC control 4 */
-#define OV7670_REG_HAECC5      0xa8    /* Hist AEC/AGC control 5 */
-#define OV7670_REG_HAECC6      0xa9    /* Hist AEC/AGC control 6 */
-#define OV7670_REG_HAECC7      0xaa    /* Hist AEC/AGC control 7 */
-#define OV7670_REG_BD60MAX     0xab    /* 60hz banding step limit */
+/* OV7660 and OV7670 registers */
+#define OV7670_R00_GAIN                0x00    /* Gain lower 8 bits (rest in vref) */
+#define OV7670_R01_BLUE                0x01    /* blue gain */
+#define OV7670_R02_RED         0x02    /* red gain */
+#define OV7670_R03_VREF                0x03    /* Pieces of GAIN, VSTART, VSTOP */
+#define OV7670_R04_COM1                0x04    /* Control 1 */
+/*#define OV7670_R07_AECHH     0x07     * AEC MS 5 bits */
+#define OV7670_R0C_COM3                0x0c    /* Control 3 */
+#define OV7670_R0D_COM4                0x0d    /* Control 4 */
+#define OV7670_R0E_COM5                0x0e    /* All "reserved" */
+#define OV7670_R0F_COM6                0x0f    /* Control 6 */
+#define OV7670_R10_AECH                0x10    /* More bits of AEC value */
+#define OV7670_R11_CLKRC       0x11    /* Clock control */
+#define OV7670_R12_COM7                0x12    /* Control 7 */
+#define   OV7670_COM7_FMT_VGA   0x00
+/*#define   OV7670_COM7_YUV     0x00    * YUV */
+#define   OV7670_COM7_FMT_QVGA  0x10   /* QVGA format */
+#define   OV7670_COM7_FMT_MASK  0x38
+#define   OV7670_COM7_RESET     0x80   /* Register reset */
+#define OV7670_R13_COM8                0x13    /* Control 8 */
+#define   OV7670_COM8_AEC       0x01   /* Auto exposure enable */
+#define   OV7670_COM8_AWB       0x02   /* White balance enable */
+#define   OV7670_COM8_AGC       0x04   /* Auto gain enable */
+#define   OV7670_COM8_BFILT     0x20   /* Band filter enable */
+#define   OV7670_COM8_AECSTEP   0x40   /* Unlimited AEC step size */
+#define   OV7670_COM8_FASTAEC   0x80   /* Enable fast AGC/AEC */
+#define OV7670_R14_COM9                0x14    /* Control 9 - gain ceiling */
+#define OV7670_R15_COM10       0x15    /* Control 10 */
+#define OV7670_R17_HSTART      0x17    /* Horiz start high bits */
+#define OV7670_R18_HSTOP       0x18    /* Horiz stop high bits */
+#define OV7670_R19_VSTART      0x19    /* Vert start high bits */
+#define OV7670_R1A_VSTOP       0x1a    /* Vert stop high bits */
+#define OV7670_R1E_MVFP                0x1e    /* Mirror / vflip */
+#define   OV7670_MVFP_VFLIP     0x10   /* vertical flip */
+#define   OV7670_MVFP_MIRROR    0x20   /* Mirror image */
+#define OV7670_R24_AEW         0x24    /* AGC upper limit */
+#define OV7670_R25_AEB         0x25    /* AGC lower limit */
+#define OV7670_R26_VPT         0x26    /* AGC/AEC fast mode op region */
+#define OV7670_R32_HREF                0x32    /* HREF pieces */
+#define OV7670_R3A_TSLB                0x3a    /* lots of stuff */
+#define OV7670_R3B_COM11       0x3b    /* Control 11 */
+#define   OV7670_COM11_EXP      0x02
+#define   OV7670_COM11_HZAUTO   0x10   /* Auto detect 50/60 Hz */
+#define OV7670_R3C_COM12       0x3c    /* Control 12 */
+#define OV7670_R3D_COM13       0x3d    /* Control 13 */
+#define   OV7670_COM13_GAMMA    0x80   /* Gamma enable */
+#define   OV7670_COM13_UVSAT    0x40   /* UV saturation auto adjustment */
+#define OV7670_R3E_COM14       0x3e    /* Control 14 */
+#define OV7670_R3F_EDGE                0x3f    /* Edge enhancement factor */
+#define OV7670_R40_COM15       0x40    /* Control 15 */
+/*#define   OV7670_COM15_R00FF  0xc0    *      00 to FF */
+#define OV7670_R41_COM16       0x41    /* Control 16 */
+#define   OV7670_COM16_AWBGAIN  0x08   /* AWB gain enable */
+/* end of ov7660 common registers */
+#define OV7670_R55_BRIGHT      0x55    /* Brightness */
+#define OV7670_R56_CONTRAS     0x56    /* Contrast control */
+#define OV7670_R69_GFIX                0x69    /* Fix gain control */
+/*#define OV7670_R8C_RGB444    0x8c     * RGB 444 control */
+#define OV7670_R9F_HAECC1      0x9f    /* Hist AEC/AGC control 1 */
+#define OV7670_RA0_HAECC2      0xa0    /* Hist AEC/AGC control 2 */
+#define OV7670_RA5_BD50MAX     0xa5    /* 50hz banding step limit */
+#define OV7670_RA6_HAECC3      0xa6    /* Hist AEC/AGC control 3 */
+#define OV7670_RA7_HAECC4      0xa7    /* Hist AEC/AGC control 4 */
+#define OV7670_RA8_HAECC5      0xa8    /* Hist AEC/AGC control 5 */
+#define OV7670_RA9_HAECC6      0xa9    /* Hist AEC/AGC control 6 */
+#define OV7670_RAA_HAECC7      0xaa    /* Hist AEC/AGC control 7 */
+#define OV7670_RAB_BD60MAX     0xab    /* 60hz banding step limit */
 
 struct ov_regvals {
-       __u8 reg;
-       __u8 val;
+       u8 reg;
+       u8 val;
 };
 struct ov_i2c_regvals {
-       __u8 reg;
-       __u8 val;
+       u8 reg;
+       u8 val;
 };
 
 /* Settings for OV2610 camera chip */
@@ -617,7 +666,6 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         * "wait 4096 external clock ... to make sure the sensor is
         * stable and ready to access registers" i.e. 160us at 24MHz
         */
-
        { 0x12, 0x80 }, /* COMH reset */
        { 0x12, 0x00 }, /* QXGA, master */
 
@@ -650,7 +698,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    COMI[0] "Exposure control"
         *                  =   0 (0x00) .......0 "Manual"
         */
-       { 0x13, 0xC0 },
+       { 0x13, 0xc0 },
 
        /*
         * 09 COMC "Common Control C"
@@ -706,7 +754,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    COME[0] "Auto zero circuit select"
         *                  =   1 (0x01) .......1 "On"
         */
-       { 0x0d, 0xA1 },
+       { 0x0d, 0xa1 },
 
        /*
         * 0E COMF "Common Control F"
@@ -770,7 +818,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    COMJ[0] "Reserved"
         *                  =   0 (0x00) .......0
         */
-       { 0x14, 0xC6 },
+       { 0x14, 0xc6 },
 
        /*
         * 15 COMK "Common Control K"
@@ -876,7 +924,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    FVOPT[7:0] "Range"
         *                  =  31 (0x1F) 00011111
         */
-       { 0x3c, 0x1F },
+       { 0x3c, 0x1f },
 
        /*
         * 44 Undocumented  =   0 (0x00) 00000000
@@ -925,7 +973,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    48[7:0] "It's a secret"
         *                  = 192 (0xC0) 11000000
         */
-       { 0x48, 0xC0 },
+       { 0x48, 0xc0 },
 
        /*
         * 49 Undocumented  =  25 (0x19) 00011001
@@ -939,18 +987,18 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    4B[7:0] "It's a secret"
         *                  = 128 (0x80) 10000000
         */
-       { 0x4B, 0x80 },
+       { 0x4b, 0x80 },
 
        /*
         * 4D Undocumented  = 196 (0xC4) 11000100
         *    4D[7:0] "It's a secret"
         *                  = 196 (0xC4) 11000100
         */
-       { 0x4D, 0xC4 },
+       { 0x4d, 0xc4 },
 
        /*
         * 35 VREF "Reference Voltage Control"
-        *                  =  76 (0x4C) 01001100
+        *                  =  76 (0x4c) 01001100
         *    VREF[7:5] "Column high reference control"
         *                  =   2 (0x02) 010..... "higher voltage"
         *    VREF[4:2] "Column low reference control"
@@ -958,21 +1006,21 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    VREF[1:0] "Reserved"
         *                  =   0 (0x00) ......00
         */
-       { 0x35, 0x4C },
+       { 0x35, 0x4c },
 
        /*
         * 3D Undocumented  =   0 (0x00) 00000000
         *    3D[7:0] "It's a secret"
         *                  =   0 (0x00) 00000000
         */
-       { 0x3D, 0x00 },
+       { 0x3d, 0x00 },
 
        /*
         * 3E Undocumented  =   0 (0x00) 00000000
         *    3E[7:0] "It's a secret"
         *                  =   0 (0x00) 00000000
         */
-       { 0x3E, 0x00 },
+       { 0x3e, 0x00 },
 
        /*
         * 3B FREFB "Internal Reference Adjustment"
@@ -1012,7 +1060,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    VBLM[3:0] "Sensor current control"
         *                  =  10 (0x0A) ....1010
         */
-       { 0x34, 0x5A },
+       { 0x34, 0x5a },
 
        /*
         * 3B FREFB "Internal Reference Adjustment"
@@ -1078,7 +1126,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    HREFST[7:0] "Horizontal window start, 8 MSBs"
         *                  =  31 (0x1F) 00011111
         */
-       { 0x17, 0x1F },
+       { 0x17, 0x1f },
 
        /*
         * 18 HREFEND "Horizontal window end"
@@ -1086,7 +1134,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
         *                  =  95 (0x5F) 01011111
         */
-       { 0x18, 0x5F },
+       { 0x18, 0x5f },
 
        /*
         * 19 VSTRT "Vertical window start"
@@ -1126,7 +1174,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    COMA[1:0] "Vertical window start line control 2 LSBs"
         *                  =   2 (0x02) ......10
         */
-       { 0x03, 0x4A },
+       { 0x03, 0x4a },
 
        /*
         * 11 CLKRC "Clock Rate Control"
@@ -1183,7 +1231,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    HREFST[7:0] "Horizontal window start, 8 MSBs"
         *                  =  31 (0x1F) 00011111
         */
-       { 0x17, 0x1F },
+       { 0x17, 0x1f },
 
        /*
         * 18 HREFEND "Horizontal window end"
@@ -1191,7 +1239,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
         *                  =  95 (0x5F) 01011111
         */
-       { 0x18, 0x5F },
+       { 0x18, 0x5f },
 
        /*
         * 19 VSTRT "Vertical window start"
@@ -1231,7 +1279,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    COMA[1:0] "Vertical window start line control 2 LSBs"
         *                  =   2 (0x02) ......10
         */
-       { 0x03, 0x4A },
+       { 0x03, 0x4a },
 
        /*
         * 02 RED "Red Gain Control"
@@ -1241,7 +1289,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    RED[6:0] "Value"
         *                  =  47 (0x2F) .0101111
         */
-       { 0x02, 0xAF },
+       { 0x02, 0xaf },
 
        /*
         * 2D ADDVSL "VSYNC Pulse Width"
@@ -1249,7 +1297,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    ADDVSL[7:0] "VSYNC pulse width, LSB"
         *                  = 210 (0xD2) 11010010
         */
-       { 0x2d, 0xD2 },
+       { 0x2d, 0xd2 },
 
        /*
         * 00 GAIN          =  24 (0x18) 00011000
@@ -1272,7 +1320,7 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    BLUE[6:0] "Value"
         *                  = 112 (0x70) .1110000
         */
-       { 0x01, 0xF0 },
+       { 0x01, 0xf0 },
 
        /*
         * 10 AEC "Automatic Exposure Control"
@@ -1280,14 +1328,14 @@ static const struct ov_i2c_regvals norm_3620b[] = {
         *    AEC[7:0] "Automatic Exposure Control, 8 MSBs"
         *                  =  10 (0x0A) 00001010
         */
-       { 0x10, 0x0A },
-
-       { 0xE1, 0x67 },
-       { 0xE3, 0x03 },
-       { 0xE4, 0x26 },
-       { 0xE5, 0x3E },
-       { 0xF8, 0x01 },
-       { 0xFF, 0x01 },
+       { 0x10, 0x0a },
+
+       { 0xe1, 0x67 },
+       { 0xe3, 0x03 },
+       { 0xe4, 0x26 },
+       { 0xe5, 0x3e },
+       { 0xf8, 0x01 },
+       { 0xff, 0x01 },
 };
 
 static const struct ov_i2c_regvals norm_6x20[] = {
@@ -1296,7 +1344,7 @@ static const struct ov_i2c_regvals norm_6x20[] = {
        { 0x03, 0x60 },
        { 0x05, 0x7f }, /* For when autoadjust is off */
        { 0x07, 0xa8 },
-       /* The ratio of 0x0c and 0x0d  controls the white point */
+       /* The ratio of 0x0c and 0x0d controls the white point */
        { 0x0c, 0x24 },
        { 0x0d, 0x24 },
        { 0x0f, 0x15 }, /* COMS */
@@ -1464,7 +1512,7 @@ static const struct ov_i2c_regvals norm_7620[] = {
        { 0x00, 0x00 },         /* gain */
        { 0x01, 0x80 },         /* blue gain */
        { 0x02, 0x80 },         /* red gain */
-       { 0x03, 0xc0 },         /* OV7670_REG_VREF */
+       { 0x03, 0xc0 },         /* OV7670_R03_VREF */
        { 0x06, 0x60 },
        { 0x07, 0x00 },
        { 0x0c, 0x24 },
@@ -1532,33 +1580,177 @@ static const struct ov_i2c_regvals norm_7640[] = {
        { 0x12, 0x14 },
 };
 
+static const struct ov_regvals init_519_ov7660[] = {
+       { 0x5d, 0x03 }, /* Turn off suspend mode */
+       { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */
+       { 0x54, 0x0f }, /* bit2 (jpeg enable) */
+       { 0xa2, 0x20 }, /* a2-a5 are undocumented */
+       { 0xa3, 0x18 },
+       { 0xa4, 0x04 },
+       { 0xa5, 0x28 },
+       { 0x37, 0x00 }, /* SetUsbInit */
+       { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
+       /* Enable both fields, YUV Input, disable defect comp (why?) */
+       { 0x20, 0x0c }, /* 0x0d does U <-> V swap */
+       { 0x21, 0x38 },
+       { 0x22, 0x1d },
+       { 0x17, 0x50 }, /* undocumented */
+       { 0x37, 0x00 }, /* undocumented */
+       { 0x40, 0xff }, /* I2C timeout counter */
+       { 0x46, 0x00 }, /* I2C clock prescaler */
+};
+static const struct ov_i2c_regvals norm_7660[] = {
+       {OV7670_R12_COM7, OV7670_COM7_RESET},
+       {OV7670_R11_CLKRC, 0x81},
+       {0x92, 0x00},                   /* DM_LNL */
+       {0x93, 0x00},                   /* DM_LNH */
+       {0x9d, 0x4c},                   /* BD50ST */
+       {0x9e, 0x3f},                   /* BD60ST */
+       {OV7670_R3B_COM11, 0x02},
+       {OV7670_R13_COM8, 0xf5},
+       {OV7670_R10_AECH, 0x00},
+       {OV7670_R00_GAIN, 0x00},
+       {OV7670_R01_BLUE, 0x7c},
+       {OV7670_R02_RED, 0x9d},
+       {OV7670_R12_COM7, 0x00},
+       {OV7670_R04_COM1, 00},
+       {OV7670_R18_HSTOP, 0x01},
+       {OV7670_R17_HSTART, 0x13},
+       {OV7670_R32_HREF, 0x92},
+       {OV7670_R19_VSTART, 0x02},
+       {OV7670_R1A_VSTOP, 0x7a},
+       {OV7670_R03_VREF, 0x00},
+       {OV7670_R0E_COM5, 0x04},
+       {OV7670_R0F_COM6, 0x62},
+       {OV7670_R15_COM10, 0x00},
+       {0x16, 0x02},                   /* RSVD */
+       {0x1b, 0x00},                   /* PSHFT */
+       {OV7670_R1E_MVFP, 0x01},
+       {0x29, 0x3c},                   /* RSVD */
+       {0x33, 0x00},                   /* CHLF */
+       {0x34, 0x07},                   /* ARBLM */
+       {0x35, 0x84},                   /* RSVD */
+       {0x36, 0x00},                   /* RSVD */
+       {0x37, 0x04},                   /* ADC */
+       {0x39, 0x43},                   /* OFON */
+       {OV7670_R3A_TSLB, 0x00},
+       {OV7670_R3C_COM12, 0x6c},
+       {OV7670_R3D_COM13, 0x98},
+       {OV7670_R3F_EDGE, 0x23},
+       {OV7670_R40_COM15, 0xc1},
+       {OV7670_R41_COM16, 0x22},
+       {0x6b, 0x0a},                   /* DBLV */
+       {0xa1, 0x08},                   /* RSVD */
+       {0x69, 0x80},                   /* HV */
+       {0x43, 0xf0},                   /* RSVD.. */
+       {0x44, 0x10},
+       {0x45, 0x78},
+       {0x46, 0xa8},
+       {0x47, 0x60},
+       {0x48, 0x80},
+       {0x59, 0xba},
+       {0x5a, 0x9a},
+       {0x5b, 0x22},
+       {0x5c, 0xb9},
+       {0x5d, 0x9b},
+       {0x5e, 0x10},
+       {0x5f, 0xe0},
+       {0x60, 0x85},
+       {0x61, 0x60},
+       {0x9f, 0x9d},                   /* RSVD */
+       {0xa0, 0xa0},                   /* DSPC2 */
+       {0x4f, 0x60},                   /* matrix */
+       {0x50, 0x64},
+       {0x51, 0x04},
+       {0x52, 0x18},
+       {0x53, 0x3c},
+       {0x54, 0x54},
+       {0x55, 0x40},
+       {0x56, 0x40},
+       {0x57, 0x40},
+       {0x58, 0x0d},                   /* matrix sign */
+       {0x8b, 0xcc},                   /* RSVD */
+       {0x8c, 0xcc},
+       {0x8d, 0xcf},
+       {0x6c, 0x40},                   /* gamma curve */
+       {0x6d, 0xe0},
+       {0x6e, 0xa0},
+       {0x6f, 0x80},
+       {0x70, 0x70},
+       {0x71, 0x80},
+       {0x72, 0x60},
+       {0x73, 0x60},
+       {0x74, 0x50},
+       {0x75, 0x40},
+       {0x76, 0x38},
+       {0x77, 0x3c},
+       {0x78, 0x32},
+       {0x79, 0x1a},
+       {0x7a, 0x28},
+       {0x7b, 0x24},
+       {0x7c, 0x04},                   /* gamma curve */
+       {0x7d, 0x12},
+       {0x7e, 0x26},
+       {0x7f, 0x46},
+       {0x80, 0x54},
+       {0x81, 0x64},
+       {0x82, 0x70},
+       {0x83, 0x7c},
+       {0x84, 0x86},
+       {0x85, 0x8e},
+       {0x86, 0x9c},
+       {0x87, 0xab},
+       {0x88, 0xc4},
+       {0x89, 0xd1},
+       {0x8a, 0xe5},
+       {OV7670_R14_COM9, 0x1e},
+       {OV7670_R24_AEW, 0x80},
+       {OV7670_R25_AEB, 0x72},
+       {OV7670_R26_VPT, 0xb3},
+       {0x62, 0x80},                   /* LCC1 */
+       {0x63, 0x80},                   /* LCC2 */
+       {0x64, 0x06},                   /* LCC3 */
+       {0x65, 0x00},                   /* LCC4 */
+       {0x66, 0x01},                   /* LCC5 */
+       {0x94, 0x0e},                   /* RSVD.. */
+       {0x95, 0x14},
+       {OV7670_R13_COM8, OV7670_COM8_FASTAEC
+                       | OV7670_COM8_AECSTEP
+                       | OV7670_COM8_BFILT
+                       | 0x10
+                       | OV7670_COM8_AGC
+                       | OV7670_COM8_AWB
+                       | OV7670_COM8_AEC},
+       {0xa1, 0xc8}
+};
+
 /* 7670. Defaults taken from OmniVision provided data,
 *  as provided by Jonathan Corbet of OLPC              */
 static const struct ov_i2c_regvals norm_7670[] = {
-       { OV7670_REG_COM7, OV7670_COM7_RESET },
-       { OV7670_REG_TSLB, 0x04 },              /* OV */
-       { OV7670_REG_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
-       { OV7670_REG_CLKRC, 0x01 },
+       { OV7670_R12_COM7, OV7670_COM7_RESET },
+       { OV7670_R3A_TSLB, 0x04 },              /* OV */
+       { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
+       { OV7670_R11_CLKRC, 0x01 },
 /*
  * Set the hardware window.  These values from OV don't entirely
  * make sense - hstop is less than hstart.  But they work...
  */
-       { OV7670_REG_HSTART, 0x13 },
-       { OV7670_REG_HSTOP, 0x01 },
-       { OV7670_REG_HREF, 0xb6 },
-       { OV7670_REG_VSTART, 0x02 },
-       { OV7670_REG_VSTOP, 0x7a },
-       { OV7670_REG_VREF, 0x0a },
-
-       { OV7670_REG_COM3, 0x00 },
-       { OV7670_REG_COM14, 0x00 },
+       { OV7670_R17_HSTART, 0x13 },
+       { OV7670_R18_HSTOP, 0x01 },
+       { OV7670_R32_HREF, 0xb6 },
+       { OV7670_R19_VSTART, 0x02 },
+       { OV7670_R1A_VSTOP, 0x7a },
+       { OV7670_R03_VREF, 0x0a },
+
+       { OV7670_R0C_COM3, 0x00 },
+       { OV7670_R3E_COM14, 0x00 },
 /* Mystery scaling numbers */
        { 0x70, 0x3a },
        { 0x71, 0x35 },
        { 0x72, 0x11 },
        { 0x73, 0xf0 },
        { 0xa2, 0x02 },
-/*     { OV7670_REG_COM10, 0x0 }, */
+/*     { OV7670_R15_COM10, 0x0 }, */
 
 /* Gamma curve values */
        { 0x7a, 0x20 },
@@ -1580,37 +1772,37 @@ static const struct ov_i2c_regvals norm_7670[] = {
 
 /* AGC and AEC parameters.  Note we start by disabling those features,
    then turn them only after tweaking the values. */
-       { OV7670_REG_COM8, OV7670_COM8_FASTAEC
+       { OV7670_R13_COM8, OV7670_COM8_FASTAEC
                         | OV7670_COM8_AECSTEP
                         | OV7670_COM8_BFILT },
-       { OV7670_REG_GAIN, 0x00 },
-       { OV7670_REG_AECH, 0x00 },
-       { OV7670_REG_COM4, 0x40 }, /* magic reserved bit */
-       { OV7670_REG_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
-       { OV7670_REG_BD50MAX, 0x05 },
-       { OV7670_REG_BD60MAX, 0x07 },
-       { OV7670_REG_AEW, 0x95 },
-       { OV7670_REG_AEB, 0x33 },
-       { OV7670_REG_VPT, 0xe3 },
-       { OV7670_REG_HAECC1, 0x78 },
-       { OV7670_REG_HAECC2, 0x68 },
+       { OV7670_R00_GAIN, 0x00 },
+       { OV7670_R10_AECH, 0x00 },
+       { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */
+       { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
+       { OV7670_RA5_BD50MAX, 0x05 },
+       { OV7670_RAB_BD60MAX, 0x07 },
+       { OV7670_R24_AEW, 0x95 },
+       { OV7670_R25_AEB, 0x33 },
+       { OV7670_R26_VPT, 0xe3 },
+       { OV7670_R9F_HAECC1, 0x78 },
+       { OV7670_RA0_HAECC2, 0x68 },
        { 0xa1, 0x03 }, /* magic */
-       { OV7670_REG_HAECC3, 0xd8 },
-       { OV7670_REG_HAECC4, 0xd8 },
-       { OV7670_REG_HAECC5, 0xf0 },
-       { OV7670_REG_HAECC6, 0x90 },
-       { OV7670_REG_HAECC7, 0x94 },
-       { OV7670_REG_COM8, OV7670_COM8_FASTAEC
+       { OV7670_RA6_HAECC3, 0xd8 },
+       { OV7670_RA7_HAECC4, 0xd8 },
+       { OV7670_RA8_HAECC5, 0xf0 },
+       { OV7670_RA9_HAECC6, 0x90 },
+       { OV7670_RAA_HAECC7, 0x94 },
+       { OV7670_R13_COM8, OV7670_COM8_FASTAEC
                        | OV7670_COM8_AECSTEP
                        | OV7670_COM8_BFILT
                        | OV7670_COM8_AGC
                        | OV7670_COM8_AEC },
 
 /* Almost all of these are magic "reserved" values.  */
-       { OV7670_REG_COM5, 0x61 },
-       { OV7670_REG_COM6, 0x4b },
+       { OV7670_R0E_COM5, 0x61 },
+       { OV7670_R0F_COM6, 0x4b },
        { 0x16, 0x02 },
-       { OV7670_REG_MVFP, 0x07 },
+       { OV7670_R1E_MVFP, 0x07 },
        { 0x21, 0x02 },
        { 0x22, 0x91 },
        { 0x29, 0x07 },
@@ -1619,10 +1811,10 @@ static const struct ov_i2c_regvals norm_7670[] = {
        { 0x37, 0x1d },
        { 0x38, 0x71 },
        { 0x39, 0x2a },
-       { OV7670_REG_COM12, 0x78 },
+       { OV7670_R3C_COM12, 0x78 },
        { 0x4d, 0x40 },
        { 0x4e, 0x20 },
-       { OV7670_REG_GFIX, 0x00 },
+       { OV7670_R69_GFIX, 0x00 },
        { 0x6b, 0x4a },
        { 0x74, 0x10 },
        { 0x8d, 0x4f },
@@ -1654,12 +1846,11 @@ static const struct ov_i2c_regvals norm_7670[] = {
        { 0x6c, 0x0a },
        { 0x6d, 0x55 },
        { 0x6e, 0x11 },
-       { 0x6f, 0x9f },
-                                       /* "9e for advance AWB" */
+       { 0x6f, 0x9f },                 /* "9e for advance AWB" */
        { 0x6a, 0x40 },
-       { OV7670_REG_BLUE, 0x40 },
-       { OV7670_REG_RED, 0x60 },
-       { OV7670_REG_COM8, OV7670_COM8_FASTAEC
+       { OV7670_R01_BLUE, 0x40 },
+       { OV7670_R02_RED, 0x60 },
+       { OV7670_R13_COM8, OV7670_COM8_FASTAEC
                        | OV7670_COM8_AECSTEP
                        | OV7670_COM8_BFILT
                        | OV7670_COM8_AGC
@@ -1675,22 +1866,22 @@ static const struct ov_i2c_regvals norm_7670[] = {
        { 0x54, 0x80 },
        { 0x58, 0x9e },
 
-       { OV7670_REG_COM16, OV7670_COM16_AWBGAIN },
-       { OV7670_REG_EDGE, 0x00 },
+       { OV7670_R41_COM16, OV7670_COM16_AWBGAIN },
+       { OV7670_R3F_EDGE, 0x00 },
        { 0x75, 0x05 },
        { 0x76, 0xe1 },
        { 0x4c, 0x00 },
        { 0x77, 0x01 },
-       { OV7670_REG_COM13, OV7670_COM13_GAMMA
+       { OV7670_R3D_COM13, OV7670_COM13_GAMMA
                          | OV7670_COM13_UVSAT
                          | 2},         /* was 3 */
        { 0x4b, 0x09 },
        { 0xc9, 0x60 },
-       { OV7670_REG_COM16, 0x38 },
+       { OV7670_R41_COM16, 0x38 },
        { 0x56, 0x40 },
 
        { 0x34, 0x11 },
-       { OV7670_REG_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
+       { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
        { 0xa4, 0x88 },
        { 0x96, 0x00 },
        { 0x97, 0x30 },
@@ -1825,10 +2016,13 @@ static unsigned char ov7670_abs_to_sm(unsigned char v)
 }
 
 /* Write a OV519 register */
-static int reg_w(struct sd *sd, __u16 index, __u16 value)
+static void reg_w(struct sd *sd, u16 index, u16 value)
 {
        int ret, req = 0;
 
+       if (sd->gspca_dev.usb_err < 0)
+               return;
+
        switch (sd->bridge) {
        case BRIDGE_OV511:
        case BRIDGE_OV511PLUS:
@@ -1838,6 +2032,8 @@ static int reg_w(struct sd *sd, __u16 index, __u16 value)
                req = 0x0a;
                /* fall through */
        case BRIDGE_W9968CF:
+               PDEBUG(D_USBO, "SET %02x %04x %04x",
+                               req, value, index);
                ret = usb_control_msg(sd->gspca_dev.dev,
                        usb_sndctrlpipe(sd->gspca_dev.dev, 0),
                        req,
@@ -1848,6 +2044,8 @@ static int reg_w(struct sd *sd, __u16 index, __u16 value)
                req = 1;
        }
 
+       PDEBUG(D_USBO, "SET %02x 0000 %04x %02x",
+                       req, index, value);
        sd->gspca_dev.usb_buf[0] = value;
        ret = usb_control_msg(sd->gspca_dev.dev,
                        usb_sndctrlpipe(sd->gspca_dev.dev, 0),
@@ -1857,22 +2055,22 @@ static int reg_w(struct sd *sd, __u16 index, __u16 value)
                        sd->gspca_dev.usb_buf, 1, 500);
 leave:
        if (ret < 0) {
-               err("Write reg 0x%04x -> [0x%02x] failed",
-                      value, index);
-               return ret;
+               err("reg_w %02x failed %d", index, ret);
+               sd->gspca_dev.usb_err = ret;
+               return;
        }
-
-       PDEBUG(D_USBO, "Write reg 0x%04x -> [0x%02x]", value, index);
-       return 0;
 }
 
 /* Read from a OV519 register, note not valid for the w9968cf!! */
 /* returns: negative is error, pos or zero is data */
-static int reg_r(struct sd *sd, __u16 index)
+static int reg_r(struct sd *sd, u16 index)
 {
        int ret;
        int req;
 
+       if (sd->gspca_dev.usb_err < 0)
+               return -1;
+
        switch (sd->bridge) {
        case BRIDGE_OV511:
        case BRIDGE_OV511PLUS:
@@ -1893,29 +2091,37 @@ static int reg_r(struct sd *sd, __u16 index)
 
        if (ret >= 0) {
                ret = sd->gspca_dev.usb_buf[0];
-               PDEBUG(D_USBI, "Read reg [0x%02X] -> 0x%04X", index, ret);
-       } else
-               err("Read reg [0x%02x] failed", index);
+               PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
+                       req, index, ret);
+       } else {
+               err("reg_r %02x failed %d", index, ret);
+               sd->gspca_dev.usb_err = ret;
+       }
 
        return ret;
 }
 
 /* Read 8 values from a OV519 register */
 static int reg_r8(struct sd *sd,
-                 __u16 index)
+                 u16 index)
 {
        int ret;
 
+       if (sd->gspca_dev.usb_err < 0)
+               return -1;
+
        ret = usb_control_msg(sd->gspca_dev.dev,
                        usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
                        1,                      /* REQ_IO */
                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                        0, index, sd->gspca_dev.usb_buf, 8, 500);
 
-       if (ret >= 0)
+       if (ret >= 0) {
                ret = sd->gspca_dev.usb_buf[0];
-       else
-               err("Read reg 8 [0x%02x] failed", index);
+       } else {
+               err("reg_r8 %02x failed %d", index, ret);
+               sd->gspca_dev.usb_err = ret;
+       }
 
        return ret;
 }
@@ -1926,34 +2132,37 @@ static int reg_r8(struct sd *sd,
  * that are in the same position as 0's in "mask" are preserved, regardless
  * of their respective state in "value".
  */
-static int reg_w_mask(struct sd *sd,
-                       __u16 index,
-                       __u8 value,
-                       __u8 mask)
+static void reg_w_mask(struct sd *sd,
+                       u16 index,
+                       u8 value,
+                       u8 mask)
 {
        int ret;
-       __u8 oldval;
+       u8 oldval;
 
        if (mask != 0xff) {
                value &= mask;                  /* Enforce mask on value */
                ret = reg_r(sd, index);
                if (ret < 0)
-                       return ret;
+                       return;
 
                oldval = ret & ~mask;           /* Clear the masked bits */
                value |= oldval;                /* Set the desired bits */
        }
-       return reg_w(sd, index, value);
+       reg_w(sd, index, value);
 }
 
 /*
  * Writes multiple (n) byte value to a single register. Only valid with certain
  * registers (0x30 and 0xc4 - 0xce).
  */
-static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n)
+static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
 {
        int ret;
 
+       if (sd->gspca_dev.usb_err < 0)
+               return;
+
        *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
 
        ret = usb_control_msg(sd->gspca_dev.dev,
@@ -1963,69 +2172,55 @@ static int ov518_reg_w32(struct sd *sd, __u16 index, u32 value, int n)
                        0, index,
                        sd->gspca_dev.usb_buf, n, 500);
        if (ret < 0) {
-               err("Write reg32 [%02x] %08x failed", index, value);
-               return ret;
+               err("reg_w32 %02x failed %d", index, ret);
+               sd->gspca_dev.usb_err = ret;
        }
-
-       return 0;
 }
 
-static int ov511_i2c_w(struct sd *sd, __u8 reg, __u8 value)
+static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
 {
        int rc, retries;
 
-       PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
+       PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value);
 
        /* Three byte write cycle */
        for (retries = 6; ; ) {
                /* Select camera register */
-               rc = reg_w(sd, R51x_I2C_SADDR_3, reg);
-               if (rc < 0)
-                       return rc;
+               reg_w(sd, R51x_I2C_SADDR_3, reg);
 
                /* Write "value" to I2C data port of OV511 */
-               rc = reg_w(sd, R51x_I2C_DATA, value);
-               if (rc < 0)
-                       return rc;
+               reg_w(sd, R51x_I2C_DATA, value);
 
                /* Initiate 3-byte write cycle */
-               rc = reg_w(sd, R511_I2C_CTL, 0x01);
-               if (rc < 0)
-                       return rc;
+               reg_w(sd, R511_I2C_CTL, 0x01);
 
                do {
                        rc = reg_r(sd, R511_I2C_CTL);
                } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
 
                if (rc < 0)
-                       return rc;
+                       return;
 
                if ((rc & 2) == 0) /* Ack? */
                        break;
                if (--retries < 0) {
                        PDEBUG(D_USBO, "i2c write retries exhausted");
-                       return -1;
+                       return;
                }
        }
-
-       return 0;
 }
 
-static int ov511_i2c_r(struct sd *sd, __u8 reg)
+static int ov511_i2c_r(struct sd *sd, u8 reg)
 {
        int rc, value, retries;
 
        /* Two byte write cycle */
        for (retries = 6; ; ) {
                /* Select camera register */
-               rc = reg_w(sd, R51x_I2C_SADDR_2, reg);
-               if (rc < 0)
-                       return rc;
+               reg_w(sd, R51x_I2C_SADDR_2, reg);
 
                /* Initiate 2-byte write cycle */
-               rc = reg_w(sd, R511_I2C_CTL, 0x03);
-               if (rc < 0)
-                       return rc;
+               reg_w(sd, R511_I2C_CTL, 0x03);
 
                do {
                        rc = reg_r(sd, R511_I2C_CTL);
@@ -2049,9 +2244,7 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg)
        /* Two byte read cycle */
        for (retries = 6; ; ) {
                /* Initiate 2-byte read cycle */
-               rc = reg_w(sd, R511_I2C_CTL, 0x05);
-               if (rc < 0)
-                       return rc;
+               reg_w(sd, R511_I2C_CTL, 0x05);
 
                do {
                        rc = reg_r(sd, R511_I2C_CTL);
@@ -2064,9 +2257,7 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg)
                        break;
 
                /* I2C abort */
-               rc = reg_w(sd, R511_I2C_CTL, 0x10);
-               if (rc < 0)
-                       return rc;
+               reg_w(sd, R511_I2C_CTL, 0x10);
 
                if (--retries < 0) {
                        PDEBUG(D_USBI, "i2c read retries exhausted");
@@ -2076,12 +2267,10 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg)
 
        value = reg_r(sd, R51x_I2C_DATA);
 
-       PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
+       PDEBUG(D_USBI, "ov511_i2c_r %02x %02x", reg, value);
 
        /* This is needed to make i2c_w() work */
-       rc = reg_w(sd, R511_I2C_CTL, 0x05);
-       if (rc < 0)
-               return rc;
+       reg_w(sd, R511_I2C_CTL, 0x05);
 
        return value;
 }
@@ -2091,32 +2280,24 @@ static int ov511_i2c_r(struct sd *sd, __u8 reg)
  * This is normally only called from i2c_w(). Note that this function
  * always succeeds regardless of whether the sensor is present and working.
  */
-static int ov518_i2c_w(struct sd *sd,
-               __u8 reg,
-               __u8 value)
+static void ov518_i2c_w(struct sd *sd,
+               u8 reg,
+               u8 value)
 {
-       int rc;
-
-       PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
+       PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value);
 
        /* Select camera register */
-       rc = reg_w(sd, R51x_I2C_SADDR_3, reg);
-       if (rc < 0)
-               return rc;
+       reg_w(sd, R51x_I2C_SADDR_3, reg);
 
        /* Write "value" to I2C data port of OV511 */
-       rc = reg_w(sd, R51x_I2C_DATA, value);
-       if (rc < 0)
-               return rc;
+       reg_w(sd, R51x_I2C_DATA, value);
 
        /* Initiate 3-byte write cycle */
-       rc = reg_w(sd, R518_I2C_CTL, 0x01);
-       if (rc < 0)
-               return rc;
+       reg_w(sd, R518_I2C_CTL, 0x01);
 
        /* wait for write complete */
        msleep(4);
-       return reg_r8(sd, R518_I2C_CTL);
+       reg_r8(sd, R518_I2C_CTL);
 }
 
 /*
@@ -2126,105 +2307,102 @@ static int ov518_i2c_w(struct sd *sd,
  * This is normally only called from i2c_r(). Note that this function
  * always succeeds regardless of whether the sensor is present and working.
  */
-static int ov518_i2c_r(struct sd *sd, __u8 reg)
+static int ov518_i2c_r(struct sd *sd, u8 reg)
 {
-       int rc, value;
+       int value;
 
        /* Select camera register */
-       rc = reg_w(sd, R51x_I2C_SADDR_2, reg);
-       if (rc < 0)
-               return rc;
+       reg_w(sd, R51x_I2C_SADDR_2, reg);
 
        /* Initiate 2-byte write cycle */
-       rc = reg_w(sd, R518_I2C_CTL, 0x03);
-       if (rc < 0)
-               return rc;
+       reg_w(sd, R518_I2C_CTL, 0x03);
 
        /* Initiate 2-byte read cycle */
-       rc = reg_w(sd, R518_I2C_CTL, 0x05);
-       if (rc < 0)
-               return rc;
+       reg_w(sd, R518_I2C_CTL, 0x05);
        value = reg_r(sd, R51x_I2C_DATA);
-       PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
+       PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value);
        return value;
 }
 
-static int ovfx2_i2c_w(struct sd *sd, __u8 reg, __u8 value)
+static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
 {
        int ret;
 
+       if (sd->gspca_dev.usb_err < 0)
+               return;
+
        ret = usb_control_msg(sd->gspca_dev.dev,
                        usb_sndctrlpipe(sd->gspca_dev.dev, 0),
                        0x02,
                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       (__u16)value, (__u16)reg, NULL, 0, 500);
+                       (u16) value, (u16) reg, NULL, 0, 500);
 
        if (ret < 0) {
-               err("i2c 0x%02x -> [0x%02x] failed", value, reg);
-               return ret;
+               err("ovfx2_i2c_w %02x failed %d", reg, ret);
+               sd->gspca_dev.usb_err = ret;
        }
 
-       PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
-       return 0;
+       PDEBUG(D_USBO, "ovfx2_i2c_w %02x %02x", reg, value);
 }
 
-static int ovfx2_i2c_r(struct sd *sd, __u8 reg)
+static int ovfx2_i2c_r(struct sd *sd, u8 reg)
 {
        int ret;
 
+       if (sd->gspca_dev.usb_err < 0)
+               return -1;
+
        ret = usb_control_msg(sd->gspca_dev.dev,
                        usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
                        0x03,
                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, (__u16)reg, sd->gspca_dev.usb_buf, 1, 500);
+                       0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500);
 
        if (ret >= 0) {
                ret = sd->gspca_dev.usb_buf[0];
-               PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, ret);
-       } else
-               err("i2c read [0x%02x] failed", reg);
+               PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
+       } else {
+               err("ovfx2_i2c_r %02x failed %d", reg, ret);
+               sd->gspca_dev.usb_err = ret;
+       }
 
        return ret;
 }
 
-static int i2c_w(struct sd *sd, __u8 reg, __u8 value)
+static void i2c_w(struct sd *sd, u8 reg, u8 value)
 {
-       int ret = -1;
-
        if (sd->sensor_reg_cache[reg] == value)
-               return 0;
+               return;
 
        switch (sd->bridge) {
        case BRIDGE_OV511:
        case BRIDGE_OV511PLUS:
-               ret = ov511_i2c_w(sd, reg, value);
+               ov511_i2c_w(sd, reg, value);
                break;
        case BRIDGE_OV518:
        case BRIDGE_OV518PLUS:
        case BRIDGE_OV519:
-               ret = ov518_i2c_w(sd, reg, value);
+               ov518_i2c_w(sd, reg, value);
                break;
        case BRIDGE_OVFX2:
-               ret = ovfx2_i2c_w(sd, reg, value);
+               ovfx2_i2c_w(sd, reg, value);
                break;
        case BRIDGE_W9968CF:
-               ret = w9968cf_i2c_w(sd, reg, value);
+               w9968cf_i2c_w(sd, reg, value);
                break;
        }
 
-       if (ret >= 0) {
+       if (sd->gspca_dev.usb_err >= 0) {
                /* Up on sensor reset empty the register cache */
                if (reg == 0x12 && (value & 0x80))
                        memset(sd->sensor_reg_cache, -1,
-                              sizeof(sd->sensor_reg_cache));
+                               sizeof(sd->sensor_reg_cache));
                else
                        sd->sensor_reg_cache[reg] = value;
        }
-
-       return ret;
 }
 
-static int i2c_r(struct sd *sd, __u8 reg)
+static int i2c_r(struct sd *sd, u8 reg)
 {
        int ret = -1;
 
@@ -2260,95 +2438,99 @@ static int i2c_r(struct sd *sd, __u8 reg)
  * that are in the same position as 0's in "mask" are preserved, regardless
  * of their respective state in "value".
  */
-static int i2c_w_mask(struct sd *sd,
-                  __u8 reg,
-                  __u8 value,
-                  __u8 mask)
+static void i2c_w_mask(struct sd *sd,
+                       u8 reg,
+                       u8 value,
+                       u8 mask)
 {
        int rc;
-       __u8 oldval;
+       u8 oldval;
 
        value &= mask;                  /* Enforce mask on value */
        rc = i2c_r(sd, reg);
        if (rc < 0)
-               return rc;
+               return;
        oldval = rc & ~mask;            /* Clear the masked bits */
        value |= oldval;                /* Set the desired bits */
-       return i2c_w(sd, reg, value);
+       i2c_w(sd, reg, value);
 }
 
 /* Temporarily stops OV511 from functioning. Must do this before changing
  * registers while the camera is streaming */
-static inline int ov51x_stop(struct sd *sd)
+static inline void ov51x_stop(struct sd *sd)
 {
        PDEBUG(D_STREAM, "stopping");
        sd->stopped = 1;
        switch (sd->bridge) {
        case BRIDGE_OV511:
        case BRIDGE_OV511PLUS:
-               return reg_w(sd, R51x_SYS_RESET, 0x3d);
+               reg_w(sd, R51x_SYS_RESET, 0x3d);
+               break;
        case BRIDGE_OV518:
        case BRIDGE_OV518PLUS:
-               return reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
+               reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
+               break;
        case BRIDGE_OV519:
-               return reg_w(sd, OV519_SYS_RESET1, 0x0f);
+               reg_w(sd, OV519_R51_RESET1, 0x0f);
+               reg_w(sd, OV519_R51_RESET1, 0x00);
+               reg_w(sd, 0x22, 0x00);          /* FRAR */
+               break;
        case BRIDGE_OVFX2:
-               return reg_w_mask(sd, 0x0f, 0x00, 0x02);
+               reg_w_mask(sd, 0x0f, 0x00, 0x02);
+               break;
        case BRIDGE_W9968CF:
-               return reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
+               reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
+               break;
        }
-
-       return 0;
 }
 
 /* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
  * actually stopped (for performance). */
-static inline int ov51x_restart(struct sd *sd)
+static inline void ov51x_restart(struct sd *sd)
 {
-       int rc;
-
        PDEBUG(D_STREAM, "restarting");
        if (!sd->stopped)
-               return 0;
+               return;
        sd->stopped = 0;
 
        /* Reinitialize the stream */
        switch (sd->bridge) {
        case BRIDGE_OV511:
        case BRIDGE_OV511PLUS:
-               return reg_w(sd, R51x_SYS_RESET, 0x00);
+               reg_w(sd, R51x_SYS_RESET, 0x00);
+               break;
        case BRIDGE_OV518:
        case BRIDGE_OV518PLUS:
-               rc = reg_w(sd, 0x2f, 0x80);
-               if (rc < 0)
-                       return rc;
-               return reg_w(sd, R51x_SYS_RESET, 0x00);
+               reg_w(sd, 0x2f, 0x80);
+               reg_w(sd, R51x_SYS_RESET, 0x00);
+               break;
        case BRIDGE_OV519:
-               return reg_w(sd, OV519_SYS_RESET1, 0x00);
+               reg_w(sd, OV519_R51_RESET1, 0x0f);
+               reg_w(sd, OV519_R51_RESET1, 0x00);
+               reg_w(sd, 0x22, 0x1d);          /* FRAR */
+               break;
        case BRIDGE_OVFX2:
-               return reg_w_mask(sd, 0x0f, 0x02, 0x02);
+               reg_w_mask(sd, 0x0f, 0x02, 0x02);
+               break;
        case BRIDGE_W9968CF:
-               return reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
+               reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
+               break;
        }
-
-       return 0;
 }
 
-static int ov51x_set_slave_ids(struct sd *sd, __u8 slave);
+static void ov51x_set_slave_ids(struct sd *sd, u8 slave);
 
 /* This does an initial reset of an OmniVision sensor and ensures that I2C
  * is synchronized. Returns <0 on failure.
  */
-static int init_ov_sensor(struct sd *sd, __u8 slave)
+static int init_ov_sensor(struct sd *sd, u8 slave)
 {
        int i;
 
-       if (ov51x_set_slave_ids(sd, slave) < 0)
-               return -EIO;
+       ov51x_set_slave_ids(sd, slave);
 
        /* Reset the sensor */
-       if (i2c_w(sd, 0x12, 0x80) < 0)
-               return -EIO;
+       i2c_w(sd, 0x12, 0x80);
 
        /* Wait for it to initialize */
        msleep(150);
@@ -2361,15 +2543,16 @@ static int init_ov_sensor(struct sd *sd, __u8 slave)
                }
 
                /* Reset the sensor */
-               if (i2c_w(sd, 0x12, 0x80) < 0)
-                       return -EIO;
+               i2c_w(sd, 0x12, 0x80);
+
                /* Wait for it to initialize */
                msleep(150);
+
                /* Dummy read to sync I2C */
                if (i2c_r(sd, 0x00) < 0)
-                       return -EIO;
+                       return -1;
        }
-       return -EIO;
+       return -1;
 }
 
 /* Set the read and write slave IDs. The "slave" argument is the write slave,
@@ -2377,53 +2560,40 @@ static int init_ov_sensor(struct sd *sd, __u8 slave)
  * This should not be called from outside the i2c I/O functions.
  * Sets I2C read and write slave IDs. Returns <0 for error
  */
-static int ov51x_set_slave_ids(struct sd *sd,
-                               __u8 slave)
+static void ov51x_set_slave_ids(struct sd *sd,
+                               u8 slave)
 {
-       int rc;
-
        switch (sd->bridge) {
        case BRIDGE_OVFX2:
-               return reg_w(sd, OVFX2_I2C_ADDR, slave);
+               reg_w(sd, OVFX2_I2C_ADDR, slave);
+               return;
        case BRIDGE_W9968CF:
                sd->sensor_addr = slave;
-               return 0;
+               return;
        }
 
-       rc = reg_w(sd, R51x_I2C_W_SID, slave);
-       if (rc < 0)
-               return rc;
-       return reg_w(sd, R51x_I2C_R_SID, slave + 1);
+       reg_w(sd, R51x_I2C_W_SID, slave);
+       reg_w(sd, R51x_I2C_R_SID, slave + 1);
 }
 
-static int write_regvals(struct sd *sd,
+static void write_regvals(struct sd *sd,
                         const struct ov_regvals *regvals,
                         int n)
 {
-       int rc;
-
        while (--n >= 0) {
-               rc = reg_w(sd, regvals->reg, regvals->val);
-               if (rc < 0)
-                       return rc;
+               reg_w(sd, regvals->reg, regvals->val);
                regvals++;
        }
-       return 0;
 }
 
-static int write_i2c_regvals(struct sd *sd,
-                            const struct ov_i2c_regvals *regvals,
-                            int n)
+static void write_i2c_regvals(struct sd *sd,
+                       const struct ov_i2c_regvals *regvals,
+                       int n)
 {
-       int rc;
-
        while (--n >= 0) {
-               rc = i2c_w(sd, regvals->reg, regvals->val);
-               if (rc < 0)
-                       return rc;
+               i2c_w(sd, regvals->reg, regvals->val);
                regvals++;
        }
-       return 0;
 }
 
 /****************************************************************************
@@ -2433,13 +2603,13 @@ static int write_i2c_regvals(struct sd *sd,
  ***************************************************************************/
 
 /* This initializes the OV2x10 / OV3610 / OV3620 */
-static int ov_hires_configure(struct sd *sd)
+static void ov_hires_configure(struct sd *sd)
 {
        int high, low;
 
        if (sd->bridge != BRIDGE_OVFX2) {
                err("error hires sensors only supported with ovfx2");
-               return -1;
+               return;
        }
 
        PDEBUG(D_PROBE, "starting ov hires configuration");
@@ -2455,20 +2625,15 @@ static int ov_hires_configure(struct sd *sd)
                PDEBUG(D_PROBE, "Sensor is an OV3610");
                sd->sensor = SEN_OV3610;
        } else {
-               err("Error unknown sensor type: 0x%02x%02x",
-                      high, low);
-               return -1;
+               err("Error unknown sensor type: %02x%02x",
+                       high, low);
        }
-
-       /* Set sensor-specific vars */
-       return 0;
 }
 
-
 /* This initializes the OV8110, OV8610 sensor. The OV8110 uses
  * the same register settings as the OV8610, since they are very similar.
  */
-static int ov8xx0_configure(struct sd *sd)
+static void ov8xx0_configure(struct sd *sd)
 {
        int rc;
 
@@ -2478,27 +2643,21 @@ static int ov8xx0_configure(struct sd *sd)
        rc = i2c_r(sd, OV7610_REG_COM_I);
        if (rc < 0) {
                PDEBUG(D_ERR, "Error detecting sensor type");
-               return -1;
+               return;
        }
-       if ((rc & 3) == 1) {
+       if ((rc & 3) == 1)
                sd->sensor = SEN_OV8610;
-       } else {
+       else
                err("Unknown image sensor version: %d", rc & 3);
-               return -1;
-       }
-
-       /* Set sensor-specific vars */
-       return 0;
 }
 
 /* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
  * the same register settings as the OV7610, since they are very similar.
  */
-static int ov7xx0_configure(struct sd *sd)
+static void ov7xx0_configure(struct sd *sd)
 {
        int rc, high, low;
 
-
        PDEBUG(D_PROBE, "starting OV7xx0 configuration");
 
        /* Detect sensor (sub)type */
@@ -2508,15 +2667,15 @@ static int ov7xx0_configure(struct sd *sd)
         * it appears to be wrongly detected as a 7610 by default */
        if (rc < 0) {
                PDEBUG(D_ERR, "Error detecting sensor type");
-               return -1;
+               return;
        }
        if ((rc & 3) == 3) {
                /* quick hack to make OV7670s work */
                high = i2c_r(sd, 0x0a);
                low = i2c_r(sd, 0x0b);
                /* info("%x, %x", high, low); */
-               if (high == 0x76 && low == 0x73) {
-                       PDEBUG(D_PROBE, "Sensor is an OV7670");
+               if (high == 0x76 && (low & 0xf0) == 0x70) {
+                       PDEBUG(D_PROBE, "Sensor is an OV76%02x", low);
                        sd->sensor = SEN_OV7670;
                } else {
                        PDEBUG(D_PROBE, "Sensor is an OV7610");
@@ -2536,19 +2695,19 @@ static int ov7xx0_configure(struct sd *sd)
                high = i2c_r(sd, 0x0a);
                if (high < 0) {
                        PDEBUG(D_ERR, "Error detecting camera chip PID");
-                       return high;
+                       return;
                }
                low = i2c_r(sd, 0x0b);
                if (low < 0) {
                        PDEBUG(D_ERR, "Error detecting camera chip VER");
-                       return low;
+                       return;
                }
                if (high == 0x76) {
                        switch (low) {
                        case 0x30:
                                err("Sensor is an OV7630/OV7635");
                                err("7630 is not supported by this driver");
-                               return -1;
+                               return;
                        case 0x40:
                                PDEBUG(D_PROBE, "Sensor is an OV7645");
                                sd->sensor = SEN_OV7640; /* FIXME */
@@ -2561,9 +2720,14 @@ static int ov7xx0_configure(struct sd *sd)
                                PDEBUG(D_PROBE, "Sensor is an OV7648");
                                sd->sensor = SEN_OV7648;
                                break;
+                       case 0x60:
+                               PDEBUG(D_PROBE, "Sensor is a OV7660");
+                               sd->sensor = SEN_OV7660;
+                               sd->invert_led = 0;
+                               break;
                        default:
                                PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
-                               return -1;
+                               return;
                        }
                } else {
                        PDEBUG(D_PROBE, "Sensor is an OV7620");
@@ -2571,15 +2735,11 @@ static int ov7xx0_configure(struct sd *sd)
                }
        } else {
                err("Unknown image sensor version: %d", rc & 3);
-               return -1;
        }
-
-       /* Set sensor-specific vars */
-       return 0;
 }
 
 /* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
-static int ov6xx0_configure(struct sd *sd)
+static void ov6xx0_configure(struct sd *sd)
 {
        int rc;
        PDEBUG(D_PROBE, "starting OV6xx0 configuration");
@@ -2588,7 +2748,7 @@ static int ov6xx0_configure(struct sd *sd)
        rc = i2c_r(sd, OV7610_REG_COM_I);
        if (rc < 0) {
                PDEBUG(D_ERR, "Error detecting sensor type");
-               return -1;
+               return;
        }
 
        /* Ugh. The first two bits are the version bits, but
@@ -2619,13 +2779,11 @@ static int ov6xx0_configure(struct sd *sd)
                break;
        default:
                err("FATAL: Unknown sensor version: 0x%02x", rc);
-               return -1;
+               return;
        }
 
        /* Set sensor-specific vars */
        sd->sif = 1;
-
-       return 0;
 }
 
 /* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
@@ -2637,14 +2795,14 @@ static void ov51x_led_control(struct sd *sd, int on)
        switch (sd->bridge) {
        /* OV511 has no LED control */
        case BRIDGE_OV511PLUS:
-               reg_w(sd, R511_SYS_LED_CTL, on ? 1 : 0);
+               reg_w(sd, R511_SYS_LED_CTL, on);
                break;
        case BRIDGE_OV518:
        case BRIDGE_OV518PLUS:
-               reg_w_mask(sd, R518_GPIO_OUT, on ? 0x02 : 0x00, 0x02);
+               reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02);
                break;
        case BRIDGE_OV519:
-               reg_w_mask(sd, OV519_GPIO_DATA_OUT0, !on, 1);   /* 0 / 1 */
+               reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1);
                break;
        }
 }
@@ -2679,7 +2837,7 @@ static void sd_reset_snapshot(struct gspca_dev *gspca_dev)
        }
 }
 
-static int ov51x_upload_quan_tables(struct sd *sd)
+static void ov51x_upload_quan_tables(struct sd *sd)
 {
        const unsigned char yQuanTable511[] = {
                0, 1, 1, 2, 2, 3, 3, 4,
@@ -2710,7 +2868,6 @@ static int ov51x_upload_quan_tables(struct sd *sd)
                6, 6, 6, 6, 7, 7, 7, 8,
                7, 7, 6, 7, 7, 7, 8, 8
        };
-
        const unsigned char uvQuanTable518[] = {
                6, 6, 6, 7, 7, 7, 7, 7,
                6, 6, 6, 7, 7, 7, 7, 7,
@@ -2720,18 +2877,18 @@ static int ov51x_upload_quan_tables(struct sd *sd)
 
        const unsigned char *pYTable, *pUVTable;
        unsigned char val0, val1;
-       int i, size, rc, reg = R51x_COMP_LUT_BEGIN;
+       int i, size, reg = R51x_COMP_LUT_BEGIN;
 
        PDEBUG(D_PROBE, "Uploading quantization tables");
 
        if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) {
                pYTable = yQuanTable511;
                pUVTable = uvQuanTable511;
-               size  = 32;
+               size = 32;
        } else {
                pYTable = yQuanTable518;
                pUVTable = uvQuanTable518;
-               size  = 16;
+               size = 16;
        }
 
        for (i = 0; i < size; i++) {
@@ -2740,30 +2897,23 @@ static int ov51x_upload_quan_tables(struct sd *sd)
                val0 &= 0x0f;
                val1 &= 0x0f;
                val0 |= val1 << 4;
-               rc = reg_w(sd, reg, val0);
-               if (rc < 0)
-                       return rc;
+               reg_w(sd, reg, val0);
 
                val0 = *pUVTable++;
                val1 = *pUVTable++;
                val0 &= 0x0f;
                val1 &= 0x0f;
                val0 |= val1 << 4;
-               rc = reg_w(sd, reg + size, val0);
-               if (rc < 0)
-                       return rc;
+               reg_w(sd, reg + size, val0);
 
                reg++;
        }
-
-       return 0;
 }
 
 /* This initializes the OV511/OV511+ and the sensor */
-static int ov511_configure(struct gspca_dev *gspca_dev)
+static void ov511_configure(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       int rc;
 
        /* For 511 and 511+ */
        const struct ov_regvals init_511[] = {
@@ -2809,42 +2959,27 @@ static int ov511_configure(struct gspca_dev *gspca_dev)
 
        PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID));
 
-       rc = write_regvals(sd, init_511, ARRAY_SIZE(init_511));
-       if (rc < 0)
-               return rc;
+       write_regvals(sd, init_511, ARRAY_SIZE(init_511));
 
        switch (sd->bridge) {
        case BRIDGE_OV511:
-               rc = write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
-               if (rc < 0)
-                       return rc;
+               write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
                break;
        case BRIDGE_OV511PLUS:
-               rc = write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
-               if (rc < 0)
-                       return rc;
+               write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
                break;
        }
 
        /* Init compression */
-       rc = write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
-       if (rc < 0)
-               return rc;
-
-       rc = ov51x_upload_quan_tables(sd);
-       if (rc < 0) {
-               PDEBUG(D_ERR, "Error uploading quantization tables");
-               return rc;
-       }
+       write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
 
-       return 0;
+       ov51x_upload_quan_tables(sd);
 }
 
 /* This initializes the OV518/OV518+ and the sensor */
-static int ov518_configure(struct gspca_dev *gspca_dev)
+static void ov518_configure(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       int rc;
 
        /* For 518 and 518+ */
        const struct ov_regvals init_518[] = {
@@ -2892,65 +3027,49 @@ static int ov518_configure(struct gspca_dev *gspca_dev)
 
        /* First 5 bits of custom ID reg are a revision ID on OV518 */
        PDEBUG(D_PROBE, "Device revision %d",
-              0x1F & reg_r(sd, R51x_SYS_CUST_ID));
+               0x1f & reg_r(sd, R51x_SYS_CUST_ID));
 
-       rc = write_regvals(sd, init_518, ARRAY_SIZE(init_518));
-       if (rc < 0)
-               return rc;
+       write_regvals(sd, init_518, ARRAY_SIZE(init_518));
 
        /* Set LED GPIO pin to output mode */
-       rc = reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
-       if (rc < 0)
-               return rc;
+       reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
 
        switch (sd->bridge) {
        case BRIDGE_OV518:
-               rc = write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
-               if (rc < 0)
-                       return rc;
+               write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
                break;
        case BRIDGE_OV518PLUS:
-               rc = write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
-               if (rc < 0)
-                       return rc;
+               write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
                break;
        }
 
-       rc = ov51x_upload_quan_tables(sd);
-       if (rc < 0) {
-               PDEBUG(D_ERR, "Error uploading quantization tables");
-               return rc;
-       }
+       ov51x_upload_quan_tables(sd);
 
-       rc = reg_w(sd, 0x2f, 0x80);
-       if (rc < 0)
-               return rc;
-
-       return 0;
+       reg_w(sd, 0x2f, 0x80);
 }
 
-static int ov519_configure(struct sd *sd)
+static void ov519_configure(struct sd *sd)
 {
        static const struct ov_regvals init_519[] = {
-               { 0x5a,  0x6d }, /* EnableSystem */
-               { 0x53,  0x9b },
-               { 0x54,  0xff }, /* set bit2 to enable jpeg */
-               { 0x5d,  0x03 },
-               { 0x49,  0x01 },
-               { 0x48,  0x00 },
+               { 0x5a, 0x6d }, /* EnableSystem */
+               { 0x53, 0x9b }, /* don't enable the microcontroller */
+               { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */
+               { 0x5d, 0x03 },
+               { 0x49, 0x01 },
+               { 0x48, 0x00 },
                /* Set LED pin to output mode. Bit 4 must be cleared or sensor
                 * detection will fail. This deserves further investigation. */
                { OV519_GPIO_IO_CTRL0,   0xee },
-               { 0x51,  0x0f }, /* SetUsbInit */
-               { 0x51,  0x00 },
-               { 0x22,  0x00 },
+               { OV519_R51_RESET1, 0x0f },
+               { OV519_R51_RESET1, 0x00 },
+               { 0x22, 0x00 },
                /* windows reads 0x55 at this point*/
        };
 
-       return write_regvals(sd, init_519, ARRAY_SIZE(init_519));
+       write_regvals(sd, init_519, ARRAY_SIZE(init_519));
 }
 
-static int ovfx2_configure(struct sd *sd)
+static void ovfx2_configure(struct sd *sd)
 {
        static const struct ov_regvals init_fx2[] = {
                { 0x00, 0x60 },
@@ -2964,7 +3083,92 @@ static int ovfx2_configure(struct sd *sd)
 
        sd->stopped = 1;
 
-       return write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2));
+       write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2));
+}
+
+/* set the mode */
+/* This function works for ov7660 only */
+static void ov519_set_mode(struct sd *sd)
+{
+       static const struct ov_regvals bridge_ov7660[2][10] = {
+               {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00},
+                {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
+                {0x25, 0x01}, {0x26, 0x00}},
+               {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00},
+                {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
+                {0x25, 0x03}, {0x26, 0x00}}
+       };
+       static const struct ov_i2c_regvals sensor_ov7660[2][3] = {
+               {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}},
+               {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}}
+       };
+       static const struct ov_i2c_regvals sensor_ov7660_2[] = {
+               {OV7670_R17_HSTART, 0x13},
+               {OV7670_R18_HSTOP, 0x01},
+               {OV7670_R32_HREF, 0x92},
+               {OV7670_R19_VSTART, 0x02},
+               {OV7670_R1A_VSTOP, 0x7a},
+               {OV7670_R03_VREF, 0x00},
+/*             {0x33, 0x00}, */
+/*             {0x34, 0x07}, */
+/*             {0x36, 0x00}, */
+/*             {0x6b, 0x0a}, */
+       };
+
+       write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode],
+                       ARRAY_SIZE(bridge_ov7660[0]));
+       write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode],
+                       ARRAY_SIZE(sensor_ov7660[0]));
+       write_i2c_regvals(sd, sensor_ov7660_2,
+                       ARRAY_SIZE(sensor_ov7660_2));
+}
+
+/* set the frame rate */
+/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */
+static void ov519_set_fr(struct sd *sd)
+{
+       int fr;
+       u8 clock;
+       /* frame rate table with indices:
+        *      - mode = 0: 320x240, 1: 640x480
+        *      - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5
+        *      - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock)
+        */
+       static const u8 fr_tb[2][6][3] = {
+               {{0x04, 0xff, 0x00},
+                {0x04, 0x1f, 0x00},
+                {0x04, 0x1b, 0x00},
+                {0x04, 0x15, 0x00},
+                {0x04, 0x09, 0x00},
+                {0x04, 0x01, 0x00}},
+               {{0x0c, 0xff, 0x00},
+                {0x0c, 0x1f, 0x00},
+                {0x0c, 0x1b, 0x00},
+                {0x04, 0xff, 0x01},
+                {0x04, 0x1f, 0x01},
+                {0x04, 0x1b, 0x01}},
+       };
+
+       if (frame_rate > 0)
+               sd->frame_rate = frame_rate;
+       if (sd->frame_rate >= 30)
+               fr = 0;
+       else if (sd->frame_rate >= 25)
+               fr = 1;
+       else if (sd->frame_rate >= 20)
+               fr = 2;
+       else if (sd->frame_rate >= 15)
+               fr = 3;
+       else if (sd->frame_rate >= 10)
+               fr = 4;
+       else
+               fr = 5;
+       reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]);
+       reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]);
+       clock = fr_tb[sd->gspca_dev.curr_mode][fr][2];
+       if (sd->sensor == SEN_OV7660)
+               clock |= 0x80;          /* enable double clock */
+       ov518_i2c_w(sd, OV7670_R11_CLKRC, clock);
 }
 
 /* this function is called at probe time */
@@ -2973,99 +3177,119 @@ static int sd_config(struct gspca_dev *gspca_dev,
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam = &gspca_dev->cam;
-       int ret = 0;
 
        sd->bridge = id->driver_info & BRIDGE_MASK;
-       sd->invert_led = id->driver_info & BRIDGE_INVERT_LED;
+       sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0;
 
        switch (sd->bridge) {
        case BRIDGE_OV511:
        case BRIDGE_OV511PLUS:
-               ret = ov511_configure(gspca_dev);
+               cam->cam_mode = ov511_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
                break;
        case BRIDGE_OV518:
        case BRIDGE_OV518PLUS:
-               ret = ov518_configure(gspca_dev);
+               cam->cam_mode = ov518_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
                break;
        case BRIDGE_OV519:
-               ret = ov519_configure(sd);
+               cam->cam_mode = ov519_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
+               sd->invert_led = !sd->invert_led;
                break;
        case BRIDGE_OVFX2:
-               ret = ovfx2_configure(sd);
+               cam->cam_mode = ov519_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
                cam->bulk_size = OVFX2_BULK_SIZE;
                cam->bulk_nurbs = MAX_NURBS;
                cam->bulk = 1;
                break;
        case BRIDGE_W9968CF:
-               ret = w9968cf_configure(sd);
+               cam->cam_mode = w9968cf_vga_mode;
+               cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
                cam->reverse_alts = 1;
                break;
        }
 
-       if (ret)
-               goto error;
+       gspca_dev->cam.ctrls = sd->ctrls;
+       sd->quality = QUALITY_DEF;
 
-       ov51x_led_control(sd, 0);       /* turn LED off */
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               ov511_configure(gspca_dev);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               ov518_configure(gspca_dev);
+               break;
+       case BRIDGE_OV519:
+               ov519_configure(sd);
+               break;
+       case BRIDGE_OVFX2:
+               ovfx2_configure(sd);
+               break;
+       case BRIDGE_W9968CF:
+               w9968cf_configure(sd);
+               break;
+       }
 
        /* The OV519 must be more aggressive about sensor detection since
         * I2C write will never fail if the sensor is not present. We have
         * to try to initialize the sensor to detect its presence */
+       sd->sensor = -1;
 
        /* Test for 76xx */
        if (init_ov_sensor(sd, OV7xx0_SID) >= 0) {
-               if (ov7xx0_configure(sd) < 0) {
-                       PDEBUG(D_ERR, "Failed to configure OV7xx0");
-                       goto error;
-               }
+               ov7xx0_configure(sd);
+
        /* Test for 6xx0 */
        } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) {
-               if (ov6xx0_configure(sd) < 0) {
-                       PDEBUG(D_ERR, "Failed to configure OV6xx0");
-                       goto error;
-               }
+               ov6xx0_configure(sd);
+
        /* Test for 8xx0 */
        } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) {
-               if (ov8xx0_configure(sd) < 0) {
-                       PDEBUG(D_ERR, "Failed to configure OV8xx0");
-                       goto error;
-               }
+               ov8xx0_configure(sd);
+
        /* Test for 3xxx / 2xxx */
        } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
-               if (ov_hires_configure(sd) < 0) {
-                       PDEBUG(D_ERR, "Failed to configure high res OV");
-                       goto error;
-               }
+               ov_hires_configure(sd);
        } else {
                err("Can't determine sensor slave IDs");
                goto error;
        }
 
+       if (sd->sensor < 0)
+               goto error;
+
+       ov51x_led_control(sd, 0);       /* turn LED off */
+
        switch (sd->bridge) {
        case BRIDGE_OV511:
        case BRIDGE_OV511PLUS:
-               if (!sd->sif) {
-                       cam->cam_mode = ov511_vga_mode;
-                       cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
-               } else {
+               if (sd->sif) {
                        cam->cam_mode = ov511_sif_mode;
                        cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
                }
                break;
        case BRIDGE_OV518:
        case BRIDGE_OV518PLUS:
-               if (!sd->sif) {
-                       cam->cam_mode = ov518_vga_mode;
-                       cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
-               } else {
+               if (sd->sif) {
                        cam->cam_mode = ov518_sif_mode;
                        cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
                }
                break;
        case BRIDGE_OV519:
-               if (!sd->sif) {
-                       cam->cam_mode = ov519_vga_mode;
-                       cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
-               } else {
+               if (sd->sif) {
                        cam->cam_mode = ov519_sif_mode;
                        cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
                }
@@ -3077,118 +3301,107 @@ static int sd_config(struct gspca_dev *gspca_dev,
                } else if (sd->sensor == SEN_OV3610) {
                        cam->cam_mode = ovfx2_ov3610_mode;
                        cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
-               } else if (!sd->sif) {
-                       cam->cam_mode = ov519_vga_mode;
-                       cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
-               } else {
+               } else if (sd->sif) {
                        cam->cam_mode = ov519_sif_mode;
                        cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
                }
                break;
        case BRIDGE_W9968CF:
-               cam->cam_mode = w9968cf_vga_mode;
-               cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
                if (sd->sif)
-                       cam->nmodes--;
+                       cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1;
 
                /* w9968cf needs initialisation once the sensor is known */
-               if (w9968cf_init(sd) < 0)
-                       goto error;
+               w9968cf_init(sd);
                break;
        }
-       gspca_dev->cam.ctrls = sd->ctrls;
-       if (sd->sensor == SEN_OV7670)
-               gspca_dev->ctrl_dis = 1 << COLORS;
-       else
-               gspca_dev->ctrl_dis = (1 << HFLIP) | (1 << VFLIP);
-       sd->quality = QUALITY_DEF;
-       if (sd->sensor == SEN_OV7640 ||
-           sd->sensor == SEN_OV7648)
-               gspca_dev->ctrl_dis |= (1 << AUTOBRIGHT) | (1 << CONTRAST);
-       if (sd->sensor == SEN_OV7670)
-               gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT;
-       /* OV8610 Frequency filter control should work but needs testing */
-       if (sd->sensor == SEN_OV8610)
-               gspca_dev->ctrl_dis |= 1 << FREQ;
-       /* No controls for the OV2610/OV3610 */
-       if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610)
-               gspca_dev->ctrl_dis |= (1 << NCTRL) - 1;
 
-       return 0;
-error:
-       PDEBUG(D_ERR, "OV519 Config failed");
-       return -EBUSY;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
+       gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
 
        /* initialize the sensor */
        switch (sd->sensor) {
        case SEN_OV2610:
-               if (write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610)))
-                       return -EIO;
+               write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610));
+
                /* Enable autogain, autoexpo, awb, bandfilter */
-               if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0)
-                       return -EIO;
+               i2c_w_mask(sd, 0x13, 0x27, 0x27);
                break;
        case SEN_OV3610:
-               if (write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b)))
-                       return -EIO;
+               write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b));
+
                /* Enable autogain, autoexpo, awb, bandfilter */
-               if (i2c_w_mask(sd, 0x13, 0x27, 0x27) < 0)
-                       return -EIO;
+               i2c_w_mask(sd, 0x13, 0x27, 0x27);
                break;
        case SEN_OV6620:
-               if (write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20)))
-                       return -EIO;
+               write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20));
                break;
        case SEN_OV6630:
        case SEN_OV66308AF:
                sd->ctrls[CONTRAST].def = 200;
                                 /* The default is too low for the ov6630 */
-               if (write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30)))
-                       return -EIO;
+               write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30));
                break;
        default:
 /*     case SEN_OV7610: */
 /*     case SEN_OV76BE: */
-               if (write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610)))
-                       return -EIO;
-               if (i2c_w_mask(sd, 0x0e, 0x00, 0x40))
-                       return -EIO;
+               write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610));
+               i2c_w_mask(sd, 0x0e, 0x00, 0x40);
                break;
        case SEN_OV7620:
        case SEN_OV7620AE:
-               if (write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620)))
-                       return -EIO;
+               write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620));
                break;
        case SEN_OV7640:
        case SEN_OV7648:
-               if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
-                       return -EIO;
+               write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640));
+               break;
+       case SEN_OV7660:
+               i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET);
+               msleep(14);
+               reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
+               write_regvals(sd, init_519_ov7660,
+                               ARRAY_SIZE(init_519_ov7660));
+               write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660));
+               sd->gspca_dev.curr_mode = 1;    /* 640x480 */
+               sd->frame_rate = 15;
+               ov519_set_mode(sd);
+               ov519_set_fr(sd);
+               sd->ctrls[COLORS].max = 4;      /* 0..4 */
+               sd->ctrls[COLORS].val =
+                       sd->ctrls[COLORS].def = 2;
+               setcolors(gspca_dev);
+               sd->ctrls[CONTRAST].max = 6;    /* 0..6 */
+               sd->ctrls[CONTRAST].val =
+                       sd->ctrls[CONTRAST].def = 3;
+               setcontrast(gspca_dev);
+               sd->ctrls[BRIGHTNESS].max = 6;  /* 0..6 */
+               sd->ctrls[BRIGHTNESS].val =
+                       sd->ctrls[BRIGHTNESS].def = 3;
+               setbrightness(gspca_dev);
+               sd_reset_snapshot(gspca_dev);
+               ov51x_restart(sd);
+               ov51x_stop(sd);                 /* not in win traces */
+               ov51x_led_control(sd, 0);
                break;
        case SEN_OV7670:
                sd->ctrls[FREQ].max = 3;        /* auto */
                sd->ctrls[FREQ].def = 3;
-               if (write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670)))
-                       return -EIO;
+               write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670));
                break;
        case SEN_OV8610:
-               if (write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610)))
-                       return -EIO;
+               write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610));
                break;
        }
-       return 0;
+       return gspca_dev->usb_err;
+error:
+       PDEBUG(D_ERR, "OV519 Config failed");
+       return -EINVAL;
 }
 
 /* Set up the OV511/OV511+ with the given image parameters.
  *
  * Do not put any sensor-specific code in here (including I2C I/O functions)
  */
-static int ov511_mode_init_regs(struct sd *sd)
+static void ov511_mode_init_regs(struct sd *sd)
 {
        int hsegs, vsegs, packet_size, fps, needed;
        int interlaced = 0;
@@ -3199,7 +3412,8 @@ static int ov511_mode_init_regs(struct sd *sd)
        alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
        if (!alt) {
                err("Couldn't get altsetting");
-               return -EIO;
+               sd->gspca_dev.usb_err = -EIO;
+               return;
        }
 
        packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
@@ -3302,8 +3516,6 @@ static int ov511_mode_init_regs(struct sd *sd)
 
        reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
        reg_w(sd, R51x_SYS_RESET, 0);
-
-       return 0;
 }
 
 /* Sets up the OV518/OV518+ with the given image parameters
@@ -3313,7 +3525,7 @@ static int ov511_mode_init_regs(struct sd *sd)
  *
  * Do not put any sensor-specific code in here (including I2C I/O functions)
  */
-static int ov518_mode_init_regs(struct sd *sd)
+static void ov518_mode_init_regs(struct sd *sd)
 {
        int hsegs, vsegs, packet_size;
        struct usb_host_interface *alt;
@@ -3323,14 +3535,14 @@ static int ov518_mode_init_regs(struct sd *sd)
        alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
        if (!alt) {
                err("Couldn't get altsetting");
-               return -EIO;
+               sd->gspca_dev.usb_err = -EIO;
+               return;
        }
 
        packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
        ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
 
        /******** Set the mode ********/
-
        reg_w(sd, 0x2b, 0);
        reg_w(sd, 0x2c, 0);
        reg_w(sd, 0x2d, 0);
@@ -3364,7 +3576,7 @@ static int ov518_mode_init_regs(struct sd *sd)
        /* Windows driver does this here; who knows why */
        reg_w(sd, 0x2f, 0x80);
 
-       /******** Set the framerate  ********/
+       /******** Set the framerate ********/
        sd->clockdiv = 1;
 
        /* Mode independent, but framerate dependent, regs */
@@ -3427,11 +3639,8 @@ static int ov518_mode_init_regs(struct sd *sd)
        }
 
        reg_w(sd, 0x2f, 0x80);
-
-       return 0;
 }
 
-
 /* Sets up the OV519 with the given image parameters
  *
  * OV519 needs a completely different approach, until we can figure out what
@@ -3439,12 +3648,12 @@ static int ov518_mode_init_regs(struct sd *sd)
  *
  * Do not put any sensor-specific code in here (including I2C I/O functions)
  */
-static int ov519_mode_init_regs(struct sd *sd)
+static void ov519_mode_init_regs(struct sd *sd)
 {
        static const struct ov_regvals mode_init_519_ov7670[] = {
                { 0x5d, 0x03 }, /* Turn off suspend mode */
                { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
-               { 0x54, 0x0f }, /* bit2 (jpeg enable) */
+               { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
                { 0xa2, 0x20 }, /* a2-a5 are undocumented */
                { 0xa3, 0x18 },
                { 0xa4, 0x04 },
@@ -3467,7 +3676,7 @@ static int ov519_mode_init_regs(struct sd *sd)
        static const struct ov_regvals mode_init_519[] = {
                { 0x5d, 0x03 }, /* Turn off suspend mode */
                { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
-               { 0x54, 0x0f }, /* bit2 (jpeg enable) */
+               { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
                { 0xa2, 0x20 }, /* a2-a5 are undocumented */
                { 0xa3, 0x18 },
                { 0xa4, 0x04 },
@@ -3486,19 +3695,21 @@ static int ov519_mode_init_regs(struct sd *sd)
        };
 
        /******** Set the mode ********/
-       if (sd->sensor != SEN_OV7670) {
-               if (write_regvals(sd, mode_init_519,
-                                 ARRAY_SIZE(mode_init_519)))
-                       return -EIO;
+       switch (sd->sensor) {
+       default:
+               write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519));
                if (sd->sensor == SEN_OV7640 ||
                    sd->sensor == SEN_OV7648) {
                        /* Select 8-bit input mode */
                        reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
                }
-       } else {
-               if (write_regvals(sd, mode_init_519_ov7670,
-                                 ARRAY_SIZE(mode_init_519_ov7670)))
-                       return -EIO;
+               break;
+       case SEN_OV7660:
+               return;         /* done by ov519_set_mode/fr() */
+       case SEN_OV7670:
+               write_regvals(sd, mode_init_519_ov7670,
+                               ARRAY_SIZE(mode_init_519_ov7670));
+               break;
        }
 
        reg_w(sd, OV519_R10_H_SIZE,     sd->gspca_dev.width >> 4);
@@ -3594,17 +3805,16 @@ static int ov519_mode_init_regs(struct sd *sd)
                }
                break;
        }
-       return 0;
 }
 
-static int mode_init_ov_sensor_regs(struct sd *sd)
+static void mode_init_ov_sensor_regs(struct sd *sd)
 {
        struct gspca_dev *gspca_dev;
        int qvga, xstart, xend, ystart, yend;
-       __u8 v;
+       u8 v;
 
        gspca_dev = &sd->gspca_dev;
-       qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1;
+       qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
 
        /******** Mode (VGA/QVGA) and sensor specific regs ********/
        switch (sd->sensor) {
@@ -3616,7 +3826,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
                i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
                i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
                i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
-               return 0;
+               return;
        case SEN_OV3610:
                if (qvga) {
                        xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4);
@@ -3640,7 +3850,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
                i2c_w(sd, 0x18, xend >> 4);
                i2c_w(sd, 0x19, ystart >> 3);
                i2c_w(sd, 0x1a, yend >> 3);
-               return 0;
+               return;
        case SEN_OV8610:
                /* For OV8610 qvga means qsvga */
                i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
@@ -3687,11 +3897,11 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
                /* set COM7_FMT_VGA or COM7_FMT_QVGA
                 * do we need to set anything else?
                 *      HSTART etc are set in set_ov_sensor_window itself */
-               i2c_w_mask(sd, OV7670_REG_COM7,
+               i2c_w_mask(sd, OV7670_R12_COM7,
                         qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA,
                         OV7670_COM7_FMT_MASK);
                i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
-               i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB,
+               i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB,
                                OV7670_COM8_AWB);
                if (qvga) {             /* QVGA from ov7670.c by
                                         * Jonathan Corbet */
@@ -3707,21 +3917,21 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
                }
                /* OV7670 hardware window registers are split across
                 * multiple locations */
-               i2c_w(sd, OV7670_REG_HSTART, xstart >> 3);
-               i2c_w(sd, OV7670_REG_HSTOP, xend >> 3);
-               v = i2c_r(sd, OV7670_REG_HREF);
+               i2c_w(sd, OV7670_R17_HSTART, xstart >> 3);
+               i2c_w(sd, OV7670_R18_HSTOP, xend >> 3);
+               v = i2c_r(sd, OV7670_R32_HREF);
                v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07);
                msleep(10);     /* need to sleep between read and write to
                                 * same reg! */
-               i2c_w(sd, OV7670_REG_HREF, v);
+               i2c_w(sd, OV7670_R32_HREF, v);
 
-               i2c_w(sd, OV7670_REG_VSTART, ystart >> 2);
-               i2c_w(sd, OV7670_REG_VSTOP, yend >> 2);
-               v = i2c_r(sd, OV7670_REG_VREF);
+               i2c_w(sd, OV7670_R19_VSTART, ystart >> 2);
+               i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2);
+               v = i2c_r(sd, OV7670_R03_VREF);
                v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03);
                msleep(10);     /* need to sleep between read and write to
                                 * same reg! */
-               i2c_w(sd, OV7670_REG_VREF, v);
+               i2c_w(sd, OV7670_R03_VREF, v);
                break;
        case SEN_OV6620:
                i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
@@ -3734,46 +3944,50 @@ static int mode_init_ov_sensor_regs(struct sd *sd)
                i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
                break;
        default:
-               return -EINVAL;
+               return;
        }
 
        /******** Clock programming ********/
        i2c_w(sd, 0x11, sd->clockdiv);
-
-       return 0;
 }
 
+/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */
 static void sethvflip(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       if (sd->sensor != SEN_OV7670)
-               return;
        if (sd->gspca_dev.streaming)
-               ov51x_stop(sd);
-       i2c_w_mask(sd, OV7670_REG_MVFP,
+               reg_w(sd, OV519_R51_RESET1, 0x0f);      /* block stream */
+       i2c_w_mask(sd, OV7670_R1E_MVFP,
                OV7670_MVFP_MIRROR * sd->ctrls[HFLIP].val
                        | OV7670_MVFP_VFLIP * sd->ctrls[VFLIP].val,
                OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
        if (sd->gspca_dev.streaming)
-               ov51x_restart(sd);
+               reg_w(sd, OV519_R51_RESET1, 0x00);      /* restart stream */
 }
 
-static int set_ov_sensor_window(struct sd *sd)
+static void set_ov_sensor_window(struct sd *sd)
 {
        struct gspca_dev *gspca_dev;
        int qvga, crop;
        int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
-       int ret;
 
        /* mode setup is fully handled in mode_init_ov_sensor_regs for these */
-       if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 ||
-           sd->sensor == SEN_OV7670)
-               return mode_init_ov_sensor_regs(sd);
+       switch (sd->sensor) {
+       case SEN_OV2610:
+       case SEN_OV3610:
+       case SEN_OV7670:
+               mode_init_ov_sensor_regs(sd);
+               return;
+       case SEN_OV7660:
+               ov519_set_mode(sd);
+               ov519_set_fr(sd);
+               return;
+       }
 
        gspca_dev = &sd->gspca_dev;
-       qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1;
-       crop = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 2;
+       qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
+       crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2;
 
        /* The different sensor ICs handle setting up of window differently.
         * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
@@ -3820,7 +4034,7 @@ static int set_ov_sensor_window(struct sd *sd)
                vwsbase = vwebase = 0x03;
                break;
        default:
-               return -EINVAL;
+               return;
        }
 
        switch (sd->sensor) {
@@ -3855,23 +4069,18 @@ static int set_ov_sensor_window(struct sd *sd)
                }
        }
 
-       ret = mode_init_ov_sensor_regs(sd);
-       if (ret < 0)
-               return ret;
+       mode_init_ov_sensor_regs(sd);
 
        i2c_w(sd, 0x17, hwsbase);
        i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale));
        i2c_w(sd, 0x19, vwsbase);
        i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale));
-
-       return 0;
 }
 
 /* -- start the camera -- */
 static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       int ret = 0;
 
        /* Default for most bridges, allow bridge_mode_init_regs to override */
        sd->sensor_width = sd->gspca_dev.width;
@@ -3880,50 +4089,46 @@ static int sd_start(struct gspca_dev *gspca_dev)
        switch (sd->bridge) {
        case BRIDGE_OV511:
        case BRIDGE_OV511PLUS:
-               ret = ov511_mode_init_regs(sd);
+               ov511_mode_init_regs(sd);
                break;
        case BRIDGE_OV518:
        case BRIDGE_OV518PLUS:
-               ret = ov518_mode_init_regs(sd);
+               ov518_mode_init_regs(sd);
                break;
        case BRIDGE_OV519:
-               ret = ov519_mode_init_regs(sd);
+               ov519_mode_init_regs(sd);
                break;
        /* case BRIDGE_OVFX2: nothing to do */
        case BRIDGE_W9968CF:
-               ret = w9968cf_mode_init_regs(sd);
+               w9968cf_mode_init_regs(sd);
                break;
        }
-       if (ret < 0)
-               goto out;
-
-       ret = set_ov_sensor_window(sd);
-       if (ret < 0)
-               goto out;
-
-       setcontrast(gspca_dev);
-       setbrightness(gspca_dev);
-       setcolors(gspca_dev);
-       sethvflip(gspca_dev);
-       setautobright(gspca_dev);
-       setfreq_i(sd);
+
+       set_ov_sensor_window(sd);
+
+       if (!(sd->gspca_dev.ctrl_dis & (1 << CONTRAST)))
+               setcontrast(gspca_dev);
+       if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS)))
+               setbrightness(gspca_dev);
+       if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS)))
+               setcolors(gspca_dev);
+       if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP))))
+               sethvflip(gspca_dev);
+       if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT)))
+               setautobright(gspca_dev);
+       if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ)))
+               setfreq_i(sd);
 
        /* Force clear snapshot state in case the snapshot button was
           pressed while we weren't streaming */
        sd->snapshot_needs_reset = 1;
        sd_reset_snapshot(gspca_dev);
-       sd->snapshot_pressed = 0;
 
        sd->first_frame = 3;
 
-       ret = ov51x_restart(sd);
-       if (ret < 0)
-               goto out;
+       ov51x_restart(sd);
        ov51x_led_control(sd, 1);
-       return 0;
-out:
-       PDEBUG(D_ERR, "camera start error:%d", ret);
-       return ret;
+       return gspca_dev->usb_err;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -3938,8 +4143,21 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
+       if (!sd->gspca_dev.present)
+               return;
        if (sd->bridge == BRIDGE_W9968CF)
                w9968cf_stop0(sd);
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       /* If the last button state is pressed, release it now! */
+       if (sd->snapshot_pressed) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               sd->snapshot_pressed = 0;
+       }
+#endif
+       if (sd->bridge == BRIDGE_OV519)
+               reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
 }
 
 static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state)
@@ -4160,6 +4378,22 @@ static void setbrightness(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int val;
+       static const struct ov_i2c_regvals brit_7660[][7] = {
+               {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90},
+                       {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}},
+               {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1},
+                       {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}},
+               {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2},
+                       {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}},
+               {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3},
+                       {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}},
+               {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3},
+                       {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}},
+               {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3},
+                       {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}},
+               {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4},
+                       {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}}
+       };
 
        val = sd->ctrls[BRIGHTNESS].val;
        switch (sd->sensor) {
@@ -4179,10 +4413,14 @@ static void setbrightness(struct gspca_dev *gspca_dev)
                if (!sd->ctrls[AUTOBRIGHT].val)
                        i2c_w(sd, OV7610_REG_BRT, val);
                break;
+       case SEN_OV7660:
+               write_i2c_regvals(sd, brit_7660[val],
+                               ARRAY_SIZE(brit_7660[0]));
+               break;
        case SEN_OV7670:
 /*win trace
- *             i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_AEC); */
-               i2c_w(sd, OV7670_REG_BRIGHT, ov7670_abs_to_sm(val));
+ *             i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */
+               i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val));
                break;
        }
 }
@@ -4191,6 +4429,64 @@ static void setcontrast(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int val;
+       static const struct ov_i2c_regvals contrast_7660[][31] = {
+               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0},
+                {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30},
+                {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24},
+                {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34},
+                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65},
+                {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83},
+                {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f},
+                {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}},
+               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94},
+                {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30},
+                {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24},
+                {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31},
+                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62},
+                {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81},
+                {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1},
+                {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}},
+               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84},
+                {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40},
+                {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24},
+                {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34},
+                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d},
+                {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81},
+                {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e},
+                {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}},
+               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70},
+                {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48},
+                {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34},
+                {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22},
+                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58},
+                {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80},
+                {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9},
+                {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}},
+               {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80},
+                {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60},
+                {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38},
+                {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e},
+                {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46},
+                {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c},
+                {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4},
+                {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}},
+               {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80},
+                {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30},
+                {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50},
+                {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08},
+                {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a},
+                {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b},
+                {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3},
+                {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}},
+               {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60},
+                {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8},
+                {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c},
+                {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04},
+                {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22},
+                {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b},
+                {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde},
+                {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}},
+       };
 
        val = sd->ctrls[CONTRAST].val;
        switch (sd->sensor) {
@@ -4203,7 +4499,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
                i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
                break;
        case SEN_OV8610: {
-               static const __u8 ctab[] = {
+               static const u8 ctab[] = {
                        0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
                };
 
@@ -4213,7 +4509,7 @@ static void setcontrast(struct gspca_dev *gspca_dev)
            }
        case SEN_OV7620:
        case SEN_OV7620AE: {
-               static const __u8 ctab[] = {
+               static const u8 ctab[] = {
                        0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
                        0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
                };
@@ -4222,9 +4518,13 @@ static void setcontrast(struct gspca_dev *gspca_dev)
                i2c_w(sd, 0x64, ctab[val >> 4]);
                break;
            }
+       case SEN_OV7660:
+               write_i2c_regvals(sd, contrast_7660[val],
+                                       ARRAY_SIZE(contrast_7660[0]));
+               break;
        case SEN_OV7670:
                /* check that this isn't just the same as ov7610 */
-               i2c_w(sd, OV7670_REG_CONTRAS, val >> 1);
+               i2c_w(sd, OV7670_R56_CONTRAS, val >> 1);
                break;
        }
 }
@@ -4233,6 +4533,18 @@ static void setcolors(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int val;
+       static const struct ov_i2c_regvals colors_7660[][6] = {
+               {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a},
+                {0x53, 0x19}, {0x54, 0x23}},
+               {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11},
+                {0x53, 0x2c}, {0x54, 0x3e}},
+               {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19},
+                {0x53, 0x40}, {0x54, 0x59}},
+               {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20},
+                {0x53, 0x53}, {0x54, 0x73}},
+               {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28},
+                {0x53, 0x66}, {0x54, 0x8e}},
+       };
 
        val = sd->ctrls[COLORS].val;
        switch (sd->sensor) {
@@ -4256,6 +4568,10 @@ static void setcolors(struct gspca_dev *gspca_dev)
        case SEN_OV7648:
                i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
                break;
+       case SEN_OV7660:
+               write_i2c_regvals(sd, colors_7660[val],
+                                       ARRAY_SIZE(colors_7660[0]));
+               break;
        case SEN_OV7670:
                /* supported later once I work out how to do it
                 * transparently fail now! */
@@ -4268,38 +4584,31 @@ static void setautobright(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648 ||
-           sd->sensor == SEN_OV7670 ||
-           sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610)
-               return;
-
        i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10);
 }
 
 static void setfreq_i(struct sd *sd)
 {
-       if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610)
-               return;
-
-       if (sd->sensor == SEN_OV7670) {
+       if (sd->sensor == SEN_OV7660
+        || sd->sensor == SEN_OV7670) {
                switch (sd->ctrls[FREQ].val) {
                case 0: /* Banding filter disabled */
-                       i2c_w_mask(sd, OV7670_REG_COM8, 0, OV7670_COM8_BFILT);
+                       i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT);
                        break;
                case 1: /* 50 hz */
-                       i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+                       i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
                                   OV7670_COM8_BFILT);
-                       i2c_w_mask(sd, OV7670_REG_COM11, 0x08, 0x18);
+                       i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18);
                        break;
                case 2: /* 60 hz */
-                       i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+                       i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
                                   OV7670_COM8_BFILT);
-                       i2c_w_mask(sd, OV7670_REG_COM11, 0x00, 0x18);
+                       i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18);
                        break;
-               case 3: /* Auto hz */
-                       i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_BFILT,
+               case 3: /* Auto hz - ov7670 only */
+                       i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
                                   OV7670_COM8_BFILT);
-                       i2c_w_mask(sd, OV7670_REG_COM11, OV7670_COM11_HZAUTO,
+                       i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO,
                                   0x18);
                        break;
                }
@@ -4436,21 +4745,21 @@ static const struct sd_desc sd_desc = {
 };
 
 /* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
+static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
        {USB_DEVICE(0x041e, 0x4052), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x041e, 0x4064),
-        .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
        {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x041e, 0x4068),
-        .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
        {USB_DEVICE(0x045e, 0x028c), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
        {USB_DEVICE(0x054c, 0x0155),
-        .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
        {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
        {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
        {USB_DEVICE(0x05a9, 0x0519), .driver_info = BRIDGE_OV519 },
@@ -4464,7 +4773,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
        {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 },
        {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 },
        {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF },
-       {USB_DEVICE(0x8020, 0xEF04), .driver_info = BRIDGE_OVFX2 },
+       {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 },
        {}
 };