.. | .. |
---|
50 | 50 | |
---|
51 | 51 | #define SC031GS_REG_COARSE_AGAIN 0x3e08 |
---|
52 | 52 | #define SC031GS_REG_FINE_AGAIN 0x3e09 |
---|
53 | | -#define ANALOG_GAIN_MIN 0x01 |
---|
54 | | -#define ANALOG_GAIN_MAX 0xF8 |
---|
| 53 | +#define ANALOG_GAIN_MIN 0x10 |
---|
| 54 | +#define ANALOG_GAIN_MAX 0x7c0 // 124x |
---|
55 | 55 | #define ANALOG_GAIN_STEP 1 |
---|
56 | 56 | #define ANALOG_GAIN_DEFAULT 0x1f |
---|
57 | 57 | |
---|
.. | .. |
---|
117 | 117 | struct v4l2_ctrl *vblank; |
---|
118 | 118 | struct v4l2_ctrl *test_pattern; |
---|
119 | 119 | struct mutex mutex; |
---|
| 120 | + struct v4l2_fract cur_fps; |
---|
| 121 | + u32 cur_vts; |
---|
120 | 122 | bool streaming; |
---|
121 | 123 | bool power_on; |
---|
122 | 124 | const struct sc031gs_mode *cur_mode; |
---|
.. | .. |
---|
296 | 298 | {0x3d08, 0x01}, |
---|
297 | 299 | {0x3e01, 0x14}, |
---|
298 | 300 | {0x3e02, 0x80}, |
---|
299 | | - {0x3e06, 0x0c}, |
---|
| 301 | + {0x3e06, 0x00}, |
---|
300 | 302 | {0x4500, 0x59}, |
---|
301 | 303 | {0x4501, 0xc4}, |
---|
302 | 304 | {0x4603, 0x00}, |
---|
.. | .. |
---|
477 | 479 | __v4l2_ctrl_modify_range(sc031gs->vblank, vblank_def, |
---|
478 | 480 | SC031GS_VTS_MAX - mode->height, |
---|
479 | 481 | 1, vblank_def); |
---|
| 482 | + sc031gs->cur_fps = mode->max_fps; |
---|
| 483 | + sc031gs->cur_vts = mode->vts_def; |
---|
480 | 484 | } |
---|
481 | 485 | |
---|
482 | 486 | mutex_unlock(&sc031gs->mutex); |
---|
.. | .. |
---|
611 | 615 | |
---|
612 | 616 | ret = sc031gs_ioctl(sd, cmd, inf); |
---|
613 | 617 | if (!ret) |
---|
614 | | - ret = copy_to_user(up, inf, sizeof(*inf)); |
---|
| 618 | + if (copy_to_user(up, inf, sizeof(*inf))) { |
---|
| 619 | + kfree(inf); |
---|
| 620 | + return -EFAULT; |
---|
| 621 | + } |
---|
615 | 622 | kfree(inf); |
---|
616 | 623 | break; |
---|
617 | 624 | case RKMODULE_AWB_CFG: |
---|
.. | .. |
---|
620 | 627 | ret = -ENOMEM; |
---|
621 | 628 | return ret; |
---|
622 | 629 | } |
---|
623 | | - |
---|
624 | | - ret = copy_from_user(cfg, up, sizeof(*cfg)); |
---|
625 | | - if (!ret) |
---|
626 | | - ret = sc031gs_ioctl(sd, cmd, cfg); |
---|
| 630 | + if (copy_from_user(cfg, up, sizeof(*cfg))) { |
---|
| 631 | + kfree(cfg); |
---|
| 632 | + return -EFAULT; |
---|
| 633 | + } |
---|
| 634 | + ret = sc031gs_ioctl(sd, cmd, cfg); |
---|
627 | 635 | kfree(cfg); |
---|
628 | 636 | break; |
---|
629 | 637 | case RKMODULE_SET_QUICK_STREAM: |
---|
630 | | - ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
631 | | - if (!ret) |
---|
632 | | - ret = sc031gs_ioctl(sd, cmd, &stream); |
---|
| 638 | + if (copy_from_user(&stream, up, sizeof(u32))) |
---|
| 639 | + return -EFAULT; |
---|
| 640 | + ret = sc031gs_ioctl(sd, cmd, &stream); |
---|
633 | 641 | break; |
---|
634 | 642 | default: |
---|
635 | 643 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
643 | 651 | static int sc031gs_set_ctrl_gain(struct sc031gs *sc031gs, u32 a_gain) |
---|
644 | 652 | { |
---|
645 | 653 | int ret = 0; |
---|
646 | | - u32 coarse_again, fine_again, fine_again_reg, coarse_again_reg; |
---|
| 654 | + u32 coarse_again, fine_again, fine_again_reg, coarse_again_reg, digital_gain_reg; |
---|
647 | 655 | |
---|
648 | 656 | if (a_gain < 0x20) { /*1x ~ 2x*/ |
---|
649 | 657 | fine_again = a_gain - 16; |
---|
.. | .. |
---|
651 | 659 | fine_again_reg = ((0x01 << 4) & 0x10) | |
---|
652 | 660 | (fine_again & 0x0f); |
---|
653 | 661 | coarse_again_reg = coarse_again & 0x1F; |
---|
| 662 | + digital_gain_reg = 0x80; |
---|
654 | 663 | } else if (a_gain < 0x40) { /*2x ~ 4x*/ |
---|
655 | 664 | fine_again = (a_gain >> 1) - 16; |
---|
656 | 665 | coarse_again = 0x7; |
---|
657 | 666 | fine_again_reg = ((0x01 << 4) & 0x10) | |
---|
658 | 667 | (fine_again & 0x0f); |
---|
659 | 668 | coarse_again_reg = coarse_again & 0x1F; |
---|
| 669 | + digital_gain_reg = 0x80; |
---|
660 | 670 | } else if (a_gain < 0x80) { /*4x ~ 8x*/ |
---|
661 | 671 | fine_again = (a_gain >> 2) - 16; |
---|
662 | 672 | coarse_again = 0xf; |
---|
663 | 673 | fine_again_reg = ((0x01 << 4) & 0x10) | |
---|
664 | 674 | (fine_again & 0x0f); |
---|
665 | 675 | coarse_again_reg = coarse_again & 0x1F; |
---|
666 | | - } else { /*8x ~ 16x*/ |
---|
| 676 | + digital_gain_reg = 0x80; |
---|
| 677 | + } else if (a_gain < 0x100) { /*8x ~ 16x*/ |
---|
667 | 678 | fine_again = (a_gain >> 3) - 16; |
---|
668 | 679 | coarse_again = 0x1f; |
---|
669 | 680 | fine_again_reg = ((0x01 << 4) & 0x10) | |
---|
670 | 681 | (fine_again & 0x0f); |
---|
671 | 682 | coarse_again_reg = coarse_again & 0x1F; |
---|
| 683 | + digital_gain_reg = 0x80; |
---|
| 684 | + } else if (a_gain < 0x200) { /*16x ~ 32x*/ |
---|
| 685 | + fine_again_reg = 0x1f; |
---|
| 686 | + coarse_again_reg = 0x1f; |
---|
| 687 | + digital_gain_reg = (a_gain * 0x80 / 0x100) & 0xf8; |
---|
| 688 | + } else if (a_gain < 0x400) { /*32x ~ 64x*/ |
---|
| 689 | + fine_again_reg = 0x1f; |
---|
| 690 | + coarse_again_reg = 0x1f; |
---|
| 691 | + digital_gain_reg = (a_gain * 0x80 / 0x200) & 0x1f8; |
---|
| 692 | + } else { /*64x ~ 124*/ |
---|
| 693 | + fine_again_reg = 0x1f; |
---|
| 694 | + coarse_again_reg = 0x1f; |
---|
| 695 | + digital_gain_reg = (a_gain * 0x80 / 0x400) & 0x3f8; |
---|
672 | 696 | } |
---|
673 | 697 | |
---|
674 | 698 | if (a_gain < 0x20) { |
---|
.. | .. |
---|
690 | 714 | SC031GS_REG_FINE_AGAIN, |
---|
691 | 715 | SC031GS_REG_VALUE_08BIT, |
---|
692 | 716 | fine_again_reg); |
---|
| 717 | + |
---|
| 718 | + ret |= sc031gs_write_reg(sc031gs->client, 0x3e06, |
---|
| 719 | + SC031GS_REG_VALUE_16BIT, digital_gain_reg); |
---|
693 | 720 | |
---|
694 | 721 | return ret; |
---|
695 | 722 | } |
---|
.. | .. |
---|
765 | 792 | struct sc031gs *sc031gs = to_sc031gs(sd); |
---|
766 | 793 | const struct sc031gs_mode *mode = sc031gs->cur_mode; |
---|
767 | 794 | |
---|
768 | | - mutex_lock(&sc031gs->mutex); |
---|
769 | | - fi->interval = mode->max_fps; |
---|
770 | | - mutex_unlock(&sc031gs->mutex); |
---|
| 795 | + if (sc031gs->streaming) |
---|
| 796 | + fi->interval = sc031gs->cur_fps; |
---|
| 797 | + else |
---|
| 798 | + fi->interval = mode->max_fps; |
---|
771 | 799 | |
---|
772 | 800 | return 0; |
---|
773 | 801 | } |
---|
.. | .. |
---|
917 | 945 | if (fie->index >= ARRAY_SIZE(supported_modes)) |
---|
918 | 946 | return -EINVAL; |
---|
919 | 947 | |
---|
920 | | - if (fie->code != PIX_FORMAT) |
---|
921 | | - return -EINVAL; |
---|
| 948 | + fie->code = PIX_FORMAT; |
---|
922 | 949 | |
---|
923 | 950 | fie->width = supported_modes[fie->index].width; |
---|
924 | 951 | fie->height = supported_modes[fie->index].height; |
---|
.. | .. |
---|
967 | 994 | .pad = &sc031gs_pad_ops, |
---|
968 | 995 | }; |
---|
969 | 996 | |
---|
| 997 | +static void sc031gs_modify_fps_info(struct sc031gs *sc031gs) |
---|
| 998 | +{ |
---|
| 999 | + const struct sc031gs_mode *mode = sc031gs->cur_mode; |
---|
| 1000 | + |
---|
| 1001 | + sc031gs->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / |
---|
| 1002 | + sc031gs->cur_vts; |
---|
| 1003 | +} |
---|
| 1004 | + |
---|
970 | 1005 | static int sc031gs_set_ctrl(struct v4l2_ctrl *ctrl) |
---|
971 | 1006 | { |
---|
972 | 1007 | struct sc031gs *sc031gs = container_of(ctrl->handler, |
---|
.. | .. |
---|
1003 | 1038 | ret = sc031gs_write_reg(sc031gs->client, SC031GS_REG_VTS, |
---|
1004 | 1039 | SC031GS_REG_VALUE_16BIT, |
---|
1005 | 1040 | ctrl->val + sc031gs->cur_mode->height); |
---|
| 1041 | + if (!ret) |
---|
| 1042 | + sc031gs->cur_vts = ctrl->val + sc031gs->cur_mode->height; |
---|
| 1043 | + if (sc031gs->cur_vts != sc031gs->cur_mode->vts_def) |
---|
| 1044 | + sc031gs_modify_fps_info(sc031gs); |
---|
1006 | 1045 | break; |
---|
1007 | 1046 | case V4L2_CID_TEST_PATTERN: |
---|
1008 | 1047 | ret = sc031gs_enable_test_pattern(sc031gs, ctrl->val); |
---|
.. | .. |
---|
1053 | 1092 | sc031gs->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
---|
1054 | 1093 | |
---|
1055 | 1094 | vblank_def = mode->vts_def - mode->height; |
---|
| 1095 | + sc031gs->cur_vts = mode->vts_def; |
---|
1056 | 1096 | sc031gs->vblank = v4l2_ctrl_new_std(handler, &sc031gs_ctrl_ops, |
---|
1057 | 1097 | V4L2_CID_VBLANK, vblank_def, |
---|
1058 | 1098 | SC031GS_VTS_MAX - mode->height, |
---|
.. | .. |
---|
1082 | 1122 | } |
---|
1083 | 1123 | |
---|
1084 | 1124 | sc031gs->subdev.ctrl_handler = handler; |
---|
| 1125 | + sc031gs->cur_fps = mode->max_fps; |
---|
1085 | 1126 | |
---|
1086 | 1127 | return 0; |
---|
1087 | 1128 | |
---|