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