xref: /linux/arch/arm/mach-rpc/include/mach/acornfb.h (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
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 King acornfb_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 King acornfb_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 King acornfb_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