]> git.sur5r.net Git - u-boot/blobdiff - board/esd/common/lcd.c
sh: lowlevel_init coding style cleanup
[u-boot] / board / esd / common / lcd.c
index a1fc18089d3a21260b06b9e08558fb4b901ab352..1eea59ecb12e9dd197a1ccaecf7d6de2a1247d06 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.
  *
  * MA 02111-1307 USA
  */
 
+#include "asm/io.h"
 #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
+#if defined(CONFIG_SYS_LCD_ENDIAN)
 void lcd_setup(int lcd, int config)
 {
        if (lcd == 0) {
                /*
                 * Set endianess and reset lcd controller 0 (small)
                 */
-               out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_LCD0_RST); /* set reset to low */
+
+               /* set reset to low */
+               out_be32((void*)GPIO0_OR,
+                        in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD0_RST);
                udelay(10); /* wait 10us */
                if (config == 1) {
-                       out32(GPIO0_OR, in32(GPIO0_OR) | CFG_LCD_ENDIAN); /* big-endian */
+                       /* big-endian */
+                       out_be32((void*)GPIO0_OR,
+                                in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN);
                } else {
-                       out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_LCD_ENDIAN); /* little-endian */
+                       /* little-endian */
+                       out_be32((void*)GPIO0_OR,
+                                in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD_ENDIAN);
                }
                udelay(10); /* wait 10us */
-               out32(GPIO0_OR, in32(GPIO0_OR) | CFG_LCD0_RST); /* set reset to high */
+               /* set reset to high */
+               out_be32((void*)GPIO0_OR,
+                        in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD0_RST);
        } else {
                /*
                 * Set endianess and reset lcd controller 1 (big)
                 */
-               out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_LCD1_RST); /* set reset to low */
+
+               /* set reset to low */
+               out_be32((void*)GPIO0_OR,
+                        in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD1_RST);
                udelay(10); /* wait 10us */
                if (config == 1) {
-                       out32(GPIO0_OR, in32(GPIO0_OR) | CFG_LCD_ENDIAN); /* big-endian */
+                       /* big-endian */
+                       out_be32((void*)GPIO0_OR,
+                                in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN);
                } else {
-                       out32(GPIO0_OR, in32(GPIO0_OR) & ~CFG_LCD_ENDIAN); /* little-endian */
+                       /* little-endian */
+                       out_be32((void*)GPIO0_OR,
+                                in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD_ENDIAN);
                }
                udelay(10); /* wait 10us */
-               out32(GPIO0_OR, in32(GPIO0_OR) | CFG_LCD1_RST); /* set reset to high */
+               /* set reset to high */
+               out_be32((void*)GPIO0_OR,
+                        in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD1_RST);
        }
 
        /*
-        * CFG_LCD_ENDIAN may also be FPGA_RESET, so set inactive
+        * CONFIG_SYS_LCD_ENDIAN may also be FPGA_RESET, so set inactive
         */
-       out32(GPIO0_OR, in32(GPIO0_OR) | CFG_LCD_ENDIAN); /* set reset high again */
+       out_be32((void*)GPIO0_OR, in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN);
 }
-#endif /* #ifdef CFG_LCD_ENDIAN */
+#endif /* CONFIG_SYS_LCD_ENDIAN */
 
 
-void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
-             uchar *logo_bmp, ulong len)
+int lcd_bmp(uchar *logo_bmp)
 {
        int i;
-       ushort s1dReg;
-       uchar s1dValue;
        uchar *ptr;
        ushort *ptr2;
        ushort val;
-       unsigned char *dst;
+       unsigned char *dst = NULL;
        int x, y;
        int width, height, bpp, colors, line_size;
        int header_size;
        unsigned char *bmp;
        unsigned char r, g, b;
        BITMAPINFOHEADER *bm_info;
-       int reg_byte_swap;
+       ulong len;
 
        /*
-        * 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 = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE;
+               dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE);
+               if (dst == NULL) {
+                       printf("Error: malloc for gunzip failed!\n");
+                       return 1;
+               }
+               if (gunzip(dst, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE,
+                          (uchar *)logo_bmp, &len) != 0) {
+                       free(dst);
+                       return 1;
+               }
+               if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) {
+                       printf("Image could be truncated"
+                              " (increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n");
+               }
+
                /*
-                * 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 1;
+               }
+       } 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;
        }
 
        /*
@@ -181,50 +173,205 @@ void lcd_init(uchar *lcd_reg, uchar *lcd_mem, S1D_REGS *regs, int reg_count,
                break;
        default:
                printf("LCD: Unknown bpp (%d) im image!\n", bpp);
-               free(dst);
-               return;
+               if ((dst != NULL) && (dst != (uchar *)logo_bmp))
+                       free(dst);
+               return 1;
        }
        printf(" (%d*%d, %dbpp)\n", width, height, bpp);
 
        /*
         * Write color palette
         */
-       if (colors <= 256) {
+       if ((colors <= 256) && (lcd_depth <= 8)) {
                ptr = (unsigned char *)(dst + 14 + 40);
-               for (i=0; i<colors; i++) {
+               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++) {
+       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++) {
+                       for (x = 0; x < line_size; x++)
                                *ptr++ = *bmp++;
-                       }
                }
        }
 
-       free(dst);
+       if ((dst != NULL) && (dst != (uchar *)logo_bmp))
+               free(dst);
+       return 0;
 }
+
+
+int 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
+        */
+       out_8(&lcd_reg[0], 0x00);
+       out_8(&lcd_reg[1], 0x00);
+
+       if (in_8(&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 (in_8(&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 (in_8(&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 (in_8(&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 {
+               out_8(&lcd_reg[0x1a], 0x00);
+               udelay(1000);
+               if (in_8(&lcd_reg[1]) == 0x0c) {
+                       /*
+                        * S1D13505 detected
+                        */
+                       reg_byte_swap = TRUE;
+                       palette_index = 0x25;
+                       palette_value = 0x27;
+                       lcd_depth = 16;
+
+                       puts("LCD:   S1D13505");
+               } else {
+                       puts("LCD:   No controller detected!\n");
+                       return 1;
+               }
+       }
+
+       /*
+        * 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;
+               out_8(&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
+        */
+       return lcd_bmp(logo_bmp);
+}
+
+int do_esdbmp(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       ulong addr;
+#ifdef CONFIG_VIDEO_SM501
+       char *str;
+#endif
+       if (argc != 2) {
+               printf ("Usage:\n%s\n", cmdtp->usage);
+               return 1;
+       }
+
+       addr = simple_strtoul(argv[1], NULL, 16);
+
+#ifdef CONFIG_VIDEO_SM501
+       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
+                */
+               return lcd_bmp((uchar *)addr);
+       }
+#else
+       return lcd_bmp((uchar *)addr);
+#endif
+}
+
+U_BOOT_CMD(
+       esdbmp, 2,      1,      do_esdbmp,
+       "esdbmp   - display BMP image\n",
+       "<imageAddr> - display image\n"
+);