uboot/board/esd/common/lcd.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2003-2004
   3 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
   4 *
   5 * (C) Copyright 2005
   6 * Stefan Roese, DENX Software Engineering, sr@denx.de.
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27#include "asm/io.h"
  28#include "lcd.h"
  29
  30
  31extern int video_display_bitmap (ulong, int, int);
  32
  33
  34int palette_index;
  35int palette_value;
  36int lcd_depth;
  37unsigned char *glob_lcd_reg;
  38unsigned char *glob_lcd_mem;
  39
  40#if defined(CONFIG_SYS_LCD_ENDIAN)
  41void lcd_setup(int lcd, int config)
  42{
  43        if (lcd == 0) {
  44                /*
  45                 * Set endianess and reset lcd controller 0 (small)
  46                 */
  47
  48                /* set reset to low */
  49                out_be32((void*)GPIO0_OR,
  50                         in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD0_RST);
  51                udelay(10); /* wait 10us */
  52                if (config == 1) {
  53                        /* big-endian */
  54                        out_be32((void*)GPIO0_OR,
  55                                 in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN);
  56                } else {
  57                        /* little-endian */
  58                        out_be32((void*)GPIO0_OR,
  59                                 in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD_ENDIAN);
  60                }
  61                udelay(10); /* wait 10us */
  62                /* set reset to high */
  63                out_be32((void*)GPIO0_OR,
  64                         in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD0_RST);
  65        } else {
  66                /*
  67                 * Set endianess and reset lcd controller 1 (big)
  68                 */
  69
  70                /* set reset to low */
  71                out_be32((void*)GPIO0_OR,
  72                         in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD1_RST);
  73                udelay(10); /* wait 10us */
  74                if (config == 1) {
  75                        /* big-endian */
  76                        out_be32((void*)GPIO0_OR,
  77                                 in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN);
  78                } else {
  79                        /* little-endian */
  80                        out_be32((void*)GPIO0_OR,
  81                                 in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD_ENDIAN);
  82                }
  83                udelay(10); /* wait 10us */
  84                /* set reset to high */
  85                out_be32((void*)GPIO0_OR,
  86                         in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD1_RST);
  87        }
  88
  89        /*
  90         * CONFIG_SYS_LCD_ENDIAN may also be FPGA_RESET, so set inactive
  91         */
  92        out_be32((void*)GPIO0_OR, in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN);
  93}
  94#endif /* CONFIG_SYS_LCD_ENDIAN */
  95
  96
  97int lcd_bmp(uchar *logo_bmp)
  98{
  99        int i;
 100        uchar *ptr;
 101        ushort *ptr2;
 102        ushort val;
 103        unsigned char *dst = NULL;
 104        int x, y;
 105        int width, height, bpp, colors, line_size;
 106        int header_size;
 107        unsigned char *bmp;
 108        unsigned char r, g, b;
 109        BITMAPINFOHEADER *bm_info;
 110        ulong len;
 111
 112        /*
 113         * Check for bmp mark 'BM'
 114         */
 115        if (*(ushort *)logo_bmp != 0x424d) {
 116                /*
 117                 * Decompress bmp image
 118                 */
 119                len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
 120                dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
 121                if (dst == NULL) {
 122                        printf("Error: malloc for gunzip failed!\n");
 123                        return 1;
 124                }
 125                if (gunzip(dst, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE,
 126                           (uchar *)logo_bmp, &len) != 0) {
 127                        free(dst);
 128                        return 1;
 129                }
 130                if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) {
 131                        printf("Image could be truncated"
 132                               " (increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
 133                }
 134
 135                /*
 136                 * Check for bmp mark 'BM'
 137                 */
 138                if (*(ushort *)dst != 0x424d) {
 139                        printf("LCD: Unknown image format!\n");
 140                        free(dst);
 141                        return 1;
 142                }
 143        } else {
 144                /*
 145                 * Uncompressed BMP image, just use this pointer
 146                 */
 147                dst = (uchar *)logo_bmp;
 148        }
 149
 150        /*
 151         * Get image info from bmp-header
 152         */
 153        bm_info = (BITMAPINFOHEADER *)(dst + 14);
 154        bpp = LOAD_SHORT(bm_info->biBitCount);
 155        width = LOAD_LONG(bm_info->biWidth);
 156        height = LOAD_LONG(bm_info->biHeight);
 157        switch (bpp) {
 158        case 1:
 159                colors = 1;
 160                line_size = width >> 3;
 161                break;
 162        case 4:
 163                colors = 16;
 164                line_size = width >> 1;
 165                break;
 166        case 8:
 167                colors = 256;
 168                line_size = width;
 169                break;
 170        case 24:
 171                colors = 0;
 172                line_size = width * 3;
 173                break;
 174        default:
 175                printf("LCD: Unknown bpp (%d) im image!\n", bpp);
 176                if ((dst != NULL) && (dst != (uchar *)logo_bmp))
 177                        free(dst);
 178                return 1;
 179        }
 180        printf(" (%d*%d, %dbpp)\n", width, height, bpp);
 181
 182        /*
 183         * Write color palette
 184         */
 185        if ((colors <= 256) && (lcd_depth <= 8)) {
 186                ptr = (unsigned char *)(dst + 14 + 40);
 187                for (i = 0; i < colors; i++) {
 188                        b = *ptr++;
 189                        g = *ptr++;
 190                        r = *ptr++;
 191                        ptr++;
 192                        S1D_WRITE_PALETTE(glob_lcd_reg, i, r, g, b);
 193                }
 194        }
 195
 196        /*
 197         * Write bitmap data into framebuffer
 198         */
 199        ptr = glob_lcd_mem;
 200        ptr2 = (ushort *)glob_lcd_mem;
 201        header_size = 14 + 40 + 4*colors;          /* skip bmp header */
 202        for (y = 0; y < height; y++) {
 203                bmp = &dst[(height-1-y)*line_size + header_size];
 204                if (lcd_depth == 16) {
 205                        if (bpp == 24) {
 206                                for (x = 0; x < width; x++) {
 207                                        /*
 208                                         * Generate epson 16bpp fb-format
 209                                         * from 24bpp image
 210                                         */
 211                                        b = *bmp++ >> 3;
 212                                        g = *bmp++ >> 2;
 213                                        r = *bmp++ >> 3;
 214                                        val = ((r & 0x1f) << 11) |
 215                                                ((g & 0x3f) << 5) |
 216                                                (b & 0x1f);
 217                                        *ptr2++ = val;
 218                                }
 219                        } else if (bpp == 8) {
 220                                for (x = 0; x < line_size; x++) {
 221                                        /* query rgb value from palette */
 222                                        ptr = (unsigned char *)(dst + 14 + 40);
 223                                        ptr += (*bmp++) << 2;
 224                                        b = *ptr++ >> 3;
 225                                        g = *ptr++ >> 2;
 226                                        r = *ptr++ >> 3;
 227                                        val = ((r & 0x1f) << 11) |
 228                                                ((g & 0x3f) << 5) |
 229                                                (b & 0x1f);
 230                                        *ptr2++ = val;
 231                                }
 232                        }
 233                } else {
 234                        for (x = 0; x < line_size; x++)
 235                                *ptr++ = *bmp++;
 236                }
 237        }
 238
 239        if ((dst != NULL) && (dst != (uchar *)logo_bmp))
 240                free(dst);
 241        return 0;
 242}
 243
 244
 245int lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
 246             uchar *logo_bmp, ulong len)
 247{
 248        int i;
 249        ushort s1dReg;
 250        uchar s1dValue;
 251        int reg_byte_swap;
 252
 253        /*
 254         * Detect epson
 255         */
 256        out_8(&lcd_reg[0], 0x00);
 257        out_8(&lcd_reg[1], 0x00);
 258
 259        if (in_8(&lcd_reg[0]) == 0x1c) {
 260                /*
 261                 * Big epson detected
 262                 */
 263                reg_byte_swap = FALSE;
 264                palette_index = 0x1e2;
 265                palette_value = 0x1e4;
 266                lcd_depth = 16;
 267                puts("LCD:   S1D13806");
 268        } else if (in_8(&lcd_reg[1]) == 0x1c) {
 269                /*
 270                 * Big epson detected (with register swap bug)
 271                 */
 272                reg_byte_swap = TRUE;
 273                palette_index = 0x1e3;
 274                palette_value = 0x1e5;
 275                lcd_depth = 16;
 276                puts("LCD:   S1D13806S");
 277        } else if (in_8(&lcd_reg[0]) == 0x18) {
 278                /*
 279                 * Small epson detected (704)
 280                 */
 281                reg_byte_swap = FALSE;
 282                palette_index = 0x15;
 283                palette_value = 0x17;
 284                lcd_depth = 8;
 285                puts("LCD:   S1D13704");
 286        } else if (in_8(&lcd_reg[0x10000]) == 0x24) {
 287                /*
 288                 * Small epson detected (705)
 289                 */
 290                reg_byte_swap = FALSE;
 291                palette_index = 0x15;
 292                palette_value = 0x17;
 293                lcd_depth = 8;
 294                lcd_reg += 0x10000; /* add offset for 705 regs */
 295                puts("LCD:   S1D13705");
 296        } else {
 297                out_8(&lcd_reg[0x1a], 0x00);
 298                udelay(1000);
 299                if (in_8(&lcd_reg[1]) == 0x0c) {
 300                        /*
 301                         * S1D13505 detected
 302                         */
 303                        reg_byte_swap = TRUE;
 304                        palette_index = 0x25;
 305                        palette_value = 0x27;
 306                        lcd_depth = 16;
 307
 308                        puts("LCD:   S1D13505");
 309                } else {
 310                        puts("LCD:   No controller detected!\n");
 311                        return 1;
 312                }
 313        }
 314
 315        /*
 316         * Setup lcd controller regs
 317         */
 318        for (i = 0; i < reg_count; i++) {
 319                s1dReg = regs[i].Index;
 320                if (reg_byte_swap) {
 321                        if ((s1dReg & 0x0001) == 0)
 322                                s1dReg |= 0x0001;
 323                        else
 324                                s1dReg &= ~0x0001;
 325                }
 326                s1dValue = regs[i].Value;
 327                out_8(&lcd_reg[s1dReg], s1dValue);
 328        }
 329
 330        /*
 331         * Save reg & mem pointer for later usage (e.g. bmp command)
 332         */
 333        glob_lcd_reg = lcd_reg;
 334        glob_lcd_mem = lcd_mem;
 335
 336        /*
 337         * Display bmp image
 338         */
 339        return lcd_bmp(logo_bmp);
 340}
 341
 342int do_esdbmp(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 343{
 344        ulong addr;
 345#ifdef CONFIG_VIDEO_SM501
 346        char *str;
 347#endif
 348        if (argc != 2) {
 349                cmd_usage(cmdtp);
 350                return 1;
 351        }
 352
 353        addr = simple_strtoul(argv[1], NULL, 16);
 354
 355#ifdef CONFIG_VIDEO_SM501
 356        str = getenv("bd_type");
 357        if ((strcmp(str, "ppc221") == 0) || (strcmp(str, "ppc231") == 0)) {
 358                /*
 359                 * SM501 available, use standard bmp command
 360                 */
 361                return video_display_bitmap(addr, 0, 0);
 362        } else {
 363                /*
 364                 * No SM501 available, use esd epson bmp command
 365                 */
 366                return lcd_bmp((uchar *)addr);
 367        }
 368#else
 369        return lcd_bmp((uchar *)addr);
 370#endif
 371}
 372
 373U_BOOT_CMD(
 374        esdbmp, 2,      1,      do_esdbmp,
 375        "display BMP image",
 376        "<imageAddr> - display image"
 377);
 378