diff options
Diffstat (limited to 'drivers/video/tdfxfb.c')
-rw-r--r-- | drivers/video/tdfxfb.c | 43 |
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 | ||
318 | static u32 do_calc_pll(int freq, int* freq_out) | 318 | static 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 | ||