bcm27xx: switch to kernel v6.1
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.15 / 950-0250-media-i2c-imx290-Add-support-for-74.25MHz-clock.patch
1 From 9fe4d33587bd7931e2a0decc7c4881945a1c0ab3 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Thu, 25 Jun 2020 08:28:51 +0100
4 Subject: [PATCH] media: i2c: imx290: Add support for 74.25MHz clock
5
6 The existing driver only supported a clock of 37.125MHz, but the
7 sensor also supports 74.25MHz.
8
9 Add the relevant register modifications to support this alternate
10 clock frequency.
11
12 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
13 ---
14 drivers/media/i2c/imx290.c | 119 ++++++++++++++++++++++++++++++-------
15 1 file changed, 97 insertions(+), 22 deletions(-)
16
17 --- a/drivers/media/i2c/imx290.c
18 +++ b/drivers/media/i2c/imx290.c
19 @@ -1,6 +1,10 @@
20 // SPDX-License-Identifier: GPL-2.0
21 /*
22 - * Sony IMX290 CMOS Image Sensor Driver
23 + * Sony IMX290/327 CMOS Image Sensor Driver
24 + *
25 + * The IMX290 and IMX327 are very similar 1920x1080 1/2.8 CMOS image sensors.
26 + * IMX327 can support up to 60fps, whilst IMX290 support up to 120fps (only
27 + * 10bit and when connected over 4 CSI-2 lanes).
28 *
29 * Copyright (C) 2019 FRAMOS GmbH.
30 *
31 @@ -22,6 +26,11 @@
32 #include <media/v4l2-fwnode.h>
33 #include <media/v4l2-subdev.h>
34
35 +enum imx290_clk_index {
36 + CLK_37_125,
37 + CLK_74_25,
38 +};
39 +
40 #define IMX290_STANDBY 0x3000
41 #define IMX290_REGHOLD 0x3001
42 #define IMX290_XMSTA 0x3002
43 @@ -60,11 +69,16 @@ struct imx290_mode {
44
45 const struct imx290_regval *data;
46 u32 data_size;
47 +
48 + /* Clock setup can vary. Index as enum imx290_clk_index */
49 + const struct imx290_regval *clk_data[2];
50 + u32 clk_size;
51 };
52
53 struct imx290 {
54 struct device *dev;
55 struct clk *xclk;
56 + u32 xclk_freq;
57 struct regmap *regmap;
58 u8 nlanes;
59 u8 bpp;
60 @@ -116,8 +130,6 @@ static const struct imx290_regval imx290
61 { 0x3018, 0x65 },
62 { 0x3019, 0x04 },
63 { 0x301a, 0x00 },
64 - { 0x3444, 0x20 },
65 - { 0x3445, 0x25 },
66 { 0x303a, 0x0c },
67 { 0x3040, 0x00 },
68 { 0x3041, 0x00 },
69 @@ -171,6 +183,30 @@ static const struct imx290_regval imx290
70 { 0x33b3, 0x04 },
71 };
72
73 +static const struct imx290_regval imx290_37_125mhz_clock_1080p[] = {
74 + { 0x305c, 0x18 },
75 + { 0x305d, 0x03 },
76 + { 0x305e, 0x20 },
77 + { 0x305f, 0x01 },
78 + { 0x315e, 0x1a },
79 + { 0x3164, 0x1a },
80 + { 0x3444, 0x20 },
81 + { 0x3445, 0x25 },
82 + { 0x3480, 0x49 },
83 +};
84 +
85 +static const struct imx290_regval imx290_74_250mhz_clock_1080p[] = {
86 + { 0x305c, 0x0c },
87 + { 0x305d, 0x03 },
88 + { 0x305e, 0x10 },
89 + { 0x305f, 0x01 },
90 + { 0x315e, 0x1b },
91 + { 0x3164, 0x1b },
92 + { 0x3444, 0x40 },
93 + { 0x3445, 0x4a },
94 + { 0x3480, 0x92 },
95 +};
96 +
97 static const struct imx290_regval imx290_1080p_settings[] = {
98 /* mode settings */
99 { 0x3007, 0x00 },
100 @@ -182,13 +218,6 @@ static const struct imx290_regval imx290
101 { 0x3419, 0x04 },
102 { 0x3012, 0x64 },
103 { 0x3013, 0x00 },
104 - { 0x305c, 0x18 },
105 - { 0x305d, 0x03 },
106 - { 0x305e, 0x20 },
107 - { 0x305f, 0x01 },
108 - { 0x315e, 0x1a },
109 - { 0x3164, 0x1a },
110 - { 0x3480, 0x49 },
111 /* data rate settings */
112 { 0x3405, 0x10 },
113 { 0x3446, 0x57 },
114 @@ -209,6 +238,30 @@ static const struct imx290_regval imx290
115 { 0x3455, 0x00 },
116 };
117
118 +static const struct imx290_regval imx290_37_125mhz_clock_720p[] = {
119 + { 0x305c, 0x20 },
120 + { 0x305d, 0x00 },
121 + { 0x305e, 0x20 },
122 + { 0x305f, 0x01 },
123 + { 0x315e, 0x1a },
124 + { 0x3164, 0x1a },
125 + { 0x3444, 0x20 },
126 + { 0x3445, 0x25 },
127 + { 0x3480, 0x49 },
128 +};
129 +
130 +static const struct imx290_regval imx290_74_250mhz_clock_720p[] = {
131 + { 0x305c, 0x10 },
132 + { 0x305d, 0x00 },
133 + { 0x305e, 0x10 },
134 + { 0x305f, 0x01 },
135 + { 0x315e, 0x1b },
136 + { 0x3164, 0x1b },
137 + { 0x3444, 0x40 },
138 + { 0x3445, 0x4a },
139 + { 0x3480, 0x92 },
140 +};
141 +
142 static const struct imx290_regval imx290_720p_settings[] = {
143 /* mode settings */
144 { 0x3007, 0x10 },
145 @@ -220,13 +273,6 @@ static const struct imx290_regval imx290
146 { 0x3419, 0x02 },
147 { 0x3012, 0x64 },
148 { 0x3013, 0x00 },
149 - { 0x305c, 0x20 },
150 - { 0x305d, 0x00 },
151 - { 0x305e, 0x20 },
152 - { 0x305f, 0x01 },
153 - { 0x315e, 0x1a },
154 - { 0x3164, 0x1a },
155 - { 0x3480, 0x49 },
156 /* data rate settings */
157 { 0x3405, 0x10 },
158 { 0x3446, 0x4f },
159 @@ -312,6 +358,11 @@ static const struct imx290_mode imx290_m
160 .link_freq_index = FREQ_INDEX_1080P,
161 .data = imx290_1080p_settings,
162 .data_size = ARRAY_SIZE(imx290_1080p_settings),
163 + .clk_data = {
164 + [CLK_37_125] = imx290_37_125mhz_clock_1080p,
165 + [CLK_74_25] = imx290_74_250mhz_clock_1080p,
166 + },
167 + .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_1080p),
168 },
169 {
170 .width = 1280,
171 @@ -320,6 +371,11 @@ static const struct imx290_mode imx290_m
172 .link_freq_index = FREQ_INDEX_720P,
173 .data = imx290_720p_settings,
174 .data_size = ARRAY_SIZE(imx290_720p_settings),
175 + .clk_data = {
176 + [CLK_37_125] = imx290_37_125mhz_clock_1080p,
177 + [CLK_74_25] = imx290_74_250mhz_clock_1080p,
178 + },
179 + .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_1080p),
180 },
181 };
182
183 @@ -331,6 +387,11 @@ static const struct imx290_mode imx290_m
184 .link_freq_index = FREQ_INDEX_1080P,
185 .data = imx290_1080p_settings,
186 .data_size = ARRAY_SIZE(imx290_1080p_settings),
187 + .clk_data = {
188 + [CLK_37_125] = imx290_37_125mhz_clock_720p,
189 + [CLK_74_25] = imx290_74_250mhz_clock_720p,
190 + },
191 + .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_720p),
192 },
193 {
194 .width = 1280,
195 @@ -339,6 +400,11 @@ static const struct imx290_mode imx290_m
196 .link_freq_index = FREQ_INDEX_720P,
197 .data = imx290_720p_settings,
198 .data_size = ARRAY_SIZE(imx290_720p_settings),
199 + .clk_data = {
200 + [CLK_37_125] = imx290_37_125mhz_clock_720p,
201 + [CLK_74_25] = imx290_74_250mhz_clock_720p,
202 + },
203 + .clk_size = ARRAY_SIZE(imx290_37_125mhz_clock_720p),
204 },
205 };
206
207 @@ -712,6 +778,8 @@ static int imx290_set_hmax(struct imx290
208 /* Start streaming */
209 static int imx290_start_streaming(struct imx290 *imx290)
210 {
211 + enum imx290_clk_index clk_idx = imx290->xclk_freq == 37125000 ?
212 + CLK_37_125 : CLK_74_25;
213 int ret;
214
215 /* Set init register settings */
216 @@ -723,6 +791,14 @@ static int imx290_start_streaming(struct
217 return ret;
218 }
219
220 + ret = imx290_set_register_array(imx290,
221 + imx290->current_mode->clk_data[clk_idx],
222 + imx290->current_mode->clk_size);
223 + if (ret < 0) {
224 + dev_err(imx290->dev, "Could not set clock registers\n");
225 + return ret;
226 + }
227 +
228 /* Apply the register values related to current frame format */
229 ret = imx290_write_current_format(imx290);
230 if (ret < 0) {
231 @@ -935,7 +1011,6 @@ static int imx290_probe(struct i2c_clien
232 .bus_type = V4L2_MBUS_CSI2_DPHY
233 };
234 struct imx290 *imx290;
235 - u32 xclk_freq;
236 s64 fq;
237 int ret;
238
239 @@ -999,21 +1074,21 @@ static int imx290_probe(struct i2c_clien
240 }
241
242 ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
243 - &xclk_freq);
244 + &imx290->xclk_freq);
245 if (ret) {
246 dev_err(dev, "Could not get xclk frequency\n");
247 goto free_err;
248 }
249
250 /* external clock must be 37.125 MHz */
251 - if (xclk_freq != 37125000) {
252 + if (imx290->xclk_freq != 37125000 && imx290->xclk_freq != 74250000) {
253 dev_err(dev, "External clock frequency %u is not supported\n",
254 - xclk_freq);
255 + imx290->xclk_freq);
256 ret = -EINVAL;
257 goto free_err;
258 }
259
260 - ret = clk_set_rate(imx290->xclk, xclk_freq);
261 + ret = clk_set_rate(imx290->xclk, imx290->xclk_freq);
262 if (ret) {
263 dev_err(dev, "Could not set xclk frequency\n");
264 goto free_err;