uboot/common/lcd.c
<<
>>
Prefs
   1/*
   2 * Common LCD routines for supported CPUs
   3 *
   4 * (C) Copyright 2001-2002
   5 * Wolfgang Denk, DENX Software Engineering -- wd@denx.de
   6 *
   7 * See file CREDITS for list of people who contributed to this
   8 * project.
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public License as
  12 * published by the Free Software Foundation; either version 2 of
  13 * the License, or (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23 * MA 02111-1307 USA
  24 */
  25
  26/************************************************************************/
  27/* ** HEADER FILES                                                      */
  28/************************************************************************/
  29
  30/* #define DEBUG */
  31
  32#include <config.h>
  33#include <common.h>
  34#include <command.h>
  35#include <stdarg.h>
  36#include <linux/types.h>
  37#include <stdio_dev.h>
  38#if defined(CONFIG_POST)
  39#include <post.h>
  40#endif
  41#include <lcd.h>
  42#include <watchdog.h>
  43
  44#if defined(CONFIG_CPU_PXA25X) || defined(CONFIG_CPU_PXA27X) || \
  45        defined(CONFIG_CPU_MONAHANS)
  46#define CONFIG_CPU_PXA
  47#include <asm/byteorder.h>
  48#endif
  49
  50#if defined(CONFIG_MPC823)
  51#include <lcdvideo.h>
  52#endif
  53
  54#if defined(CONFIG_ATMEL_LCD)
  55#include <atmel_lcdc.h>
  56#endif
  57
  58/************************************************************************/
  59/* ** FONT DATA                                                         */
  60/************************************************************************/
  61#include <video_font.h>         /* Get font data, width and height      */
  62#include <video_font_data.h>
  63
  64/************************************************************************/
  65/* ** LOGO DATA                                                         */
  66/************************************************************************/
  67#ifdef CONFIG_LCD_LOGO
  68# include <bmp_logo.h>          /* Get logo data, width and height      */
  69# include <bmp_logo_data.h>
  70# if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET) && (LCD_BPP != LCD_COLOR16)
  71#  error Default Color Map overlaps with Logo Color Map
  72# endif
  73#endif
  74
  75DECLARE_GLOBAL_DATA_PTR;
  76
  77ulong lcd_setmem (ulong addr);
  78
  79static void lcd_drawchars(ushort x, ushort y, uchar *str, int count);
  80static inline void lcd_puts_xy(ushort x, ushort y, uchar *s);
  81static inline void lcd_putc_xy(ushort x, ushort y, uchar  c);
  82
  83static int lcd_init(void *lcdbase);
  84
  85static void *lcd_logo (void);
  86
  87static int lcd_getbgcolor(void);
  88static void lcd_setfgcolor(int color);
  89static void lcd_setbgcolor(int color);
  90
  91char lcd_is_enabled = 0;
  92
  93#ifdef  NOT_USED_SO_FAR
  94static void lcd_getcolreg(ushort regno,
  95                                ushort *red, ushort *green, ushort *blue);
  96static int lcd_getfgcolor(void);
  97#endif  /* NOT_USED_SO_FAR */
  98
  99/************************************************************************/
 100
 101/*----------------------------------------------------------------------*/
 102
 103static void console_scrollup(void)
 104{
 105        /* Copy up rows ignoring the first one */
 106        memcpy(CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE);
 107
 108        /* Clear the last one */
 109        memset(CONSOLE_ROW_LAST, COLOR_MASK(lcd_color_bg), CONSOLE_ROW_SIZE);
 110}
 111
 112/*----------------------------------------------------------------------*/
 113
 114static inline void console_back(void)
 115{
 116        if (--console_col < 0) {
 117                console_col = CONSOLE_COLS-1 ;
 118                if (--console_row < 0) {
 119                        console_row = 0;
 120                }
 121        }
 122
 123        lcd_putc_xy(console_col * VIDEO_FONT_WIDTH,
 124                console_row * VIDEO_FONT_HEIGHT, ' ');
 125}
 126
 127/*----------------------------------------------------------------------*/
 128
 129static inline void console_newline(void)
 130{
 131        ++console_row;
 132        console_col = 0;
 133
 134        /* Check if we need to scroll the terminal */
 135        if (console_row >= CONSOLE_ROWS) {
 136                /* Scroll everything up */
 137                console_scrollup();
 138                --console_row;
 139        }
 140}
 141
 142/*----------------------------------------------------------------------*/
 143
 144void lcd_putc(const char c)
 145{
 146        if (!lcd_is_enabled) {
 147                serial_putc(c);
 148
 149                return;
 150        }
 151
 152        switch (c) {
 153        case '\r':
 154                console_col = 0;
 155
 156                return;
 157        case '\n':
 158                console_newline();
 159
 160                return;
 161        case '\t':      /* Tab (8 chars alignment) */
 162                console_col +=  8;
 163                console_col &= ~7;
 164
 165                if (console_col >= CONSOLE_COLS)
 166                        console_newline();
 167
 168                return;
 169        case '\b':
 170                console_back();
 171
 172                return;
 173        default:
 174                lcd_putc_xy(console_col * VIDEO_FONT_WIDTH,
 175                        console_row * VIDEO_FONT_HEIGHT, c);
 176                if (++console_col >= CONSOLE_COLS)
 177                        console_newline();
 178        }
 179}
 180
 181/*----------------------------------------------------------------------*/
 182
 183void lcd_puts(const char *s)
 184{
 185        if (!lcd_is_enabled) {
 186                serial_puts(s);
 187
 188                return;
 189        }
 190
 191        while (*s) {
 192                lcd_putc(*s++);
 193        }
 194}
 195
 196/*----------------------------------------------------------------------*/
 197
 198void lcd_printf(const char *fmt, ...)
 199{
 200        va_list args;
 201        char buf[CONFIG_SYS_PBSIZE];
 202
 203        va_start(args, fmt);
 204        vsprintf(buf, fmt, args);
 205        va_end(args);
 206
 207        lcd_puts(buf);
 208}
 209
 210/************************************************************************/
 211/* ** Low-Level Graphics Routines                                       */
 212/************************************************************************/
 213
 214static void lcd_drawchars(ushort x, ushort y, uchar *str, int count)
 215{
 216        uchar *dest;
 217        ushort row;
 218
 219#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
 220        y += BMP_LOGO_HEIGHT;
 221#endif
 222
 223#if LCD_BPP == LCD_MONOCHROME
 224        ushort off  = x * (1 << LCD_BPP) % 8;
 225#endif
 226
 227        dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / 8);
 228
 229        for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
 230                uchar *s = str;
 231                int i;
 232#if LCD_BPP == LCD_COLOR16
 233                ushort *d = (ushort *)dest;
 234#else
 235                uchar *d = dest;
 236#endif
 237
 238#if LCD_BPP == LCD_MONOCHROME
 239                uchar rest = *d & -(1 << (8-off));
 240                uchar sym;
 241#endif
 242                for (i = 0; i < count; ++i) {
 243                        uchar c, bits;
 244
 245                        c = *s++;
 246                        bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
 247
 248#if LCD_BPP == LCD_MONOCHROME
 249                        sym  = (COLOR_MASK(lcd_color_fg) & bits) |
 250                                (COLOR_MASK(lcd_color_bg) & ~bits);
 251
 252                        *d++ = rest | (sym >> off);
 253                        rest = sym << (8-off);
 254#elif LCD_BPP == LCD_COLOR8
 255                        for (c = 0; c < 8; ++c) {
 256                                *d++ = (bits & 0x80) ?
 257                                                lcd_color_fg : lcd_color_bg;
 258                                bits <<= 1;
 259                        }
 260#elif LCD_BPP == LCD_COLOR16
 261                        for (c = 0; c < 8; ++c) {
 262                                *d++ = (bits & 0x80) ?
 263                                                lcd_color_fg : lcd_color_bg;
 264                                bits <<= 1;
 265                        }
 266#endif
 267                }
 268#if LCD_BPP == LCD_MONOCHROME
 269                *d  = rest | (*d & ((1 << (8-off)) - 1));
 270#endif
 271        }
 272}
 273
 274/*----------------------------------------------------------------------*/
 275
 276static inline void lcd_puts_xy(ushort x, ushort y, uchar *s)
 277{
 278        lcd_drawchars(x, y, s, strlen((char *)s));
 279}
 280
 281/*----------------------------------------------------------------------*/
 282
 283static inline void lcd_putc_xy(ushort x, ushort y, uchar c)
 284{
 285        lcd_drawchars(x, y, &c, 1);
 286}
 287
 288/************************************************************************/
 289/**  Small utility to check that you got the colours right              */
 290/************************************************************************/
 291#ifdef LCD_TEST_PATTERN
 292
 293#define N_BLK_VERT      2
 294#define N_BLK_HOR       3
 295
 296static int test_colors[N_BLK_HOR*N_BLK_VERT] = {
 297        CONSOLE_COLOR_RED,      CONSOLE_COLOR_GREEN,    CONSOLE_COLOR_YELLOW,
 298        CONSOLE_COLOR_BLUE,     CONSOLE_COLOR_MAGENTA,  CONSOLE_COLOR_CYAN,
 299};
 300
 301static void test_pattern(void)
 302{
 303        ushort v_max  = panel_info.vl_row;
 304        ushort h_max  = panel_info.vl_col;
 305        ushort v_step = (v_max + N_BLK_VERT - 1) / N_BLK_VERT;
 306        ushort h_step = (h_max + N_BLK_HOR  - 1) / N_BLK_HOR;
 307        ushort v, h;
 308        uchar *pix = (uchar *)lcd_base;
 309
 310        printf("[LCD] Test Pattern: %d x %d [%d x %d]\n",
 311                h_max, v_max, h_step, v_step);
 312
 313        /* WARNING: Code silently assumes 8bit/pixel */
 314        for (v = 0; v < v_max; ++v) {
 315                uchar iy = v / v_step;
 316                for (h = 0; h < h_max; ++h) {
 317                        uchar ix = N_BLK_HOR * iy + (h/h_step);
 318                        *pix++ = test_colors[ix];
 319                }
 320        }
 321}
 322#endif /* LCD_TEST_PATTERN */
 323
 324
 325/************************************************************************/
 326/* ** GENERIC Initialization Routines                                   */
 327/************************************************************************/
 328
 329int drv_lcd_init (void)
 330{
 331        struct stdio_dev lcddev;
 332        int rc;
 333
 334        lcd_base = (void *)(gd->fb_base);
 335
 336        lcd_line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8;
 337
 338        lcd_init(lcd_base);             /* LCD initialization */
 339
 340        /* Device initialization */
 341        memset(&lcddev, 0, sizeof(lcddev));
 342
 343        strcpy(lcddev.name, "lcd");
 344        lcddev.ext   = 0;                       /* No extensions */
 345        lcddev.flags = DEV_FLAGS_OUTPUT;        /* Output only */
 346        lcddev.putc  = lcd_putc;                /* 'putc' function */
 347        lcddev.puts  = lcd_puts;                /* 'puts' function */
 348
 349        rc = stdio_register (&lcddev);
 350
 351        return (rc == 0) ? 1 : rc;
 352}
 353
 354/*----------------------------------------------------------------------*/
 355static
 356int do_lcd_clear(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 357{
 358        lcd_clear();
 359        return 0;
 360}
 361
 362void lcd_clear(void)
 363{
 364#if LCD_BPP == LCD_MONOCHROME
 365        /* Setting the palette */
 366        lcd_initcolregs();
 367
 368#elif LCD_BPP == LCD_COLOR8
 369        /* Setting the palette */
 370        lcd_setcolreg(CONSOLE_COLOR_BLACK, 0, 0, 0);
 371        lcd_setcolreg(CONSOLE_COLOR_RED, 0xFF, 0, 0);
 372        lcd_setcolreg(CONSOLE_COLOR_GREEN, 0, 0xFF, 0);
 373        lcd_setcolreg(CONSOLE_COLOR_YELLOW, 0xFF, 0xFF, 0);
 374        lcd_setcolreg(CONSOLE_COLOR_BLUE, 0, 0, 0xFF);
 375        lcd_setcolreg(CONSOLE_COLOR_MAGENTA, 0xFF, 0, 0xFF);
 376        lcd_setcolreg(CONSOLE_COLOR_CYAN, 0, 0xFF, 0xFF);
 377        lcd_setcolreg(CONSOLE_COLOR_GREY, 0xAA, 0xAA, 0xAA);
 378        lcd_setcolreg(CONSOLE_COLOR_WHITE, 0xFF, 0xFF, 0xFF);
 379#endif
 380
 381#ifndef CONFIG_SYS_WHITE_ON_BLACK
 382        lcd_setfgcolor(CONSOLE_COLOR_BLACK);
 383        lcd_setbgcolor(CONSOLE_COLOR_WHITE);
 384#else
 385        lcd_setfgcolor(CONSOLE_COLOR_WHITE);
 386        lcd_setbgcolor(CONSOLE_COLOR_BLACK);
 387#endif  /* CONFIG_SYS_WHITE_ON_BLACK */
 388
 389#ifdef  LCD_TEST_PATTERN
 390        test_pattern();
 391#else
 392        /* set framebuffer to background color */
 393        memset((char *)lcd_base,
 394                COLOR_MASK(lcd_getbgcolor()),
 395                lcd_line_length*panel_info.vl_row);
 396#endif
 397        /* Paint the logo and retrieve LCD base address */
 398        debug("[LCD] Drawing the logo...\n");
 399        lcd_console_address = lcd_logo ();
 400
 401        console_col = 0;
 402        console_row = 0;
 403}
 404
 405U_BOOT_CMD(
 406        cls,    1,      1,      do_lcd_clear,
 407        "clear screen",
 408        ""
 409);
 410
 411/*----------------------------------------------------------------------*/
 412
 413static int lcd_init(void *lcdbase)
 414{
 415        /* Initialize the lcd controller */
 416        debug("[LCD] Initializing LCD frambuffer at %p\n", lcdbase);
 417
 418        lcd_ctrl_init(lcdbase);
 419        lcd_is_enabled = 1;
 420        lcd_clear();
 421        lcd_enable ();
 422
 423        /* Initialize the console */
 424        console_col = 0;
 425#ifdef CONFIG_LCD_INFO_BELOW_LOGO
 426        console_row = 7 + BMP_LOGO_HEIGHT / VIDEO_FONT_HEIGHT;
 427#else
 428        console_row = 1;        /* leave 1 blank line below logo */
 429#endif
 430
 431        return 0;
 432}
 433
 434
 435/************************************************************************/
 436/* ** ROM capable initialization part - needed to reserve FB memory     */
 437/************************************************************************/
 438/*
 439 * This is called early in the system initialization to grab memory
 440 * for the LCD controller.
 441 * Returns new address for monitor, after reserving LCD buffer memory
 442 *
 443 * Note that this is running from ROM, so no write access to global data.
 444 */
 445ulong lcd_setmem(ulong addr)
 446{
 447        ulong size;
 448        int line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
 449
 450        debug("LCD panel info: %d x %d, %d bit/pix\n", panel_info.vl_col,
 451                panel_info.vl_row, NBITS(panel_info.vl_bpix));
 452
 453        size = line_length * panel_info.vl_row;
 454
 455        /* Round up to nearest full page */
 456        size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
 457
 458        /* Allocate pages for the frame buffer. */
 459        addr -= size;
 460
 461        debug("Reserving %ldk for LCD Framebuffer at: %08lx\n", size>>10, addr);
 462
 463        return addr;
 464}
 465
 466/*----------------------------------------------------------------------*/
 467
 468static void lcd_setfgcolor(int color)
 469{
 470        lcd_color_fg = color;
 471}
 472
 473/*----------------------------------------------------------------------*/
 474
 475static void lcd_setbgcolor(int color)
 476{
 477        lcd_color_bg = color;
 478}
 479
 480/*----------------------------------------------------------------------*/
 481
 482#ifdef  NOT_USED_SO_FAR
 483static int lcd_getfgcolor(void)
 484{
 485        return lcd_color_fg;
 486}
 487#endif  /* NOT_USED_SO_FAR */
 488
 489/*----------------------------------------------------------------------*/
 490
 491static int lcd_getbgcolor(void)
 492{
 493        return lcd_color_bg;
 494}
 495
 496/*----------------------------------------------------------------------*/
 497
 498/************************************************************************/
 499/* ** Chipset depending Bitmap / Logo stuff...                          */
 500/************************************************************************/
 501#ifdef CONFIG_LCD_LOGO
 502void bitmap_plot(int x, int y)
 503{
 504#ifdef CONFIG_ATMEL_LCD
 505        uint *cmap;
 506#else
 507        ushort *cmap;
 508#endif
 509        ushort i, j;
 510        uchar *bmap;
 511        uchar *fb;
 512        ushort *fb16;
 513#if defined(CONFIG_CPU_PXA)
 514        struct pxafb_info *fbi = &panel_info.pxa;
 515#elif defined(CONFIG_MPC823)
 516        volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
 517        volatile cpm8xx_t *cp = &(immr->im_cpm);
 518#endif
 519
 520        debug("Logo: width %d  height %d  colors %d  cmap %d\n",
 521                BMP_LOGO_WIDTH, BMP_LOGO_HEIGHT, BMP_LOGO_COLORS,
 522                ARRAY_SIZE(bmp_logo_palette));
 523
 524        bmap = &bmp_logo_bitmap[0];
 525        fb   = (uchar *)(lcd_base + y * lcd_line_length + x);
 526
 527        if (NBITS(panel_info.vl_bpix) < 12) {
 528                /* Leave room for default color map */
 529#if defined(CONFIG_CPU_PXA)
 530                cmap = (ushort *) fbi->palette;
 531#elif defined(CONFIG_MPC823)
 532                cmap = (ushort *) &(cp->lcd_cmap[BMP_LOGO_OFFSET * sizeof(ushort)]);
 533#elif defined(CONFIG_ATMEL_LCD)
 534                cmap = (uint *) (panel_info.mmio + ATMEL_LCDC_LUT(0));
 535#else
 536                /*
 537                 * default case: generic system with no cmap (most likely 16bpp)
 538                 * We set cmap to the source palette, so no change is done.
 539                 * This avoids even more ifdef in the next stanza
 540                 */
 541                cmap = bmp_logo_palette;
 542#endif
 543
 544                WATCHDOG_RESET();
 545
 546                /* Set color map */
 547                for (i = 0; i < ARRAY_SIZE(bmp_logo_palette); ++i) {
 548                        ushort colreg = bmp_logo_palette[i];
 549#ifdef CONFIG_ATMEL_LCD
 550                        uint lut_entry;
 551#ifdef CONFIG_ATMEL_LCD_BGR555
 552                        lut_entry = ((colreg & 0x000F) << 11) |
 553                                        ((colreg & 0x00F0) <<  2) |
 554                                        ((colreg & 0x0F00) >>  7);
 555#else /* CONFIG_ATMEL_LCD_RGB565 */
 556                        lut_entry = ((colreg & 0x000F) << 1) |
 557                                        ((colreg & 0x00F0) << 3) |
 558                                        ((colreg & 0x0F00) << 4);
 559#endif
 560                        *(cmap + BMP_LOGO_OFFSET) = lut_entry;
 561                        cmap++;
 562#else /* !CONFIG_ATMEL_LCD */
 563#ifdef  CONFIG_SYS_INVERT_COLORS
 564                        *cmap++ = 0xffff - colreg;
 565#else
 566                        *cmap++ = colreg;
 567#endif
 568#endif /* CONFIG_ATMEL_LCD */
 569                }
 570
 571                WATCHDOG_RESET();
 572
 573                for (i = 0; i < BMP_LOGO_HEIGHT; ++i) {
 574                        memcpy(fb, bmap, BMP_LOGO_WIDTH);
 575                        bmap += BMP_LOGO_WIDTH;
 576                        fb   += panel_info.vl_col;
 577                }
 578        }
 579        else { /* true color mode */
 580                u16 col16;
 581                fb16 = (ushort *)(lcd_base + y * lcd_line_length + x);
 582                for (i = 0; i < BMP_LOGO_HEIGHT; ++i) {
 583                        for (j = 0; j < BMP_LOGO_WIDTH; j++) {
 584                                col16 = bmp_logo_palette[(bmap[j]-16)];
 585                                fb16[j] =
 586                                        ((col16 & 0x000F) << 1) |
 587                                        ((col16 & 0x00F0) << 3) |
 588                                        ((col16 & 0x0F00) << 4);
 589                                }
 590                        bmap += BMP_LOGO_WIDTH;
 591                        fb16 += panel_info.vl_col;
 592                }
 593        }
 594
 595        WATCHDOG_RESET();
 596}
 597#else
 598static inline void bitmap_plot(int x, int y) {}
 599#endif /* CONFIG_LCD_LOGO */
 600
 601/*----------------------------------------------------------------------*/
 602#if defined(CONFIG_CMD_BMP) || defined(CONFIG_SPLASH_SCREEN)
 603/*
 604 * Display the BMP file located at address bmp_image.
 605 * Only uncompressed.
 606 */
 607
 608#ifdef CONFIG_SPLASH_SCREEN_ALIGN
 609#define BMP_ALIGN_CENTER        0x7FFF
 610#endif
 611
 612int lcd_display_bitmap(ulong bmp_image, int x, int y)
 613{
 614#if !defined(CONFIG_MCC200)
 615        ushort *cmap = NULL;
 616#endif
 617        ushort *cmap_base = NULL;
 618        ushort i, j;
 619        uchar *fb;
 620        bmp_image_t *bmp=(bmp_image_t *)bmp_image;
 621        uchar *bmap;
 622        ushort padded_line;
 623        unsigned long width, height, byte_width;
 624        unsigned long pwidth = panel_info.vl_col;
 625        unsigned colors, bpix, bmp_bpix;
 626#if defined(CONFIG_CPU_PXA)
 627        struct pxafb_info *fbi = &panel_info.pxa;
 628#elif defined(CONFIG_MPC823)
 629        volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR;
 630        volatile cpm8xx_t *cp = &(immr->im_cpm);
 631#endif
 632
 633        if (!((bmp->header.signature[0] == 'B') &&
 634                (bmp->header.signature[1] == 'M'))) {
 635                printf("Error: no valid bmp image at %lx\n", bmp_image);
 636
 637                return 1;
 638        }
 639
 640        width = le32_to_cpu(bmp->header.width);
 641        height = le32_to_cpu(bmp->header.height);
 642        bmp_bpix = le16_to_cpu(bmp->header.bit_count);
 643        colors = 1 << bmp_bpix;
 644
 645        bpix = NBITS(panel_info.vl_bpix);
 646
 647        if ((bpix != 1) && (bpix != 8) && (bpix != 16) && (bpix != 32)) {
 648                printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
 649                        bpix, bmp_bpix);
 650
 651                return 1;
 652        }
 653
 654        /* We support displaying 8bpp BMPs on 16bpp LCDs */
 655        if (bpix != bmp_bpix && (bmp_bpix != 8 || bpix != 16 || bpix != 32)) {
 656                printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n",
 657                        bpix,
 658                        le16_to_cpu(bmp->header.bit_count));
 659
 660                return 1;
 661        }
 662
 663        debug("Display-bmp: %d x %d  with %d colors\n",
 664                (int)width, (int)height, (int)colors);
 665
 666#if !defined(CONFIG_MCC200)
 667        /* MCC200 LCD doesn't need CMAP, supports 1bpp b&w only */
 668        if (bmp_bpix == 8) {
 669#if defined(CONFIG_CPU_PXA)
 670                cmap = (ushort *)fbi->palette;
 671#elif defined(CONFIG_MPC823)
 672                cmap = (ushort *)&(cp->lcd_cmap[255*sizeof(ushort)]);
 673#elif !defined(CONFIG_ATMEL_LCD) && !defined(CONFIG_EXYNOS_FB)
 674                cmap = panel_info.cmap;
 675#endif
 676
 677                cmap_base = cmap;
 678
 679                /* Set color map */
 680                for (i = 0; i < colors; ++i) {
 681                        bmp_color_table_entry_t cte = bmp->color_table[i];
 682#if !defined(CONFIG_ATMEL_LCD)
 683                        ushort colreg =
 684                                ( ((cte.red)   << 8) & 0xf800) |
 685                                ( ((cte.green) << 3) & 0x07e0) |
 686                                ( ((cte.blue)  >> 3) & 0x001f) ;
 687#ifdef CONFIG_SYS_INVERT_COLORS
 688                        *cmap = 0xffff - colreg;
 689#else
 690                        *cmap = colreg;
 691#endif
 692#if defined(CONFIG_MPC823)
 693                        cmap--;
 694#else
 695                        cmap++;
 696#endif
 697#else /* CONFIG_ATMEL_LCD */
 698                        lcd_setcolreg(i, cte.red, cte.green, cte.blue);
 699#endif
 700                }
 701        }
 702#endif
 703
 704        /*
 705         *  BMP format for Monochrome assumes that the state of a
 706         * pixel is described on a per Bit basis, not per Byte.
 707         *  So, in case of Monochrome BMP we should align widths
 708         * on a byte boundary and convert them from Bit to Byte
 709         * units.
 710         *  Probably, PXA250 and MPC823 process 1bpp BMP images in
 711         * their own ways, so make the converting to be MCC200
 712         * specific.
 713         */
 714#if defined(CONFIG_MCC200)
 715        if (bpix == 1) {
 716                width = ((width + 7) & ~7) >> 3;
 717                x     = ((x + 7) & ~7) >> 3;
 718                pwidth= ((pwidth + 7) & ~7) >> 3;
 719        }
 720#endif
 721
 722        padded_line = (width&0x3) ? ((width&~0x3)+4) : (width);
 723
 724#ifdef CONFIG_SPLASH_SCREEN_ALIGN
 725        if (x == BMP_ALIGN_CENTER)
 726                x = max(0, (pwidth - width) / 2);
 727        else if (x < 0)
 728                x = max(0, pwidth - width + x + 1);
 729
 730        if (y == BMP_ALIGN_CENTER)
 731                y = max(0, (panel_info.vl_row - height) / 2);
 732        else if (y < 0)
 733                y = max(0, panel_info.vl_row - height + y + 1);
 734#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
 735
 736        if ((x + width) > pwidth)
 737                width = pwidth - x;
 738        if ((y + height) > panel_info.vl_row)
 739                height = panel_info.vl_row - y;
 740
 741        bmap = (uchar *)bmp + le32_to_cpu(bmp->header.data_offset);
 742        fb   = (uchar *) (lcd_base +
 743                (y + height - 1) * lcd_line_length + x * bpix / 8);
 744
 745        switch (bmp_bpix) {
 746        case 1: /* pass through */
 747        case 8:
 748                if (bpix != 16)
 749                        byte_width = width;
 750                else
 751                        byte_width = width * 2;
 752
 753                for (i = 0; i < height; ++i) {
 754                        WATCHDOG_RESET();
 755                        for (j = 0; j < width; j++) {
 756                                if (bpix != 16) {
 757#if defined(CONFIG_CPU_PXA) || defined(CONFIG_ATMEL_LCD)
 758                                        *(fb++) = *(bmap++);
 759#elif defined(CONFIG_MPC823) || defined(CONFIG_MCC200)
 760                                        *(fb++) = 255 - *(bmap++);
 761#endif
 762                                } else {
 763                                        *(uint16_t *)fb = cmap_base[*(bmap++)];
 764                                        fb += sizeof(uint16_t) / sizeof(*fb);
 765                                }
 766                        }
 767                        bmap += (width - padded_line);
 768                        fb   -= (byte_width + lcd_line_length);
 769                }
 770                break;
 771
 772#if defined(CONFIG_BMP_16BPP)
 773        case 16:
 774                for (i = 0; i < height; ++i) {
 775                        WATCHDOG_RESET();
 776                        for (j = 0; j < width; j++) {
 777#if defined(CONFIG_ATMEL_LCD_BGR555)
 778                                *(fb++) = ((bmap[0] & 0x1f) << 2) |
 779                                        (bmap[1] & 0x03);
 780                                *(fb++) = (bmap[0] & 0xe0) |
 781                                        ((bmap[1] & 0x7c) >> 2);
 782                                bmap += 2;
 783#else
 784                                *(fb++) = *(bmap++);
 785                                *(fb++) = *(bmap++);
 786#endif
 787                        }
 788                        bmap += (padded_line - width) * 2;
 789                        fb   -= (width * 2 + lcd_line_length);
 790                }
 791                break;
 792#endif /* CONFIG_BMP_16BPP */
 793
 794#if defined(CONFIG_BMP_32BPP)
 795        case 32:
 796                for (i = 0; i < height; ++i) {
 797                        for (j = 0; j < width; j++) {
 798                                *(fb++) = *(bmap++);
 799                                *(fb++) = *(bmap++);
 800                                *(fb++) = *(bmap++);
 801                                *(fb++) = *(bmap++);
 802                        }
 803                        fb  -= (lcd_line_length + width * (bpix / 8));
 804                }
 805                break;
 806#endif /* CONFIG_BMP_32BPP */
 807        default:
 808                break;
 809        };
 810
 811        return 0;
 812}
 813#endif
 814
 815static void *lcd_logo(void)
 816{
 817#ifdef CONFIG_SPLASH_SCREEN
 818        char *s;
 819        ulong addr;
 820        static int do_splash = 1;
 821
 822        if (do_splash && (s = getenv("splashimage")) != NULL) {
 823                int x = 0, y = 0;
 824                do_splash = 0;
 825
 826                addr = simple_strtoul (s, NULL, 16);
 827#ifdef CONFIG_SPLASH_SCREEN_ALIGN
 828                s = getenv("splashpos");
 829                if (s != NULL) {
 830                        if (s[0] == 'm')
 831                                x = BMP_ALIGN_CENTER;
 832                        else
 833                                x = simple_strtol(s, NULL, 0);
 834
 835                        s = strchr(s + 1, ',');
 836                        if (s != NULL) {
 837                                if (s[1] == 'm')
 838                                        y = BMP_ALIGN_CENTER;
 839                                else
 840                                        y = simple_strtol (s + 1, NULL, 0);
 841                        }
 842                }
 843#endif /* CONFIG_SPLASH_SCREEN_ALIGN */
 844
 845#ifdef CONFIG_VIDEO_BMP_GZIP
 846                bmp_image_t *bmp = (bmp_image_t *)addr;
 847                unsigned long len;
 848
 849                if (!((bmp->header.signature[0] == 'B') &&
 850                        (bmp->header.signature[1] == 'M'))) {
 851                        addr = (ulong)gunzip_bmp(addr, &len);
 852                }
 853#endif
 854
 855                if (lcd_display_bitmap(addr, x, y) == 0)
 856                        return (void *)lcd_base;
 857        }
 858#endif /* CONFIG_SPLASH_SCREEN */
 859
 860        bitmap_plot(0, 0);
 861
 862#ifdef CONFIG_LCD_INFO
 863        console_col = LCD_INFO_X / VIDEO_FONT_WIDTH;
 864        console_row = LCD_INFO_Y / VIDEO_FONT_HEIGHT;
 865        lcd_show_board_info();
 866#endif /* CONFIG_LCD_INFO */
 867
 868#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
 869        return (void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length);
 870#else
 871        return (void *)lcd_base;
 872#endif /* CONFIG_LCD_LOGO && !CONFIG_LCD_INFO_BELOW_LOGO */
 873}
 874
 875/************************************************************************/
 876/************************************************************************/
 877