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