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