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