1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-02-15 04:42:02 +00:00
openmptcprouter/root/target/linux/bcm27xx/patches-5.15/950-0349-media-i2c-imx477-Add-very-long-exposure-control-to-t.patch

127 lines
4.2 KiB
Diff
Raw Normal View History

2022-04-22 15:00:47 +00:00
From 9149bbcd831f94750da7fb0be9ab99335d5c834b Mon Sep 17 00:00:00 2001
2021-11-24 17:32:01 +00:00
From: Naushir Patuck <naush@raspberrypi.com>
Date: Wed, 10 Feb 2021 10:50:32 +0000
2022-04-22 15:00:47 +00:00
Subject: [PATCH 349/828] media: i2c: imx477: Add very long exposure control to
2021-11-24 17:32:01 +00:00
the driver
Add support for very long exposures by using the exposure multiplier
register. Userland does not need to pass any additional controls to
enable long exposures, it simply requests a larger vblank to extend the
exposure control range appropriately.
Currently, since hblank is fixed, a maximum of approximately 124 seconds
of exposure time can be used. In a future change, hblank could also be
controlled in userland to give over 200 seconds of exposure time.
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
---
drivers/media/i2c/imx477.c | 47 +++++++++++++++++++++++++++++++++-----
1 file changed, 41 insertions(+), 6 deletions(-)
--- a/drivers/media/i2c/imx477.c
+++ b/drivers/media/i2c/imx477.c
@@ -44,6 +44,10 @@
#define IMX477_REG_FRAME_LENGTH 0x0340
#define IMX477_FRAME_LENGTH_MAX 0xffdc
+/* Long exposure multiplier */
+#define IMX477_LONG_EXP_SHIFT_MAX 7
+#define IMX477_LONG_EXP_SHIFT_REG 0x3100
+
/* Exposure control */
#define IMX477_REG_EXPOSURE 0x0202
#define IMX477_EXPOSURE_OFFSET 22
@@ -1097,6 +1101,9 @@ struct imx477 {
/* Rewrite common registers on stream on? */
bool common_regs_written;
+
+ /* Current long exposure factor in use. Set through V4L2_CID_VBLANK */
+ unsigned int long_exp_shift;
};
static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
2022-04-22 15:00:47 +00:00
@@ -1285,13 +1292,33 @@ static void imx477_adjust_exposure_range
2021-11-24 17:32:01 +00:00
/* Honour the VBLANK limits when setting exposure. */
exposure_max = imx477->mode->height + imx477->vblank->val -
- IMX477_EXPOSURE_OFFSET;
+ (IMX477_EXPOSURE_OFFSET << imx477->long_exp_shift);
exposure_def = min(exposure_max, imx477->exposure->val);
__v4l2_ctrl_modify_range(imx477->exposure, imx477->exposure->minimum,
exposure_max, imx477->exposure->step,
exposure_def);
}
+static int imx477_set_frame_length(struct imx477 *imx477, unsigned int val)
+{
+ int ret = 0;
+
+ imx477->long_exp_shift = 0;
+
+ while (val > IMX477_FRAME_LENGTH_MAX) {
+ imx477->long_exp_shift++;
+ val >>= 1;
+ }
+
+ ret = imx477_write_reg(imx477, IMX477_REG_FRAME_LENGTH,
+ IMX477_REG_VALUE_16BIT, val);
+ if (ret)
+ return ret;
+
+ return imx477_write_reg(imx477, IMX477_LONG_EXP_SHIFT_REG,
+ IMX477_REG_VALUE_08BIT, imx477->long_exp_shift);
+}
+
static int imx477_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct imx477 *imx477 =
2022-04-22 15:00:47 +00:00
@@ -1299,6 +1326,10 @@ static int imx477_set_ctrl(struct v4l2_c
2021-11-24 17:32:01 +00:00
struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd);
int ret = 0;
+ /*
+ * The VBLANK control may change the limits of usable exposure, so check
+ * and adjust if necessary.
+ */
if (ctrl->id == V4L2_CID_VBLANK)
imx477_adjust_exposure_range(imx477, ctrl);
2022-04-22 15:00:47 +00:00
@@ -1316,7 +1347,8 @@ static int imx477_set_ctrl(struct v4l2_c
2021-11-24 17:32:01 +00:00
break;
case V4L2_CID_EXPOSURE:
ret = imx477_write_reg(imx477, IMX477_REG_EXPOSURE,
- IMX477_REG_VALUE_16BIT, ctrl->val);
+ IMX477_REG_VALUE_16BIT, ctrl->val >>
+ imx477->long_exp_shift);
break;
case V4L2_CID_DIGITAL_GAIN:
ret = imx477_write_reg(imx477, IMX477_REG_DIGITAL_GAIN,
2022-04-22 15:00:47 +00:00
@@ -1350,9 +1382,8 @@ static int imx477_set_ctrl(struct v4l2_c
2021-11-24 17:32:01 +00:00
imx477->vflip->val << 1);
break;
case V4L2_CID_VBLANK:
- ret = imx477_write_reg(imx477, IMX477_REG_FRAME_LENGTH,
- IMX477_REG_VALUE_16BIT,
- imx477->mode->height + ctrl->val);
+ ret = imx477_set_frame_length(imx477,
+ imx477->mode->height + ctrl->val);
break;
default:
dev_info(&client->dev,
2022-04-22 15:00:47 +00:00
@@ -1521,9 +1552,13 @@ static void imx477_set_framing_limits(st
2021-11-24 17:32:01 +00:00
frm_length_default =
imx477_get_frame_length(mode, &mode->timeperframe_default);
+ /* Default to no long exposure multiplier. */
+ imx477->long_exp_shift = 0;
+
/* Update limits and set FPS to default */
__v4l2_ctrl_modify_range(imx477->vblank, frm_length_min - mode->height,
- IMX477_FRAME_LENGTH_MAX - mode->height,
+ ((1 << IMX477_LONG_EXP_SHIFT_MAX) *
+ IMX477_FRAME_LENGTH_MAX) - mode->height,
1, frm_length_default - mode->height);
/* Setting this will adjust the exposure limits as well. */