@@ -76,8 +76,10 @@
#define IMX219_VBLANK_MIN 32
-/* HBLANK control - read only */
-#define IMX219_PPL_DEFAULT 3448
+/* HBLANK control range */
+#define IMX219_PPL_MIN 3448
+#define IMX219_PPL_MAX 0x7ff0
+#define IMX219_REG_HTS CCI_REG16(0x0162)
#define IMX219_REG_LINE_LENGTH_A CCI_REG16(0x0162)
#define IMX219_REG_X_ADD_STA_A CCI_REG16(0x0164)
@@ -422,6 +424,10 @@ static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
cci_write(imx219->regmap, IMX219_REG_VTS,
format->height + ctrl->val, &ret);
break;
+ case V4L2_CID_HBLANK:
+ cci_write(imx219->regmap, IMX219_REG_HTS,
+ format->width + ctrl->val, &ret);
+ break;
case V4L2_CID_TEST_PATTERN_RED:
cci_write(imx219->regmap, IMX219_REG_TESTP_RED,
ctrl->val, &ret);
@@ -496,12 +502,11 @@ static int imx219_init_controls(struct imx219 *imx219)
V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
IMX219_VTS_MAX - mode->height, 1,
mode->vts_def - mode->height);
- hblank = IMX219_PPL_DEFAULT - mode->width;
+ hblank = IMX219_PPL_MIN - mode->width;
imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
- V4L2_CID_HBLANK, hblank, hblank,
+ V4L2_CID_HBLANK, hblank,
+ IMX219_PPL_MIN - mode->width,
1, hblank);
- if (imx219->hblank)
- imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
exposure_max = mode->vts_def - 4;
exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
exposure_max : IMX219_EXPOSURE_DEFAULT;
@@ -842,6 +847,7 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
crop->top = (IMX219_NATIVE_HEIGHT - crop->height) / 2;
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ u32 prev_hts = format->width + imx219->hblank->val;
int exposure_max;
int exposure_def;
int hblank;
@@ -861,13 +867,18 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
exposure_max, imx219->exposure->step,
exposure_def);
/*
- * Currently PPL is fixed to IMX219_PPL_DEFAULT, so hblank
- * depends on mode->width only, and is not changeble in any
- * way other than changing the mode.
+ * Retain PPL setting from previous mode so that the
+ * line time does not change on a mode change.
+ * Limits have to be recomputed as the controls define
+ * the blanking only, so PPL values need to have the
+ * mode width subtracted.
*/
- hblank = IMX219_PPL_DEFAULT - mode->width;
- __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank, 1,
- hblank);
+ hblank = prev_hts - mode->width;
+ __v4l2_ctrl_modify_range(imx219->hblank,
+ IMX219_PPL_MIN - mode->width,
+ IMX219_PPL_MAX - mode->width,
+ 1, IMX219_PPL_MIN - mode->width);
+ __v4l2_ctrl_s_ctrl(imx219->hblank, hblank);
}
return 0;