aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca/sn9c20x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/sn9c20x.c')
-rw-r--r--drivers/media/video/gspca/sn9c20x.c141
1 files changed, 103 insertions, 38 deletions
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
index 6b155ae3a746..cb08d00d0a31 100644
--- a/drivers/media/video/gspca/sn9c20x.c
+++ b/drivers/media/video/gspca/sn9c20x.c
@@ -33,6 +33,14 @@ MODULE_LICENSE("GPL");
33 33
34#define MODULE_NAME "sn9c20x" 34#define MODULE_NAME "sn9c20x"
35 35
36/*
37 * Pixel format private data
38 */
39#define SCALE_MASK 0x0f
40#define SCALE_160x120 0
41#define SCALE_320x240 1
42#define SCALE_640x480 2
43#define SCALE_1280x1024 3
36#define MODE_RAW 0x10 44#define MODE_RAW 0x10
37#define MODE_JPEG 0x20 45#define MODE_JPEG 0x20
38#define MODE_SXGA 0x80 46#define MODE_SXGA 0x80
@@ -348,47 +356,47 @@ static const struct v4l2_pix_format vga_mode[] = {
348 .bytesperline = 160, 356 .bytesperline = 160,
349 .sizeimage = 160 * 120 * 4 / 8 + 590, 357 .sizeimage = 160 * 120 * 4 / 8 + 590,
350 .colorspace = V4L2_COLORSPACE_JPEG, 358 .colorspace = V4L2_COLORSPACE_JPEG,
351 .priv = 0 | MODE_JPEG}, 359 .priv = SCALE_160x120 | MODE_JPEG},
352 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 360 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
353 .bytesperline = 160, 361 .bytesperline = 160,
354 .sizeimage = 160 * 120, 362 .sizeimage = 160 * 120,
355 .colorspace = V4L2_COLORSPACE_SRGB, 363 .colorspace = V4L2_COLORSPACE_SRGB,
356 .priv = 0 | MODE_RAW}, 364 .priv = SCALE_160x120 | MODE_RAW},
357 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 365 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
358 .bytesperline = 160, 366 .bytesperline = 160,
359 .sizeimage = 240 * 120, 367 .sizeimage = 240 * 120,
360 .colorspace = V4L2_COLORSPACE_SRGB, 368 .colorspace = V4L2_COLORSPACE_SRGB,
361 .priv = 0}, 369 .priv = SCALE_160x120},
362 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 370 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
363 .bytesperline = 320, 371 .bytesperline = 320,
364 .sizeimage = 320 * 240 * 3 / 8 + 590, 372 .sizeimage = 320 * 240 * 3 / 8 + 590,
365 .colorspace = V4L2_COLORSPACE_JPEG, 373 .colorspace = V4L2_COLORSPACE_JPEG,
366 .priv = 1 | MODE_JPEG}, 374 .priv = SCALE_320x240 | MODE_JPEG},
367 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 375 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
368 .bytesperline = 320, 376 .bytesperline = 320,
369 .sizeimage = 320 * 240 , 377 .sizeimage = 320 * 240 ,
370 .colorspace = V4L2_COLORSPACE_SRGB, 378 .colorspace = V4L2_COLORSPACE_SRGB,
371 .priv = 1 | MODE_RAW}, 379 .priv = SCALE_320x240 | MODE_RAW},
372 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 380 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
373 .bytesperline = 320, 381 .bytesperline = 320,
374 .sizeimage = 480 * 240 , 382 .sizeimage = 480 * 240 ,
375 .colorspace = V4L2_COLORSPACE_SRGB, 383 .colorspace = V4L2_COLORSPACE_SRGB,
376 .priv = 1}, 384 .priv = SCALE_320x240},
377 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 385 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
378 .bytesperline = 640, 386 .bytesperline = 640,
379 .sizeimage = 640 * 480 * 3 / 8 + 590, 387 .sizeimage = 640 * 480 * 3 / 8 + 590,
380 .colorspace = V4L2_COLORSPACE_JPEG, 388 .colorspace = V4L2_COLORSPACE_JPEG,
381 .priv = 2 | MODE_JPEG}, 389 .priv = SCALE_640x480 | MODE_JPEG},
382 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 390 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
383 .bytesperline = 640, 391 .bytesperline = 640,
384 .sizeimage = 640 * 480, 392 .sizeimage = 640 * 480,
385 .colorspace = V4L2_COLORSPACE_SRGB, 393 .colorspace = V4L2_COLORSPACE_SRGB,
386 .priv = 2 | MODE_RAW}, 394 .priv = SCALE_640x480 | MODE_RAW},
387 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 395 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
388 .bytesperline = 640, 396 .bytesperline = 640,
389 .sizeimage = 960 * 480, 397 .sizeimage = 960 * 480,
390 .colorspace = V4L2_COLORSPACE_SRGB, 398 .colorspace = V4L2_COLORSPACE_SRGB,
391 .priv = 2}, 399 .priv = SCALE_640x480},
392}; 400};
393 401
394static const struct v4l2_pix_format sxga_mode[] = { 402static const struct v4l2_pix_format sxga_mode[] = {
@@ -396,52 +404,75 @@ static const struct v4l2_pix_format sxga_mode[] = {
396 .bytesperline = 160, 404 .bytesperline = 160,
397 .sizeimage = 160 * 120 * 4 / 8 + 590, 405 .sizeimage = 160 * 120 * 4 / 8 + 590,
398 .colorspace = V4L2_COLORSPACE_JPEG, 406 .colorspace = V4L2_COLORSPACE_JPEG,
399 .priv = 0 | MODE_JPEG}, 407 .priv = SCALE_160x120 | MODE_JPEG},
400 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 408 {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
401 .bytesperline = 160, 409 .bytesperline = 160,
402 .sizeimage = 160 * 120, 410 .sizeimage = 160 * 120,
403 .colorspace = V4L2_COLORSPACE_SRGB, 411 .colorspace = V4L2_COLORSPACE_SRGB,
404 .priv = 0 | MODE_RAW}, 412 .priv = SCALE_160x120 | MODE_RAW},
405 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 413 {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
406 .bytesperline = 160, 414 .bytesperline = 160,
407 .sizeimage = 240 * 120, 415 .sizeimage = 240 * 120,
408 .colorspace = V4L2_COLORSPACE_SRGB, 416 .colorspace = V4L2_COLORSPACE_SRGB,
409 .priv = 0}, 417 .priv = SCALE_160x120},
410 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 418 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
411 .bytesperline = 320, 419 .bytesperline = 320,
412 .sizeimage = 320 * 240 * 3 / 8 + 590, 420 .sizeimage = 320 * 240 * 3 / 8 + 590,
413 .colorspace = V4L2_COLORSPACE_JPEG, 421 .colorspace = V4L2_COLORSPACE_JPEG,
414 .priv = 1 | MODE_JPEG}, 422 .priv = SCALE_320x240 | MODE_JPEG},
415 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 423 {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
416 .bytesperline = 320, 424 .bytesperline = 320,
417 .sizeimage = 320 * 240 , 425 .sizeimage = 320 * 240 ,
418 .colorspace = V4L2_COLORSPACE_SRGB, 426 .colorspace = V4L2_COLORSPACE_SRGB,
419 .priv = 1 | MODE_RAW}, 427 .priv = SCALE_320x240 | MODE_RAW},
420 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 428 {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
421 .bytesperline = 320, 429 .bytesperline = 320,
422 .sizeimage = 480 * 240 , 430 .sizeimage = 480 * 240 ,
423 .colorspace = V4L2_COLORSPACE_SRGB, 431 .colorspace = V4L2_COLORSPACE_SRGB,
424 .priv = 1}, 432 .priv = SCALE_320x240},
425 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 433 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
426 .bytesperline = 640, 434 .bytesperline = 640,
427 .sizeimage = 640 * 480 * 3 / 8 + 590, 435 .sizeimage = 640 * 480 * 3 / 8 + 590,
428 .colorspace = V4L2_COLORSPACE_JPEG, 436 .colorspace = V4L2_COLORSPACE_JPEG,
429 .priv = 2 | MODE_JPEG}, 437 .priv = SCALE_640x480 | MODE_JPEG},
430 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 438 {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
431 .bytesperline = 640, 439 .bytesperline = 640,
432 .sizeimage = 640 * 480, 440 .sizeimage = 640 * 480,
433 .colorspace = V4L2_COLORSPACE_SRGB, 441 .colorspace = V4L2_COLORSPACE_SRGB,
434 .priv = 2 | MODE_RAW}, 442 .priv = SCALE_640x480 | MODE_RAW},
435 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE, 443 {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
436 .bytesperline = 640, 444 .bytesperline = 640,
437 .sizeimage = 960 * 480, 445 .sizeimage = 960 * 480,
438 .colorspace = V4L2_COLORSPACE_SRGB, 446 .colorspace = V4L2_COLORSPACE_SRGB,
439 .priv = 2}, 447 .priv = SCALE_640x480},
440 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, 448 {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
441 .bytesperline = 1280, 449 .bytesperline = 1280,
442 .sizeimage = 1280 * 1024, 450 .sizeimage = 1280 * 1024,
443 .colorspace = V4L2_COLORSPACE_SRGB, 451 .colorspace = V4L2_COLORSPACE_SRGB,
444 .priv = 3 | MODE_RAW | MODE_SXGA}, 452 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
453};
454
455static const struct v4l2_pix_format mono_mode[] = {
456 {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
457 .bytesperline = 160,
458 .sizeimage = 160 * 120,
459 .colorspace = V4L2_COLORSPACE_SRGB,
460 .priv = SCALE_160x120 | MODE_RAW},
461 {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
462 .bytesperline = 320,
463 .sizeimage = 320 * 240 ,
464 .colorspace = V4L2_COLORSPACE_SRGB,
465 .priv = SCALE_320x240 | MODE_RAW},
466 {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
467 .bytesperline = 640,
468 .sizeimage = 640 * 480,
469 .colorspace = V4L2_COLORSPACE_SRGB,
470 .priv = SCALE_640x480 | MODE_RAW},
471 {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
472 .bytesperline = 1280,
473 .sizeimage = 1280 * 1024,
474 .colorspace = V4L2_COLORSPACE_SRGB,
475 .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
445}; 476};
446 477
447static const s16 hsv_red_x[] = { 478static const s16 hsv_red_x[] = {
@@ -1029,16 +1060,19 @@ static struct i2c_reg_u16 mt9v011_init[] = {
1029}; 1060};
1030 1061
1031static struct i2c_reg_u16 mt9m001_init[] = { 1062static struct i2c_reg_u16 mt9m001_init[] = {
1032 {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e}, 1063 {0x0d, 0x0001},
1033 {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501}, 1064 {0x0d, 0x0000},
1034 {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002}, 1065 {0x04, 0x0500}, /* hres = 1280 */
1035 {0x0a, 0x0000}, {0x0c, 0x0000}, {0x11, 0x0000}, 1066 {0x03, 0x0400}, /* vres = 1024 */
1036 {0x1e, 0x8000}, {0x5f, 0x8904}, {0x60, 0x0000}, 1067 {0x20, 0x1100},
1037 {0x61, 0x0000}, {0x62, 0x0498}, {0x63, 0x0000}, 1068 {0x06, 0x0010},
1038 {0x64, 0x0000}, {0x20, 0x111d}, {0x06, 0x00f2}, 1069 {0x2b, 0x0024},
1039 {0x05, 0x0013}, {0x09, 0x10f2}, {0x07, 0x0003}, 1070 {0x2e, 0x0024},
1040 {0x2b, 0x002a}, {0x2d, 0x002a}, {0x2c, 0x002a}, 1071 {0x35, 0x0024},
1041 {0x2e, 0x0029}, {0x07, 0x0002}, 1072 {0x2d, 0x0020},
1073 {0x2c, 0x0020},
1074 {0x09, 0x0ad4},
1075 {0x35, 0x0057},
1042}; 1076};
1043 1077
1044static struct i2c_reg_u16 mt9m111_init[] = { 1078static struct i2c_reg_u16 mt9m111_init[] = {
@@ -1224,8 +1258,17 @@ static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
1224static int ov9650_init_sensor(struct gspca_dev *gspca_dev) 1258static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
1225{ 1259{
1226 int i; 1260 int i;
1261 u16 id;
1227 struct sd *sd = (struct sd *) gspca_dev; 1262 struct sd *sd = (struct sd *) gspca_dev;
1228 1263
1264 if (i2c_r2(gspca_dev, 0x1c, &id) < 0)
1265 return -EINVAL;
1266
1267 if (id != 0x7fa2) {
1268 err("sensor id for ov9650 doesn't match (0x%04x)", id);
1269 return -ENODEV;
1270 }
1271
1229 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) { 1272 for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
1230 if (i2c_w1(gspca_dev, ov9650_init[i].reg, 1273 if (i2c_w1(gspca_dev, ov9650_init[i].reg,
1231 ov9650_init[i].val) < 0) { 1274 ov9650_init[i].val) < 0) {
@@ -1425,6 +1468,25 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1425{ 1468{
1426 struct sd *sd = (struct sd *) gspca_dev; 1469 struct sd *sd = (struct sd *) gspca_dev;
1427 int i; 1470 int i;
1471 u16 id;
1472
1473 if (i2c_r2(gspca_dev, 0x00, &id) < 0)
1474 return -EINVAL;
1475
1476 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
1477 switch (id) {
1478 case 0x8411:
1479 case 0x8421:
1480 info("MT9M001 color sensor detected");
1481 break;
1482 case 0x8431:
1483 info("MT9M001 mono sensor detected");
1484 break;
1485 default:
1486 err("No MT9M001 chip detected, ID = %x\n", id);
1487 return -ENODEV;
1488 }
1489
1428 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) { 1490 for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
1429 if (i2c_w2(gspca_dev, mt9m001_init[i].reg, 1491 if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
1430 mt9m001_init[i].val) < 0) { 1492 mt9m001_init[i].val) < 0) {
@@ -1434,8 +1496,8 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
1434 } 1496 }
1435 /* disable hflip and vflip */ 1497 /* disable hflip and vflip */
1436 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX); 1498 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
1437 sd->hstart = 2; 1499 sd->hstart = 1;
1438 sd->vstart = 2; 1500 sd->vstart = 1;
1439 return 0; 1501 return 0;
1440} 1502}
1441 1503
@@ -1977,6 +2039,10 @@ static int sd_config(struct gspca_dev *gspca_dev,
1977 cam->cam_mode = sxga_mode; 2039 cam->cam_mode = sxga_mode;
1978 cam->nmodes = ARRAY_SIZE(sxga_mode); 2040 cam->nmodes = ARRAY_SIZE(sxga_mode);
1979 break; 2041 break;
2042 case SENSOR_MT9M001:
2043 cam->cam_mode = mono_mode;
2044 cam->nmodes = ARRAY_SIZE(mono_mode);
2045 break;
1980 default: 2046 default:
1981 cam->cam_mode = vga_mode; 2047 cam->cam_mode = vga_mode;
1982 cam->nmodes = ARRAY_SIZE(vga_mode); 2048 cam->nmodes = ARRAY_SIZE(vga_mode);
@@ -2075,7 +2141,6 @@ static int sd_init(struct gspca_dev *gspca_dev)
2075 case SENSOR_MT9M001: 2141 case SENSOR_MT9M001:
2076 if (mt9m001_init_sensor(gspca_dev) < 0) 2142 if (mt9m001_init_sensor(gspca_dev) < 0)
2077 return -ENODEV; 2143 return -ENODEV;
2078 info("MT9M001 sensor detected");
2079 break; 2144 break;
2080 case SENSOR_HV7131R: 2145 case SENSOR_HV7131R:
2081 if (hv7131r_init_sensor(gspca_dev) < 0) 2146 if (hv7131r_init_sensor(gspca_dev) < 0)
@@ -2173,22 +2238,22 @@ static int sd_start(struct gspca_dev *gspca_dev)
2173 else if (mode & MODE_JPEG) 2238 else if (mode & MODE_JPEG)
2174 fmt = 0x2c; 2239 fmt = 0x2c;
2175 else 2240 else
2176 fmt = 0x2f; 2241 fmt = 0x2f; /* YUV 420 */
2177 2242
2178 switch (mode & 0x0f) { 2243 switch (mode & SCALE_MASK) {
2179 case 3: 2244 case SCALE_1280x1024:
2180 scale = 0xc0; 2245 scale = 0xc0;
2181 info("Set 1280x1024"); 2246 info("Set 1280x1024");
2182 break; 2247 break;
2183 case 2: 2248 case SCALE_640x480:
2184 scale = 0x80; 2249 scale = 0x80;
2185 info("Set 640x480"); 2250 info("Set 640x480");
2186 break; 2251 break;
2187 case 1: 2252 case SCALE_320x240:
2188 scale = 0x90; 2253 scale = 0x90;
2189 info("Set 320x240"); 2254 info("Set 320x240");
2190 break; 2255 break;
2191 case 0: 2256 case SCALE_160x120:
2192 scale = 0xa0; 2257 scale = 0xa0;
2193 info("Set 160x120"); 2258 info("Set 160x120");
2194 break; 2259 break;