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