.. | .. |
---|
93 | 93 | |
---|
94 | 94 | #define SC2232_NUM_SUPPLIES ARRAY_SIZE(sc2232_supply_names) |
---|
95 | 95 | |
---|
96 | | -enum sc2232_max_pad { |
---|
97 | | - PAD0, |
---|
98 | | - PAD1, |
---|
99 | | - PAD2, |
---|
100 | | - PAD3, |
---|
101 | | - PAD_MAX, |
---|
102 | | -}; |
---|
103 | | - |
---|
104 | 96 | struct regval { |
---|
105 | 97 | u16 addr; |
---|
106 | 98 | u8 val; |
---|
.. | .. |
---|
141 | 133 | struct v4l2_ctrl *pixel_rate; |
---|
142 | 134 | struct v4l2_ctrl *link_freq; |
---|
143 | 135 | struct mutex mutex; |
---|
| 136 | + struct v4l2_fract cur_fps; |
---|
144 | 137 | bool streaming; |
---|
145 | 138 | bool power_on; |
---|
146 | 139 | const struct sc2232_mode *cur_mode; |
---|
.. | .. |
---|
518 | 511 | pixel_rate = (u32)link_freq_items[mode->mipi_freq_idx] / |
---|
519 | 512 | mode->bpp * 2 * SC2232_LANES; |
---|
520 | 513 | __v4l2_ctrl_s_ctrl_int64(sc2232->pixel_rate, pixel_rate); |
---|
| 514 | + sc2232->cur_fps = mode->max_fps; |
---|
| 515 | + sc2232->cur_vts = mode->vts_def; |
---|
521 | 516 | } |
---|
522 | 517 | |
---|
523 | 518 | mutex_unlock(&sc2232->mutex); |
---|
.. | .. |
---|
594 | 589 | struct sc2232 *sc2232 = to_sc2232(sd); |
---|
595 | 590 | const struct sc2232_mode *mode = sc2232->cur_mode; |
---|
596 | 591 | |
---|
597 | | - mutex_lock(&sc2232->mutex); |
---|
598 | | - fi->interval = mode->max_fps; |
---|
599 | | - mutex_unlock(&sc2232->mutex); |
---|
| 592 | + if (sc2232->streaming) |
---|
| 593 | + fi->interval = sc2232->cur_fps; |
---|
| 594 | + else |
---|
| 595 | + fi->interval = mode->max_fps; |
---|
600 | 596 | |
---|
601 | 597 | return 0; |
---|
602 | 598 | } |
---|
603 | 599 | |
---|
604 | | -static int sc2232_g_mbus_config(struct v4l2_subdev *sd, |
---|
| 600 | +static int sc2232_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id, |
---|
605 | 601 | struct v4l2_mbus_config *config) |
---|
606 | 602 | { |
---|
607 | 603 | struct sc2232 *sc2232 = to_sc2232(sd); |
---|
.. | .. |
---|
618 | 614 | V4L2_MBUS_CSI2_CONTINUOUS_CLOCK | |
---|
619 | 615 | V4L2_MBUS_CSI2_CHANNEL_1; |
---|
620 | 616 | |
---|
621 | | - config->type = V4L2_MBUS_CSI2; |
---|
| 617 | + config->type = V4L2_MBUS_CSI2_DPHY; |
---|
622 | 618 | config->flags = val; |
---|
623 | 619 | |
---|
624 | 620 | return 0; |
---|
.. | .. |
---|
803 | 799 | } |
---|
804 | 800 | |
---|
805 | 801 | ret = sc2232_ioctl(sd, cmd, inf); |
---|
806 | | - if (!ret) |
---|
| 802 | + if (!ret) { |
---|
807 | 803 | ret = copy_to_user(up, inf, sizeof(*inf)); |
---|
| 804 | + if (ret) |
---|
| 805 | + ret = -EFAULT; |
---|
| 806 | + } |
---|
808 | 807 | kfree(inf); |
---|
809 | 808 | break; |
---|
810 | 809 | case RKMODULE_AWB_CFG: |
---|
.. | .. |
---|
817 | 816 | ret = copy_from_user(cfg, up, sizeof(*cfg)); |
---|
818 | 817 | if (!ret) |
---|
819 | 818 | ret = sc2232_ioctl(sd, cmd, cfg); |
---|
| 819 | + else |
---|
| 820 | + ret = -EFAULT; |
---|
820 | 821 | kfree(cfg); |
---|
821 | 822 | break; |
---|
822 | 823 | case RKMODULE_GET_HDR_CFG: |
---|
.. | .. |
---|
827 | 828 | } |
---|
828 | 829 | |
---|
829 | 830 | ret = sc2232_ioctl(sd, cmd, hdr); |
---|
830 | | - if (!ret) |
---|
| 831 | + if (!ret) { |
---|
831 | 832 | ret = copy_to_user(up, hdr, sizeof(*hdr)); |
---|
| 833 | + if (ret) |
---|
| 834 | + ret = -EFAULT; |
---|
| 835 | + } |
---|
832 | 836 | kfree(hdr); |
---|
833 | 837 | break; |
---|
834 | 838 | case RKMODULE_SET_HDR_CFG: |
---|
.. | .. |
---|
841 | 845 | ret = copy_from_user(hdr, up, sizeof(*hdr)); |
---|
842 | 846 | if (!ret) |
---|
843 | 847 | ret = sc2232_ioctl(sd, cmd, hdr); |
---|
| 848 | + else |
---|
| 849 | + ret = -EFAULT; |
---|
844 | 850 | kfree(hdr); |
---|
845 | 851 | break; |
---|
846 | 852 | case PREISP_CMD_SET_HDRAE_EXP: |
---|
.. | .. |
---|
853 | 859 | ret = copy_from_user(hdrae, up, sizeof(*hdrae)); |
---|
854 | 860 | if (!ret) |
---|
855 | 861 | ret = sc2232_ioctl(sd, cmd, hdrae); |
---|
| 862 | + else |
---|
| 863 | + ret = -EFAULT; |
---|
856 | 864 | kfree(hdrae); |
---|
857 | 865 | break; |
---|
858 | 866 | case RKMODULE_SET_CONVERSION_GAIN: |
---|
859 | 867 | ret = copy_from_user(&cg, up, sizeof(cg)); |
---|
860 | 868 | if (!ret) |
---|
861 | 869 | ret = sc2232_ioctl(sd, cmd, &cg); |
---|
| 870 | + else |
---|
| 871 | + ret = -EFAULT; |
---|
862 | 872 | break; |
---|
863 | 873 | case RKMODULE_SET_QUICK_STREAM: |
---|
864 | 874 | ret = copy_from_user(&stream, up, sizeof(u32)); |
---|
865 | 875 | if (!ret) |
---|
866 | 876 | ret = sc2232_ioctl(sd, cmd, &stream); |
---|
| 877 | + else |
---|
| 878 | + ret = -EFAULT; |
---|
867 | 879 | break; |
---|
868 | 880 | default: |
---|
869 | 881 | ret = -ENOIOCTLCMD; |
---|
.. | .. |
---|
1128 | 1140 | static const struct v4l2_subdev_video_ops sc2232_video_ops = { |
---|
1129 | 1141 | .s_stream = sc2232_s_stream, |
---|
1130 | 1142 | .g_frame_interval = sc2232_g_frame_interval, |
---|
1131 | | - .g_mbus_config = sc2232_g_mbus_config, |
---|
1132 | 1143 | }; |
---|
1133 | 1144 | |
---|
1134 | 1145 | static const struct v4l2_subdev_pad_ops sc2232_pad_ops = { |
---|
.. | .. |
---|
1137 | 1148 | .enum_frame_interval = sc2232_enum_frame_interval, |
---|
1138 | 1149 | .get_fmt = sc2232_get_fmt, |
---|
1139 | 1150 | .set_fmt = sc2232_set_fmt, |
---|
| 1151 | + .get_mbus_config = sc2232_g_mbus_config, |
---|
1140 | 1152 | }; |
---|
1141 | 1153 | |
---|
1142 | 1154 | static const struct v4l2_subdev_ops sc2232_subdev_ops = { |
---|
.. | .. |
---|
1144 | 1156 | .video = &sc2232_video_ops, /* */ |
---|
1145 | 1157 | .pad = &sc2232_pad_ops, /* */ |
---|
1146 | 1158 | }; |
---|
| 1159 | + |
---|
| 1160 | +static void sc2232_modify_fps_info(struct sc2232 *sc2232) |
---|
| 1161 | +{ |
---|
| 1162 | + const struct sc2232_mode *mode = sc2232->cur_mode; |
---|
| 1163 | + |
---|
| 1164 | + sc2232->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / |
---|
| 1165 | + sc2232->cur_vts; |
---|
| 1166 | +} |
---|
1147 | 1167 | |
---|
1148 | 1168 | static int sc2232_set_ctrl(struct v4l2_ctrl *ctrl) |
---|
1149 | 1169 | { |
---|
.. | .. |
---|
1172 | 1192 | switch (ctrl->id) { |
---|
1173 | 1193 | case V4L2_CID_EXPOSURE: |
---|
1174 | 1194 | if (sc2232->cur_mode->hdr_mode != NO_HDR) |
---|
1175 | | - return ret; |
---|
| 1195 | + goto ctrl_end; |
---|
1176 | 1196 | val = ctrl->val << 1; |
---|
1177 | 1197 | ret = sc2232_write_reg(sc2232->client, |
---|
1178 | 1198 | SC2232_REG_EXP_LONG_L, |
---|
.. | .. |
---|
1190 | 1210 | break; |
---|
1191 | 1211 | case V4L2_CID_ANALOGUE_GAIN: |
---|
1192 | 1212 | if (sc2232->cur_mode->hdr_mode != NO_HDR) |
---|
1193 | | - return ret; |
---|
| 1213 | + goto ctrl_end; |
---|
1194 | 1214 | ret = sc2232_set_gain(sc2232, ctrl->val); |
---|
1195 | 1215 | break; |
---|
1196 | 1216 | case V4L2_CID_VBLANK: |
---|
1197 | 1217 | ret = sc2232_write_reg(sc2232->client, SC2232_REG_VTS, |
---|
1198 | 1218 | SC2232_REG_VALUE_16BIT, |
---|
1199 | 1219 | ctrl->val + sc2232->cur_mode->height); |
---|
| 1220 | + if (!ret) |
---|
| 1221 | + sc2232->cur_vts = ctrl->val + sc2232->cur_mode->height; |
---|
| 1222 | + sc2232_modify_fps_info(sc2232); |
---|
1200 | 1223 | dev_dbg(&client->dev, "set vblank 0x%x\n", |
---|
1201 | 1224 | ctrl->val); |
---|
1202 | 1225 | break; |
---|
.. | .. |
---|
1232 | 1255 | break; |
---|
1233 | 1256 | } |
---|
1234 | 1257 | |
---|
| 1258 | +ctrl_end: |
---|
1235 | 1259 | pm_runtime_put(&client->dev); |
---|
1236 | 1260 | return ret; |
---|
1237 | 1261 | } |
---|
.. | .. |
---|
1303 | 1327 | |
---|
1304 | 1328 | sc2232->subdev.ctrl_handler = handler; |
---|
1305 | 1329 | sc2232->has_init_exp = false; |
---|
| 1330 | + sc2232->cur_vts = mode->vts_def; |
---|
| 1331 | + sc2232->cur_fps = mode->max_fps; |
---|
1306 | 1332 | |
---|
1307 | 1333 | return 0; |
---|
1308 | 1334 | |
---|