.. | .. |
---|
89 | 89 | #define to_sc210iot(sd) container_of(sd, struct sc210iot, subdev) |
---|
90 | 90 | |
---|
91 | 91 | enum { |
---|
92 | | - PAD0, |
---|
93 | | - PAD1, |
---|
94 | | - PAD2, |
---|
95 | | - PAD3, |
---|
96 | | - PAD_MAX, |
---|
97 | | -}; |
---|
98 | | - |
---|
99 | | -enum { |
---|
100 | 92 | LINK_FREQ_INDEX, |
---|
101 | 93 | }; |
---|
102 | 94 | |
---|
.. | .. |
---|
148 | 140 | struct v4l2_ctrl *link_freq; |
---|
149 | 141 | struct v4l2_ctrl *pixel_rate; |
---|
150 | 142 | struct mutex lock; |
---|
| 143 | + struct v4l2_fract cur_fps; |
---|
| 144 | + u32 cur_vts; |
---|
151 | 145 | bool streaming; |
---|
152 | 146 | bool power_on; |
---|
153 | 147 | bool is_thunderboot; |
---|
.. | .. |
---|
371 | 365 | return ret; |
---|
372 | 366 | } |
---|
373 | 367 | |
---|
| 368 | +static void sc210iot_modify_fps_info(struct sc210iot *sc210iot) |
---|
| 369 | +{ |
---|
| 370 | + const struct sc210iot_mode *mode = sc210iot->cur_mode; |
---|
| 371 | + |
---|
| 372 | + sc210iot->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / |
---|
| 373 | + sc210iot->cur_vts; |
---|
| 374 | +} |
---|
| 375 | + |
---|
374 | 376 | static int sc210iot_set_ctrl(struct v4l2_ctrl *ctrl) |
---|
375 | 377 | { |
---|
376 | 378 | struct sc210iot *sc210iot = container_of(ctrl->handler, |
---|
.. | .. |
---|
402 | 404 | dev_dbg(sc210iot->dev, "set vblank 0x%x\n", ctrl->val); |
---|
403 | 405 | ret = sc210iot_write_reg(sc210iot, SC210IOT_REG_VTS_H, |
---|
404 | 406 | (ctrl->val + sc210iot->cur_mode->height) >> 8); |
---|
405 | | - ret = sc210iot_write_reg(sc210iot, SC210IOT_REG_VTS_L, |
---|
| 407 | + ret |= sc210iot_write_reg(sc210iot, SC210IOT_REG_VTS_L, |
---|
406 | 408 | (ctrl->val + sc210iot->cur_mode->height) & 0xff); |
---|
| 409 | + if (!ret) |
---|
| 410 | + sc210iot->cur_vts = ctrl->val + sc210iot->cur_mode->height; |
---|
| 411 | + sc210iot_modify_fps_info(sc210iot); |
---|
407 | 412 | break; |
---|
408 | 413 | case V4L2_CID_HFLIP: |
---|
409 | 414 | regmap_update_bits(sc210iot->regmap, SC210IOT_REG_MIRROR_FLIP, |
---|
.. | .. |
---|
487 | 492 | } |
---|
488 | 493 | sc210iot->subdev.ctrl_handler = handler; |
---|
489 | 494 | sc210iot->has_init_exp = false; |
---|
| 495 | + sc210iot->cur_fps = mode->max_fps; |
---|
| 496 | + sc210iot->cur_vts = mode->vts_def; |
---|
490 | 497 | return 0; |
---|
491 | 498 | err_free_handler: |
---|
492 | 499 | v4l2_ctrl_handler_free(handler); |
---|
.. | .. |
---|
687 | 694 | return ret; |
---|
688 | 695 | } |
---|
689 | 696 | ret = sc210iot_ioctl(sd, cmd, inf); |
---|
690 | | - if (!ret) |
---|
| 697 | + if (!ret) { |
---|
691 | 698 | ret = copy_to_user(up, inf, sizeof(*inf)); |
---|
| 699 | + if (ret) |
---|
| 700 | + ret = -EFAULT; |
---|
| 701 | + } |
---|
692 | 702 | kfree(inf); |
---|
693 | 703 | break; |
---|
694 | 704 | case RKMODULE_GET_HDR_CFG: |
---|
.. | .. |
---|
698 | 708 | return ret; |
---|
699 | 709 | } |
---|
700 | 710 | ret = sc210iot_ioctl(sd, cmd, hdr); |
---|
701 | | - if (!ret) |
---|
| 711 | + if (!ret) { |
---|
702 | 712 | ret = copy_to_user(up, hdr, sizeof(*hdr)); |
---|
| 713 | + if (ret) |
---|
| 714 | + ret = -EFAULT; |
---|
| 715 | + } |
---|
703 | 716 | kfree(hdr); |
---|
704 | | - break; |
---|
705 | | - case RKMODULE_SET_HDR_CFG: |
---|
706 | 717 | break; |
---|
707 | 718 | case RKMODULE_SET_QUICK_STREAM: |
---|
708 | 719 | ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
709 | 720 | if (!ret) |
---|
710 | 721 | ret = sc210iot_ioctl(sd, cmd, &stream); |
---|
| 722 | + else |
---|
| 723 | + ret = -EFAULT; |
---|
711 | 724 | break; |
---|
712 | 725 | default: |
---|
713 | 726 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
758 | 771 | struct sc210iot *sc210iot = to_sc210iot(sd); |
---|
759 | 772 | const struct sc210iot_mode *mode = sc210iot->cur_mode; |
---|
760 | 773 | |
---|
761 | | - mutex_lock(&sc210iot->lock); |
---|
762 | | - fi->interval = mode->max_fps; |
---|
763 | | - mutex_unlock(&sc210iot->lock); |
---|
| 774 | + if (sc210iot->streaming) |
---|
| 775 | + fi->interval = sc210iot->cur_fps; |
---|
| 776 | + else |
---|
| 777 | + fi->interval = mode->max_fps; |
---|
764 | 778 | return 0; |
---|
765 | 779 | } |
---|
766 | 780 | |
---|
767 | | -static int sc210iot_g_mbus_config(struct v4l2_subdev *sd, |
---|
| 781 | +static int sc210iot_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
---|
768 | 782 | struct v4l2_mbus_config *config) |
---|
769 | 783 | { |
---|
770 | 784 | struct sc210iot *sc210iot = to_sc210iot(sd); |
---|
771 | 785 | |
---|
772 | 786 | u32 val = 1 << (SC210IOT_LANES - 1) | V4L2_MBUS_CSI2_CHANNEL_0 | |
---|
773 | 787 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; |
---|
774 | | - config->type = V4L2_MBUS_CSI2; |
---|
| 788 | + config->type = V4L2_MBUS_CSI2_DPHY; |
---|
775 | 789 | config->flags = (sc210iot->cur_mode->hdr_mode == NO_HDR) ? |
---|
776 | 790 | val : (val | V4L2_MBUS_CSI2_CHANNEL_1); |
---|
777 | 791 | return 0; |
---|
.. | .. |
---|
856 | 870 | __v4l2_ctrl_modify_range(sc210iot->vblank, vblank_def, |
---|
857 | 871 | SC210IOT_VTS_MAX - mode->height, |
---|
858 | 872 | 1, vblank_def); |
---|
| 873 | + sc210iot->cur_fps = mode->max_fps; |
---|
| 874 | + sc210iot->cur_vts = mode->vts_def; |
---|
859 | 875 | } |
---|
860 | 876 | mutex_unlock(&sc210iot->lock); |
---|
861 | 877 | return 0; |
---|
.. | .. |
---|
951 | 967 | static const struct v4l2_subdev_video_ops sc210iot_video_ops = { |
---|
952 | 968 | .s_stream = sc210iot_s_stream, |
---|
953 | 969 | .g_frame_interval = sc210iot_g_frame_interval, |
---|
954 | | - .g_mbus_config = sc210iot_g_mbus_config, |
---|
955 | 970 | }; |
---|
956 | 971 | |
---|
957 | 972 | static const struct v4l2_subdev_pad_ops sc210iot_pad_ops = { |
---|
.. | .. |
---|
960 | 975 | .enum_frame_interval = sc210iot_enum_frame_interval, |
---|
961 | 976 | .get_fmt = sc210iot_get_fmt, |
---|
962 | 977 | .set_fmt = sc210iot_set_fmt, |
---|
| 978 | + .get_mbus_config = sc210iot_g_mbus_config, |
---|
963 | 979 | }; |
---|
964 | 980 | |
---|
965 | 981 | static const struct v4l2_subdev_ops sc210iot_subdev_ops = { |
---|