6262#define OV7251_ACTIVE_HEIGHT 488
6363
6464#define OV7251_FIXED_PPL 928
65+ #define OV7251_TIMING_VTS_REG 0x380e
66+ #define OV7251_TIMING_MIN_VTS 1
67+ #define OV7251_TIMING_MAX_VTS 0xffff
68+ #define OV7251_INTEGRATION_MARGIN 20
6569
6670struct reg_value {
6771 u16 reg ;
@@ -71,6 +75,7 @@ struct reg_value {
7175struct ov7251_mode_info {
7276 u32 width ;
7377 u32 height ;
78+ u32 vts ;
7479 const struct reg_value * data ;
7580 u32 data_size ;
7681 u32 pixel_clock ;
@@ -142,6 +147,7 @@ struct ov7251 {
142147 struct v4l2_ctrl * exposure ;
143148 struct v4l2_ctrl * gain ;
144149 struct v4l2_ctrl * hblank ;
150+ struct v4l2_ctrl * vblank ;
145151
146152 /* Cached register values */
147153 u8 aec_pk_manual ;
@@ -637,6 +643,7 @@ static const struct ov7251_mode_info ov7251_mode_info_data[] = {
637643 {
638644 .width = 640 ,
639645 .height = 480 ,
646+ .vts = 1724 ,
640647 .data = ov7251_setting_vga_30fps ,
641648 .data_size = ARRAY_SIZE (ov7251_setting_vga_30fps ),
642649 .exposure_max = 1704 ,
@@ -649,6 +656,7 @@ static const struct ov7251_mode_info ov7251_mode_info_data[] = {
649656 {
650657 .width = 640 ,
651658 .height = 480 ,
659+ .vts = 860 ,
652660 .data = ov7251_setting_vga_60fps ,
653661 .data_size = ARRAY_SIZE (ov7251_setting_vga_60fps ),
654662 .exposure_max = 840 ,
@@ -661,6 +669,7 @@ static const struct ov7251_mode_info ov7251_mode_info_data[] = {
661669 {
662670 .width = 640 ,
663671 .height = 480 ,
672+ .vts = 572 ,
664673 .data = ov7251_setting_vga_90fps ,
665674 .data_size = ARRAY_SIZE (ov7251_setting_vga_90fps ),
666675 .exposure_max = 552 ,
@@ -1001,12 +1010,36 @@ static const char * const ov7251_test_pattern_menu[] = {
10011010 "Vertical Pattern Bars" ,
10021011};
10031012
1013+ static int ov7251_vts_configure (struct ov7251 * ov7251 , s32 vblank )
1014+ {
1015+ u8 vts [2 ];
1016+
1017+ vts [0 ] = ((ov7251 -> current_mode -> height + vblank ) & 0xff00 ) >> 8 ;
1018+ vts [1 ] = ((ov7251 -> current_mode -> height + vblank ) & 0x00ff );
1019+
1020+ return ov7251_write_seq_regs (ov7251 , OV7251_TIMING_VTS_REG , vts , 2 );
1021+ }
1022+
10041023static int ov7251_s_ctrl (struct v4l2_ctrl * ctrl )
10051024{
10061025 struct ov7251 * ov7251 = container_of (ctrl -> handler ,
10071026 struct ov7251 , ctrls );
10081027 int ret ;
10091028
1029+ /* If VBLANK is altered we need to update exposure to compensate */
1030+ if (ctrl -> id == V4L2_CID_VBLANK ) {
1031+ int exposure_max ;
1032+
1033+ exposure_max = ov7251 -> current_mode -> height + ctrl -> val -
1034+ OV7251_INTEGRATION_MARGIN ;
1035+ __v4l2_ctrl_modify_range (ov7251 -> exposure ,
1036+ ov7251 -> exposure -> minimum ,
1037+ exposure_max ,
1038+ ov7251 -> exposure -> step ,
1039+ min (ov7251 -> exposure -> val ,
1040+ exposure_max ));
1041+ }
1042+
10101043 /* v4l2_ctrl_lock() locks our mutex */
10111044
10121045 if (!pm_runtime_get_if_in_use (ov7251 -> dev ))
@@ -1028,6 +1061,9 @@ static int ov7251_s_ctrl(struct v4l2_ctrl *ctrl)
10281061 case V4L2_CID_VFLIP :
10291062 ret = ov7251_set_vflip (ov7251 , ctrl -> val );
10301063 break ;
1064+ case V4L2_CID_VBLANK :
1065+ ret = ov7251_vts_configure (ov7251 , ctrl -> val );
1066+ break ;
10311067 default :
10321068 ret = - EINVAL ;
10331069 break ;
@@ -1179,6 +1215,7 @@ static int ov7251_set_format(struct v4l2_subdev *sd,
11791215{
11801216 struct ov7251 * ov7251 = to_ov7251 (sd );
11811217 struct v4l2_mbus_framefmt * __format ;
1218+ int vblank_max , vblank_def ;
11821219 struct v4l2_rect * __crop ;
11831220 const struct ov7251_mode_info * new_mode ;
11841221 int ret = 0 ;
@@ -1212,6 +1249,14 @@ static int ov7251_set_format(struct v4l2_subdev *sd,
12121249 if (ret < 0 )
12131250 goto exit ;
12141251
1252+ vblank_max = OV7251_TIMING_MAX_VTS - new_mode -> height ;
1253+ vblank_def = new_mode -> vts - new_mode -> height ;
1254+ ret = __v4l2_ctrl_modify_range (ov7251 -> vblank ,
1255+ OV7251_TIMING_MIN_VTS ,
1256+ vblank_max , 1 , vblank_def );
1257+ if (ret < 0 )
1258+ goto exit ;
1259+
12151260 ov7251 -> current_mode = new_mode ;
12161261 }
12171262
@@ -1490,6 +1535,7 @@ static int ov7251_detect_chip(struct ov7251 *ov7251)
14901535
14911536static int ov7251_init_ctrls (struct ov7251 * ov7251 )
14921537{
1538+ int vblank_max , vblank_def ;
14931539 s64 pixel_rate ;
14941540 int hblank ;
14951541
@@ -1533,6 +1579,13 @@ static int ov7251_init_ctrls(struct ov7251 *ov7251)
15331579 if (ov7251 -> hblank )
15341580 ov7251 -> hblank -> flags |= V4L2_CTRL_FLAG_READ_ONLY ;
15351581
1582+ vblank_max = OV7251_TIMING_MAX_VTS - ov7251 -> current_mode -> height ;
1583+ vblank_def = ov7251 -> current_mode -> vts - ov7251 -> current_mode -> height ;
1584+ ov7251 -> vblank = v4l2_ctrl_new_std (& ov7251 -> ctrls , & ov7251_ctrl_ops ,
1585+ V4L2_CID_VBLANK ,
1586+ OV7251_TIMING_MIN_VTS , vblank_max , 1 ,
1587+ vblank_def );
1588+
15361589 ov7251 -> sd .ctrl_handler = & ov7251 -> ctrls ;
15371590
15381591 if (ov7251 -> ctrls .error ) {
0 commit comments