diff options
Diffstat (limited to 'drivers/video/tdfxfb.c')
-rw-r--r-- | drivers/video/tdfxfb.c | 88 |
1 files changed, 53 insertions, 35 deletions
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index c34ba39b6f7e..7044226c5d4c 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 | ||
@@ -411,36 +430,35 @@ static void do_write_regs(struct fb_info *info, struct banshee_reg* reg) | |||
411 | 430 | ||
412 | static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) | 431 | static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) |
413 | { | 432 | { |
414 | u32 draminit0 = 0; | 433 | u32 draminit0; |
415 | u32 draminit1 = 0; | 434 | u32 draminit1; |
416 | u32 miscinit1 = 0; | 435 | u32 miscinit1; |
417 | u32 lfbsize = 0; | 436 | |
418 | int sgram_p = 0; | 437 | int num_chips; |
438 | int chip_size; /* in MB */ | ||
439 | u32 lfbsize; | ||
440 | int has_sgram; | ||
419 | 441 | ||
420 | draminit0 = tdfx_inl(par, DRAMINIT0); | 442 | draminit0 = tdfx_inl(par, DRAMINIT0); |
421 | draminit1 = tdfx_inl(par, DRAMINIT1); | 443 | draminit1 = tdfx_inl(par, DRAMINIT1); |
444 | |||
445 | num_chips = (draminit0 & DRAMINIT0_SGRAM_NUM) ? 8 : 4; | ||
422 | 446 | ||
423 | if ((dev_id == PCI_DEVICE_ID_3DFX_BANSHEE) || | 447 | if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) { |
424 | (dev_id == PCI_DEVICE_ID_3DFX_VOODOO3)) { | 448 | /* Banshee/Voodoo3 */ |
425 | sgram_p = (draminit1 & DRAMINIT1_MEM_SDRAM) ? 0 : 1; | 449 | has_sgram = draminit1 & DRAMINIT1_MEM_SDRAM; |
426 | 450 | chip_size = has_sgram ? ((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 2 : 1) | |
427 | lfbsize = sgram_p ? | 451 | : 2; |
428 | (((draminit0 & DRAMINIT0_SGRAM_NUM) ? 2 : 1) * | ||
429 | ((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 8 : 4) * 1024 * 1024) : | ||
430 | 16 * 1024 * 1024; | ||
431 | } else { | 452 | } else { |
432 | /* Voodoo4/5 */ | 453 | /* Voodoo4/5 */ |
433 | u32 chips, psize, banks; | 454 | has_sgram = 0; |
434 | 455 | chip_size = 1 << ((draminit0 & DRAMINIT0_SGRAM_TYPE_MASK) >> DRAMINIT0_SGRAM_TYPE_SHIFT); | |
435 | chips = ((draminit0 & (1 << 26)) == 0) ? 4 : 8; | 456 | } |
436 | psize = 1 << ((draminit0 & 0x38000000) >> 28); | 457 | lfbsize = num_chips * chip_size * 1024 * 1024; |
437 | banks = ((draminit0 & (1 << 30)) == 0) ? 2 : 4; | 458 | |
438 | lfbsize = chips * psize * banks; | 459 | /* disable block writes for SDRAM */ |
439 | lfbsize <<= 20; | ||
440 | } | ||
441 | /* disable block writes for SDRAM (why?) */ | ||
442 | miscinit1 = tdfx_inl(par, MISCINIT1); | 460 | miscinit1 = tdfx_inl(par, MISCINIT1); |
443 | miscinit1 |= sgram_p ? 0 : MISCINIT1_2DBLOCK_DIS; | 461 | miscinit1 |= has_sgram ? 0 : MISCINIT1_2DBLOCK_DIS; |
444 | miscinit1 |= MISCINIT1_CLUT_INV; | 462 | miscinit1 |= MISCINIT1_CLUT_INV; |
445 | 463 | ||
446 | banshee_make_room(par, 1); | 464 | banshee_make_room(par, 1); |