[media] smiapp: Remove FSF's address from the license header
[deliverable/linux.git] / drivers / media / i2c / smiapp-pll.c
CommitLineData
cf1c5fae 1/*
cb7a01ac 2 * drivers/media/i2c/smiapp-pll.c
cf1c5fae
SA
3 *
4 * Generic driver for SMIA/SMIA++ compliant camera modules
5 *
6 * Copyright (C) 2011--2012 Nokia Corporation
8c5dff90 7 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
cf1c5fae
SA
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
cf1c5fae
SA
17 */
18
19#include <linux/gcd.h>
20#include <linux/lcm.h>
21#include <linux/module.h>
22
23#include "smiapp-pll.h"
24
25/* Return an even number or one. */
26static inline uint32_t clk_div_even(uint32_t a)
27{
28 return max_t(uint32_t, 1, a & ~1);
29}
30
31/* Return an even number or one. */
32static inline uint32_t clk_div_even_up(uint32_t a)
33{
34 if (a == 1)
35 return 1;
36 return (a + 1) & ~1;
37}
38
39static inline uint32_t is_one_or_even(uint32_t a)
40{
41 if (a == 1)
42 return 1;
43 if (a & 1)
44 return 0;
45
46 return 1;
47}
48
49static int bounds_check(struct device *dev, uint32_t val,
50 uint32_t min, uint32_t max, char *str)
51{
52 if (val >= min && val <= max)
53 return 0;
54
6de1b143 55 dev_dbg(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);
cf1c5fae
SA
56
57 return -EINVAL;
58}
59
60static void print_pll(struct device *dev, struct smiapp_pll *pll)
61{
c37f9bf9
SA
62 dev_dbg(dev, "pre_pll_clk_div\t%u\n", pll->pre_pll_clk_div);
63 dev_dbg(dev, "pll_multiplier \t%u\n", pll->pll_multiplier);
bc47150a 64 if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
e3f8bc8c
SA
65 dev_dbg(dev, "op_sys_clk_div \t%u\n", pll->op.sys_clk_div);
66 dev_dbg(dev, "op_pix_clk_div \t%u\n", pll->op.pix_clk_div);
cf1c5fae 67 }
e3f8bc8c
SA
68 dev_dbg(dev, "vt_sys_clk_div \t%u\n", pll->vt.sys_clk_div);
69 dev_dbg(dev, "vt_pix_clk_div \t%u\n", pll->vt.pix_clk_div);
cf1c5fae 70
c37f9bf9
SA
71 dev_dbg(dev, "ext_clk_freq_hz \t%u\n", pll->ext_clk_freq_hz);
72 dev_dbg(dev, "pll_ip_clk_freq_hz \t%u\n", pll->pll_ip_clk_freq_hz);
73 dev_dbg(dev, "pll_op_clk_freq_hz \t%u\n", pll->pll_op_clk_freq_hz);
bc47150a 74 if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
c37f9bf9 75 dev_dbg(dev, "op_sys_clk_freq_hz \t%u\n",
e3f8bc8c 76 pll->op.sys_clk_freq_hz);
c37f9bf9 77 dev_dbg(dev, "op_pix_clk_freq_hz \t%u\n",
e3f8bc8c 78 pll->op.pix_clk_freq_hz);
cf1c5fae 79 }
e3f8bc8c
SA
80 dev_dbg(dev, "vt_sys_clk_freq_hz \t%u\n", pll->vt.sys_clk_freq_hz);
81 dev_dbg(dev, "vt_pix_clk_freq_hz \t%u\n", pll->vt.pix_clk_freq_hz);
cf1c5fae
SA
82}
83
c859470a
SA
84static int check_all_bounds(struct device *dev,
85 const struct smiapp_pll_limits *limits,
974abe44
SA
86 const struct smiapp_pll_branch_limits *op_limits,
87 struct smiapp_pll *pll,
88 struct smiapp_pll_branch *op_pll)
c859470a
SA
89{
90 int rval;
91
92 rval = bounds_check(dev, pll->pll_ip_clk_freq_hz,
93 limits->min_pll_ip_freq_hz,
94 limits->max_pll_ip_freq_hz,
95 "pll_ip_clk_freq_hz");
96 if (!rval)
97 rval = bounds_check(
98 dev, pll->pll_multiplier,
99 limits->min_pll_multiplier, limits->max_pll_multiplier,
100 "pll_multiplier");
101 if (!rval)
102 rval = bounds_check(
103 dev, pll->pll_op_clk_freq_hz,
104 limits->min_pll_op_freq_hz, limits->max_pll_op_freq_hz,
105 "pll_op_clk_freq_hz");
106 if (!rval)
107 rval = bounds_check(
974abe44
SA
108 dev, op_pll->sys_clk_div,
109 op_limits->min_sys_clk_div, op_limits->max_sys_clk_div,
c859470a 110 "op_sys_clk_div");
c859470a
SA
111 if (!rval)
112 rval = bounds_check(
974abe44
SA
113 dev, op_pll->sys_clk_freq_hz,
114 op_limits->min_sys_clk_freq_hz,
115 op_limits->max_sys_clk_freq_hz,
c859470a
SA
116 "op_sys_clk_freq_hz");
117 if (!rval)
118 rval = bounds_check(
974abe44
SA
119 dev, op_pll->pix_clk_freq_hz,
120 op_limits->min_pix_clk_freq_hz,
121 op_limits->max_pix_clk_freq_hz,
c859470a 122 "op_pix_clk_freq_hz");
63516b55
SA
123
124 /*
125 * If there are no OP clocks, the VT clocks are contained in
126 * the OP clock struct.
127 */
128 if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)
129 return rval;
130
c859470a
SA
131 if (!rval)
132 rval = bounds_check(
e3f8bc8c 133 dev, pll->vt.sys_clk_freq_hz,
c859470a
SA
134 limits->vt.min_sys_clk_freq_hz,
135 limits->vt.max_sys_clk_freq_hz,
136 "vt_sys_clk_freq_hz");
137 if (!rval)
138 rval = bounds_check(
e3f8bc8c 139 dev, pll->vt.pix_clk_freq_hz,
c859470a
SA
140 limits->vt.min_pix_clk_freq_hz,
141 limits->vt.max_pix_clk_freq_hz,
142 "vt_pix_clk_freq_hz");
143
144 return rval;
145}
146
367da7a3
SA
147/*
148 * Heuristically guess the PLL tree for a given common multiplier and
149 * divisor. Begin with the operational timing and continue to video
150 * timing once operational timing has been verified.
151 *
152 * @mul is the PLL multiplier and @div is the common divisor
153 * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL
154 * multiplier will be a multiple of @mul.
155 *
156 * @return Zero on success, error code on error.
157 */
974abe44
SA
158static int __smiapp_pll_calculate(
159 struct device *dev, const struct smiapp_pll_limits *limits,
160 const struct smiapp_pll_branch_limits *op_limits,
161 struct smiapp_pll *pll, struct smiapp_pll_branch *op_pll, uint32_t mul,
162 uint32_t div, uint32_t lane_op_clock_ratio)
cf1c5fae
SA
163{
164 uint32_t sys_div;
165 uint32_t best_pix_div = INT_MAX >> 1;
166 uint32_t vt_op_binning_div;
367da7a3
SA
167 /*
168 * Higher multipliers (and divisors) are often required than
169 * necessitated by the external clock and the output clocks.
170 * There are limits for all values in the clock tree. These
171 * are the minimum and maximum multiplier for mul.
172 */
cf1c5fae
SA
173 uint32_t more_mul_min, more_mul_max;
174 uint32_t more_mul_factor;
175 uint32_t min_vt_div, max_vt_div, vt_div;
176 uint32_t min_sys_div, max_sys_div;
177 unsigned int i;
cf1c5fae 178
cf1c5fae
SA
179 /*
180 * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
181 * too high.
182 */
c37f9bf9 183 dev_dbg(dev, "pre_pll_clk_div %u\n", pll->pre_pll_clk_div);
cf1c5fae
SA
184
185 /* Don't go above max pll multiplier. */
186 more_mul_max = limits->max_pll_multiplier / mul;
c37f9bf9 187 dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %u\n",
cf1c5fae
SA
188 more_mul_max);
189 /* Don't go above max pll op frequency. */
190 more_mul_max =
c2ebca00 191 min_t(uint32_t,
cf1c5fae
SA
192 more_mul_max,
193 limits->max_pll_op_freq_hz
194 / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
c37f9bf9 195 dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %u\n",
cf1c5fae
SA
196 more_mul_max);
197 /* Don't go above the division capability of op sys clock divider. */
198 more_mul_max = min(more_mul_max,
974abe44 199 op_limits->max_sys_clk_div * pll->pre_pll_clk_div
cf1c5fae 200 / div);
c37f9bf9 201 dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n",
cf1c5fae
SA
202 more_mul_max);
203 /* Ensure we won't go above min_pll_multiplier. */
204 more_mul_max = min(more_mul_max,
205 DIV_ROUND_UP(limits->max_pll_multiplier, mul));
c37f9bf9 206 dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n",
cf1c5fae
SA
207 more_mul_max);
208
209 /* Ensure we won't go below min_pll_op_freq_hz. */
210 more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz,
211 pll->ext_clk_freq_hz / pll->pre_pll_clk_div
212 * mul);
c37f9bf9 213 dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %u\n",
cf1c5fae
SA
214 more_mul_min);
215 /* Ensure we won't go below min_pll_multiplier. */
216 more_mul_min = max(more_mul_min,
217 DIV_ROUND_UP(limits->min_pll_multiplier, mul));
c37f9bf9 218 dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %u\n",
cf1c5fae
SA
219 more_mul_min);
220
221 if (more_mul_min > more_mul_max) {
6de1b143
SA
222 dev_dbg(dev,
223 "unable to compute more_mul_min and more_mul_max\n");
cf1c5fae
SA
224 return -EINVAL;
225 }
226
227 more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
c37f9bf9 228 dev_dbg(dev, "more_mul_factor: %u\n", more_mul_factor);
974abe44
SA
229 more_mul_factor = lcm(more_mul_factor, op_limits->min_sys_clk_div);
230 dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
cf1c5fae
SA
231 more_mul_factor);
232 i = roundup(more_mul_min, more_mul_factor);
233 if (!is_one_or_even(i))
234 i <<= 1;
235
c37f9bf9 236 dev_dbg(dev, "final more_mul: %u\n", i);
cf1c5fae 237 if (i > more_mul_max) {
c37f9bf9 238 dev_dbg(dev, "final more_mul is bad, max %u\n", more_mul_max);
cf1c5fae
SA
239 return -EINVAL;
240 }
241
242 pll->pll_multiplier = mul * i;
974abe44
SA
243 op_pll->sys_clk_div = div * i / pll->pre_pll_clk_div;
244 dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll->sys_clk_div);
cf1c5fae
SA
245
246 pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz
247 / pll->pre_pll_clk_div;
248
249 pll->pll_op_clk_freq_hz = pll->pll_ip_clk_freq_hz
250 * pll->pll_multiplier;
251
252 /* Derive pll_op_clk_freq_hz. */
974abe44
SA
253 op_pll->sys_clk_freq_hz =
254 pll->pll_op_clk_freq_hz / op_pll->sys_clk_div;
cf1c5fae 255
974abe44
SA
256 op_pll->pix_clk_div = pll->bits_per_pixel;
257 dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll->pix_clk_div);
cf1c5fae 258
974abe44
SA
259 op_pll->pix_clk_freq_hz =
260 op_pll->sys_clk_freq_hz / op_pll->pix_clk_div;
261
262 if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
263 /* No OP clocks --- VT clocks are used instead. */
264 goto out_skip_vt_calc;
265 }
cf1c5fae
SA
266
267 /*
268 * Some sensors perform analogue binning and some do this
269 * digitally. The ones doing this digitally can be roughly be
270 * found out using this formula. The ones doing this digitally
271 * should run at higher clock rate, so smaller divisor is used
272 * on video timing side.
273 */
274 if (limits->min_line_length_pck_bin > limits->min_line_length_pck
275 / pll->binning_horizontal)
276 vt_op_binning_div = pll->binning_horizontal;
277 else
278 vt_op_binning_div = 1;
c37f9bf9 279 dev_dbg(dev, "vt_op_binning_div: %u\n", vt_op_binning_div);
cf1c5fae
SA
280
281 /*
282 * Profile 2 supports vt_pix_clk_div E [4, 10]
283 *
284 * Horizontal binning can be used as a base for difference in
285 * divisors. One must make sure that horizontal blanking is
286 * enough to accommodate the CSI-2 sync codes.
287 *
288 * Take scaling factor into account as well.
289 *
290 * Find absolute limits for the factor of vt divider.
291 */
c37f9bf9 292 dev_dbg(dev, "scale_m: %u\n", pll->scale_m);
974abe44 293 min_vt_div = DIV_ROUND_UP(op_pll->pix_clk_div * op_pll->sys_clk_div
cf1c5fae
SA
294 * pll->scale_n,
295 lane_op_clock_ratio * vt_op_binning_div
296 * pll->scale_m);
297
298 /* Find smallest and biggest allowed vt divisor. */
c37f9bf9 299 dev_dbg(dev, "min_vt_div: %u\n", min_vt_div);
cf1c5fae
SA
300 min_vt_div = max(min_vt_div,
301 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
6ec84a28 302 limits->vt.max_pix_clk_freq_hz));
c37f9bf9 303 dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n",
cf1c5fae
SA
304 min_vt_div);
305 min_vt_div = max_t(uint32_t, min_vt_div,
6ec84a28
LP
306 limits->vt.min_pix_clk_div
307 * limits->vt.min_sys_clk_div);
c37f9bf9 308 dev_dbg(dev, "min_vt_div: min_vt_clk_div: %u\n", min_vt_div);
cf1c5fae 309
6ec84a28 310 max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div;
c37f9bf9 311 dev_dbg(dev, "max_vt_div: %u\n", max_vt_div);
cf1c5fae
SA
312 max_vt_div = min(max_vt_div,
313 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
6ec84a28 314 limits->vt.min_pix_clk_freq_hz));
c37f9bf9 315 dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n",
cf1c5fae
SA
316 max_vt_div);
317
318 /*
319 * Find limitsits for sys_clk_div. Not all values are possible
320 * with all values of pix_clk_div.
321 */
6ec84a28 322 min_sys_div = limits->vt.min_sys_clk_div;
c37f9bf9 323 dev_dbg(dev, "min_sys_div: %u\n", min_sys_div);
cf1c5fae
SA
324 min_sys_div = max(min_sys_div,
325 DIV_ROUND_UP(min_vt_div,
6ec84a28 326 limits->vt.max_pix_clk_div));
c37f9bf9 327 dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div);
cf1c5fae
SA
328 min_sys_div = max(min_sys_div,
329 pll->pll_op_clk_freq_hz
6ec84a28 330 / limits->vt.max_sys_clk_freq_hz);
c37f9bf9 331 dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div);
cf1c5fae 332 min_sys_div = clk_div_even_up(min_sys_div);
c37f9bf9 333 dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div);
cf1c5fae 334
6ec84a28 335 max_sys_div = limits->vt.max_sys_clk_div;
c37f9bf9 336 dev_dbg(dev, "max_sys_div: %u\n", max_sys_div);
cf1c5fae
SA
337 max_sys_div = min(max_sys_div,
338 DIV_ROUND_UP(max_vt_div,
6ec84a28 339 limits->vt.min_pix_clk_div));
c37f9bf9 340 dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div);
cf1c5fae
SA
341 max_sys_div = min(max_sys_div,
342 DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
6ec84a28 343 limits->vt.min_pix_clk_freq_hz));
c37f9bf9 344 dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div);
cf1c5fae
SA
345
346 /*
347 * Find pix_div such that a legal pix_div * sys_div results
348 * into a value which is not smaller than div, the desired
349 * divisor.
350 */
351 for (vt_div = min_vt_div; vt_div <= max_vt_div;
352 vt_div += 2 - (vt_div & 1)) {
353 for (sys_div = min_sys_div;
354 sys_div <= max_sys_div;
355 sys_div += 2 - (sys_div & 1)) {
c2ebca00 356 uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div);
cf1c5fae 357
6ec84a28
LP
358 if (pix_div < limits->vt.min_pix_clk_div
359 || pix_div > limits->vt.max_pix_clk_div) {
cf1c5fae 360 dev_dbg(dev,
c37f9bf9 361 "pix_div %u too small or too big (%u--%u)\n",
cf1c5fae 362 pix_div,
6ec84a28
LP
363 limits->vt.min_pix_clk_div,
364 limits->vt.max_pix_clk_div);
cf1c5fae
SA
365 continue;
366 }
367
368 /* Check if this one is better. */
369 if (pix_div * sys_div
370 <= roundup(min_vt_div, best_pix_div))
371 best_pix_div = pix_div;
372 }
373 if (best_pix_div < INT_MAX >> 1)
374 break;
375 }
376
e3f8bc8c
SA
377 pll->vt.sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div);
378 pll->vt.pix_clk_div = best_pix_div;
cf1c5fae 379
e3f8bc8c
SA
380 pll->vt.sys_clk_freq_hz =
381 pll->pll_op_clk_freq_hz / pll->vt.sys_clk_div;
382 pll->vt.pix_clk_freq_hz =
383 pll->vt.sys_clk_freq_hz / pll->vt.pix_clk_div;
cf1c5fae 384
974abe44 385out_skip_vt_calc:
cf1c5fae 386 pll->pixel_rate_csi =
974abe44 387 op_pll->pix_clk_freq_hz * lane_op_clock_ratio;
e7c329a0 388 pll->pixel_rate_pixel_array = pll->vt.pix_clk_freq_hz;
cf1c5fae 389
974abe44 390 return check_all_bounds(dev, limits, op_limits, pll, op_pll);
cf1c5fae 391}
6de1b143 392
8f7e91a3
LP
393int smiapp_pll_calculate(struct device *dev,
394 const struct smiapp_pll_limits *limits,
6de1b143
SA
395 struct smiapp_pll *pll)
396{
974abe44
SA
397 const struct smiapp_pll_branch_limits *op_limits = &limits->op;
398 struct smiapp_pll_branch *op_pll = &pll->op;
8f7e91a3
LP
399 uint16_t min_pre_pll_clk_div;
400 uint16_t max_pre_pll_clk_div;
6de1b143
SA
401 uint32_t lane_op_clock_ratio;
402 uint32_t mul, div;
403 unsigned int i;
404 int rval = -EINVAL;
405
974abe44
SA
406 if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
407 /*
408 * If there's no OP PLL at all, use the VT values
409 * instead. The OP values are ignored for the rest of
410 * the PLL calculation.
411 */
412 op_limits = &limits->vt;
413 op_pll = &pll->vt;
414 }
415
6de1b143 416 if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
f5984bbd 417 lane_op_clock_ratio = pll->csi2.lanes;
6de1b143
SA
418 else
419 lane_op_clock_ratio = 1;
c37f9bf9 420 dev_dbg(dev, "lane_op_clock_ratio: %u\n", lane_op_clock_ratio);
6de1b143 421
c37f9bf9 422 dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal,
6de1b143
SA
423 pll->binning_vertical);
424
f5984bbd
SA
425 switch (pll->bus_type) {
426 case SMIAPP_PLL_BUS_TYPE_CSI2:
427 /* CSI transfers 2 bits per clock per lane; thus times 2 */
428 pll->pll_op_clk_freq_hz = pll->link_freq * 2
429 * (pll->csi2.lanes / lane_op_clock_ratio);
430 break;
431 case SMIAPP_PLL_BUS_TYPE_PARALLEL:
432 pll->pll_op_clk_freq_hz = pll->link_freq * pll->bits_per_pixel
433 / DIV_ROUND_UP(pll->bits_per_pixel,
434 pll->parallel.bus_width);
435 break;
436 default:
437 return -EINVAL;
438 }
6de1b143
SA
439
440 /* Figure out limits for pre-pll divider based on extclk */
c37f9bf9 441 dev_dbg(dev, "min / max pre_pll_clk_div: %u / %u\n",
6de1b143 442 limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
8f7e91a3 443 max_pre_pll_clk_div =
6de1b143
SA
444 min_t(uint16_t, limits->max_pre_pll_clk_div,
445 clk_div_even(pll->ext_clk_freq_hz /
446 limits->min_pll_ip_freq_hz));
8f7e91a3 447 min_pre_pll_clk_div =
6de1b143
SA
448 max_t(uint16_t, limits->min_pre_pll_clk_div,
449 clk_div_even_up(
450 DIV_ROUND_UP(pll->ext_clk_freq_hz,
451 limits->max_pll_ip_freq_hz)));
c37f9bf9 452 dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %u / %u\n",
8f7e91a3 453 min_pre_pll_clk_div, max_pre_pll_clk_div);
6de1b143
SA
454
455 i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
456 mul = div_u64(pll->pll_op_clk_freq_hz, i);
457 div = pll->ext_clk_freq_hz / i;
c37f9bf9 458 dev_dbg(dev, "mul %u / div %u\n", mul, div);
6de1b143 459
8f7e91a3
LP
460 min_pre_pll_clk_div =
461 max_t(uint16_t, min_pre_pll_clk_div,
6de1b143
SA
462 clk_div_even_up(
463 DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
464 limits->max_pll_op_freq_hz)));
c37f9bf9 465 dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %u / %u\n",
8f7e91a3 466 min_pre_pll_clk_div, max_pre_pll_clk_div);
6de1b143 467
8f7e91a3
LP
468 for (pll->pre_pll_clk_div = min_pre_pll_clk_div;
469 pll->pre_pll_clk_div <= max_pre_pll_clk_div;
6de1b143 470 pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) {
974abe44
SA
471 rval = __smiapp_pll_calculate(dev, limits, op_limits, pll,
472 op_pll, mul, div,
6de1b143
SA
473 lane_op_clock_ratio);
474 if (rval)
475 continue;
476
477 print_pll(dev, pll);
478 return 0;
479 }
480
481 dev_info(dev, "unable to compute pre_pll divisor\n");
482 return rval;
483}
cf1c5fae
SA
484EXPORT_SYMBOL_GPL(smiapp_pll_calculate);
485
8c5dff90 486MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
cf1c5fae
SA
487MODULE_DESCRIPTION("Generic SMIA/SMIA++ PLL calculator");
488MODULE_LICENSE("GPL");
This page took 0.245947 seconds and 5 git commands to generate.