diff --git a/drivers/video/am335x-fb.c b/drivers/video/am335x-fb.c
index e53c1d276e..e8bd9c6464 100644
--- a/drivers/video/am335x-fb.c
+++ b/drivers/video/am335x-fb.c
@@ -2,6 +2,7 @@
 /*
  * Copyright (C) 2013-2018 Hannes Schmelzer <oe5hpm at oevsv.at>
  * B&R Industrial Automation GmbH - http://www.br-automation.com
+ * Copyright (C) 2020 Dario Binacchi <dariobin at libero.it>
  *
  * minimal framebuffer driver for TI's AM335x SoC to be compatible with
  * Wolfgang Denk's LCD-Framework (CONFIG_LCD, common/lcd.c)
@@ -11,19 +12,18 @@
  * - starts output DMA from gd->fb_base buffer
  */
 #include <common.h>
+#include <dm.h>
 #include <asm/io.h>
 #include <asm/arch/hardware.h>
 #include <asm/arch/omap.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/sys_proto.h>
+#include <asm/utils.h>
 #include <linux/err.h>
 #include <lcd.h>
+#include <video.h>
 #include "am335x-fb.h"
 
-#if !defined(LCD_CNTL_BASE)
-#error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!"
-#endif
-
 #define LCDC_FMAX				200000000
 
 /* LCD Control Register */
@@ -41,6 +41,7 @@
 #define LCDC_DMA_CTRL_BURST_4			0x2
 #define LCDC_DMA_CTRL_BURST_8			0x3
 #define LCDC_DMA_CTRL_BURST_16			0x4
+#define LCDC_DMA_CTRL_FIFO_TH(x)		(((x) & 0x07) << 8)
 /* LCD Timing_0 Register */
 #define LCDC_RASTER_TIMING_0_HORMSB(x)		(((((x) >> 4) - 1) & 0x40) >> 4)
 #define LCDC_RASTER_TIMING_0_HORLSB(x)		(((((x) >> 4) - 1) & 0x3F) << 4)
@@ -55,19 +56,26 @@
 /* LCD Timing_2 Register */
 #define LCDC_RASTER_TIMING_2_HFPMSB(x)		((((x) - 1) & 0x300) >> 8)
 #define LCDC_RASTER_TIMING_2_HBPMSB(x)		((((x) - 1) & 0x300) >> 4)
-#define LCDC_RASTER_TIMING_2_INVMASK(x)		((x) & 0x3F00000)
+#define LCDC_RASTER_TIMING_2_ACB(x)		(((x) & 0xFF) << 8)
+#define LCDC_RASTER_TIMING_2_ACBI(x)		(((x) & 0x0F) << 16)
+#define LCDC_RASTER_TIMING_2_VSYNC_INVERT	BIT(20)
+#define LCDC_RASTER_TIMING_2_HSYNC_INVERT	BIT(21)
+#define LCDC_RASTER_TIMING_2_PXCLK_INVERT	BIT(22)
+#define LCDC_RASTER_TIMING_2_DE_INVERT		BIT(23)
+#define LCDC_RASTER_TIMING_2_HSVS_RISEFALL	BIT(24)
+#define LCDC_RASTER_TIMING_2_HSVS_CONTROL	BIT(25)
 #define LCDC_RASTER_TIMING_2_VERMSB(x)		((((x) - 1) & 0x400) << 16)
 #define LCDC_RASTER_TIMING_2_HSWMSB(x)		((((x) - 1) & 0x3C0) << 21)
 /* LCD Raster Ctrl Register */
 #define LCDC_RASTER_CTRL_ENABLE			BIT(0)
 #define LCDC_RASTER_CTRL_TFT_MODE		BIT(7)
+#define LCDC_RASTER_CTRL_DATA_ORDER		BIT(8)
+#define LCDC_RASTER_CTRL_REQDLY(x)		(((x) & 0xFF) << 12)
 #define LCDC_RASTER_CTRL_PALMODE_RAWDATA	(0x02 << 20)
+#define LCDC_RASTER_CTRL_TFT_ALT_ENABLE		BIT(23)
 #define LCDC_RASTER_CTRL_TFT_24BPP_MODE		BIT(25)
 #define LCDC_RASTER_CTRL_TFT_24BPP_UNPACK	BIT(26)
 
-/* Macro definitions */
-#define FBSIZE(x)	((x->hactive * x->vactive * x->bpp) >> 3)
-
 struct am335x_lcdhw {
 	unsigned int		pid;			/* 0x00 */
 	unsigned int		ctrl;			/* 0x04 */
@@ -107,8 +115,6 @@ struct dpll_data {
 	u8 rounded_div;
 };
 
-static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE;
-
 DECLARE_GLOBAL_DATA_PTR;
 
 /**
@@ -189,6 +195,19 @@ static ulong am335x_fb_set_pixel_clk_rate(struct am335x_lcdhw *regs, ulong rate)
 	return round_rate;
 }
 
+#if !defined(CONFIG_DM_VIDEO)
+
+#if !defined(LCD_CNTL_BASE)
+#error "hw-base address of LCD-Controller (LCD_CNTL_BASE) not defined!"
+#endif
+
+/* Macro definitions */
+#define FBSIZE(x)	(((x)->hactive * (x)->vactive * (x)->bpp) >> 3)
+
+#define LCDC_RASTER_TIMING_2_INVMASK(x)		((x) & 0x3F00000)
+
+static struct am335x_lcdhw *lcdhw = (void *)LCD_CNTL_BASE;
+
 int lcd_get_size(int *line_length)
 {
 	*line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8;
@@ -299,3 +318,310 @@ int am335xfb_init(struct am335x_lcdpanel *panel)
 
 	return 0;
 }
+
+#else /* CONFIG_DM_VIDEO */
+
+#define FBSIZE(t, p)	(((t)->hactive.typ * (t)->vactive.typ * (p)->bpp) >> 3)
+
+enum {
+	LCD_MAX_WIDTH		= 2048,
+	LCD_MAX_HEIGHT		= 2048,
+	LCD_MAX_LOG2_BPP	= VIDEO_BPP32,
+};
+
+/**
+ * tilcdc_panel_info: Panel parameters
+ *
+ * @ac_bias: AC Bias Pin Frequency
+ * @ac_bias_intrpt: AC Bias Pin Transitions per Interrupt
+ * @dma_burst_sz: DMA burst size
+ * @bpp: Bits per pixel
+ * @fdd: FIFO DMA Request Delay
+ * @tft_alt_mode: TFT Alternative Signal Mapping (Only for active)
+ * @invert_pxl_clk: Invert pixel clock
+ * @sync_edge: Horizontal and Vertical Sync Edge: 0=rising 1=falling
+ * @sync_ctrl: Horizontal and Vertical Sync: Control: 0=ignore
+ * @raster_order: Raster Data Order Select: 1=Most-to-least 0=Least-to-most
+ * @fifo_th: DMA FIFO threshold
+ */
+struct tilcdc_panel_info {
+	u32 ac_bias;
+	u32 ac_bias_intrpt;
+	u32 dma_burst_sz;
+	u32 bpp;
+	u32 fdd;
+	bool tft_alt_mode;
+	bool invert_pxl_clk;
+	u32 sync_edge;
+	u32 sync_ctrl;
+	u32 raster_order;
+	u32 fifo_th;
+};
+
+struct am335x_fb_priv {
+	struct am335x_lcdhw *regs;
+	struct tilcdc_panel_info panel;
+	struct display_timing timing;
+};
+
+static int am335x_fb_remove(struct udevice *dev)
+{
+	struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
+
+	uc_plat->base -= 0x20;
+	uc_plat->size += 0x20;
+	return 0;
+}
+
+static int am335x_fb_probe(struct udevice *dev)
+{
+	struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
+	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+	struct am335x_fb_priv *priv = dev_get_priv(dev);
+	struct am335x_lcdhw *regs = priv->regs;
+	struct tilcdc_panel_info *panel = &priv->panel;
+	struct display_timing *timing = &priv->timing;
+	struct cm_dpll *const cmdpll = (struct cm_dpll *)CM_DPLL;
+	struct cm_perpll *const cmper = (struct cm_perpll *)CM_PER;
+	u32 *const clk_domains[] = { 0 };
+	u32 *const clk_modules[] = {
+		&cmper->lcdclkctrl,
+		&cmper->lcdcclkstctrl,
+		0
+	};
+	u32 reg;
+
+	/* Before relocation we don't need to do anything */
+	if (!(gd->flags & GD_FLG_RELOC))
+		return 0;
+
+	do_enable_clocks(clk_domains, clk_modules, 1);
+
+	am335x_fb_set_pixel_clk_rate(regs, timing->pixelclock.typ);
+
+	/* clock source for LCDC from dispPLL M2 */
+	writel(0, &cmdpll->clklcdcpixelclk);
+
+	/* palette default entry */
+	memset((void *)uc_plat->base, 0, 0x20);
+	*(unsigned int *)uc_plat->base = 0x4000;
+	/* point fb behind palette */
+	uc_plat->base += 0x20;
+	uc_plat->size -= 0x20;
+
+	writel(LCDC_CLKC_ENABLE_CORECLKEN | LCDC_CLKC_ENABLE_LIDDCLKEN |
+	       LCDC_CLKC_ENABLE_DMACLKEN, &regs->clkc_enable);
+	writel(0, &regs->raster_ctrl);
+
+	reg = readl(&regs->ctrl) & LCDC_CTRL_CLK_DIVISOR_MASK;
+	reg |= LCDC_CTRL_RASTER_MODE;
+	writel(reg, &regs->ctrl);
+
+	writel(uc_plat->base, &regs->lcddma_fb0_base);
+	writel(uc_plat->base + FBSIZE(timing, panel),
+	       &regs->lcddma_fb0_ceiling);
+	writel(uc_plat->base, &regs->lcddma_fb1_base);
+	writel(uc_plat->base + FBSIZE(timing, panel),
+	       &regs->lcddma_fb1_ceiling);
+
+	reg = LCDC_DMA_CTRL_FIFO_TH(panel->fifo_th);
+	switch (panel->dma_burst_sz) {
+	case 1:
+		reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_1);
+		break;
+	case 2:
+		reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_2);
+		break;
+	case 4:
+		reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_4);
+		break;
+	case 8:
+		reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_8);
+		break;
+	case 16:
+		reg |= LCDC_DMA_CTRL_BURST_SIZE(LCDC_DMA_CTRL_BURST_16);
+		break;
+	}
+
+	writel(reg, &regs->lcddma_ctrl);
+
+	writel(LCDC_RASTER_TIMING_0_HORLSB(timing->hactive.typ) |
+	       LCDC_RASTER_TIMING_0_HORMSB(timing->hactive.typ) |
+	       LCDC_RASTER_TIMING_0_HFPLSB(timing->hfront_porch.typ) |
+	       LCDC_RASTER_TIMING_0_HBPLSB(timing->hback_porch.typ) |
+	       LCDC_RASTER_TIMING_0_HSWLSB(timing->hsync_len.typ),
+	       &regs->raster_timing0);
+
+	writel(LCDC_RASTER_TIMING_1_VBP(timing->vback_porch.typ) |
+	       LCDC_RASTER_TIMING_1_VFP(timing->vfront_porch.typ) |
+	       LCDC_RASTER_TIMING_1_VSW(timing->vsync_len.typ) |
+	       LCDC_RASTER_TIMING_1_VERLSB(timing->vactive.typ),
+	       &regs->raster_timing1);
+
+	reg = LCDC_RASTER_TIMING_2_ACB(panel->ac_bias) |
+		LCDC_RASTER_TIMING_2_ACBI(panel->ac_bias_intrpt) |
+		LCDC_RASTER_TIMING_2_HSWMSB(timing->hsync_len.typ) |
+		LCDC_RASTER_TIMING_2_VERMSB(timing->vactive.typ) |
+		LCDC_RASTER_TIMING_2_HBPMSB(timing->hback_porch.typ) |
+		LCDC_RASTER_TIMING_2_HFPMSB(timing->hfront_porch.typ);
+
+	if (timing->flags & DISPLAY_FLAGS_VSYNC_LOW)
+		reg |= LCDC_RASTER_TIMING_2_VSYNC_INVERT;
+
+	if (timing->flags & DISPLAY_FLAGS_HSYNC_LOW)
+		reg |= LCDC_RASTER_TIMING_2_HSYNC_INVERT;
+
+	if (panel->invert_pxl_clk)
+		reg |= LCDC_RASTER_TIMING_2_PXCLK_INVERT;
+
+	if (panel->sync_edge)
+		reg |= LCDC_RASTER_TIMING_2_HSVS_RISEFALL;
+
+	if (panel->sync_ctrl)
+		reg |= LCDC_RASTER_TIMING_2_HSVS_CONTROL;
+
+	writel(reg, &regs->raster_timing2);
+
+	reg = LCDC_RASTER_CTRL_PALMODE_RAWDATA | LCDC_RASTER_CTRL_TFT_MODE |
+		LCDC_RASTER_CTRL_ENABLE | LCDC_RASTER_CTRL_REQDLY(panel->fdd);
+
+	if (panel->tft_alt_mode)
+		reg |= LCDC_RASTER_CTRL_TFT_ALT_ENABLE;
+
+	if (panel->bpp == 24)
+		reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE;
+	else if (panel->bpp == 32)
+		reg |= LCDC_RASTER_CTRL_TFT_24BPP_MODE |
+			LCDC_RASTER_CTRL_TFT_24BPP_UNPACK;
+
+	if (panel->raster_order)
+		reg |= LCDC_RASTER_CTRL_DATA_ORDER;
+
+	writel(reg, &regs->raster_ctrl);
+
+	uc_priv->xsize = timing->hactive.typ;
+	uc_priv->ysize = timing->vactive.typ;
+	uc_priv->bpix = log_2_n_round_up(panel->bpp);
+	return 0;
+}
+
+static int am335x_fb_ofdata_to_platdata(struct udevice *dev)
+{
+	struct am335x_fb_priv *priv = dev_get_priv(dev);
+	struct tilcdc_panel_info *panel = &priv->panel;
+	struct display_timing *timing = &priv->timing;
+	ofnode node;
+	int err;
+
+	node = ofnode_by_compatible(ofnode_null(), "ti,am33xx-tilcdc");
+	if (!ofnode_valid(node)) {
+		dev_err(dev, "missing 'ti,am33xx-tilcdc' node\n");
+		return -ENXIO;
+	}
+
+	priv->regs = (struct am335x_lcdhw *)ofnode_get_addr(node);
+	dev_dbg(dev, "LCD: base address=0x%x\n", (unsigned int)priv->regs);
+
+	err = ofnode_decode_display_timing(dev_ofnode(dev), 0, timing);
+	if (err) {
+		dev_err(dev, "failed to get display timing\n");
+		return err;
+	}
+
+	if (timing->pixelclock.typ > (LCDC_FMAX / 2)) {
+		dev_err(dev, "invalid display clock-frequency: %d Hz\n",
+			timing->pixelclock.typ);
+		return -EINVAL;
+	}
+
+	if (timing->hactive.typ > LCD_MAX_WIDTH)
+		timing->hactive.typ = LCD_MAX_WIDTH;
+
+	if (timing->vactive.typ > LCD_MAX_HEIGHT)
+		timing->vactive.typ = LCD_MAX_HEIGHT;
+
+	node = ofnode_find_subnode(dev_ofnode(dev), "panel-info");
+	if (!ofnode_valid(node)) {
+		dev_err(dev, "missing 'panel-info' node\n");
+		return -ENXIO;
+	}
+
+	err |= ofnode_read_u32(node, "ac-bias", &panel->ac_bias);
+	err |= ofnode_read_u32(node, "ac-bias-intrpt", &panel->ac_bias_intrpt);
+	err |= ofnode_read_u32(node, "dma-burst-sz", &panel->dma_burst_sz);
+	err |= ofnode_read_u32(node, "bpp", &panel->bpp);
+	err |= ofnode_read_u32(node, "fdd", &panel->fdd);
+	err |= ofnode_read_u32(node, "sync-edge", &panel->sync_edge);
+	err |= ofnode_read_u32(node, "sync-ctrl", &panel->sync_ctrl);
+	err |= ofnode_read_u32(node, "raster-order", &panel->raster_order);
+	err |= ofnode_read_u32(node, "fifo-th", &panel->fifo_th);
+	if (err) {
+		dev_err(dev, "failed to get panel info\n");
+		return err;
+	}
+
+	switch (panel->bpp) {
+	case 16:
+	case 24:
+	case 32:
+		break;
+	default:
+		dev_err(dev, "invalid seting, bpp: %d\n", panel->bpp);
+		return -EINVAL;
+	}
+
+	switch (panel->dma_burst_sz) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+	case 16:
+		break;
+	default:
+		dev_err(dev, "invalid setting, dma-burst-sz: %d\n",
+			panel->dma_burst_sz);
+		return -EINVAL;
+	}
+
+	/* optional */
+	panel->tft_alt_mode = ofnode_read_bool(node, "tft-alt-mode");
+	panel->invert_pxl_clk = ofnode_read_bool(node, "invert-pxl-clk");
+
+	dev_dbg(dev, "LCD: %dx%d, bpp=%d, clk=%d Hz\n", timing->hactive.typ,
+		timing->vactive.typ, panel->bpp, timing->pixelclock.typ);
+	dev_dbg(dev, "     hbp=%d, hfp=%d, hsw=%d\n", timing->hback_porch.typ,
+		timing->hfront_porch.typ, timing->hsync_len.typ);
+	dev_dbg(dev, "     vbp=%d, vfp=%d, vsw=%d\n", timing->vback_porch.typ,
+		timing->vfront_porch.typ, timing->vsync_len.typ);
+
+	return 0;
+}
+
+static int am335x_fb_bind(struct udevice *dev)
+{
+	struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev);
+
+	uc_plat->size = ((LCD_MAX_WIDTH * LCD_MAX_HEIGHT *
+			  (1 << LCD_MAX_LOG2_BPP)) >> 3) + 0x20;
+
+	dev_dbg(dev, "frame buffer size 0x%x\n", uc_plat->size);
+	return 0;
+}
+
+static const struct udevice_id am335x_fb_ids[] = {
+	{ .compatible = "ti,tilcdc,panel" },
+	{ }
+};
+
+U_BOOT_DRIVER(am335x_fb) = {
+	.name = "am335x_fb",
+	.id = UCLASS_VIDEO,
+	.of_match = am335x_fb_ids,
+	.bind = am335x_fb_bind,
+	.ofdata_to_platdata = am335x_fb_ofdata_to_platdata,
+	.probe = am335x_fb_probe,
+	.remove = am335x_fb_remove,
+	.priv_auto_alloc_size = sizeof(struct am335x_fb_priv),
+};
+
+#endif /* CONFIG_DM_VIDEO */
diff --git a/drivers/video/am335x-fb.h b/drivers/video/am335x-fb.h
index ad9b015e09..7e7ec02ea6 100644
--- a/drivers/video/am335x-fb.h
+++ b/drivers/video/am335x-fb.h
@@ -7,6 +7,8 @@
 #ifndef AM335X_FB_H
 #define AM335X_FB_H
 
+#if !defined(CONFIG_DM_VIDEO)
+
 #define HSVS_CONTROL		BIT(25)	/*
 					 * 0 = lcd_lp and lcd_fp are driven on
 					 * opposite edges of pixel clock than
@@ -68,4 +70,6 @@ struct am335x_lcdpanel {
 
 int am335xfb_init(struct am335x_lcdpanel *panel);
 
+#endif  /* CONFIG_DM_VIDEO */
+
 #endif  /* AM335X_FB_H */
