mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 15:02:32 +00:00
103 lines
3.1 KiB
Diff
103 lines
3.1 KiB
Diff
|
From 321814f1f361336278e9d682492152098b0a0f00 Mon Sep 17 00:00:00 2001
|
||
|
From: Naushir Patuck <naush@raspberrypi.com>
|
||
|
Date: Thu, 5 Jan 2023 14:44:48 +0000
|
||
|
Subject: [PATCH] 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,
|