Openwrt/target/linux/bcm27xx/patches-5.4/950-0830-media-i2c-imx290-Add-support-for-V4L2_CID_VBLANK.patch
Álvaro Fernández Rojas f07e572f64 bcm27xx: import latest patches from the RPi foundation
bcm2708: boot tested on RPi B+ v1.2
bcm2709: boot tested on RPi 3B v1.2 and RPi 4B v1.1 4G
bcm2710: boot tested on RPi 3B v1.2
bcm2711: boot tested on RPi 4B v1.1 4G

Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
2021-02-18 23:42:32 +01:00

142 lines
4.3 KiB
Diff

From 12a04a18c7a56dbd2943b6666c7978b09499fc4b Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Thu, 11 Jun 2020 18:09:12 +0100
Subject: [PATCH] media: i2c: imx290: Add support for V4L2_CID_VBLANK
In order to calculate framerate and durations userspace needs
the vertical blanking information. This can be configurable,
and indeed the datasheet lists different values for VBLANK for
the 1080p and 720p modes.
Add the new control, and adopt the datasheet values for each mode.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
drivers/media/i2c/imx290.c | 38 ++++++++++++++++++++++++++++++++++++--
1 file changed, 36 insertions(+), 2 deletions(-)
--- a/drivers/media/i2c/imx290.c
+++ b/drivers/media/i2c/imx290.c
@@ -38,6 +38,8 @@ enum imx290_clk_index {
#define IMX290_BLKLEVEL_LOW 0x300a
#define IMX290_BLKLEVEL_HIGH 0x300b
#define IMX290_GAIN 0x3014
+#define IMX290_VMAX_LOW 0x3018
+#define IMX290_VMAX_MAX 0x3fff
#define IMX290_HMAX_LOW 0x301c
#define IMX290_HMAX_HIGH 0x301d
#define IMX290_HMAX_MIN_2LANE 4400 /* Min of 4400 pixels = 30fps */
@@ -68,6 +70,7 @@ struct imx290_mode {
u32 width;
u32 height;
u32 hmax;
+ u32 vmax;
u8 link_freq_index;
const struct imx290_regval *data;
@@ -99,6 +102,7 @@ struct imx290 {
struct v4l2_ctrl *link_freq;
struct v4l2_ctrl *pixel_rate;
struct v4l2_ctrl *hblank;
+ struct v4l2_ctrl *vblank;
struct mutex lock;
};
@@ -132,8 +136,6 @@ static const char * const imx290_test_pa
static const struct imx290_regval imx290_global_init_settings[] = {
{ 0x3007, 0x00 },
- { 0x3018, 0x65 },
- { 0x3019, 0x04 },
{ 0x301a, 0x00 },
{ 0x303a, 0x0c },
{ 0x3040, 0x00 },
@@ -360,6 +362,7 @@ static const struct imx290_mode imx290_m
.width = 1920,
.height = 1080,
.hmax = 0x1130,
+ .vmax = 0x0465,
.link_freq_index = FREQ_INDEX_1080P,
.data = imx290_1080p_settings,
.data_size = ARRAY_SIZE(imx290_1080p_settings),
@@ -373,6 +376,7 @@ static const struct imx290_mode imx290_m
.width = 1280,
.height = 720,
.hmax = 0x19c8,
+ .vmax = 0x02ee,
.link_freq_index = FREQ_INDEX_720P,
.data = imx290_720p_settings,
.data_size = ARRAY_SIZE(imx290_720p_settings),
@@ -389,6 +393,7 @@ static const struct imx290_mode imx290_m
.width = 1920,
.height = 1080,
.hmax = 0x0898,
+ .vmax = 0x0465,
.link_freq_index = FREQ_INDEX_1080P,
.data = imx290_1080p_settings,
.data_size = ARRAY_SIZE(imx290_1080p_settings),
@@ -402,6 +407,7 @@ static const struct imx290_mode imx290_m
.width = 1280,
.height = 720,
.hmax = 0x0ce4,
+ .vmax = 0x02ee,
.link_freq_index = FREQ_INDEX_720P,
.data = imx290_720p_settings,
.data_size = ARRAY_SIZE(imx290_720p_settings),
@@ -543,6 +549,19 @@ static int imx290_set_hmax(struct imx290
return 0;
}
+static int imx290_set_vmax(struct imx290 *imx290, u32 val)
+{
+ u32 vmax = val + imx290->current_mode->height;
+ int ret;
+
+ ret = imx290_write_buffered_reg(imx290, IMX290_VMAX_LOW, 3,
+ vmax);
+ if (ret)
+ dev_err(imx290->dev, "Unable to write vmax\n");
+
+ return ret;
+}
+
/* Stop streaming */
static int imx290_stop_streaming(struct imx290 *imx290)
{
@@ -574,6 +593,9 @@ static int imx290_set_ctrl(struct v4l2_c
case V4L2_CID_HBLANK:
ret = imx290_set_hmax(imx290, ctrl->val);
break;
+ case V4L2_CID_VBLANK:
+ ret = imx290_set_vmax(imx290, ctrl->val);
+ break;
case V4L2_CID_TEST_PATTERN:
if (ctrl->val) {
imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x00);
@@ -736,6 +758,12 @@ static int imx290_set_fmt(struct v4l2_su
imx290->hmax_min - mode->width,
IMX290_HMAX_MAX - mode->width,
1, mode->hmax - mode->width);
+ if (imx290->vblank)
+ __v4l2_ctrl_modify_range(imx290->vblank,
+ mode->vmax - mode->height,
+ IMX290_VMAX_MAX - mode->height,
+ 1,
+ mode->vmax - mode->height);
}
*format = fmt->format;
@@ -1148,6 +1176,12 @@ static int imx290_probe(struct i2c_clien
IMX290_HMAX_MAX - mode->width, 1,
mode->hmax - mode->width);
+ imx290->vblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+ V4L2_CID_VBLANK,
+ mode->vmax - mode->height,
+ IMX290_VMAX_MAX - mode->height, 1,
+ mode->vmax - mode->height);
+
imx290->link_freq =
v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
V4L2_CID_LINK_FREQ,