diff options
author | Brian Johnson <brijohn@gmail.com> | 2009-09-02 11:39:41 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:20:11 -0400 |
commit | e14304712939133d58a5132501e80509658e0449 (patch) | |
tree | c31ca4dfeedaaee3a6e1f319ef189b985973ed10 | |
parent | f077b0a64856c5b3bf346ae9fba8631c1fb210cf (diff) |
V4L/DVB (12704): gspca - sn9c20x: Fix exposure on SOI968 sensors
Fixes broken exposure on SOI968 webcams that was causing
the camera to display a black screen
Signed-off-by: Brian Johnson <brijohn@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/video/gspca/sn9c20x.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 52a7f8edf7ac..a74c36f4c8d2 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c | |||
@@ -799,7 +799,7 @@ static u8 soi968_init[][2] = { | |||
799 | {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff}, | 799 | {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff}, |
800 | {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20}, | 800 | {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20}, |
801 | {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e}, | 801 | {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e}, |
802 | {0x13, 0x8a}, {0x12, 0x40}, {0x17, 0x13}, | 802 | {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13}, |
803 | {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79}, | 803 | {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79}, |
804 | {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40}, | 804 | {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40}, |
805 | {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32}, | 805 | {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32}, |
@@ -1246,7 +1246,7 @@ static int soi968_init_sensor(struct gspca_dev *gspca_dev) | |||
1246 | } | 1246 | } |
1247 | } | 1247 | } |
1248 | /* disable hflip and vflip */ | 1248 | /* disable hflip and vflip */ |
1249 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); | 1249 | gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | (1 << EXPOSURE_IDX); |
1250 | sd->hstart = 60; | 1250 | sd->hstart = 60; |
1251 | sd->vstart = 11; | 1251 | sd->vstart = 11; |
1252 | return 0; | 1252 | return 0; |
@@ -1622,7 +1622,6 @@ static int set_exposure(struct gspca_dev *gspca_dev) | |||
1622 | switch (sd->sensor) { | 1622 | switch (sd->sensor) { |
1623 | case SENSOR_OV7660: | 1623 | case SENSOR_OV7660: |
1624 | case SENSOR_OV7670: | 1624 | case SENSOR_OV7670: |
1625 | case SENSOR_SOI968: | ||
1626 | case SENSOR_OV9655: | 1625 | case SENSOR_OV9655: |
1627 | case SENSOR_OV9650: | 1626 | case SENSOR_OV9650: |
1628 | exp[0] |= (3 << 4); | 1627 | exp[0] |= (3 << 4); |
@@ -1647,6 +1646,8 @@ static int set_exposure(struct gspca_dev *gspca_dev) | |||
1647 | exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8; | 1646 | exp[4] = ((sd->exposure * 0xffffff) / 0xffff) >> 8; |
1648 | exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff; | 1647 | exp[5] = ((sd->exposure * 0xffffff) / 0xffff) & 0xff; |
1649 | break; | 1648 | break; |
1649 | default: | ||
1650 | return 0; | ||
1650 | } | 1651 | } |
1651 | i2c_w(gspca_dev, exp); | 1652 | i2c_w(gspca_dev, exp); |
1652 | return 0; | 1653 | return 0; |
@@ -1690,6 +1691,8 @@ static int set_gain(struct gspca_dev *gspca_dev) | |||
1690 | gain[2] = 0x30; | 1691 | gain[2] = 0x30; |
1691 | gain[3] = hv7131r_gain[sd->gain]; | 1692 | gain[3] = hv7131r_gain[sd->gain]; |
1692 | break; | 1693 | break; |
1694 | default: | ||
1695 | return 0; | ||
1693 | } | 1696 | } |
1694 | i2c_w(gspca_dev, gain); | 1697 | i2c_w(gspca_dev, gain); |
1695 | return 0; | 1698 | return 0; |
@@ -2213,15 +2216,10 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
2213 | kfree(sd->jpeg_hdr); | 2216 | kfree(sd->jpeg_hdr); |
2214 | } | 2217 | } |
2215 | 2218 | ||
2216 | static void do_autoexposure(struct gspca_dev *gspca_dev) | 2219 | static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum) |
2217 | { | 2220 | { |
2218 | struct sd *sd = (struct sd *) gspca_dev; | 2221 | struct sd *sd = (struct sd *) gspca_dev; |
2219 | int avg_lum, new_exp; | 2222 | s16 new_exp; |
2220 | |||
2221 | if (!sd->auto_exposure) | ||
2222 | return; | ||
2223 | |||
2224 | avg_lum = atomic_read(&sd->avg_lum); | ||
2225 | 2223 | ||
2226 | /* | 2224 | /* |
2227 | * some hardcoded values are present | 2225 | * some hardcoded values are present |
@@ -2268,6 +2266,39 @@ static void do_autoexposure(struct gspca_dev *gspca_dev) | |||
2268 | } | 2266 | } |
2269 | } | 2267 | } |
2270 | 2268 | ||
2269 | static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum) | ||
2270 | { | ||
2271 | struct sd *sd = (struct sd *) gspca_dev; | ||
2272 | |||
2273 | if (avg_lum < MIN_AVG_LUM) { | ||
2274 | if (sd->gain + 1 <= 28) { | ||
2275 | sd->gain++; | ||
2276 | set_gain(gspca_dev); | ||
2277 | } | ||
2278 | } | ||
2279 | if (avg_lum > MAX_AVG_LUM) { | ||
2280 | if (sd->gain - 1 >= 0) { | ||
2281 | sd->gain--; | ||
2282 | set_gain(gspca_dev); | ||
2283 | } | ||
2284 | } | ||
2285 | } | ||
2286 | |||
2287 | static void sd_dqcallback(struct gspca_dev *gspca_dev) | ||
2288 | { | ||
2289 | struct sd *sd = (struct sd *) gspca_dev; | ||
2290 | int avg_lum; | ||
2291 | |||
2292 | if (!sd->auto_exposure) | ||
2293 | return; | ||
2294 | |||
2295 | avg_lum = atomic_read(&sd->avg_lum); | ||
2296 | if (sd->sensor == SENSOR_SOI968) | ||
2297 | do_autogain(gspca_dev, avg_lum); | ||
2298 | else | ||
2299 | do_autoexposure(gspca_dev, avg_lum); | ||
2300 | } | ||
2301 | |||
2271 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 2302 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
2272 | struct gspca_frame *frame, /* target */ | 2303 | struct gspca_frame *frame, /* target */ |
2273 | u8 *data, /* isoc packet */ | 2304 | u8 *data, /* isoc packet */ |
@@ -2335,7 +2366,7 @@ static const struct sd_desc sd_desc = { | |||
2335 | .stopN = sd_stopN, | 2366 | .stopN = sd_stopN, |
2336 | .stop0 = sd_stop0, | 2367 | .stop0 = sd_stop0, |
2337 | .pkt_scan = sd_pkt_scan, | 2368 | .pkt_scan = sd_pkt_scan, |
2338 | .dq_callback = do_autoexposure, | 2369 | .dq_callback = sd_dqcallback, |
2339 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 2370 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
2340 | .set_register = sd_dbg_s_register, | 2371 | .set_register = sd_dbg_s_register, |
2341 | .get_register = sd_dbg_g_register, | 2372 | .get_register = sd_dbg_g_register, |