From 7e985b02d80fd6afe04858f2501f6e12868d0417 Mon Sep 17 00:00:00 2001
From: Zhiming Liu <zhiming.liu_1@nxp.com>
Date: Tue, 14 Mar 2023 12:06:54 +0800
Subject: [PATCH] [L5.15.32]Add i.MX8MP LVDS driver in uboot

---
 arch/arm/dts/imx8mp-evk.dts            |  56 ++++-
 arch/arm/dts/imx8mp.dtsi               | 116 ++++++++++-
 arch/arm/mach-imx/imx8m/clock_imx8mm.c |  15 +-
 configs/imx8mp_evk_defconfig           |   2 +
 drivers/core/device.c                  |  20 +-
 drivers/video/it6263_bridge.c          |   1 -
 drivers/video/nxp/imx/Kconfig          |   9 +
 drivers/video/nxp/imx/Makefile         |   1 +
 drivers/video/nxp/imx/imx8mp_lvds.c    | 278 +++++++++++++++++++++++++
 drivers/video/nxp/imx/imx_lcdifv3.c    |  31 ++-
 10 files changed, 488 insertions(+), 41 deletions(-)
 create mode 100644 drivers/video/nxp/imx/imx8mp_lvds.c

diff --git a/arch/arm/dts/imx8mp-evk.dts b/arch/arm/dts/imx8mp-evk.dts
index a5c797d357..56d1afab7c 100644
--- a/arch/arm/dts/imx8mp-evk.dts
+++ b/arch/arm/dts/imx8mp-evk.dts
@@ -307,12 +307,25 @@
 	sda-gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>;
 	status = "okay";
 
+	lvds_bridge: lvds-to-hdmi-bridge@4c {
+		compatible = "ite,it6263";
+		reg = <0x4c>;
+		reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
+		status = "okay";
+
+		port {
+			it6263_in: endpoint {
+				remote-endpoint = <&lvds_out>;
+			};
+		};
+	};
+
 	adv_bridge: adv7535@3d {
 		compatible = "adi,adv7533";
 		reg = <0x3d>;
 		adi,addr-cec = <0x3c>;
 		adi,dsi-lanes = <4>;
-		status = "okay";
+		status = "disabled";
 
 		port {
 			adv7535_from_dsim: endpoint {
@@ -379,12 +392,49 @@
 	};
 };
 
-&lcdif1 {
+&lcdif2 {
 	status = "okay";
 };
 
-&mipi_dsi {
+
+&ldb {
+ 	status = "okay";
+ 
+	lvds-channel@0 {
+		fsl,data-mapping = "jeida";
+		fsl,data-width = <24>;
+		status = "okay";
+
+		display-timings {
+			native-mode = <&timing0>;
+
+			timing0: timing0 {
+				clock-frequency = <74250000>;
+				hactive = <1280>;
+				vactive = <720>;
+				hfront-porch = <220>;
+				hback-porch = <110>;
+				hsync-len = <40>;
+				vback-porch = <5>;
+				vfront-porch = <20>;
+				vsync-len = <5>;
+			};
+		};
+		port@1 {
+			reg = <1>;
+
+			lvds_out: endpoint {
+				remote-endpoint = <&it6263_in>;
+			};
+		};
+	};
+};
+&ldb_phy {
 	status = "okay";
+};
+
+&mipi_dsi {
+	status = "disabled";
 
 	port@1 {
 		dsim_to_adv7535: endpoint {
diff --git a/arch/arm/dts/imx8mp.dtsi b/arch/arm/dts/imx8mp.dtsi
index 2876b94b2a..d51cc2716e 100644
--- a/arch/arm/dts/imx8mp.dtsi
+++ b/arch/arm/dts/imx8mp.dtsi
@@ -41,7 +41,7 @@
 		usb0 = &usb_dwc3_0;
 		usb1 = &usb_dwc3_1;
 		spi0 = &flexspi;
-		video0 = &lcdif1;
+		video0 = &lcdif2;
 	};
 
 	cpus {
@@ -351,6 +351,14 @@
 			domain-name = "hdmi_phy";
 			parent-domains = <&hdmimix_pd>;
 		};
+
+		lvds_phy_pd: lvdsphy-pd {
+			compatible = "fsl,imx8m-pm-domain";
+			#power-domain-cells = <0>;
+			domain-index = <19>;
+			domain-name = "lvds_phy";
+			parent-domains = <&mediamix_pd>;
+		};
 	};
 
 	pmu {
@@ -1173,6 +1181,44 @@
 				};
 			};
 
+			lcdif2: lcd-controller@32e90000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx8mp-lcdif2";
+				reg = <0x32e90000 0x10000>;
+				clocks = <&clk IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT>,
+					 <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>,
+					 <&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
+				clock-names = "pix", "disp-axi", "disp-apb";
+				assigned-clocks = <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>,
+						  <&clk IMX8MP_CLK_MEDIA_AXI>,
+						  <&clk IMX8MP_CLK_MEDIA_APB>;
+				assigned-clock-parents = <&clk IMX8MP_VIDEO_PLL1_OUT>,
+							 <&clk IMX8MP_SYS_PLL2_1000M>,
+							 <&clk IMX8MP_SYS_PLL1_800M>;
+				assigned-clock-rates = <0>, <500000000>, <200000000>;
+				interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+				blk-ctl = <&mediamix_blk_ctl>;
+				power-domains = <&mediamix_pd>;
+				status = "disabled";
+
+				lcdif2_disp: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					lcdif2_disp_ldb_ch0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&ldb_ch0>;
+					};
+
+					lcdif2_disp_ldb_ch1: endpoint@1 {
+						reg = <1>;
+						remote-endpoint = <&ldb_ch1>;
+					};
+				};
+			};
+
 			mediamix_blk_ctl: blk-ctl@32ec0000 {
 				compatible = "fsl,imx8mp-mediamix-blk-ctl",
 					     "syscon";
@@ -1181,6 +1227,74 @@
 
 		};
 
+			ldb: ldb@32ec005c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,imx8mp-ldb";
+				clocks = <&clk IMX8MP_CLK_MEDIA_LDB_ROOT>;
+				clock-names = "ldb";
+				assigned-clocks = <&clk IMX8MP_CLK_MEDIA_LDB>;
+				assigned-clock-parents = <&clk IMX8MP_VIDEO_PLL1_OUT>;
+				gpr = <&mediamix_blk_ctl>;
+				power-domains = <&mediamix_pd>;
+				status = "disabled";
+
+				lvds-channel@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+					phys = <&ldb_phy1>;
+					phy-names = "ldb_phy";
+					status = "disabled";
+
+					port@0 {
+						reg = <0>;
+
+						ldb_ch0: endpoint {
+							remote-endpoint = <&lcdif2_disp_ldb_ch0>;
+						};
+					};
+				};
+
+				lvds-channel@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+					phys = <&ldb_phy2>;
+					phy-names = "ldb_phy";
+					status = "disabled";
+
+					port@0 {
+						reg = <0>;
+
+						ldb_ch1: endpoint {
+							remote-endpoint = <&lcdif2_disp_ldb_ch1>;
+						};
+					};
+				};
+			};
+
+			ldb_phy: phy@32ec0128 {
+				compatible = "fsl,imx8mp-lvds-phy";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				gpr = <&mediamix_blk_ctl>;
+				clocks = <&clk IMX8MP_CLK_MEDIA_APB_ROOT>;
+				clock-names = "apb";
+				power-domains = <&mediamix_pd>;
+				status = "disabled";
+
+				ldb_phy1: port@0 {
+					reg = <0>;
+					#phy-cells = <0>;
+				};
+
+				ldb_phy2: port@1 {
+					reg = <1>;
+					#phy-cells = <0>;
+				};
+			};
+
 		ddr-pmu@3d800000 {
 			compatible = "fsl,imx8mp-ddr-pmu", "fsl,imx8m-ddr-pmu";
 			reg = <0x3d800000 0x400000>;
diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c
index d6be307e6e..ee1c306987 100644
--- a/arch/arm/mach-imx/imx8m/clock_imx8mm.c
+++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c
@@ -48,6 +48,7 @@ int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
 }
 
 static struct imx_int_pll_rate_table imx8mm_fracpll_tbl[] = {
+	PLL_1443X_RATE(1039500000U, 693, 4, 2, 0),
 	PLL_1443X_RATE(1000000000U, 250, 3, 1, 0),
 	PLL_1443X_RATE(800000000U, 200, 3, 1, 0),
 	PLL_1443X_RATE(750000000U, 250, 2, 2, 0),
@@ -299,7 +300,7 @@ int intpll_configure(enum pll_clocks pll, ulong freq)
 	return 0;
 }
 
-#define VIDEO_PLL_RATE 594000000U
+#define VIDEO_PLL_RATE 1039500000U
 
 void mxs_set_lcdclk(uint32_t base_addr, uint32_t freq)
 {
@@ -327,7 +328,7 @@ find:
 	debug("mxs_set_lcdclk, pre = %d, post = %d\n", pre, post);
 
 #ifdef CONFIG_IMX8MP
-	clock_set_target_val(MEDIA_DISP1_PIX_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(1) | CLK_ROOT_PRE_DIV(pre - 1) | CLK_ROOT_POST_DIV(post - 1));
+	clock_set_target_val(MEDIA_DISP2_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(1) | CLK_ROOT_PRE_DIV(pre - 1) | CLK_ROOT_POST_DIV(post - 1));
 #elif defined(CONFIG_IMX8MN)
 	clock_set_target_val(DISPLAY_PIXEL_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(1) | CLK_ROOT_PRE_DIV(pre - 1) | CLK_ROOT_POST_DIV(post - 1));
 #else
@@ -342,17 +343,17 @@ void enable_display_clk(unsigned char enable)
 	if (enable) {
 		clock_enable(CCGR_DISPMIX, false);
 
-		/* Set Video PLL to 594Mhz, p = 1, m = 99,  k = 0, s = 2 */
+		/* Set Video PLL to 1039.5Mhz for LVDS, p = 4, m = 693,  k = 0, s = 2 */
 		fracpll_configure(ANATOP_VIDEO_PLL, VIDEO_PLL_RATE);
 
-		/* 400Mhz */
-		clock_set_target_val(MEDIA_AXI_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(2) | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV2));
+		/* 500Mhz */
+		clock_set_target_val(MEDIA_AXI_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(1) | CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV2));
 
 		/* 200Mhz */
 		clock_set_target_val(MEDIA_APB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(2) |CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV4));
 
-		/* 27Mhz MIPI DPHY PLL ref from video PLL */
-		clock_set_target_val(MEDIA_MIPI_PHY1_REF_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(7) |CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV22));
+		/* 519.75Mhz LVDS PLL ref from video PLL */
+		clock_set_target_val(MEDIA_LDB_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(7) |CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2));
 		clock_enable(CCGR_DISPMIX, true);
 	} else {
 		clock_enable(CCGR_DISPMIX, false);
diff --git a/configs/imx8mp_evk_defconfig b/configs/imx8mp_evk_defconfig
index 393e9b8aba..bdeb5ad6f2 100644
--- a/configs/imx8mp_evk_defconfig
+++ b/configs/imx8mp_evk_defconfig
@@ -166,6 +166,8 @@ CONFIG_VIDEO_IMX_LCDIFV3=y
 CONFIG_SPLASH_SCREEN=y
 CONFIG_SPLASH_SCREEN_ALIGN=y
 CONFIG_VIDEO_ADV7535=y
+CONFIG_VIDEO_IMX8MP_LVDS=y
+CONFIG_VIDEO_IT6263_BRIDGE=y
 CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_LZO=y
 CONFIG_BZIP2=y
diff --git a/drivers/core/device.c b/drivers/core/device.c
index b12f594963..317ea0c1ca 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -569,16 +569,16 @@ int device_probe(struct udevice *dev)
 			goto fail;
 	}
 
-	/* Only handle devices that have a valid ofnode */
-	if (dev_has_ofnode(dev) && !(dev->driver->flags & DM_FLAG_IGNORE_DEFAULT_CLKS)) {
-		/*
-		 * Process 'assigned-{clocks/clock-parents/clock-rates}'
-		 * properties
-		 */
-		ret = clk_set_defaults(dev, CLK_DEFAULTS_PRE);
-		if (ret)
-			goto fail;
-	}
+	// /* Only handle devices that have a valid ofnode */
+	// if (dev_has_ofnode(dev) && !(dev->driver->flags & DM_FLAG_IGNORE_DEFAULT_CLKS)) {
+	// 	/*
+	// 	 * Process 'assigned-{clocks/clock-parents/clock-rates}'
+	// 	 * properties
+	// 	 */
+	// 	ret = clk_set_defaults(dev, CLK_DEFAULTS_PRE);
+	// 	if (ret)
+	// 		goto fail;
+	// }
 
 	if (drv->probe) {
 		ret = drv->probe(dev);
diff --git a/drivers/video/it6263_bridge.c b/drivers/video/it6263_bridge.c
index 405d0571ab..0120e0c660 100644
--- a/drivers/video/it6263_bridge.c
+++ b/drivers/video/it6263_bridge.c
@@ -184,7 +184,6 @@ static int it6263_set_backlight(struct udevice *dev, int percent)
 static int it6263_probe(struct udevice *dev)
 {
 	struct it6263_priv *priv = dev_get_priv(dev);
-
 	debug("%s\n", __func__);
 
 	priv->addr  = dev_read_addr(dev);
diff --git a/drivers/video/nxp/imx/Kconfig b/drivers/video/nxp/imx/Kconfig
index 05dacc8818..98508ecbfc 100644
--- a/drivers/video/nxp/imx/Kconfig
+++ b/drivers/video/nxp/imx/Kconfig
@@ -34,6 +34,15 @@ config VIDEO_IMX8_LVDS
 	help
 	  Support for i.MX8 LDVS bridge controller for i.MX8 processors.
 
+config VIDEO_IMX8MP_LVDS
+	bool "i.MX8MP LDVS bridge support"
+	default n
+	depends on IMX8MP && DM_VIDEO
+	select DISPLAY
+	select VIDEO_LINK
+	help
+	  Support for i.MX8MP LDVS bridge controller for i.MX8 processors.
+
 config VIDEO_IMX_HDP_LOAD
 	bool "i.MX8 HDMI/DP firmware loading"
 	default n
diff --git a/drivers/video/nxp/imx/Makefile b/drivers/video/nxp/imx/Makefile
index 1315033e35..13c223edd8 100644
--- a/drivers/video/nxp/imx/Makefile
+++ b/drivers/video/nxp/imx/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_VIDEO_IMX8M_DCSS) += imx8m_dcss.o
 obj-$(CONFIG_VIDEO_SEC_MIPI_DSI) += sec_mipi_dsim.o
 obj-$(CONFIG_VIDEO_IMX_SEC_DSI) += sec_dsim_imx.o
 obj-$(CONFIG_VIDEO_IMX_LCDIFV3) += imx_lcdifv3.o
+obj-$(CONFIG_VIDEO_IMX8MP_LVDS) += imx8mp_lvds.o
 obj-$(CONFIG_VIDEO_NW_MIPI_DSI) += mipi_dsi_northwest.o
 obj-$(CONFIG_VIDEO_IMX_NW_DSI) += nw_dsi_imx.o
 obj-$(CONFIG_VIDEO_IMX_DCNANO) += dcnano.o
diff --git a/drivers/video/nxp/imx/imx8mp_lvds.c b/drivers/video/nxp/imx/imx8mp_lvds.c
new file mode 100644
index 0000000000..11ff41ac56
--- /dev/null
+++ b/drivers/video/nxp/imx/imx8mp_lvds.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2022 NXP
+ */
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <display.h>
+#include <video.h>
+#include <video_bridge.h>
+#include <video_link.h>
+#include <asm/io.h>
+#include <dm/device-internal.h>
+#include <linux/iopoll.h>
+#include <linux/err.h>
+#include <clk.h>
+
+#include <power-domain.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#define DRIVER_NAME "imx8mp-ldb"
+
+
+#define LVDS_CTRL		0x128
+#define HS_DISABLE		(0 << 3)
+#define SPARE_IN(n)		(((n) & 0x7) << 25)
+#define SPARE_IN_MASK		0xe000000
+#define TEST_RANDOM_NUM_EN	BIT(24)
+#define TEST_MUX_SRC(n)		(((n) & 0x3) << 22)
+#define TEST_MUX_SRC_MASK	0xc00000
+#define TEST_EN			BIT(21)
+#define TEST_DIV4_EN		BIT(20)
+#define VBG_ADJ(n)		(((n) & 0x7) << 17)
+#define VBG_ADJ_MASK		0xe0000
+#define SLEW_ADJ(n)		(((n) & 0x7) << 14)
+#define SLEW_ADJ_MASK		0x1c000
+#define CC_ADJ(n)		(((n) & 0x7) << 11)
+#define CC_ADJ_MASK		0x3800
+#define CM_ADJ(n)		(((n) & 0x7) << 8)
+#define CM_ADJ_MASK		0x700
+#define PRE_EMPH_ADJ(n)		(((n) & 0x7) << 5)
+#define PRE_EMPH_ADJ_MASK	0xe0
+#define PRE_EMPH_EN		BIT(4)
+#define HS_EN			BIT(3)
+#define BG_EN			BIT(2)
+#define CH_EN		    BIT(0)
+
+
+#define LDB_CTRL		0x5c
+#define LDB_CH0_MODE_EN_TO_DI0		(1 << 0)
+#define LDB_CH0_MODE_EN_TO_DI1		(3 << 0)
+#define LDB_CH0_MODE_EN_MASK		(3 << 0)
+#define LDB_CH1_MODE_EN_TO_DI0		(1 << 2)
+#define LDB_CH1_MODE_EN_TO_DI1		(3 << 2)
+#define LDB_CH1_MODE_EN_MASK		(3 << 2)
+#define CH0_DATA_WIDTH_24BIT		(1 << 5)
+#define CH0_BIT_MAPPING_JEIDA		(1 << 6)
+#define CH0_BIT_MAPPING_SPWG		(0 << 6)
+#define LDB_REG_CH0_FIFO_RESET		(1 << 11)
+#define LDB_REG_CH1_FIFO_RESET		(1 << 12)
+#define LDB_REG_ASYNC_FIFO_EN		(1 << 24)
+#define LDB_FIFO_THRESHOLD		(4 << 25)
+
+#define CLK_EN 0x4
+
+#define usleep_range(a, b) udelay((b))
+
+#define serial_clk 74250*7000
+
+struct imx8mp_ldb_priv {
+	struct regmap *regmap;
+	struct udevice *conn_dev;
+	unsigned int ldb_id;
+	struct clk *ldb_root_clk;
+	struct clk *apb_root_clk;
+	struct display_timing timings;
+};
+
+
+static inline unsigned int media_blk_read(struct imx8mp_ldb_priv *priv, unsigned int reg)
+{
+	unsigned int val;
+
+	regmap_read(priv->regmap, reg, &val);
+
+	return val;
+}
+
+static inline void media_blk_write(struct imx8mp_ldb_priv *priv, unsigned int reg, unsigned int value)
+{
+	regmap_write(priv->regmap, reg, value);
+}
+
+static int imx8mp_lvds_phy_power_on(struct udevice *dev)
+{
+	struct imx8mp_ldb_priv *priv = dev_get_priv(dev);
+	
+	unsigned int val;
+	u32 ldb_ctrl;
+	bool bg_en;
+
+ 	media_blk_write(priv, LVDS_CTRL, HS_DISABLE);
+
+	val = media_blk_read(priv,LVDS_CTRL);
+	bg_en = !!(val & BG_EN);
+	val |= BG_EN;
+	media_blk_write(priv, LVDS_CTRL, val);
+
+	if (!bg_en){
+		usleep_range(15, 20);
+	}
+		
+	val = media_blk_read(priv, LVDS_CTRL);
+	val |= CH_EN;
+	val |= BIT(3);
+	media_blk_write(priv, LVDS_CTRL, val);
+
+	media_blk_write(priv, LDB_CTRL, LDB_CH0_MODE_EN_TO_DI0 | CH0_DATA_WIDTH_24BIT | CH0_BIT_MAPPING_JEIDA);
+ 
+	usleep_range(5, 10);
+	
+	return 0;
+
+}
+
+int imx8mp_ldb_read_timing(struct udevice *dev, struct display_timing *timing)
+{
+	struct imx8mp_ldb_priv *priv = dev_get_priv(dev);
+
+	if (dev->plat_ == NULL)
+		return -EINVAL;
+
+	if (timing) {
+		memcpy(timing, &priv->timings, sizeof(struct display_timing));
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int imx8mp_ldb_probe(struct udevice *dev)
+{
+	struct imx8mp_ldb_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	debug("%s\n", __func__);
+	printf("imx8mp_ldb_probe");
+
+	if (dev->plat_ == NULL) {
+		priv->regmap = syscon_regmap_lookup_by_phandle(dev, "gpr");
+		if (IS_ERR(priv->regmap)) {
+			debug("fail to get fsl,imx8mp-mediamix-blk-ctl regmap\n");
+			return PTR_ERR(priv->regmap);
+		}
+
+		/* Require to add alias in DTB */
+		priv->ldb_id = dev_seq(dev);
+
+		debug("ldb_id %u\n", priv->ldb_id);
+	}else{
+		
+		priv->conn_dev = video_link_get_next_device(dev);
+		if (!priv->conn_dev) {
+			debug("can't find next device in video link\n");
+		}
+
+		ret = video_link_get_display_timings(&priv->timings);
+		if (ret) {
+			debug("decode display timing error %d\n", ret);
+			return ret;
+		}
+		
+		if(priv->conn_dev && device_get_uclass_id(priv->conn_dev) == UCLASS_PANEL){
+			ret = panel_enable_backlight(priv->conn_dev);
+			if (ret) {
+					dev_err(dev, "fail to enable panel backlight\n");
+					return ret;
+			}
+			ret = panel_set_backlight(priv->conn_dev, 80);
+				if (ret) {
+					dev_err(dev, "fail to set panel backlight\n");
+					return ret;
+			}
+		}
+
+		if (IS_ENABLED(CONFIG_VIDEO_BRIDGE)) {
+			if (priv->conn_dev &&
+				device_get_uclass_id(priv->conn_dev) == UCLASS_VIDEO_BRIDGE) {
+
+				ret = video_bridge_attach(priv->conn_dev);
+				if (ret) {
+					dev_err(dev, "fail to attach bridge\n");
+					return ret;
+				}
+				ret = video_bridge_set_active(priv->conn_dev, true);
+				if (ret) {
+					dev_err(dev, "fail to active bridge\n");
+					return ret;
+				}
+			}
+		}
+	}
+    printf("imx8mp_ldb_probe\n");
+
+	return 0;
+
+}
+
+static int imx8mp_ldb_bind(struct udevice *dev)
+{
+	struct imx8mp_ldb_priv *priv = dev_get_priv(dev);
+	ofnode lvds_ch_node;
+	int ret = 0;
+
+	debug("%s\n", __func__);
+	lvds_ch_node = ofnode_find_subnode(dev_ofnode(dev), "lvds-channel@0");
+	if (ofnode_valid(lvds_ch_node)) {
+		ret = device_bind(dev, dev->driver, "lvds-channel@0", (void *)1,
+			lvds_ch_node, NULL);
+		if (ret)
+			debug("Error binding driver '%s': %d\n", dev->driver->name,
+				ret);
+	}
+
+	return ret;
+}
+
+
+int imx8mp_ldb_enable(struct udevice *dev, int panel_bpp,
+		      const struct display_timing *timing)
+{
+	struct imx8mp_ldb_priv *priv = dev_get_priv(dev);
+	int ret;
+	debug("%s\n", __func__);
+
+	if (dev->plat_ == NULL) {
+
+		imx8mp_lvds_phy_power_on(dev);
+	} else {
+		display_enable(dev->parent, panel_bpp, &priv->timings);
+
+		if (IS_ENABLED(CONFIG_VIDEO_BRIDGE)) {
+			if (priv->conn_dev &&
+				device_get_uclass_id(priv->conn_dev) == UCLASS_VIDEO_BRIDGE) {
+				ret = video_bridge_set_backlight(priv->conn_dev, 80);
+				if (ret) {
+					dev_err(dev, "fail to set backlight\n");
+					return ret;
+				}
+			}
+		}
+	}
+
+	return 0;
+
+}
+
+struct dm_display_ops imx8mp_ldb_ops = {
+	.read_timing = imx8mp_ldb_read_timing,
+	.enable = imx8mp_ldb_enable,
+};
+
+static const struct udevice_id imx8mp_ldb_ids[] = {
+	{ .compatible = "fsl,imx8mp-ldb" },
+	{ }
+};
+
+U_BOOT_DRIVER(imx8mp_ldb) = {
+	.name				= "imx8mp_ldb",
+	.id				= UCLASS_DISPLAY,
+	.of_match			= imx8mp_ldb_ids,
+	.bind				= imx8mp_ldb_bind,
+	.probe				= imx8mp_ldb_probe,
+	.ops				= &imx8mp_ldb_ops,
+	.priv_auto		= sizeof(struct imx8mp_ldb_priv),
+};
\ No newline at end of file
diff --git a/drivers/video/nxp/imx/imx_lcdifv3.c b/drivers/video/nxp/imx/imx_lcdifv3.c
index 1eb9938777..e2a95e3e72 100644
--- a/drivers/video/nxp/imx/imx_lcdifv3.c
+++ b/drivers/video/nxp/imx/imx_lcdifv3.c
@@ -16,6 +16,8 @@
 #include <asm/arch/sys_proto.h>
 #include <linux/err.h>
 #include <asm/io.h>
+#include <display.h>
+
 
 #include "../../videomodes.h"
 #include <linux/string.h>
@@ -103,8 +105,8 @@ static void lcdifv3_set_mode(struct lcdifv3_priv *priv,
 	writel(CTRL_INV_VS, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
 
 	/* SEC MIPI DSI specific */
-	writel(CTRL_INV_PXCK, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
-	writel(CTRL_INV_DE, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
+	//writel(CTRL_INV_PXCK, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
+	//writel(CTRL_INV_DE, (ulong)(priv->reg_base + LCDIFV3_CTRL_CLR));
 
 }
 
@@ -344,22 +346,12 @@ static int lcdifv3_video_probe(struct udevice *dev)
 
 	lcdifv3_of_parse_thres(dev);
 
-	if (priv->disp_dev) {
-#if IS_ENABLED(CONFIG_VIDEO_BRIDGE)
-		if (device_get_uclass_id(priv->disp_dev) == UCLASS_VIDEO_BRIDGE) {
-			ret = video_bridge_attach(priv->disp_dev);
-			if (ret) {
-				dev_err(dev, "fail to attach bridge\n");
-				return ret;
-			}
-
-			ret = video_bridge_set_backlight(priv->disp_dev, 80);
-			if (ret) {
-				dev_err(dev, "fail to set backlight\n");
-				return ret;
-			}
-		}
-#endif
+	printf("lcdifv3_video_probe000\n");
+
+	ret = display_enable(priv->disp_dev, NULL, NULL);
+	if (ret) {
+		debug("%s: Display enable error %d\n", __func__, ret);
+		return ret;
 	}
 
 	mode.xres = timings.hactive.typ;
@@ -386,7 +378,7 @@ static int lcdifv3_video_probe(struct udevice *dev)
 					DCACHE_WRITEBACK);
 	video_set_flush_dcache(dev, true);
 	gd->fb_base = plat->base;
-
+	
 	return ret;
 }
 
@@ -416,6 +408,7 @@ static int lcdifv3_video_remove(struct udevice *dev)
 
 static const struct udevice_id lcdifv3_video_ids[] = {
 	{ .compatible = "fsl,imx8mp-lcdif1" },
+	{ .compatible = "fsl,imx8mp-lcdif2" },
 	{ /* sentinel */ }
 };
 
-- 
2.25.1

