]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
video: sunxi_display: Convert to DM_VIDEO
authorJagan Teki <jagan@amarulasolutions.com>
Mon, 22 Feb 2021 00:12:34 +0000 (00:12 +0000)
committerAnatolij Gustschin <agust@denx.de>
Wed, 3 Mar 2021 09:03:15 +0000 (10:03 +0100)
DM_VIDEO migration deadline is already expired, but around
80 Allwinner boards are still using video in a legacy way:

===================== WARNING ======================
This board does not use CONFIG_DM_VIDEO Please update
the board to use CONFIG_DM_VIDEO before the v2019.07 release.
Failure to update by the deadline may result in board removal.
See doc/driver-model/migration.rst for more info.
====================================================

Convert the legacy video driver over to the DM_VIDEO framework. This is
a minimal conversion: it doesn't use the DT for finding its resources,
nor does it use DM clocks or DM devices for the outputs (LCD, HDMI, CVBS).

Tested in Bananapi M1+ Plus 1920x1200 HDMI out. (Jagan)

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
[Andre: rebase and smaller fixes]
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: Simon Glass <sjg@chromium.org>
arch/arm/mach-sunxi/Kconfig
drivers/video/sunxi/sunxi_display.c
include/configs/sunxi-common.h
scripts/config_whitelist.txt

index 0135575ca1ebbde0c0d70b953f97f6a85454c17b..a29d11505aa43d2c54ce24a33e8d92b3cd016c10 100644 (file)
@@ -816,13 +816,14 @@ config VIDEO_SUNXI
        depends on !MACH_SUN9I
        depends on !MACH_SUN50I
        depends on !SUN50I_GEN_H6
-       select VIDEO
+       select DM_VIDEO
+       select DISPLAY
        imply VIDEO_DT_SIMPLEFB
        default y
        ---help---
-       Say Y here to add support for using a cfb console on the HDMI, LCD
-       or VGA output found on most sunxi devices. See doc/README.video for
-       info on how to select the video output and mode.
+       Say Y here to add support for using a graphical console on the HDMI,
+       LCD or VGA output found on older sunxi devices. This will also provide
+       a simple_framebuffer device for Linux.
 
 config VIDEO_HDMI
        bool "HDMI output support"
index f52aba4d21c098aab5c2c5b43e98583cd36ccec5..4361a58cd7e39f752cbac103968e543f48654ddd 100644 (file)
@@ -7,6 +7,8 @@
  */
 
 #include <common.h>
+#include <display.h>
+#include <dm.h>
 #include <cpu_func.h>
 #include <efi_loader.h>
 #include <init.h>
@@ -28,7 +30,9 @@
 #include <fdt_support.h>
 #include <i2c.h>
 #include <malloc.h>
+#include <video.h>
 #include <video_fb.h>
+#include <dm/uclass-internal.h>
 #include "../videomodes.h"
 #include "../anx9804.h"
 #include "../hitachi_tx18d42vm_lcd.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
+/* Maximum LCD size we support */
+#define LCD_MAX_WIDTH          3840
+#define LCD_MAX_HEIGHT         2160
+#define LCD_MAX_LOG2_BPP       VIDEO_BPP32
+
 enum sunxi_monitor {
        sunxi_monitor_none,
        sunxi_monitor_dvi,
@@ -58,13 +67,12 @@ enum sunxi_monitor {
 };
 #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
 
-struct sunxi_display {
-       GraphicDevice graphic_device;
+struct sunxi_display_priv {
        enum sunxi_monitor monitor;
        unsigned int depth;
        unsigned int fb_addr;
        unsigned int fb_size;
-} sunxi_display;
+};
 
 const struct ctfb_res_modes composite_video_modes[2] = {
        /*  x     y  hz  pixclk ps/kHz   le   ri  up  lo   hs vs  s  vmode */
@@ -214,7 +222,8 @@ static int sunxi_hdmi_edid_get_block(int block, u8 *buf)
        return r;
 }
 
-static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode,
+static int sunxi_hdmi_edid_get_mode(struct sunxi_display_priv *sunxi_display,
+                                   struct ctfb_res_modes *mode,
                                    bool verbose_mode)
 {
        struct edid1_info edid1;
@@ -291,14 +300,14 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode,
        }
 
        /* Check for basic audio support, if found enable hdmi output */
-       sunxi_display.monitor = sunxi_monitor_dvi;
+       sunxi_display->monitor = sunxi_monitor_dvi;
        for (i = 0; i < ext_blocks; i++) {
                if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG ||
                    cea681[i].revision < 2)
                        continue;
 
                if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i]))
-                       sunxi_display.monitor = sunxi_monitor_hdmi;
+                       sunxi_display->monitor = sunxi_monitor_hdmi;
        }
 
        return 0;
@@ -414,9 +423,9 @@ static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
 static void sunxi_frontend_enable(void) {}
 #endif
 
-static bool sunxi_is_composite(void)
+static bool sunxi_is_composite(enum sunxi_monitor monitor)
 {
-       switch (sunxi_display.monitor) {
+       switch (monitor) {
        case sunxi_monitor_none:
        case sunxi_monitor_dvi:
        case sunxi_monitor_hdmi:
@@ -473,7 +482,8 @@ static const u32 sunxi_rgb2yuv_coef[12] = {
 };
 
 static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
-                                   unsigned int address)
+                                   unsigned int address,
+                                   enum sunxi_monitor monitor)
 {
        struct sunxi_de_be_reg * const de_be =
                (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
@@ -502,7 +512,7 @@ static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
 #endif
                             SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
 
-       if (sunxi_is_composite()) {
+       if (sunxi_is_composite(monitor)) {
                writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
                       &de_be->output_color_ctrl);
                for (i = 0; i < 12; i++)
@@ -616,7 +626,8 @@ static void sunxi_lcdc_backlight_enable(void)
                gpio_direction_output(pin, PWM_ON);
 }
 
-static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
+static void sunxi_lcdc_tcon0_mode_set(struct sunxi_display_priv *sunxi_display,
+                                     const struct ctfb_res_modes *mode,
                                      bool for_ext_vga_dac)
 {
        struct sunxi_lcdc_reg * const lcdc =
@@ -643,17 +654,18 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
        }
 
        lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double,
-                    sunxi_is_composite());
+                    sunxi_is_composite(sunxi_display->monitor));
 
        video_ctfb_mode_to_display_timing(mode, &timing);
        lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac,
-                           sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
+                           sunxi_display->depth, CONFIG_VIDEO_LCD_DCLK_PHASE);
 }
 
 #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
 static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
                                      int *clk_div, int *clk_double,
-                                     bool use_portd_hvsync)
+                                     bool use_portd_hvsync,
+                                     enum sunxi_monitor monitor)
 {
        struct sunxi_lcdc_reg * const lcdc =
                (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
@@ -663,7 +675,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
 
        video_ctfb_mode_to_display_timing(mode, &timing);
        lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync,
-                           sunxi_is_composite());
+                           sunxi_is_composite(monitor));
 
        if (use_portd_hvsync) {
                sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0);
@@ -671,7 +683,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
        }
 
        lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double,
-                    sunxi_is_composite());
+                    sunxi_is_composite(monitor));
 }
 #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
 
@@ -725,7 +737,8 @@ static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
 }
 
 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
-                               int clk_div, int clk_double)
+                               int clk_div, int clk_double,
+                               enum sunxi_monitor monitor)
 {
        struct sunxi_hdmi_reg * const hdmi =
                (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
@@ -734,7 +747,7 @@ static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
        /* Write clear interrupt status bits */
        writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
 
-       if (sunxi_display.monitor == sunxi_monitor_hdmi)
+       if (monitor == sunxi_monitor_hdmi)
                sunxi_hdmi_setup_info_frames(mode);
 
        /* Set input sync enable */
@@ -789,7 +802,7 @@ static void sunxi_hdmi_enable(void)
 
 #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
 
-static void sunxi_tvencoder_mode_set(void)
+static void sunxi_tvencoder_mode_set(enum sunxi_monitor monitor)
 {
        struct sunxi_ccm_reg * const ccm =
                (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
@@ -801,7 +814,7 @@ static void sunxi_tvencoder_mode_set(void)
        /* Clock on */
        setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
 
-       switch (sunxi_display.monitor) {
+       switch (monitor) {
        case sunxi_monitor_vga:
                tvencoder_mode_set(tve, tve_mode_vga);
                break;
@@ -896,26 +909,28 @@ static void sunxi_engines_init(void)
        sunxi_drc_init();
 }
 
-static void sunxi_mode_set(const struct ctfb_res_modes *mode,
+static void sunxi_mode_set(struct sunxi_display_priv *sunxi_display,
+                          const struct ctfb_res_modes *mode,
                           unsigned int address)
 {
+       enum sunxi_monitor monitor = sunxi_display->monitor;
        int __maybe_unused clk_div, clk_double;
        struct sunxi_lcdc_reg * const lcdc =
                (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
        struct sunxi_tve_reg * __maybe_unused const tve =
                (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
 
-       switch (sunxi_display.monitor) {
+       switch (sunxi_display->monitor) {
        case sunxi_monitor_none:
                break;
        case sunxi_monitor_dvi:
        case sunxi_monitor_hdmi:
 #ifdef CONFIG_VIDEO_HDMI
-               sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
-               sunxi_hdmi_mode_set(mode, clk_div, clk_double);
+               sunxi_composer_mode_set(mode, address, monitor);
+               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
+               sunxi_hdmi_mode_set(mode, clk_div, clk_double, monitor);
                sunxi_composer_enable();
-               lcdc_enable(lcdc, sunxi_display.depth);
+               lcdc_enable(lcdc, sunxi_display->depth);
                sunxi_hdmi_enable();
 #endif
                break;
@@ -930,7 +945,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
                        axp_set_eldo(3, 1800);
                        anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4,
                                     ANX9804_DATA_RATE_1620M,
-                                    sunxi_display.depth);
+                                    sunxi_display->depth);
                }
                if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) {
                        mdelay(50); /* Wait for lcd controller power on */
@@ -942,10 +957,10 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
                        i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */
                        i2c_set_bus_num(orig_i2c_bus);
                }
-               sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon0_mode_set(mode, false);
+               sunxi_composer_mode_set(mode, address, monitor);
+               sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, false);
                sunxi_composer_enable();
-               lcdc_enable(lcdc, sunxi_display.depth);
+               lcdc_enable(lcdc, sunxi_display->depth);
 #ifdef CONFIG_VIDEO_LCD_SSD2828
                sunxi_ssd2828_init(mode);
 #endif
@@ -953,17 +968,17 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
                break;
        case sunxi_monitor_vga:
 #ifdef CONFIG_VIDEO_VGA
-               sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
-               sunxi_tvencoder_mode_set();
+               sunxi_composer_mode_set(mode, address, monitor);
+               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1, monitor);
+               sunxi_tvencoder_mode_set(monitor);
                sunxi_composer_enable();
-               lcdc_enable(lcdc, sunxi_display.depth);
+               lcdc_enable(lcdc, sunxi_display->depth);
                tvencoder_enable(tve);
 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
-               sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon0_mode_set(mode, true);
+               sunxi_composer_mode_set(mode, address, monitor);
+               sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, true);
                sunxi_composer_enable();
-               lcdc_enable(lcdc, sunxi_display.depth);
+               lcdc_enable(lcdc, sunxi_display->depth);
                sunxi_vga_external_dac_enable();
 #endif
                break;
@@ -972,11 +987,11 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
        case sunxi_monitor_composite_pal_m:
        case sunxi_monitor_composite_pal_nc:
 #ifdef CONFIG_VIDEO_COMPOSITE
-               sunxi_composer_mode_set(mode, address);
-               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
-               sunxi_tvencoder_mode_set();
+               sunxi_composer_mode_set(mode, address, monitor);
+               sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor);
+               sunxi_tvencoder_mode_set(monitor);
                sunxi_composer_enable();
-               lcdc_enable(lcdc, sunxi_display.depth);
+               lcdc_enable(lcdc, sunxi_display->depth);
                tvencoder_enable(tve);
 #endif
                break;
@@ -999,11 +1014,6 @@ static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
        }
 }
 
-ulong board_get_usable_ram_top(ulong total_size)
-{
-       return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
-}
-
 static bool sunxi_has_hdmi(void)
 {
 #ifdef CONFIG_VIDEO_HDMI
@@ -1052,9 +1062,11 @@ static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
                return sunxi_monitor_none;
 }
 
-void *video_hw_init(void)
+static int sunxi_de_probe(struct udevice *dev)
 {
-       static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
+       struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+       struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+       struct sunxi_display_priv *sunxi_display = dev_get_priv(dev);
        const struct ctfb_res_modes *mode;
        struct ctfb_res_modes custom;
        const char *options;
@@ -1067,10 +1079,8 @@ void *video_hw_init(void)
        char mon[16];
        char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
 
-       memset(&sunxi_display, 0, sizeof(struct sunxi_display));
-
        video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode,
-                                &sunxi_display.depth, &options);
+                                &sunxi_display->depth, &options);
 #ifdef CONFIG_VIDEO_HDMI
        hpd = video_get_option_int(options, "hpd", 1);
        hpd_delay = video_get_option_int(options, "hpd_delay", 500);
@@ -1078,35 +1088,35 @@ void *video_hw_init(void)
 #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);
+       sunxi_display->monitor = sunxi_get_default_mon(true);
        video_get_option_string(options, "monitor", mon, sizeof(mon),
-                               sunxi_get_mon_desc(sunxi_display.monitor));
+                               sunxi_get_mon_desc(sunxi_display->monitor));
        for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
                if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) {
-                       sunxi_display.monitor = i;
+                       sunxi_display->monitor = i;
                        break;
                }
        }
        if (i > SUNXI_MONITOR_LAST)
                printf("Unknown monitor: '%s', falling back to '%s'\n",
-                      mon, sunxi_get_mon_desc(sunxi_display.monitor));
+                      mon, sunxi_get_mon_desc(sunxi_display->monitor));
 
 #ifdef CONFIG_VIDEO_HDMI
        /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */
-       if (sunxi_display.monitor == sunxi_monitor_dvi ||
-           sunxi_display.monitor == sunxi_monitor_hdmi) {
+       if (sunxi_display->monitor == sunxi_monitor_dvi ||
+           sunxi_display->monitor == sunxi_monitor_hdmi) {
                /* Always call hdp_detect, as it also enables clocks, etc. */
                hdmi_present = (sunxi_hdmi_hpd_detect(hpd_delay) == 1);
                if (hdmi_present && edid) {
                        printf("HDMI connected: ");
-                       if (sunxi_hdmi_edid_get_mode(&custom, true) == 0)
+                       if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, true) == 0)
                                mode = &custom;
                        else
                                hdmi_present = false;
                }
                /* Fall back to EDID in case HPD failed */
                if (edid && !hdmi_present) {
-                       if (sunxi_hdmi_edid_get_mode(&custom, false) == 0) {
+                       if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, false) == 0) {
                                mode = &custom;
                                hdmi_present = true;
                        }
@@ -1114,38 +1124,39 @@ void *video_hw_init(void)
                /* Shut down when display was not found */
                if ((hpd || edid) && !hdmi_present) {
                        sunxi_hdmi_shutdown();
-                       sunxi_display.monitor = sunxi_get_default_mon(false);
+                       sunxi_display->monitor = sunxi_get_default_mon(false);
                } /* else continue with hdmi/dvi without a cable connected */
        }
 #endif
 
-       switch (sunxi_display.monitor) {
+       switch (sunxi_display->monitor) {
        case sunxi_monitor_none:
-               return NULL;
+               printf("Unknown monitor\n");
+               return -EINVAL;
        case sunxi_monitor_dvi:
        case sunxi_monitor_hdmi:
                if (!sunxi_has_hdmi()) {
                        printf("HDMI/DVI not supported on this board\n");
-                       sunxi_display.monitor = sunxi_monitor_none;
-                       return NULL;
+                       sunxi_display->monitor = sunxi_monitor_none;
+                       return -EINVAL;
                }
                break;
        case sunxi_monitor_lcd:
                if (!sunxi_has_lcd()) {
                        printf("LCD not supported on this board\n");
-                       sunxi_display.monitor = sunxi_monitor_none;
-                       return NULL;
+                       sunxi_display->monitor = sunxi_monitor_none;
+                       return -EINVAL;
                }
-               sunxi_display.depth = video_get_params(&custom, lcd_mode);
+               sunxi_display->depth = video_get_params(&custom, lcd_mode);
                mode = &custom;
                break;
        case sunxi_monitor_vga:
                if (!sunxi_has_vga()) {
                        printf("VGA not supported on this board\n");
-                       sunxi_display.monitor = sunxi_monitor_none;
-                       return NULL;
+                       sunxi_display->monitor = sunxi_monitor_none;
+                       return -EINVAL;
                }
-               sunxi_display.depth = 18;
+               sunxi_display->depth = 18;
                break;
        case sunxi_monitor_composite_pal:
        case sunxi_monitor_composite_ntsc:
@@ -1153,85 +1164,99 @@ void *video_hw_init(void)
        case sunxi_monitor_composite_pal_nc:
                if (!sunxi_has_composite()) {
                        printf("Composite video not supported on this board\n");
-                       sunxi_display.monitor = sunxi_monitor_none;
-                       return NULL;
+                       sunxi_display->monitor = sunxi_monitor_none;
+                       return -EINVAL;
                }
-               if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
-                   sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
+               if (sunxi_display->monitor == sunxi_monitor_composite_pal ||
+                   sunxi_display->monitor == sunxi_monitor_composite_pal_nc)
                        mode = &composite_video_modes[0];
                else
                        mode = &composite_video_modes[1];
-               sunxi_display.depth = 24;
+               sunxi_display->depth = 24;
                break;
        }
 
        /* Yes these defaults are quite high, overscan on composite sucks... */
        if (overscan_x == -1)
-               overscan_x = sunxi_is_composite() ? 32 : 0;
+               overscan_x = sunxi_is_composite(sunxi_display->monitor) ? 32 : 0;
        if (overscan_y == -1)
-               overscan_y = sunxi_is_composite() ? 20 : 0;
+               overscan_y = sunxi_is_composite(sunxi_display->monitor) ? 20 : 0;
 
-       sunxi_display.fb_size =
-               (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
+       sunxi_display->fb_size = plat->size;
        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,
-                      CONFIG_SUNXI_MAX_FB_SIZE >> 10);
-               return NULL;
-       }
+               sunxi_display->fb_size += 0x1000;
 
        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_display->fb_addr = plat->base;
        sunxi_engines_init();
 
 #ifdef CONFIG_EFI_LOADER
-       efi_add_memory_map(gd->fb_base, sunxi_display.fb_size,
+       efi_add_memory_map(sunxi_display->fb_addr, sunxi_display->fb_size,
                           EFI_RESERVED_MEMORY_TYPE);
 #endif
 
-       fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE;
-       sunxi_display.fb_addr = gd->fb_base;
+       fb_dma_addr = sunxi_display->fb_addr - CONFIG_SYS_SDRAM_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_display->fb_addr += ALIGN(overscan_offset, 0x1000);
+               memset((void *)sunxi_display->fb_addr, 0, sunxi_display->fb_size);
+               flush_cache(sunxi_display->fb_addr, sunxi_display->fb_size);
        }
-       sunxi_mode_set(mode, fb_dma_addr);
+       sunxi_mode_set(sunxi_display, mode, fb_dma_addr);
 
-       /*
-        * These are the only members of this structure that are used. All the
-        * others are driver specific. The pitch is stored in plnSizeX.
-        */
-       graphic_device->frameAdrs = sunxi_display.fb_addr;
-       graphic_device->gdfIndex = GDF_32BIT_X888RGB;
-       graphic_device->gdfBytesPP = 4;
-       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;
+       /* The members of struct video_priv to be set by the driver. */
+       uc_priv->bpix = VIDEO_BPP32;
+       uc_priv->xsize = mode->xres;
+       uc_priv->ysize = mode->yres;
+
+       video_set_flush_dcache(dev, true);
+
+       return 0;
 }
 
+static int sunxi_de_bind(struct udevice *dev)
+{
+       struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+
+       plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * VNBYTES(LCD_MAX_LOG2_BPP);
+
+       return 0;
+}
+
+static const struct video_ops sunxi_de_ops = {
+};
+
+U_BOOT_DRIVER(sunxi_de) = {
+       .name   = "sunxi_de",
+       .id     = UCLASS_VIDEO,
+       .ops    = &sunxi_de_ops,
+       .bind   = sunxi_de_bind,
+       .probe  = sunxi_de_probe,
+       .priv_auto = sizeof(struct sunxi_display_priv),
+       .flags  = DM_FLAG_PRE_RELOC,
+};
+
+U_BOOT_DRVINFO(sunxi_de) = {
+       .name = "sunxi_de"
+};
+
 /*
  * Simplefb support.
  */
 #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB)
 int sunxi_simplefb_setup(void *blob)
 {
-       static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
+       struct sunxi_display_priv *sunxi_display;
+       struct video_priv *uc_priv;
+       struct udevice *de;
        int offset, ret;
        u64 start, size;
        const char *pipeline = NULL;
@@ -1242,7 +1267,19 @@ int sunxi_simplefb_setup(void *blob)
 #define PIPELINE_PREFIX
 #endif
 
-       switch (sunxi_display.monitor) {
+       ret = uclass_find_device_by_name(UCLASS_VIDEO, "sunxi_de", &de);
+       if (ret) {
+               printf("DE not present\n");
+               return 0;
+       } else if (!device_active(de)) {
+               printf("DE is present but not probed\n");
+               return 0;
+       }
+
+       uc_priv = dev_get_uclass_priv(de);
+       sunxi_display = dev_get_priv(de);
+
+       switch (sunxi_display->monitor) {
        case sunxi_monitor_none:
                return 0;
        case sunxi_monitor_dvi:
@@ -1280,16 +1317,17 @@ int sunxi_simplefb_setup(void *blob)
         * 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;
+       size = sunxi_display->fb_addr - start;
        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, sunxi_display.fb_addr,
-                       graphic_device->winSizeX, graphic_device->winSizeY,
-                       graphic_device->plnSizeX, "x8r8g8b8");
+       ret = fdt_setup_simplefb_node(blob, offset, sunxi_display->fb_addr,
+                                     uc_priv->xsize, uc_priv->ysize,
+                                     VNBYTES(uc_priv->bpix) * uc_priv->xsize,
+                                     "x8r8g8b8");
        if (ret)
                eprintf("Cannot setup simplefb: Error setting properties\n");
 
index 7b602dd9ea453da7629ca178a8085394b0b98148..33a4d7b63736fd1fe10bc6e2bba709e0145a2375 100644 (file)
@@ -223,23 +223,6 @@ extern int soft_i2c_gpio_scl;
 #define CONFIG_VIDEO_LCD_I2C_BUS       -1 /* NA, but necessary to compile */
 #endif
 
-#ifdef CONFIG_VIDEO_SUNXI
-/*
- * The amount of RAM to keep free at the top of RAM when relocating u-boot,
- * to use as framebuffer. This must be a multiple of 4096.
- */
-#define CONFIG_SUNXI_MAX_FB_SIZE (16 << 20)
-
-#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. */
-/* stop x86 thinking in cfbconsole from trying to init a pc keyboard */
-
-#endif /* CONFIG_VIDEO_SUNXI */
-
 /* Ethernet support */
 
 #ifdef CONFIG_USB_EHCI_HCD
@@ -401,11 +384,7 @@ extern int soft_i2c_gpio_scl;
        "stdin=serial\0"
 #endif
 
-#ifdef CONFIG_VIDEO
-#define CONSOLE_STDOUT_SETTINGS \
-       "stdout=serial,vga\0" \
-       "stderr=serial,vga\0"
-#elif CONFIG_DM_VIDEO
+#ifdef CONFIG_DM_VIDEO
 #define CONSOLE_STDOUT_SETTINGS \
        "stdout=serial,vidconsole\0" \
        "stderr=serial,vidconsole\0"
index c8c87900ce8fab2d724dc5c39cab96aea8beaf1e..7340e95bd4ef26285b8d5752ccb5ac057f8b8a71 100644 (file)
@@ -1636,7 +1636,6 @@ CONFIG_STV0991
 CONFIG_STV0991_HZ
 CONFIG_STV0991_HZ_CLOCK
 CONFIG_ST_SMI
-CONFIG_SUNXI_MAX_FB_SIZE
 CONFIG_SXNI855T
 CONFIG_SYSFLAGS_ADDR
 CONFIG_SYSFS