]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/video/cfb_console.c
video: fix bug in cfb_console.c code
[karo-tx-uboot.git] / drivers / video / cfb_console.c
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 int drv_video_init (void)
1334 {
1335         int skip_dev_init;
1336         device_t console_dev;
1337
1338         skip_dev_init = 0;
1339
1340         /* Init video chip - returns with framebuffer cleared */
1341         if (video_init () == -1)
1342                 skip_dev_init = 1;
1343
1344 #ifdef CONFIG_VGA_AS_SINGLE_DEVICE
1345         /* Devices VGA and Keyboard will be assigned seperately */
1346         /* Init vga device */
1347         if (!skip_dev_init) {
1348                 memset (&console_dev, 0, sizeof (console_dev));
1349                 strcpy (console_dev.name, "vga");
1350                 console_dev.ext = DEV_EXT_VIDEO;        /* Video extensions */
1351                 console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
1352                 console_dev.putc = video_putc;  /* 'putc' function */
1353                 console_dev.puts = video_puts;  /* 'puts' function */
1354                 console_dev.tstc = NULL;        /* 'tstc' function */
1355                 console_dev.getc = NULL;        /* 'getc' function */
1356
1357                 if (device_register (&console_dev) == 0)
1358                         return 1;
1359         }
1360 #else
1361         PRINTD ("KBD: Keyboard init ...\n");
1362         if (VIDEO_KBD_INIT_FCT == -1)
1363                 skip_dev_init = 1;
1364
1365         /* Init console device */
1366         if (!skip_dev_init) {
1367                 memset (&console_dev, 0, sizeof (console_dev));
1368                 strcpy (console_dev.name, "vga");
1369                 console_dev.ext = DEV_EXT_VIDEO;        /* Video extensions */
1370                 console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
1371                 console_dev.putc = video_putc;  /* 'putc' function */
1372                 console_dev.puts = video_puts;  /* 'puts' function */
1373                 console_dev.tstc = VIDEO_TSTC_FCT;      /* 'tstc' function */
1374                 console_dev.getc = VIDEO_GETC_FCT;      /* 'getc' function */
1375
1376                 if (device_register (&console_dev) == 0)
1377                         return 1;
1378         }
1379 #endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
1380         /* No console dev available */
1381         return 0;
1382 }