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