diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-14 15:23:43 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-15 15:42:14 -0400 |
commit | cb7a01ac324bf2ee2c666f37ac867e4135f9785a (patch) | |
tree | 7246b915a9334d4bc823c93ba9acab65ef882678 /drivers/media/i2c/smiapp-pll.c | |
parent | f0af8fa4dad0839f844fd0633e1936493f6d685a (diff) |
[media] move i2c files into drivers/media/i2c
Move ancillary I2C drivers into drivers/media/i2c, in order to
better organize them.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/i2c/smiapp-pll.c')
-rw-r--r-- | drivers/media/i2c/smiapp-pll.c | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c new file mode 100644 index 000000000000..a577614bd84f --- /dev/null +++ b/drivers/media/i2c/smiapp-pll.c | |||
@@ -0,0 +1,418 @@ | |||
1 | /* | ||
2 | * drivers/media/i2c/smiapp-pll.c | ||
3 | * | ||
4 | * Generic driver for SMIA/SMIA++ compliant camera modules | ||
5 | * | ||
6 | * Copyright (C) 2011--2012 Nokia Corporation | ||
7 | * Contact: Sakari Ailus <sakari.ailus@maxwell.research.nokia.com> | ||
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. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/gcd.h> | ||
26 | #include <linux/lcm.h> | ||
27 | #include <linux/module.h> | ||
28 | |||
29 | #include "smiapp-pll.h" | ||
30 | |||
31 | /* Return an even number or one. */ | ||
32 | static inline uint32_t clk_div_even(uint32_t a) | ||
33 | { | ||
34 | return max_t(uint32_t, 1, a & ~1); | ||
35 | } | ||
36 | |||
37 | /* Return an even number or one. */ | ||
38 | static inline uint32_t clk_div_even_up(uint32_t a) | ||
39 | { | ||
40 | if (a == 1) | ||
41 | return 1; | ||
42 | return (a + 1) & ~1; | ||
43 | } | ||
44 | |||
45 | static inline uint32_t is_one_or_even(uint32_t a) | ||
46 | { | ||
47 | if (a == 1) | ||
48 | return 1; | ||
49 | if (a & 1) | ||
50 | return 0; | ||
51 | |||
52 | return 1; | ||
53 | } | ||
54 | |||
55 | static int bounds_check(struct device *dev, uint32_t val, | ||
56 | uint32_t min, uint32_t max, char *str) | ||
57 | { | ||
58 | if (val >= min && val <= max) | ||
59 | return 0; | ||
60 | |||
61 | dev_warn(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max); | ||
62 | |||
63 | return -EINVAL; | ||
64 | } | ||
65 | |||
66 | static void print_pll(struct device *dev, struct smiapp_pll *pll) | ||
67 | { | ||
68 | dev_dbg(dev, "pre_pll_clk_div\t%d\n", pll->pre_pll_clk_div); | ||
69 | dev_dbg(dev, "pll_multiplier \t%d\n", pll->pll_multiplier); | ||
70 | if (pll->flags != SMIAPP_PLL_FLAG_NO_OP_CLOCKS) { | ||
71 | dev_dbg(dev, "op_sys_clk_div \t%d\n", pll->op_sys_clk_div); | ||
72 | dev_dbg(dev, "op_pix_clk_div \t%d\n", pll->op_pix_clk_div); | ||
73 | } | ||
74 | dev_dbg(dev, "vt_sys_clk_div \t%d\n", pll->vt_sys_clk_div); | ||
75 | dev_dbg(dev, "vt_pix_clk_div \t%d\n", pll->vt_pix_clk_div); | ||
76 | |||
77 | dev_dbg(dev, "ext_clk_freq_hz \t%d\n", pll->ext_clk_freq_hz); | ||
78 | dev_dbg(dev, "pll_ip_clk_freq_hz \t%d\n", pll->pll_ip_clk_freq_hz); | ||
79 | dev_dbg(dev, "pll_op_clk_freq_hz \t%d\n", pll->pll_op_clk_freq_hz); | ||
80 | if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) { | ||
81 | dev_dbg(dev, "op_sys_clk_freq_hz \t%d\n", | ||
82 | pll->op_sys_clk_freq_hz); | ||
83 | dev_dbg(dev, "op_pix_clk_freq_hz \t%d\n", | ||
84 | pll->op_pix_clk_freq_hz); | ||
85 | } | ||
86 | dev_dbg(dev, "vt_sys_clk_freq_hz \t%d\n", pll->vt_sys_clk_freq_hz); | ||
87 | dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz); | ||
88 | } | ||
89 | |||
90 | int smiapp_pll_calculate(struct device *dev, struct smiapp_pll_limits *limits, | ||
91 | struct smiapp_pll *pll) | ||
92 | { | ||
93 | uint32_t sys_div; | ||
94 | uint32_t best_pix_div = INT_MAX >> 1; | ||
95 | uint32_t vt_op_binning_div; | ||
96 | uint32_t lane_op_clock_ratio; | ||
97 | uint32_t mul, div; | ||
98 | uint32_t more_mul_min, more_mul_max; | ||
99 | uint32_t more_mul_factor; | ||
100 | uint32_t min_vt_div, max_vt_div, vt_div; | ||
101 | uint32_t min_sys_div, max_sys_div; | ||
102 | unsigned int i; | ||
103 | int rval; | ||
104 | |||
105 | if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE) | ||
106 | lane_op_clock_ratio = pll->lanes; | ||
107 | else | ||
108 | lane_op_clock_ratio = 1; | ||
109 | dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio); | ||
110 | |||
111 | dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal, | ||
112 | pll->binning_vertical); | ||
113 | |||
114 | /* CSI transfers 2 bits per clock per lane; thus times 2 */ | ||
115 | pll->pll_op_clk_freq_hz = pll->link_freq * 2 | ||
116 | * (pll->lanes / lane_op_clock_ratio); | ||
117 | |||
118 | /* Figure out limits for pre-pll divider based on extclk */ | ||
119 | dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n", | ||
120 | limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div); | ||
121 | limits->max_pre_pll_clk_div = | ||
122 | min_t(uint16_t, limits->max_pre_pll_clk_div, | ||
123 | clk_div_even(pll->ext_clk_freq_hz / | ||
124 | limits->min_pll_ip_freq_hz)); | ||
125 | limits->min_pre_pll_clk_div = | ||
126 | max_t(uint16_t, limits->min_pre_pll_clk_div, | ||
127 | clk_div_even_up( | ||
128 | DIV_ROUND_UP(pll->ext_clk_freq_hz, | ||
129 | limits->max_pll_ip_freq_hz))); | ||
130 | dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n", | ||
131 | limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div); | ||
132 | |||
133 | i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz); | ||
134 | mul = div_u64(pll->pll_op_clk_freq_hz, i); | ||
135 | div = pll->ext_clk_freq_hz / i; | ||
136 | dev_dbg(dev, "mul %d / div %d\n", mul, div); | ||
137 | |||
138 | limits->min_pre_pll_clk_div = | ||
139 | max_t(uint16_t, limits->min_pre_pll_clk_div, | ||
140 | clk_div_even_up( | ||
141 | DIV_ROUND_UP(mul * pll->ext_clk_freq_hz, | ||
142 | limits->max_pll_op_freq_hz))); | ||
143 | dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n", | ||
144 | limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div); | ||
145 | |||
146 | if (limits->min_pre_pll_clk_div > limits->max_pre_pll_clk_div) { | ||
147 | dev_err(dev, "unable to compute pre_pll divisor\n"); | ||
148 | return -EINVAL; | ||
149 | } | ||
150 | |||
151 | pll->pre_pll_clk_div = limits->min_pre_pll_clk_div; | ||
152 | |||
153 | /* | ||
154 | * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be | ||
155 | * too high. | ||
156 | */ | ||
157 | dev_dbg(dev, "pre_pll_clk_div %d\n", pll->pre_pll_clk_div); | ||
158 | |||
159 | /* Don't go above max pll multiplier. */ | ||
160 | more_mul_max = limits->max_pll_multiplier / mul; | ||
161 | dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %d\n", | ||
162 | more_mul_max); | ||
163 | /* Don't go above max pll op frequency. */ | ||
164 | more_mul_max = | ||
165 | min_t(int, | ||
166 | more_mul_max, | ||
167 | limits->max_pll_op_freq_hz | ||
168 | / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul)); | ||
169 | dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %d\n", | ||
170 | more_mul_max); | ||
171 | /* Don't go above the division capability of op sys clock divider. */ | ||
172 | more_mul_max = min(more_mul_max, | ||
173 | limits->max_op_sys_clk_div * pll->pre_pll_clk_div | ||
174 | / div); | ||
175 | dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %d\n", | ||
176 | more_mul_max); | ||
177 | /* Ensure we won't go above min_pll_multiplier. */ | ||
178 | more_mul_max = min(more_mul_max, | ||
179 | DIV_ROUND_UP(limits->max_pll_multiplier, mul)); | ||
180 | dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %d\n", | ||
181 | more_mul_max); | ||
182 | |||
183 | /* Ensure we won't go below min_pll_op_freq_hz. */ | ||
184 | more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz, | ||
185 | pll->ext_clk_freq_hz / pll->pre_pll_clk_div | ||
186 | * mul); | ||
187 | dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %d\n", | ||
188 | more_mul_min); | ||
189 | /* Ensure we won't go below min_pll_multiplier. */ | ||
190 | more_mul_min = max(more_mul_min, | ||
191 | DIV_ROUND_UP(limits->min_pll_multiplier, mul)); | ||
192 | dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %d\n", | ||
193 | more_mul_min); | ||
194 | |||
195 | if (more_mul_min > more_mul_max) { | ||
196 | dev_warn(dev, | ||
197 | "unable to compute more_mul_min and more_mul_max"); | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | |||
201 | more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div; | ||
202 | dev_dbg(dev, "more_mul_factor: %d\n", more_mul_factor); | ||
203 | more_mul_factor = lcm(more_mul_factor, limits->min_op_sys_clk_div); | ||
204 | dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n", | ||
205 | more_mul_factor); | ||
206 | i = roundup(more_mul_min, more_mul_factor); | ||
207 | if (!is_one_or_even(i)) | ||
208 | i <<= 1; | ||
209 | |||
210 | dev_dbg(dev, "final more_mul: %d\n", i); | ||
211 | if (i > more_mul_max) { | ||
212 | dev_warn(dev, "final more_mul is bad, max %d", more_mul_max); | ||
213 | return -EINVAL; | ||
214 | } | ||
215 | |||
216 | pll->pll_multiplier = mul * i; | ||
217 | pll->op_sys_clk_div = div * i / pll->pre_pll_clk_div; | ||
218 | dev_dbg(dev, "op_sys_clk_div: %d\n", pll->op_sys_clk_div); | ||
219 | |||
220 | pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz | ||
221 | / pll->pre_pll_clk_div; | ||
222 | |||
223 | pll->pll_op_clk_freq_hz = pll->pll_ip_clk_freq_hz | ||
224 | * pll->pll_multiplier; | ||
225 | |||
226 | /* Derive pll_op_clk_freq_hz. */ | ||
227 | pll->op_sys_clk_freq_hz = | ||
228 | pll->pll_op_clk_freq_hz / pll->op_sys_clk_div; | ||
229 | |||
230 | pll->op_pix_clk_div = pll->bits_per_pixel; | ||
231 | dev_dbg(dev, "op_pix_clk_div: %d\n", pll->op_pix_clk_div); | ||
232 | |||
233 | pll->op_pix_clk_freq_hz = | ||
234 | pll->op_sys_clk_freq_hz / pll->op_pix_clk_div; | ||
235 | |||
236 | /* | ||
237 | * Some sensors perform analogue binning and some do this | ||
238 | * digitally. The ones doing this digitally can be roughly be | ||
239 | * found out using this formula. The ones doing this digitally | ||
240 | * should run at higher clock rate, so smaller divisor is used | ||
241 | * on video timing side. | ||
242 | */ | ||
243 | if (limits->min_line_length_pck_bin > limits->min_line_length_pck | ||
244 | / pll->binning_horizontal) | ||
245 | vt_op_binning_div = pll->binning_horizontal; | ||
246 | else | ||
247 | vt_op_binning_div = 1; | ||
248 | dev_dbg(dev, "vt_op_binning_div: %d\n", vt_op_binning_div); | ||
249 | |||
250 | /* | ||
251 | * Profile 2 supports vt_pix_clk_div E [4, 10] | ||
252 | * | ||
253 | * Horizontal binning can be used as a base for difference in | ||
254 | * divisors. One must make sure that horizontal blanking is | ||
255 | * enough to accommodate the CSI-2 sync codes. | ||
256 | * | ||
257 | * Take scaling factor into account as well. | ||
258 | * | ||
259 | * Find absolute limits for the factor of vt divider. | ||
260 | */ | ||
261 | dev_dbg(dev, "scale_m: %d\n", pll->scale_m); | ||
262 | min_vt_div = DIV_ROUND_UP(pll->op_pix_clk_div * pll->op_sys_clk_div | ||
263 | * pll->scale_n, | ||
264 | lane_op_clock_ratio * vt_op_binning_div | ||
265 | * pll->scale_m); | ||
266 | |||
267 | /* Find smallest and biggest allowed vt divisor. */ | ||
268 | dev_dbg(dev, "min_vt_div: %d\n", min_vt_div); | ||
269 | min_vt_div = max(min_vt_div, | ||
270 | DIV_ROUND_UP(pll->pll_op_clk_freq_hz, | ||
271 | limits->max_vt_pix_clk_freq_hz)); | ||
272 | dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %d\n", | ||
273 | min_vt_div); | ||
274 | min_vt_div = max_t(uint32_t, min_vt_div, | ||
275 | limits->min_vt_pix_clk_div | ||
276 | * limits->min_vt_sys_clk_div); | ||
277 | dev_dbg(dev, "min_vt_div: min_vt_clk_div: %d\n", min_vt_div); | ||
278 | |||
279 | max_vt_div = limits->max_vt_sys_clk_div * limits->max_vt_pix_clk_div; | ||
280 | dev_dbg(dev, "max_vt_div: %d\n", max_vt_div); | ||
281 | max_vt_div = min(max_vt_div, | ||
282 | DIV_ROUND_UP(pll->pll_op_clk_freq_hz, | ||
283 | limits->min_vt_pix_clk_freq_hz)); | ||
284 | dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %d\n", | ||
285 | max_vt_div); | ||
286 | |||
287 | /* | ||
288 | * Find limitsits for sys_clk_div. Not all values are possible | ||
289 | * with all values of pix_clk_div. | ||
290 | */ | ||
291 | min_sys_div = limits->min_vt_sys_clk_div; | ||
292 | dev_dbg(dev, "min_sys_div: %d\n", min_sys_div); | ||
293 | min_sys_div = max(min_sys_div, | ||
294 | DIV_ROUND_UP(min_vt_div, | ||
295 | limits->max_vt_pix_clk_div)); | ||
296 | dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %d\n", min_sys_div); | ||
297 | min_sys_div = max(min_sys_div, | ||
298 | pll->pll_op_clk_freq_hz | ||
299 | / limits->max_vt_sys_clk_freq_hz); | ||
300 | dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %d\n", min_sys_div); | ||
301 | min_sys_div = clk_div_even_up(min_sys_div); | ||
302 | dev_dbg(dev, "min_sys_div: one or even: %d\n", min_sys_div); | ||
303 | |||
304 | max_sys_div = limits->max_vt_sys_clk_div; | ||
305 | dev_dbg(dev, "max_sys_div: %d\n", max_sys_div); | ||
306 | max_sys_div = min(max_sys_div, | ||
307 | DIV_ROUND_UP(max_vt_div, | ||
308 | limits->min_vt_pix_clk_div)); | ||
309 | dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %d\n", max_sys_div); | ||
310 | max_sys_div = min(max_sys_div, | ||
311 | DIV_ROUND_UP(pll->pll_op_clk_freq_hz, | ||
312 | limits->min_vt_pix_clk_freq_hz)); | ||
313 | dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %d\n", max_sys_div); | ||
314 | |||
315 | /* | ||
316 | * Find pix_div such that a legal pix_div * sys_div results | ||
317 | * into a value which is not smaller than div, the desired | ||
318 | * divisor. | ||
319 | */ | ||
320 | for (vt_div = min_vt_div; vt_div <= max_vt_div; | ||
321 | vt_div += 2 - (vt_div & 1)) { | ||
322 | for (sys_div = min_sys_div; | ||
323 | sys_div <= max_sys_div; | ||
324 | sys_div += 2 - (sys_div & 1)) { | ||
325 | int pix_div = DIV_ROUND_UP(vt_div, sys_div); | ||
326 | |||
327 | if (pix_div < limits->min_vt_pix_clk_div | ||
328 | || pix_div > limits->max_vt_pix_clk_div) { | ||
329 | dev_dbg(dev, | ||
330 | "pix_div %d too small or too big (%d--%d)\n", | ||
331 | pix_div, | ||
332 | limits->min_vt_pix_clk_div, | ||
333 | limits->max_vt_pix_clk_div); | ||
334 | continue; | ||
335 | } | ||
336 | |||
337 | /* Check if this one is better. */ | ||
338 | if (pix_div * sys_div | ||
339 | <= roundup(min_vt_div, best_pix_div)) | ||
340 | best_pix_div = pix_div; | ||
341 | } | ||
342 | if (best_pix_div < INT_MAX >> 1) | ||
343 | break; | ||
344 | } | ||
345 | |||
346 | pll->vt_sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div); | ||
347 | pll->vt_pix_clk_div = best_pix_div; | ||
348 | |||
349 | pll->vt_sys_clk_freq_hz = | ||
350 | pll->pll_op_clk_freq_hz / pll->vt_sys_clk_div; | ||
351 | pll->vt_pix_clk_freq_hz = | ||
352 | pll->vt_sys_clk_freq_hz / pll->vt_pix_clk_div; | ||
353 | |||
354 | pll->pixel_rate_csi = | ||
355 | pll->op_pix_clk_freq_hz * lane_op_clock_ratio; | ||
356 | |||
357 | print_pll(dev, pll); | ||
358 | |||
359 | rval = bounds_check(dev, pll->pre_pll_clk_div, | ||
360 | limits->min_pre_pll_clk_div, | ||
361 | limits->max_pre_pll_clk_div, "pre_pll_clk_div"); | ||
362 | if (!rval) | ||
363 | rval = bounds_check( | ||
364 | dev, pll->pll_ip_clk_freq_hz, | ||
365 | limits->min_pll_ip_freq_hz, limits->max_pll_ip_freq_hz, | ||
366 | "pll_ip_clk_freq_hz"); | ||
367 | if (!rval) | ||
368 | rval = bounds_check( | ||
369 | dev, pll->pll_multiplier, | ||
370 | limits->min_pll_multiplier, limits->max_pll_multiplier, | ||
371 | "pll_multiplier"); | ||
372 | if (!rval) | ||
373 | rval = bounds_check( | ||
374 | dev, pll->pll_op_clk_freq_hz, | ||
375 | limits->min_pll_op_freq_hz, limits->max_pll_op_freq_hz, | ||
376 | "pll_op_clk_freq_hz"); | ||
377 | if (!rval) | ||
378 | rval = bounds_check( | ||
379 | dev, pll->op_sys_clk_div, | ||
380 | limits->min_op_sys_clk_div, limits->max_op_sys_clk_div, | ||
381 | "op_sys_clk_div"); | ||
382 | if (!rval) | ||
383 | rval = bounds_check( | ||
384 | dev, pll->op_pix_clk_div, | ||
385 | limits->min_op_pix_clk_div, limits->max_op_pix_clk_div, | ||
386 | "op_pix_clk_div"); | ||
387 | if (!rval) | ||
388 | rval = bounds_check( | ||
389 | dev, pll->op_sys_clk_freq_hz, | ||
390 | limits->min_op_sys_clk_freq_hz, | ||
391 | limits->max_op_sys_clk_freq_hz, | ||
392 | "op_sys_clk_freq_hz"); | ||
393 | if (!rval) | ||
394 | rval = bounds_check( | ||
395 | dev, pll->op_pix_clk_freq_hz, | ||
396 | limits->min_op_pix_clk_freq_hz, | ||
397 | limits->max_op_pix_clk_freq_hz, | ||
398 | "op_pix_clk_freq_hz"); | ||
399 | if (!rval) | ||
400 | rval = bounds_check( | ||
401 | dev, pll->vt_sys_clk_freq_hz, | ||
402 | limits->min_vt_sys_clk_freq_hz, | ||
403 | limits->max_vt_sys_clk_freq_hz, | ||
404 | "vt_sys_clk_freq_hz"); | ||
405 | if (!rval) | ||
406 | rval = bounds_check( | ||
407 | dev, pll->vt_pix_clk_freq_hz, | ||
408 | limits->min_vt_pix_clk_freq_hz, | ||
409 | limits->max_vt_pix_clk_freq_hz, | ||
410 | "vt_pix_clk_freq_hz"); | ||
411 | |||
412 | return rval; | ||
413 | } | ||
414 | EXPORT_SYMBOL_GPL(smiapp_pll_calculate); | ||
415 | |||
416 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@maxwell.research.nokia.com>"); | ||
417 | MODULE_DESCRIPTION("Generic SMIA/SMIA++ PLL calculator"); | ||
418 | MODULE_LICENSE("GPL"); | ||