xref: /openbmc/u-boot/drivers/video/bus_vcxk.c (revision f9727161)
1 /*
2  * (C) Copyright 2005-2009
3  * Jens Scharsig @ BuS Elektronik GmbH & Co. KG, <esw@bus-elektronik.de>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <bmp_layout.h>
10 #include <asm/io.h>
11 
12 vu_char  *vcxk_bws      = ((vu_char *) (CONFIG_SYS_VCXK_BASE));
13 vu_short *vcxk_bws_word = ((vu_short *)(CONFIG_SYS_VCXK_BASE));
14 vu_long  *vcxk_bws_long = ((vu_long *) (CONFIG_SYS_VCXK_BASE));
15 
16 #ifdef CONFIG_AT91RM9200
17 	#include <asm/arch/hardware.h>
18 	#include <asm/arch/at91_pio.h>
19 
20 	#ifndef VCBITMASK
21 		#define VCBITMASK(bitno)	(0x0001 << (bitno % 16))
22 	#endif
23 #ifndef CONFIG_AT91_LEGACY
24 at91_pio_t *pio = (at91_pio_t *) AT91_PIO_BASE;
25 #define VCXK_INIT_PIN(PORT, PIN, DDR, I0O1) \
26 	do { \
27 		writel(PIN, &pio->PORT.per); \
28 		writel(PIN, &pio->PORT.DDR); \
29 		writel(PIN, &pio->PORT.mddr); \
30 		if (!I0O1) \
31 			writel(PIN, &pio->PORT.puer); \
32 	} while (0);
33 
34 #define VCXK_SET_PIN(PORT, PIN)	writel(PIN, &pio->PORT.sodr);
35 #define VCXK_CLR_PIN(PORT, PIN)	writel(PIN, &pio->PORT.codr);
36 
37 #define VCXK_ACKNOWLEDGE	\
38 	(!(readl(&pio->CONFIG_SYS_VCXK_ACKNOWLEDGE_PORT.pdsr) & \
39 			CONFIG_SYS_VCXK_ACKNOWLEDGE_PIN))
40 #else
41 	#define VCXK_INIT_PIN(PORT, PIN, DDR, I0O1) \
42 		((AT91PS_PIO) PORT)->PIO_PER = PIN; \
43 		((AT91PS_PIO) PORT)->DDR = PIN; \
44 		((AT91PS_PIO) PORT)->PIO_MDDR = PIN; \
45 		if (!I0O1) ((AT91PS_PIO) PORT)->PIO_PPUER = PIN;
46 
47 	#define VCXK_SET_PIN(PORT, PIN)	((AT91PS_PIO) PORT)->PIO_SODR  = PIN;
48 	#define VCXK_CLR_PIN(PORT, PIN)	((AT91PS_PIO) PORT)->PIO_CODR  = PIN;
49 
50 	#define VCXK_ACKNOWLEDGE	\
51 		(!(((AT91PS_PIO) CONFIG_SYS_VCXK_ACKNOWLEDGE_PORT)->\
52 			PIO_PDSR & CONFIG_SYS_VCXK_ACKNOWLEDGE_PIN))
53 #endif
54 #elif defined(CONFIG_MCF52x2)
55 	#include <asm/m5282.h>
56 	#ifndef VCBITMASK
57 		#define VCBITMASK(bitno) (0x8000 >> (bitno % 16))
58 	#endif
59 
60 	#define VCXK_INIT_PIN(PORT, PIN, DDR, I0O1) \
61 		if (I0O1) DDR |= PIN; else DDR &= ~PIN;
62 
63 	#define VCXK_SET_PIN(PORT, PIN)	PORT |= PIN;
64 	#define VCXK_CLR_PIN(PORT, PIN)	PORT &= ~PIN;
65 
66 	#define VCXK_ACKNOWLEDGE \
67 		(!(CONFIG_SYS_VCXK_ACKNOWLEDGE_PORT &	\
68 			CONFIG_SYS_VCXK_ACKNOWLEDGE_PIN))
69 
70 #else
71 	#error no vcxk support for selected ARCH
72 #endif
73 
74 #define VCXK_DISABLE\
75 	VCXK_SET_PIN(CONFIG_SYS_VCXK_ENABLE_PORT, CONFIG_SYS_VCXK_ENABLE_PIN)
76 #define VCXK_ENABLE\
77 	VCXK_CLR_PIN(CONFIG_SYS_VCXK_ENABLE_PORT, CONFIG_SYS_VCXK_ENABLE_PIN)
78 
79 #ifndef CONFIG_SYS_VCXK_DOUBLEBUFFERED
80 	#define VCXK_BWS(x, data)		vcxk_bws[x] = data;
81 	#define VCXK_BWS_WORD_SET(x, mask) 	vcxk_bws_word[x] |= mask;
82 	#define VCXK_BWS_WORD_CLEAR(x, mask) 	vcxk_bws_word[x] &= ~mask;
83 	#define VCXK_BWS_LONG(x, data)		vcxk_bws_long[x] = data;
84 #else
85 	u_char double_bws[16384];
86 	u_short *double_bws_word;
87 	u_long  *double_bws_long;
88 	#define VCXK_BWS(x,data)	\
89 		double_bws[x] = data; vcxk_bws[x] = data;
90 	#define VCXK_BWS_WORD_SET(x,mask)	\
91 		double_bws_word[x] |= mask;	\
92 		vcxk_bws_word[x] = double_bws_word[x];
93 	#define VCXK_BWS_WORD_CLEAR(x,mask)	\
94 		double_bws_word[x] &= ~mask;	\
95 		vcxk_bws_word[x] = double_bws_word[x];
96 	#define VCXK_BWS_LONG(x,data) \
97 		double_bws_long[x] = data; vcxk_bws_long[x] = data;
98 #endif
99 
100 #define VC4K16_Bright1	vcxk_bws_word[0x20004 / 2]
101 #define VC4K16_Bright2 	vcxk_bws_word[0x20006 / 2]
102 #define VC2K_Bright	vcxk_bws[0x8000]
103 #define VC8K_BrightH	vcxk_bws[0xC000]
104 #define VC8K_BrightL	vcxk_bws[0xC001]
105 
106 vu_char VC4K16;
107 
108 u_long display_width;
109 u_long display_height;
110 u_long display_bwidth;
111 
112 ulong search_vcxk_driver(void);
113 void vcxk_cls(void);
114 void vcxk_setbrightness(unsigned int side, short brightness);
115 int vcxk_request(void);
116 int vcxk_acknowledge_wait(void);
117 void vcxk_clear(void);
118 
119 /*
120  ****f* bus_vcxk/vcxk_init
121  * FUNCTION
122  * initialalize Video Controller
123  * PARAMETERS
124  * width	visible display width in pixel
125  * height	visible display height  in pixel
126  ***
127  */
128 
129 int vcxk_init(unsigned long width, unsigned long height)
130 {
131 #ifdef CONFIG_SYS_VCXK_RESET_PORT
132 	VCXK_INIT_PIN(CONFIG_SYS_VCXK_RESET_PORT,
133 		CONFIG_SYS_VCXK_RESET_PIN, CONFIG_SYS_VCXK_RESET_DDR, 1)
134 	VCXK_SET_PIN(CONFIG_SYS_VCXK_RESET_PORT, CONFIG_SYS_VCXK_RESET_PIN);
135 #endif
136 
137 #ifdef CONFIG_SYS_VCXK_DOUBLEBUFFERED
138 	double_bws_word  = (u_short *)double_bws;
139 	double_bws_long  = (u_long *)double_bws;
140 	debug("%px %px %px\n", double_bws, double_bws_word, double_bws_long);
141 #endif
142 	display_width  = width;
143 	display_height = height;
144 #if (CONFIG_SYS_VCXK_DEFAULT_LINEALIGN == 4)
145 	display_bwidth = ((width + 31) / 8) & ~0x3;
146 #elif (CONFIG_SYS_VCXK_DEFAULT_LINEALIGN == 2)
147 	display_bwidth = ((width + 15) / 8) & ~0x1;
148 #else
149 	#error CONFIG_SYS_VCXK_DEFAULT_LINEALIGN is invalid
150 #endif
151 	debug("linesize ((%ld + 15) / 8 & ~0x1) = %ld\n",
152 		display_width, display_bwidth);
153 
154 #ifdef CONFIG_SYS_VCXK_AUTODETECT
155 	VC4K16 = 0;
156 	vcxk_bws_long[1] = 0x0;
157 	vcxk_bws_long[1] = 0x55AAAA55;
158 	vcxk_bws_long[5] = 0x0;
159 	if (vcxk_bws_long[1] == 0x55AAAA55)
160 		VC4K16 = 1;
161 #else
162 	VC4K16 = 1;
163 	debug("No autodetect: use vc4k\n");
164 #endif
165 
166 	VCXK_INIT_PIN(CONFIG_SYS_VCXK_INVERT_PORT,
167 		CONFIG_SYS_VCXK_INVERT_PIN, CONFIG_SYS_VCXK_INVERT_DDR, 1)
168 	VCXK_SET_PIN(CONFIG_SYS_VCXK_INVERT_PORT, CONFIG_SYS_VCXK_INVERT_PIN)
169 
170 	VCXK_SET_PIN(CONFIG_SYS_VCXK_REQUEST_PORT, CONFIG_SYS_VCXK_REQUEST_PIN);
171 	VCXK_INIT_PIN(CONFIG_SYS_VCXK_REQUEST_PORT,
172 		CONFIG_SYS_VCXK_REQUEST_PIN, CONFIG_SYS_VCXK_REQUEST_DDR, 1)
173 
174 	VCXK_INIT_PIN(CONFIG_SYS_VCXK_ACKNOWLEDGE_PORT,
175 		CONFIG_SYS_VCXK_ACKNOWLEDGE_PIN,
176 		CONFIG_SYS_VCXK_ACKNOWLEDGE_DDR, 0)
177 
178 	VCXK_DISABLE;
179 	VCXK_INIT_PIN(CONFIG_SYS_VCXK_ENABLE_PORT,
180 		CONFIG_SYS_VCXK_ENABLE_PIN, CONFIG_SYS_VCXK_ENABLE_DDR, 1)
181 
182 	vcxk_cls();
183 	vcxk_cls();	/* clear second/hidden page */
184 
185 	vcxk_setbrightness(3, 1000);
186 	VCXK_ENABLE;
187 	return 1;
188 }
189 
190 /*
191  ****f* bus_vcxk/vcxk_setpixel
192  * FUNCTION
193  * set the pixel[x,y] with the given color
194  * PARAMETER
195  * x		pixel colum
196  * y		pixel row
197  * color	<0x40 off/black
198  *			>0x40 on
199  ***
200  */
201 
202 void vcxk_setpixel(int x, int y, unsigned long color)
203 {
204 	vu_short dataptr;
205 
206 	if ((x < display_width) && (y < display_height)) {
207 		dataptr = ((x / 16)) + (y * (display_bwidth >> 1));
208 
209 		color = ((color >> 16) & 0xFF) |
210 			    ((color >> 8) & 0xFF) | (color & 0xFF);
211 
212 		if (color > 0x40) {
213 			VCXK_BWS_WORD_SET(dataptr, VCBITMASK(x));
214 		} else {
215 			VCXK_BWS_WORD_CLEAR(dataptr, VCBITMASK(x));
216 		}
217 	}
218 }
219 
220 /*
221  ****f* bus_vcxk/vcxk_loadimage
222  * FUNCTION
223  * copies a binary image to display memory
224  ***
225  */
226 
227 void vcxk_loadimage(ulong source)
228 {
229 	int cnt;
230 	vcxk_acknowledge_wait();
231 	if (VC4K16) {
232 		for (cnt = 0; cnt < (16384 / 4); cnt++) {
233 			VCXK_BWS_LONG(cnt, (*(ulong *) source));
234 			source = source + 4;
235 		}
236 	} else {
237 		for (cnt = 0; cnt < 16384; cnt++) {
238 			VCXK_BWS_LONG(cnt*2, (*(vu_char *) source));
239 			source++;
240 		}
241 	}
242 	vcxk_request();
243 }
244 
245 /*
246  ****f* bus_vcxk/vcxk_cls
247  * FUNCTION
248  * clear the display
249  ***
250  */
251 
252 void vcxk_cls(void)
253 {
254 	vcxk_acknowledge_wait();
255 	vcxk_clear();
256 	vcxk_request();
257 }
258 
259 /*
260  ****f* bus_vcxk/vcxk_clear(void)
261  * FUNCTION
262  * clear the display memory
263  ***
264  */
265 
266 void vcxk_clear(void)
267 {
268 	int cnt;
269 
270 	for (cnt = 0; cnt < (16384 / 4); cnt++) {
271 		VCXK_BWS_LONG(cnt, 0)
272 	}
273 }
274 
275 /*
276  ****f* bus_vcxk/vcxk_setbrightness
277  * FUNCTION
278  * set the display brightness
279  * PARAMETER
280  * side	1	set front side brightness
281  * 		2	set back  side brightness
282  *		3	set brightness for both sides
283  * brightness 0..1000
284  ***
285  */
286 
287 void vcxk_setbrightness(unsigned int side, short brightness)
288 {
289 	if (VC4K16) {
290 		if ((side == 0) || (side & 0x1))
291 			VC4K16_Bright1 = brightness + 23;
292 		if ((side == 0) || (side & 0x2))
293 			VC4K16_Bright2 = brightness + 23;
294 	} else 	{
295 		VC2K_Bright = (brightness >> 4) + 2;
296 		VC8K_BrightH = (brightness + 23) >> 8;
297 		VC8K_BrightL = (brightness + 23) & 0xFF;
298 	}
299 }
300 
301 /*
302  ****f* bus_vcxk/vcxk_request
303  * FUNCTION
304  * requests viewing of display memory
305  ***
306  */
307 
308 int vcxk_request(void)
309 {
310 	VCXK_CLR_PIN(CONFIG_SYS_VCXK_REQUEST_PORT,
311 		CONFIG_SYS_VCXK_REQUEST_PIN)
312 	VCXK_SET_PIN(CONFIG_SYS_VCXK_REQUEST_PORT,
313 		CONFIG_SYS_VCXK_REQUEST_PIN);
314 	return 1;
315 }
316 
317 /*
318  ****f* bus_vcxk/vcxk_acknowledge_wait
319  * FUNCTION
320  * wait for acknowledge viewing requests
321  ***
322  */
323 
324 int vcxk_acknowledge_wait(void)
325 {
326 	while (VCXK_ACKNOWLEDGE)
327 		;
328 	return 1;
329 }
330 
331 /*
332  ****f* bus_vcxk/vcxk_draw_mono
333  * FUNCTION
334  * copies a monochrom bitmap (BMP-Format) from given memory
335  * PARAMETER
336  * dataptr	pointer to bitmap
337  * x		output bitmap @ columne
338  * y		output bitmap @ row
339  ***
340  */
341 
342 void vcxk_draw_mono(unsigned char *dataptr, unsigned long linewidth,
343 	unsigned long  cp_width, unsigned long cp_height)
344 {
345 	unsigned char *lineptr;
346 	unsigned long xcnt, ycnt;
347 
348 	for (ycnt = cp_height; ycnt > 0; ycnt--) {
349 		lineptr	= dataptr;
350 		for (xcnt = 0; xcnt < cp_width; xcnt++) {
351 			if ((*lineptr << (xcnt % 8)) & 0x80)
352 				vcxk_setpixel(xcnt, ycnt - 1, 0xFFFFFF);
353 			else
354 				vcxk_setpixel(xcnt, ycnt-1, 0);
355 
356 			if ((xcnt % 8) == 7)
357 				lineptr++;
358 		} /* endfor xcnt */
359 		dataptr = dataptr + linewidth;
360 	} /* endfor ycnt */
361 }
362 
363 /*
364  ****f* bus_vcxk/vcxk_display_bitmap
365  * FUNCTION
366  * copies a bitmap (BMP-Format) to the given position
367  * PARAMETER
368  * addr		pointer to bitmap
369  * x		output bitmap @ columne
370  * y		output bitmap @ row
371  ***
372  */
373 
374 int vcxk_display_bitmap(ulong addr, int x, int y)
375 {
376 	bmp_image_t *bmp;
377 	unsigned long width;
378 	unsigned long height;
379 	unsigned long bpp;
380 
381 	unsigned long lw;
382 
383 	unsigned long c_width;
384 	unsigned long c_height;
385 	unsigned char *dataptr;
386 
387 	bmp = (bmp_image_t *) addr;
388 	if ((bmp->header.signature[0] == 'B') &&
389 	    (bmp->header.signature[1] == 'M')) {
390 		width        = le32_to_cpu(bmp->header.width);
391 		height       = le32_to_cpu(bmp->header.height);
392 		bpp          = le16_to_cpu(bmp->header.bit_count);
393 
394 		dataptr = (unsigned char *) bmp +
395 				le32_to_cpu(bmp->header.data_offset);
396 
397 		if (display_width < (width + x))
398 			c_width = display_width - x;
399 		else
400 			c_width = width;
401 		if (display_height < (height + y))
402 			c_height = display_height - y;
403 		else
404 			c_height = height;
405 
406 		lw = (((width + 7) / 8) + 3) & ~0x3;
407 
408 		if (c_height < height)
409 			dataptr = dataptr + lw * (height - c_height);
410 		switch (bpp) {
411 		case 1:
412 			vcxk_draw_mono(dataptr, lw, c_width, c_height);
413 			break;
414 		default:
415 			printf("Error: %ld bit per pixel "
416 				"not supported by VCxK\n", bpp);
417 			return 0;
418 		}
419 	} else	{
420 		printf("Error: no valid bmp at %lx\n", (ulong) bmp);
421 		return 0;
422 	}
423 	return 1;
424 }
425 
426 /*
427  ****f* bus_vcxk/video_display_bitmap
428  ***
429  */
430 
431 int video_display_bitmap(ulong addr, int x, int y)
432 {
433 	vcxk_acknowledge_wait();
434 	if (vcxk_display_bitmap(addr, x, y)) {
435 		vcxk_request();
436 		return 0;
437 	}
438 	return 1;
439 }
440 
441 /* EOF */
442