diff options
author | Hans de Goede <hdegoede@redhat.com> | 2009-10-16 06:42:53 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:40:45 -0500 |
commit | fb1f9020609ead93fcec4b0dd02511a46294c147 (patch) | |
tree | 867752434af3591fa3f57abaf315d8b40d3348b9 /drivers/media/video/gspca/ov519.c | |
parent | a511ba947600ae263f8c29c86020ba66a901d3e5 (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.c | 53 |
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 | ||
2211 | static int i2c_w(struct sd *sd, __u8 reg, __u8 value) | 2212 | static 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 | ||
2229 | static int i2c_r(struct sd *sd, __u8 reg) | 2249 | static 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 |