openwrt/target/linux/bcm27xx/patches-6.6/950-0410-drivers-media-imx708-Enable-long-exposure-mode.patch

103 lines
3.1 KiB
Diff
Raw Normal View History

From a39707acca4efe72d4dee5651230033072017a10 Mon Sep 17 00:00:00 2001
From: Naushir Patuck <naush@raspberrypi.com>
Date: Thu, 5 Jan 2023 14:44:48 +0000
Subject: [PATCH 0410/1085] drivers: media: imx708: Enable long exposure mode
Enable long exposure modes by using the long exposure shift register setting
in the imx708 sensor.
Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
---
drivers/media/i2c/imx708.c | 41 +++++++++++++++++++++++++++++++++-----
1 file changed, 36 insertions(+), 5 deletions(-)
--- a/drivers/media/i2c/imx708.c
+++ b/drivers/media/i2c/imx708.c
@@ -44,6 +44,10 @@
#define IMX708_REG_FRAME_LENGTH 0x0340
#define IMX708_FRAME_LENGTH_MAX 0xffff
+/* Long exposure multiplier */
+#define IMX708_LONG_EXP_SHIFT_MAX 7
+#define IMX708_LONG_EXP_SHIFT_REG 0x3100
+
/* Exposure control */
#define IMX708_REG_EXPOSURE 0x0202
#define IMX708_EXPOSURE_OFFSET 48
@@ -806,6 +810,9 @@ struct imx708 {
/* 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 imx708 *to_imx708(struct v4l2_subdev *_sd)
@@ -994,7 +1001,8 @@ static int imx708_set_exposure(struct im
* will automatically divide the medium and short ones by 4,16.
*/
ret = imx708_write_reg(imx708, IMX708_REG_EXPOSURE,
- IMX708_REG_VALUE_16BIT, val);
+ IMX708_REG_VALUE_16BIT,
+ val >> imx708->long_exp_shift);
return ret;
}
@@ -1027,18 +1035,42 @@ static int imx708_set_analogue_gain(stru
return ret;
}
+static int imx708_set_frame_length(struct imx708 *imx708, unsigned int val)
+{
+ int ret = 0;
+
+ imx708->long_exp_shift = 0;
+
+ while (val > IMX708_FRAME_LENGTH_MAX) {
+ imx708->long_exp_shift++;
+ val >>= 1;
+ }
+
+ ret = imx708_write_reg(imx708, IMX708_REG_FRAME_LENGTH,
+ IMX708_REG_VALUE_16BIT, val);
+ if (ret)
+ return ret;
+
+ return imx708_write_reg(imx708, IMX708_LONG_EXP_SHIFT_REG,
+ IMX708_REG_VALUE_08BIT, imx708->long_exp_shift);
+}
+
static void imx708_set_framing_limits(struct imx708 *imx708)
{
unsigned int hblank;
const struct imx708_mode *mode = imx708->mode;
+ /* Default to no long exposure multiplier */
+ imx708->long_exp_shift = 0;
+
__v4l2_ctrl_modify_range(imx708->pixel_rate,
mode->pixel_rate, mode->pixel_rate,
1, mode->pixel_rate);
/* Update limits and set FPS to default */
__v4l2_ctrl_modify_range(imx708->vblank, mode->vblank_min,
- IMX708_FRAME_LENGTH_MAX - mode->height,
+ ((1 << IMX708_LONG_EXP_SHIFT_MAX) *
+ IMX708_FRAME_LENGTH_MAX) - mode->height,
1, mode->vblank_default);
/*
@@ -1112,9 +1144,8 @@ static int imx708_set_ctrl(struct v4l2_c
imx708->vflip->val << 1);
break;
case V4L2_CID_VBLANK:
- ret = imx708_write_reg(imx708, IMX708_REG_FRAME_LENGTH,
- IMX708_REG_VALUE_16BIT,
- imx708->mode->height + ctrl->val);
+ ret = imx708_set_frame_length(imx708,
+ imx708->mode->height + ctrl->val);
break;
case V4L2_CID_NOTIFY_GAINS:
ret = imx708_write_reg(imx708, IMX708_REG_COLOUR_BALANCE_BLUE,