]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/video/cfb_console.c
board/tqc/tqm5200/cam5200_flash.c: Fix GCC 4.6 build warning
[people/ms/u-boot.git] / drivers / video / cfb_console.c
CommitLineData
c609719b
WD
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
4b248f3f 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
c609719b
WD
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
64e40d72 32 * information strings (that normally goes to serial port) can be drawn.
c609719b
WD
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.
64e40d72
WD
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
63 * delay loop in VIDEO_TSTC_FCT (i8042)
64 *
65 * CONFIG_SYS_CONSOLE_BLINK_COUNT - value for delay loop - blink rate
66 * CONFIG_CONSOLE_TIME - display time/date in upper right
67 * corner, needs CONFIG_CMD_DATE and
68 * CONFIG_CONSOLE_CURSOR
69 * CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner
70 * CONFIG_VIDEO_BMP_LOGO - use bmp_logo instead of linux_logo
71 * CONFIG_CONSOLE_EXTRA_INFO - display additional board information
72 * strings that normaly goes to serial
73 * port. This define requires a board
74 * specific function:
75 * video_drawstring (VIDEO_INFO_X,
76 * VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT,
77 * info);
78 * that fills a info buffer at i=row.
79 * s.a: board/eltec/bab7xx.
80 * CONFIG_VGA_AS_SINGLE_DEVICE - If set the framebuffer device will be
81 * initialized as an output only device.
82 * The Keyboard driver will not be
83 * set-up. This may be used, if you have
84 * no or more than one Keyboard devices
85 * (USB Keyboard, AT Keyboard).
86 *
87 * CONFIG_VIDEO_SW_CURSOR: - Draws a cursor after the last
88 * character. No blinking is provided.
89 * Uses the macros CURSOR_SET and
90 * CURSOR_OFF.
91 *
92 * CONFIG_VIDEO_HW_CURSOR: - Uses the hardware cursor capability
93 * of the graphic chip. Uses the macro
94 * CURSOR_SET. ATTENTION: If booting an
95 * OS, the display driver must disable
96 * the hardware register of the graphic
97 * chip. Otherwise a blinking field is
98 * displayed.
99 */
c609719b
WD
100
101#include <common.h>
09c2e90c 102#include <version.h>
a6c7ad2f
WD
103#include <malloc.h>
104
64e40d72
WD
105/*
106 * Console device defines with SMI graphic
107 * Any other graphic must change this section
108 */
c609719b 109
4b248f3f 110#ifdef CONFIG_VIDEO_SMI_LYNXEM
c609719b
WD
111
112#define VIDEO_FB_LITTLE_ENDIAN
113#define VIDEO_HW_RECTFILL
114#define VIDEO_HW_BITBLT
115#endif
116
64e40d72
WD
117/*
118 * Defines for the CT69000 driver
119 */
4b248f3f 120#ifdef CONFIG_VIDEO_CT69000
c609719b
WD
121
122#define VIDEO_FB_LITTLE_ENDIAN
123#define VIDEO_HW_RECTFILL
124#define VIDEO_HW_BITBLT
125#endif
126
64e40d72
WD
127/*
128 * Defines for the SED13806 driver
129 */
a6c7ad2f
WD
130#ifdef CONFIG_VIDEO_SED13806
131
89394047 132#ifndef CONFIG_TOTAL5200
a6c7ad2f 133#define VIDEO_FB_LITTLE_ENDIAN
89394047 134#endif
a6c7ad2f
WD
135#define VIDEO_HW_RECTFILL
136#define VIDEO_HW_BITBLT
137#endif
138
64e40d72
WD
139/*
140 * Defines for the SED13806 driver
141 */
98f4a3df
SR
142#ifdef CONFIG_VIDEO_SM501
143
144#ifdef CONFIG_HH405
145#define VIDEO_FB_LITTLE_ENDIAN
146#endif
147#endif
148
64e40d72
WD
149/*
150 * Defines for the MB862xx driver
151 */
bed53753
AG
152#ifdef CONFIG_VIDEO_MB862xx
153
154#ifdef CONFIG_VIDEO_CORALP
155#define VIDEO_FB_LITTLE_ENDIAN
156#endif
5d16ca87 157#ifdef CONFIG_VIDEO_MB862xx_ACCEL
bed53753
AG
158#define VIDEO_HW_RECTFILL
159#define VIDEO_HW_BITBLT
160#endif
5d16ca87 161#endif
bed53753 162
62a22dca
HR
163/*
164 * Defines for the i.MX31 driver (mx3fb.c)
165 */
166#ifdef CONFIG_VIDEO_MX3
167#define VIDEO_FB_16BPP_WORD_SWAP
168#endif
169
64e40d72
WD
170/*
171 * Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc.
172 */
c609719b
WD
173#include <video_fb.h>
174
64e40d72
WD
175/*
176 * some Macros
177 */
4b248f3f
WD
178#define VIDEO_VISIBLE_COLS (pGD->winSizeX)
179#define VIDEO_VISIBLE_ROWS (pGD->winSizeY)
180#define VIDEO_PIXEL_SIZE (pGD->gdfBytesPP)
181#define VIDEO_DATA_FORMAT (pGD->gdfIndex)
182#define VIDEO_FB_ADRS (pGD->frameAdrs)
c609719b 183
64e40d72
WD
184/*
185 * Console device defines with i8042 keyboard controller
186 * Any other keyboard controller must change this section
187 */
c609719b 188
4b248f3f 189#ifdef CONFIG_I8042_KBD
c609719b
WD
190#include <i8042.h>
191
4b248f3f
WD
192#define VIDEO_KBD_INIT_FCT i8042_kbd_init()
193#define VIDEO_TSTC_FCT i8042_tstc
194#define VIDEO_GETC_FCT i8042_getc
c609719b
WD
195#endif
196
64e40d72
WD
197/*
198 * Console device
199 */
c609719b
WD
200
201#include <version.h>
202#include <linux/types.h>
52cb4d4f 203#include <stdio_dev.h>
c609719b 204#include <video_font.h>
c609719b 205
ddb5d86f
JL
206#if defined(CONFIG_CMD_DATE)
207#include <rtc.h>
c609719b
WD
208#endif
209
07d38a17 210#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
4b248f3f
WD
211#include <watchdog.h>
212#include <bmp_layout.h>
1ca298ce
MW
213
214#ifdef CONFIG_SPLASH_SCREEN_ALIGN
215#define BMP_ALIGN_CENTER 0x7FFF
216#endif
217
07d38a17 218#endif
4b248f3f 219
64e40d72
WD
220/*
221 * Cursor definition:
222 * CONFIG_CONSOLE_CURSOR: Uses a timer function (see drivers/input/i8042.c)
223 * to let the cursor blink. Uses the macros
224 * CURSOR_OFF and CURSOR_ON.
225 * CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No
226 * blinking is provided. Uses the macros CURSOR_SET
227 * and CURSOR_OFF.
228 * CONFIG_VIDEO_HW_CURSOR: Uses the hardware cursor capability of the
229 * graphic chip. Uses the macro CURSOR_SET.
230 * ATTENTION: If booting an OS, the display driver
231 * must disable the hardware register of the graphic
232 * chip. Otherwise a blinking field is displayed
233 */
c609719b
WD
234#if !defined(CONFIG_CONSOLE_CURSOR) && \
235 !defined(CONFIG_VIDEO_SW_CURSOR) && \
236 !defined(CONFIG_VIDEO_HW_CURSOR)
237/* no Cursor defined */
238#define CURSOR_ON
239#define CURSOR_OFF
240#define CURSOR_SET
241#endif
242
4b248f3f
WD
243#ifdef CONFIG_CONSOLE_CURSOR
244#ifdef CURSOR_ON
64e40d72
WD
245#error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
246 or CONFIG_VIDEO_HW_CURSOR can be defined
c609719b 247#endif
64e40d72
WD
248void console_cursor(int state);
249
65618636
TT
250#define CURSOR_ON console_cursor(1)
251#define CURSOR_OFF console_cursor(0)
c609719b
WD
252#define CURSOR_SET
253#ifndef CONFIG_I8042_KBD
7817cb20 254#warning Cursor drawing on/off needs timer function s.a. drivers/input/i8042.c
c609719b
WD
255#endif
256#else
4b248f3f
WD
257#ifdef CONFIG_CONSOLE_TIME
258#error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME
c609719b
WD
259#endif
260#endif /* CONFIG_CONSOLE_CURSOR */
261
4b248f3f
WD
262#ifdef CONFIG_VIDEO_SW_CURSOR
263#ifdef CURSOR_ON
64e40d72
WD
264#error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
265 or CONFIG_VIDEO_HW_CURSOR can be defined
c609719b
WD
266#endif
267#define CURSOR_ON
268#define CURSOR_OFF video_putchar(console_col * VIDEO_FONT_WIDTH,\
65618636
TT
269 console_row * VIDEO_FONT_HEIGHT, ' ')
270#define CURSOR_SET video_set_cursor()
c609719b
WD
271#endif /* CONFIG_VIDEO_SW_CURSOR */
272
273
274#ifdef CONFIG_VIDEO_HW_CURSOR
4b248f3f 275#ifdef CURSOR_ON
64e40d72
WD
276#error only one of CONFIG_CONSOLE_CURSOR, CONFIG_VIDEO_SW_CURSOR, \
277 or CONFIG_VIDEO_HW_CURSOR can be defined
c609719b
WD
278#endif
279#define CURSOR_ON
280#define CURSOR_OFF
281#define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \
65618636 282 (console_row * VIDEO_FONT_HEIGHT) + video_logo_height)
64e40d72 283#endif /* CONFIG_VIDEO_HW_CURSOR */
c609719b 284
4b248f3f
WD
285#ifdef CONFIG_VIDEO_LOGO
286#ifdef CONFIG_VIDEO_BMP_LOGO
a6c7ad2f 287#include <bmp_logo.h>
4b248f3f
WD
288#define VIDEO_LOGO_WIDTH BMP_LOGO_WIDTH
289#define VIDEO_LOGO_HEIGHT BMP_LOGO_HEIGHT
290#define VIDEO_LOGO_LUT_OFFSET BMP_LOGO_OFFSET
291#define VIDEO_LOGO_COLORS BMP_LOGO_COLORS
292
64e40d72 293#else /* CONFIG_VIDEO_BMP_LOGO */
4b248f3f
WD
294#define LINUX_LOGO_WIDTH 80
295#define LINUX_LOGO_HEIGHT 80
296#define LINUX_LOGO_COLORS 214
297#define LINUX_LOGO_LUT_OFFSET 0x20
c609719b
WD
298#define __initdata
299#include <linux_logo.h>
4b248f3f
WD
300#define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH
301#define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT
302#define VIDEO_LOGO_LUT_OFFSET LINUX_LOGO_LUT_OFFSET
303#define VIDEO_LOGO_COLORS LINUX_LOGO_COLORS
64e40d72 304#endif /* CONFIG_VIDEO_BMP_LOGO */
4b248f3f
WD
305#define VIDEO_INFO_X (VIDEO_LOGO_WIDTH)
306#define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2)
64e40d72 307#else /* CONFIG_VIDEO_LOGO */
4b248f3f
WD
308#define VIDEO_LOGO_WIDTH 0
309#define VIDEO_LOGO_HEIGHT 0
64e40d72 310#endif /* CONFIG_VIDEO_LOGO */
4b248f3f
WD
311
312#define VIDEO_COLS VIDEO_VISIBLE_COLS
313#define VIDEO_ROWS VIDEO_VISIBLE_ROWS
314#define VIDEO_SIZE (VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE)
315#define VIDEO_PIX_BLOCKS (VIDEO_SIZE >> 2)
316#define VIDEO_LINE_LEN (VIDEO_COLS*VIDEO_PIXEL_SIZE)
317#define VIDEO_BURST_LEN (VIDEO_COLS/8)
318
319#ifdef CONFIG_VIDEO_LOGO
be129aa7 320#define CONSOLE_ROWS ((VIDEO_ROWS - video_logo_height) / VIDEO_FONT_HEIGHT)
c609719b 321#else
4b248f3f 322#define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT)
c609719b
WD
323#endif
324
4b248f3f
WD
325#define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH)
326#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN)
327#define CONSOLE_ROW_FIRST (video_console_address)
328#define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE)
329#define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE)
330#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS)
331#define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
c609719b
WD
332
333/* Macros */
4b248f3f 334#ifdef VIDEO_FB_LITTLE_ENDIAN
64e40d72
WD
335#define SWAP16(x) ((((x) & 0x00ff) << 8) | \
336 ((x) >> 8) \
337 )
338#define SWAP32(x) ((((x) & 0x000000ff) << 24) | \
339 (((x) & 0x0000ff00) << 8) | \
340 (((x) & 0x00ff0000) >> 8) | \
341 (((x) & 0xff000000) >> 24) \
342 )
343#define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | \
344 (((x) & 0x0000ff00) >> 8) | \
345 (((x) & 0x00ff0000) << 8) | \
346 (((x) & 0xff000000) >> 8) \
347 )
c609719b 348#else
64e40d72
WD
349#define SWAP16(x) (x)
350#define SWAP32(x) (x)
229b6dce 351#if defined(VIDEO_FB_16BPP_WORD_SWAP)
64e40d72 352#define SHORTSWAP32(x) (((x) >> 16) | ((x) << 16))
cc347801 353#else
64e40d72 354#define SHORTSWAP32(x) (x)
bed53753 355#endif
c609719b
WD
356#endif
357
c609719b 358#ifdef CONFIG_CONSOLE_EXTRA_INFO
64e40d72
WD
359/*
360 * setup a board string: type, speed, etc.
361 *
362 * line_number: location to place info string beside logo
363 * info: buffer for info string
364 */
365extern void video_get_info_str(int line_number, char *info);
c609719b
WD
366#endif
367
368/* Locals */
369static GraphicDevice *pGD; /* Pointer to Graphic array */
370
64e40d72 371static void *video_fb_address; /* frame buffer address */
4b248f3f 372static void *video_console_address; /* console buffer start address */
c609719b 373
be129aa7
MW
374static int video_logo_height = VIDEO_LOGO_HEIGHT;
375
57912939
WD
376static int console_col; /* cursor col */
377static int console_row; /* cursor row */
c609719b 378
64e40d72 379static u32 eorx, fgx, bgx; /* color pats */
c609719b
WD
380
381static const int video_font_draw_table8[] = {
64e40d72
WD
382 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
383 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
384 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
385 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
386};
c609719b
WD
387
388static const int video_font_draw_table15[] = {
64e40d72
WD
389 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff
390};
c609719b
WD
391
392static const int video_font_draw_table16[] = {
64e40d72
WD
393 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
394};
c609719b
WD
395
396static const int video_font_draw_table24[16][3] = {
64e40d72
WD
397 {0x00000000, 0x00000000, 0x00000000},
398 {0x00000000, 0x00000000, 0x00ffffff},
399 {0x00000000, 0x0000ffff, 0xff000000},
400 {0x00000000, 0x0000ffff, 0xffffffff},
401 {0x000000ff, 0xffff0000, 0x00000000},
402 {0x000000ff, 0xffff0000, 0x00ffffff},
403 {0x000000ff, 0xffffffff, 0xff000000},
404 {0x000000ff, 0xffffffff, 0xffffffff},
405 {0xffffff00, 0x00000000, 0x00000000},
406 {0xffffff00, 0x00000000, 0x00ffffff},
407 {0xffffff00, 0x0000ffff, 0xff000000},
408 {0xffffff00, 0x0000ffff, 0xffffffff},
409 {0xffffffff, 0xffff0000, 0x00000000},
410 {0xffffffff, 0xffff0000, 0x00ffffff},
411 {0xffffffff, 0xffffffff, 0xff000000},
412 {0xffffffff, 0xffffffff, 0xffffffff}
413};
c609719b
WD
414
415static const int video_font_draw_table32[16][4] = {
64e40d72
WD
416 {0x00000000, 0x00000000, 0x00000000, 0x00000000},
417 {0x00000000, 0x00000000, 0x00000000, 0x00ffffff},
418 {0x00000000, 0x00000000, 0x00ffffff, 0x00000000},
419 {0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff},
420 {0x00000000, 0x00ffffff, 0x00000000, 0x00000000},
421 {0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff},
422 {0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000},
423 {0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff},
424 {0x00ffffff, 0x00000000, 0x00000000, 0x00000000},
425 {0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff},
426 {0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000},
427 {0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff},
428 {0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000},
429 {0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff},
430 {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000},
431 {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff}
432};
433
434
435static void video_drawchars(int xx, int yy, unsigned char *s, int count)
c609719b 436{
4b248f3f
WD
437 u8 *cdat, *dest, *dest0;
438 int rows, offset, c;
439
440 offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE;
441 dest0 = video_fb_address + offset;
442
443 switch (VIDEO_DATA_FORMAT) {
444 case GDF__8BIT_INDEX:
445 case GDF__8BIT_332RGB:
446 while (count--) {
447 c = *s;
448 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
449 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
64e40d72 450 rows--; dest += VIDEO_LINE_LEN) {
4b248f3f
WD
451 u8 bits = *cdat++;
452
64e40d72
WD
453 ((u32 *) dest)[0] =
454 (video_font_draw_table8[bits >> 4] &
455 eorx) ^ bgx;
456 ((u32 *) dest)[1] =
457 (video_font_draw_table8[bits & 15] &
458 eorx) ^ bgx;
4b248f3f
WD
459 }
460 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
461 s++;
462 }
463 break;
c609719b 464
4b248f3f
WD
465 case GDF_15BIT_555RGB:
466 while (count--) {
467 c = *s;
468 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
469 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
64e40d72 470 rows--; dest += VIDEO_LINE_LEN) {
4b248f3f
WD
471 u8 bits = *cdat++;
472
64e40d72
WD
473 ((u32 *) dest)[0] =
474 SHORTSWAP32((video_font_draw_table15
475 [bits >> 6] & eorx) ^
476 bgx);
477 ((u32 *) dest)[1] =
478 SHORTSWAP32((video_font_draw_table15
479 [bits >> 4 & 3] & eorx) ^
480 bgx);
481 ((u32 *) dest)[2] =
482 SHORTSWAP32((video_font_draw_table15
483 [bits >> 2 & 3] & eorx) ^
484 bgx);
485 ((u32 *) dest)[3] =
486 SHORTSWAP32((video_font_draw_table15
487 [bits & 3] & eorx) ^
488 bgx);
4b248f3f
WD
489 }
490 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
491 s++;
492 }
493 break;
c609719b 494
4b248f3f
WD
495 case GDF_16BIT_565RGB:
496 while (count--) {
497 c = *s;
498 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
499 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
64e40d72 500 rows--; dest += VIDEO_LINE_LEN) {
4b248f3f
WD
501 u8 bits = *cdat++;
502
64e40d72
WD
503 ((u32 *) dest)[0] =
504 SHORTSWAP32((video_font_draw_table16
505 [bits >> 6] & eorx) ^
506 bgx);
507 ((u32 *) dest)[1] =
508 SHORTSWAP32((video_font_draw_table16
509 [bits >> 4 & 3] & eorx) ^
510 bgx);
511 ((u32 *) dest)[2] =
512 SHORTSWAP32((video_font_draw_table16
513 [bits >> 2 & 3] & eorx) ^
514 bgx);
515 ((u32 *) dest)[3] =
516 SHORTSWAP32((video_font_draw_table16
517 [bits & 3] & eorx) ^
518 bgx);
4b248f3f
WD
519 }
520 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
521 s++;
522 }
523 break;
c609719b 524
4b248f3f
WD
525 case GDF_32BIT_X888RGB:
526 while (count--) {
527 c = *s;
528 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
529 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
64e40d72 530 rows--; dest += VIDEO_LINE_LEN) {
4b248f3f
WD
531 u8 bits = *cdat++;
532
64e40d72
WD
533 ((u32 *) dest)[0] =
534 SWAP32((video_font_draw_table32
535 [bits >> 4][0] & eorx) ^ bgx);
536 ((u32 *) dest)[1] =
537 SWAP32((video_font_draw_table32
538 [bits >> 4][1] & eorx) ^ bgx);
539 ((u32 *) dest)[2] =
540 SWAP32((video_font_draw_table32
541 [bits >> 4][2] & eorx) ^ bgx);
542 ((u32 *) dest)[3] =
543 SWAP32((video_font_draw_table32
544 [bits >> 4][3] & eorx) ^ bgx);
545 ((u32 *) dest)[4] =
546 SWAP32((video_font_draw_table32
547 [bits & 15][0] & eorx) ^ bgx);
548 ((u32 *) dest)[5] =
549 SWAP32((video_font_draw_table32
550 [bits & 15][1] & eorx) ^ bgx);
551 ((u32 *) dest)[6] =
552 SWAP32((video_font_draw_table32
553 [bits & 15][2] & eorx) ^ bgx);
554 ((u32 *) dest)[7] =
555 SWAP32((video_font_draw_table32
556 [bits & 15][3] & eorx) ^ bgx);
4b248f3f
WD
557 }
558 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
559 s++;
560 }
561 break;
c609719b 562
4b248f3f
WD
563 case GDF_24BIT_888RGB:
564 while (count--) {
565 c = *s;
566 cdat = video_fontdata + c * VIDEO_FONT_HEIGHT;
567 for (rows = VIDEO_FONT_HEIGHT, dest = dest0;
64e40d72 568 rows--; dest += VIDEO_LINE_LEN) {
4b248f3f
WD
569 u8 bits = *cdat++;
570
64e40d72
WD
571 ((u32 *) dest)[0] =
572 (video_font_draw_table24[bits >> 4][0]
573 & eorx) ^ bgx;
574 ((u32 *) dest)[1] =
575 (video_font_draw_table24[bits >> 4][1]
576 & eorx) ^ bgx;
577 ((u32 *) dest)[2] =
578 (video_font_draw_table24[bits >> 4][2]
579 & eorx) ^ bgx;
580 ((u32 *) dest)[3] =
581 (video_font_draw_table24[bits & 15][0]
582 & eorx) ^ bgx;
583 ((u32 *) dest)[4] =
584 (video_font_draw_table24[bits & 15][1]
585 & eorx) ^ bgx;
586 ((u32 *) dest)[5] =
587 (video_font_draw_table24[bits & 15][2]
588 & eorx) ^ bgx;
4b248f3f
WD
589 }
590 dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE;
591 s++;
592 }
593 break;
8bde7f77 594 }
c609719b
WD
595}
596
64e40d72 597static inline void video_drawstring(int xx, int yy, unsigned char *s)
c609719b 598{
64e40d72 599 video_drawchars(xx, yy, s, strlen((char *) s));
c609719b
WD
600}
601
64e40d72 602static void video_putchar(int xx, int yy, unsigned char c)
c609719b 603{
64e40d72 604 video_drawchars(xx, yy + video_logo_height, &c, 1);
c609719b
WD
605}
606
c609719b 607#if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR)
64e40d72 608static void video_set_cursor(void)
c609719b 609{
4b248f3f
WD
610 /* swap drawing colors */
611 eorx = fgx;
612 fgx = bgx;
613 bgx = eorx;
614 eorx = fgx ^ bgx;
615 /* draw cursor */
64e40d72
WD
616 video_putchar(console_col * VIDEO_FONT_WIDTH,
617 console_row * VIDEO_FONT_HEIGHT, ' ');
4b248f3f
WD
618 /* restore drawing colors */
619 eorx = fgx;
620 fgx = bgx;
621 bgx = eorx;
622 eorx = fgx ^ bgx;
c609719b
WD
623}
624#endif
64e40d72 625
c609719b 626#ifdef CONFIG_CONSOLE_CURSOR
64e40d72 627void console_cursor(int state)
c609719b 628{
4b248f3f
WD
629 static int last_state = 0;
630
c609719b 631#ifdef CONFIG_CONSOLE_TIME
4b248f3f
WD
632 struct rtc_time tm;
633 char info[16];
634
635 /* time update only if cursor is on (faster scroll) */
636 if (state) {
64e40d72
WD
637 rtc_get(&tm);
638
639 sprintf(info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min,
640 tm.tm_sec);
641 video_drawstring(VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
642 VIDEO_INFO_Y, (uchar *) info);
643
644 sprintf(info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon,
645 tm.tm_year);
646 video_drawstring(VIDEO_VISIBLE_COLS - 10 * VIDEO_FONT_WIDTH,
647 VIDEO_INFO_Y + 1 * VIDEO_FONT_HEIGHT,
648 (uchar *) info);
4b248f3f 649 }
c609719b
WD
650#endif
651
4b248f3f 652 if (state && (last_state != state)) {
64e40d72 653 video_set_cursor();
4b248f3f 654 }
c609719b 655
4b248f3f
WD
656 if (!state && (last_state != state)) {
657 /* clear cursor */
64e40d72
WD
658 video_putchar(console_col * VIDEO_FONT_WIDTH,
659 console_row * VIDEO_FONT_HEIGHT, ' ');
4b248f3f 660 }
c609719b 661
4b248f3f 662 last_state = state;
c609719b
WD
663}
664#endif
665
c609719b 666#ifndef VIDEO_HW_RECTFILL
64e40d72 667static void memsetl(int *p, int c, int v)
c609719b 668{
4b248f3f
WD
669 while (c--)
670 *(p++) = v;
c609719b
WD
671}
672#endif
673
c609719b 674#ifndef VIDEO_HW_BITBLT
64e40d72 675static void memcpyl(int *d, int *s, int c)
c609719b 676{
4b248f3f
WD
677 while (c--)
678 *(d++) = *(s++);
c609719b
WD
679}
680#endif
681
64e40d72 682static void console_scrollup(void)
c609719b 683{
4b248f3f 684 /* copy up rows ignoring the first one */
c609719b
WD
685
686#ifdef VIDEO_HW_BITBLT
64e40d72
WD
687 video_hw_bitblt(VIDEO_PIXEL_SIZE, /* bytes per pixel */
688 0, /* source pos x */
689 video_logo_height +
690 VIDEO_FONT_HEIGHT, /* source pos y */
691 0, /* dest pos x */
692 video_logo_height, /* dest pos y */
693 VIDEO_VISIBLE_COLS, /* frame width */
694 VIDEO_VISIBLE_ROWS
695 - video_logo_height
696 - VIDEO_FONT_HEIGHT /* frame height */
4b248f3f 697 );
c609719b 698#else
64e40d72
WD
699 memcpyl(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND,
700 CONSOLE_SCROLL_SIZE >> 2);
c609719b
WD
701#endif
702
4b248f3f 703 /* clear the last one */
c609719b 704#ifdef VIDEO_HW_RECTFILL
64e40d72
WD
705 video_hw_rectfill(VIDEO_PIXEL_SIZE, /* bytes per pixel */
706 0, /* dest pos x */
707 VIDEO_VISIBLE_ROWS
708 - VIDEO_FONT_HEIGHT, /* dest pos y */
709 VIDEO_VISIBLE_COLS, /* frame width */
710 VIDEO_FONT_HEIGHT, /* frame height */
711 CONSOLE_BG_COL /* fill color */
4b248f3f 712 );
c609719b 713#else
64e40d72 714 memsetl(CONSOLE_ROW_LAST, CONSOLE_ROW_SIZE >> 2, CONSOLE_BG_COL);
c609719b
WD
715#endif
716}
717
64e40d72 718static void console_back(void)
c609719b 719{
65618636
TT
720 CURSOR_OFF;
721 console_col--;
4b248f3f
WD
722
723 if (console_col < 0) {
724 console_col = CONSOLE_COLS - 1;
725 console_row--;
726 if (console_row < 0)
727 console_row = 0;
728 }
64e40d72
WD
729 video_putchar(console_col * VIDEO_FONT_WIDTH,
730 console_row * VIDEO_FONT_HEIGHT, ' ');
c609719b
WD
731}
732
64e40d72 733static void console_newline(void)
c609719b 734{
20c450ef
AG
735 /* Check if last character in the line was just drawn. If so, cursor was
736 overwriten and need not to be cleared. Cursor clearing without this
737 check causes overwriting the 1st character of the line if line lenght
738 is >= CONSOLE_COLS
739 */
740 if (console_col < CONSOLE_COLS)
65618636 741 CURSOR_OFF;
20c450ef 742 console_row++;
4b248f3f
WD
743 console_col = 0;
744
745 /* Check if we need to scroll the terminal */
746 if (console_row >= CONSOLE_ROWS) {
747 /* Scroll everything up */
64e40d72 748 console_scrollup();
4b248f3f
WD
749
750 /* Decrement row number */
751 console_row--;
752 }
c609719b
WD
753}
754
64e40d72 755static void console_cr(void)
20c450ef 756{
65618636
TT
757 CURSOR_OFF;
758 console_col = 0;
20c450ef
AG
759}
760
64e40d72 761void video_putc(const char c)
c609719b 762{
20c450ef
AG
763 static int nl = 1;
764
4b248f3f 765 switch (c) {
20c450ef 766 case 13: /* back to first column */
64e40d72 767 console_cr();
4b248f3f 768 break;
c609719b 769
4b248f3f 770 case '\n': /* next line */
20c450ef 771 if (console_col || (!console_col && nl))
64e40d72 772 console_newline();
20c450ef 773 nl = 1;
4b248f3f
WD
774 break;
775
776 case 9: /* tab 8 */
65618636
TT
777 CURSOR_OFF;
778 console_col |= 0x0008;
4b248f3f 779 console_col &= ~0x0007;
c609719b 780
4b248f3f 781 if (console_col >= CONSOLE_COLS)
64e40d72 782 console_newline();
4b248f3f 783 break;
c609719b 784
4b248f3f 785 case 8: /* backspace */
64e40d72 786 console_back();
4b248f3f 787 break;
c609719b 788
4b248f3f 789 default: /* draw the char */
64e40d72
WD
790 video_putchar(console_col * VIDEO_FONT_WIDTH,
791 console_row * VIDEO_FONT_HEIGHT, c);
4b248f3f 792 console_col++;
c609719b 793
4b248f3f 794 /* check for newline */
20c450ef 795 if (console_col >= CONSOLE_COLS) {
64e40d72 796 console_newline();
20c450ef
AG
797 nl = 0;
798 }
4b248f3f 799 }
65618636
TT
800 CURSOR_SET;
801}
c609719b 802
64e40d72 803void video_puts(const char *s)
c609719b 804{
64e40d72 805 int count = strlen(s);
4b248f3f
WD
806
807 while (count--)
64e40d72 808 video_putc(*s++);
4b248f3f
WD
809}
810
10543820
AG
811/*
812 * Do not enforce drivers (or board code) to provide empty
813 * video_set_lut() if they do not support 8 bpp format.
814 * Implement weak default function instead.
815 */
64e40d72
WD
816void __video_set_lut(unsigned int index, unsigned char r,
817 unsigned char g, unsigned char b)
10543820
AG
818{
819}
64e40d72
WD
820
821void video_set_lut(unsigned int, unsigned char, unsigned char, unsigned char)
822 __attribute__ ((weak, alias("__video_set_lut")));
10543820 823
07d38a17 824#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
4b248f3f
WD
825
826#define FILL_8BIT_332RGB(r,g,b) { \
827 *fb = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6); \
828 fb ++; \
829}
830
831#define FILL_15BIT_555RGB(r,g,b) { \
64e40d72
WD
832 *(unsigned short *)fb = \
833 SWAP16((unsigned short)(((r>>3)<<10) | \
834 ((g>>3)<<5) | \
835 (b>>3))); \
4b248f3f
WD
836 fb += 2; \
837}
838
839#define FILL_16BIT_565RGB(r,g,b) { \
64e40d72
WD
840 *(unsigned short *)fb = \
841 SWAP16((unsigned short)((((r)>>3)<<11)| \
842 (((g)>>2)<<5) | \
843 ((b)>>3))); \
4b248f3f
WD
844 fb += 2; \
845}
846
847#define FILL_32BIT_X888RGB(r,g,b) { \
64e40d72
WD
848 *(unsigned long *)fb = \
849 SWAP32((unsigned long)(((r<<16) | \
850 (g<<8) | \
851 b))); \
4b248f3f
WD
852 fb += 4; \
853}
854
855#ifdef VIDEO_FB_LITTLE_ENDIAN
856#define FILL_24BIT_888RGB(r,g,b) { \
857 fb[0] = b; \
858 fb[1] = g; \
859 fb[2] = r; \
860 fb += 3; \
861}
862#else
863#define FILL_24BIT_888RGB(r,g,b) { \
864 fb[0] = r; \
865 fb[1] = g; \
866 fb[2] = b; \
867 fb += 3; \
868}
869#endif
870
e84d568f 871#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
64e40d72 872static inline void fill_555rgb_pswap(uchar *fb, int x, u8 r, u8 g, u8 b)
e84d568f 873{
64e40d72
WD
874 ushort *dst = (ushort *) fb;
875 ushort color = (ushort) (((r >> 3) << 10) |
876 ((g >> 3) << 5) |
877 (b >> 3));
e84d568f
AG
878 if (x & 1)
879 *(--dst) = color;
880 else
881 *(++dst) = color;
882}
883#endif
4b248f3f 884
d5011762
AG
885/*
886 * RLE8 bitmap support
887 */
888
889#ifdef CONFIG_VIDEO_BMP_RLE8
890/* Pre-calculated color table entry */
891struct palette {
892 union {
64e40d72
WD
893 unsigned short w; /* word */
894 unsigned int dw; /* double word */
895 } ce; /* color entry */
d5011762
AG
896};
897
898/*
899 * Helper to draw encoded/unencoded run.
900 */
64e40d72
WD
901static void draw_bitmap(uchar **fb, uchar *bm, struct palette *p,
902 int cnt, int enc)
d5011762 903{
64e40d72 904 ulong addr = (ulong) *fb;
d5011762
AG
905 int *off;
906 int enc_off = 1;
907 int i;
908
909 /*
910 * Setup offset of the color index in the bitmap.
911 * Color index of encoded run is at offset 1.
912 */
913 off = enc ? &enc_off : &i;
914
915 switch (VIDEO_DATA_FORMAT) {
916 case GDF__8BIT_INDEX:
917 for (i = 0; i < cnt; i++)
64e40d72 918 *(unsigned char *) addr++ = bm[*off];
d5011762
AG
919 break;
920 case GDF_15BIT_555RGB:
921 case GDF_16BIT_565RGB:
922 /* differences handled while pre-calculating palette */
923 for (i = 0; i < cnt; i++) {
64e40d72 924 *(unsigned short *) addr = p[bm[*off]].ce.w;
d5011762
AG
925 addr += 2;
926 }
927 break;
928 case GDF_32BIT_X888RGB:
929 for (i = 0; i < cnt; i++) {
64e40d72 930 *(unsigned long *) addr = p[bm[*off]].ce.dw;
d5011762
AG
931 addr += 4;
932 }
933 break;
934 }
64e40d72 935 *fb = (uchar *) addr; /* return modified address */
d5011762
AG
936}
937
64e40d72
WD
938static int display_rle8_bitmap(bmp_image_t *img, int xoff, int yoff,
939 int width, int height)
d5011762
AG
940{
941 unsigned char *bm;
942 unsigned char *fbp;
943 unsigned int cnt, runlen;
944 int decode = 1;
945 int x, y, bpp, i, ncolors;
946 struct palette p[256];
947 bmp_color_table_entry_t cte;
948 int green_shift, red_off;
74446b63
AG
949 int limit = VIDEO_COLS * VIDEO_ROWS;
950 int pixels = 0;
d5011762
AG
951
952 x = 0;
953 y = __le32_to_cpu(img->header.height) - 1;
954 ncolors = __le32_to_cpu(img->header.colors_used);
955 bpp = VIDEO_PIXEL_SIZE;
64e40d72
WD
956 fbp = (unsigned char *) ((unsigned int) video_fb_address +
957 (((y + yoff) * VIDEO_COLS) + xoff) * bpp);
d5011762 958
64e40d72 959 bm = (uchar *) img + __le32_to_cpu(img->header.data_offset);
d5011762
AG
960
961 /* pre-calculate and setup palette */
962 switch (VIDEO_DATA_FORMAT) {
963 case GDF__8BIT_INDEX:
964 for (i = 0; i < ncolors; i++) {
965 cte = img->color_table[i];
64e40d72 966 video_set_lut(i, cte.red, cte.green, cte.blue);
d5011762
AG
967 }
968 break;
969 case GDF_15BIT_555RGB:
970 case GDF_16BIT_565RGB:
971 if (VIDEO_DATA_FORMAT == GDF_15BIT_555RGB) {
972 green_shift = 3;
973 red_off = 10;
974 } else {
975 green_shift = 2;
976 red_off = 11;
977 }
978 for (i = 0; i < ncolors; i++) {
979 cte = img->color_table[i];
980 p[i].ce.w = SWAP16((unsigned short)
981 (((cte.red >> 3) << red_off) |
982 ((cte.green >> green_shift) << 5) |
983 cte.blue >> 3));
984 }
985 break;
986 case GDF_32BIT_X888RGB:
987 for (i = 0; i < ncolors; i++) {
988 cte = img->color_table[i];
64e40d72
WD
989 p[i].ce.dw = SWAP32((cte.red << 16) |
990 (cte.green << 8) |
d5011762
AG
991 cte.blue);
992 }
993 break;
994 default:
995 printf("RLE Bitmap unsupported in video mode 0x%x\n",
64e40d72 996 VIDEO_DATA_FORMAT);
d5011762
AG
997 return -1;
998 }
999
1000 while (decode) {
1001 switch (bm[0]) {
1002 case 0:
1003 switch (bm[1]) {
1004 case 0:
1005 /* scan line end marker */
1006 bm += 2;
1007 x = 0;
1008 y--;
1009 fbp = (unsigned char *)
64e40d72 1010 ((unsigned int) video_fb_address +
d5011762
AG
1011 (((y + yoff) * VIDEO_COLS) +
1012 xoff) * bpp);
1013 continue;
1014 case 1:
1015 /* end of bitmap data marker */
1016 decode = 0;
1017 break;
1018 case 2:
1019 /* run offset marker */
1020 x += bm[2];
1021 y -= bm[3];
1022 fbp = (unsigned char *)
64e40d72 1023 ((unsigned int) video_fb_address +
d5011762
AG
1024 (((y + yoff) * VIDEO_COLS) +
1025 x + xoff) * bpp);
1026 bm += 4;
1027 break;
1028 default:
1029 /* unencoded run */
1030 cnt = bm[1];
1031 runlen = cnt;
74446b63
AG
1032 pixels += cnt;
1033 if (pixels > limit)
1034 goto error;
1035
d5011762
AG
1036 bm += 2;
1037 if (y < height) {
1038 if (x >= width) {
1039 x += runlen;
1040 goto next_run;
1041 }
1042 if (x + runlen > width)
1043 cnt = width - x;
64e40d72 1044 draw_bitmap(&fbp, bm, p, cnt, 0);
d5011762
AG
1045 x += runlen;
1046 }
1047next_run:
1048 bm += runlen;
1049 if (runlen & 1)
64e40d72 1050 bm++; /* 0 padding if length is odd */
d5011762
AG
1051 }
1052 break;
1053 default:
1054 /* encoded run */
74446b63
AG
1055 cnt = bm[0];
1056 runlen = cnt;
1057 pixels += cnt;
1058 if (pixels > limit)
1059 goto error;
1060
64e40d72 1061 if (y < height) { /* only draw into visible area */
d5011762
AG
1062 if (x >= width) {
1063 x += runlen;
1064 bm += 2;
1065 continue;
1066 }
1067 if (x + runlen > width)
1068 cnt = width - x;
64e40d72 1069 draw_bitmap(&fbp, bm, p, cnt, 1);
d5011762
AG
1070 x += runlen;
1071 }
1072 bm += 2;
1073 break;
1074 }
1075 }
1076 return 0;
74446b63
AG
1077error:
1078 printf("Error: Too much encoded pixel data, validate your bitmap\n");
1079 return -1;
d5011762
AG
1080}
1081#endif
1082
4b248f3f
WD
1083/*
1084 * Display the BMP file located at address bmp_image.
4b248f3f 1085 */
64e40d72 1086int video_display_bitmap(ulong bmp_image, int x, int y)
4b248f3f
WD
1087{
1088 ushort xcount, ycount;
1089 uchar *fb;
1090 bmp_image_t *bmp = (bmp_image_t *) bmp_image;
1091 uchar *bmap;
1092 ushort padded_line;
1093 unsigned long width, height, bpp;
1094 unsigned colors;
1095 unsigned long compression;
1096 bmp_color_table_entry_t cte;
64e40d72 1097
98f4a3df
SR
1098#ifdef CONFIG_VIDEO_BMP_GZIP
1099 unsigned char *dst = NULL;
1100 ulong len;
1101#endif
4b248f3f 1102
64e40d72 1103 WATCHDOG_RESET();
4b248f3f
WD
1104
1105 if (!((bmp->header.signature[0] == 'B') &&
1106 (bmp->header.signature[1] == 'M'))) {
98f4a3df
SR
1107
1108#ifdef CONFIG_VIDEO_BMP_GZIP
1109 /*
1110 * Could be a gzipped bmp image, try to decrompress...
1111 */
6d0f6bcf
JCPV
1112 len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
1113 dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
c29ab9d7
SR
1114 if (dst == NULL) {
1115 printf("Error: malloc in gunzip failed!\n");
64e40d72 1116 return 1;
c29ab9d7 1117 }
64e40d72
WD
1118 if (gunzip(dst, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE,
1119 (uchar *) bmp_image,
1120 &len) != 0) {
1121 printf("Error: no valid bmp or bmp.gz image at %lx\n",
1122 bmp_image);
98f4a3df
SR
1123 free(dst);
1124 return 1;
1125 }
6d0f6bcf 1126 if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) {
64e40d72
WD
1127 printf("Image could be truncated "
1128 "(increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
c29ab9d7 1129 }
98f4a3df
SR
1130
1131 /*
1132 * Set addr to decompressed image
1133 */
64e40d72 1134 bmp = (bmp_image_t *) dst;
98f4a3df
SR
1135
1136 if (!((bmp->header.signature[0] == 'B') &&
1137 (bmp->header.signature[1] == 'M'))) {
64e40d72
WD
1138 printf("Error: no valid bmp.gz image at %lx\n",
1139 bmp_image);
a49e0d17 1140 free(dst);
98f4a3df
SR
1141 return 1;
1142 }
1143#else
64e40d72 1144 printf("Error: no valid bmp image at %lx\n", bmp_image);
4b248f3f 1145 return 1;
98f4a3df 1146#endif /* CONFIG_VIDEO_BMP_GZIP */
4b248f3f
WD
1147 }
1148
64e40d72
WD
1149 width = le32_to_cpu(bmp->header.width);
1150 height = le32_to_cpu(bmp->header.height);
1151 bpp = le16_to_cpu(bmp->header.bit_count);
1152 colors = le32_to_cpu(bmp->header.colors_used);
1153 compression = le32_to_cpu(bmp->header.compression);
c609719b 1154
68da5b19 1155 debug("Display-bmp: %ld x %ld with %d colors\n",
64e40d72 1156 width, height, colors);
4b248f3f 1157
d5011762
AG
1158 if (compression != BMP_BI_RGB
1159#ifdef CONFIG_VIDEO_BMP_RLE8
1160 && compression != BMP_BI_RLE8
1161#endif
64e40d72
WD
1162 ) {
1163 printf("Error: compression type %ld not supported\n",
1164 compression);
a49e0d17
MF
1165#ifdef CONFIG_VIDEO_BMP_GZIP
1166 if (dst)
1167 free(dst);
1168#endif
4b248f3f
WD
1169 return 1;
1170 }
1171
1172 padded_line = (((width * bpp + 7) / 8) + 3) & ~0x3;
1173
1ca298ce
MW
1174#ifdef CONFIG_SPLASH_SCREEN_ALIGN
1175 if (x == BMP_ALIGN_CENTER)
1176 x = max(0, (VIDEO_VISIBLE_COLS - width) / 2);
1177 else if (x < 0)
1178 x = max(0, VIDEO_VISIBLE_COLS - width + x + 1);
1179
1180 if (y == BMP_ALIGN_CENTER)
1181 y = max(0, (VIDEO_VISIBLE_ROWS - height) / 2);
1182 else if (y < 0)
1183 y = max(0, VIDEO_VISIBLE_ROWS - height + y + 1);
1184#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
1185
4b248f3f
WD
1186 if ((x + width) > VIDEO_VISIBLE_COLS)
1187 width = VIDEO_VISIBLE_COLS - x;
1188 if ((y + height) > VIDEO_VISIBLE_ROWS)
1189 height = VIDEO_VISIBLE_ROWS - y;
1190
64e40d72 1191 bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset);
4b248f3f
WD
1192 fb = (uchar *) (video_fb_address +
1193 ((y + height - 1) * VIDEO_COLS * VIDEO_PIXEL_SIZE) +
1194 x * VIDEO_PIXEL_SIZE);
1195
d5011762
AG
1196#ifdef CONFIG_VIDEO_BMP_RLE8
1197 if (compression == BMP_BI_RLE8) {
64e40d72 1198 return display_rle8_bitmap(bmp, x, y, width, height);
d5011762
AG
1199 }
1200#endif
1201
68f6618b 1202 /* We handle only 4, 8, or 24 bpp bitmaps */
64e40d72 1203 switch (le16_to_cpu(bmp->header.bit_count)) {
68f6618b
TT
1204 case 4:
1205 padded_line -= width / 2;
1206 ycount = height;
1207
1208 switch (VIDEO_DATA_FORMAT) {
1209 case GDF_32BIT_X888RGB:
1210 while (ycount--) {
64e40d72 1211 WATCHDOG_RESET();
68f6618b
TT
1212 /*
1213 * Don't assume that 'width' is an
1214 * even number
1215 */
1216 for (xcount = 0; xcount < width; xcount++) {
1217 uchar idx;
1218
1219 if (xcount & 1) {
1220 idx = *bmap & 0xF;
1221 bmap++;
1222 } else
1223 idx = *bmap >> 4;
1224 cte = bmp->color_table[idx];
1225 FILL_32BIT_X888RGB(cte.red, cte.green,
1226 cte.blue);
1227 }
1228 bmap += padded_line;
1229 fb -= (VIDEO_VISIBLE_COLS + width) *
64e40d72 1230 VIDEO_PIXEL_SIZE;
68f6618b
TT
1231 }
1232 break;
1233 default:
1234 puts("4bpp bitmap unsupported with current "
1235 "video mode\n");
1236 break;
1237 }
1238 break;
1239
4b248f3f
WD
1240 case 8:
1241 padded_line -= width;
1242 if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
7c050f81 1243 /* Copy colormap */
4b248f3f
WD
1244 for (xcount = 0; xcount < colors; ++xcount) {
1245 cte = bmp->color_table[xcount];
64e40d72
WD
1246 video_set_lut(xcount, cte.red, cte.green,
1247 cte.blue);
4b248f3f
WD
1248 }
1249 }
1250 ycount = height;
1251 switch (VIDEO_DATA_FORMAT) {
1252 case GDF__8BIT_INDEX:
1253 while (ycount--) {
64e40d72 1254 WATCHDOG_RESET();
4b248f3f
WD
1255 xcount = width;
1256 while (xcount--) {
1257 *fb++ = *bmap++;
1258 }
1259 bmap += padded_line;
64e40d72
WD
1260 fb -= (VIDEO_VISIBLE_COLS + width) *
1261 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1262 }
1263 break;
1264 case GDF__8BIT_332RGB:
1265 while (ycount--) {
64e40d72 1266 WATCHDOG_RESET();
4b248f3f
WD
1267 xcount = width;
1268 while (xcount--) {
1269 cte = bmp->color_table[*bmap++];
64e40d72
WD
1270 FILL_8BIT_332RGB(cte.red, cte.green,
1271 cte.blue);
4b248f3f
WD
1272 }
1273 bmap += padded_line;
64e40d72
WD
1274 fb -= (VIDEO_VISIBLE_COLS + width) *
1275 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1276 }
1277 break;
1278 case GDF_15BIT_555RGB:
1279 while (ycount--) {
e84d568f
AG
1280#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1281 int xpos = x;
1282#endif
64e40d72 1283 WATCHDOG_RESET();
4b248f3f
WD
1284 xcount = width;
1285 while (xcount--) {
1286 cte = bmp->color_table[*bmap++];
cc347801 1287#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
64e40d72
WD
1288 fill_555rgb_pswap(fb, xpos++, cte.red,
1289 cte.green,
1290 cte.blue);
e84d568f 1291 fb += 2;
cc347801 1292#else
64e40d72
WD
1293 FILL_15BIT_555RGB(cte.red, cte.green,
1294 cte.blue);
e84d568f 1295#endif
4b248f3f
WD
1296 }
1297 bmap += padded_line;
64e40d72
WD
1298 fb -= (VIDEO_VISIBLE_COLS + width) *
1299 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1300 }
1301 break;
1302 case GDF_16BIT_565RGB:
1303 while (ycount--) {
64e40d72 1304 WATCHDOG_RESET();
4b248f3f
WD
1305 xcount = width;
1306 while (xcount--) {
1307 cte = bmp->color_table[*bmap++];
64e40d72
WD
1308 FILL_16BIT_565RGB(cte.red, cte.green,
1309 cte.blue);
4b248f3f
WD
1310 }
1311 bmap += padded_line;
64e40d72
WD
1312 fb -= (VIDEO_VISIBLE_COLS + width) *
1313 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1314 }
1315 break;
1316 case GDF_32BIT_X888RGB:
1317 while (ycount--) {
64e40d72 1318 WATCHDOG_RESET();
4b248f3f
WD
1319 xcount = width;
1320 while (xcount--) {
1321 cte = bmp->color_table[*bmap++];
64e40d72
WD
1322 FILL_32BIT_X888RGB(cte.red, cte.green,
1323 cte.blue);
4b248f3f
WD
1324 }
1325 bmap += padded_line;
64e40d72
WD
1326 fb -= (VIDEO_VISIBLE_COLS + width) *
1327 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1328 }
1329 break;
1330 case GDF_24BIT_888RGB:
1331 while (ycount--) {
64e40d72 1332 WATCHDOG_RESET();
4b248f3f
WD
1333 xcount = width;
1334 while (xcount--) {
1335 cte = bmp->color_table[*bmap++];
64e40d72
WD
1336 FILL_24BIT_888RGB(cte.red, cte.green,
1337 cte.blue);
4b248f3f
WD
1338 }
1339 bmap += padded_line;
64e40d72
WD
1340 fb -= (VIDEO_VISIBLE_COLS + width) *
1341 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1342 }
1343 break;
1344 }
1345 break;
1346 case 24:
1347 padded_line -= 3 * width;
1348 ycount = height;
1349 switch (VIDEO_DATA_FORMAT) {
1350 case GDF__8BIT_332RGB:
1351 while (ycount--) {
64e40d72 1352 WATCHDOG_RESET();
4b248f3f
WD
1353 xcount = width;
1354 while (xcount--) {
64e40d72
WD
1355 FILL_8BIT_332RGB(bmap[2], bmap[1],
1356 bmap[0]);
4b248f3f
WD
1357 bmap += 3;
1358 }
1359 bmap += padded_line;
64e40d72
WD
1360 fb -= (VIDEO_VISIBLE_COLS + width) *
1361 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1362 }
1363 break;
1364 case GDF_15BIT_555RGB:
1365 while (ycount--) {
e84d568f
AG
1366#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1367 int xpos = x;
1368#endif
64e40d72 1369 WATCHDOG_RESET();
4b248f3f
WD
1370 xcount = width;
1371 while (xcount--) {
cc347801 1372#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
64e40d72
WD
1373 fill_555rgb_pswap(fb, xpos++, bmap[2],
1374 bmap[1], bmap[0]);
e84d568f 1375 fb += 2;
cc347801 1376#else
64e40d72
WD
1377 FILL_15BIT_555RGB(bmap[2], bmap[1],
1378 bmap[0]);
e84d568f 1379#endif
4b248f3f
WD
1380 bmap += 3;
1381 }
1382 bmap += padded_line;
64e40d72
WD
1383 fb -= (VIDEO_VISIBLE_COLS + width) *
1384 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1385 }
1386 break;
1387 case GDF_16BIT_565RGB:
1388 while (ycount--) {
64e40d72 1389 WATCHDOG_RESET();
4b248f3f
WD
1390 xcount = width;
1391 while (xcount--) {
64e40d72
WD
1392 FILL_16BIT_565RGB(bmap[2], bmap[1],
1393 bmap[0]);
4b248f3f
WD
1394 bmap += 3;
1395 }
1396 bmap += padded_line;
64e40d72
WD
1397 fb -= (VIDEO_VISIBLE_COLS + width) *
1398 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1399 }
1400 break;
1401 case GDF_32BIT_X888RGB:
1402 while (ycount--) {
64e40d72 1403 WATCHDOG_RESET();
4b248f3f
WD
1404 xcount = width;
1405 while (xcount--) {
64e40d72
WD
1406 FILL_32BIT_X888RGB(bmap[2], bmap[1],
1407 bmap[0]);
4b248f3f
WD
1408 bmap += 3;
1409 }
1410 bmap += padded_line;
64e40d72
WD
1411 fb -= (VIDEO_VISIBLE_COLS + width) *
1412 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1413 }
1414 break;
1415 case GDF_24BIT_888RGB:
1416 while (ycount--) {
64e40d72 1417 WATCHDOG_RESET();
4b248f3f
WD
1418 xcount = width;
1419 while (xcount--) {
64e40d72
WD
1420 FILL_24BIT_888RGB(bmap[2], bmap[1],
1421 bmap[0]);
4b248f3f
WD
1422 bmap += 3;
1423 }
1424 bmap += padded_line;
64e40d72
WD
1425 fb -= (VIDEO_VISIBLE_COLS + width) *
1426 VIDEO_PIXEL_SIZE;
4b248f3f
WD
1427 }
1428 break;
1429 default:
64e40d72
WD
1430 printf("Error: 24 bits/pixel bitmap incompatible "
1431 "with current video mode\n");
4b248f3f
WD
1432 break;
1433 }
1434 break;
1435 default:
64e40d72
WD
1436 printf("Error: %d bit/pixel bitmaps not supported by U-Boot\n",
1437 le16_to_cpu(bmp->header.bit_count));
4b248f3f
WD
1438 break;
1439 }
98f4a3df
SR
1440
1441#ifdef CONFIG_VIDEO_BMP_GZIP
1442 if (dst) {
1443 free(dst);
1444 }
1445#endif
1446
4b248f3f 1447 return (0);
c609719b 1448}
07d38a17 1449#endif
c609719b 1450
c609719b
WD
1451
1452#ifdef CONFIG_VIDEO_LOGO
64e40d72 1453void logo_plot(void *screen, int width, int x, int y)
c609719b 1454{
a6c7ad2f 1455
4b248f3f 1456 int xcount, i;
64e40d72 1457 int skip = (width - VIDEO_LOGO_WIDTH) * VIDEO_PIXEL_SIZE;
be129aa7 1458 int ycount = video_logo_height;
4b248f3f
WD
1459 unsigned char r, g, b, *logo_red, *logo_blue, *logo_green;
1460 unsigned char *source;
64e40d72
WD
1461 unsigned char *dest = (unsigned char *) screen +
1462 ((y * width * VIDEO_PIXEL_SIZE) + x * VIDEO_PIXEL_SIZE);
a6c7ad2f
WD
1463
1464#ifdef CONFIG_VIDEO_BMP_LOGO
4b248f3f
WD
1465 source = bmp_logo_bitmap;
1466
7c050f81 1467 /* Allocate temporary space for computing colormap */
64e40d72
WD
1468 logo_red = malloc(BMP_LOGO_COLORS);
1469 logo_green = malloc(BMP_LOGO_COLORS);
1470 logo_blue = malloc(BMP_LOGO_COLORS);
7c050f81 1471 /* Compute color map */
4b248f3f
WD
1472 for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
1473 logo_red[i] = (bmp_logo_palette[i] & 0x0f00) >> 4;
1474 logo_green[i] = (bmp_logo_palette[i] & 0x00f0);
1475 logo_blue[i] = (bmp_logo_palette[i] & 0x000f) << 4;
1476 }
a6c7ad2f 1477#else
4b248f3f
WD
1478 source = linux_logo;
1479 logo_red = linux_logo_red;
1480 logo_green = linux_logo_green;
1481 logo_blue = linux_logo_blue;
a6c7ad2f 1482#endif
8bde7f77 1483
4b248f3f
WD
1484 if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) {
1485 for (i = 0; i < VIDEO_LOGO_COLORS; i++) {
64e40d72
WD
1486 video_set_lut(i + VIDEO_LOGO_LUT_OFFSET,
1487 logo_red[i], logo_green[i],
1488 logo_blue[i]);
4b248f3f 1489 }
8bde7f77 1490 }
c609719b 1491
4b248f3f 1492 while (ycount--) {
e84d568f
AG
1493#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
1494 int xpos = x;
1495#endif
4b248f3f
WD
1496 xcount = VIDEO_LOGO_WIDTH;
1497 while (xcount--) {
1498 r = logo_red[*source - VIDEO_LOGO_LUT_OFFSET];
1499 g = logo_green[*source - VIDEO_LOGO_LUT_OFFSET];
1500 b = logo_blue[*source - VIDEO_LOGO_LUT_OFFSET];
1501
1502 switch (VIDEO_DATA_FORMAT) {
1503 case GDF__8BIT_INDEX:
1504 *dest = *source;
1505 break;
1506 case GDF__8BIT_332RGB:
64e40d72
WD
1507 *dest = ((r >> 5) << 5) |
1508 ((g >> 5) << 2) |
1509 (b >> 6);
4b248f3f
WD
1510 break;
1511 case GDF_15BIT_555RGB:
cc347801 1512#if defined(VIDEO_FB_16BPP_PIXEL_SWAP)
64e40d72 1513 fill_555rgb_pswap(dest, xpos++, r, g, b);
cc347801 1514#else
4b248f3f 1515 *(unsigned short *) dest =
64e40d72
WD
1516 SWAP16((unsigned short) (
1517 ((r >> 3) << 10) |
1518 ((g >> 3) << 5) |
1519 (b >> 3)));
bed53753 1520#endif
4b248f3f
WD
1521 break;
1522 case GDF_16BIT_565RGB:
1523 *(unsigned short *) dest =
64e40d72
WD
1524 SWAP16((unsigned short) (
1525 ((r >> 3) << 11) |
1526 ((g >> 2) << 5) |
1527 (b >> 3)));
4b248f3f
WD
1528 break;
1529 case GDF_32BIT_X888RGB:
1530 *(unsigned long *) dest =
64e40d72
WD
1531 SWAP32((unsigned long) (
1532 (r << 16) |
1533 (g << 8) |
1534 b));
4b248f3f
WD
1535 break;
1536 case GDF_24BIT_888RGB:
c609719b 1537#ifdef VIDEO_FB_LITTLE_ENDIAN
4b248f3f
WD
1538 dest[0] = b;
1539 dest[1] = g;
1540 dest[2] = r;
c609719b 1541#else
4b248f3f
WD
1542 dest[0] = r;
1543 dest[1] = g;
1544 dest[2] = b;
c609719b 1545#endif
4b248f3f
WD
1546 break;
1547 }
1548 source++;
1549 dest += VIDEO_PIXEL_SIZE;
1550 }
1551 dest += skip;
8bde7f77 1552 }
a6c7ad2f 1553#ifdef CONFIG_VIDEO_BMP_LOGO
64e40d72
WD
1554 free(logo_red);
1555 free(logo_green);
1556 free(logo_blue);
a6c7ad2f 1557#endif
c609719b
WD
1558}
1559
64e40d72 1560static void *video_logo(void)
c609719b 1561{
4b248f3f 1562 char info[128];
3dcbe628 1563 int space, len, y_off = 0;
4b248f3f
WD
1564
1565#ifdef CONFIG_SPLASH_SCREEN
1566 char *s;
1567 ulong addr;
1568
57912939
WD
1569 s = getenv("splashimage");
1570 if (s != NULL) {
1ca298ce
MW
1571 int x = 0, y = 0;
1572
64e40d72 1573 addr = simple_strtoul(s, NULL, 16);
1ca298ce 1574#ifdef CONFIG_SPLASH_SCREEN_ALIGN
57912939
WD
1575 s = getenv("splashpos");
1576 if (s != NULL) {
1ca298ce
MW
1577 if (s[0] == 'm')
1578 x = BMP_ALIGN_CENTER;
1579 else
64e40d72 1580 x = simple_strtol(s, NULL, 0);
1ca298ce 1581
57912939
WD
1582 s = strchr(s + 1, ',');
1583 if (s != NULL) {
1ca298ce
MW
1584 if (s[1] == 'm')
1585 y = BMP_ALIGN_CENTER;
1586 else
64e40d72 1587 y = simple_strtol(s + 1, NULL, 0);
1ca298ce
MW
1588 }
1589 }
1590#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
4b248f3f 1591
64e40d72 1592 if (video_display_bitmap(addr, x, y) == 0) {
be129aa7 1593 video_logo_height = 0;
4b248f3f
WD
1594 return ((void *) (video_fb_address));
1595 }
1596 }
1597#endif /* CONFIG_SPLASH_SCREEN */
c609719b 1598
64e40d72 1599 logo_plot(video_fb_address, VIDEO_COLS, 0, 0);
4b248f3f 1600
64e40d72 1601 sprintf(info, " %s", version_string);
3dcbe628
AG
1602
1603 space = (VIDEO_LINE_LEN / 2 - VIDEO_INFO_X) / VIDEO_FONT_WIDTH;
1604 len = strlen(info);
1605
1606 if (len > space) {
64e40d72
WD
1607 video_drawchars(VIDEO_INFO_X, VIDEO_INFO_Y,
1608 (uchar *) info, space);
1609 video_drawchars(VIDEO_INFO_X + VIDEO_FONT_WIDTH,
1610 VIDEO_INFO_Y + VIDEO_FONT_HEIGHT,
1611 (uchar *) info + space, len - space);
3dcbe628
AG
1612 y_off = 1;
1613 } else
64e40d72 1614 video_drawstring(VIDEO_INFO_X, VIDEO_INFO_Y, (uchar *) info);
c609719b
WD
1615
1616#ifdef CONFIG_CONSOLE_EXTRA_INFO
4b248f3f 1617 {
64e40d72
WD
1618 int i, n =
1619 ((video_logo_height -
1620 VIDEO_FONT_HEIGHT) / VIDEO_FONT_HEIGHT);
4b248f3f
WD
1621
1622 for (i = 1; i < n; i++) {
64e40d72 1623 video_get_info_str(i, info);
3dcbe628
AG
1624 if (!*info)
1625 continue;
1626
1627 len = strlen(info);
1628 if (len > space) {
64e40d72
WD
1629 video_drawchars(VIDEO_INFO_X,
1630 VIDEO_INFO_Y +
1631 (i + y_off) *
1632 VIDEO_FONT_HEIGHT,
1633 (uchar *) info, space);
3dcbe628 1634 y_off++;
64e40d72
WD
1635 video_drawchars(VIDEO_INFO_X +
1636 VIDEO_FONT_WIDTH,
1637 VIDEO_INFO_Y +
1638 (i + y_off) *
1639 VIDEO_FONT_HEIGHT,
1640 (uchar *) info + space,
1641 len - space);
3dcbe628 1642 } else {
64e40d72
WD
1643 video_drawstring(VIDEO_INFO_X,
1644 VIDEO_INFO_Y +
1645 (i + y_off) *
1646 VIDEO_FONT_HEIGHT,
1647 (uchar *) info);
3dcbe628 1648 }
4b248f3f
WD
1649 }
1650 }
c609719b
WD
1651#endif
1652
be129aa7 1653 return (video_fb_address + video_logo_height * VIDEO_LINE_LEN);
c609719b
WD
1654}
1655#endif
1656
64e40d72 1657static int video_init(void)
c609719b 1658{
4b248f3f 1659 unsigned char color8;
c609719b 1660
57912939
WD
1661 pGD = video_hw_init();
1662 if (pGD == NULL)
4b248f3f 1663 return -1;
c609719b 1664
4b248f3f 1665 video_fb_address = (void *) VIDEO_FB_ADRS;
c609719b 1666#ifdef CONFIG_VIDEO_HW_CURSOR
64e40d72 1667 video_init_hw_cursor(VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT);
c609719b
WD
1668#endif
1669
4b248f3f
WD
1670 /* Init drawing pats */
1671 switch (VIDEO_DATA_FORMAT) {
1672 case GDF__8BIT_INDEX:
64e40d72
WD
1673 video_set_lut(0x01, CONSOLE_FG_COL, CONSOLE_FG_COL,
1674 CONSOLE_FG_COL);
1675 video_set_lut(0x00, CONSOLE_BG_COL, CONSOLE_BG_COL,
1676 CONSOLE_BG_COL);
4b248f3f
WD
1677 fgx = 0x01010101;
1678 bgx = 0x00000000;
1679 break;
1680 case GDF__8BIT_332RGB:
1681 color8 = ((CONSOLE_FG_COL & 0xe0) |
64e40d72
WD
1682 ((CONSOLE_FG_COL >> 3) & 0x1c) |
1683 CONSOLE_FG_COL >> 6);
1684 fgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
1685 color8;
4b248f3f 1686 color8 = ((CONSOLE_BG_COL & 0xe0) |
64e40d72
WD
1687 ((CONSOLE_BG_COL >> 3) & 0x1c) |
1688 CONSOLE_BG_COL >> 6);
1689 bgx = (color8 << 24) | (color8 << 16) | (color8 << 8) |
1690 color8;
4b248f3f
WD
1691 break;
1692 case GDF_15BIT_555RGB:
1693 fgx = (((CONSOLE_FG_COL >> 3) << 26) |
64e40d72
WD
1694 ((CONSOLE_FG_COL >> 3) << 21) |
1695 ((CONSOLE_FG_COL >> 3) << 16) |
1696 ((CONSOLE_FG_COL >> 3) << 10) |
1697 ((CONSOLE_FG_COL >> 3) << 5) |
1698 (CONSOLE_FG_COL >> 3));
4b248f3f 1699 bgx = (((CONSOLE_BG_COL >> 3) << 26) |
64e40d72
WD
1700 ((CONSOLE_BG_COL >> 3) << 21) |
1701 ((CONSOLE_BG_COL >> 3) << 16) |
1702 ((CONSOLE_BG_COL >> 3) << 10) |
1703 ((CONSOLE_BG_COL >> 3) << 5) |
1704 (CONSOLE_BG_COL >> 3));
4b248f3f
WD
1705 break;
1706 case GDF_16BIT_565RGB:
1707 fgx = (((CONSOLE_FG_COL >> 3) << 27) |
64e40d72
WD
1708 ((CONSOLE_FG_COL >> 2) << 21) |
1709 ((CONSOLE_FG_COL >> 3) << 16) |
1710 ((CONSOLE_FG_COL >> 3) << 11) |
1711 ((CONSOLE_FG_COL >> 2) << 5) |
1712 (CONSOLE_FG_COL >> 3));
4b248f3f 1713 bgx = (((CONSOLE_BG_COL >> 3) << 27) |
64e40d72
WD
1714 ((CONSOLE_BG_COL >> 2) << 21) |
1715 ((CONSOLE_BG_COL >> 3) << 16) |
1716 ((CONSOLE_BG_COL >> 3) << 11) |
1717 ((CONSOLE_BG_COL >> 2) << 5) |
1718 (CONSOLE_BG_COL >> 3));
4b248f3f
WD
1719 break;
1720 case GDF_32BIT_X888RGB:
64e40d72
WD
1721 fgx = (CONSOLE_FG_COL << 16) |
1722 (CONSOLE_FG_COL << 8) |
1723 CONSOLE_FG_COL;
1724 bgx = (CONSOLE_BG_COL << 16) |
1725 (CONSOLE_BG_COL << 8) |
1726 CONSOLE_BG_COL;
4b248f3f
WD
1727 break;
1728 case GDF_24BIT_888RGB:
64e40d72
WD
1729 fgx = (CONSOLE_FG_COL << 24) |
1730 (CONSOLE_FG_COL << 16) |
1731 (CONSOLE_FG_COL << 8) |
1732 CONSOLE_FG_COL;
1733 bgx = (CONSOLE_BG_COL << 24) |
1734 (CONSOLE_BG_COL << 16) |
1735 (CONSOLE_BG_COL << 8) |
1736 CONSOLE_BG_COL;
4b248f3f
WD
1737 break;
1738 }
1739 eorx = fgx ^ bgx;
c609719b
WD
1740
1741#ifdef CONFIG_VIDEO_LOGO
4b248f3f 1742 /* Plot the logo and get start point of console */
72c65f6f 1743 debug("Video: Drawing the logo ...\n");
64e40d72 1744 video_console_address = video_logo();
c609719b 1745#else
4b248f3f 1746 video_console_address = video_fb_address;
c609719b
WD
1747#endif
1748
4b248f3f
WD
1749 /* Initialize the console */
1750 console_col = 0;
1751 console_row = 0;
c609719b 1752
4b248f3f 1753 return 0;
c609719b
WD
1754}
1755
6cc7ba9e
WD
1756/*
1757 * Implement a weak default function for boards that optionally
1758 * need to skip the video initialization.
1759 */
1760int __board_video_skip(void)
1761{
1762 /* As default, don't skip test */
1763 return 0;
1764}
6cc7ba9e 1765
64e40d72
WD
1766int board_video_skip(void)
1767 __attribute__ ((weak, alias("__board_video_skip")));
1768
1769int drv_video_init(void)
c609719b 1770{
4b248f3f 1771 int skip_dev_init;
52cb4d4f 1772 struct stdio_dev console_dev;
c609719b 1773
6cc7ba9e
WD
1774 /* Check if video initialization should be skipped */
1775 if (board_video_skip())
1776 return 0;
1777
81050926 1778 /* Init video chip - returns with framebuffer cleared */
64e40d72 1779 skip_dev_init = (video_init() == -1);
81050926 1780
f62f6469 1781#if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
72c65f6f 1782 debug("KBD: Keyboard init ...\n");
f62f6469
WD
1783 skip_dev_init |= (VIDEO_KBD_INIT_FCT == -1);
1784#endif
1785
1786 if (skip_dev_init)
1787 return 0;
1788
1789 /* Init vga device */
64e40d72
WD
1790 memset(&console_dev, 0, sizeof(console_dev));
1791 strcpy(console_dev.name, "vga");
f62f6469
WD
1792 console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */
1793 console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
1794 console_dev.putc = video_putc; /* 'putc' function */
1795 console_dev.puts = video_puts; /* 'puts' function */
1796 console_dev.tstc = NULL; /* 'tstc' function */
1797 console_dev.getc = NULL; /* 'getc' function */
1798
1799#if !defined(CONFIG_VGA_AS_SINGLE_DEVICE)
1800 /* Also init console device */
1801 console_dev.flags |= DEV_FLAGS_INPUT;
1802 console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */
1803 console_dev.getc = VIDEO_GETC_FCT; /* 'getc' function */
c609719b 1804#endif /* CONFIG_VGA_AS_SINGLE_DEVICE */
f62f6469 1805
64e40d72 1806 if (stdio_register(&console_dev) != 0)
f62f6469
WD
1807 return 0;
1808
1809 /* Return success */
1810 return 1;
c609719b 1811}