video: Clean drivers/video/Makefile
[platform/kernel/u-boot.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 #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)
319 #else
320 #define SHORTSWAP32(x)   ( ((x) >> 16) | ((x) << 16) )
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 = CFG_VIDEO_LOGO_MAX_SIZE;
828                 dst = malloc(CFG_VIDEO_LOGO_MAX_SIZE);
829                 if (dst == NULL) {
830                         printf("Error: malloc in gunzip failed!\n");
831                         return(1);
832                 }
833                 if (gunzip(dst, CFG_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 == CFG_VIDEO_LOGO_MAX_SIZE) {
839                         printf("Image could be truncated (increase CFG_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_15BIT_555RGB (cte.red, cte.green, cte.blue);
937 #else
938                                         fill_555rgb_pswap (fb, xpos++, cte.red,
939                                                            cte.green, cte.blue);
940                                         fb += 2;
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_15BIT_555RGB (bmap[2], bmap[1], bmap[0]);
1011 #else
1012                                         fill_555rgb_pswap (fb, xpos++, bmap[2],
1013                                                            bmap[1], bmap[0]);
1014                                         fb += 2;
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                                 *(unsigned short *) dest =
1141                                         SWAP16 ((unsigned short) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)));
1142 #else
1143                                 fill_555rgb_pswap (dest, xpos++, r, g, b);
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
1185 #ifdef CONFIG_SPLASH_SCREEN
1186         char *s;
1187         ulong addr;
1188
1189         if ((s = getenv ("splashimage")) != NULL) {
1190                 addr = simple_strtoul (s, NULL, 16);
1191
1192                 if (video_display_bitmap (addr, 0, 0) == 0) {
1193                         return ((void *) (video_fb_address));
1194                 }
1195         }
1196 #endif /* CONFIG_SPLASH_SCREEN */
1197
1198         logo_plot (video_fb_address, VIDEO_COLS, 0, 0);
1199
1200         sprintf (info, " %s", &version_string);
1201         video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *)info);
1202
1203 #ifdef CONFIG_CONSOLE_EXTRA_INFO
1204         {
1205                 int i, n = ((VIDEO_LOGO_HEIGHT - VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
1206
1207                 for (i = 1; i < n; i++) {
1208                         video_get_info_str (i, info);
1209                         if (*info)
1210                                 video_drawstring (VIDEO_INFO_X,
1211                                                   VIDEO_INFO_Y + i * VIDEO_FONT_HEIGHT,
1212                                                   (uchar *)info);
1213                 }
1214         }
1215 #endif
1216
1217         return (video_fb_address + VIDEO_LOGO_HEIGHT * VIDEO_LINE_LEN);
1218 }
1219 #endif
1220
1221
1222 /*****************************************************************************/
1223
1224 static int video_init (void)
1225 {
1226         unsigned char color8;
1227
1228         if ((pGD = video_hw_init ()) == NULL)
1229                 return -1;
1230
1231         video_fb_address = (void *) VIDEO_FB_ADRS;
1232 #ifdef CONFIG_VIDEO_HW_CURSOR
1233         video_init_hw_cursor (VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
1234 #endif
1235
1236         /* Init drawing pats */
1237         switch (VIDEO_DATA_FORMAT) {
1238         case GDF__8BIT_INDEX:
1239                 video_set_lut (0x01, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL);
1240                 video_set_lut (0x00, CONSOLE_BG_COL, CONSOLE_BG_COL, CONSOLE_BG_COL);
1241                 fgx = 0x01010101;
1242                 bgx = 0x00000000;
1243                 break;
1244         case GDF__8BIT_332RGB:
1245                 color8 = ((CONSOLE_FG_COL & 0xe0) |
1246                           ((CONSOLE_FG_COL >> 3) & 0x1c) | CONSOLE_FG_COL >> 6);
1247                 fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8;
1248                 color8 = ((CONSOLE_BG_COL & 0xe0) |
1249                           ((CONSOLE_BG_COL >> 3) & 0x1c) | CONSOLE_BG_COL >> 6);
1250                 bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) | color8;
1251                 break;
1252         case GDF_15BIT_555RGB:
1253                 fgx = (((CONSOLE_FG_COL >> 3) << 26) |
1254                        ((CONSOLE_FG_COL >> 3) << 21) | ((CONSOLE_FG_COL >> 3) << 16) |
1255                        ((CONSOLE_FG_COL >> 3) << 10) | ((CONSOLE_FG_COL >> 3) << 5) |
1256                        (CONSOLE_FG_COL >> 3));
1257                 bgx = (((CONSOLE_BG_COL >> 3) << 26) |
1258                        ((CONSOLE_BG_COL >> 3) << 21) | ((CONSOLE_BG_COL >> 3) << 16) |
1259                        ((CONSOLE_BG_COL >> 3) << 10) | ((CONSOLE_BG_COL >> 3) << 5) |
1260                        (CONSOLE_BG_COL >> 3));
1261                 break;
1262         case GDF_16BIT_565RGB:
1263                 fgx = (((CONSOLE_FG_COL >> 3) << 27) |
1264                        ((CONSOLE_FG_COL >> 2) << 21) | ((CONSOLE_FG_COL >> 3) << 16) |
1265                        ((CONSOLE_FG_COL >> 3) << 11) | ((CONSOLE_FG_COL >> 2) << 5) |
1266                        (CONSOLE_FG_COL >> 3));
1267                 bgx = (((CONSOLE_BG_COL >> 3) << 27) |
1268                        ((CONSOLE_BG_COL >> 2) << 21) | ((CONSOLE_BG_COL >> 3) << 16) |
1269                        ((CONSOLE_BG_COL >> 3) << 11) | ((CONSOLE_BG_COL >> 2) << 5) |
1270                        (CONSOLE_BG_COL >> 3));
1271                 break;
1272         case GDF_32BIT_X888RGB:
1273                 fgx = (CONSOLE_FG_COL << 16) | (CONSOLE_FG_COL << 8) | CONSOLE_FG_COL;
1274                 bgx = (CONSOLE_BG_COL << 16) | (CONSOLE_BG_COL << 8) | CONSOLE_BG_COL;
1275                 break;
1276         case GDF_24BIT_888RGB:
1277                 fgx = (CONSOLE_FG_COL << 24) | (CONSOLE_FG_COL << 16) |
1278                         (CONSOLE_FG_COL << 8) | CONSOLE_FG_COL;
1279                 bgx = (CONSOLE_BG_COL << 24) | (CONSOLE_BG_COL << 16) |
1280                         (CONSOLE_BG_COL << 8) | CONSOLE_BG_COL;
1281                 break;
1282         }
1283         eorx = fgx ^ bgx;
1284
1285 #ifdef CONFIG_VIDEO_LOGO
1286         /* Plot the logo and get start point of console */
1287         PRINTD ("Video: Drawing the logo ...\n");
1288         video_console_address = video_logo ();
1289 #else
1290         video_console_address = video_fb_address;
1291 #endif
1292
1293         /* Initialize the console */
1294         console_col = 0;
1295         console_row = 0;
1296
1297         return 0;
1298 }
1299
1300
1301 /*****************************************************************************/
1302
1303 int drv_video_init (void)
1304 {
1305         int skip_dev_init;
1306         device_t console_dev;
1307
1308         skip_dev_init = 0;
1309
1310         /* Init video chip - returns with framebuffer cleared */
1311         if (video_init () == -1)
1312                 skip_dev_init = 1;
1313
1314 #ifdef CONFIG_VGA_AS_SINGLE_DEVICE
1315         /* Devices VGA and Keyboard will be assigned seperately */
1316         /* Init vga device */
1317         if (!skip_dev_init) {
1318                 memset (&console_dev, 0, sizeof (console_dev));
1319                 strcpy (console_dev.name, "vga");
1320                 console_dev.ext = DEV_EXT_VIDEO;        /* Video extensions */
1321                 console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
1322                 console_dev.putc = video_putc;  /* 'putc' function */
1323                 console_dev.puts = video_puts;  /* 'puts' function */
1324                 console_dev.tstc = NULL;        /* 'tstc' function */
1325                 console_dev.getc = NULL;        /* 'getc' function */
1326
1327                 if (device_register (&console_dev) == 0)
1328                         return 1;
1329         }
1330 #else
1331         PRINTD ("KBD: Keyboard init ...\n");
1332         if (VIDEO_KBD_INIT_FCT == -1)
1333                 skip_dev_init = 1;
1334
1335         /* Init console device */
1336         if (!skip_dev_init) {
1337                 memset (&console_dev, 0, sizeof (console_dev));
1338                 strcpy (console_dev.name, "vga");
1339                 console_dev.ext = DEV_EXT_VIDEO;        /* Video extensions */
1340                 console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
1341                 console_dev.putc = video_putc;  /* 'putc' function */
1342                 console_dev.puts = video_puts;  /* 'puts' function */
1343                 console_dev.tstc = VIDEO_TSTC_FCT;      /* 'tstc' function */
1344                 console_dev.getc = VIDEO_GETC_FCT;      /* 'getc' function */
1345
1346                 if (device_register (&console_dev) == 0)
1347                         return 1;
1348         }
1349 #endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
1350         /* No console dev available */
1351         return 0;
1352 }