diff options
Diffstat (limited to 'drivers/media/video/gspca/sonixj.c')
-rw-r--r-- | drivers/media/video/gspca/sonixj.c | 57 |
1 files changed, 40 insertions, 17 deletions
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index b60ff600a757..245a30ec5fb1 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
@@ -32,7 +32,7 @@ MODULE_LICENSE("GPL"); | |||
32 | struct sd { | 32 | struct sd { |
33 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 33 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
34 | 34 | ||
35 | int avg_lum; | 35 | atomic_t avg_lum; |
36 | unsigned int exposure; | 36 | unsigned int exposure; |
37 | 37 | ||
38 | unsigned short brightness; | 38 | unsigned short brightness; |
@@ -781,6 +781,8 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
781 | sd->contrast = CONTRAST_DEF; | 781 | sd->contrast = CONTRAST_DEF; |
782 | sd->colors = COLOR_DEF; | 782 | sd->colors = COLOR_DEF; |
783 | sd->autogain = AUTOGAIN_DEF; | 783 | sd->autogain = AUTOGAIN_DEF; |
784 | sd->ag_cnt = -1; | ||
785 | |||
784 | return 0; | 786 | return 0; |
785 | } | 787 | } |
786 | 788 | ||
@@ -946,6 +948,22 @@ static void setcolors(struct gspca_dev *gspca_dev) | |||
946 | reg_w1(gspca_dev, 0x05, data); | 948 | reg_w1(gspca_dev, 0x05, data); |
947 | } | 949 | } |
948 | 950 | ||
951 | static void setautogain(struct gspca_dev *gspca_dev) | ||
952 | { | ||
953 | struct sd *sd = (struct sd *) gspca_dev; | ||
954 | |||
955 | switch (sd->sensor) { | ||
956 | case SENSOR_HV7131R: | ||
957 | case SENSOR_MO4000: | ||
958 | case SENSOR_MI0360: | ||
959 | if (sd->autogain) | ||
960 | sd->ag_cnt = AG_CNT_START; | ||
961 | else | ||
962 | sd->ag_cnt = -1; | ||
963 | break; | ||
964 | } | ||
965 | } | ||
966 | |||
949 | /* -- start the camera -- */ | 967 | /* -- start the camera -- */ |
950 | static void sd_start(struct gspca_dev *gspca_dev) | 968 | static void sd_start(struct gspca_dev *gspca_dev) |
951 | { | 969 | { |
@@ -1078,6 +1096,7 @@ static void sd_start(struct gspca_dev *gspca_dev) | |||
1078 | reg_w1(gspca_dev, 0x01, reg1); | 1096 | reg_w1(gspca_dev, 0x01, reg1); |
1079 | setbrightness(gspca_dev); | 1097 | setbrightness(gspca_dev); |
1080 | setcontrast(gspca_dev); | 1098 | setcontrast(gspca_dev); |
1099 | setautogain(gspca_dev); | ||
1081 | } | 1100 | } |
1082 | 1101 | ||
1083 | static void sd_stopN(struct gspca_dev *gspca_dev) | 1102 | static void sd_stopN(struct gspca_dev *gspca_dev) |
@@ -1124,16 +1143,23 @@ static void sd_close(struct gspca_dev *gspca_dev) | |||
1124 | { | 1143 | { |
1125 | } | 1144 | } |
1126 | 1145 | ||
1127 | static void setautogain(struct gspca_dev *gspca_dev) | 1146 | static void do_autogain(struct gspca_dev *gspca_dev) |
1128 | { | 1147 | { |
1129 | struct sd *sd = (struct sd *) gspca_dev; | 1148 | struct sd *sd = (struct sd *) gspca_dev; |
1130 | /* Thanks S., without your advice, autobright should not work :) */ | ||
1131 | int delta; | 1149 | int delta; |
1132 | int expotimes = 0; | 1150 | int expotimes; |
1133 | __u8 luma_mean = 130; | 1151 | __u8 luma_mean = 130; |
1134 | __u8 luma_delta = 20; | 1152 | __u8 luma_delta = 20; |
1135 | 1153 | ||
1136 | delta = sd->avg_lum; | 1154 | /* Thanks S., without your advice, autobright should not work :) */ |
1155 | if (sd->ag_cnt < 0) | ||
1156 | return; | ||
1157 | if (--sd->ag_cnt >= 0) | ||
1158 | return; | ||
1159 | sd->ag_cnt = AG_CNT_START; | ||
1160 | |||
1161 | delta = atomic_read(&sd->avg_lum); | ||
1162 | PDEBUG(D_FRAM, "mean lum %d", delta); | ||
1137 | if (delta < luma_mean - luma_delta || | 1163 | if (delta < luma_mean - luma_delta || |
1138 | delta > luma_mean + luma_delta) { | 1164 | delta > luma_mean + luma_delta) { |
1139 | switch (sd->sensor) { | 1165 | switch (sd->sensor) { |
@@ -1145,8 +1171,9 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
1145 | sd->exposure = setexposure(gspca_dev, | 1171 | sd->exposure = setexposure(gspca_dev, |
1146 | (unsigned int) (expotimes << 8)); | 1172 | (unsigned int) (expotimes << 8)); |
1147 | break; | 1173 | break; |
1148 | case SENSOR_MO4000: | 1174 | default: |
1149 | case SENSOR_MI0360: | 1175 | /* case SENSOR_MO4000: */ |
1176 | /* case SENSOR_MI0360: */ | ||
1150 | expotimes = sd->exposure; | 1177 | expotimes = sd->exposure; |
1151 | expotimes += (luma_mean - delta) >> 6; | 1178 | expotimes += (luma_mean - delta) >> 6; |
1152 | if (expotimes < 0) | 1179 | if (expotimes < 0) |
@@ -1159,6 +1186,8 @@ static void setautogain(struct gspca_dev *gspca_dev) | |||
1159 | } | 1186 | } |
1160 | } | 1187 | } |
1161 | 1188 | ||
1189 | /* scan the URB packets */ | ||
1190 | /* This function is run at interrupt level. */ | ||
1162 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 1191 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
1163 | struct gspca_frame *frame, /* target */ | 1192 | struct gspca_frame *frame, /* target */ |
1164 | __u8 *data, /* isoc packet */ | 1193 | __u8 *data, /* isoc packet */ |
@@ -1175,9 +1204,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1175 | frame, data, sof + 2); | 1204 | frame, data, sof + 2); |
1176 | if (sd->ag_cnt < 0) | 1205 | if (sd->ag_cnt < 0) |
1177 | return; | 1206 | return; |
1178 | if (--sd->ag_cnt >= 0) | ||
1179 | return; | ||
1180 | sd->ag_cnt = AG_CNT_START; | ||
1181 | /* w1 w2 w3 */ | 1207 | /* w1 w2 w3 */ |
1182 | /* w4 w5 w6 */ | 1208 | /* w4 w5 w6 */ |
1183 | /* w7 w8 */ | 1209 | /* w7 w8 */ |
@@ -1192,9 +1218,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1192 | /* w5 */ | 1218 | /* w5 */ |
1193 | avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4; | 1219 | avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4; |
1194 | avg_lum >>= 4; | 1220 | avg_lum >>= 4; |
1195 | sd->avg_lum = avg_lum; | 1221 | atomic_set(&sd->avg_lum, avg_lum); |
1196 | PDEBUG(D_PACK, "mean lum %d", avg_lum); | ||
1197 | setautogain(gspca_dev); | ||
1198 | return; | 1222 | return; |
1199 | } | 1223 | } |
1200 | if (gspca_dev->last_packet_type == LAST_PACKET) { | 1224 | if (gspca_dev->last_packet_type == LAST_PACKET) { |
@@ -1321,10 +1345,8 @@ static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | |||
1321 | struct sd *sd = (struct sd *) gspca_dev; | 1345 | struct sd *sd = (struct sd *) gspca_dev; |
1322 | 1346 | ||
1323 | sd->autogain = val; | 1347 | sd->autogain = val; |
1324 | if (val) | 1348 | if (gspca_dev->streaming) |
1325 | sd->ag_cnt = AG_CNT_START; | 1349 | setautogain(gspca_dev); |
1326 | else | ||
1327 | sd->ag_cnt = -1; | ||
1328 | return 0; | 1350 | return 0; |
1329 | } | 1351 | } |
1330 | 1352 | ||
@@ -1348,6 +1370,7 @@ static const struct sd_desc sd_desc = { | |||
1348 | .stop0 = sd_stop0, | 1370 | .stop0 = sd_stop0, |
1349 | .close = sd_close, | 1371 | .close = sd_close, |
1350 | .pkt_scan = sd_pkt_scan, | 1372 | .pkt_scan = sd_pkt_scan, |
1373 | .dq_callback = do_autogain, | ||
1351 | }; | 1374 | }; |
1352 | 1375 | ||
1353 | /* -- module initialisation -- */ | 1376 | /* -- module initialisation -- */ |