Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / board / esd / common / lcd.c
diff --git a/qemu/roms/u-boot/board/esd/common/lcd.c b/qemu/roms/u-boot/board/esd/common/lcd.c
new file mode 100644 (file)
index 0000000..22a59e4
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * (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.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#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;
+
+#if defined(CONFIG_SYS_LCD_ENDIAN)
+void lcd_setup(int lcd, int config)
+{
+       if (lcd == 0) {
+               /*
+                * Set endianess and reset lcd controller 0 (small)
+                */
+
+               /* 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) {
+                       /* big-endian */
+                       out_be32((void*)GPIO0_OR,
+                                in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN);
+               } else {
+                       /* little-endian */
+                       out_be32((void*)GPIO0_OR,
+                                in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD_ENDIAN);
+               }
+               udelay(10); /* wait 10us */
+               /* 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)
+                */
+
+               /* 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) {
+                       /* big-endian */
+                       out_be32((void*)GPIO0_OR,
+                                in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN);
+               } else {
+                       /* little-endian */
+                       out_be32((void*)GPIO0_OR,
+                                in_be32((void*)GPIO0_OR) & ~CONFIG_SYS_LCD_ENDIAN);
+               }
+               udelay(10); /* wait 10us */
+               /* set reset to high */
+               out_be32((void*)GPIO0_OR,
+                        in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD1_RST);
+       }
+
+       /*
+        * CONFIG_SYS_LCD_ENDIAN may also be FPGA_RESET, so set inactive
+        */
+       out_be32((void*)GPIO0_OR, in_be32((void*)GPIO0_OR) | CONFIG_SYS_LCD_ENDIAN);
+}
+#endif /* CONFIG_SYS_LCD_ENDIAN */
+
+
+int lcd_bmp(uchar *logo_bmp)
+{
+       int i;
+       uchar *ptr;
+       ushort *ptr2;
+       ushort val;
+       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;
+       ulong len;
+
+       /*
+        * Check for bmp mark 'BM'
+        */
+       if (*(ushort *)logo_bmp != 0x424d) {
+               /*
+                * Decompress bmp image
+                */
+               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");
+               }
+
+               /*
+                * Check for bmp mark 'BM'
+                */
+               if (*(ushort *)dst != 0x424d) {
+                       printf("LCD: Unknown image format!\n");
+                       free(dst);
+                       return 1;
+               }
+       } else {
+               /*
+                * Uncompressed BMP image, just use this pointer
+                */
+               dst = (uchar *)logo_bmp;
+       }
+
+       /*
+        * Get image info from bmp-header
+        */
+       bm_info = (BITMAPINFOHEADER *)(dst + 14);
+       bpp = LOAD_SHORT(bm_info->biBitCount);
+       width = LOAD_LONG(bm_info->biWidth);
+       height = LOAD_LONG(bm_info->biHeight);
+       switch (bpp) {
+       case 1:
+               colors = 1;
+               line_size = width >> 3;
+               break;
+       case 4:
+               colors = 16;
+               line_size = width >> 1;
+               break;
+       case 8:
+               colors = 256;
+               line_size = width;
+               break;
+       case 24:
+               colors = 0;
+               line_size = width * 3;
+               break;
+       default:
+               printf("LCD: Unknown bpp (%d) im image!\n", bpp);
+               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) && (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(glob_lcd_reg, i, r, g, b);
+               }
+       }
+
+       /*
+        * Write bitmap data into framebuffer
+        */
+       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 (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++)
+                               *ptr++ = *bmp++;
+               }
+       }
+
+       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 * const argv[])
+{
+       ulong addr;
+#ifdef CONFIG_VIDEO_SM501
+       char *str;
+#endif
+       if (argc != 2)
+               return cmd_usage(cmdtp);
+
+       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,
+       "display BMP image",
+       "<imageAddr> - display image"
+);