video: ipuv3: add DM_VIDEO support
authorAnatolij Gustschin <agust@denx.de>
Mon, 18 Mar 2019 22:29:31 +0000 (23:29 +0100)
committerStefano Babic <sbabic@denx.de>
Sat, 13 Apr 2019 18:30:09 +0000 (20:30 +0200)
Extend the driver to build with DM_VIDEO enabled. DTS files
must additionally include 'u-boot,dm-pre-reloc' property in
soc and ipu nodes to enable driver binding to ipu device.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
arch/arm/include/asm/mach-imx/video.h
arch/arm/mach-imx/video.c
drivers/video/Kconfig
drivers/video/mxc_ipuv3_fb.c

index 812e6f85e4346e21b1df812b20bc9d4aef6a4238..d1a14ad7d348256fd14a165b6cd692b3b8606983 100644 (file)
@@ -26,4 +26,5 @@ extern size_t display_count;
 #endif
 
 int ipu_set_ldb_clock(int rate);
+int ipu_displays_init(void);
 #endif
index 953fe53cb49a3a0d4a80e2e03f34cf29c3e21688..22a371a212d6c471d8fc6b5854152c3d738cf651 100644 (file)
@@ -4,6 +4,17 @@
 #include <linux/errno.h>
 #include <asm/mach-imx/video.h>
 
+#ifdef CONFIG_IMX_HDMI
+#include <asm/arch/mxc_hdmi.h>
+#include <asm/io.h>
+
+int detect_hdmi(struct display_info_t const *dev)
+{
+       struct hdmi_regs *hdmi  = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
+       return readb(&hdmi->phy_stat0) & HDMI_DVI_STAT;
+}
+#endif
+
 int board_video_skip(void)
 {
        int i;
@@ -42,6 +53,11 @@ int board_video_skip(void)
                               displays[i].mode.name,
                               displays[i].mode.xres,
                               displays[i].mode.yres);
+
+#ifdef CONFIG_IMX_HDMI
+                       if (!strcmp(displays[i].mode.name, "HDMI"))
+                               imx_enable_hdmi_phy();
+#endif
                } else
                        printf("LCD %s cannot be configured: %d\n",
                               displays[i].mode.name, ret);
@@ -53,12 +69,7 @@ int board_video_skip(void)
        return ret;
 }
 
-#ifdef CONFIG_IMX_HDMI
-#include <asm/arch/mxc_hdmi.h>
-#include <asm/io.h>
-int detect_hdmi(struct display_info_t const *dev)
+int ipu_displays_init(void)
 {
-       struct hdmi_regs *hdmi  = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR;
-       return readb(&hdmi->phy_stat0) & HDMI_DVI_STAT;
+       return board_video_skip();
 }
-#endif
index 2eac4b63813d20376ed23256ec01691b5cd74477..73a2402f41b8346c8afcb61ceafd3f73380960b1 100644 (file)
@@ -538,6 +538,13 @@ config VIDEO_TEGRA124
 
 source "drivers/video/bridge/Kconfig"
 
+config VIDEO_IPUV3
+       bool "i.MX IPUv3 Core video support"
+       depends on (VIDEO || DM_VIDEO) && (MX5 || MX6)
+       help
+         This enables framebuffer driver for i.MX processors working
+         on the IPUv3(Image Processing Unit) internal graphic processor.
+
 config VIDEO
        bool "Enable legacy video support"
        depends on !DM_VIDEO
@@ -547,13 +554,6 @@ config VIDEO
          model. Video drivers typically provide a colour text console and
          cursor.
 
-config VIDEO_IPUV3
-       bool "i.MX IPUv3 Core video support"
-       depends on VIDEO && MX6
-       help
-         This enables framebuffer driver for i.MX processors working
-         on the IPUv3(Image Processing Unit) internal graphic processor.
-
 config CFB_CONSOLE
        bool "Enable colour frame buffer console"
        depends on VIDEO
index 23cd55de47967a487e76383cf2c3f3faf3eabac4..5b3ba7b3a946d3938042fad2dbf1fde242da694c 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/fb.h>
 #include <asm/io.h>
+#include <asm/mach-imx/video.h>
 #include <malloc.h>
 #include <video_fb.h>
 #include "videomodes.h"
@@ -24,6 +25,9 @@
 #include "mxcfb.h"
 #include "ipu_regs.h"
 
+#include <dm.h>
+#include <video.h>
+
 DECLARE_GLOBAL_DATA_PTR;
 
 static int mxcfb_map_video_memory(struct fb_info *fbi);
@@ -401,8 +405,14 @@ static int mxcfb_map_video_memory(struct fb_info *fbi)
                                    fbi->fix.line_length;
        }
        fbi->fix.smem_len = roundup(fbi->fix.smem_len, ARCH_DMA_MINALIGN);
+
+#if CONFIG_IS_ENABLED(DM_VIDEO)
+       fbi->screen_base = (char *)gd->video_bottom;
+#else
        fbi->screen_base = (char *)memalign(ARCH_DMA_MINALIGN,
                                            fbi->fix.smem_len);
+#endif
+
        fbi->fix.smem_start = (unsigned long)fbi->screen_base;
        if (fbi->screen_base == 0) {
                puts("Unable to allocate framebuffer memory\n");
@@ -416,7 +426,9 @@ static int mxcfb_map_video_memory(struct fb_info *fbi)
 
        fbi->screen_size = fbi->fix.smem_len;
 
+#if CONFIG_IS_ENABLED(VIDEO)
        gd->fb_base = fbi->fix.smem_start;
+#endif
 
        /* Clear the screen */
        memset((char *)fbi->screen_base, 0, fbi->fix.smem_len);
@@ -611,3 +623,78 @@ int ipuv3_fb_init(struct fb_videomode const *mode,
 
        return 0;
 }
+
+#if CONFIG_IS_ENABLED(DM_VIDEO)
+enum {
+       /* Maximum display size we support */
+       LCD_MAX_WIDTH           = 1920,
+       LCD_MAX_HEIGHT          = 1080,
+       LCD_MAX_LOG2_BPP        = VIDEO_BPP16,
+};
+
+static int ipuv3_video_probe(struct udevice *dev)
+{
+       struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+       struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+       u32 fb_start, fb_end;
+       int ret;
+
+       debug("%s() plat: base 0x%lx, size 0x%x\n",
+             __func__, plat->base, plat->size);
+
+       ret = ipu_probe();
+       if (ret)
+               return ret;
+
+       ret = ipu_displays_init();
+       if (ret < 0)
+               return ret;
+
+       ret = mxcfb_probe(gpixfmt, gdisp, gmode);
+       if (ret < 0)
+               return ret;
+
+       uc_priv->xsize = gmode->xres;
+       uc_priv->ysize = gmode->yres;
+       uc_priv->bpix = LCD_MAX_LOG2_BPP;
+
+       /* Enable dcache for the frame buffer */
+       fb_start = plat->base & ~(MMU_SECTION_SIZE - 1);
+       fb_end = plat->base + plat->size;
+       fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT);
+       mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start,
+                                       DCACHE_WRITEBACK);
+       video_set_flush_dcache(dev, true);
+
+       return 0;
+}
+
+struct ipuv3_video_priv {
+       ulong regs;
+};
+
+static int ipuv3_video_bind(struct udevice *dev)
+{
+       struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
+
+       plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
+                    (1 << LCD_MAX_LOG2_BPP) / 8;
+
+       return 0;
+}
+
+static const struct udevice_id ipuv3_video_ids[] = {
+       { .compatible = "fsl,imx6q-ipu" },
+       { }
+};
+
+U_BOOT_DRIVER(ipuv3_video) = {
+       .name   = "ipuv3_video",
+       .id     = UCLASS_VIDEO,
+       .of_match = ipuv3_video_ids,
+       .bind   = ipuv3_video_bind,
+       .probe  = ipuv3_video_probe,
+       .priv_auto_alloc_size = sizeof(struct ipuv3_video_priv),
+       .flags  = DM_FLAG_PRE_RELOC,
+};
+#endif /* CONFIG_DM_VIDEO */