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