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