Fix VOH405 Support
[platform/kernel/u-boot.git] / board / esd / common / lcd.c
index a1fc180..05c76ff 100644 (file)
@@ -2,6 +2,9 @@
  * (C) Copyright 2003-2004
  * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
  *
+ * (C) Copyright 2005
+ * Stefan Roese, DENX Software Engineering, sr@denx.de.
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
 #include "lcd.h"
 
 
+extern int video_display_bitmap (ulong, int, int);
+
+
 int palette_index;
 int palette_value;
-
+int lcd_depth;
+unsigned char *glob_lcd_reg;
+unsigned char *glob_lcd_mem;
 
 #ifdef CFG_LCD_ENDIAN
 void lcd_setup(int lcd, int config)
@@ -67,12 +75,9 @@ void lcd_setup(int lcd, int config)
 #endif /* #ifdef CFG_LCD_ENDIAN */
 
 
-void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
-             uchar *logo_bmp, ulong len)
+void lcd_bmp(uchar *logo_bmp)
 {
        int i;
-       ushort s1dReg;
-       uchar s1dValue;
        uchar *ptr;
        ushort *ptr2;
        ushort val;
@@ -83,76 +88,37 @@ void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
        unsigned char *bmp;
        unsigned char r, g, b;
        BITMAPINFOHEADER *bm_info;
-       int reg_byte_swap;
+       ulong len;
+       int do_free = 0;
 
        /*
-        * Detect epson
+        * Check for bmp mark 'BM'
         */
-       if (lcd_reg[0] == 0x1c) {
-               /*
-                * Big epson detected
-                */
-               reg_byte_swap = FALSE;
-               palette_index = 0x1e2;
-               palette_value = 0x1e4;
-               puts("LCD:   S1D13806");
-       } else if (lcd_reg[1] == 0x1c) {
+       if (*(ushort *)logo_bmp != 0x424d) {
+
                /*
-                * Big epson detected (with register swap bug)
+                * Decompress bmp image
                 */
-               reg_byte_swap = TRUE;
-               palette_index = 0x1e3;
-               palette_value = 0x1e5;
-               puts("LCD:   S1D13806S");
-       } else if (lcd_reg[0] == 0x18) {
+               len = CFG_LCD_LOGO_MAX_SIZE;
+               dst = malloc(CFG_LCD_LOGO_MAX_SIZE);
+               do_free = 1;
+               if (gunzip(dst, CFG_LCD_LOGO_MAX_SIZE, (uchar *)logo_bmp, &len) != 0) {
+                       return;
+               }
+
                /*
-                * Small epson detected (704)
+                * Check for bmp mark 'BM'
                 */
-               reg_byte_swap = FALSE;
-               palette_index = 0x15;
-               palette_value = 0x17;
-               puts("LCD:   S1D13704");
-       } else if (lcd_reg[0x10000] == 0x24) {
+               if (*(ushort *)dst != 0x424d) {
+                       printf("LCD: Unknown image format!\n");
+                       free(dst);
+                       return;
+               }
+       } else {
                /*
-                * Small epson detected (705)
+                * Uncompressed BMP image, just use this pointer
                 */
-               reg_byte_swap = FALSE;
-               palette_index = 0x15;
-               palette_value = 0x17;
-               lcd_reg += 0x10000; /* add offset for 705 regs */
-               puts("LCD:   S1D13705");
-       } else {
-               puts("LCD:   No controller detected!\n");
-               return;
-       }
-
-       for (i = 0; i<reg_count; i++) {
-               s1dReg = regs[i].Index;
-               if (reg_byte_swap) {
-                       if ((s1dReg & 0x0001) == 0)
-                               s1dReg |= 0x0001;
-                       else
-                               s1dReg &= ~0x0001;
-               }
-               s1dValue = regs[i].Value;
-               lcd_reg[s1dReg] = s1dValue;
-        }
-
-       /*
-        * Decompress bmp image
-        */
-       dst = malloc(CFG_LCD_LOGO_MAX_SIZE);
-       if (gunzip(dst, CFG_LCD_LOGO_MAX_SIZE, (uchar *)logo_bmp, &len) != 0) {
-               return;
-       }
-
-       /*
-        * Check for bmp mark 'BM'
-        */
-       if (*(ushort *)dst != 0x424d) {
-               printf("LCD: Unknown image format!\n");
-               free(dst);
-               return;
+               dst = (uchar *)logo_bmp;
        }
 
        /*
@@ -189,35 +155,48 @@ void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
        /*
         * Write color palette
         */
-       if (colors <= 256) {
+       if ((colors <= 256) && (lcd_depth <= 8)) {
                ptr = (unsigned char *)(dst + 14 + 40);
                for (i=0; i<colors; i++) {
                        b = *ptr++;
                        g = *ptr++;
                        r = *ptr++;
                        ptr++;
-                       S1D_WRITE_PALETTE(lcd_reg, i, r, g, b);
+                       S1D_WRITE_PALETTE(glob_lcd_reg, i, r, g, b);
                }
        }
 
        /*
         * Write bitmap data into framebuffer
         */
-       ptr = lcd_mem;
-       ptr2 = (ushort *)lcd_mem;
+       ptr = glob_lcd_mem;
+       ptr2 = (ushort *)glob_lcd_mem;
        header_size = 14 + 40 + 4*colors;          /* skip bmp header */
        for (y=0; y<height; y++) {
                bmp = &dst[(height-1-y)*line_size + header_size];
-               if (bpp == 24) {
-                       for (x=0; x<width; x++) {
-                               /*
-                                * Generate epson 16bpp fb-format from 24bpp image
-                                */
-                               b = *bmp++ >> 3;
-                               g = *bmp++ >> 2;
-                               r = *bmp++ >> 3;
-                               val = ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b & 0x1f);
-                               *ptr2++ = val;
+               if (lcd_depth == 16) {
+                       if (bpp == 24) {
+                               for (x=0; x<width; x++) {
+                                       /*
+                                        * Generate epson 16bpp fb-format from 24bpp image
+                                        */
+                                       b = *bmp++ >> 3;
+                                       g = *bmp++ >> 2;
+                                       r = *bmp++ >> 3;
+                                       val = ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b & 0x1f);
+                                       *ptr2++ = val;
+                               }
+                       } else if (bpp == 8) {
+                               for (x=0; x<line_size; x++) {
+                                       /* query rgb value from palette */
+                                       ptr = (unsigned char *)(dst + 14 + 40) ;
+                                       ptr += (*bmp++) << 2;
+                                       b = *ptr++ >> 3;
+                                       g = *ptr++ >> 2;
+                                       r = *ptr++ >> 3;
+                                       val = ((r & 0x1f) << 11) | ((g & 0x3f) << 5) | (b & 0x1f);
+                                       *ptr2++ = val;
+                               }
                        }
                } else {
                        for (x=0; x<line_size; x++) {
@@ -226,5 +205,123 @@ void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
                }
        }
 
-       free(dst);
+       if (do_free) {
+               free(dst);
+       }
+}
+
+
+void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
+             uchar *logo_bmp, ulong len)
+{
+       int i;
+       ushort s1dReg;
+       uchar s1dValue;
+       int reg_byte_swap;
+
+       /*
+        * Detect epson
+        */
+       if (lcd_reg[0] == 0x1c) {
+               /*
+                * Big epson detected
+                */
+               reg_byte_swap = FALSE;
+               palette_index = 0x1e2;
+               palette_value = 0x1e4;
+               lcd_depth = 16;
+               puts("LCD:   S1D13806");
+       } else if (lcd_reg[1] == 0x1c) {
+               /*
+                * Big epson detected (with register swap bug)
+                */
+               reg_byte_swap = TRUE;
+               palette_index = 0x1e3;
+               palette_value = 0x1e5;
+               lcd_depth = 16;
+               puts("LCD:   S1D13806S");
+       } else if (lcd_reg[0] == 0x18) {
+               /*
+                * Small epson detected (704)
+                */
+               reg_byte_swap = FALSE;
+               palette_index = 0x15;
+               palette_value = 0x17;
+               lcd_depth = 8;
+               puts("LCD:   S1D13704");
+       } else if (lcd_reg[0x10000] == 0x24) {
+               /*
+                * Small epson detected (705)
+                */
+               reg_byte_swap = FALSE;
+               palette_index = 0x15;
+               palette_value = 0x17;
+               lcd_depth = 8;
+               lcd_reg += 0x10000; /* add offset for 705 regs */
+               puts("LCD:   S1D13705");
+       } else {
+               puts("LCD:   No controller detected!\n");
+               return;
+       }
+
+       /*
+        * Setup lcd controller regs
+        */
+       for (i = 0; i<reg_count; i++) {
+               s1dReg = regs[i].Index;
+               if (reg_byte_swap) {
+                       if ((s1dReg & 0x0001) == 0)
+                               s1dReg |= 0x0001;
+                       else
+                               s1dReg &= ~0x0001;
+               }
+               s1dValue = regs[i].Value;
+               lcd_reg[s1dReg] = s1dValue;
+       }
+
+       /*
+        * Save reg & mem pointer for later usage (e.g. bmp command)
+        */
+       glob_lcd_reg = lcd_reg;
+       glob_lcd_mem = lcd_mem;
+
+       /*
+        * Display bmp image
+        */
+       lcd_bmp(logo_bmp);
 }
+
+#ifdef CONFIG_VIDEO_SM501
+int do_esdbmp(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       ulong addr;
+       char *str;
+
+       if (argc != 2) {
+               printf ("Usage:\n%s\n", cmdtp->usage);
+               return 1;
+       }
+
+       addr = simple_strtoul(argv[1], NULL, 16);
+
+       str = getenv("bd_type");
+       if ((strcmp(str, "ppc221") == 0) || (strcmp(str, "ppc231") == 0)) {
+               /*
+                * SM501 available, use standard bmp command
+                */
+               return (video_display_bitmap(addr, 0, 0));
+       } else {
+               /*
+                * No SM501 available, use esd epson bmp command
+                */
+               lcd_bmp((uchar *)addr);
+               return 0;
+       }
+}
+
+U_BOOT_CMD(
+       esdbmp, 2,      1,      do_esdbmp,
+       "esdbmp   - display BMP image\n",
+       "<imageAddr> - display image\n"
+);
+#endif