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