1 /* 2 * arch/arm/mach-rpc/include/mach/acornfb.h 3 * 4 * Copyright (C) 1999 Russell King 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * AcornFB architecture specific code 11 */ 12 13 #define acornfb_bandwidth(var) ((var)->pixclock * 8 / (var)->bits_per_pixel) 14 15 static inline int acornfb_valid_pixrate(struct fb_var_screeninfo * var)16acornfb_valid_pixrate(struct fb_var_screeninfo *var) 17 { 18 u_long limit; 19 20 if (!var->pixclock) 21 return 0; 22 23 /* 24 * Limits below are taken from RISC OS bandwidthlimit file 25 */ 26 if (current_par.using_vram) { 27 if (current_par.vram_half_sam == 2048) 28 limit = 6578; 29 else 30 limit = 13157; 31 } else { 32 limit = 26315; 33 } 34 35 return acornfb_bandwidth(var) >= limit; 36 } 37 38 /* 39 * Try to find the best PLL parameters for the pixel clock. 40 * This algorithm seems to give best predictable results, 41 * and produces the same values as detailed in the VIDC20 42 * data sheet. 43 */ 44 static inline u_int acornfb_vidc20_find_pll(u_int pixclk)45acornfb_vidc20_find_pll(u_int pixclk) 46 { 47 u_int r, best_r = 2, best_v = 2; 48 int best_d = 0x7fffffff; 49 50 for (r = 2; r <= 32; r++) { 51 u_int rr, v, p; 52 int d; 53 54 rr = 41667 * r; 55 56 v = (rr + pixclk / 2) / pixclk; 57 58 if (v > 32 || v < 2) 59 continue; 60 61 p = (rr + v / 2) / v; 62 63 d = pixclk - p; 64 65 if (d < 0) 66 d = -d; 67 68 if (d < best_d) { 69 best_d = d; 70 best_v = v - 1; 71 best_r = r - 1; 72 } 73 74 if (d == 0) 75 break; 76 } 77 78 return best_v << 8 | best_r; 79 } 80 81 static inline void acornfb_vidc20_find_rates(struct vidc_timing * vidc,struct fb_var_screeninfo * var)82acornfb_vidc20_find_rates(struct vidc_timing *vidc, 83 struct fb_var_screeninfo *var) 84 { 85 u_int div; 86 87 /* Select pixel-clock divisor to keep PLL in range */ 88 div = var->pixclock / 9090; /*9921*/ 89 90 /* Limit divisor */ 91 if (div == 0) 92 div = 1; 93 if (div > 8) 94 div = 8; 95 96 /* Encode divisor to VIDC20 setting */ 97 switch (div) { 98 case 1: vidc->control |= VIDC20_CTRL_PIX_CK; break; 99 case 2: vidc->control |= VIDC20_CTRL_PIX_CK2; break; 100 case 3: vidc->control |= VIDC20_CTRL_PIX_CK3; break; 101 case 4: vidc->control |= VIDC20_CTRL_PIX_CK4; break; 102 case 5: vidc->control |= VIDC20_CTRL_PIX_CK5; break; 103 case 6: vidc->control |= VIDC20_CTRL_PIX_CK6; break; 104 case 7: vidc->control |= VIDC20_CTRL_PIX_CK7; break; 105 case 8: vidc->control |= VIDC20_CTRL_PIX_CK8; break; 106 } 107 108 /* 109 * With VRAM, the FIFO can be set to the highest possible setting 110 * because there are no latency considerations for other memory 111 * accesses. However, in 64 bit bus mode the FIFO preload value 112 * must not be set to VIDC20_CTRL_FIFO_28 because this will let 113 * the FIFO overflow. See VIDC20 manual page 33 (6.0 Setting the 114 * FIFO preload value). 115 */ 116 if (current_par.using_vram) { 117 if (current_par.vram_half_sam == 2048) 118 vidc->control |= VIDC20_CTRL_FIFO_24; 119 else 120 vidc->control |= VIDC20_CTRL_FIFO_28; 121 } else { 122 unsigned long bandwidth = acornfb_bandwidth(var); 123 124 /* Encode bandwidth as VIDC20 setting */ 125 if (bandwidth > 33334) /* < 30.0MB/s */ 126 vidc->control |= VIDC20_CTRL_FIFO_16; 127 else if (bandwidth > 26666) /* < 37.5MB/s */ 128 vidc->control |= VIDC20_CTRL_FIFO_20; 129 else if (bandwidth > 22222) /* < 45.0MB/s */ 130 vidc->control |= VIDC20_CTRL_FIFO_24; 131 else /* > 45.0MB/s */ 132 vidc->control |= VIDC20_CTRL_FIFO_28; 133 } 134 135 /* Find the PLL values */ 136 vidc->pll_ctl = acornfb_vidc20_find_pll(var->pixclock / div); 137 } 138 139 #define acornfb_default_control() (VIDC20_CTRL_PIX_VCLK) 140 #define acornfb_default_econtrol() (VIDC20_ECTL_DAC | VIDC20_ECTL_REG(3)) 141