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