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