diff options
Diffstat (limited to 'drivers/media/video/gspca/sn9c20x.c')
-rw-r--r-- | drivers/media/video/gspca/sn9c20x.c | 141 |
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 | ||
394 | static const struct v4l2_pix_format sxga_mode[] = { | 402 | static 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 | |||
455 | static 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 | ||
447 | static const s16 hsv_red_x[] = { | 478 | static const s16 hsv_red_x[] = { |
@@ -1029,16 +1060,19 @@ static struct i2c_reg_u16 mt9v011_init[] = { | |||
1029 | }; | 1060 | }; |
1030 | 1061 | ||
1031 | static struct i2c_reg_u16 mt9m001_init[] = { | 1062 | static 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 | ||
1044 | static struct i2c_reg_u16 mt9m111_init[] = { | 1078 | static struct i2c_reg_u16 mt9m111_init[] = { |
@@ -1224,8 +1258,17 @@ static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val) | |||
1224 | static int ov9650_init_sensor(struct gspca_dev *gspca_dev) | 1258 | static 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; |