GNU Linux-libre 5.15.137-gnu
[releases.git] / arch / arm / mach-rpc / include / mach / acornfb.h
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
13 acornfb_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
42 acornfb_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
79 acornfb_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))