aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/sonixj.c
diff options
context:
space:
mode:
authorJean-Francois Moine <moinejf@free.fr>2008-08-03 06:52:53 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-08-06 05:57:25 -0400
commitcebf3b67f7f80fd69bd1ff5787fee69ab8fd3c2a (patch)
tree606952be0566fa22515d142978d51d1a14be95e7 /drivers/media/video/gspca/sonixj.c
parent594f5b8b3cce6d3137ebf260b7386520b2534385 (diff)
V4L/DVB (8604): gspca: Fix of "scheduling while atomic" crash.
The crash is due to USB exchanges done at interrupt level. These exchanges, tied to autogain, are now done by the application. Also, there is a fix about autogain start. Concerned subdrivers: etoms, pac7311, sonixj and spca561. Signed-off-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
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 -- */