2022-05-16 21:40:32 +00:00
|
|
|
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
|
2023-03-12 14:16:50 +00:00
|
|
|
@@ -162,6 +162,9 @@ struct imx219_mode {
|
2022-05-16 21:40:32 +00:00
|
|
|
|
2023-03-12 14:16:50 +00:00
|
|
|
/* 2x2 binning is used */
|
|
|
|
bool binning;
|
2022-05-16 21:40:32 +00:00
|
|
|
+
|
|
|
|
+ /* Relative pixel clock rate factor for the mode. */
|
|
|
|
+ unsigned int rate_factor;
|
|
|
|
};
|
|
|
|
|
2023-03-12 14:16:50 +00:00
|
|
|
static const struct imx219_reg imx219_common_regs[] = {
|
|
|
|
@@ -402,6 +405,7 @@ static const struct imx219_mode supporte
|
2022-05-16 21:40:32 +00:00
|
|
|
.regs = mode_3280x2464_regs,
|
|
|
|
},
|
2023-03-12 14:16:50 +00:00
|
|
|
.binning = false,
|
2022-05-16 21:40:32 +00:00
|
|
|
+ .rate_factor = 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* 1080P 30fps cropped */
|
2023-03-12 14:16:50 +00:00
|
|
|
@@ -419,6 +423,7 @@ static const struct imx219_mode supporte
|
2022-05-16 21:40:32 +00:00
|
|
|
.regs = mode_1920_1080_regs,
|
|
|
|
},
|
2023-03-12 14:16:50 +00:00
|
|
|
.binning = false,
|
2022-05-16 21:40:32 +00:00
|
|
|
+ .rate_factor = 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* 2x2 binned 30fps mode */
|
2023-03-12 14:16:50 +00:00
|
|
|
@@ -436,6 +441,7 @@ static const struct imx219_mode supporte
|
2022-05-16 21:40:32 +00:00
|
|
|
.regs = mode_1640_1232_regs,
|
|
|
|
},
|
2023-03-12 14:16:50 +00:00
|
|
|
.binning = true,
|
2022-05-16 21:40:32 +00:00
|
|
|
+ .rate_factor = 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
/* 640x480 30fps mode */
|
2023-03-12 14:16:50 +00:00
|
|
|
@@ -453,6 +459,11 @@ static const struct imx219_mode supporte
|
2022-05-16 21:40:32 +00:00
|
|
|
.regs = mode_640_480_regs,
|
|
|
|
},
|
2023-03-12 14:16:50 +00:00
|
|
|
.binning = true,
|
2022-05-16 21:40:32 +00:00
|
|
|
+ /*
|
2023-03-12 14:16:50 +00:00
|
|
|
+ * This mode uses a special 2x2 binning that doubles the
|
|
|
|
+ * the internal pixel clock rate.
|
|
|
|
+ */
|
2022-05-16 21:40:32 +00:00
|
|
|
+ .rate_factor = 2,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2023-03-12 14:16:50 +00:00
|
|
|
@@ -675,7 +686,8 @@ static int imx219_set_ctrl(struct v4l2_c
|
2022-05-16 21:40:32 +00:00
|
|
|
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,
|
2023-03-12 14:16:50 +00:00
|
|
|
@@ -695,7 +707,8 @@ static int imx219_set_ctrl(struct v4l2_c
|
2022-05-16 21:40:32 +00:00
|
|
|
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,
|
2023-03-12 14:16:50 +00:00
|
|
|
@@ -867,7 +880,7 @@ static int imx219_set_pad_format(struct
|
2022-05-16 21:40:32 +00:00
|
|
|
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)
|
2023-03-12 14:16:50 +00:00
|
|
|
@@ -928,6 +941,12 @@ static int imx219_set_pad_format(struct
|
2022-05-16 21:40:32 +00:00
|
|
|
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) {
|
2023-03-12 14:16:50 +00:00
|
|
|
@@ -1315,7 +1334,7 @@ static int imx219_init_controls(struct i
|
2022-05-16 21:40:32 +00:00
|
|
|
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;
|
2023-03-12 14:16:50 +00:00
|
|
|
@@ -1327,11 +1346,11 @@ static int imx219_init_controls(struct i
|
2022-05-16 21:40:32 +00:00
|
|
|
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,
|