aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0829-media-i2c-imx290-Convert-HMAX-setting-into-V4L2_CID_.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-5.4/950-0829-media-i2c-imx290-Convert-HMAX-setting-into-V4L2_CID_.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.4/950-0829-media-i2c-imx290-Convert-HMAX-setting-into-V4L2_CID_.patch159
1 files changed, 159 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.4/950-0829-media-i2c-imx290-Convert-HMAX-setting-into-V4L2_CID_.patch b/target/linux/bcm27xx/patches-5.4/950-0829-media-i2c-imx290-Convert-HMAX-setting-into-V4L2_CID_.patch
new file mode 100644
index 0000000000..7a0a5f06aa
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.4/950-0829-media-i2c-imx290-Convert-HMAX-setting-into-V4L2_CID_.patch
@@ -0,0 +1,159 @@
+From 116dc059ca9c6b088afba98dde7b679a97ae7198 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Date: Thu, 11 Jun 2020 14:36:40 +0100
+Subject: [PATCH] media: i2c: imx290: Convert HMAX setting into
+ V4L2_CID_HBLANK
+
+Userspace needs to know HBLANK if it is to work out exposure times
+and frame rates, therefore convert it to map onto V4L2_CID_HBLANK
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+---
+ drivers/media/i2c/imx290.c | 66 +++++++++++++++++++++++++-------------
+ 1 file changed, 44 insertions(+), 22 deletions(-)
+
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -40,6 +40,9 @@ enum imx290_clk_index {
+ #define IMX290_GAIN 0x3014
+ #define IMX290_HMAX_LOW 0x301c
+ #define IMX290_HMAX_HIGH 0x301d
++#define IMX290_HMAX_MIN_2LANE 4400 /* Min of 4400 pixels = 30fps */
++#define IMX290_HMAX_MIN_4LANE 2200 /* Min of 2200 pixels = 60fps */
++#define IMX290_HMAX_MAX 0xffff
+ #define IMX290_PGCTRL 0x308c
+ #define IMX290_PHY_LANE_NUM 0x3407
+ #define IMX290_CSI_LANE_MODE 0x3443
+@@ -82,6 +85,7 @@ struct imx290 {
+ struct regmap *regmap;
+ u8 nlanes;
+ u8 bpp;
++ u16 hmax_min;
+
+ struct v4l2_subdev sd;
+ struct media_pad pad;
+@@ -94,6 +98,7 @@ struct imx290 {
+ struct v4l2_ctrl_handler ctrls;
+ struct v4l2_ctrl *link_freq;
+ struct v4l2_ctrl *pixel_rate;
++ struct v4l2_ctrl *hblank;
+
+ struct mutex lock;
+ };
+@@ -518,6 +523,26 @@ static int imx290_set_gain(struct imx290
+ return ret;
+ }
+
++static int imx290_set_hmax(struct imx290 *imx290, u32 val)
++{
++ u32 hmax = val + imx290->current_mode->width;
++ int ret;
++
++ ret = imx290_write_reg(imx290, IMX290_HMAX_LOW, (hmax & 0xff));
++ if (ret) {
++ dev_err(imx290->dev, "Error setting HMAX register\n");
++ return ret;
++ }
++
++ ret = imx290_write_reg(imx290, IMX290_HMAX_HIGH, ((hmax >> 8) & 0xff));
++ if (ret) {
++ dev_err(imx290->dev, "Error setting HMAX register\n");
++ return ret;
++ }
++
++ return 0;
++}
++
+ /* Stop streaming */
+ static int imx290_stop_streaming(struct imx290 *imx290)
+ {
+@@ -546,6 +571,9 @@ static int imx290_set_ctrl(struct v4l2_c
+ case V4L2_CID_GAIN:
+ ret = imx290_set_gain(imx290, ctrl->val);
+ break;
++ case V4L2_CID_HBLANK:
++ ret = imx290_set_hmax(imx290, ctrl->val);
++ break;
+ case V4L2_CID_TEST_PATTERN:
+ if (ctrl->val) {
+ imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x00);
+@@ -702,6 +730,12 @@ static int imx290_set_fmt(struct v4l2_su
+ if (imx290->pixel_rate)
+ __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
+ imx290_calc_pixel_rate(imx290));
++
++ if (imx290->hblank)
++ __v4l2_ctrl_modify_range(imx290->hblank,
++ imx290->hmax_min - mode->width,
++ IMX290_HMAX_MAX - mode->width,
++ 1, mode->hmax - mode->width);
+ }
+
+ *format = fmt->format;
+@@ -756,25 +790,6 @@ static int imx290_write_current_format(s
+ return 0;
+ }
+
+-static int imx290_set_hmax(struct imx290 *imx290, u32 val)
+-{
+- int ret;
+-
+- ret = imx290_write_reg(imx290, IMX290_HMAX_LOW, (val & 0xff));
+- if (ret) {
+- dev_err(imx290->dev, "Error setting HMAX register\n");
+- return ret;
+- }
+-
+- ret = imx290_write_reg(imx290, IMX290_HMAX_HIGH, ((val >> 8) & 0xff));
+- if (ret) {
+- dev_err(imx290->dev, "Error setting HMAX register\n");
+- return ret;
+- }
+-
+- return 0;
+-}
+-
+ /* Start streaming */
+ static int imx290_start_streaming(struct imx290 *imx290)
+ {
+@@ -813,9 +828,6 @@ static int imx290_start_streaming(struct
+ dev_err(imx290->dev, "Could not set current mode\n");
+ return ret;
+ }
+- ret = imx290_set_hmax(imx290, imx290->current_mode->hmax);
+- if (ret < 0)
+- return ret;
+
+ /* Apply customized values from user */
+ ret = v4l2_ctrl_handler_setup(imx290->sd.ctrl_handler);
+@@ -1014,6 +1026,7 @@ static int imx290_probe(struct i2c_clien
+ struct v4l2_fwnode_endpoint ep = {
+ .bus_type = V4L2_MBUS_CSI2_DPHY
+ };
++ const struct imx290_mode *mode;
+ struct imx290 *imx290;
+ s64 fq;
+ int ret;
+@@ -1052,6 +1065,8 @@ static int imx290_probe(struct i2c_clien
+ ret = -EINVAL;
+ goto free_err;
+ }
++ imx290->hmax_min = (imx290->nlanes == 2) ? IMX290_HMAX_MIN_2LANE :
++ IMX290_HMAX_MIN_4LANE;
+
+ dev_dbg(dev, "Using %u data lanes\n", imx290->nlanes);
+
+@@ -1126,6 +1141,13 @@ static int imx290_probe(struct i2c_clien
+ v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
+ V4L2_CID_GAIN, 0, 238, 1, 0);
+
++ mode = imx290->current_mode;
++ imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
++ V4L2_CID_HBLANK,
++ imx290->hmax_min - mode->width,
++ IMX290_HMAX_MAX - mode->width, 1,
++ mode->hmax - mode->width);
++
+ imx290->link_freq =
+ v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
+ V4L2_CID_LINK_FREQ,