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