]> git.sur5r.net Git - u-boot/commitdiff
sunxi: display: Add overscan correction
authorHans de Goede <hdegoede@redhat.com>
Tue, 4 Aug 2015 22:06:47 +0000 (00:06 +0200)
committerHans de Goede <hdegoede@redhat.com>
Fri, 14 Aug 2015 06:37:36 +0000 (08:37 +0200)
Add support for making the visual area of the framebuffer smaller and
drawing a black border around it. This is intended for use with
overscanning monitors (esp. with composite video out), to avoid part
of the picture being invisible.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Ian Campbell <ijc@hellion.org.uk>
Acked-by: Anatolij Gustschin <agust@denx.de>
doc/README.video
drivers/video/sunxi_display.c
include/configs/sunxi-common.h

index 4f7a4b5db54b4ade757d09f252ca272cfe4ffb24..62ac17b0490f96cbbc07665eb6411dfa039aa332 100644 (file)
@@ -68,6 +68,11 @@ The sunxi u-boot driver supports the following video-mode options:
     overrides the xres, yres and refresh from the video-mode env. variable.
  Defaults to edid=1.
 
+- overscan_x/overscan_y=<int> - Set x/y overscan value
+ This configures a black border on the left and right resp. top and bottom
+ to deal with overscanning displays. Defaults to overscan_x=32 and
+ overscan_y=20 for composite monitors, 0 for other monitors.
+
 For example to always use the hdmi connector, even if no cable is inserted,
 using edid info when available and otherwise initalizing it at 1024x768@60Hz,
 use: "setenv video-mode sunxi:1024x768-24@60,monitor=dvi,hpd=0,edid=1".
index 18681850587c61e9bddb638c8b38db520a2383c7..7c1ea8f2f6a903529398e036ac3e66eaffa5c29e 100644 (file)
@@ -19,6 +19,7 @@
 #include <fdtdec.h>
 #include <fdt_support.h>
 #include <i2c.h>
+#include <malloc.h>
 #include <video_fb.h>
 #include "videomodes.h"
 #include "hitachi_tx18d42vm_lcd.h"
@@ -51,6 +52,7 @@ struct sunxi_display {
        GraphicDevice graphic_device;
        enum sunxi_monitor monitor;
        unsigned int depth;
+       unsigned int fb_addr;
        unsigned int fb_size;
 } sunxi_display;
 
@@ -1297,9 +1299,10 @@ void *video_hw_init(void)
 #ifdef CONFIG_VIDEO_HDMI
        int ret, hpd, hpd_delay, edid;
 #endif
+       int i, overscan_offset, overscan_x, overscan_y;
+       unsigned int fb_dma_addr;
        char mon[16];
        char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
-       int i;
 
        memset(&sunxi_display, 0, sizeof(struct sunxi_display));
 
@@ -1310,6 +1313,8 @@ void *video_hw_init(void)
        hpd_delay = video_get_option_int(options, "hpd_delay", 500);
        edid = video_get_option_int(options, "edid", 1);
 #endif
+       overscan_x = video_get_option_int(options, "overscan_x", -1);
+       overscan_y = video_get_option_int(options, "overscan_y", -1);
        sunxi_display.monitor = sunxi_get_default_mon(true);
        video_get_option_string(options, "monitor", mon, sizeof(mon),
                                sunxi_get_mon_desc(sunxi_display.monitor));
@@ -1386,8 +1391,20 @@ void *video_hw_init(void)
                break;
        }
 
+       /* Yes these defaults are quite high, overscan on composite sucks... */
+       if (overscan_x == -1)
+               overscan_x = sunxi_is_composite() ? 32 : 0;
+       if (overscan_y == -1)
+               overscan_y = sunxi_is_composite() ? 20 : 0;
+
        sunxi_display.fb_size =
                (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
+       overscan_offset = (overscan_y * mode->xres + overscan_x) * 4;
+       /* We want to keep the fb_base for simplefb page aligned, where as
+        * the sunxi dma engines will happily accept an unaligned address. */
+       if (overscan_offset)
+               sunxi_display.fb_size += 0x1000;
+
        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,
@@ -1395,25 +1412,36 @@ void *video_hw_init(void)
                return NULL;
        }
 
-       printf("Setting up a %dx%d%s %s console\n", mode->xres, mode->yres,
+       printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n",
+              mode->xres, mode->yres,
               (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
-              sunxi_get_mon_desc(sunxi_display.monitor));
+              sunxi_get_mon_desc(sunxi_display.monitor),
+              overscan_x, overscan_y);
 
        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);
+
+       fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
+       sunxi_display.fb_addr = gd->fb_base;
+       if (overscan_offset) {
+               fb_dma_addr += 0x1000 - (overscan_offset & 0xfff);
+               sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff;
+               memset((void *)gd->fb_base, 0, sunxi_display.fb_size);
+               flush_cache(gd->fb_base, sunxi_display.fb_size);
+       }
+       sunxi_mode_set(mode, fb_dma_addr);
 
        /*
         * These are the only members of this structure that are used. All the
-        * others are driver specific. There is nothing to decribe pitch or
-        * stride, but we are lucky with our hw.
+        * others are driver specific. The pitch is stored in plnSizeX.
         */
-       graphic_device->frameAdrs = gd->fb_base;
+       graphic_device->frameAdrs = sunxi_display.fb_addr;
        graphic_device->gdfIndex = GDF_32BIT_X888RGB;
        graphic_device->gdfBytesPP = 4;
-       graphic_device->winSizeX = mode->xres;
-       graphic_device->winSizeY = mode->yres;
+       graphic_device->winSizeX = mode->xres - 2 * overscan_x;
+       graphic_device->winSizeY = mode->yres - 2 * overscan_y;
+       graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP;
 
        return graphic_device;
 }
@@ -1490,10 +1518,9 @@ int sunxi_simplefb_setup(void *blob)
                return ret;
        }
 
-       ret = fdt_setup_simplefb_node(blob, offset, gd->fb_base,
+       ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr,
                        graphic_device->winSizeX, graphic_device->winSizeY,
-                       graphic_device->winSizeX * graphic_device->gdfBytesPP,
-                       "x8r8g8b8");
+                       graphic_device->plnSizeX, "x8r8g8b8");
        if (ret)
                eprintf("Cannot setup simplefb: Error setting properties\n");
 
index 0ecb91b78dfd94c827d00951fff5afaaec89fa26..7608f121caf3d3d24685d774d68b295d75b95c72 100644 (file)
@@ -300,6 +300,7 @@ extern int soft_i2c_gpio_scl;
 #define CONFIG_VIDEO_LOGO
 #define CONFIG_VIDEO_STD_TIMINGS
 #define CONFIG_I2C_EDID
+#define VIDEO_LINE_LEN (pGD->plnSizeX)
 
 /* allow both serial and cfb console. */
 #define CONFIG_CONSOLE_MUX