| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * ov534-ov7xxx gspca driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 13 | 14 | * PS3 Eye camera - brightness, contrast, awb, agc, aec controls |
|---|
| 14 | 15 | * added by Max Thrun <bear24rw@gmail.com> |
|---|
| 15 | 16 | * PS3 Eye camera - FPS range extended by Joseph Howse |
|---|
| 16 | | - * <josephhowse@nummist.com> http://nummist.com |
|---|
| 17 | | - * |
|---|
| 18 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 19 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 20 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 21 | | - * any later version. |
|---|
| 22 | | - * |
|---|
| 23 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 24 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 25 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 26 | | - * GNU General Public License for more details. |
|---|
| 17 | + * <josephhowse@nummist.com> https://nummist.com |
|---|
| 27 | 18 | */ |
|---|
| 28 | 19 | |
|---|
| 29 | 20 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 103 | 94 | .sizeimage = 640 * 480 * 2, |
|---|
| 104 | 95 | .colorspace = V4L2_COLORSPACE_SRGB, |
|---|
| 105 | 96 | .priv = 0}, |
|---|
| 97 | + {320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, |
|---|
| 98 | + .bytesperline = 320, |
|---|
| 99 | + .sizeimage = 320 * 240, |
|---|
| 100 | + .colorspace = V4L2_COLORSPACE_SRGB, |
|---|
| 101 | + .priv = 1}, |
|---|
| 102 | + {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE, |
|---|
| 103 | + .bytesperline = 640, |
|---|
| 104 | + .sizeimage = 640 * 480, |
|---|
| 105 | + .colorspace = V4L2_COLORSPACE_SRGB, |
|---|
| 106 | + .priv = 0}, |
|---|
| 106 | 107 | }; |
|---|
| 107 | 108 | static const struct v4l2_pix_format ov767x_mode[] = { |
|---|
| 108 | 109 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
|---|
| .. | .. |
|---|
| 124 | 125 | .nrates = ARRAY_SIZE(qvga_rates), |
|---|
| 125 | 126 | }, |
|---|
| 126 | 127 | { /* 640x480 */ |
|---|
| 128 | + .rates = vga_rates, |
|---|
| 129 | + .nrates = ARRAY_SIZE(vga_rates), |
|---|
| 130 | + }, |
|---|
| 131 | + { /* 320x240 SGBRG8 */ |
|---|
| 132 | + .rates = qvga_rates, |
|---|
| 133 | + .nrates = ARRAY_SIZE(qvga_rates), |
|---|
| 134 | + }, |
|---|
| 135 | + { /* 640x480 SGBRG8 */ |
|---|
| 127 | 136 | .rates = vga_rates, |
|---|
| 128 | 137 | .nrates = ARRAY_SIZE(vga_rates), |
|---|
| 129 | 138 | }, |
|---|
| .. | .. |
|---|
| 411 | 420 | }; |
|---|
| 412 | 421 | |
|---|
| 413 | 422 | static const u8 bridge_init_772x[][2] = { |
|---|
| 414 | | - { 0xc2, 0x0c }, |
|---|
| 415 | 423 | { 0x88, 0xf8 }, |
|---|
| 416 | | - { 0xc3, 0x69 }, |
|---|
| 417 | 424 | { 0x89, 0xff }, |
|---|
| 418 | 425 | { 0x76, 0x03 }, |
|---|
| 419 | 426 | { 0x92, 0x01 }, |
|---|
| .. | .. |
|---|
| 439 | 446 | { 0x1f, 0x81 }, |
|---|
| 440 | 447 | { 0x34, 0x05 }, |
|---|
| 441 | 448 | { 0xe3, 0x04 }, |
|---|
| 442 | | - { 0x88, 0x00 }, |
|---|
| 443 | 449 | { 0x89, 0x00 }, |
|---|
| 444 | 450 | { 0x76, 0x00 }, |
|---|
| 445 | 451 | { 0xe7, 0x2e }, |
|---|
| .. | .. |
|---|
| 447 | 453 | { 0x25, 0x42 }, |
|---|
| 448 | 454 | { 0x21, 0xf0 }, |
|---|
| 449 | 455 | |
|---|
| 450 | | - { 0x1c, 0x00 }, |
|---|
| 451 | | - { 0x1d, 0x40 }, |
|---|
| 452 | | - { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */ |
|---|
| 453 | | - { 0x1d, 0x00 }, /* payload size */ |
|---|
| 454 | | - |
|---|
| 455 | | - { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */ |
|---|
| 456 | | - { 0x1d, 0x58 }, /* frame size */ |
|---|
| 457 | | - { 0x1d, 0x00 }, /* frame size */ |
|---|
| 458 | | - |
|---|
| 459 | 456 | { 0x1c, 0x0a }, |
|---|
| 460 | 457 | { 0x1d, 0x08 }, /* turn on UVC header */ |
|---|
| 461 | 458 | { 0x1d, 0x0e }, /* .. */ |
|---|
| 462 | | - |
|---|
| 463 | | - { 0x8d, 0x1c }, |
|---|
| 464 | | - { 0x8e, 0x80 }, |
|---|
| 465 | | - { 0xe5, 0x04 }, |
|---|
| 466 | | - |
|---|
| 467 | | - { 0xc0, 0x50 }, |
|---|
| 468 | | - { 0xc1, 0x3c }, |
|---|
| 469 | | - { 0xc2, 0x0c }, |
|---|
| 470 | 459 | }; |
|---|
| 471 | 460 | static const u8 sensor_init_772x[][2] = { |
|---|
| 472 | 461 | { 0x12, 0x80 }, |
|---|
| .. | .. |
|---|
| 545 | 534 | { 0x8c, 0xe8 }, |
|---|
| 546 | 535 | { 0x8d, 0x20 }, |
|---|
| 547 | 536 | |
|---|
| 548 | | - { 0x0c, 0x90 }, |
|---|
| 549 | | - |
|---|
| 550 | 537 | { 0x2b, 0x00 }, |
|---|
| 551 | 538 | { 0x22, 0x7f }, |
|---|
| 552 | 539 | { 0x23, 0x03 }, |
|---|
| 553 | 540 | { 0x11, 0x01 }, |
|---|
| 554 | | - { 0x0c, 0xd0 }, |
|---|
| 555 | 541 | { 0x64, 0xff }, |
|---|
| 556 | 542 | { 0x0d, 0x41 }, |
|---|
| 557 | 543 | |
|---|
| .. | .. |
|---|
| 559 | 545 | { 0x0e, 0xcd }, |
|---|
| 560 | 546 | { 0xac, 0xbf }, |
|---|
| 561 | 547 | { 0x8e, 0x00 }, /* De-noise threshold */ |
|---|
| 562 | | - { 0x0c, 0xd0 } |
|---|
| 563 | 548 | }; |
|---|
| 564 | | -static const u8 bridge_start_vga_772x[][2] = { |
|---|
| 549 | +static const u8 bridge_start_vga_yuyv_772x[][2] = { |
|---|
| 550 | + {0x88, 0x00}, |
|---|
| 565 | 551 | {0x1c, 0x00}, |
|---|
| 566 | 552 | {0x1d, 0x40}, |
|---|
| 567 | 553 | {0x1d, 0x02}, |
|---|
| .. | .. |
|---|
| 569 | 555 | {0x1d, 0x02}, |
|---|
| 570 | 556 | {0x1d, 0x58}, |
|---|
| 571 | 557 | {0x1d, 0x00}, |
|---|
| 558 | + {0x8d, 0x1c}, |
|---|
| 559 | + {0x8e, 0x80}, |
|---|
| 572 | 560 | {0xc0, 0x50}, |
|---|
| 573 | 561 | {0xc1, 0x3c}, |
|---|
| 562 | + {0xc2, 0x0c}, |
|---|
| 563 | + {0xc3, 0x69}, |
|---|
| 574 | 564 | }; |
|---|
| 575 | | -static const u8 sensor_start_vga_772x[][2] = { |
|---|
| 565 | +static const u8 sensor_start_vga_yuyv_772x[][2] = { |
|---|
| 576 | 566 | {0x12, 0x00}, |
|---|
| 577 | 567 | {0x17, 0x26}, |
|---|
| 578 | 568 | {0x18, 0xa0}, |
|---|
| .. | .. |
|---|
| 581 | 571 | {0x29, 0xa0}, |
|---|
| 582 | 572 | {0x2c, 0xf0}, |
|---|
| 583 | 573 | {0x65, 0x20}, |
|---|
| 574 | + {0x67, 0x00}, |
|---|
| 584 | 575 | }; |
|---|
| 585 | | -static const u8 bridge_start_qvga_772x[][2] = { |
|---|
| 576 | +static const u8 bridge_start_qvga_yuyv_772x[][2] = { |
|---|
| 577 | + {0x88, 0x00}, |
|---|
| 586 | 578 | {0x1c, 0x00}, |
|---|
| 587 | 579 | {0x1d, 0x40}, |
|---|
| 588 | 580 | {0x1d, 0x02}, |
|---|
| .. | .. |
|---|
| 590 | 582 | {0x1d, 0x01}, |
|---|
| 591 | 583 | {0x1d, 0x4b}, |
|---|
| 592 | 584 | {0x1d, 0x00}, |
|---|
| 585 | + {0x8d, 0x1c}, |
|---|
| 586 | + {0x8e, 0x80}, |
|---|
| 593 | 587 | {0xc0, 0x28}, |
|---|
| 594 | 588 | {0xc1, 0x1e}, |
|---|
| 589 | + {0xc2, 0x0c}, |
|---|
| 590 | + {0xc3, 0x69}, |
|---|
| 595 | 591 | }; |
|---|
| 596 | | -static const u8 sensor_start_qvga_772x[][2] = { |
|---|
| 592 | +static const u8 sensor_start_qvga_yuyv_772x[][2] = { |
|---|
| 597 | 593 | {0x12, 0x40}, |
|---|
| 598 | 594 | {0x17, 0x3f}, |
|---|
| 599 | 595 | {0x18, 0x50}, |
|---|
| .. | .. |
|---|
| 602 | 598 | {0x29, 0x50}, |
|---|
| 603 | 599 | {0x2c, 0x78}, |
|---|
| 604 | 600 | {0x65, 0x2f}, |
|---|
| 601 | + {0x67, 0x00}, |
|---|
| 602 | +}; |
|---|
| 603 | +static const u8 bridge_start_vga_gbrg_772x[][2] = { |
|---|
| 604 | + {0x88, 0x08}, |
|---|
| 605 | + {0x1c, 0x00}, |
|---|
| 606 | + {0x1d, 0x00}, |
|---|
| 607 | + {0x1d, 0x02}, |
|---|
| 608 | + {0x1d, 0x00}, |
|---|
| 609 | + {0x1d, 0x01}, |
|---|
| 610 | + {0x1d, 0x2c}, |
|---|
| 611 | + {0x1d, 0x00}, |
|---|
| 612 | + {0x8d, 0x00}, |
|---|
| 613 | + {0x8e, 0x00}, |
|---|
| 614 | + {0xc0, 0x50}, |
|---|
| 615 | + {0xc1, 0x3c}, |
|---|
| 616 | + {0xc2, 0x01}, |
|---|
| 617 | + {0xc3, 0x01}, |
|---|
| 618 | +}; |
|---|
| 619 | +static const u8 sensor_start_vga_gbrg_772x[][2] = { |
|---|
| 620 | + {0x12, 0x01}, |
|---|
| 621 | + {0x17, 0x26}, |
|---|
| 622 | + {0x18, 0xa0}, |
|---|
| 623 | + {0x19, 0x07}, |
|---|
| 624 | + {0x1a, 0xf0}, |
|---|
| 625 | + {0x29, 0xa0}, |
|---|
| 626 | + {0x2c, 0xf0}, |
|---|
| 627 | + {0x65, 0x20}, |
|---|
| 628 | + {0x67, 0x02}, |
|---|
| 629 | +}; |
|---|
| 630 | +static const u8 bridge_start_qvga_gbrg_772x[][2] = { |
|---|
| 631 | + {0x88, 0x08}, |
|---|
| 632 | + {0x1c, 0x00}, |
|---|
| 633 | + {0x1d, 0x00}, |
|---|
| 634 | + {0x1d, 0x02}, |
|---|
| 635 | + {0x1d, 0x00}, |
|---|
| 636 | + {0x1d, 0x00}, |
|---|
| 637 | + {0x1d, 0x4b}, |
|---|
| 638 | + {0x1d, 0x00}, |
|---|
| 639 | + {0x8d, 0x00}, |
|---|
| 640 | + {0x8e, 0x00}, |
|---|
| 641 | + {0xc0, 0x28}, |
|---|
| 642 | + {0xc1, 0x1e}, |
|---|
| 643 | + {0xc2, 0x01}, |
|---|
| 644 | + {0xc3, 0x01}, |
|---|
| 645 | +}; |
|---|
| 646 | +static const u8 sensor_start_qvga_gbrg_772x[][2] = { |
|---|
| 647 | + {0x12, 0x41}, |
|---|
| 648 | + {0x17, 0x3f}, |
|---|
| 649 | + {0x18, 0x50}, |
|---|
| 650 | + {0x19, 0x03}, |
|---|
| 651 | + {0x1a, 0x78}, |
|---|
| 652 | + {0x29, 0x50}, |
|---|
| 653 | + {0x2c, 0x78}, |
|---|
| 654 | + {0x65, 0x2f}, |
|---|
| 655 | + {0x67, 0x02}, |
|---|
| 605 | 656 | }; |
|---|
| 606 | 657 | |
|---|
| 607 | 658 | static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val) |
|---|
| .. | .. |
|---|
| 684 | 735 | int i; |
|---|
| 685 | 736 | |
|---|
| 686 | 737 | for (i = 0; i < 5; i++) { |
|---|
| 687 | | - msleep(10); |
|---|
| 738 | + usleep_range(10000, 20000); |
|---|
| 688 | 739 | data = ov534_reg_read(gspca_dev, OV534_REG_STATUS); |
|---|
| 689 | 740 | |
|---|
| 690 | 741 | switch (data) { |
|---|
| .. | .. |
|---|
| 1282 | 1333 | |
|---|
| 1283 | 1334 | /* reset sensor */ |
|---|
| 1284 | 1335 | sccb_reg_write(gspca_dev, 0x12, 0x80); |
|---|
| 1285 | | - msleep(10); |
|---|
| 1336 | + usleep_range(10000, 20000); |
|---|
| 1286 | 1337 | |
|---|
| 1287 | 1338 | /* probe the sensor */ |
|---|
| 1288 | 1339 | sccb_reg_read(gspca_dev, 0x0a); |
|---|
| .. | .. |
|---|
| 1320 | 1371 | { |
|---|
| 1321 | 1372 | struct sd *sd = (struct sd *) gspca_dev; |
|---|
| 1322 | 1373 | int mode; |
|---|
| 1323 | | - static const struct reg_array bridge_start[NSENSORS][2] = { |
|---|
| 1374 | + static const struct reg_array bridge_start[NSENSORS][4] = { |
|---|
| 1324 | 1375 | [SENSOR_OV767x] = {{bridge_start_qvga_767x, |
|---|
| 1325 | 1376 | ARRAY_SIZE(bridge_start_qvga_767x)}, |
|---|
| 1326 | 1377 | {bridge_start_vga_767x, |
|---|
| 1327 | 1378 | ARRAY_SIZE(bridge_start_vga_767x)}}, |
|---|
| 1328 | | - [SENSOR_OV772x] = {{bridge_start_qvga_772x, |
|---|
| 1329 | | - ARRAY_SIZE(bridge_start_qvga_772x)}, |
|---|
| 1330 | | - {bridge_start_vga_772x, |
|---|
| 1331 | | - ARRAY_SIZE(bridge_start_vga_772x)}}, |
|---|
| 1379 | + [SENSOR_OV772x] = {{bridge_start_qvga_yuyv_772x, |
|---|
| 1380 | + ARRAY_SIZE(bridge_start_qvga_yuyv_772x)}, |
|---|
| 1381 | + {bridge_start_vga_yuyv_772x, |
|---|
| 1382 | + ARRAY_SIZE(bridge_start_vga_yuyv_772x)}, |
|---|
| 1383 | + {bridge_start_qvga_gbrg_772x, |
|---|
| 1384 | + ARRAY_SIZE(bridge_start_qvga_gbrg_772x)}, |
|---|
| 1385 | + {bridge_start_vga_gbrg_772x, |
|---|
| 1386 | + ARRAY_SIZE(bridge_start_vga_gbrg_772x)} }, |
|---|
| 1332 | 1387 | }; |
|---|
| 1333 | | - static const struct reg_array sensor_start[NSENSORS][2] = { |
|---|
| 1388 | + static const struct reg_array sensor_start[NSENSORS][4] = { |
|---|
| 1334 | 1389 | [SENSOR_OV767x] = {{sensor_start_qvga_767x, |
|---|
| 1335 | 1390 | ARRAY_SIZE(sensor_start_qvga_767x)}, |
|---|
| 1336 | 1391 | {sensor_start_vga_767x, |
|---|
| 1337 | 1392 | ARRAY_SIZE(sensor_start_vga_767x)}}, |
|---|
| 1338 | | - [SENSOR_OV772x] = {{sensor_start_qvga_772x, |
|---|
| 1339 | | - ARRAY_SIZE(sensor_start_qvga_772x)}, |
|---|
| 1340 | | - {sensor_start_vga_772x, |
|---|
| 1341 | | - ARRAY_SIZE(sensor_start_vga_772x)}}, |
|---|
| 1393 | + [SENSOR_OV772x] = {{sensor_start_qvga_yuyv_772x, |
|---|
| 1394 | + ARRAY_SIZE(sensor_start_qvga_yuyv_772x)}, |
|---|
| 1395 | + {sensor_start_vga_yuyv_772x, |
|---|
| 1396 | + ARRAY_SIZE(sensor_start_vga_yuyv_772x)}, |
|---|
| 1397 | + {sensor_start_qvga_gbrg_772x, |
|---|
| 1398 | + ARRAY_SIZE(sensor_start_qvga_gbrg_772x)}, |
|---|
| 1399 | + {sensor_start_vga_gbrg_772x, |
|---|
| 1400 | + ARRAY_SIZE(sensor_start_vga_gbrg_772x)} }, |
|---|
| 1342 | 1401 | }; |
|---|
| 1343 | 1402 | |
|---|
| 1344 | 1403 | /* (from ms-win trace) */ |
|---|
| .. | .. |
|---|
| 1444 | 1503 | /* If this packet is marked as EOF, end the frame */ |
|---|
| 1445 | 1504 | } else if (data[1] & UVC_STREAM_EOF) { |
|---|
| 1446 | 1505 | sd->last_pts = 0; |
|---|
| 1447 | | - if (gspca_dev->pixfmt.pixelformat == V4L2_PIX_FMT_YUYV |
|---|
| 1506 | + if (gspca_dev->pixfmt.pixelformat != V4L2_PIX_FMT_JPEG |
|---|
| 1448 | 1507 | && gspca_dev->image_len + len - 12 != |
|---|
| 1449 | | - gspca_dev->pixfmt.width * |
|---|
| 1450 | | - gspca_dev->pixfmt.height * 2) { |
|---|
| 1508 | + gspca_dev->pixfmt.sizeimage) { |
|---|
| 1451 | 1509 | gspca_dbg(gspca_dev, D_PACK, "wrong sized frame\n"); |
|---|
| 1452 | 1510 | goto discard; |
|---|
| 1453 | 1511 | } |
|---|