| .. | .. |
|---|
| 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 = { |
|---|