Merge branch 'master' of git://git.denx.de/u-boot-fdt
[oweals/u-boot.git] / drivers / video / sunxi_display.c
index af728b51c746783e46d3edc06b01538814dd44ea..dbda97e746b97b5dc2a729198738c449e59163c7 100644 (file)
@@ -46,6 +46,7 @@ struct sunxi_display {
        GraphicDevice graphic_device;
        enum sunxi_monitor monitor;
        unsigned int depth;
+       unsigned int fb_size;
 } sunxi_display;
 
 #ifdef CONFIG_VIDEO_HDMI
@@ -645,7 +646,8 @@ static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode)
        return (delay > 30) ? 30 : delay;
 }
 
-static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode)
+static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
+                                     bool for_ext_vga_dac)
 {
        struct sunxi_lcdc_reg * const lcdc =
                (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
@@ -719,6 +721,11 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode)
                val |= SUNXI_LCDC_TCON_HSYNC_MASK;
        if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT))
                val |= SUNXI_LCDC_TCON_VSYNC_MASK;
+
+#ifdef CONFIG_VIDEO_VGA_VIA_LCD_FORCE_SYNC_ACTIVE_HIGH
+       if (for_ext_vga_dac)
+               val = 0;
+#endif
        writel(val, &lcdc->tcon0_io_polarity);
 
        writel(0, &lcdc->tcon0_io_tristate);
@@ -1015,7 +1022,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
                        hitachi_tx18d42vm_init();
                }
                sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon0_mode_set(mode);
+               sunxi_lcdc_tcon0_mode_set(mode, false);
                sunxi_composer_enable();
                sunxi_lcdc_enable();
 #ifdef CONFIG_VIDEO_LCD_SSD2828
@@ -1033,7 +1040,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
                sunxi_vga_enable();
 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
                sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon0_mode_set(mode);
+               sunxi_lcdc_tcon0_mode_set(mode, true);
                sunxi_composer_enable();
                sunxi_lcdc_enable();
                sunxi_vga_external_dac_enable();
@@ -1054,6 +1061,11 @@ static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
        return NULL; /* never reached */
 }
 
+ulong board_get_usable_ram_top(ulong total_size)
+{
+       return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
+}
+
 void *video_hw_init(void)
 {
        static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
@@ -1069,10 +1081,6 @@ void *video_hw_init(void)
 
        memset(&sunxi_display, 0, sizeof(struct sunxi_display));
 
-       printf("Reserved %dkB of RAM for Framebuffer.\n",
-              CONFIG_SUNXI_FB_SIZE >> 10);
-       gd->fb_base = gd->ram_top;
-
        video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
                                 &sunxi_display.depth, &options);
 #ifdef CONFIG_VIDEO_HDMI
@@ -1163,6 +1171,17 @@ void *video_hw_init(void)
                       mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));
        }
 
+       sunxi_display.fb_size =
+               (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
+       if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) {
+               printf("Error need %dkB for fb, but only %dkB is reserved\n",
+                      sunxi_display.fb_size >> 10,
+                      CONFIG_SUNXI_MAX_FB_SIZE >> 10);
+               return NULL;
+       }
+
+       gd->fb_base = gd->bd->bi_dram[0].start +
+                     gd->bd->bi_dram[0].size - sunxi_display.fb_size;
        sunxi_engines_init();
        sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
 
@@ -1188,6 +1207,7 @@ int sunxi_simplefb_setup(void *blob)
 {
        static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
        int offset, ret;
+       u64 start, size;
        const char *pipeline = NULL;
 
 #ifdef CONFIG_MACH_SUN4I
@@ -1231,6 +1251,20 @@ int sunxi_simplefb_setup(void *blob)
                return 0; /* Keep older kernels working */
        }
 
+       /*
+        * Do not report the framebuffer as free RAM to the OS, note we cannot
+        * use fdt_add_mem_rsv() here, because then it is still seen as RAM,
+        * and e.g. Linux refuses to iomap RAM on ARM, see:
+        * linux/arch/arm/mm/ioremap.c around line 301.
+        */
+       start = gd->bd->bi_dram[0].start;
+       size = gd->bd->bi_dram[0].size - sunxi_display.fb_size;
+       ret = fdt_fixup_memory_banks(blob, &start, &size, 1);
+       if (ret) {
+               eprintf("Cannot setup simplefb: Error reserving memory\n");
+               return ret;
+       }
+
        ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base,
                        graphic_device->winSizeX, graphic_device->winSizeY,
                        graphic_device->winSizeX * graphic_device->gdfBytesPP,