aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0706-media-i2c-imx219-Scale-the-pixel-clock-rate-for-the-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0706-media-i2c-imx219-Scale-the-pixel-clock-rate-for-the-.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.15/950-0706-media-i2c-imx219-Scale-the-pixel-clock-rate-for-the-.patch129
1 files changed, 129 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0706-media-i2c-imx219-Scale-the-pixel-clock-rate-for-the-.patch b/target/linux/bcm27xx/patches-5.15/950-0706-media-i2c-imx219-Scale-the-pixel-clock-rate-for-the-.patch
new file mode 100644
index 0000000000..124117ce8b
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.15/950-0706-media-i2c-imx219-Scale-the-pixel-clock-rate-for-the-.patch
@@ -0,0 +1,129 @@
+From 055e3d70b0227e26d58b2efc4561eb21a3fbf640 Mon Sep 17 00:00:00 2001
+From: Naushir Patuck <naush@raspberrypi.com>
+Date: Tue, 8 Feb 2022 13:49:11 +0000
+Subject: [PATCH] media: i2c: imx219: Scale the pixel clock rate for
+ the 640x480 mode
+
+The 640x480 mode uses a special binning mode for high framerate operation where
+the pixel rate is effectively doubled. Account for this when setting up the
+pixel clock rate, and applying the vblank and exposure controls.
+
+Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
+---
+ drivers/media/i2c/imx219.c | 33 ++++++++++++++++++++++++++-------
+ 1 file changed, 26 insertions(+), 7 deletions(-)
+
+--- a/drivers/media/i2c/imx219.c
++++ b/drivers/media/i2c/imx219.c
+@@ -153,6 +153,9 @@ struct imx219_mode {
+
+ /* Default register values */
+ struct imx219_reg_list reg_list;
++
++ /* Relative pixel clock rate factor for the mode. */
++ unsigned int rate_factor;
+ };
+
+ /*
+@@ -495,6 +498,7 @@ static const struct imx219_mode supporte
+ .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
+ .regs = mode_3280x2464_regs,
+ },
++ .rate_factor = 1,
+ },
+ {
+ /* 1080P 30fps cropped */
+@@ -511,6 +515,7 @@ static const struct imx219_mode supporte
+ .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
+ .regs = mode_1920_1080_regs,
+ },
++ .rate_factor = 1,
+ },
+ {
+ /* 2x2 binned 30fps mode */
+@@ -527,6 +532,7 @@ static const struct imx219_mode supporte
+ .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
+ .regs = mode_1640_1232_regs,
+ },
++ .rate_factor = 1,
+ },
+ {
+ /* 640x480 30fps mode */
+@@ -543,6 +549,11 @@ static const struct imx219_mode supporte
+ .num_of_regs = ARRAY_SIZE(mode_640_480_regs),
+ .regs = mode_640_480_regs,
+ },
++ /*
++ * This mode uses a special 2x2 binning that doubles the
++ * the internal pixel clock rate.
++ */
++ .rate_factor = 2,
+ },
+ };
+
+@@ -765,7 +776,8 @@ static int imx219_set_ctrl(struct v4l2_c
+ break;
+ case V4L2_CID_EXPOSURE:
+ ret = imx219_write_reg(imx219, IMX219_REG_EXPOSURE,
+- IMX219_REG_VALUE_16BIT, ctrl->val);
++ IMX219_REG_VALUE_16BIT,
++ ctrl->val / imx219->mode->rate_factor);
+ break;
+ case V4L2_CID_DIGITAL_GAIN:
+ ret = imx219_write_reg(imx219, IMX219_REG_DIGITAL_GAIN,
+@@ -785,7 +797,8 @@ static int imx219_set_ctrl(struct v4l2_c
+ case V4L2_CID_VBLANK:
+ ret = imx219_write_reg(imx219, IMX219_REG_VTS,
+ IMX219_REG_VALUE_16BIT,
+- imx219->mode->height + ctrl->val);
++ (imx219->mode->height + ctrl->val) /
++ imx219->mode->rate_factor);
+ break;
+ case V4L2_CID_TEST_PATTERN_RED:
+ ret = imx219_write_reg(imx219, IMX219_REG_TESTP_RED,
+@@ -957,7 +970,7 @@ static int imx219_set_pad_format(struct
+ struct imx219 *imx219 = to_imx219(sd);
+ const struct imx219_mode *mode;
+ struct v4l2_mbus_framefmt *framefmt;
+- int exposure_max, exposure_def, hblank;
++ int exposure_max, exposure_def, hblank, pixel_rate;
+ unsigned int i;
+
+ if (fmt->pad >= NUM_PADS)
+@@ -1018,6 +1031,12 @@ static int imx219_set_pad_format(struct
+ hblank = IMX219_PPL_DEFAULT - mode->width;
+ __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank,
+ 1, hblank);
++
++ /* Scale the pixel rate based on the mode specific factor */
++ pixel_rate =
++ IMX219_PIXEL_RATE * imx219->mode->rate_factor;
++ __v4l2_ctrl_modify_range(imx219->pixel_rate, pixel_rate,
++ pixel_rate, 1, pixel_rate);
+ }
+ } else {
+ if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+@@ -1362,7 +1381,7 @@ static int imx219_init_controls(struct i
+ struct v4l2_ctrl_handler *ctrl_hdlr;
+ unsigned int height = imx219->mode->height;
+ struct v4l2_fwnode_device_properties props;
+- int exposure_max, exposure_def, hblank;
++ int exposure_max, exposure_def, hblank, pixel_rate;
+ int i, ret;
+
+ ctrl_hdlr = &imx219->ctrl_handler;
+@@ -1374,11 +1393,11 @@ static int imx219_init_controls(struct i
+ ctrl_hdlr->lock = &imx219->mutex;
+
+ /* By default, PIXEL_RATE is read only */
++ pixel_rate = IMX219_PIXEL_RATE * imx219->mode->rate_factor;
+ imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
+ V4L2_CID_PIXEL_RATE,
+- IMX219_PIXEL_RATE,
+- IMX219_PIXEL_RATE, 1,
+- IMX219_PIXEL_RATE);
++ pixel_rate, pixel_rate,
++ 1, pixel_rate);
+
+ imx219->link_freq =
+ v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops,