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