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