aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/sonixj.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/sonixj.c')
-rw-r--r--drivers/media/video/gspca/sonixj.c57
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");
32struct sd { 32struct 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
951static 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 -- */
950static void sd_start(struct gspca_dev *gspca_dev) 968static 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
1083static void sd_stopN(struct gspca_dev *gspca_dev) 1102static 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
1127static void setautogain(struct gspca_dev *gspca_dev) 1146static 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. */
1162static void sd_pkt_scan(struct gspca_dev *gspca_dev, 1191static 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 -- */