aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/ov519.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2009-10-16 06:42:53 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:40:45 -0500
commitfb1f9020609ead93fcec4b0dd02511a46294c147 (patch)
tree867752434af3591fa3f57abaf315d8b40d3348b9 /drivers/media/video/gspca/ov519.c
parenta511ba947600ae263f8c29c86020ba66a901d3e5 (diff)
V4L/DVB (13179): gspca_ov519: cache sensor regs to avoid unnecessary slow i2c reads / writes
Cache sensor regs to avoid unnecessary slow i2c reads / writes, this speeds up sd_start a bit with most bridges and a lot (from 5 seconds down to 0.3 seconds) with W996xCF cams, as this avoids very slow bit bang IO over USB i2c reads. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/ov519.c')
-rw-r--r--drivers/media/video/gspca/ov519.c53
1 files changed, 43 insertions, 10 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 994a5e927d2d..91e9b23a3a01 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -103,6 +103,7 @@ struct sd {
103 u8 sensor_addr; 103 u8 sensor_addr;
104 int sensor_width; 104 int sensor_width;
105 int sensor_height; 105 int sensor_height;
106 int sensor_reg_cache[256];
106}; 107};
107 108
108/* Note this is a bit of a hack, but the w9968cf driver needs the code for all 109/* Note this is a bit of a hack, but the w9968cf driver needs the code for all
@@ -2210,38 +2211,70 @@ static int ovfx2_i2c_r(struct sd *sd, __u8 reg)
2210 2211
2211static int i2c_w(struct sd *sd, __u8 reg, __u8 value) 2212static int i2c_w(struct sd *sd, __u8 reg, __u8 value)
2212{ 2213{
2214 int ret = -1;
2215
2216 if (sd->sensor_reg_cache[reg] == value)
2217 return 0;
2218
2213 switch (sd->bridge) { 2219 switch (sd->bridge) {
2214 case BRIDGE_OV511: 2220 case BRIDGE_OV511:
2215 case BRIDGE_OV511PLUS: 2221 case BRIDGE_OV511PLUS:
2216 return ov511_i2c_w(sd, reg, value); 2222 ret = ov511_i2c_w(sd, reg, value);
2223 break;
2217 case BRIDGE_OV518: 2224 case BRIDGE_OV518:
2218 case BRIDGE_OV518PLUS: 2225 case BRIDGE_OV518PLUS:
2219 case BRIDGE_OV519: 2226 case BRIDGE_OV519:
2220 return ov518_i2c_w(sd, reg, value); 2227 ret = ov518_i2c_w(sd, reg, value);
2228 break;
2221 case BRIDGE_OVFX2: 2229 case BRIDGE_OVFX2:
2222 return ovfx2_i2c_w(sd, reg, value); 2230 ret = ovfx2_i2c_w(sd, reg, value);
2231 break;
2223 case BRIDGE_W9968CF: 2232 case BRIDGE_W9968CF:
2224 return w9968cf_i2c_w(sd, reg, value); 2233 ret = w9968cf_i2c_w(sd, reg, value);
2234 break;
2235 }
2236
2237 if (ret >= 0) {
2238 /* Up on sensor reset empty the register cache */
2239 if (reg == 0x12 && (value & 0x80))
2240 memset(sd->sensor_reg_cache, -1,
2241 sizeof(sd->sensor_reg_cache));
2242 else
2243 sd->sensor_reg_cache[reg] = value;
2225 } 2244 }
2226 return -1; /* Should never happen */ 2245
2246 return ret;
2227} 2247}
2228 2248
2229static int i2c_r(struct sd *sd, __u8 reg) 2249static int i2c_r(struct sd *sd, __u8 reg)
2230{ 2250{
2251 int ret;
2252
2253 if (sd->sensor_reg_cache[reg] != -1)
2254 return sd->sensor_reg_cache[reg];
2255
2231 switch (sd->bridge) { 2256 switch (sd->bridge) {
2232 case BRIDGE_OV511: 2257 case BRIDGE_OV511:
2233 case BRIDGE_OV511PLUS: 2258 case BRIDGE_OV511PLUS:
2234 return ov511_i2c_r(sd, reg); 2259 ret = ov511_i2c_r(sd, reg);
2260 break;
2235 case BRIDGE_OV518: 2261 case BRIDGE_OV518:
2236 case BRIDGE_OV518PLUS: 2262 case BRIDGE_OV518PLUS:
2237 case BRIDGE_OV519: 2263 case BRIDGE_OV519:
2238 return ov518_i2c_r(sd, reg); 2264 ret = ov518_i2c_r(sd, reg);
2265 break;
2239 case BRIDGE_OVFX2: 2266 case BRIDGE_OVFX2:
2240 return ovfx2_i2c_r(sd, reg); 2267 ret = ovfx2_i2c_r(sd, reg);
2268 break;
2241 case BRIDGE_W9968CF: 2269 case BRIDGE_W9968CF:
2242 return w9968cf_i2c_r(sd, reg); 2270 ret = w9968cf_i2c_r(sd, reg);
2271 break;
2243 } 2272 }
2244 return -1; /* Should never happen */ 2273
2274 if (ret >= 0)
2275 sd->sensor_reg_cache[reg] = ret;
2276
2277 return ret;
2245} 2278}
2246 2279
2247/* Writes bits at positions specified by mask to an I2C reg. Bits that are in 2280/* Writes bits at positions specified by mask to an I2C reg. Bits that are in