xref: /rk3399_rockchip-uboot/drivers/video/cfb_console.c (revision 20c450ef61ef2eb1c96f9b59ba0eb8d849bba058)
1 /*
2  * (C) Copyright 2002 ELTEC Elektronik AG
3  * Frank Gottschling <fgottschling@eltec.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 /*
25  * cfb_console.c
26  *
27  * Color Framebuffer Console driver for 8/15/16/24/32 bits per pixel.
28  *
29  * At the moment only the 8x16 font is tested and the font fore- and
30  * background color is limited to black/white/gray colors. The Linux
31  * logo can be placed in the upper left corner and additional board
32  * information strings (that normaly goes to serial port) can be drawed.
33  *
34  * The console driver can use the standard PC keyboard interface (i8042)
35  * for character input. Character output goes to a memory mapped video
36  * framebuffer with little or big-endian organisation.
37  * With environment setting 'console=serial' the console i/o can be
38  * forced to serial port.
39 
40  The driver uses graphic specific defines/parameters/functions:
41 
42  (for SMI LynxE graphic chip)
43 
44  CONFIG_VIDEO_SMI_LYNXEM - use graphic driver for SMI 710,712,810
45  VIDEO_FB_LITTLE_ENDIAN	 - framebuffer organisation default: big endian
46  VIDEO_HW_RECTFILL	 - graphic driver supports hardware rectangle fill
47  VIDEO_HW_BITBLT	 - graphic driver supports hardware bit blt
48 
49  Console Parameters are set by graphic drivers global struct:
50 
51  VIDEO_VISIBLE_COLS	     - x resolution
52  VIDEO_VISIBLE_ROWS	     - y resolution
53  VIDEO_PIXEL_SIZE	     - storage size in byte per pixel
54  VIDEO_DATA_FORMAT	     - graphical data format GDF
55  VIDEO_FB_ADRS		     - start of video memory
56 
57  CONFIG_I8042_KBD	     - AT Keyboard driver for i8042
58  VIDEO_KBD_INIT_FCT	     - init function for keyboard
59  VIDEO_TSTC_FCT		     - keyboard_tstc function
60  VIDEO_GETC_FCT		     - keyboard_getc function
61 
62  CONFIG_CONSOLE_CURSOR	     - on/off drawing cursor is done with delay
63 			       loop in VIDEO_TSTC_FCT (i8042)
64  CFG_CONSOLE_BLINK_COUNT     - value for delay loop - blink rate
65  CONFIG_CONSOLE_TIME	     - display time/date in upper right corner,
66 			       needs CONFIG_CMD_DATE and CONFIG_CONSOLE_CURSOR
67  CONFIG_VIDEO_LOGO	     - display Linux Logo in upper left corner
68  CONFIG_VIDEO_BMP_LOGO	     - use bmp_logo instead of linux_logo
69  CONFIG_CONSOLE_EXTRA_INFO   - display additional board information strings
70 			       that normaly goes to serial port. This define
71 			       requires a board specific function:
72 			       video_drawstring (VIDEO_INFO_X,
73 						 VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT,
74 						 info);
75 			       that fills a info buffer at i=row.
76 			       s.a: board/eltec/bab7xx.
77 CONFIG_VGA_AS_SINGLE_DEVICE  - If set the framebuffer device will be initialised
78 			       as an output only device. The Keyboard driver
79 			       will not be set-up. This may be used, if you
80 			       have none or more than one Keyboard devices
81 			       (USB Keyboard, AT Keyboard).
82 
83 CONFIG_VIDEO_SW_CURSOR:	     - Draws a cursor after the last character. No
84 			       blinking is provided. Uses the macros CURSOR_SET
85 			       and CURSOR_OFF.
86 CONFIG_VIDEO_HW_CURSOR:	     - Uses the hardware cursor capability of the
87 			       graphic chip. Uses the macro CURSOR_SET.
88 			       ATTENTION: If booting an OS, the display driver
89 			       must disable the hardware register of the graphic
90 			       chip. Otherwise a blinking field is displayed
91 */
92 
93 #include <common.h>
94 
95 #ifdef CONFIG_CFB_CONSOLE
96 
97 #include <malloc.h>
98 
99 /*****************************************************************************/
100 /* Console device defines with SMI graphic				     */
101 /* Any other graphic must change this section				     */
102 /*****************************************************************************/
103 
104 #ifdef	CONFIG_VIDEO_SMI_LYNXEM
105 
106 #define VIDEO_FB_LITTLE_ENDIAN
107 #define VIDEO_HW_RECTFILL
108 #define VIDEO_HW_BITBLT
109 #endif
110 
111 /*****************************************************************************/
112 /* Defines for the CT69000 driver					     */
113 /*****************************************************************************/
114 #ifdef	CONFIG_VIDEO_CT69000
115 
116 #define VIDEO_FB_LITTLE_ENDIAN
117 #define VIDEO_HW_RECTFILL
118 #define VIDEO_HW_BITBLT
119 #endif
120 
121 /*****************************************************************************/
122 /* Defines for the SED13806 driver					     */
123 /*****************************************************************************/
124 #ifdef CONFIG_VIDEO_SED13806
125 
126 #ifndef CONFIG_TOTAL5200
127 #define VIDEO_FB_LITTLE_ENDIAN
128 #endif
129 #define VIDEO_HW_RECTFILL
130 #define VIDEO_HW_BITBLT
131 #endif
132 
133 /*****************************************************************************/
134 /* Defines for the SED13806 driver					     */
135 /*****************************************************************************/
136 #ifdef CONFIG_VIDEO_SM501
137 
138 #ifdef CONFIG_HH405
139 #define VIDEO_FB_LITTLE_ENDIAN
140 #endif
141 #endif
142 
143 /*****************************************************************************/
144 /* Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc	     */
145 /*****************************************************************************/
146 #include <video_fb.h>
147 
148 /*****************************************************************************/
149 /* some Macros								     */
150 /*****************************************************************************/
151 #define VIDEO_VISIBLE_COLS	(pGD->winSizeX)
152 #define VIDEO_VISIBLE_ROWS	(pGD->winSizeY)
153 #define VIDEO_PIXEL_SIZE	(pGD->gdfBytesPP)
154 #define VIDEO_DATA_FORMAT	(pGD->gdfIndex)
155 #define VIDEO_FB_ADRS		(pGD->frameAdrs)
156 
157 /*****************************************************************************/
158 /* Console device defines with i8042 keyboard controller		     */
159 /* Any other keyboard controller must change this section		     */
160 /*****************************************************************************/
161 
162 #ifdef	CONFIG_I8042_KBD
163 #include <i8042.h>
164 
165 #define VIDEO_KBD_INIT_FCT	i8042_kbd_init()
166 #define VIDEO_TSTC_FCT		i8042_tstc
167 #define VIDEO_GETC_FCT		i8042_getc
168 #endif
169 
170 /*****************************************************************************/
171 /* Console device							     */
172 /*****************************************************************************/
173 
174 #include <version.h>
175 #include <linux/types.h>
176 #include <devices.h>
177 #include <video_font.h>
178 
179 #if defined(CONFIG_CMD_DATE)
180 #include <rtc.h>
181 #endif
182 
183 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
184 #include <watchdog.h>
185 #include <bmp_layout.h>
186 #endif
187 
188 /*****************************************************************************/
189 /* Cursor definition:							     */
190 /* CONFIG_CONSOLE_CURSOR:  Uses a timer function (see drivers/input/i8042.c) */
191 /*                         to let the cursor blink. Uses the macros	     */
192 /*                         CURSOR_OFF and CURSOR_ON.			     */
193 /* CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No	     */
194 /*			   blinking is provided. Uses the macros CURSOR_SET  */
195 /*			   and CURSOR_OFF.				     */
196 /* CONFIG_VIDEO_HW_CURSOR: Uses the hardware cursor capability of the	     */
197 /*			   graphic chip. Uses the macro CURSOR_SET.	     */
198 /*			   ATTENTION: If booting an OS, the display driver   */
199 /*			   must disable the hardware register of the graphic */
200 /*			   chip. Otherwise a blinking field is displayed     */
201 /*****************************************************************************/
202 #if !defined(CONFIG_CONSOLE_CURSOR) && \
203     !defined(CONFIG_VIDEO_SW_CURSOR) && \
204     !defined(CONFIG_VIDEO_HW_CURSOR)
205 /* no Cursor defined */
206 #define CURSOR_ON
207 #define CURSOR_OFF
208 #define CURSOR_SET
209 #endif
210 
211 #ifdef	CONFIG_CONSOLE_CURSOR
212 #ifdef	CURSOR_ON
213 #error	only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
214 #endif
215 void	console_cursor (int state);
216 #define CURSOR_ON  console_cursor(1);
217 #define CURSOR_OFF console_cursor(0);
218 #define CURSOR_SET
219 #ifndef CONFIG_I8042_KBD
220 #warning Cursor drawing on/off needs timer function s.a. drivers/input/i8042.c
221 #endif
222 #else
223 #ifdef	CONFIG_CONSOLE_TIME
224 #error	CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
225 #endif
226 #endif /* CONFIG_CONSOLE_CURSOR */
227 
228 #ifdef	CONFIG_VIDEO_SW_CURSOR
229 #ifdef	CURSOR_ON
230 #error	only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
231 #endif
232 #define CURSOR_ON
233 #define CURSOR_OFF video_putchar(console_col * VIDEO_FONT_WIDTH,\
234 				 console_row * VIDEO_FONT_HEIGHT, ' ');
235 #define CURSOR_SET video_set_cursor();
236 #endif /* CONFIG_VIDEO_SW_CURSOR */
237 
238 
239 #ifdef CONFIG_VIDEO_HW_CURSOR
240 #ifdef	CURSOR_ON
241 #error	only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined
242 #endif
243 #define CURSOR_ON
244 #define CURSOR_OFF
245 #define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \
246 		  (console_row * VIDEO_FONT_HEIGHT) + VIDEO_LOGO_HEIGHT);
247 #endif	/* CONFIG_VIDEO_HW_CURSOR */
248 
249 #ifdef	CONFIG_VIDEO_LOGO
250 #ifdef	CONFIG_VIDEO_BMP_LOGO
251 #include <bmp_logo.h>
252 #define VIDEO_LOGO_WIDTH	BMP_LOGO_WIDTH
253 #define VIDEO_LOGO_HEIGHT	BMP_LOGO_HEIGHT
254 #define VIDEO_LOGO_LUT_OFFSET	BMP_LOGO_OFFSET
255 #define VIDEO_LOGO_COLORS	BMP_LOGO_COLORS
256 
257 #else	/* CONFIG_VIDEO_BMP_LOGO */
258 #define LINUX_LOGO_WIDTH	80
259 #define LINUX_LOGO_HEIGHT	80
260 #define LINUX_LOGO_COLORS	214
261 #define LINUX_LOGO_LUT_OFFSET	0x20
262 #define __initdata
263 #include <linux_logo.h>
264 #define VIDEO_LOGO_WIDTH	LINUX_LOGO_WIDTH
265 #define VIDEO_LOGO_HEIGHT	LINUX_LOGO_HEIGHT
266 #define VIDEO_LOGO_LUT_OFFSET	LINUX_LOGO_LUT_OFFSET
267 #define VIDEO_LOGO_COLORS	LINUX_LOGO_COLORS
268 #endif	/* CONFIG_VIDEO_BMP_LOGO */
269 #define VIDEO_INFO_X		(VIDEO_LOGO_WIDTH)
270 #define VIDEO_INFO_Y		(VIDEO_FONT_HEIGHT/2)
271 #else	/* CONFIG_VIDEO_LOGO */
272 #define VIDEO_LOGO_WIDTH	0
273 #define VIDEO_LOGO_HEIGHT	0
274 #endif	/* CONFIG_VIDEO_LOGO */
275 
276 #define VIDEO_COLS		VIDEO_VISIBLE_COLS
277 #define VIDEO_ROWS		VIDEO_VISIBLE_ROWS
278 #define VIDEO_SIZE		(VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE)
279 #define VIDEO_PIX_BLOCKS	(VIDEO_SIZE >> 2)
280 #define VIDEO_LINE_LEN		(VIDEO_COLS*VIDEO_PIXEL_SIZE)
281 #define VIDEO_BURST_LEN		(VIDEO_COLS/8)
282 
283 #ifdef	CONFIG_VIDEO_LOGO
284 #define CONSOLE_ROWS		((VIDEO_ROWS - VIDEO_LOGO_HEIGHT) / VIDEO_FONT_HEIGHT)
285 #else
286 #define CONSOLE_ROWS		(VIDEO_ROWS / VIDEO_FONT_HEIGHT)
287 #endif
288 
289 #define CONSOLE_COLS		(VIDEO_COLS / VIDEO_FONT_WIDTH)
290 #define CONSOLE_ROW_SIZE	(VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
291 #define CONSOLE_ROW_FIRST	(video_console_address)
292 #define CONSOLE_ROW_SECOND	(video_console_address + CONSOLE_ROW_SIZE)
293 #define CONSOLE_ROW_LAST	(video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
294 #define CONSOLE_SIZE		(CONSOLE_ROW_SIZE * CONSOLE_ROWS)
295 #define CONSOLE_SCROLL_SIZE	(CONSOLE_SIZE - CONSOLE_ROW_SIZE)
296 
297 /* Macros */
298 #ifdef	VIDEO_FB_LITTLE_ENDIAN
299 #define SWAP16(x)	 ((((x) & 0x00ff) << 8) | ( (x) >> 8))
300 #define SWAP32(x)	 ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\
301 			  (((x) & 0x00ff0000) >>  8) | (((x) & 0xff000000) >> 24) )
302 #define SHORTSWAP32(x)	 ((((x) & 0x000000ff) <<  8) | (((x) & 0x0000ff00) >> 8)|\
303 			  (((x) & 0x00ff0000) <<  8) | (((x) & 0xff000000) >> 8) )
304 #else
305 #define SWAP16(x)	 (x)
306 #define SWAP32(x)	 (x)
307 #define SHORTSWAP32(x)	 (x)
308 #endif
309 
310 #if defined(DEBUG) || defined(DEBUG_CFB_CONSOLE)
311 #define PRINTD(x)	  printf(x)
312 #else
313 #define PRINTD(x)
314 #endif
315 
316 
317 #ifdef CONFIG_CONSOLE_EXTRA_INFO
318 extern void video_get_info_str (    /* setup a board string: type, speed, etc. */
319     int line_number,	    /* location to place info string beside logo */
320     char *info		    /* buffer for info string */
321     );
322 
323 #endif
324 
325 /* Locals */
326 static GraphicDevice *pGD;	/* Pointer to Graphic array */
327 
328 static void *video_fb_address;		/* frame buffer address */
329 static void *video_console_address;	/* console buffer start address */
330 
331 static int console_col = 0; /* cursor col */
332 static int console_row = 0; /* cursor row */
333 
334 static u32 eorx, fgx, bgx;  /* color pats */
335 
336 static const int video_font_draw_table8[] = {
337 	    0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
338 	    0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
339 	    0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
340 	    0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff };
341 
342 static const int video_font_draw_table15[] = {
343 	    0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff };
344 
345 static const int video_font_draw_table16[] = {
346 	    0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff };
347 
348 static const int video_font_draw_table24[16][3] = {
349 	    { 0x00000000, 0x00000000, 0x00000000 },
350 	    { 0x00000000, 0x00000000, 0x00ffffff },
351 	    { 0x00000000, 0x0000ffff, 0xff000000 },
352 	    { 0x00000000, 0x0000ffff, 0xffffffff },
353 	    { 0x000000ff, 0xffff0000, 0x00000000 },
354 	    { 0x000000ff, 0xffff0000, 0x00ffffff },
355 	    { 0x000000ff, 0xffffffff, 0xff000000 },
356 	    { 0x000000ff, 0xffffffff, 0xffffffff },
357 	    { 0xffffff00, 0x00000000, 0x00000000 },
358 	    { 0xffffff00, 0x00000000, 0x00ffffff },
359 	    { 0xffffff00, 0x0000ffff, 0xff000000 },
360 	    { 0xffffff00, 0x0000ffff, 0xffffffff },
361 	    { 0xffffffff, 0xffff0000, 0x00000000 },
362 	    { 0xffffffff, 0xffff0000, 0x00ffffff },
363 	    { 0xffffffff, 0xffffffff, 0xff000000 },
364 	    { 0xffffffff, 0xffffffff, 0xffffffff } };
365 
366 static const int video_font_draw_table32[16][4] = {
367 	    { 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
368 	    { 0x00000000, 0x00000000, 0x00000000, 0x00ffffff },
369 	    { 0x00000000, 0x00000000, 0x00ffffff, 0x00000000 },
370 	    { 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff },
371 	    { 0x00000000, 0x00ffffff, 0x00000000, 0x00000000 },
372 	    { 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff },
373 	    { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000 },
374 	    { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff },
375 	    { 0x00ffffff, 0x00000000, 0x00000000, 0x00000000 },
376 	    { 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff },
377 	    { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000 },
378 	    { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff },
379 	    { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000 },
380 	    { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff },
381 	    { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000 },
382 	    { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } };
383 
384 
385 int gunzip(void *, int, unsigned char *, unsigned long *);
386 
387 /******************************************************************************/
388 
389 static void video_drawchars (int xx, int yy, unsigned char *s, int count)
390 {
391 	u8 *cdat, *dest, *dest0;
392 	int rows, offset, c;
393 
394 	offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
395 	dest0 = video_fb_address + offset;
396 
397 	switch (VIDEO_DATA_FORMAT) {
398 	case GDF__8BIT_INDEX:
399 	case GDF__8BIT_332RGB:
400 		while (count--) {
401 			c = *s;
402 			cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
403 			for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
404 			     rows--;
405 			     dest += VIDEO_LINE_LEN) {
406 				u8 bits = *cdat++;
407 
408 				((u32 *) dest)[0] = (video_font_draw_table8[bits >> 4] & eorx) ^ bgx;
409 				((u32 *) dest)[1] = (video_font_draw_table8[bits & 15] & eorx) ^ bgx;
410 			}
411 			dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
412 			s++;
413 		}
414 		break;
415 
416 	case GDF_15BIT_555RGB:
417 		while (count--) {
418 			c = *s;
419 			cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
420 			for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
421 			     rows--;
422 			     dest += VIDEO_LINE_LEN) {
423 				u8 bits = *cdat++;
424 
425 				((u32 *) dest)[0] = SHORTSWAP32 ((video_font_draw_table15 [bits >> 6] & eorx) ^ bgx);
426 				((u32 *) dest)[1] = SHORTSWAP32 ((video_font_draw_table15 [bits >> 4 & 3] & eorx) ^ bgx);
427 				((u32 *) dest)[2] = SHORTSWAP32 ((video_font_draw_table15 [bits >> 2 & 3] & eorx) ^ bgx);
428 				((u32 *) dest)[3] = SHORTSWAP32 ((video_font_draw_table15 [bits & 3] & eorx) ^ bgx);
429 			}
430 			dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
431 			s++;
432 		}
433 		break;
434 
435 	case GDF_16BIT_565RGB:
436 		while (count--) {
437 			c = *s;
438 			cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
439 			for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
440 			     rows--;
441 			     dest += VIDEO_LINE_LEN) {
442 				u8 bits = *cdat++;
443 
444 				((u32 *) dest)[0] = SHORTSWAP32 ((video_font_draw_table16 [bits >> 6] & eorx) ^ bgx);
445 				((u32 *) dest)[1] = SHORTSWAP32 ((video_font_draw_table16 [bits >> 4 & 3] & eorx) ^ bgx);
446 				((u32 *) dest)[2] = SHORTSWAP32 ((video_font_draw_table16 [bits >> 2 & 3] & eorx) ^ bgx);
447 				((u32 *) dest)[3] = SHORTSWAP32 ((video_font_draw_table16 [bits & 3] & eorx) ^ bgx);
448 			}
449 			dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
450 			s++;
451 		}
452 		break;
453 
454 	case GDF_32BIT_X888RGB:
455 		while (count--) {
456 			c = *s;
457 			cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
458 			for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
459 			     rows--;
460 			     dest += VIDEO_LINE_LEN) {
461 				u8 bits = *cdat++;
462 
463 				((u32 *) dest)[0] = SWAP32 ((video_font_draw_table32 [bits >> 4][0] & eorx) ^ bgx);
464 				((u32 *) dest)[1] = SWAP32 ((video_font_draw_table32 [bits >> 4][1] & eorx) ^ bgx);
465 				((u32 *) dest)[2] = SWAP32 ((video_font_draw_table32 [bits >> 4][2] & eorx) ^ bgx);
466 				((u32 *) dest)[3] = SWAP32 ((video_font_draw_table32 [bits >> 4][3] & eorx) ^ bgx);
467 				((u32 *) dest)[4] = SWAP32 ((video_font_draw_table32 [bits & 15][0] & eorx) ^ bgx);
468 				((u32 *) dest)[5] = SWAP32 ((video_font_draw_table32 [bits & 15][1] & eorx) ^ bgx);
469 				((u32 *) dest)[6] = SWAP32 ((video_font_draw_table32 [bits & 15][2] & eorx) ^ bgx);
470 				((u32 *) dest)[7] = SWAP32 ((video_font_draw_table32 [bits & 15][3] & eorx) ^ bgx);
471 			}
472 			dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
473 			s++;
474 		}
475 		break;
476 
477 	case GDF_24BIT_888RGB:
478 		while (count--) {
479 			c = *s;
480 			cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
481 			for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
482 			     rows--;
483 			     dest += VIDEO_LINE_LEN) {
484 				u8 bits = *cdat++;
485 
486 				((u32 *) dest)[0] = (video_font_draw_table24[bits >> 4][0] & eorx) ^ bgx;
487 				((u32 *) dest)[1] = (video_font_draw_table24[bits >> 4][1] & eorx) ^ bgx;
488 				((u32 *) dest)[2] = (video_font_draw_table24[bits >> 4][2] & eorx) ^ bgx;
489 				((u32 *) dest)[3] = (video_font_draw_table24[bits & 15][0] & eorx) ^ bgx;
490 				((u32 *) dest)[4] = (video_font_draw_table24[bits & 15][1] & eorx) ^ bgx;
491 				((u32 *) dest)[5] = (video_font_draw_table24[bits & 15][2] & eorx) ^ bgx;
492 			}
493 			dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
494 			s++;
495 		}
496 		break;
497 	}
498 }
499 
500 /*****************************************************************************/
501 
502 static inline void video_drawstring (int xx, int yy, unsigned char *s)
503 {
504 	video_drawchars (xx, yy, s, strlen ((char *)s));
505 }
506 
507 /*****************************************************************************/
508 
509 static void video_putchar (int xx, int yy, unsigned char c)
510 {
511 	video_drawchars (xx, yy + VIDEO_LOGO_HEIGHT, &c, 1);
512 }
513 
514 /*****************************************************************************/
515 #if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
516 static void video_set_cursor (void)
517 {
518 	/* swap drawing colors */
519 	eorx = fgx;
520 	fgx = bgx;
521 	bgx = eorx;
522 	eorx = fgx ^ bgx;
523 	/* draw cursor */
524 	video_putchar (console_col * VIDEO_FONT_WIDTH,
525 		       console_row * VIDEO_FONT_HEIGHT,
526 		       ' ');
527 	/* restore drawing colors */
528 	eorx = fgx;
529 	fgx = bgx;
530 	bgx = eorx;
531 	eorx = fgx ^ bgx;
532 }
533 #endif
534 /*****************************************************************************/
535 #ifdef CONFIG_CONSOLE_CURSOR
536 void console_cursor (int state)
537 {
538 	static int last_state = 0;
539 
540 #ifdef CONFIG_CONSOLE_TIME
541 	struct rtc_time tm;
542 	char info[16];
543 
544 	/* time update only if cursor is on (faster scroll) */
545 	if (state) {
546 		rtc_get (&tm);
547 
548 		sprintf (info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min,
549 			 tm.tm_sec);
550 		video_drawstring (VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
551 				  VIDEO_INFO_Y, (uchar *)info);
552 
553 		sprintf (info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon,
554 			 tm.tm_year);
555 		video_drawstring (VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
556 				  VIDEO_INFO_Y + 1 * VIDEO_FONT_HEIGHT, (uchar *)info);
557 	}
558 #endif
559 
560 	if (state && (last_state != state)) {
561 		video_set_cursor ();
562 	}
563 
564 	if (!state && (last_state != state)) {
565 		/* clear cursor */
566 		video_putchar (console_col * VIDEO_FONT_WIDTH,
567 			       console_row * VIDEO_FONT_HEIGHT,
568 			       ' ');
569 	}
570 
571 	last_state = state;
572 }
573 #endif
574 
575 /*****************************************************************************/
576 
577 #ifndef VIDEO_HW_RECTFILL
578 static void memsetl (int *p, int c, int v)
579 {
580 	while (c--)
581 		*(p++) = v;
582 }
583 #endif
584 
585 /*****************************************************************************/
586 
587 #ifndef VIDEO_HW_BITBLT
588 static void memcpyl (int *d, int *s, int c)
589 {
590 	while (c--)
591 		*(d++) = *(s++);
592 }
593 #endif
594 
595 /*****************************************************************************/
596 
597 static void console_scrollup (void)
598 {
599 	/* copy up rows ignoring the first one */
600 
601 #ifdef VIDEO_HW_BITBLT
602 	video_hw_bitblt (VIDEO_PIXEL_SIZE,	/* bytes per pixel */
603 			 0,	/* source pos x */
604 			 VIDEO_LOGO_HEIGHT + VIDEO_FONT_HEIGHT, /* source pos y */
605 			 0,	/* dest pos x */
606 			 VIDEO_LOGO_HEIGHT,	/* dest pos y */
607 			 VIDEO_VISIBLE_COLS,	/* frame width */
608 			 VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT - VIDEO_FONT_HEIGHT	/* frame height */
609 		);
610 #else
611 	memcpyl (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND,
612 		 CONSOLE_SCROLL_SIZE >> 2);
613 #endif
614 
615 	/* clear the last one */
616 #ifdef VIDEO_HW_RECTFILL
617 	video_hw_rectfill (VIDEO_PIXEL_SIZE,	/* bytes per pixel */
618 			   0,	/* dest pos x */
619 			   VIDEO_VISIBLE_ROWS - VIDEO_FONT_HEIGHT,	/* dest pos y */
620 			   VIDEO_VISIBLE_COLS,	/* frame width */
621 			   VIDEO_FONT_HEIGHT,	/* frame height */
622 			   CONSOLE_BG_COL	/* fill color */
623 		);
624 #else
625 	memsetl (CONSOLE_ROW_LAST, CONSOLE_ROW_SIZE >> 2, CONSOLE_BG_COL);
626 #endif
627 }
628 
629 /*****************************************************************************/
630 
631 static void console_back (void)
632 {
633 	CURSOR_OFF console_col--;
634 
635 	if (console_col < 0) {
636 		console_col = CONSOLE_COLS - 1;
637 		console_row--;
638 		if (console_row < 0)
639 			console_row = 0;
640 	}
641 	video_putchar (console_col * VIDEO_FONT_WIDTH,
642 		       console_row * VIDEO_FONT_HEIGHT,
643 		       ' ');
644 }
645 
646 /*****************************************************************************/
647 
648 static void console_newline (void)
649 {
650 	/* Check if last character in the line was just drawn. If so, cursor was
651 	   overwriten and need not to be cleared. Cursor clearing without this
652 	   check causes overwriting the 1st character of the line if line lenght
653 	   is >= CONSOLE_COLS
654 	 */
655 	if (console_col < CONSOLE_COLS)
656 		CURSOR_OFF
657 	console_row++;
658 	console_col = 0;
659 
660 	/* Check if we need to scroll the terminal */
661 	if (console_row >= CONSOLE_ROWS) {
662 		/* Scroll everything up */
663 		console_scrollup ();
664 
665 		/* Decrement row number */
666 		console_row--;
667 	}
668 }
669 
670 static void console_cr (void)
671 {
672 	CURSOR_OFF console_col = 0;
673 }
674 
675 /*****************************************************************************/
676 
677 void video_putc (const char c)
678 {
679 	static int nl = 1;
680 
681 	switch (c) {
682 	case 13:		/* back to first column */
683 		console_cr ();
684 		break;
685 
686 	case '\n':		/* next line */
687 		if (console_col || (!console_col && nl))
688 			console_newline ();
689 		nl = 1;
690 		break;
691 
692 	case 9:		/* tab 8 */
693 		CURSOR_OFF console_col |= 0x0008;
694 		console_col &= ~0x0007;
695 
696 		if (console_col >= CONSOLE_COLS)
697 			console_newline ();
698 		break;
699 
700 	case 8:		/* backspace */
701 		console_back ();
702 		break;
703 
704 	default:		/* draw the char */
705 		video_putchar (console_col * VIDEO_FONT_WIDTH,
706 			       console_row * VIDEO_FONT_HEIGHT,
707 			       c);
708 		console_col++;
709 
710 		/* check for newline */
711 		if (console_col >= CONSOLE_COLS) {
712 			console_newline ();
713 			nl = 0;
714 		}
715 	}
716 CURSOR_SET}
717 
718 
719 /*****************************************************************************/
720 
721 void video_puts (const char *s)
722 {
723 	int count = strlen (s);
724 
725 	while (count--)
726 		video_putc (*s++);
727 }
728 
729 /*****************************************************************************/
730 
731 #if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
732 
733 #define FILL_8BIT_332RGB(r,g,b)	{			\
734 	*fb = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6);	\
735 	fb ++;						\
736 }
737 
738 #define FILL_15BIT_555RGB(r,g,b) {			\
739 	*(unsigned short *)fb = SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3))); \
740 	fb += 2;					\
741 }
742 
743 #define FILL_16BIT_565RGB(r,g,b) {			\
744 	*(unsigned short *)fb = SWAP16((unsigned short)((((r)>>3)<<11) | (((g)>>2)<<5) | ((b)>>3))); \
745 	fb += 2;					\
746 }
747 
748 #define FILL_32BIT_X888RGB(r,g,b) {			\
749 	*(unsigned long *)fb = SWAP32((unsigned long)(((r<<16) | (g<<8) | b))); \
750 	fb += 4;					\
751 }
752 
753 #ifdef VIDEO_FB_LITTLE_ENDIAN
754 #define FILL_24BIT_888RGB(r,g,b) {			\
755 	fb[0] = b;					\
756 	fb[1] = g;					\
757 	fb[2] = r;					\
758 	fb += 3;					\
759 }
760 #else
761 #define FILL_24BIT_888RGB(r,g,b) {			\
762 	fb[0] = r;					\
763 	fb[1] = g;					\
764 	fb[2] = b;					\
765 	fb += 3;					\
766 }
767 #endif
768 
769 
770 /*
771  * Display the BMP file located at address bmp_image.
772  * Only uncompressed
773  */
774 int video_display_bitmap (ulong bmp_image, int x, int y)
775 {
776 	ushort xcount, ycount;
777 	uchar *fb;
778 	bmp_image_t *bmp = (bmp_image_t *) bmp_image;
779 	uchar *bmap;
780 	ushort padded_line;
781 	unsigned long width, height, bpp;
782 	unsigned colors;
783 	unsigned long compression;
784 	bmp_color_table_entry_t cte;
785 #ifdef CONFIG_VIDEO_BMP_GZIP
786 	unsigned char *dst = NULL;
787 	ulong len;
788 #endif
789 
790 	WATCHDOG_RESET ();
791 
792 	if (!((bmp->header.signature[0] == 'B') &&
793 	      (bmp->header.signature[1] == 'M'))) {
794 
795 #ifdef CONFIG_VIDEO_BMP_GZIP
796 		/*
797 		 * Could be a gzipped bmp image, try to decrompress...
798 		 */
799 		len = CFG_VIDEO_LOGO_MAX_SIZE;
800 		dst = malloc(CFG_VIDEO_LOGO_MAX_SIZE);
801 		if (dst == NULL) {
802 			printf("Error: malloc in gunzip failed!\n");
803 			return(1);
804 		}
805 		if (gunzip(dst, CFG_VIDEO_LOGO_MAX_SIZE, (uchar *)bmp_image, &len) != 0) {
806 			printf ("Error: no valid bmp or bmp.gz image at %lx\n", bmp_image);
807 			free(dst);
808 			return 1;
809 		}
810 		if (len == CFG_VIDEO_LOGO_MAX_SIZE) {
811 			printf("Image could be truncated (increase CFG_VIDEO_LOGO_MAX_SIZE)!\n");
812 		}
813 
814 		/*
815 		 * Set addr to decompressed image
816 		 */
817 		bmp = (bmp_image_t *)dst;
818 
819 		if (!((bmp->header.signature[0] == 'B') &&
820 		      (bmp->header.signature[1] == 'M'))) {
821 			printf ("Error: no valid bmp.gz image at %lx\n", bmp_image);
822 			return 1;
823 		}
824 #else
825 		printf ("Error: no valid bmp image at %lx\n", bmp_image);
826 		return 1;
827 #endif /* CONFIG_VIDEO_BMP_GZIP */
828 	}
829 
830 	width = le32_to_cpu (bmp->header.width);
831 	height = le32_to_cpu (bmp->header.height);
832 	bpp = le16_to_cpu (bmp->header.bit_count);
833 	colors = le32_to_cpu (bmp->header.colors_used);
834 	compression = le32_to_cpu (bmp->header.compression);
835 
836 	debug ("Display-bmp: %d x %d  with %d colors\n",
837 	       width, height, colors);
838 
839 	if (compression != BMP_BI_RGB) {
840 		printf ("Error: compression type %ld not supported\n",
841 			compression);
842 		return 1;
843 	}
844 
845 	padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
846 
847 	if ((x + width) > VIDEO_VISIBLE_COLS)
848 		width = VIDEO_VISIBLE_COLS - x;
849 	if ((y + height) > VIDEO_VISIBLE_ROWS)
850 		height = VIDEO_VISIBLE_ROWS - y;
851 
852 	bmap = (uchar *) bmp + le32_to_cpu (bmp->header.data_offset);
853 	fb = (uchar *) (video_fb_address +
854 			((y + height - 1) * VIDEO_COLS * VIDEO_PIXEL_SIZE) +
855 			x * VIDEO_PIXEL_SIZE);
856 
857 	/* We handle only 8bpp or 24 bpp bitmap */
858 	switch (le16_to_cpu (bmp->header.bit_count)) {
859 	case 8:
860 		padded_line -= width;
861 		if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
862 			/* Copy colormap					     */
863 			for (xcount = 0; xcount < colors; ++xcount) {
864 				cte = bmp->color_table[xcount];
865 				video_set_lut (xcount, cte.red, cte.green, cte.blue);
866 			}
867 		}
868 		ycount = height;
869 		switch (VIDEO_DATA_FORMAT) {
870 		case GDF__8BIT_INDEX:
871 			while (ycount--) {
872 				WATCHDOG_RESET ();
873 				xcount = width;
874 				while (xcount--) {
875 					*fb++ = *bmap++;
876 				}
877 				bmap += padded_line;
878 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
879 			}
880 			break;
881 		case GDF__8BIT_332RGB:
882 			while (ycount--) {
883 				WATCHDOG_RESET ();
884 				xcount = width;
885 				while (xcount--) {
886 					cte = bmp->color_table[*bmap++];
887 					FILL_8BIT_332RGB (cte.red, cte.green, cte.blue);
888 				}
889 				bmap += padded_line;
890 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
891 			}
892 			break;
893 		case GDF_15BIT_555RGB:
894 			while (ycount--) {
895 				WATCHDOG_RESET ();
896 				xcount = width;
897 				while (xcount--) {
898 					cte = bmp->color_table[*bmap++];
899 					FILL_15BIT_555RGB (cte.red, cte.green, cte.blue);
900 				}
901 				bmap += padded_line;
902 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
903 			}
904 			break;
905 		case GDF_16BIT_565RGB:
906 			while (ycount--) {
907 				WATCHDOG_RESET ();
908 				xcount = width;
909 				while (xcount--) {
910 					cte = bmp->color_table[*bmap++];
911 					FILL_16BIT_565RGB (cte.red, cte.green, cte.blue);
912 				}
913 				bmap += padded_line;
914 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
915 			}
916 			break;
917 		case GDF_32BIT_X888RGB:
918 			while (ycount--) {
919 				WATCHDOG_RESET ();
920 				xcount = width;
921 				while (xcount--) {
922 					cte = bmp->color_table[*bmap++];
923 					FILL_32BIT_X888RGB (cte.red, cte.green, cte.blue);
924 				}
925 				bmap += padded_line;
926 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
927 			}
928 			break;
929 		case GDF_24BIT_888RGB:
930 			while (ycount--) {
931 				WATCHDOG_RESET ();
932 				xcount = width;
933 				while (xcount--) {
934 					cte = bmp->color_table[*bmap++];
935 					FILL_24BIT_888RGB (cte.red, cte.green, cte.blue);
936 				}
937 				bmap += padded_line;
938 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
939 			}
940 			break;
941 		}
942 		break;
943 	case 24:
944 		padded_line -= 3 * width;
945 		ycount = height;
946 		switch (VIDEO_DATA_FORMAT) {
947 		case GDF__8BIT_332RGB:
948 			while (ycount--) {
949 				WATCHDOG_RESET ();
950 				xcount = width;
951 				while (xcount--) {
952 					FILL_8BIT_332RGB (bmap[2], bmap[1], bmap[0]);
953 					bmap += 3;
954 				}
955 				bmap += padded_line;
956 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
957 			}
958 			break;
959 		case GDF_15BIT_555RGB:
960 			while (ycount--) {
961 				WATCHDOG_RESET ();
962 				xcount = width;
963 				while (xcount--) {
964 					FILL_15BIT_555RGB (bmap[2], bmap[1], bmap[0]);
965 					bmap += 3;
966 				}
967 				bmap += padded_line;
968 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
969 			}
970 			break;
971 		case GDF_16BIT_565RGB:
972 			while (ycount--) {
973 				WATCHDOG_RESET ();
974 				xcount = width;
975 				while (xcount--) {
976 					FILL_16BIT_565RGB (bmap[2], bmap[1], bmap[0]);
977 					bmap += 3;
978 				}
979 				bmap += padded_line;
980 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
981 			}
982 			break;
983 		case GDF_32BIT_X888RGB:
984 			while (ycount--) {
985 				WATCHDOG_RESET ();
986 				xcount = width;
987 				while (xcount--) {
988 					FILL_32BIT_X888RGB (bmap[2], bmap[1], bmap[0]);
989 					bmap += 3;
990 				}
991 				bmap += padded_line;
992 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
993 			}
994 			break;
995 		case GDF_24BIT_888RGB:
996 			while (ycount--) {
997 				WATCHDOG_RESET ();
998 				xcount = width;
999 				while (xcount--) {
1000 					FILL_24BIT_888RGB (bmap[2], bmap[1], bmap[0]);
1001 					bmap += 3;
1002 				}
1003 				bmap += padded_line;
1004 				fb -= (VIDEO_VISIBLE_COLS + width) * VIDEO_PIXEL_SIZE;
1005 			}
1006 			break;
1007 		default:
1008 			printf ("Error: 24 bits/pixel bitmap incompatible with current video mode\n");
1009 			break;
1010 		}
1011 		break;
1012 	default:
1013 		printf ("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
1014 			le16_to_cpu (bmp->header.bit_count));
1015 		break;
1016 	}
1017 
1018 #ifdef CONFIG_VIDEO_BMP_GZIP
1019 	if (dst) {
1020 		free(dst);
1021 	}
1022 #endif
1023 
1024 	return (0);
1025 }
1026 #endif
1027 
1028 /*****************************************************************************/
1029 
1030 #ifdef CONFIG_VIDEO_LOGO
1031 void logo_plot (void *screen, int width, int x, int y)
1032 {
1033 
1034 	int xcount, i;
1035 	int skip   = (width - VIDEO_LOGO_WIDTH) * VIDEO_PIXEL_SIZE;
1036 	int ycount = VIDEO_LOGO_HEIGHT;
1037 	unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
1038 	unsigned char *source;
1039 	unsigned char *dest = (unsigned char *)screen + ((y * width * VIDEO_PIXEL_SIZE) + x);
1040 
1041 #ifdef CONFIG_VIDEO_BMP_LOGO
1042 	source = bmp_logo_bitmap;
1043 
1044 	/* Allocate temporary space for computing colormap			 */
1045 	logo_red = malloc (BMP_LOGO_COLORS);
1046 	logo_green = malloc (BMP_LOGO_COLORS);
1047 	logo_blue = malloc (BMP_LOGO_COLORS);
1048 	/* Compute color map							 */
1049 	for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
1050 		logo_red[i] = (bmp_logo_palette[i] & 0x0f00) >> 4;
1051 		logo_green[i] = (bmp_logo_palette[i] & 0x00f0);
1052 		logo_blue[i] = (bmp_logo_palette[i] & 0x000f) << 4;
1053 	}
1054 #else
1055 	source = linux_logo;
1056 	logo_red = linux_logo_red;
1057 	logo_green = linux_logo_green;
1058 	logo_blue = linux_logo_blue;
1059 #endif
1060 
1061 	if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
1062 		for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
1063 			video_set_lut (i + VIDEO_LOGO_LUT_OFFSET,
1064 				       logo_red[i], logo_green[i], logo_blue[i]);
1065 		}
1066 	}
1067 
1068 	while (ycount--) {
1069 		xcount = VIDEO_LOGO_WIDTH;
1070 		while (xcount--) {
1071 			r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET];
1072 			g = logo_green[*source - VIDEO_LOGO_LUT_OFFSET];
1073 			b = logo_blue[*source - VIDEO_LOGO_LUT_OFFSET];
1074 
1075 			switch (VIDEO_DATA_FORMAT) {
1076 			case GDF__8BIT_INDEX:
1077 				*dest = *source;
1078 				break;
1079 			case GDF__8BIT_332RGB:
1080 				*dest = ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
1081 				break;
1082 			case GDF_15BIT_555RGB:
1083 				*(unsigned short *) dest =
1084 					SWAP16 ((unsigned short) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)));
1085 				break;
1086 			case GDF_16BIT_565RGB:
1087 				*(unsigned short *) dest =
1088 					SWAP16 ((unsigned short) (((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)));
1089 				break;
1090 			case GDF_32BIT_X888RGB:
1091 				*(unsigned long *) dest =
1092 					SWAP32 ((unsigned long) ((r << 16) | (g << 8) | b));
1093 				break;
1094 			case GDF_24BIT_888RGB:
1095 #ifdef VIDEO_FB_LITTLE_ENDIAN
1096 				dest[0] = b;
1097 				dest[1] = g;
1098 				dest[2] = r;
1099 #else
1100 				dest[0] = r;
1101 				dest[1] = g;
1102 				dest[2] = b;
1103 #endif
1104 				break;
1105 			}
1106 			source++;
1107 			dest += VIDEO_PIXEL_SIZE;
1108 		}
1109 		dest += skip;
1110 	}
1111 #ifdef CONFIG_VIDEO_BMP_LOGO
1112 	free (logo_red);
1113 	free (logo_green);
1114 	free (logo_blue);
1115 #endif
1116 }
1117 
1118 /*****************************************************************************/
1119 
1120 static void *video_logo (void)
1121 {
1122 	char info[128];
1123 	extern char version_string;
1124 
1125 #ifdef CONFIG_SPLASH_SCREEN
1126 	char *s;
1127 	ulong addr;
1128 
1129 	if ((s = getenv ("splashimage")) != NULL) {
1130 		addr = simple_strtoul (s, NULL, 16);
1131 
1132 		if (video_display_bitmap (addr, 0, 0) == 0) {
1133 			return ((void *) (video_fb_address));
1134 		}
1135 	}
1136 #endif /* CONFIG_SPLASH_SCREEN */
1137 
1138 	logo_plot (video_fb_address, VIDEO_COLS, 0, 0);
1139 
1140 	sprintf (info, " %s", &version_string);
1141 	video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *)info);
1142 
1143 #ifdef CONFIG_CONSOLE_EXTRA_INFO
1144 	{
1145 		int i, n = ((VIDEO_LOGO_HEIGHT - VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
1146 
1147 		for (i = 1; i < n; i++) {
1148 			video_get_info_str (i, info);
1149 			if (*info)
1150 				video_drawstring (VIDEO_INFO_X,
1151 						  VIDEO_INFO_Y + i * VIDEO_FONT_HEIGHT,
1152 						  (uchar *)info);
1153 		}
1154 	}
1155 #endif
1156 
1157 	return (video_fb_address + VIDEO_LOGO_HEIGHT * VIDEO_LINE_LEN);
1158 }
1159 #endif
1160 
1161 
1162 /*****************************************************************************/
1163 
1164 static int video_init (void)
1165 {
1166 	unsigned char color8;
1167 
1168 	if ((pGD = video_hw_init ()) == NULL)
1169 		return -1;
1170 
1171 	video_fb_address = (void *) VIDEO_FB_ADRS;
1172 #ifdef CONFIG_VIDEO_HW_CURSOR
1173 	video_init_hw_cursor (VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
1174 #endif
1175 
1176 	/* Init drawing pats */
1177 	switch (VIDEO_DATA_FORMAT) {
1178 	case GDF__8BIT_INDEX:
1179 		video_set_lut (0x01, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
1180 		video_set_lut (0x00, CONSOLE_BG_COL, CONSOLE_BG_COL, CONSOLE_BG_COL);
1181 		fgx = 0x01010101;
1182 		bgx = 0x00000000;
1183 		break;
1184 	case GDF__8BIT_332RGB:
1185 		color8 = ((CONSOLE_FG_COL & 0xe0) |
1186 			  ((CONSOLE_FG_COL >> 3) & 0x1c) | CONSOLE_FG_COL >> 6);
1187 		fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8;
1188 		color8 = ((CONSOLE_BG_COL & 0xe0) |
1189 			  ((CONSOLE_BG_COL >> 3) & 0x1c) | CONSOLE_BG_COL >> 6);
1190 		bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8;
1191 		break;
1192 	case GDF_15BIT_555RGB:
1193 		fgx = (((CONSOLE_FG_COL >> 3) << 26) |
1194 		       ((CONSOLE_FG_COL >> 3) << 21) | ((CONSOLE_FG_COL >> 3) << 16) |
1195 		       ((CONSOLE_FG_COL >> 3) << 10) | ((CONSOLE_FG_COL >> 3) << 5) |
1196 		       (CONSOLE_FG_COL >> 3));
1197 		bgx = (((CONSOLE_BG_COL >> 3) << 26) |
1198 		       ((CONSOLE_BG_COL >> 3) << 21) | ((CONSOLE_BG_COL >> 3) << 16) |
1199 		       ((CONSOLE_BG_COL >> 3) << 10) | ((CONSOLE_BG_COL >> 3) << 5) |
1200 		       (CONSOLE_BG_COL >> 3));
1201 		break;
1202 	case GDF_16BIT_565RGB:
1203 		fgx = (((CONSOLE_FG_COL >> 3) << 27) |
1204 		       ((CONSOLE_FG_COL >> 2) << 21) | ((CONSOLE_FG_COL >> 3) << 16) |
1205 		       ((CONSOLE_FG_COL >> 3) << 11) | ((CONSOLE_FG_COL >> 2) << 5) |
1206 		       (CONSOLE_FG_COL >> 3));
1207 		bgx = (((CONSOLE_BG_COL >> 3) << 27) |
1208 		       ((CONSOLE_BG_COL >> 2) << 21) | ((CONSOLE_BG_COL >> 3) << 16) |
1209 		       ((CONSOLE_BG_COL >> 3) << 11) | ((CONSOLE_BG_COL >> 2) << 5) |
1210 		       (CONSOLE_BG_COL >> 3));
1211 		break;
1212 	case GDF_32BIT_X888RGB:
1213 		fgx = (CONSOLE_FG_COL << 16) | (CONSOLE_FG_COL << 8) | CONSOLE_FG_COL;
1214 		bgx = (CONSOLE_BG_COL << 16) | (CONSOLE_BG_COL << 8) | CONSOLE_BG_COL;
1215 		break;
1216 	case GDF_24BIT_888RGB:
1217 		fgx = (CONSOLE_FG_COL << 24) | (CONSOLE_FG_COL << 16) |
1218 			(CONSOLE_FG_COL << 8) | CONSOLE_FG_COL;
1219 		bgx = (CONSOLE_BG_COL << 24) | (CONSOLE_BG_COL << 16) |
1220 			(CONSOLE_BG_COL << 8) | CONSOLE_BG_COL;
1221 		break;
1222 	}
1223 	eorx = fgx ^ bgx;
1224 
1225 #ifdef CONFIG_VIDEO_LOGO
1226 	/* Plot the logo and get start point of console */
1227 	PRINTD ("Video: Drawing the logo ...\n");
1228 	video_console_address = video_logo ();
1229 #else
1230 	video_console_address = video_fb_address;
1231 #endif
1232 
1233 	/* Initialize the console */
1234 	console_col = 0;
1235 	console_row = 0;
1236 
1237 	return 0;
1238 }
1239 
1240 
1241 /*****************************************************************************/
1242 
1243 int drv_video_init (void)
1244 {
1245 	int skip_dev_init;
1246 	device_t console_dev;
1247 
1248 	skip_dev_init = 0;
1249 
1250 	/* Init video chip - returns with framebuffer cleared */
1251 	if (video_init () == -1)
1252 		skip_dev_init = 1;
1253 
1254 #ifdef CONFIG_VGA_AS_SINGLE_DEVICE
1255 	/* Devices VGA and Keyboard will be assigned seperately */
1256 	/* Init vga device */
1257 	if (!skip_dev_init) {
1258 		memset (&console_dev, 0, sizeof (console_dev));
1259 		strcpy (console_dev.name, "vga");
1260 		console_dev.ext = DEV_EXT_VIDEO;	/* Video extensions */
1261 		console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
1262 		console_dev.putc = video_putc;	/* 'putc' function */
1263 		console_dev.puts = video_puts;	/* 'puts' function */
1264 		console_dev.tstc = NULL;	/* 'tstc' function */
1265 		console_dev.getc = NULL;	/* 'getc' function */
1266 
1267 		if (device_register (&console_dev) == 0)
1268 			return 1;
1269 	}
1270 #else
1271 	PRINTD ("KBD: Keyboard init ...\n");
1272 	if (VIDEO_KBD_INIT_FCT == -1)
1273 		skip_dev_init = 1;
1274 
1275 	/* Init console device */
1276 	if (!skip_dev_init) {
1277 		memset (&console_dev, 0, sizeof (console_dev));
1278 		strcpy (console_dev.name, "vga");
1279 		console_dev.ext = DEV_EXT_VIDEO;	/* Video extensions */
1280 		console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
1281 		console_dev.putc = video_putc;	/* 'putc' function */
1282 		console_dev.puts = video_puts;	/* 'puts' function */
1283 		console_dev.tstc = VIDEO_TSTC_FCT;	/* 'tstc' function */
1284 		console_dev.getc = VIDEO_GETC_FCT;	/* 'getc' function */
1285 
1286 		if (device_register (&console_dev) == 0)
1287 			return 1;
1288 	}
1289 #endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
1290 	/* No console dev available */
1291 	return 0;
1292 }
1293 #endif /* CONFIG_CFB_CONSOLE */
1294