kernel: bump 5.15 to 5.15.77
[openwrt/openwrt.git] / target / linux / bcm27xx / patches-5.15 / 950-0721-media-i2c-Add-ov7251_pll_configure.patch
1 From c16cebe5ebfb309074ff7cc9ddeaf37724d31512 Mon Sep 17 00:00:00 2001
2 From: Daniel Scally <djrscally@gmail.com>
3 Date: Tue, 15 Feb 2022 23:07:32 +0000
4 Subject: [PATCH] media: i2c: Add ov7251_pll_configure()
5
6 Rather than having the pll settings hidden inside mode blobs, define
7 them in structs and use a dedicated function to set them. This makes
8 it simpler to extend the driver to support other external clock
9 frequencies.
10
11 Signed-off-by: Daniel Scally <djrscally@gmail.com>
12 ---
13 drivers/media/i2c/ov7251.c | 165 ++++++++++++++++++++++++++++++-------
14 1 file changed, 135 insertions(+), 30 deletions(-)
15
16 --- a/drivers/media/i2c/ov7251.c
17 +++ b/drivers/media/i2c/ov7251.c
18 @@ -42,6 +42,16 @@
19 #define OV7251_TIMING_FORMAT2_MIRROR BIT(2)
20 #define OV7251_PRE_ISP_00 0x5e00
21 #define OV7251_PRE_ISP_00_TEST_PATTERN BIT(7)
22 +#define OV7251_PLL1_PRE_DIV_REG 0x30b4
23 +#define OV7251_PLL1_MULT_REG 0x30b3
24 +#define OV7251_PLL1_DIVIDER_REG 0x30b1
25 +#define OV7251_PLL1_PIX_DIV_REG 0x30b0
26 +#define OV7251_PLL1_MIPI_DIV_REG 0x30b5
27 +#define OV7251_PLL2_PRE_DIV_REG 0x3098
28 +#define OV7251_PLL2_MULT_REG 0x3099
29 +#define OV7251_PLL2_DIVIDER_REG 0x309d
30 +#define OV7251_PLL2_SYS_DIV_REG 0x309a
31 +#define OV7251_PLL2_ADC_DIV_REG 0x309b
32
33 struct reg_value {
34 u16 reg;
35 @@ -60,6 +70,27 @@ struct ov7251_mode_info {
36 struct v4l2_fract timeperframe;
37 };
38
39 +struct ov7251_pll1_config {
40 + unsigned int pre_div;
41 + unsigned int mult;
42 + unsigned int div;
43 + unsigned int pix_div;
44 + unsigned int mipi_div;
45 +};
46 +
47 +struct ov7251_pll2_config {
48 + unsigned int pre_div;
49 + unsigned int mult;
50 + unsigned int div;
51 + unsigned int sys_div;
52 + unsigned int adc_div;
53 +};
54 +
55 +struct ov7251_pll_configs {
56 + const struct ov7251_pll1_config *pll1;
57 + const struct ov7251_pll2_config *pll2;
58 +};
59 +
60 struct ov7251 {
61 struct i2c_client *i2c_client;
62 struct device *dev;
63 @@ -71,6 +102,8 @@ struct ov7251 {
64 struct clk *xclk;
65 u32 xclk_freq;
66
67 + const struct ov7251_pll_configs *pll_configs;
68 +
69 struct regulator *io_regulator;
70 struct regulator *core_regulator;
71 struct regulator *analog_regulator;
72 @@ -100,6 +133,36 @@ static inline struct ov7251 *to_ov7251(s
73 return container_of(sd, struct ov7251, sd);
74 }
75
76 +enum xclk_rate {
77 + OV7251_24_MHZ,
78 + OV7251_NUM_SUPPORTED_RATES
79 +};
80 +
81 +static const struct ov7251_pll1_config ov7251_pll1_config_24_mhz = {
82 + .pre_div = 0x03,
83 + .mult = 0x64,
84 + .div = 0x01,
85 + .pix_div = 0x0a,
86 + .mipi_div = 0x05
87 +};
88 +
89 +static const struct ov7251_pll2_config ov7251_pll2_config_24_mhz = {
90 + .pre_div = 0x04,
91 + .mult = 0x28,
92 + .div = 0x00,
93 + .sys_div = 0x05,
94 + .adc_div = 0x04
95 +};
96 +
97 +static const struct ov7251_pll_configs ov7251_pll_configs_24_mhz = {
98 + .pll1 = &ov7251_pll1_config_24_mhz,
99 + .pll2 = &ov7251_pll2_config_24_mhz
100 +};
101 +
102 +static const struct ov7251_pll_configs *ov7251_pll_configs[] = {
103 + [OV7251_24_MHZ] = &ov7251_pll_configs_24_mhz
104 +};
105 +
106 static const struct reg_value ov7251_global_init_setting[] = {
107 { 0x0103, 0x01 },
108 { 0x303b, 0x02 },
109 @@ -118,16 +181,6 @@ static const struct reg_value ov7251_set
110 { 0x301c, 0xf0 },
111 { 0x3023, 0x05 },
112 { 0x3037, 0xf0 },
113 - { 0x3098, 0x04 }, /* pll2 pre divider */
114 - { 0x3099, 0x28 }, /* pll2 multiplier */
115 - { 0x309a, 0x05 }, /* pll2 sys divider */
116 - { 0x309b, 0x04 }, /* pll2 adc divider */
117 - { 0x309d, 0x00 }, /* pll2 divider */
118 - { 0x30b0, 0x0a }, /* pll1 pix divider */
119 - { 0x30b1, 0x01 }, /* pll1 divider */
120 - { 0x30b3, 0x64 }, /* pll1 multiplier */
121 - { 0x30b4, 0x03 }, /* pll1 pre divider */
122 - { 0x30b5, 0x05 }, /* pll1 mipi divider */
123 { 0x3106, 0xda },
124 { 0x3503, 0x07 },
125 { 0x3509, 0x10 },
126 @@ -256,16 +309,6 @@ static const struct reg_value ov7251_set
127 { 0x301c, 0x00 },
128 { 0x3023, 0x05 },
129 { 0x3037, 0xf0 },
130 - { 0x3098, 0x04 }, /* pll2 pre divider */
131 - { 0x3099, 0x28 }, /* pll2 multiplier */
132 - { 0x309a, 0x05 }, /* pll2 sys divider */
133 - { 0x309b, 0x04 }, /* pll2 adc divider */
134 - { 0x309d, 0x00 }, /* pll2 divider */
135 - { 0x30b0, 0x0a }, /* pll1 pix divider */
136 - { 0x30b1, 0x01 }, /* pll1 divider */
137 - { 0x30b3, 0x64 }, /* pll1 multiplier */
138 - { 0x30b4, 0x03 }, /* pll1 pre divider */
139 - { 0x30b5, 0x05 }, /* pll1 mipi divider */
140 { 0x3106, 0xda },
141 { 0x3503, 0x07 },
142 { 0x3509, 0x10 },
143 @@ -394,16 +437,6 @@ static const struct reg_value ov7251_set
144 { 0x301c, 0x00 },
145 { 0x3023, 0x05 },
146 { 0x3037, 0xf0 },
147 - { 0x3098, 0x04 }, /* pll2 pre divider */
148 - { 0x3099, 0x28 }, /* pll2 multiplier */
149 - { 0x309a, 0x05 }, /* pll2 sys divider */
150 - { 0x309b, 0x04 }, /* pll2 adc divider */
151 - { 0x309d, 0x00 }, /* pll2 divider */
152 - { 0x30b0, 0x0a }, /* pll1 pix divider */
153 - { 0x30b1, 0x01 }, /* pll1 divider */
154 - { 0x30b3, 0x64 }, /* pll1 multiplier */
155 - { 0x30b4, 0x03 }, /* pll1 pre divider */
156 - { 0x30b5, 0x05 }, /* pll1 mipi divider */
157 { 0x3106, 0xda },
158 { 0x3503, 0x07 },
159 { 0x3509, 0x10 },
160 @@ -519,6 +552,10 @@ static const struct reg_value ov7251_set
161 { 0x5001, 0x80 },
162 };
163
164 +static const unsigned long supported_xclk_rates[] = {
165 + [OV7251_24_MHZ] = 24000000,
166 +};
167 +
168 static const s64 link_freq[] = {
169 240000000,
170 };
171 @@ -692,6 +729,63 @@ static int ov7251_read_reg(struct ov7251
172 return 0;
173 }
174
175 +static int ov7251_pll_configure(struct ov7251 *ov7251)
176 +{
177 + const struct ov7251_pll_configs *configs;
178 + int ret;
179 +
180 + configs = ov7251->pll_configs;
181 +
182 + ret = ov7251_write_reg(ov7251, OV7251_PLL1_PRE_DIV_REG,
183 + configs->pll1->pre_div);
184 + if (ret < 0)
185 + return ret;
186 +
187 + ret = ov7251_write_reg(ov7251, OV7251_PLL1_MULT_REG,
188 + configs->pll1->mult);
189 + if (ret < 0)
190 + return ret;
191 + ret = ov7251_write_reg(ov7251, OV7251_PLL1_DIVIDER_REG,
192 + configs->pll1->div);
193 + if (ret < 0)
194 + return ret;
195 +
196 + ret = ov7251_write_reg(ov7251, OV7251_PLL1_PIX_DIV_REG,
197 + configs->pll1->pix_div);
198 + if (ret < 0)
199 + return ret;
200 +
201 + ret = ov7251_write_reg(ov7251, OV7251_PLL1_MIPI_DIV_REG,
202 + configs->pll1->mipi_div);
203 + if (ret < 0)
204 + return ret;
205 +
206 + ret = ov7251_write_reg(ov7251, OV7251_PLL2_PRE_DIV_REG,
207 + configs->pll2->pre_div);
208 + if (ret < 0)
209 + return ret;
210 +
211 + ret = ov7251_write_reg(ov7251, OV7251_PLL2_MULT_REG,
212 + configs->pll2->mult);
213 + if (ret < 0)
214 + return ret;
215 +
216 + ret = ov7251_write_reg(ov7251, OV7251_PLL2_DIVIDER_REG,
217 + configs->pll2->div);
218 + if (ret < 0)
219 + return ret;
220 +
221 + ret = ov7251_write_reg(ov7251, OV7251_PLL2_SYS_DIV_REG,
222 + configs->pll2->sys_div);
223 + if (ret < 0)
224 + return ret;
225 +
226 + ret = ov7251_write_reg(ov7251, OV7251_PLL2_ADC_DIV_REG,
227 + configs->pll2->adc_div);
228 +
229 + return ret;
230 +}
231 +
232 static int ov7251_set_exposure(struct ov7251 *ov7251, s32 exposure)
233 {
234 u16 reg;
235 @@ -1143,6 +1237,11 @@ static int ov7251_s_stream(struct v4l2_s
236 mutex_lock(&ov7251->lock);
237
238 if (enable) {
239 + ret = ov7251_pll_configure(ov7251);
240 + if (ret)
241 + return dev_err_probe(ov7251->dev, ret,
242 + "error configuring PLLs\n");
243 +
244 ret = ov7251_set_register_array(ov7251,
245 ov7251->current_mode->data,
246 ov7251->current_mode->data_size);
247 @@ -1326,6 +1425,7 @@ static int ov7251_probe(struct i2c_clien
248 struct ov7251 *ov7251;
249 u8 chip_id_high, chip_id_low, chip_rev;
250 int ret;
251 + int i;
252
253 ov7251 = devm_kzalloc(dev, sizeof(struct ov7251), GFP_KERNEL);
254 if (!ov7251)
255 @@ -1364,6 +1464,11 @@ static int ov7251_probe(struct i2c_clien
256 dev_err(dev, "could not set xclk frequency\n");
257 return ret;
258 }
259 + for (i = 0; i < ARRAY_SIZE(supported_xclk_rates); i++)
260 + if (ov7251->xclk_freq == supported_xclk_rates[i])
261 + break;
262 +
263 + ov7251->pll_configs = ov7251_pll_configs[i];
264
265 ov7251->io_regulator = devm_regulator_get(dev, "vdddo");
266 if (IS_ERR(ov7251->io_regulator)) {