aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/sonixb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/sonixb.c')
-rw-r--r--drivers/media/video/gspca/sonixb.c236
1 files changed, 167 insertions, 69 deletions
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
index 706f96f92654..73504a3f87b7 100644
--- a/drivers/media/video/gspca/sonixb.c
+++ b/drivers/media/video/gspca/sonixb.c
@@ -56,6 +56,8 @@ struct sd {
56 int prev_avg_lum; 56 int prev_avg_lum;
57 int exp_too_low_cnt; 57 int exp_too_low_cnt;
58 int exp_too_high_cnt; 58 int exp_too_high_cnt;
59 int header_read;
60 u8 header[12]; /* Header without sof marker */
59 61
60 unsigned short exposure; 62 unsigned short exposure;
61 unsigned char gain; 63 unsigned char gain;
@@ -71,14 +73,15 @@ struct sd {
71#define BRIDGE_103 1 73#define BRIDGE_103 1
72 74
73 __u8 sensor; /* Type of image sensor chip */ 75 __u8 sensor; /* Type of image sensor chip */
74#define SENSOR_HV7131R 0 76#define SENSOR_HV7131D 0
75#define SENSOR_OV6650 1 77#define SENSOR_HV7131R 1
76#define SENSOR_OV7630 2 78#define SENSOR_OV6650 2
77#define SENSOR_PAS106 3 79#define SENSOR_OV7630 3
78#define SENSOR_PAS202 4 80#define SENSOR_PAS106 4
79#define SENSOR_TAS5110C 5 81#define SENSOR_PAS202 5
80#define SENSOR_TAS5110D 6 82#define SENSOR_TAS5110C 6
81#define SENSOR_TAS5130CXX 7 83#define SENSOR_TAS5110D 7
84#define SENSOR_TAS5130CXX 8
82 __u8 reg11; 85 __u8 reg11;
83}; 86};
84 87
@@ -303,14 +306,29 @@ static const struct v4l2_pix_format sif_mode[] = {
303 .priv = 0}, 306 .priv = 0},
304}; 307};
305 308
306static const __u8 initHv7131[] = { 309static const __u8 initHv7131d[] = {
310 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
311 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
313 0x28, 0x1e, 0x60, 0x8e, 0x42,
314 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
315};
316static const __u8 hv7131d_sensor_init[][8] = {
317 {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17},
318 {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17},
319 {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17},
320 {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */
321 {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */
322};
323
324static const __u8 initHv7131r[] = {
307 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00, 325 0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
308 0x00, 0x00, 326 0x00, 0x00,
309 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 327 0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
310 0x28, 0x1e, 0x60, 0x8a, 0x20, 328 0x28, 0x1e, 0x60, 0x8a, 0x20,
311 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c 329 0x1d, 0x10, 0x02, 0x03, 0x0f, 0x0c
312}; 330};
313static const __u8 hv7131_sensor_init[][8] = { 331static const __u8 hv7131r_sensor_init[][8] = {
314 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10}, 332 {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
315 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10}, 333 {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
316 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10}, 334 {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
@@ -340,7 +358,7 @@ static const __u8 ov6650_sensor_init[][8] = {
340 * but blue wont be there. Avoid this data ... */ 358 * but blue wont be there. Avoid this data ... */
341 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */ 359 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
342 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, 360 {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
343 {0xa0, 0x60, 0x30, 0x3d, 0x0A, 0xd8, 0xa4, 0x10}, 361 {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10},
344 /* Enable rgb brightness control */ 362 /* Enable rgb brightness control */
345 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10}, 363 {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
346 /* HDG: Note windows uses the line below, which sets both register 0x60 364 /* HDG: Note windows uses the line below, which sets both register 0x60
@@ -505,7 +523,7 @@ static const __u8 pas202_sensor_init[][8] = {
505 {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10}, 523 {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
506 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10}, 524 {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
507 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10}, 525 {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
508 {0xd0, 0x40, 0x0C, 0x00, 0x0C, 0x01, 0x32, 0x10}, 526 {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10},
509 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10}, 527 {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
510 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10}, 528 {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
511 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10}, 529 {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
@@ -551,7 +569,8 @@ static const __u8 tas5130_sensor_init[][8] = {
551}; 569};
552 570
553static struct sensor_data sensor_data[] = { 571static struct sensor_data sensor_data[] = {
554SENS(initHv7131, NULL, hv7131_sensor_init, NULL, NULL, 0, NO_EXPO|NO_FREQ, 0), 572SENS(initHv7131d, NULL, hv7131d_sensor_init, NULL, NULL, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0),
573SENS(initHv7131r, NULL, hv7131r_sensor_init, NULL, NULL, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0),
555SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60), 574SENS(initOv6650, NULL, ov6650_sensor_init, NULL, NULL, F_GAIN|F_SIF, 0, 0x60),
556SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3, 575SENS(initOv7630, initOv7630_3, ov7630_sensor_init, NULL, ov7630_sensor_init_3,
557 F_GAIN, 0, 0x21), 576 F_GAIN, 0, 0x21),
@@ -701,7 +720,18 @@ static void setsensorgain(struct gspca_dev *gspca_dev)
701 unsigned char gain = sd->gain; 720 unsigned char gain = sd->gain;
702 721
703 switch (sd->sensor) { 722 switch (sd->sensor) {
723 case SENSOR_HV7131D: {
724 __u8 i2c[] =
725 {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
704 726
727 i2c[3] = 0x3f - (sd->gain / 4);
728 i2c[4] = 0x3f - (sd->gain / 4);
729 i2c[5] = 0x3f - (sd->gain / 4);
730
731 if (i2c_w(gspca_dev, i2c) < 0)
732 goto err;
733 break;
734 }
705 case SENSOR_TAS5110C: 735 case SENSOR_TAS5110C:
706 case SENSOR_TAS5110D: { 736 case SENSOR_TAS5110D: {
707 __u8 i2c[] = 737 __u8 i2c[] =
@@ -788,6 +818,23 @@ static void setexposure(struct gspca_dev *gspca_dev)
788 struct sd *sd = (struct sd *) gspca_dev; 818 struct sd *sd = (struct sd *) gspca_dev;
789 819
790 switch (sd->sensor) { 820 switch (sd->sensor) {
821 case SENSOR_HV7131D: {
822 /* Note the datasheet wrongly says line mode exposure uses reg
823 0x26 and 0x27, testing has shown 0x25 + 0x26 */
824 __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17};
825 /* The HV7131D's exposure goes from 0 - 65535, we scale our
826 exposure of 0-1023 to 0-6138. There are 2 reasons for this:
827 1) This puts our exposure knee of 200 at approx the point
828 where the framerate starts dropping
829 2) At 6138 the framerate has already dropped to 2 fps,
830 going any lower makes little sense */
831 __u16 reg = sd->exposure * 6;
832 i2c[3] = reg >> 8;
833 i2c[4] = reg & 0xff;
834 if (i2c_w(gspca_dev, i2c) != 0)
835 goto err;
836 break;
837 }
791 case SENSOR_TAS5110C: 838 case SENSOR_TAS5110C:
792 case SENSOR_TAS5110D: { 839 case SENSOR_TAS5110D: {
793 /* register 19's high nibble contains the sn9c10x clock divider 840 /* register 19's high nibble contains the sn9c10x clock divider
@@ -1177,13 +1224,10 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
1177 sd_init(gspca_dev); 1224 sd_init(gspca_dev);
1178} 1225}
1179 1226
1180static void sd_pkt_scan(struct gspca_dev *gspca_dev, 1227static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
1181 u8 *data, /* isoc packet */
1182 int len) /* iso packet length */
1183{ 1228{
1184 int i;
1185 struct sd *sd = (struct sd *) gspca_dev; 1229 struct sd *sd = (struct sd *) gspca_dev;
1186 struct cam *cam = &gspca_dev->cam; 1230 int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
1187 1231
1188 /* frames start with: 1232 /* frames start with:
1189 * ff ff 00 c4 c4 96 synchro 1233 * ff ff 00 c4 c4 96 synchro
@@ -1194,58 +1238,84 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1194 * ll mm brightness sum outside auto exposure 1238 * ll mm brightness sum outside auto exposure
1195 * (xx xx xx xx xx) audio values for snc103 1239 * (xx xx xx xx xx) audio values for snc103
1196 */ 1240 */
1197 if (len > 6 && len < 24) { 1241 for (i = 0; i < len; i++) {
1198 for (i = 0; i < len - 6; i++) { 1242 switch (sd->header_read) {
1199 if (data[0 + i] == 0xff 1243 case 0:
1200 && data[1 + i] == 0xff 1244 if (data[i] == 0xff)
1201 && data[2 + i] == 0x00 1245 sd->header_read++;
1202 && data[3 + i] == 0xc4 1246 break;
1203 && data[4 + i] == 0xc4 1247 case 1:
1204 && data[5 + i] == 0x96) { /* start of frame */ 1248 if (data[i] == 0xff)
1205 int lum = -1; 1249 sd->header_read++;
1206 int pkt_type = LAST_PACKET; 1250 else
1207 int fr_h_sz = (sd->bridge == BRIDGE_103) ? 1251 sd->header_read = 0;
1208 18 : 12; 1252 break;
1209 1253 case 2:
1210 if (len - i < fr_h_sz) { 1254 if (data[i] == 0x00)
1211 PDEBUG(D_STREAM, "packet too short to" 1255 sd->header_read++;
1212 " get avg brightness"); 1256 else if (data[i] != 0xff)
1213 } else if (sd->bridge == BRIDGE_103) { 1257 sd->header_read = 0;
1214 lum = data[i + 9] + 1258 break;
1215 (data[i + 10] << 8); 1259 case 3:
1216 } else { 1260 if (data[i] == 0xc4)
1217 lum = data[i + 8] + (data[i + 9] << 8); 1261 sd->header_read++;
1218 } 1262 else if (data[i] == 0xff)
1219 /* When exposure changes midway a frame we 1263 sd->header_read = 1;
1220 get a lum of 0 in this case drop 2 frames 1264 else
1221 as the frames directly after an exposure 1265 sd->header_read = 0;
1222 change have an unstable image. Sometimes lum 1266 break;
1223 *really* is 0 (cam used in low light with 1267 case 4:
1224 low exposure setting), so do not drop frames 1268 if (data[i] == 0xc4)
1225 if the previous lum was 0 too. */ 1269 sd->header_read++;
1226 if (lum == 0 && sd->prev_avg_lum != 0) { 1270 else if (data[i] == 0xff)
1227 lum = -1; 1271 sd->header_read = 1;
1228 sd->frames_to_drop = 2; 1272 else
1229 sd->prev_avg_lum = 0; 1273 sd->header_read = 0;
1230 } else 1274 break;
1231 sd->prev_avg_lum = lum; 1275 case 5:
1232 atomic_set(&sd->avg_lum, lum); 1276 if (data[i] == 0x96)
1233 1277 sd->header_read++;
1234 if (sd->frames_to_drop) { 1278 else if (data[i] == 0xff)
1235 sd->frames_to_drop--; 1279 sd->header_read = 1;
1236 pkt_type = DISCARD_PACKET; 1280 else
1237 } 1281 sd->header_read = 0;
1238 1282 break;
1239 gspca_frame_add(gspca_dev, pkt_type, 1283 default:
1240 NULL, 0); 1284 sd->header[sd->header_read - 6] = data[i];
1241 data += i + fr_h_sz; 1285 sd->header_read++;
1242 len -= i + fr_h_sz; 1286 if (sd->header_read == header_size) {
1243 gspca_frame_add(gspca_dev, FIRST_PACKET, 1287 sd->header_read = 0;
1244 data, len); 1288 return data + i + 1;
1245 return;
1246 } 1289 }
1247 } 1290 }
1248 } 1291 }
1292 return NULL;
1293}
1294
1295static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1296 u8 *data, /* isoc packet */
1297 int len) /* iso packet length */
1298{
1299 int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
1300 struct sd *sd = (struct sd *) gspca_dev;
1301 struct cam *cam = &gspca_dev->cam;
1302 u8 *sof;
1303
1304 sof = find_sof(gspca_dev, data, len);
1305 if (sof) {
1306 if (sd->bridge == BRIDGE_103) {
1307 fr_h_sz = 18;
1308 lum_offset = 3;
1309 } else {
1310 fr_h_sz = 12;
1311 lum_offset = 2;
1312 }
1313
1314 len_after_sof = len - (sof - data);
1315 len = (sof - data) - fr_h_sz;
1316 if (len < 0)
1317 len = 0;
1318 }
1249 1319
1250 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) { 1320 if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
1251 /* In raw mode we sometimes get some garbage after the frame 1321 /* In raw mode we sometimes get some garbage after the frame
@@ -1259,6 +1329,33 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
1259 } 1329 }
1260 1330
1261 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 1331 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
1332
1333 if (sof) {
1334 int lum = sd->header[lum_offset] +
1335 (sd->header[lum_offset + 1] << 8);
1336
1337 /* When exposure changes midway a frame we
1338 get a lum of 0 in this case drop 2 frames
1339 as the frames directly after an exposure
1340 change have an unstable image. Sometimes lum
1341 *really* is 0 (cam used in low light with
1342 low exposure setting), so do not drop frames
1343 if the previous lum was 0 too. */
1344 if (lum == 0 && sd->prev_avg_lum != 0) {
1345 lum = -1;
1346 sd->frames_to_drop = 2;
1347 sd->prev_avg_lum = 0;
1348 } else
1349 sd->prev_avg_lum = lum;
1350 atomic_set(&sd->avg_lum, lum);
1351
1352 if (sd->frames_to_drop)
1353 sd->frames_to_drop--;
1354 else
1355 gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
1356
1357 gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
1358 }
1262} 1359}
1263 1360
1264static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) 1361static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
@@ -1431,9 +1528,7 @@ static const struct sd_desc sd_desc = {
1431static const struct usb_device_id device_table[] __devinitconst = { 1528static const struct usb_device_id device_table[] __devinitconst = {
1432 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */ 1529 {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
1433 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */ 1530 {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
1434#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1435 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */ 1531 {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
1436#endif
1437 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)}, 1532 {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
1438 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)}, 1533 {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
1439 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)}, 1534 {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
@@ -1444,9 +1539,12 @@ static const struct usb_device_id device_table[] __devinitconst = {
1444#endif 1539#endif
1445 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)}, 1540 {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
1446 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)}, 1541 {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
1542 {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
1543 /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */
1447 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)}, 1544 {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
1448 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)}, 1545 {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
1449 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)}, 1546 {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
1547 /* {USB_DEVICE(0x0c45, 0x602b), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */
1450 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)}, 1548 {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
1451#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE 1549#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
1452 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)}, 1550 {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},