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