]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: i2c: ov5647: Add control of V4L2_CID_HBLANK
authorDave Stevenson <dave.stevenson@raspberrypi.com>
Mon, 22 Dec 2025 08:15:36 +0000 (13:45 +0530)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Wed, 14 Jan 2026 22:33:03 +0000 (23:33 +0100)
The driver did expose V4L2_CID_HBLANK, but as a READ_ONLY control.

The sensor only uses the HTS register to control the line length,
so convert this control to read/write, with the appropriate ranges.
Adopt the old fixed values as the minimum values permitted in each
mode to avoid issues of it not streaming.

This should allow exposure times up to ~3 seconds (up from ~1sec).

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/media/i2c/ov5647.c

index d6accdd20ef5f3d3c16d2fceadd0fca3afd6fc9e..c89e13442e29796e0971faa204cf7132283c51b1 100644 (file)
@@ -53,6 +53,8 @@
 #define OV5647_REG_AEC_AGC             0x3503
 #define OV5647_REG_GAIN_HI             0x350a
 #define OV5647_REG_GAIN_LO             0x350b
+#define OV5647_REG_HTS_HI              0x380c
+#define OV5647_REG_HTS_LO              0x380d
 #define OV5647_REG_VTS_HI              0x380e
 #define OV5647_REG_VTS_LO              0x380f
 #define OV5647_REG_TIMING_TC_V         0x3820
@@ -79,6 +81,8 @@
 #define OV5647_VBLANK_MIN              24
 #define OV5647_VTS_MAX                 32767
 
+#define OV5647_HTS_MAX                 0x1fff
+
 #define OV5647_EXPOSURE_MIN            4
 #define OV5647_EXPOSURE_STEP           1
 #define OV5647_EXPOSURE_DEFAULT                1000
@@ -187,8 +191,6 @@ static struct regval_list ov5647_2592x1944_10bpp[] = {
        {0x3a19, 0xf8},
        {0x3c01, 0x80},
        {0x3b07, 0x0c},
-       {0x380c, 0x0b},
-       {0x380d, 0x1c},
        {0x3814, 0x11},
        {0x3815, 0x11},
        {0x3708, 0x64},
@@ -276,8 +278,6 @@ static struct regval_list ov5647_1080p30_10bpp[] = {
        {0x3a19, 0xf8},
        {0x3c01, 0x80},
        {0x3b07, 0x0c},
-       {0x380c, 0x09},
-       {0x380d, 0x70},
        {0x3814, 0x11},
        {0x3815, 0x11},
        {0x3708, 0x64},
@@ -375,8 +375,6 @@ static struct regval_list ov5647_2x2binned_10bpp[] = {
        {0x3809, 0x10},
        {0x380a, 0x03},
        {0x380b, 0xcc},
-       {0x380c, 0x07},
-       {0x380d, 0x68},
        {0x3811, 0x0c},
        {0x3813, 0x06},
        {0x3814, 0x31},
@@ -450,8 +448,6 @@ static struct regval_list ov5647_640x480_10bpp[] = {
        {0x3a19, 0xf8},
        {0x3c01, 0x80},
        {0x3b07, 0x0c},
-       {0x380c, 0x07},
-       {0x380d, 0x3c},
        {0x3814, 0x35},
        {0x3815, 0x35},
        {0x3708, 0x64},
@@ -1063,7 +1059,8 @@ static int ov5647_set_pad_fmt(struct v4l2_subdev *sd,
                                         mode->pixel_rate, 1, mode->pixel_rate);
 
                hblank = mode->hts - mode->format.width;
-               __v4l2_ctrl_modify_range(sensor->hblank, hblank, hblank, 1,
+               __v4l2_ctrl_modify_range(sensor->hblank, hblank,
+                                        OV5647_HTS_MAX - mode->format.width, 1,
                                         hblank);
 
                vblank = mode->vts - mode->format.height;
@@ -1333,6 +1330,10 @@ static int ov5647_s_ctrl(struct v4l2_ctrl *ctrl)
                ret = ov5647_write16(sd, OV5647_REG_VTS_HI,
                                     sensor->mode->format.height + ctrl->val);
                break;
+       case V4L2_CID_HBLANK:
+               ret = ov5647_write16(sd, OV5647_REG_HTS_HI,
+                                    sensor->mode->format.width + ctrl->val);
+               break;
        case V4L2_CID_TEST_PATTERN:
                ret = ov5647_write(sd, OV5647_REG_ISPCTRL3D,
                                   ov5647_test_pattern_val[ctrl->val]);
@@ -1340,7 +1341,6 @@ static int ov5647_s_ctrl(struct v4l2_ctrl *ctrl)
 
        /* Read-only, but we adjust it based on mode. */
        case V4L2_CID_PIXEL_RATE:
-       case V4L2_CID_HBLANK:
                /* Read-only, but we adjust it based on mode. */
                break;
 
@@ -1416,10 +1416,11 @@ static int ov5647_init_controls(struct ov5647 *sensor)
                                               sensor->mode->pixel_rate, 1,
                                               sensor->mode->pixel_rate);
 
-       /* By default, HBLANK is read only, but it does change per mode. */
        hblank = sensor->mode->hts - sensor->mode->format.width;
        sensor->hblank = v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
-                                          V4L2_CID_HBLANK, hblank, hblank, 1,
+                                          V4L2_CID_HBLANK, hblank,
+                                          OV5647_HTS_MAX -
+                                          sensor->mode->format.width, 1,
                                           hblank);
 
        sensor->vblank = v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
@@ -1449,7 +1450,6 @@ static int ov5647_init_controls(struct ov5647 *sensor)
                goto handler_free;
 
        sensor->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-       sensor->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
        sensor->sd.ctrl_handler = &sensor->ctrls;
 
        return 0;