aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Drummond <evilrich@rcdrummond.net>2005-05-01 11:59:24 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-01 11:59:24 -0400
commit0fbe9cafff72799700713e6a9d5a4ec7191e8d19 (patch)
treebd0c48641b7281926346465ab7c8f7fae05bbeaf
parent7c2f891cb64b0b9c8d389da97c221ee4288f1307 (diff)
[PATCH] Better PLL frequency matching for tdfxfb driver
Improve the PLL frequency matching in the tdfxfb driver. Instead of requiring 64260 iterations to obtain the closest supported PLL frequency, this code does it with the same degree of accuracy in at most 768 iterations. Signed-off-by: Richard Drummond <evilrich@rcdrummond.net> Cc: <linux-fbdev-devel@lists.sourceforge.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/video/tdfxfb.c43
1 files changed, 31 insertions, 12 deletions
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index c34ba39b6f7e..c8b0be2d8715 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -317,30 +317,49 @@ static inline void do_setpalentry(struct tdfx_par *par, unsigned regno, u32 c)
317 317
318static u32 do_calc_pll(int freq, int* freq_out) 318static u32 do_calc_pll(int freq, int* freq_out)
319{ 319{
320 int m, n, k, best_m, best_n, best_k, f_cur, best_error; 320 int m, n, k, best_m, best_n, best_k, best_error;
321 int fref = 14318; 321 int fref = 14318;
322 322
323 /* this really could be done with more intelligence --
324 255*63*4 = 64260 iterations is silly */
325 best_error = freq; 323 best_error = freq;
326 best_n = best_m = best_k = 0; 324 best_n = best_m = best_k = 0;
327 for (n = 1; n < 256; n++) { 325
328 for (m = 1; m < 64; m++) { 326 for (k = 3; k >= 0; k--) {
329 for (k = 0; k < 4; k++) { 327 for (m = 63; m >= 0; m--) {
330 f_cur = fref*(n + 2)/(m + 2)/(1 << k); 328 /*
331 if (abs(f_cur - freq) < best_error) { 329 * Estimate value of n that produces target frequency
332 best_error = abs(f_cur-freq); 330 * with current m and k
333 best_n = n; 331 */
334 best_m = m; 332 int n_estimated = (freq * (m + 2) * (1 << k) / fref) - 2;
335 best_k = k; 333
334 /* Search neighborhood of estimated n */
335 for (n = max(0, n_estimated - 1);
336 n <= min(255, n_estimated + 1); n++) {
337 /*
338 * Calculate PLL freqency with current m, k and
339 * estimated n
340 */
341 int f = fref * (n + 2) / (m + 2) / (1 << k);
342 int error = abs (f - freq);
343
344 /*
345 * If this is the closest we've come to the
346 * target frequency then remember n, m and k
347 */
348 if (error < best_error) {
349 best_error = error;
350 best_n = n;
351 best_m = m;
352 best_k = k;
336 } 353 }
337 } 354 }
338 } 355 }
339 } 356 }
357
340 n = best_n; 358 n = best_n;
341 m = best_m; 359 m = best_m;
342 k = best_k; 360 k = best_k;
343 *freq_out = fref*(n + 2)/(m + 2)/(1 << k); 361 *freq_out = fref*(n + 2)/(m + 2)/(1 << k);
362
344 return (n << 8) | (m << 2) | k; 363 return (n << 8) | (m << 2) | k;
345} 364}
346 365