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