X-Git-Url: https://git.karo-electronics.de/?p=mv-sheeva.git;a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fgspca%2Fov519.c;fp=drivers%2Fmedia%2Fvideo%2Fgspca%2Fov519.c;h=8ab2c452c25effdba21d956e494bbe6b7ea3ff39;hp=6cf6855aa5067456e20ee7d5842825530e91eedf;hb=92d62d098f574ed70b26548e6a2e2f67025864dc;hpb=690c12d2c8ca50e55a3f507059c780ecdb8fd83f diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 6cf6855aa50..8ab2c452c25 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c @@ -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 }, {} };