| .. | .. |
|---|
| 120 | 120 | |
|---|
| 121 | 121 | #define SC401AI_NUM_SUPPLIES ARRAY_SIZE(sc401ai_supply_names) |
|---|
| 122 | 122 | |
|---|
| 123 | | -enum sc401ai_max_pad { |
|---|
| 124 | | - PAD0, /* link to isp */ |
|---|
| 125 | | - PAD1, /* link to csi wr0 | hdr x2:L x3:M */ |
|---|
| 126 | | - PAD2, /* link to csi wr1 | hdr x3:L */ |
|---|
| 127 | | - PAD3, /* link to csi wr2 | hdr x2:M x3:S */ |
|---|
| 128 | | - PAD_MAX, |
|---|
| 129 | | -}; |
|---|
| 130 | | - |
|---|
| 131 | 123 | struct regval { |
|---|
| 132 | 124 | u16 addr; |
|---|
| 133 | 125 | u8 val; |
|---|
| .. | .. |
|---|
| 170 | 162 | struct v4l2_ctrl *pixel_rate; |
|---|
| 171 | 163 | struct v4l2_ctrl *link_freq; |
|---|
| 172 | 164 | struct mutex mutex; |
|---|
| 165 | + struct v4l2_fract cur_fps; |
|---|
| 173 | 166 | bool streaming; |
|---|
| 174 | 167 | bool power_on; |
|---|
| 175 | 168 | unsigned int lane_num; |
|---|
| .. | .. |
|---|
| 709 | 702 | __v4l2_ctrl_modify_range(sc401ai->vblank, vblank_def, |
|---|
| 710 | 703 | SC401AI_VTS_MAX - mode->height, |
|---|
| 711 | 704 | 1, vblank_def); |
|---|
| 705 | + sc401ai->cur_fps = mode->max_fps; |
|---|
| 706 | + sc401ai->cur_vts = mode->vts_def; |
|---|
| 712 | 707 | } |
|---|
| 713 | 708 | |
|---|
| 714 | 709 | mutex_unlock(&sc401ai->mutex); |
|---|
| .. | .. |
|---|
| 800 | 795 | struct sc401ai *sc401ai = to_sc401ai(sd); |
|---|
| 801 | 796 | const struct sc401ai_mode *mode = sc401ai->cur_mode; |
|---|
| 802 | 797 | |
|---|
| 803 | | - mutex_lock(&sc401ai->mutex); |
|---|
| 804 | | - fi->interval = mode->max_fps; |
|---|
| 805 | | - mutex_unlock(&sc401ai->mutex); |
|---|
| 798 | + if (sc401ai->streaming) |
|---|
| 799 | + fi->interval = sc401ai->cur_fps; |
|---|
| 800 | + else |
|---|
| 801 | + fi->interval = mode->max_fps; |
|---|
| 806 | 802 | |
|---|
| 807 | 803 | return 0; |
|---|
| 808 | 804 | } |
|---|
| 809 | 805 | |
|---|
| 810 | 806 | static int sc401ai_g_mbus_config(struct v4l2_subdev *sd, |
|---|
| 811 | | - struct v4l2_mbus_config *config) |
|---|
| 807 | + unsigned int pad_id, |
|---|
| 808 | + struct v4l2_mbus_config *config) |
|---|
| 812 | 809 | { |
|---|
| 813 | 810 | struct sc401ai *sc401ai = to_sc401ai(sd); |
|---|
| 814 | 811 | const struct sc401ai_mode *mode = sc401ai->cur_mode; |
|---|
| .. | .. |
|---|
| 823 | 820 | if (mode->hdr_mode == HDR_X3) |
|---|
| 824 | 821 | val |= V4L2_MBUS_CSI2_CHANNEL_2; |
|---|
| 825 | 822 | |
|---|
| 826 | | - config->type = V4L2_MBUS_CSI2; |
|---|
| 823 | + config->type = V4L2_MBUS_CSI2_DPHY; |
|---|
| 827 | 824 | config->flags = val; |
|---|
| 828 | 825 | |
|---|
| 829 | 826 | return 0; |
|---|
| .. | .. |
|---|
| 833 | 830 | struct rkmodule_inf *inf) |
|---|
| 834 | 831 | { |
|---|
| 835 | 832 | memset(inf, 0, sizeof(*inf)); |
|---|
| 836 | | - strlcpy(inf->base.sensor, SC401AI_NAME, sizeof(inf->base.sensor)); |
|---|
| 837 | | - strlcpy(inf->base.module, sc401ai->module_name, |
|---|
| 833 | + strscpy(inf->base.sensor, SC401AI_NAME, sizeof(inf->base.sensor)); |
|---|
| 834 | + strscpy(inf->base.module, sc401ai->module_name, |
|---|
| 838 | 835 | sizeof(inf->base.module)); |
|---|
| 839 | | - strlcpy(inf->base.lens, sc401ai->len_name, sizeof(inf->base.lens)); |
|---|
| 836 | + strscpy(inf->base.lens, sc401ai->len_name, sizeof(inf->base.lens)); |
|---|
| 840 | 837 | } |
|---|
| 841 | 838 | |
|---|
| 842 | 839 | static long sc401ai_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) |
|---|
| .. | .. |
|---|
| 1249 | 1246 | static const struct v4l2_subdev_video_ops sc401ai_video_ops = { |
|---|
| 1250 | 1247 | .s_stream = sc401ai_s_stream, |
|---|
| 1251 | 1248 | .g_frame_interval = sc401ai_g_frame_interval, |
|---|
| 1252 | | - .g_mbus_config = sc401ai_g_mbus_config, |
|---|
| 1253 | 1249 | }; |
|---|
| 1254 | 1250 | |
|---|
| 1255 | 1251 | static const struct v4l2_subdev_pad_ops sc401ai_pad_ops = { |
|---|
| .. | .. |
|---|
| 1258 | 1254 | .enum_frame_interval = sc401ai_enum_frame_interval, |
|---|
| 1259 | 1255 | .get_fmt = sc401ai_get_fmt, |
|---|
| 1260 | 1256 | .set_fmt = sc401ai_set_fmt, |
|---|
| 1257 | + .get_mbus_config = sc401ai_g_mbus_config, |
|---|
| 1261 | 1258 | }; |
|---|
| 1262 | 1259 | |
|---|
| 1263 | 1260 | static const struct v4l2_subdev_ops sc401ai_subdev_ops = { |
|---|
| .. | .. |
|---|
| 1265 | 1262 | .video = &sc401ai_video_ops, |
|---|
| 1266 | 1263 | .pad = &sc401ai_pad_ops, |
|---|
| 1267 | 1264 | }; |
|---|
| 1265 | + |
|---|
| 1266 | +static void sc401ai_modify_fps_info(struct sc401ai *sc401ai) |
|---|
| 1267 | +{ |
|---|
| 1268 | + const struct sc401ai_mode *mode = sc401ai->cur_mode; |
|---|
| 1269 | + |
|---|
| 1270 | + sc401ai->cur_fps.denominator = mode->max_fps.denominator * mode->vts_def / |
|---|
| 1271 | + sc401ai->cur_vts; |
|---|
| 1272 | +} |
|---|
| 1268 | 1273 | |
|---|
| 1269 | 1274 | static int sc401ai_set_ctrl(struct v4l2_ctrl *ctrl) |
|---|
| 1270 | 1275 | { |
|---|
| .. | .. |
|---|
| 1324 | 1329 | SC401AI_REG_VALUE_08BIT, |
|---|
| 1325 | 1330 | (ctrl->val + sc401ai->cur_mode->height) |
|---|
| 1326 | 1331 | & 0xff); |
|---|
| 1327 | | - sc401ai->cur_vts = ctrl->val + sc401ai->cur_mode->height; |
|---|
| 1332 | + if (!ret) |
|---|
| 1333 | + sc401ai->cur_vts = ctrl->val + sc401ai->cur_mode->height; |
|---|
| 1334 | + sc401ai_modify_fps_info(sc401ai); |
|---|
| 1328 | 1335 | break; |
|---|
| 1329 | 1336 | case V4L2_CID_TEST_PATTERN: |
|---|
| 1330 | 1337 | ret = sc401ai_enable_test_pattern(sc401ai, ctrl->val); |
|---|
| .. | .. |
|---|
| 1466 | 1473 | } |
|---|
| 1467 | 1474 | |
|---|
| 1468 | 1475 | sc401ai->subdev.ctrl_handler = handler; |
|---|
| 1476 | + sc401ai->cur_fps = mode->max_fps; |
|---|
| 1477 | + sc401ai->cur_vts = mode->vts_def; |
|---|
| 1469 | 1478 | |
|---|
| 1470 | 1479 | return 0; |
|---|
| 1471 | 1480 | |
|---|
| .. | .. |
|---|
| 1713 | 1722 | module_exit(sensor_mod_exit); |
|---|
| 1714 | 1723 | |
|---|
| 1715 | 1724 | MODULE_DESCRIPTION("smartsens sc401ai sensor driver"); |
|---|
| 1716 | | -MODULE_LICENSE("GPL v2"); |
|---|
| 1725 | +MODULE_LICENSE("GPL"); |
|---|