6d21d183a2ec601c6ed2ff26e7fdb331278bcfd7
[openwrt/staging/neocturne.git] /
1 From 1ef87a70e7e946447835c8cefa0bc690c29d7ac8 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Thu, 11 Jun 2020 14:36:40 +0100
4 Subject: [PATCH] media: i2c: imx290: Convert HMAX setting into
5 V4L2_CID_HBLANK
6
7 Userspace needs to know HBLANK if it is to work out exposure times
8 and frame rates, therefore convert it to map onto V4L2_CID_HBLANK
9
10 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
11 ---
12 drivers/media/i2c/imx290.c | 66 +++++++++++++++++++++++++-------------
13 1 file changed, 44 insertions(+), 22 deletions(-)
14
15 --- a/drivers/media/i2c/imx290.c
16 +++ b/drivers/media/i2c/imx290.c
17 @@ -40,6 +40,9 @@ enum imx290_clk_index {
18 #define IMX290_GAIN 0x3014
19 #define IMX290_HMAX_LOW 0x301c
20 #define IMX290_HMAX_HIGH 0x301d
21 +#define IMX290_HMAX_MIN_2LANE 4400 /* Min of 4400 pixels = 30fps */
22 +#define IMX290_HMAX_MIN_4LANE 2200 /* Min of 2200 pixels = 60fps */
23 +#define IMX290_HMAX_MAX 0xffff
24 #define IMX290_PGCTRL 0x308c
25 #define IMX290_PHY_LANE_NUM 0x3407
26 #define IMX290_CSI_LANE_MODE 0x3443
27 @@ -82,6 +85,7 @@ struct imx290 {
28 struct regmap *regmap;
29 u8 nlanes;
30 u8 bpp;
31 + u16 hmax_min;
32
33 struct v4l2_subdev sd;
34 struct media_pad pad;
35 @@ -94,6 +98,7 @@ struct imx290 {
36 struct v4l2_ctrl_handler ctrls;
37 struct v4l2_ctrl *link_freq;
38 struct v4l2_ctrl *pixel_rate;
39 + struct v4l2_ctrl *hblank;
40
41 struct mutex lock;
42 };
43 @@ -518,6 +523,26 @@ static int imx290_set_gain(struct imx290
44 return ret;
45 }
46
47 +static int imx290_set_hmax(struct imx290 *imx290, u32 val)
48 +{
49 + u32 hmax = val + imx290->current_mode->width;
50 + int ret;
51 +
52 + ret = imx290_write_reg(imx290, IMX290_HMAX_LOW, (hmax & 0xff));
53 + if (ret) {
54 + dev_err(imx290->dev, "Error setting HMAX register\n");
55 + return ret;
56 + }
57 +
58 + ret = imx290_write_reg(imx290, IMX290_HMAX_HIGH, ((hmax >> 8) & 0xff));
59 + if (ret) {
60 + dev_err(imx290->dev, "Error setting HMAX register\n");
61 + return ret;
62 + }
63 +
64 + return 0;
65 +}
66 +
67 /* Stop streaming */
68 static int imx290_stop_streaming(struct imx290 *imx290)
69 {
70 @@ -546,6 +571,9 @@ static int imx290_set_ctrl(struct v4l2_c
71 case V4L2_CID_GAIN:
72 ret = imx290_set_gain(imx290, ctrl->val);
73 break;
74 + case V4L2_CID_HBLANK:
75 + ret = imx290_set_hmax(imx290, ctrl->val);
76 + break;
77 case V4L2_CID_TEST_PATTERN:
78 if (ctrl->val) {
79 imx290_write_reg(imx290, IMX290_BLKLEVEL_LOW, 0x00);
80 @@ -702,6 +730,12 @@ static int imx290_set_fmt(struct v4l2_su
81 if (imx290->pixel_rate)
82 __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
83 imx290_calc_pixel_rate(imx290));
84 +
85 + if (imx290->hblank)
86 + __v4l2_ctrl_modify_range(imx290->hblank,
87 + imx290->hmax_min - mode->width,
88 + IMX290_HMAX_MAX - mode->width,
89 + 1, mode->hmax - mode->width);
90 }
91
92 *format = fmt->format;
93 @@ -756,25 +790,6 @@ static int imx290_write_current_format(s
94 return 0;
95 }
96
97 -static int imx290_set_hmax(struct imx290 *imx290, u32 val)
98 -{
99 - int ret;
100 -
101 - ret = imx290_write_reg(imx290, IMX290_HMAX_LOW, (val & 0xff));
102 - if (ret) {
103 - dev_err(imx290->dev, "Error setting HMAX register\n");
104 - return ret;
105 - }
106 -
107 - ret = imx290_write_reg(imx290, IMX290_HMAX_HIGH, ((val >> 8) & 0xff));
108 - if (ret) {
109 - dev_err(imx290->dev, "Error setting HMAX register\n");
110 - return ret;
111 - }
112 -
113 - return 0;
114 -}
115 -
116 /* Start streaming */
117 static int imx290_start_streaming(struct imx290 *imx290)
118 {
119 @@ -813,9 +828,6 @@ static int imx290_start_streaming(struct
120 dev_err(imx290->dev, "Could not set current mode\n");
121 return ret;
122 }
123 - ret = imx290_set_hmax(imx290, imx290->current_mode->hmax);
124 - if (ret < 0)
125 - return ret;
126
127 /* Apply customized values from user */
128 ret = v4l2_ctrl_handler_setup(imx290->sd.ctrl_handler);
129 @@ -1010,6 +1022,7 @@ static int imx290_probe(struct i2c_clien
130 struct v4l2_fwnode_endpoint ep = {
131 .bus_type = V4L2_MBUS_CSI2_DPHY
132 };
133 + const struct imx290_mode *mode;
134 struct imx290 *imx290;
135 s64 fq;
136 int ret;
137 @@ -1048,6 +1061,8 @@ static int imx290_probe(struct i2c_clien
138 ret = -EINVAL;
139 goto free_err;
140 }
141 + imx290->hmax_min = (imx290->nlanes == 2) ? IMX290_HMAX_MIN_2LANE :
142 + IMX290_HMAX_MIN_4LANE;
143
144 dev_dbg(dev, "Using %u data lanes\n", imx290->nlanes);
145
146 @@ -1122,6 +1137,13 @@ static int imx290_probe(struct i2c_clien
147 v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
148 V4L2_CID_GAIN, 0, 238, 1, 0);
149
150 + mode = imx290->current_mode;
151 + imx290->hblank = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
152 + V4L2_CID_HBLANK,
153 + imx290->hmax_min - mode->width,
154 + IMX290_HMAX_MAX - mode->width, 1,
155 + mode->hmax - mode->width);
156 +
157 imx290->link_freq =
158 v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
159 V4L2_CID_LINK_FREQ,