diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 6ba353360b4f9ccd2175f20da814bbfebd263ff1..2f3c80ebab159332079d7746d8cda4889f7b55e9 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -48,7 +48,7 @@ ifneq ($(CONFIG_SPL_BUILD),y)
 obj-$(CONFIG_FSL_MFGPROT) += cmd_mfgprot.o
 endif
 endif
-ifeq ($(SOC),$(filter $(SOC),mx5 mx6 mx7))
+ifeq ($(SOC),$(filter $(SOC),mx5 mx6 mx7 imx8m))
 obj-$(CONFIG_IMX_VIDEO_SKIP) += video.o
 endif
 ifeq ($(SOC),$(filter $(SOC),mx6 mx7))
diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c
index 1cfa2cf6803667eff84e40a6484aeb0eb5893598..890d08bd8e1c7bdfa4a795fb43bb22f4fb5244a2 100644
--- a/arch/arm/mach-imx/imx8m/clock_imx8mm.c
+++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c
@@ -301,7 +301,11 @@ int intpll_configure(enum pll_clocks pll, ulong freq)
 	return 0;
 }
 
+#ifdef CONFIG_IMX8MP
 #define VIDEO_PLL_RATE 1039500000U
+#else
+#define VIDEO_PLL_RATE 594000000U
+#endif
 
 void mxs_set_lcdclk_type(u32 base_addr, u32 freq, enum lcdifv3_type type)
 {
diff --git a/board/seco/common/seco_fuse.h b/board/seco/common/seco_fuse.h
index 50a33b7798d99a65fad63d3866db430f5d857921..e6a6c66a2d6e69e363d18f5ac01f200b2eba9a27 100644
--- a/board/seco/common/seco_fuse.h
+++ b/board/seco/common/seco_fuse.h
@@ -57,6 +57,12 @@ enum SECO_FUSE_MODULE_TYPE {
 };
 int seco_fuse_GetModule(void);
 
+// clang-format off
+#define MODULE_IS_MYON_TYPE(m)         (((m == SECO_FUSE_MODULE_MYON2)       ||(m == SECO_FUSE_MODULE_MYON2NANO))    ? 1 : 0)
+#define MODULE_IS_TRIZEPS8MINI_TYPE(m) (((m == SECO_FUSE_MODULE_TRIZEPS8MINI)||(m == SECO_FUSE_MODULE_TRIZEPS8NANO)) ? 1 : 0)
+#define MODULE_IS_TRIZEPS8PLUS_TYPE(m) ( (m == SECO_FUSE_MODULE_TRIZEPS8PLUS)                                  ? 1 : 0)
+// clang-format on
+
 enum SECO_FUSE_RAMWIDTH {
 	SECO_FUSE_RAMWIDTH_UNKNOWN = -1,
 	SECO_FUSE_RAMWIDTH_8BIT = 8,
diff --git a/board/seco/imx8mm_myon2/Makefile b/board/seco/imx8mm_myon2/Makefile
index f8d782b9641a62af2f07f7167268562a083745bd..af75b6c970ccad856a3ec28eeeaa5772d1ccadd3 100644
--- a/board/seco/imx8mm_myon2/Makefile
+++ b/board/seco/imx8mm_myon2/Makefile
@@ -5,6 +5,7 @@
 #
 
 obj-y += imx8mm_myon2.o
+obj-$(CONFIG_VIDEO_MXS) += display.o
 
 ifdef CONFIG_SPL_BUILD
 obj-y += spl.o
diff --git a/board/seco/imx8mm_myon2/README b/board/seco/imx8mm_myon2/README
index 8249a5432b94ab51fec9ccdefc3d4d7f9a32bd0f..374d61ab290ff793f0064bcb2c73c0ad55007d53 100644
--- a/board/seco/imx8mm_myon2/README
+++ b/board/seco/imx8mm_myon2/README
@@ -38,6 +38,28 @@ https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
 II. Implementation notes
 ========================
 
+Video output and logo
+---------------------
+
+List of supported outputs:
+  * HDMI_1920x1080
+  * RGB_ATM0700D6J
+  * LVDS_ATM0700L61
+  * LVDS_SCF1001C44GGU05
+  * PCONXS
+  * LVDS_AM19201080D1
+  * RGB18_ATM0700D6J
+  * LVDS_G156HAN02.1
+  * GUF_LVDS_SCF1001C44GGU05
+
+The video output is controlled by the "panel" environment variable.
+To select a specific output, set the value to the one of the supported outputs (see above).
+If "panel" is not set, auto detection is performed.
+To disable video output, set the "panel" to "none".
+
+The splash screen image (splash.bmp) is located on the first partition of the boot device,
+and can be easily changed by replacing the file with a new one.
+
 Universal Serial Bus
 --------------------
 
diff --git a/board/seco/imx8mm_myon2/display.c b/board/seco/imx8mm_myon2/display.c
new file mode 100644
index 0000000000000000000000000000000000000000..c63bd7f50c079801749930a00000cc6dcae31067
--- /dev/null
+++ b/board/seco/imx8mm_myon2/display.c
@@ -0,0 +1,1144 @@
+/*
+ * Copyright 2025 SECO
+ */
+
+/*
+ * Display detection routine for SECO Nother Europe hardware.
+ * Try to detect the display/baseboard based on the detection of
+ * the used touch or other board unique devices.
+*/
+
+#include <common.h>
+#include <asm-generic/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/mach-imx/gpio.h>
+#include <asm/mach-imx/video.h>
+#include <linux/arm-smccc.h>
+#include <linux/delay.h>
+#include <dm/uclass.h>
+#include <env.h>
+#include <i2c.h>
+#include <imx_sip.h>
+#include <imx_mipi_dsi_bridge.h>
+#include <sec_mipi_dsim.h>
+#include "../common/seco_fuse.h"
+
+// clang-format off
+#define FPGA_ID				0x41
+#define LVDS_ID				0x2C
+
+#define ADV7535_MAIN			0x39
+#define ADV7535_DSI_CEC			0x3C
+// clang-format on
+
+static int pConXS_detected = 0;
+
+static const struct sec_mipi_dsim_plat_data imx8mm_mipi_dsim_plat_data = {
+	.version = 0x1060200,
+	.max_data_lanes = 4,
+	.max_data_rate = 1500000000ULL,
+	.reg_base = MIPI_DSI_BASE_ADDR,
+	.gpr_base = CSI_BASE_ADDR + 0x8000,
+};
+
+static void fpga_init(uint8_t val)
+{
+	struct udevice *bus, *main_dev;
+	int i2c_bus = 2;
+	int ret;
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+	if (ret) {
+		printf("%s: No bus %d\n", __func__, i2c_bus);
+		return;
+	}
+
+	ret = dm_i2c_probe(bus, FPGA_ID, 0, &main_dev);
+	if (ret) {
+		printf("%s: Can't find device id=0x%x, on bus %d\n", __func__, FPGA_ID, i2c_bus);
+		return;
+	}
+
+	ret = dm_i2c_write(main_dev, 0x10, &val, 1);
+}
+
+static void lvds_init(struct display_info_t const *dev)
+{
+	struct udevice *bus, *main_dev;
+	int i2c_bus = 2;
+	int ret;
+	uint8_t i = 0;
+
+	uint8_t addr[] = { 0x09, 0x0A, 0x0A, 0x0B, 0x0D, 0x10, 0x11, 0x12, 0x13, 0x18, 0x19, 0x1A,
+			   0x1B, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
+			   0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+			   0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x0D, 0xFF };
+	uint8_t valb[] = { 0x01, 0x00, 0x05, 0x10, 0x00, 0x26, 0x00, 0x27, 0x00, 0x78, 0x00, 0x03,
+			   0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x21, 0x00, 0x00,
+			   0x00, 0x08, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00,
+			   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF };
+
+	int module;
+	module = seco_fuse_GetModule();
+
+	if (strncmp(dev->mode.name, "LVDS_SCF1001C44GGU05", strlen(dev->mode.name)) == 0) {
+		//DataImage
+		valb[7] = 0x2A;
+		valb[14] = 0x05;
+		valb[18] = 0x00;
+		valb[25] = 0x3C;
+		valb[29] = 0x03;
+		valb[33] = 0x30;
+	} else if (strncmp(dev->mode.name, "GUF_LVDS_SCF1001C44GGU05", strlen(dev->mode.name)) ==
+		   0) {
+		//SIS 9255
+		valb[7] = 0x2A;
+		valb[14] = 0x05;
+		valb[18] = 0x00;
+		valb[25] = 0x3C;
+		valb[29] = 0x03;
+		valb[33] = 0x30;
+	} else if (strncmp(dev->mode.name, "PCONXS", strlen(dev->mode.name)) == 0) {
+		//printf("%s: -> PCONXS\n", __func__);
+		valb[2] = 0x03;
+		valb[3] = 0x14;
+		valb[5] = 0x20;
+		valb[7] = 0x3D;
+		valb[17] = 0x58;
+		valb[18] = 0x02;
+		valb[21] = 0x20;
+		valb[25] = 0x04;
+		valb[29] = 0x01;
+		valb[33] = 0xA0;
+		valb[37] = 0xA0;
+		valb[39] = 0x0C;
+	} else if (strncmp(dev->mode.name, "LVDS_ATM0700D6J", strlen(dev->mode.name)) == 0) {
+		//printf("%s: -> IPANM7\n", __func__);
+		valb[2] = 0x03;
+		valb[3] = 0x14;
+		valb[5] = 0x20;
+		valb[7] = 0x3D;
+		valb[17] = 0x58;
+		valb[18] = 0x02;
+		valb[21] = 0x20;
+		valb[25] = 0x04;
+		valb[29] = 0x01;
+		valb[33] = 0xA0;
+		valb[37] = 0xA0;
+		valb[39] = 0x0C;
+	} else if (strncmp(dev->mode.name, "LVDS_ATM0700L61", strlen(dev->mode.name)) == 0) {
+		//printf("%s: -> LVDS_ATM0700L61\n", __func__);
+		valb[2] = 0x03;
+		valb[3] = 0x14;
+		valb[5] = 0x20;
+		valb[7] = 0x3D;
+		valb[17] = 0x58;
+		valb[18] = 0x02;
+		valb[21] = 0x20;
+		valb[25] = 0x04;
+		valb[29] = 0x01;
+		valb[33] = 0xA0;
+		valb[37] = 0xA0;
+		valb[39] = 0x0C;
+
+		gpio_request(IMX_GPIO_NR(3, 22), "BACKLIGHT EN");
+		if (module == SECO_FUSE_MODULE_TRIZEPS8MINI)
+			gpio_direction_output(IMX_GPIO_NR(3, 22), 0);
+		else
+			gpio_direction_output(IMX_GPIO_NR(3, 22), 1);
+	} else if (strncmp(dev->mode.name, "LVDS_AM19201080D1", strlen(dev->mode.name)) == 0) {
+		//printf("%s: -> AM19201080D1\n", __func__);
+		valb[2] = 0x83;
+		valb[3] = 0x28;
+		valb[7] = 0x48;
+		valb[9] = 0x6C;
+		valb[13] = 0x80;
+		valb[14] = 0x07;
+		valb[17] = 0x38;
+		valb[18] = 0x04;
+		valb[25] = 0x23;
+		valb[30] = 0x0A;
+		valb[33] = 0x23;
+		valb[37] = 0x46;
+		valb[39] = 0x0A;
+	} else if (strncmp(dev->mode.name, "LVDS_G156HAN02.1", strlen(dev->mode.name)) == 0) {
+		printf("%s: -> LVDS_G156HAN02.1\n", __func__);
+		valb[2] = 0x83;
+		valb[3] = 0x28;
+		valb[7] = 0x48;
+		valb[9] = 0x6C;
+		valb[13] = 0x80;
+		valb[14] = 0x07;
+		valb[17] = 0x38;
+		valb[18] = 0x04;
+		valb[25] = 0x23;
+		valb[30] = 0x0A;
+		valb[33] = 0x23;
+		valb[37] = 0x46;
+		valb[39] = 0x0A;
+	}
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+	if (ret) {
+		printf("%s: No bus %d\n", __func__, i2c_bus);
+		return;
+	}
+
+	ret = dm_i2c_probe(bus, LVDS_ID, 0, &main_dev);
+	if (ret) {
+		printf("%s: Can't find device id=0x%x, on bus %d\n", __func__, LVDS_ID, i2c_bus);
+		return;
+	}
+
+	do {
+		//printf("[0x%x] = 0x%x\n", addr[i], valb[i]);
+		dm_i2c_write(main_dev, addr[i], &valb[i], 1);
+		i++;
+	} while (addr[i] != 0xFF);
+
+	return;
+}
+
+static int adv7535_i2c_reg_write(struct udevice *dev, uint addr, uint mask, uint data)
+{
+	uint8_t valb;
+	int err;
+
+	if (mask != 0xff) {
+		err = dm_i2c_read(dev, addr, &valb, 1);
+		if (err)
+			return err;
+
+		valb &= ~mask;
+		valb |= data;
+	} else {
+		valb = data;
+	}
+
+	err = dm_i2c_write(dev, addr, &valb, 1);
+	return err;
+}
+
+static int adv7535_i2c_reg_read(struct udevice *dev, uint8_t addr, uint8_t *data)
+{
+	uint8_t valb;
+	int err;
+
+	err = dm_i2c_read(dev, addr, &valb, 1);
+	if (err)
+		return err;
+
+	*data = (int)valb;
+	return 0;
+}
+
+typedef struct stADV753XReg {
+	uint8_t addr;
+	uint8_t reg;
+	uint8_t val;
+} ADV753XREG, *PADV753XREG;
+
+static ADV753XREG advinit[] = {
+	{ 0x39, 0x41, 0x10 }, { 0xff, 0x05, 0x00 }, { 0x39, 0xd6, 0x48 }, { 0xff, 0x05, 0x00 },
+	{ 0x3c, 0x03, 0x89 }, { 0x39, 0x16, 0x20 }, { 0x39, 0x9a, 0xe0 }, { 0x39, 0xba, 0x70 },
+	{ 0x39, 0xde, 0x82 }, { 0x39, 0xe4, 0xc0 }, { 0x39, 0xe5, 0x80 }, { 0x3c, 0x15, 0xd0 },
+	{ 0x3c, 0x17, 0xd0 }, { 0x3c, 0x24, 0x20 }, { 0x3c, 0x57, 0x11 }, { 0x39, 0xaf, 0x06 },
+	{ 0x39, 0x40, 0x80 }, { 0x39, 0x4c, 0x04 }, { 0x39, 0x49, 0x02 }, { 0x39, 0x0d, 0x40 },
+	{ 0x3c, 0x1c, 0x40 }, { 0x39, 0x17, 0x02 }, { 0x3c, 0x16, 0x00 }, { 0x3c, 0x27, 0xCB },
+	{ 0x3c, 0x28, 0x89 }, { 0x3c, 0x29, 0x80 }, { 0x3c, 0x2a, 0x02 }, { 0x3c, 0x2b, 0xc0 },
+	{ 0x3c, 0x2c, 0x05 }, { 0x3c, 0x2d, 0x80 }, { 0x3c, 0x2e, 0x09 }, { 0x3c, 0x2f, 0x40 },
+	{ 0x3c, 0x30, 0x46 }, { 0x3c, 0x31, 0x50 }, { 0x3c, 0x32, 0x00 }, { 0x3c, 0x33, 0x50 },
+	{ 0x3c, 0x34, 0x00 }, { 0x3c, 0x35, 0x40 }, { 0x3c, 0x36, 0x02 }, { 0x3c, 0x37, 0x40 },
+	{ 0x3c, 0x27, 0xCB }, { 0x3c, 0x27, 0x8B }, { 0xff, 0x05, 0x00 }, { 0x3c, 0x27, 0xCB },
+	{ 0xff, 0x64, 0x00 }, { 0x3c, 0x55, 0x00 }, { 0x3c, 0x03, 0x09 }, { 0xff, 0x05, 0x00 },
+	{ 0x3c, 0x03, 0x89 }, { 0x39, 0x12, 0x20 }, { 0x39, 0x13, 0x00 }, { 0x39, 0x14, 0x02 },
+	{ 0x39, 0x15, 0x20 }, { 0x39, 0x0a, 0x41 }, { 0x39, 0x0c, 0xbc }, { 0x39, 0x0d, 0x18 },
+	{ 0x39, 0x03, 0x00 }, { 0x39, 0x02, 0x18 }, { 0x39, 0x01, 0x00 }, { 0x39, 0x09, 0x70 },
+	{ 0x39, 0x08, 0x62 }, { 0x39, 0x07, 0x00 }, { 0x39, 0x73, 0x01 }, { 0x39, 0x76, 0x00 },
+	{ 0x3c, 0x05, 0xC8 }, { 0x00, 0x00, 0x00 }
+};
+
+static int adv7535_init(struct display_info_t const *dev)
+{
+	struct udevice *bus, *main_dev, *cec_dev;
+	int i2c_bus = 1;
+	int ret;
+	uint8_t val;
+	PADV753XREG padvseq = &advinit[0];
+
+	for (i2c_bus = 1; i2c_bus <= 2; i2c_bus++) {
+		ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+		if (ret) {
+			//printf("%s: No bus %d\n", __func__, i2c_bus);
+			continue;
+		}
+
+		ret = dm_i2c_probe(bus, ADV7535_MAIN, 0, &main_dev);
+		if (ret) {
+			//printf("%s: Can't find device id=0x%x, on bus %d\n",
+			//	__func__, ADV7535_MAIN, i2c_bus);
+			continue;
+		}
+
+		ret = dm_i2c_probe(bus, ADV7535_DSI_CEC, 0, &cec_dev);
+		if (ret) {
+			//printf("%s: Can't find device id=0x%x, on bus %d\n",
+			//	__func__, ADV7535_MAIN, i2c_bus);
+			continue;
+		}
+
+		if (!ret) {
+			break;
+		}
+	}
+	if (ret) {
+		//printf("%s: Can't find ADV7535\n", __func__);
+		return 0;
+	}
+
+	//printf("%s: ADV7535 found\n", __func__);
+	adv7535_i2c_reg_read(main_dev, 0x00, &val);
+	if (val != 0x14) {
+		printf("Chip revision: 0x%x (expected: 0x14)\n", val);
+		return 0;
+	}
+	adv7535_i2c_reg_read(cec_dev, 0x00, &val);
+	if (val != 0x75) {
+		printf("Chip ID MSB: 0x%x (expected: 0x75)\n", val);
+		return 0;
+	}
+	adv7535_i2c_reg_read(cec_dev, 0x01, &val);
+	if (val != 0x33) {
+		printf("Chip ID LSB: 0x%x (expected: 0x33)\n", val);
+		return 0;
+	}
+
+	while (padvseq->addr != 0) {
+		if (padvseq->addr == 0xFF) {
+			mdelay(padvseq->reg);
+		} else if (padvseq->addr == ADV7535_MAIN) {
+			adv7535_i2c_reg_write(main_dev, padvseq->reg, 0xff, padvseq->val);
+		} else if (padvseq->addr == ADV7535_DSI_CEC) {
+			adv7535_i2c_reg_write(cec_dev, padvseq->reg, 0xff, padvseq->val);
+		} else {
+			printf("Unknown ADV7535 address\n");
+		}
+		padvseq++;
+	}
+
+	return 1;
+}
+
+// clang-format off
+#define DISPLAY_MIX_SFT_RSTN_CSR	0x00
+#define DISPLAY_MIX_CLK_EN_CSR		0x04
+
+/* 'DISP_MIX_SFT_RSTN_CSR' bit fields */
+#define BUS_RSTN_BLK_SYNC_SFT_EN	BIT(6)
+
+/* 'DISP_MIX_CLK_EN_CSR' bit fields */
+#define LCDIF_PIXEL_CLK_SFT_EN		BIT(7)
+#define LCDIF_APB_CLK_SFT_EN		BIT(6)
+// clang-format on
+
+void disp_mix_bus_rstn_reset(ulong gpr_base, bool reset)
+{
+	if (!reset)
+		/* release reset */
+		setbits_le32(gpr_base + DISPLAY_MIX_SFT_RSTN_CSR, BUS_RSTN_BLK_SYNC_SFT_EN);
+	else
+		/* hold reset */
+		clrbits_le32(gpr_base + DISPLAY_MIX_SFT_RSTN_CSR, BUS_RSTN_BLK_SYNC_SFT_EN);
+}
+
+void disp_mix_lcdif_clks_enable(ulong gpr_base, bool enable)
+{
+	if (enable)
+		/* enable lcdif clks */
+		setbits_le32(gpr_base + DISPLAY_MIX_CLK_EN_CSR,
+			     LCDIF_PIXEL_CLK_SFT_EN | LCDIF_APB_CLK_SFT_EN);
+	else
+		/* disable lcdif clks */
+		clrbits_le32(gpr_base + DISPLAY_MIX_CLK_EN_CSR,
+			     LCDIF_PIXEL_CLK_SFT_EN | LCDIF_APB_CLK_SFT_EN);
+}
+
+struct mipi_dsi_client_dev seco_fuse_panel_drv = {
+	.channel = 0,
+	.lanes = 4,
+	.format = MIPI_DSI_FMT_RGB888,
+	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
+	.name = "default",
+};
+
+struct mipi_dsi_client_dev adv7535_dev = {
+	.channel = 0,
+	.lanes = 4,
+	.format = MIPI_DSI_FMT_RGB888,
+	.mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+		      MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE,
+	.name = "ADV7535",
+};
+
+// clang-format off
+#define DISPMIX				9
+#define MIPI				10
+// clang-format on
+
+void do_enable_mipi2rgb(struct display_info_t const *dev)
+{
+	struct arm_smccc_res res;
+
+	printf("%s: Enable %s \n", __func__, dev->mode.name);
+
+	gpio_request(IMX_GPIO_NR(1, 5), "DISPLAY_EN");
+	gpio_direction_output(IMX_GPIO_NR(1, 5), 1);
+
+	gpio_request(IMX_GPIO_NR(1, 1), "BACKLIGHT_PWM");
+
+	gpio_request(IMX_GPIO_NR(3, 22), "BACKLIGHT_EN");
+	gpio_direction_output(IMX_GPIO_NR(3, 22), 1);
+
+	if (!(strncmp(dev->mode.name, "RGB18_ATM0700D6J", strlen(dev->mode.name)))) {
+		gpio_direction_output(IMX_GPIO_NR(1, 1), 0);
+		fpga_init(0x89);
+	} else {
+		gpio_direction_output(IMX_GPIO_NR(1, 1), 1);
+		fpga_init(0x8D);
+	}
+
+	/* enable the dispmix & mipi phy power domain */
+	arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN,
+		      DISPMIX, true, 0, 0, 0, 0, &res);
+	arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN,
+		      MIPI, true, 0, 0, 0, 0, &res);
+
+	/* Put lcdif out of reset */
+	disp_mix_bus_rstn_reset(imx8mm_mipi_dsim_plat_data.gpr_base, false);
+	disp_mix_lcdif_clks_enable(imx8mm_mipi_dsim_plat_data.gpr_base, true);
+
+	/* Setup mipi dsim */
+	sec_mipi_dsim_setup(&imx8mm_mipi_dsim_plat_data);
+
+	imx_mipi_dsi_bridge_attach(&seco_fuse_panel_drv);
+}
+
+void do_display_default(struct display_info_t const *dev)
+{
+	int module;
+	module = seco_fuse_GetModule();
+
+	printf("%s: Enable %s \n", __func__, dev->mode.name);
+
+	switch (module) {
+	case SECO_FUSE_MODULE_SBCSOM8MINI:
+	case SECO_FUSE_MODULE_SBCSOM8NANO:
+		gpio_request(IMX_GPIO_NR(3, 22), "BACKLIGHT_ENABLE");
+		gpio_request(IMX_GPIO_NR(1, 1), "BACKLIGHT_PWM");
+		gpio_request(IMX_GPIO_NR(1, 5), "DISPLAY_ENABLE");
+
+		gpio_direction_output(IMX_GPIO_NR(3, 22), 0);
+		gpio_direction_output(IMX_GPIO_NR(1, 1), 0);
+		gpio_direction_output(IMX_GPIO_NR(1, 5), 0);
+		break;
+	case SECO_FUSE_MODULE_MYON2:
+		gpio_request(IMX_GPIO_NR(1, 5), "DISPLAY_EN");
+		gpio_request(IMX_GPIO_NR(1, 1), "BACKLIGHT_PWM");
+		gpio_request(IMX_GPIO_NR(3, 22), "BACKLIGHT_EN");
+		gpio_request(IMX_GPIO_NR(1, 4), "LVDS EN");
+
+		gpio_direction_output(IMX_GPIO_NR(1, 4), 0);
+		gpio_direction_output(IMX_GPIO_NR(1, 5), 0);
+		gpio_direction_output(IMX_GPIO_NR(1, 1), 0);
+		gpio_direction_output(IMX_GPIO_NR(3, 22), 0);
+		break;
+	case SECO_FUSE_MODULE_TRIZEPS8MINI:
+		gpio_request(IMX_GPIO_NR(1, 5), "DISPLAY_EN");
+		gpio_request(IMX_GPIO_NR(1, 1), "BACKLIGHT_PWM");
+		gpio_request(IMX_GPIO_NR(3, 22), "BACKLIGHT_EN");
+		gpio_request(IMX_GPIO_NR(1, 4), "LVDS EN");
+
+		gpio_direction_output(IMX_GPIO_NR(1, 4), 0);
+		gpio_direction_output(IMX_GPIO_NR(1, 5), 0);
+		gpio_direction_output(IMX_GPIO_NR(1, 1), 0);
+		gpio_direction_output(IMX_GPIO_NR(3, 22), 0);
+		break;
+	default:
+		break;
+	}
+}
+
+void do_enable_mipi2lvds(struct display_info_t const *dev)
+{
+	struct arm_smccc_res res;
+
+	//printf("%s: Enable %s \n", __func__, dev->mode.name);
+
+	gpio_request(IMX_GPIO_NR(1, 5), "DISPLAY_EN");
+	gpio_direction_output(IMX_GPIO_NR(1, 5), 1);
+
+	gpio_request(IMX_GPIO_NR(1, 4), "LVDS EN");
+	gpio_direction_output(IMX_GPIO_NR(1, 4), 1);
+
+	gpio_request(IMX_GPIO_NR(1, 1), "BACKLIGHT PWM");
+	gpio_direction_output(IMX_GPIO_NR(1, 1), 1);
+	//gpio_direction_output(IMX_GPIO_NR(1, 1), 0);
+
+	//printf("do_enable_mipi2lvds pConXS_detected=%d\n", pConXS_detected);
+	if (pConXS_detected) {
+		// ToDo find out wether code runs on pConXS....
+		gpio_request(IMX_GPIO_NR(3, 22),
+			     "BACKLIGHT EN"); // Needed for pConXS
+		gpio_direction_output(IMX_GPIO_NR(3, 22),
+				      1); // Crashes iPANT7 FF
+	}
+
+	if (seco_fuse_GetModule() == SECO_FUSE_MODULE_TRIZEPS8MINI) {
+		if (seco_fuse_GetPCBrevision() <= SECO_FUSE_PCBREV_V1R3) {
+			lvds_init(dev);
+		}
+	}
+
+	/* enable the dispmix & mipi phy power domain */
+	arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN,
+		      DISPMIX, true, 0, 0, 0, 0, &res);
+	arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN,
+		      MIPI, true, 0, 0, 0, 0, &res);
+
+	/* Put lcdif out of reset */
+	disp_mix_bus_rstn_reset(imx8mm_mipi_dsim_plat_data.gpr_base, false);
+	disp_mix_lcdif_clks_enable(imx8mm_mipi_dsim_plat_data.gpr_base, true);
+
+	/* Setup mipi dsim */
+	sec_mipi_dsim_setup(&imx8mm_mipi_dsim_plat_data);
+
+	imx_mipi_dsi_bridge_attach(&seco_fuse_panel_drv);
+}
+
+void do_enable_mipi2hdmi(struct display_info_t const *dev)
+{
+	struct arm_smccc_res res;
+
+	/* ADV7353 initialization */
+	adv7535_init(dev);
+
+	/* enable the dispmix & mipi phy power domain */
+	arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN,
+		      DISPMIX, true, 0, 0, 0, 0, &res);
+	arm_smccc_smc(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN,
+		      MIPI, true, 0, 0, 0, 0, &res);
+
+	/* Put lcdif out of reset */
+	disp_mix_bus_rstn_reset(imx8mm_mipi_dsim_plat_data.gpr_base, false);
+	disp_mix_lcdif_clks_enable(imx8mm_mipi_dsim_plat_data.gpr_base, true);
+
+	/* Setup mipi dsim */
+	sec_mipi_dsim_setup(&imx8mm_mipi_dsim_plat_data);
+	imx_mipi_dsi_bridge_attach(&adv7535_dev); /* attach adv7535 device */
+}
+
+// clang-format off
+#define FOCALTECH_ID			0x38
+#define DATAIMAGE_ID			0x5C
+#define GOODIX_ID			0x5D
+#define ILITEK_ID			0x41
+#define EGALAX_ID			0x2A // eGalax Touch / G156HAN02.1 Display (15.6" GuF)
+#define SIS9255_ID			0x5C // SIS 9255 Touch / SFC1001 10.1" Display
+
+#define FT5X06_OP_REG_CHIPID		0xA3 /* vendor’s chip id */
+#define FT5X06_OP_REG_FIRMID		0xA6 /* the firmware id of the application */
+#define FT5X06_OP_REG_FT5201ID		0xA8
+// clang-format on
+
+static int detect_ipant7(struct display_info_t const *dev)
+{
+	struct udevice *bus, *main_dev;
+	int i2c_bus = 1;
+	int ret;
+	uint8_t touch_id = 0, chip_id = 0, firm_id = 0;
+
+	printf("%s:  %s \n", __func__, dev->mode.name);
+
+	gpio_request(IMX_GPIO_NR(3, 23), "TOUCH EN");
+	gpio_direction_output(IMX_GPIO_NR(3, 23), 1);
+
+	mdelay(100);
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, 1, &bus);
+	if (ret) {
+		printf("%s: No bus %d\n", __func__, 1);
+		return 0;
+	}
+
+	ret = dm_i2c_probe(bus, 0x4E, 0, &main_dev);
+	if (!ret) {
+		printf("%s: Can't find device id=0x%x, on bus %d\n", __func__, 0x4E, i2c_bus);
+		return 0;
+	}
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+	if (ret) {
+		//printf("%s: No bus %d\n", __func__, i2c_bus);
+		return 0;
+	}
+
+	ret = dm_i2c_probe(bus, FOCALTECH_ID, 0, &main_dev);
+	if (ret) {
+		//printf("%s: Can't find device id=0x%x, on bus %d\n",
+		//	__func__, FOCALTECH_ID, i2c_bus);
+		return 0;
+	}
+
+	//Check Version
+	ret = dm_i2c_read(main_dev, FT5X06_OP_REG_CHIPID, &chip_id, 1);
+	ret = dm_i2c_read(main_dev, FT5X06_OP_REG_FIRMID, &firm_id, 1);
+	ret = dm_i2c_read(main_dev, FT5X06_OP_REG_FT5201ID, &touch_id, 1);
+
+	printf("%s: ChipID 0x%x, FirmwareID 0x%x, TouchID 0x%x\n", __func__, chip_id, firm_id,
+	       touch_id);
+
+	if ((chip_id == 0x14 && firm_id == 0x06 && touch_id == 0x51) &&
+	    (!(strncmp(dev->mode.name, "RGB_ATM0700D6J", strlen(dev->mode.name))))) {
+		printf("%s: Version 1 AZ Coverlens Display \n", __func__);
+		seco_fuse_panel_drv.lanes = 2;
+		seco_fuse_panel_drv.name = "RGB_ATM0700D6J";
+		return 1;
+	} else if ((chip_id == 0x0A && firm_id == 0x3 && touch_id == 0x79) &&
+		   (!(strncmp(dev->mode.name, "RGB_ATM0700D6J", strlen(dev->mode.name))))) {
+		printf("%s: Version 1 AZ Display \n", __func__);
+		seco_fuse_panel_drv.lanes = 2;
+		seco_fuse_panel_drv.name = "RGB_ATM0700D6J";
+		return 1;
+	} else if (((chip_id == 0x0A && firm_id == 0x08 && touch_id == 0x79) &&
+		    (!(strncmp(dev->mode.name, "RGB_ATM0700D6J", strlen(dev->mode.name)))))) {
+		printf("%s: Version 1 HT Display  \n", __func__);
+		//TODO
+		return 0;
+	} else if (chip_id == 0x54 && (firm_id == 0x01 || firm_id == 0x02 || firm_id == 0x03) &&
+		   touch_id == 0x79 &&
+		   (!(strncmp(dev->mode.name, "LVDS_ATM0700L61", strlen(dev->mode.name))))) {
+		printf("%s: Version 2 \n", __func__);
+		seco_fuse_panel_drv.lanes = 4;
+		seco_fuse_panel_drv.name = "LVDS_ATM0700L61";
+		return 1;
+	} else {
+		printf("%s: unknown touch ChipID 0x%x, FirmwareID 0x%x, TouchID 0x%x \n", __func__,
+		       chip_id, firm_id, touch_id);
+		return 0;
+	}
+
+	return 0;
+}
+
+static int detect_ipanm7(struct display_info_t const *dev)
+{
+	struct udevice *bus, *main_dev;
+	int i2c_bus = 2;
+	int ret;
+
+	//printf("%s:  %s \n", __func__, dev->mode.name);
+	//Check LVDS
+
+	gpio_request(IMX_GPIO_NR(1, 4), "LVDS EN");
+	gpio_direction_output(IMX_GPIO_NR(1, 4), 1);
+#if 1
+	/*                                                                                       */
+	mdelay(60); // when adding this line: u-boot stops. See below:
+	/*
+	  CPU:   Commercial temperature grade (0C to 95C)Error in parsing TMU FDT -22
+	  ....
+	  Some drivers failed to bind
+	  initcall sequence 00000000fffb21c8 failed at call 000000004021c21c (err=-11)
+	  ### ERROR ### Please RESET the board ###
+	*/
+	// CONFIG_OF_EMBED helps. Also #define DEBUG 1 in drivers/core/root.c (dm_init() problem)
+	/*                                                                                        */
+#endif
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+	if (ret) {
+		//	printf("%s: No bus %d\n", __func__, i2c_bus);
+		return 0;
+	}
+
+	ret = dm_i2c_probe(bus, LVDS_ID, 0, &main_dev);
+	if (ret) {
+		//printf("%s: Can't find device id=0x%x, on bus %d\n",
+		//	__func__, LVDS_ID, i2c_bus);
+		return 0;
+	}
+
+	gpio_request(IMX_GPIO_NR(3, 23), "TOUCH EN");
+	gpio_direction_output(IMX_GPIO_NR(3, 23), 1);
+
+	mdelay(10);
+	i2c_bus = 1;
+	ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+	if (ret) {
+		//printf("%s: No bus %d\n", __func__, i2c_bus);
+		return 0;
+	}
+
+	ret = dm_i2c_probe(bus, FOCALTECH_ID, 0, &main_dev);
+	if (ret) {
+		//printf("%s: Can't find device id=0x%x, on bus %d\n",
+		//	__func__, FOCALTECH_ID, i2c_bus);
+		return 0;
+	}
+
+	seco_fuse_panel_drv.lanes = 4;
+	seco_fuse_panel_drv.name = "LVDS_ATM0700D6J";
+
+	return 1;
+}
+
+static int detect_ipant10(struct display_info_t const *dev)
+{
+	struct udevice *bus, *main_dev;
+	int i2c_bus = 1;
+	int ret;
+
+	//printf("%s:  %s \n", __func__, dev->mode.name);
+
+	gpio_request(IMX_GPIO_NR(3, 23), "TOUCH EN");
+	gpio_direction_output(IMX_GPIO_NR(3, 23), 0);
+
+	mdelay(10);
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+	if (ret) {
+		//printf("%s: No bus %d\n", __func__, i2c_bus);
+		return 0;
+	}
+
+	ret = dm_i2c_probe(bus, DATAIMAGE_ID, 0, &main_dev);
+	if (ret) {
+		//printf("%s: Can't find device id=0x%x, on bus %d\n",
+		//	__func__, DATAIMAGE_ID, i2c_bus);
+		return 0;
+	}
+
+	seco_fuse_panel_drv.lanes = 4;
+	seco_fuse_panel_drv.name = "LVDS_SCF1001C44GGU05";
+
+	return 1;
+}
+
+static int detect_pconxs(struct display_info_t const *dev, int touch)
+{
+	struct udevice *bus, *main_dev;
+	int i2c_bus = 2;
+	int ret;
+
+	gpio_request(IMX_GPIO_NR(3, 23), "TOUCH_EN");
+	gpio_direction_output(IMX_GPIO_NR(3, 23), 1);
+
+	gpio_request(IMX_GPIO_NR(1, 5), "DISPLAY_EN");
+	gpio_direction_output(IMX_GPIO_NR(1, 5), 1);
+
+	gpio_request(IMX_GPIO_NR(4, 14), "BL_EN");
+	gpio_direction_output(IMX_GPIO_NR(4, 14), 1);
+
+	gpio_request(IMX_GPIO_NR(1, 1), "BACKLIGHT_PWM");
+	//gpio_direction_output(IMX_GPIO_NR(1, 1), 1);
+	gpio_direction_output(IMX_GPIO_NR(1, 1), 0);
+
+	mdelay(10);
+
+	//Check LM75
+	i2c_bus = 0;
+	ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+	if (ret) {
+		printf("%s: No bus %d\n", __func__, 1);
+		return 0;
+	}
+
+	ret = dm_i2c_probe(bus, 0x4E, 0, &main_dev);
+	if (ret) {
+		printf("%s: Can't find device id=0x%x, on bus %d\n", __func__, 0x4E, i2c_bus);
+		return 0;
+	}
+
+	for (i2c_bus = 0; i2c_bus <= 1; i2c_bus++) {
+		printf("%s: bus %d\n", __func__, i2c_bus);
+		ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+		if (ret) {
+			printf("%s: No bus %d\n", __func__, i2c_bus);
+			//return 0;
+		}
+
+		ret = dm_i2c_probe(bus, touch, 0, &main_dev);
+		if (ret) {
+			printf("%s: Can't find device id=0x%x, on bus %d\n", __func__, touch,
+			       i2c_bus);
+			//return 0;
+		}
+		if (!ret)
+			break;
+	}
+
+	if (ret) {
+		return 0;
+	}
+
+	seco_fuse_panel_drv.lanes = 4;
+	seco_fuse_panel_drv.name = dev->mode.name;
+	pConXS_detected = 1;
+	return 1;
+}
+
+static int detect_display(struct display_info_t const *dev)
+{
+	struct udevice *bus;
+	int ret;
+	int i2c_bus = 1;
+	char *s;
+	int module;
+
+	s = env_get("display");
+	if (s) {
+		//printk("%s: Environment display=%s \n", __func__, s);
+		if (!(strncmp(s, dev->mode.name, strlen(s)))) {
+			//printf("%s: Choose %s \n", __func__, dev->mode.name);
+
+			ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+			if (ret) {
+				//printf("%s: No bus %d\n", __func__, i2c_bus);
+				return 0;
+			}
+
+			if (!(strncmp(s, "IPANT10", strlen(s)))) {
+				gpio_request(IMX_GPIO_NR(3, 23), "TOUCH EN");
+				gpio_direction_output(IMX_GPIO_NR(3, 23), 0);
+
+				seco_fuse_panel_drv.lanes = 4;
+				seco_fuse_panel_drv.name = "LVDS_SCF1001C44GGU05";
+			} else if (!(strncmp(s, "IPANT7", strlen(s)))) {
+				gpio_request(IMX_GPIO_NR(3, 23), "TOUCH EN");
+				gpio_direction_output(IMX_GPIO_NR(3, 23), 1);
+
+				seco_fuse_panel_drv.lanes = 2;
+				seco_fuse_panel_drv.name = "RGB_ATM0700D6J";
+			} else if (!(strncmp(s, "PCONXS", strlen(s)))) {
+				gpio_request(IMX_GPIO_NR(3, 23), "TOUCH EN");
+				gpio_direction_output(IMX_GPIO_NR(3, 23), 0);
+
+				gpio_request(IMX_GPIO_NR(4, 14), "BL_EN");
+				gpio_direction_output(IMX_GPIO_NR(4, 14), 1);
+
+				seco_fuse_panel_drv.lanes = 4;
+				seco_fuse_panel_drv.name = "PCONXS";
+			} else if (!(strncmp(s, "IPANM7", strlen(s)))) {
+				gpio_request(IMX_GPIO_NR(3, 23), "TOUCH EN");
+				gpio_direction_output(IMX_GPIO_NR(3, 23), 1);
+
+				seco_fuse_panel_drv.lanes = 4;
+				seco_fuse_panel_drv.name = "LVDS_ATM0700D6J";
+			} else if (!(strncmp(s, "IPANT7_V2", strlen(s)))) {
+				gpio_request(IMX_GPIO_NR(3, 23), "TOUCH EN");
+				gpio_direction_output(IMX_GPIO_NR(3, 23), 1);
+
+				seco_fuse_panel_drv.lanes = 4;
+				seco_fuse_panel_drv.name = "LVDS_ATM0700L61";
+			} else if (!(strncmp(s, "LVDS_AM19201080D1", strlen(s)))) {
+				gpio_request(IMX_GPIO_NR(4, 14), "BL_EN");
+				gpio_direction_output(IMX_GPIO_NR(4, 14), 1);
+
+				gpio_request(IMX_GPIO_NR(3, 23), "TOUCH EN");
+				gpio_direction_output(IMX_GPIO_NR(3, 23), 1);
+
+				seco_fuse_panel_drv.lanes = 4;
+				seco_fuse_panel_drv.name = "LVDS_AM19201080D1";
+			} else if (!(strncmp(s, "LVDS_G156HAN02.1", strlen(s)))) {
+				gpio_request(IMX_GPIO_NR(4, 14), "BL_EN");
+				gpio_direction_output(IMX_GPIO_NR(4, 14), 1);
+
+				gpio_request(IMX_GPIO_NR(3, 23), "TOUCH EN");
+				gpio_direction_output(IMX_GPIO_NR(3, 23), 1);
+
+				gpio_request(IMX_GPIO_NR(3, 7), "PCIE_EN");
+				gpio_direction_output(IMX_GPIO_NR(3, 7), 1);
+				seco_fuse_panel_drv.lanes = 4;
+				seco_fuse_panel_drv.name = "LVDS_G156HAN02.1";
+			}
+
+			return 1;
+		}
+		if (strncmp(s, "auto", strlen(s))) {
+			return 0;
+		}
+	}
+	printk("%s: Try autodetect... %s \n", __func__, dev->mode.name);
+	module = seco_fuse_GetModule();
+	if (MODULE_IS_TRIZEPS8MINI_TYPE(module)) {
+		if ((!(strncmp(dev->mode.name, "RGB_ATM0700D6J", strlen(dev->mode.name))))) {
+			return detect_ipant7(dev);
+		} else if ((!(strncmp(dev->mode.name, "LVDS_ATM0700L61", strlen(dev->mode.name))))) {
+			return detect_ipant7(dev);
+		} else if (!(strncmp(dev->mode.name, "LVDS_SCF1001C44GGU05",
+				     strlen(dev->mode.name)))) {
+			return detect_ipant10(dev);
+		} else if (!(strncmp(dev->mode.name, "PCONXS", strlen(dev->mode.name)))) {
+			if (detect_pconxs(dev, FOCALTECH_ID)) {
+				return 1;
+			} else
+				return 0;
+		} else if (!(strncmp(dev->mode.name, "LVDS_AM19201080D1",
+				     strlen(dev->mode.name)))) {
+			if (detect_pconxs(dev, ILITEK_ID)) {
+				gpio_request(IMX_GPIO_NR(4, 14), "BL_EN");
+				gpio_direction_output(IMX_GPIO_NR(4, 14), 1);
+
+				return 1;
+			} else
+				return 0;
+		} else if ((!(strncmp(dev->mode.name, "RGB18_ATM0700D6J",
+				      strlen(dev->mode.name))))) {
+			if (detect_pconxs(dev, FOCALTECH_ID)) {
+				seco_fuse_panel_drv.lanes = 2;
+				seco_fuse_panel_drv.name = "RGB18_ATM0700D6J";
+				return 1;
+			} else
+				return 0;
+		} else if ((!(strncmp(dev->mode.name, "LVDS_G156HAN02.1",
+				      strlen(dev->mode.name))))) {
+			if (detect_pconxs(dev, EGALAX_ID)) {
+				gpio_request(IMX_GPIO_NR(3, 7), "PCIE_EN");
+				gpio_direction_output(IMX_GPIO_NR(3, 7), 1);
+
+				seco_fuse_panel_drv.lanes = 4;
+				seco_fuse_panel_drv.name = "LVDS_G156HAN02.1";
+				return 1;
+			} else
+				return 0;
+		} else if ((!(strncmp(dev->mode.name, "GUF_LVDS_SCF1001C44GGU05",
+				      strlen(dev->mode.name))))) {
+			if (detect_pconxs(dev, SIS9255_ID)) {
+				gpio_request(IMX_GPIO_NR(3, 7), "PCIE_EN");
+				gpio_direction_output(IMX_GPIO_NR(3, 7), 1);
+
+				seco_fuse_panel_drv.lanes = 4;
+				seco_fuse_panel_drv.name = "GUF_LVDS_SCF1001C44GGU05";
+				return 1;
+			} else
+				return 0;
+		}
+	}
+	if ((!(strncmp(dev->mode.name, "LVDS_ATM0700D6J", strlen(dev->mode.name)))) &&
+	    MODULE_IS_MYON_TYPE(module)) {
+		return detect_ipanm7(dev);
+	} else if (!(strncmp(dev->mode.name, "HDMI_1920x1080", strlen(dev->mode.name)))) {
+		return adv7535_init(dev);
+	}
+
+	return 0;
+}
+
+// clang-format off
+struct display_info_t const displays[] = {
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2lvds,
+	  .mode = { .name = "G104XVN01",
+		    .refresh = 60,
+		    .xres = 1024,
+		    .yres = 768,
+		    .pixclock = 16835, /* 59400000 // 65000000 */
+		    .left_margin = 156,
+		    .right_margin = 156,
+		    .upper_margin = 21,
+		    .lower_margin = 7,
+		    .hsync_len = 8,
+		    .vsync_len = 10,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED } },
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2lvds,
+	  .mode = { .name = "PCONXS",
+		    .refresh = 60,
+		    .xres = 1024,
+		    .yres = 600,
+		    .pixclock = 16835, /* 59400000 // 65000000 */
+		    .left_margin = 156,
+		    .right_margin = 156,
+		    .upper_margin = 21,
+		    .lower_margin = 7,
+		    .hsync_len = 8,
+		    .vsync_len = 10,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED } },
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2lvds,
+	  .mode = { .name = "LVDS_SCF1001C44GGU05",
+		    .refresh = 60,
+		    .xres = 1280,
+		    .yres = 800,
+		    .pixclock = 24390, /* 41000000 */
+		    .left_margin = 48,
+		    .right_margin = 52,
+		    .upper_margin = 10,
+		    .lower_margin = 10,
+		    .hsync_len = 60,
+		    .vsync_len = 3,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED } },
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2lvds,
+	  .mode = { .name = "GUF_LVDS_SCF1001C44GGU05",
+		    .refresh = 60,
+		    .xres = 1280,
+		    .yres = 800,
+		    .pixclock = 24390, /* 41000000 */
+		    .left_margin = 48,
+		    .right_margin = 52,
+		    .upper_margin = 10,
+		    .lower_margin = 10,
+		    .hsync_len = 60,
+		    .vsync_len = 3,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED } },
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2lvds,
+	  .mode = { .name = "LVDS_ATM0700L61",
+		    .refresh = 60,
+		    .xres = 1024,
+		    .yres = 600,
+		    .pixclock = 16835, /* 59400000 // 65000000 */
+		    .left_margin = 156,
+		    .right_margin = 156,
+		    .upper_margin = 21,
+		    .lower_margin = 7,
+		    .hsync_len = 8,
+		    .vsync_len = 10,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED } },
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2rgb,
+	  .mode = { .name = "RGB18_ATM0700D6J",
+		    .refresh = 60,
+		    .xres = 800,
+		    .yres = 480,
+		    .pixclock = 33300, /* 33300000 */
+		    .left_margin = 40,
+		    .right_margin = 210,
+		    .upper_margin = 20,
+		    .lower_margin = 22,
+		    .hsync_len = 6,
+		    .vsync_len = 3,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED } },
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2rgb,
+	  .mode = { .name = "RGB_ATM0700D6J",
+		    .refresh = 60,
+		    .xres = 800,
+		    .yres = 480,
+		    .pixclock = 33300, /* 33300000 */
+		    .left_margin = 40,
+		    .right_margin = 210,
+		    .upper_margin = 20,
+		    .lower_margin = 22,
+		    .hsync_len = 6,
+		    .vsync_len = 3,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED } },
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2lvds,
+	  .mode = { .name = "LVDS_ATM0700D6J",
+		    .refresh = 60,
+		    .xres = 800,
+		    .yres = 480,
+		    .pixclock = 16835, /* 59400000 // 65000000 */
+		    .left_margin = 156,
+		    .right_margin = 156,
+		    .upper_margin = 21,
+		    .lower_margin = 7,
+		    .hsync_len = 8,
+		    .vsync_len = 10,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED } },
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2hdmi,
+	  .mode = { .name = "HDMI_1920x1080",
+		    .refresh = 60,
+		    .xres = 1920,
+		    .yres = 1080,
+		    .pixclock = 6734, /* 148500000 */
+		    .left_margin = 148,
+		    .right_margin = 88,
+		    .upper_margin = 36,
+		    .lower_margin = 4,
+		    .hsync_len = 44,
+		    .vsync_len = 5,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED } },
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2lvds,
+	  .mode = { .name = "LVDS_AM19201080D1",
+		    .refresh = 60,
+		    .xres = 1920,
+		    .yres = 1080,
+		    .pixclock = 6734, /* 148500000 */
+		    .left_margin = 148,
+		    .right_margin = 88,
+		    .upper_margin = 36,
+		    .lower_margin = 4,
+		    .hsync_len = 44,
+		    .vsync_len = 5,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED } },
+	{ .bus = LCDIF_BASE_ADDR,
+	  .addr = 0,
+	  .pixfmt = 24,
+	  .detect = detect_display,
+	  .enable = do_enable_mipi2lvds,
+	  .mode = { .name = "LVDS_G156HAN02.1",
+		    .refresh = 60,
+		    .xres = 1920,
+		    .yres = 1080,
+		    .pixclock = 6734, /* 68.5 > 70.5 MHz > 74.5 */
+		    .left_margin = 91,
+		    .right_margin = 91,
+		    .upper_margin = 8,
+		    .lower_margin = 8,
+		    .hsync_len = 40,
+		    .vsync_len = 4,
+		    .sync = FB_SYNC_EXT,
+		    .vmode = FB_VMODE_NONINTERLACED
+	} },
+	{ .detect = detect_display,
+	  .enable = do_display_default,
+	  .mode = { .name = "none", }
+	} } ;
+// clang-format on
+size_t display_count = ARRAY_SIZE(displays);
diff --git a/board/seco/imx8mm_myon2/spl.c b/board/seco/imx8mm_myon2/spl.c
index b2e091e90c08bb80f839318538d70859fe66d733..c83ea1fdb098c446aef494b03dea3a904d22bd81 100644
--- a/board/seco/imx8mm_myon2/spl.c
+++ b/board/seco/imx8mm_myon2/spl.c
@@ -342,6 +342,7 @@ void board_init_f(ulong dummy)
 	/* DDR initialization */
 	spl_dram_init();
 
+#if 0
 	if (seco_fuse_GetPCBrevision() < SECO_FUSE_PCBREV_V2R2)
 		/* Hardcode spread spectrum on VideoPLL1 30kHz, 2%, centered
 		 * used for lvds signals via MIPI-to-LVDS converter
@@ -350,6 +351,7 @@ void board_init_f(ulong dummy)
 		ssc_state_video_pll(true, 0x80019052);
 	else
 		ssc_state_video_pll(false, 0x80019052);
+#endif
 
 	max_freq = get_cpu_speed_grade_hz();
 	if (max_freq) {
diff --git a/board/seco/imx8mm_myon2/video_callgraph b/board/seco/imx8mm_myon2/video_callgraph
new file mode 100644
index 0000000000000000000000000000000000000000..a60f9e57866beb3b08555ddfbdd1ec95262a7fa7
--- /dev/null
+++ b/board/seco/imx8mm_myon2/video_callgraph
@@ -0,0 +1,30 @@
+stdio_add_devices()                         common/stdio.c
+  |
+  ->  drv_video_init()                      drivers/video/cfb_console.c    !defined(CONFIG_DM_VIDEO) && (defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE))
+      |
+      +>  board_video_skip()                arch/arm/mach-imx/video.c
+      |    |
+      |    +->  detect_display()            board/seco/imx8mm_myon2/display.c
+      |    |
+      |    ->  do_enable_mipi2lvds()        board/seco/imx8mm_myon2/display.c
+      |        |
+      |        +>  sec_mipi_dsim_setup()    drivers/video/sec_mipi_dsim.c
+      |        |    |
+      |        |    ->  imx_mipi_dsi_bridge_register_driver()
+      |        |
+      |        ->  imx_mipi_dsi_bridge_attach()
+      |
+      ->  cfg_video_init()                  drivers/video/cfb_console.c
+          |
+          +>  video_hw_init()               drivers/video/mxsfb.c
+          |    |
+          |    +>  imx_mipi_dsi_bridge_mode_set()
+          |    |
+          |    +>  imx_mipi_dsi_bridge_enable()
+          |    |
+          |    ->  mxs_lcd_init()           drivers/video/mxsfb.c
+          |
+          ->  video_logo()                  drivers/video/cfb_console.c    defined(CONFIG_VIDEO_LOGO)
+              |
+              ->  logo_plot()
+
diff --git a/configs/seco_imx8mm_myon2_defconfig b/configs/seco_imx8mm_myon2_defconfig
index 284973a3e883ffc4448a7900f883453858358cec..017fe65cb55fbf9df8be3d6a731d6ca42799de5d 100644
--- a/configs/seco_imx8mm_myon2_defconfig
+++ b/configs/seco_imx8mm_myon2_defconfig
@@ -117,6 +117,8 @@ CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_USB_FUNCTION_SDP=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_VIDEO=y
+CONFIG_IMX_SEC_MIPI_DSI=y
 CONFIG_IMX_WATCHDOG=y
 CONFIG_WDT=y
 CONFIG_PANIC_HANG=y
diff --git a/configs/seco_imx8mm_myon2_fastboot_defconfig b/configs/seco_imx8mm_myon2_fastboot_defconfig
index a710ef0627d82817f00428a592c84bdaa96be20d..a4ec7600311a43e5ff2d636e560d51ddb5cba316 100644
--- a/configs/seco_imx8mm_myon2_fastboot_defconfig
+++ b/configs/seco_imx8mm_myon2_fastboot_defconfig
@@ -121,6 +121,8 @@ CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_USB_FUNCTION_SDP=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_VIDEO=y
+CONFIG_IMX_SEC_MIPI_DSI=y
 CONFIG_IMX_WATCHDOG=y
 CONFIG_WDT=y
 CONFIG_PANIC_HANG=y
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 759434763066226ea3308e1d2e1261593193f318..1b63f4000cbe9b58310bb15bdf2122aaf2d21ee2 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -695,6 +695,19 @@ config VIDEO
 	  model. Video drivers typically provide a colour text console and
 	  cursor.
 
+config IMX_MIPI_DSI_BRIDGE
+	bool
+	help
+	  Enable MIPI DSI bridge interface for display controller.
+
+config IMX_SEC_MIPI_DSI
+	bool "i.MX Samsung's MIPI DSI"
+	default n
+	select IMX_MIPI_DSI_BRIDGE
+	depends on VIDEO && (IMX8MM || IMX8MN || MX7 || IMX8MP)
+	help
+	  Support for i.MX7, i.MX8MM and i.MX8MN MIPI DSI controller.
+
 config MXC_EPDC
 	bool "i.MX EPDC support"
 	depends on LCD && (MX7 || MX6)
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index c4da9e5e20fffb2fb8aa029d5745baef5d28758b..4710c72f0efce68e21deb5158b63c0e3a727f62c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -82,6 +82,9 @@ obj-$(CONFIG_VIDEO_CSI) += mxc_csi.o
 obj-$(CONFIG_VIDEO_PXP) += mxc_pxp.o
 obj-$(CONFIG_VIDEO_GIS) += mxc_gis.o
 
+obj-$(CONFIG_IMX_MIPI_DSI_BRIDGE) += imx_mipi_dsi_bridge.o
+obj-$(CONFIG_IMX_SEC_MIPI_DSI) += sec_mipi_dsim.o
+
 obj-y += bridge/
 obj-y += sunxi/
 obj-y += nxp/
diff --git a/drivers/video/imx_mipi_dsi_bridge.c b/drivers/video/imx_mipi_dsi_bridge.c
new file mode 100644
index 0000000000000000000000000000000000000000..a3e9e26317d876d026a57fc270bdbae280a3fe79
--- /dev/null
+++ b/drivers/video/imx_mipi_dsi_bridge.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2018 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <imx_mipi_dsi_bridge.h>
+
+static struct mipi_dsi_bridge_driver *registered_driver = NULL;
+
+int imx_mipi_dsi_bridge_attach(struct mipi_dsi_client_dev *dsi_dev)
+{
+	int ret = 0;
+
+	if (!registered_driver)
+		return -EPERM;
+
+	if (registered_driver->attach)
+		ret = registered_driver->attach(registered_driver, dsi_dev);
+
+	return ret;
+}
+
+int imx_mipi_dsi_bridge_mode_set(struct fb_videomode *pvmode)
+{
+	int ret = 0;
+
+	if (!registered_driver)
+		return -EPERM;
+
+	if (registered_driver->mode_set)
+		ret = registered_driver->mode_set(registered_driver, pvmode);
+
+	return ret;
+}
+
+int imx_mipi_dsi_bridge_enable(void)
+{
+	int ret = 0;
+
+	if (!registered_driver)
+		return -EPERM;
+
+	if (registered_driver->enable)
+		ret = registered_driver->enable(registered_driver);
+
+	return ret;
+}
+
+int imx_mipi_dsi_bridge_disable(void)
+{
+	int ret = 0;
+
+	if (!registered_driver)
+		return -EPERM;
+
+	if (registered_driver->disable)
+		ret = registered_driver->disable(registered_driver);
+
+	return ret;
+}
+
+int imx_mipi_dsi_bridge_pkt_write(u8 data_type, const u8 *buf, int len)
+{
+	int ret = 0;
+
+	if (!registered_driver)
+		return -EPERM;
+
+	if (registered_driver->pkt_write)
+		ret = registered_driver->pkt_write(registered_driver, data_type, buf, len);
+
+	return ret;
+}
+
+int imx_mipi_dsi_bridge_add_client_driver(struct mipi_dsi_client_driver *client_driver)
+{
+	int ret = 0;
+
+	if (!registered_driver)
+		return -EPERM;
+
+	if (registered_driver->add_client_driver)
+		ret = registered_driver->add_client_driver(registered_driver, client_driver);
+
+	return ret;
+}
+
+int imx_mipi_dsi_bridge_register_driver(struct mipi_dsi_bridge_driver *driver)
+{
+	if (!driver)
+		return -EINVAL;
+
+	if (registered_driver)
+		return -EBUSY;
+
+	registered_driver = driver;
+
+	return 0;
+}
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index 4757f3ec753d833b6ecb05a8caf723ef1e36f7be..df546dc90fb03a720e9e8bc56c0b6aae4a5bc675 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -44,6 +44,10 @@
 #include <gis.h>
 #endif
 
+#ifdef CONFIG_IMX_MIPI_DSI_BRIDGE
+#include <imx_mipi_dsi_bridge.h>
+#endif
+
 #define	PS2KHZ(ps)	(1000000000UL / (ps))
 #define HZ2PS(hz)	(1000000000UL / ((hz) / 1000))
 
@@ -360,7 +364,22 @@ void *video_hw_init(void)
 	printf("%s\n", panel.modeIdent);
 
 	video_ctfb_mode_to_display_timing(&mode, &timings);
+
+#ifdef CONFIG_IMX_MIPI_DSI_BRIDGE
+	int dsi_ret;
+	imx_mipi_dsi_bridge_mode_set(&fbmode);
+	dsi_ret = imx_mipi_dsi_bridge_enable();
+	if (dsi_ret) {
+		printf("Enable DSI bridge failed, err %d\n", dsi_ret);
+		return NULL;
+	}
+#endif
+
+#ifdef CONFIG_IMX_SEC_MIPI_DSI
+	timings.flags |= DISPLAY_FLAGS_DE_LOW;
+#else
 	timings.flags |= DISPLAY_FLAGS_DE_HIGH; /* Force enable pol */
+#endif
 
 	ret = mxs_probe_common(panel.isaBase, &timings, bpp, (u32)fb, false);
 	if (ret)
diff --git a/drivers/video/sec_mipi_dsim.c b/drivers/video/sec_mipi_dsim.c
new file mode 100644
index 0000000000000000000000000000000000000000..e8922115b1d68422ed5f314774f48f8f9fad1561
--- /dev/null
+++ b/drivers/video/sec_mipi_dsim.c
@@ -0,0 +1,1024 @@
+/*
+ * Copyright 2018 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <div64.h>
+#include <i2c.h>
+#include <malloc.h>
+#include <linux/delay.h>
+#include <sec_mipi_dsim.h>
+#include <imx_mipi_dsi_bridge.h>
+#include <asm-generic/gpio.h>
+#include <asm/mach-imx/gpio.h>
+#include "../../board/seco/common/seco_fuse.h"
+
+#define BX5_ID				0x64
+
+#define MIPI_FIFO_TIMEOUT		250000 /* 250ms */
+
+#define DRIVER_NAME	"imx_sec_mipi_dsim"
+
+/* dsim registers */
+#define DSIM_VERSION			0x00
+#define DSIM_STATUS			0x04
+#define DSIM_RGB_STATUS			0x08
+#define DSIM_SWRST			0x0c
+#define DSIM_CLKCTRL			0x10
+#define DSIM_TIMEOUT			0x14
+#define DSIM_CONFIG			0x18
+#define DSIM_ESCMODE			0x1c
+#define DSIM_MDRESOL			0x20
+#define DSIM_MVPORCH			0x24
+#define DSIM_MHPORCH			0x28
+#define DSIM_MSYNC			0x2c
+#define DSIM_SDRESOL			0x30
+#define DSIM_INTSRC			0x34
+#define DSIM_INTMSK			0x38
+
+/* packet */
+#define DSIM_PKTHDR			0x3c
+#define DSIM_PAYLOAD			0x40
+#define DSIM_RXFIFO			0x44
+#define DSIM_FIFOTHLD			0x48
+#define DSIM_FIFOCTRL			0x4c
+#define DSIM_MEMACCHR			0x50
+#define DSIM_MULTI_PKT			0x78
+
+/* pll control */
+#define DSIM_PLLCTRL_1G			0x90
+#define DSIM_PLLCTRL			0x94
+#define DSIM_PLLCTRL1			0x98
+#define DSIM_PLLCTRL2			0x9c
+#define DSIM_PLLTMR			0xa0
+
+/* dphy */
+#define DSIM_PHYTIMING			0xb4
+#define DSIM_PHYTIMING1			0xb8
+#define DSIM_PHYTIMING2			0xbc
+
+/* reg bit manipulation */
+#define REG_MASK(e, s) (((1 << ((e) - (s) + 1)) - 1) << (s))
+#define REG_PUT(x, e, s) (((x) << (s)) & REG_MASK(e, s))
+#define REG_GET(x, e, s) (((x) & REG_MASK(e, s)) >> (s))
+
+/* register bit fields */
+#define STATUS_PLLSTABLE		BIT(31)
+#define STATUS_SWRSTRLS			BIT(20)
+#define STATUS_TXREADYHSCLK		BIT(10)
+#define STATUS_ULPSCLK			BIT(9)
+#define STATUS_STOPSTATECLK		BIT(8)
+#define STATUS_GET_ULPSDAT(x)		REG_GET(x,  7,  4)
+#define STATUS_GET_STOPSTATEDAT(x)	REG_GET(x,  3,  0)
+
+#define RGB_STATUS_CMDMODE_INSEL	BIT(31)
+#define RGB_STATUS_GET_RGBSTATE(x)	REG_GET(x, 12,  0)
+
+#define CLKCTRL_TXREQUESTHSCLK		BIT(31)
+#define CLKCTRL_DPHY_SEL_1G		BIT(29)
+#define CLKCTRL_DPHY_SEL_1P5G		(0x0 << 29)
+#define CLKCTRL_ESCCLKEN		BIT(28)
+#define CLKCTRL_PLLBYPASS		BIT(29)
+#define CLKCTRL_BYTECLKSRC_DPHY_PLL	REG_PUT(0, 26, 25)
+#define CLKCTRL_BYTECLKEN		BIT(24)
+#define CLKCTRL_SET_LANEESCCLKEN(x)	REG_PUT(x, 23, 19)
+#define CLKCTRL_SET_ESCPRESCALER(x)	REG_PUT(x, 15,  0)
+
+#define TIMEOUT_SET_BTAOUT(x)		REG_PUT(x, 23, 16)
+#define TIMEOUT_SET_LPDRTOUT(x)		REG_PUT(x, 15,  0)
+
+#define CONFIG_NON_CONTINOUS_CLOCK_LANE	BIT(31)
+#define CONFIG_CLKLANE_STOP_START	BIT(30)
+#define CONFIG_MFLUSH_VS		BIT(29)
+#define CONFIG_EOT_R03			BIT(28)
+#define CONFIG_SYNCINFORM		BIT(27)
+#define CONFIG_BURSTMODE		BIT(26)
+#define CONFIG_VIDEOMODE		BIT(25)
+#define CONFIG_AUTOMODE			BIT(24)
+#define CONFIG_HSEDISABLEMODE		BIT(23)
+#define CONFIG_HFPDISABLEMODE		BIT(22)
+#define CONFIG_HBPDISABLEMODE		BIT(21)
+#define CONFIG_HSADISABLEMODE		BIT(20)
+#define CONFIG_SET_MAINVC(x)		REG_PUT(x, 19, 18)
+#define CONFIG_SET_SUBVC(x)		REG_PUT(x, 17, 16)
+#define CONFIG_SET_MAINPIXFORMAT(x)	REG_PUT(x, 14, 12)
+#define CONFIG_SET_SUBPIXFORMAT(x)	REG_PUT(x, 10,  8)
+#define CONFIG_SET_NUMOFDATLANE(x)	REG_PUT(x,  6,  5)
+#define CONFIG_SET_LANEEN(x)		REG_PUT(x,  4,  0)
+
+#define MDRESOL_MAINSTANDBY		BIT(31)
+#define MDRESOL_SET_MAINVRESOL(x)	REG_PUT(x, 27, 16)
+#define MDRESOL_SET_MAINHRESOL(x)	REG_PUT(x, 11,  0)
+
+#define MVPORCH_SET_CMDALLOW(x)		REG_PUT(x, 31, 28)
+#define MVPORCH_SET_STABLEVFP(x)	REG_PUT(x, 26, 16)
+#define MVPORCH_SET_MAINVBP(x)		REG_PUT(x, 10,  0)
+
+#define MHPORCH_SET_MAINHFP(x)		REG_PUT(x, 31, 16)
+#define MHPORCH_SET_MAINHBP(x)		REG_PUT(x, 15,  0)
+
+#define MSYNC_SET_MAINVSA(x)		REG_PUT(x, 31, 22)
+#define MSYNC_SET_MAINHSA(x)		REG_PUT(x, 15,  0)
+
+#define INTSRC_PLLSTABLE		BIT(31)
+#define INTSRC_SWRSTRELEASE		BIT(30)
+#define INTSRC_SFRPLFIFOEMPTY		BIT(29)
+#define INTSRC_SFRPHFIFOEMPTY		BIT(28)
+#define INTSRC_FRAMEDONE		BIT(24)
+#define INTSRC_LPDRTOUT			BIT(21)
+#define INTSRC_TATOUT			BIT(20)
+#define INTSRC_RXDATDONE		BIT(18)
+#define INTSRC_MASK			(INTSRC_PLLSTABLE	|	\
+					 INTSRC_SWRSTRELEASE	|	\
+					 INTSRC_SFRPLFIFOEMPTY	|	\
+					 INTSRC_SFRPHFIFOEMPTY	|	\
+					 INTSRC_FRAMEDONE	|	\
+					 INTSRC_LPDRTOUT	|	\
+					 INTSRC_TATOUT		|	\
+					 INTSRC_RXDATDONE)
+
+#define INTMSK_MSKPLLSTABLE		BIT(31)
+#define INTMSK_MSKSWRELEASE		BIT(30)
+#define INTMSK_MSKSFRPLFIFOEMPTY	BIT(29)
+#define INTMSK_MSKSFRPHFIFOEMPTY	BIT(28)
+#define INTMSK_MSKFRAMEDONE		BIT(24)
+#define INTMSK_MSKLPDRTOUT		BIT(21)
+#define INTMSK_MSKTATOUT		BIT(20)
+#define INTMSK_MSKRXDATDONE		BIT(18)
+
+#define PLLCTRL_DPDNSWAP_CLK		BIT(25)
+#define PLLCTRL_DPDNSWAP_DAT		BIT(24)
+#define PLLCTRL_PLLEN			BIT(23)
+#define PLLCTRL_SET_PMS(x)		REG_PUT(x, 19,  1)
+
+#define PHYTIMING_SET_M_TLPXCTL(x)	REG_PUT(x, 15,  8)
+#define PHYTIMING_SET_M_THSEXITCTL(x)	REG_PUT(x,  7,  0)
+
+#define PHYTIMING1_SET_M_TCLKPRPRCTL(x)	 REG_PUT(x, 31, 24)
+#define PHYTIMING1_SET_M_TCLKZEROCTL(x)	 REG_PUT(x, 23, 16)
+#define PHYTIMING1_SET_M_TCLKPOSTCTL(x)	 REG_PUT(x, 15,  8)
+#define PHYTIMING1_SET_M_TCLKTRAILCTL(x) REG_PUT(x,  7,  0)
+
+#define PHYTIMING2_SET_M_THSPRPRCTL(x)	REG_PUT(x, 23, 16)
+#define PHYTIMING2_SET_M_THSZEROCTL(x)	REG_PUT(x, 15,  8)
+#define PHYTIMING2_SET_M_THSTRAILCTL(x)	REG_PUT(x,  7,  0)
+
+#define dsim_read(dsim, reg)		readl(dsim->base + reg)
+#define dsim_write(dsim, val, reg)	writel(val, dsim->base + reg)
+
+/* fixed phy ref clk rate */
+#define PHY_REF_CLK		27000000
+
+#define MAX_MAIN_HRESOL		2047
+#define MAX_MAIN_VRESOL		2047
+#define MAX_SUB_HRESOL		1024
+#define MAX_SUB_VRESOL		1024
+
+/* in KHZ */
+#define MAX_ESC_CLK_FREQ	20000
+
+/* dsim all irqs index */
+#define PLLSTABLE		1
+#define SWRSTRELEASE		2
+#define SFRPLFIFOEMPTY		3
+#define SFRPHFIFOEMPTY		4
+#define SYNCOVERRIDE		5
+#define BUSTURNOVER		6
+#define FRAMEDONE		7
+#define LPDRTOUT		8
+#define TATOUT			9
+#define RXDATDONE		10
+#define RXTE			11
+#define RXACK			12
+#define ERRRXECC		13
+#define ERRRXCRC		14
+#define ERRESC3			15
+#define ERRESC2			16
+#define ERRESC1			17
+#define ERRESC0			18
+#define ERRSYNC3		19
+#define ERRSYNC2		20
+#define ERRSYNC1		21
+#define ERRSYNC0		22
+#define ERRCONTROL3		23
+#define ERRCONTROL2		24
+#define ERRCONTROL1		25
+#define ERRCONTROL0		26
+
+#define MIPI_HFP_PKT_OVERHEAD	6
+#define MIPI_HBP_PKT_OVERHEAD	6
+#define MIPI_HSA_PKT_OVERHEAD	6
+
+/* Dispmix Control & GPR Registers */
+#define DISPLAY_MIX_SFT_RSTN_CSR		0x00
+#ifdef CONFIG_IMX8MN
+#define MIPI_DSI_I_PRESETn_SFT_EN		BIT(0) | BIT(1)
+#else
+#define MIPI_DSI_I_PRESETn_SFT_EN		BIT(5)
+#endif
+#define DISPLAY_MIX_CLK_EN_CSR			0x04
+
+#ifdef CONFIG_IMX8MN
+#define MIPI_DSI_PCLK_SFT_EN			BIT(0)
+#define MIPI_DSI_CLKREF_SFT_EN			BIT(1)
+#else
+#define MIPI_DSI_PCLK_SFT_EN			BIT(8)
+#define MIPI_DSI_CLKREF_SFT_EN			BIT(9)
+#endif
+#define GPR_MIPI_RESET_DIV			0x08
+/* Clock & Data lanes reset: Active Low */
+#define GPR_MIPI_S_RESETN			BIT(16)
+#define GPR_MIPI_M_RESETN			BIT(17)
+
+#define	PS2KHZ(ps)	(1000000000UL / (ps))
+
+/* DSIM PLL configuration from spec:
+ *
+ * Fout(DDR) = (M * Fin) / (P * 2^S), so Fout / Fin = M / (P * 2^S)
+ * Fin_pll   = Fin / P     (6 ~ 12 MHz)
+ * S: [2:0], M: [12:3], P: [18:13], so
+ * TODO: 'S' is in [0 ~ 3], 'M' is in, 'P' is in [1 ~ 33]
+ *
+ */
+
+// Initialize QuickLogic ArcticLink III Bx5 with auto-generated array
+static void bx5_init(void)
+{
+	printf("Bx5 Init Sequence\n");
+	struct udevice *bus, *bx5_dev;
+	int i2c_bus = 2;
+	int ret;
+	uint8_t CONTROL_BYTE_GEN = 0x09;
+	uint8_t i2c_telegram[10] = { 0x29, 0x05, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+	// Generated by SECO_ATM0700L61-CT18_U-Boot.xlsm (18.08.2022 16:16:20)
+	struct Addr_data {
+		int addr;
+		int data;
+	} Vx_addr_data[] = {
+		{ 0x700, 0x6C000040 }, { 0x704, 0x3009A },    { 0x70C, 0x00004604 },
+		{ 0x710, 0x00CD000B }, { 0x714, 0x0 },	      { 0x718, 0x00000101 },
+		{ 0x71C, 0x2F },       { 0x720, 0x0 },	      { 0x154, 0x00000000 },
+		{ 0x154, 0x80000000 }, { 0x700, 0x6C000040 }, { 0x70C, 0x00004646 },
+		{ 0x718, 0x00000001 }, { 0x154, 0x00000000 }, { 0x154, 0x80000000 },
+		{ 0x120, 0x5 },	       { 0x124, 0x212C400 },  { 0x128, 0x101C15 },
+		{ 0x12C, 0x99 },       { 0x130, 0x3C18 },     { 0x134, 0x00000015 },
+		{ 0x138, 0xFF8000 },   { 0x13C, 0x0 },	      { 0x140, 0x10000 },
+		{ 0x20C, 0x124 },      { 0x21C, 0x3E8 },      { 0x224, 0x0 },
+		{ 0x228, 0x10000 },    { 0x228, 0x10000 },    { 0x22C, 0xFF03 },
+		{ 0x230, 0x1 },	       { 0x234, 0xCA033E10 }, { 0x238, 0x00000060 },
+		{ 0x244, 0x00120285 }, { 0x258, 0xA0008 },    { 0x158, 0x0 },
+		{ 0x158, 0x1 },	       { 0x37C, 0x00001063 }, { 0x380, 0x82A86030 },
+		{ 0x384, 0x2861408B }, { 0x388, 0x00130285 }, { 0x38C, 0x10630009 },
+		{ 0x394, 0x400B82A8 }, { 0x600, 0x16CC78C },  { 0x604, 0x3FFFFFE0 },
+		{ 0x608, 0xFEC },      { 0x154, 0x00000000 }, { 0x154, 0x80000000 },
+	};
+
+	ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus);
+	if (ret) {
+		printf("%s: No bus %d\n", __func__, i2c_bus);
+		return;
+	}
+	ret = dm_i2c_probe(bus, BX5_ID, 0, &bx5_dev);
+	if (ret) {
+		printf("%s: Can't find Bx5 device id=0x%x, on bus %d\n", __func__, BX5_ID, i2c_bus);
+		return;
+	} else {
+		printf("QuickLogic ArcticLink III Bx5 (0x%x) found\n", BX5_ID);
+	}
+
+	for (int i = 0; i < (sizeof(Vx_addr_data) / 8); i++) {
+		i2c_telegram[4] = (Vx_addr_data[i].addr) & 0xFF;
+		i2c_telegram[5] = (Vx_addr_data[i].addr >> 8) & 0xFF;
+		i2c_telegram[6] = (Vx_addr_data[i].data) & 0xFF;
+		i2c_telegram[7] = (Vx_addr_data[i].data >> 8) & 0xFF;
+		i2c_telegram[8] = (Vx_addr_data[i].data >> 16) & 0xFF;
+		i2c_telegram[9] = (Vx_addr_data[i].data >> 24) & 0xFF;
+
+		dm_i2c_write(bx5_dev, CONTROL_BYTE_GEN, i2c_telegram, sizeof(i2c_telegram));
+
+		if (((Vx_addr_data[i].addr == 0x154) && (Vx_addr_data[i].data == 0x80000000)) ||
+		    ((Vx_addr_data[i].addr == 0x158) && (Vx_addr_data[i].data == 0x00000001)))
+			udelay(1000);
+	}
+}
+
+struct sec_mipi_dsim {
+	void __iomem *base;
+	void __iomem *disp_mix_gpr_base;
+
+	/* kHz clocks */
+	uint64_t pix_clk;
+	uint64_t bit_clk;
+
+	unsigned int lanes;
+	unsigned int channel; /* virtual channel */
+	enum mipi_dsi_pixel_format format;
+	unsigned long mode_flags;
+	unsigned int pms;
+	unsigned int p;
+	unsigned int m;
+	unsigned int s;
+	struct fb_videomode vmode;
+
+	const struct sec_mipi_dsim_plat_data *pdata;
+
+	struct mipi_dsi_client_dev *dsi_panel_dev;
+	struct mipi_dsi_client_driver *dsi_panel_drv;
+};
+
+#ifndef CONFIG_IMX8MP
+static void disp_mix_dsim_soft_reset_release(struct sec_mipi_dsim *dsim, bool release)
+{
+	if (release)
+		/* release dsi blk reset */
+		setbits_le32(dsim->disp_mix_gpr_base + DISPLAY_MIX_SFT_RSTN_CSR,
+			     MIPI_DSI_I_PRESETn_SFT_EN);
+
+	else
+		clrbits_le32(dsim->disp_mix_gpr_base + DISPLAY_MIX_SFT_RSTN_CSR,
+			     MIPI_DSI_I_PRESETn_SFT_EN);
+}
+
+static void disp_mix_dsim_clks_enable(struct sec_mipi_dsim *dsim, bool enable)
+{
+	if (enable)
+		setbits_le32(dsim->disp_mix_gpr_base + DISPLAY_MIX_CLK_EN_CSR,
+			     MIPI_DSI_PCLK_SFT_EN | MIPI_DSI_CLKREF_SFT_EN);
+	else
+		clrbits_le32(dsim->disp_mix_gpr_base + DISPLAY_MIX_CLK_EN_CSR,
+			     MIPI_DSI_PCLK_SFT_EN | MIPI_DSI_CLKREF_SFT_EN);
+}
+
+static void disp_mix_dsim_lanes_reset(struct sec_mipi_dsim *dsim, bool reset)
+{
+	if (!reset)
+		/* release lanes reset */
+		setbits_le32(dsim->disp_mix_gpr_base + GPR_MIPI_RESET_DIV, GPR_MIPI_M_RESETN);
+	else
+		/* reset lanes */
+		clrbits_le32(dsim->disp_mix_gpr_base + GPR_MIPI_RESET_DIV, GPR_MIPI_M_RESETN);
+}
+#endif
+
+static void sec_mipi_dsim_wr_tx_header(struct sec_mipi_dsim *dsim, u8 di, u8 data0, u8 data1)
+{
+	unsigned int reg;
+
+	reg = (data1 << 16) | (data0 << 8) | ((di & 0x3f) << 0);
+	dsim_write(dsim, reg, DSIM_PKTHDR);
+}
+
+static void sec_mipi_dsim_wr_tx_data(struct sec_mipi_dsim *dsim, unsigned int tx_data)
+{
+	dsim_write(dsim, tx_data, DSIM_PAYLOAD);
+}
+
+static void sec_mipi_dsim_long_data_wr(struct sec_mipi_dsim *dsim, const unsigned char *data0,
+				       unsigned int data_size)
+{
+	unsigned int data_cnt = 0, payload = 0;
+
+	/* in case that data count is more then 4 */
+	for (data_cnt = 0; data_cnt < data_size; data_cnt += 4) {
+		/*
+		 * after sending 4 bytes per one time,
+		 * send remainder data less then 4.
+		 */
+		if ((data_size - data_cnt) < 4) {
+			if ((data_size - data_cnt) == 3) {
+				payload = data0[data_cnt] |
+					  data0[data_cnt + 1] << 8 |
+					  data0[data_cnt + 2] << 16;
+				debug("count = 3 payload = %x, %x %x %x\n", payload,
+				      data0[data_cnt], data0[data_cnt + 1], data0[data_cnt + 2]);
+			} else if ((data_size - data_cnt) == 2) {
+				payload = data0[data_cnt] |
+					  data0[data_cnt + 1] << 8;
+				debug("count = 2 payload = %x, %x %x\n", payload,
+				      data0[data_cnt], data0[data_cnt + 1]);
+			} else if ((data_size - data_cnt) == 1) {
+				payload = data0[data_cnt];
+			}
+
+			sec_mipi_dsim_wr_tx_data(dsim, payload);
+			/* send 4 bytes per one time. */
+		} else {
+			payload = data0[data_cnt] |
+				  data0[data_cnt + 1] << 8 |
+				  data0[data_cnt + 2] << 16 |
+				  data0[data_cnt + 3] << 24;
+
+			debug("count = 4 payload = %x, %x %x %x %x\n", payload, *(u8 *)(data0 + data_cnt),
+			      data0[data_cnt + 1], data0[data_cnt + 2], data0[data_cnt + 3]);
+
+			sec_mipi_dsim_wr_tx_data(dsim, payload);
+		}
+	}
+}
+
+static int sec_mipi_dsim_wait_for_pkt_done(struct sec_mipi_dsim *dsim, unsigned long timeout)
+{
+	uint32_t intsrc;
+
+	do {
+		intsrc = dsim_read(dsim, DSIM_INTSRC);
+		if (intsrc & INTSRC_SFRPLFIFOEMPTY) {
+			dsim_write(dsim, INTSRC_SFRPLFIFOEMPTY, DSIM_INTSRC);
+			return 0;
+		}
+
+		udelay(1);
+	} while (--timeout);
+
+	return -ETIMEDOUT;
+}
+
+static int sec_mipi_dsim_pkt_write(struct sec_mipi_dsim *dsim, u8 data_type, const u8 *buf, int len)
+{
+	int ret = 0;
+	const unsigned char *data = (const unsigned char *)buf;
+
+	if (len == 0)
+		/* handle generic short write command */
+		sec_mipi_dsim_wr_tx_header(dsim, data_type, data[0], data[1]);
+	else {
+		/* handle generic long write command */
+		sec_mipi_dsim_long_data_wr(dsim, data, len);
+		sec_mipi_dsim_wr_tx_header(dsim, data_type, len & 0xff, (len & 0xff00) >> 8);
+
+		ret = sec_mipi_dsim_wait_for_pkt_done(dsim, MIPI_FIFO_TIMEOUT);
+		if (ret) {
+			printf("wait tx done timeout!\n");
+			return -ETIMEDOUT;
+		}
+	}
+	mdelay(10);
+
+	return 0;
+}
+
+static int sec_mipi_dsim_wait_pll_stable(struct sec_mipi_dsim *dsim)
+{
+	uint32_t status;
+	ulong start;
+
+	start = get_timer(0); /* Get current timestamp */
+
+	do {
+		status = dsim_read(dsim, DSIM_STATUS);
+		if (status & STATUS_PLLSTABLE)
+			return 0;
+	} while (get_timer(0) < (start + 100)); /* Wait 100ms */
+
+	return -ETIMEDOUT;
+}
+
+static int sec_mipi_dsim_config_pll(struct sec_mipi_dsim *dsim)
+{
+	int ret;
+	uint32_t pllctrl = 0, status, data_lanes_en, stop;
+
+	dsim_write(dsim, 0x8000, DSIM_PLLTMR);
+
+	/* TODO: config dp/dn swap if requires */
+
+	pllctrl |= PLLCTRL_SET_PMS(dsim->pms) | PLLCTRL_PLLEN;
+	dsim_write(dsim, pllctrl, DSIM_PLLCTRL);
+
+	ret = sec_mipi_dsim_wait_pll_stable(dsim);
+	if (ret) {
+		printf("wait for pll stable time out\n");
+		return ret;
+	}
+
+	/* wait for clk & data lanes to go to stop state */
+	mdelay(1);
+
+	data_lanes_en = (0x1 << dsim->lanes) - 1;
+	status = dsim_read(dsim, DSIM_STATUS);
+	if (!(status & STATUS_STOPSTATECLK)) {
+		printf("clock is not in stop state\n");
+		return -EBUSY;
+	}
+
+	stop = STATUS_GET_STOPSTATEDAT(status);
+	if ((stop & data_lanes_en) != data_lanes_en) {
+		printf("one or more data lanes is not in stop state\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static void sec_mipi_dsim_set_main_mode(struct sec_mipi_dsim *dsim)
+{
+	uint32_t bpp, hfp_wc, hbp_wc, hsa_wc, wc;
+	uint32_t mdresol = 0, mvporch = 0, mhporch = 0, msync = 0;
+	struct fb_videomode *vmode = &dsim->vmode;
+
+	mdresol |= MDRESOL_SET_MAINVRESOL(vmode->yres) |
+		   MDRESOL_SET_MAINHRESOL(vmode->xres);
+	dsim_write(dsim, mdresol, DSIM_MDRESOL);
+
+	mvporch |= MVPORCH_SET_MAINVBP(vmode->upper_margin)    |
+		   MVPORCH_SET_STABLEVFP(vmode->lower_margin) |
+		   MVPORCH_SET_CMDALLOW(0x0);
+	dsim_write(dsim, mvporch, DSIM_MVPORCH);
+
+	bpp = mipi_dsi_pixel_format_to_bpp(dsim->format);
+
+	/* calculate hfp & hbp word counts */
+	if (dsim->dsi_panel_drv) {
+		/* Panel driver is registered, will work with panel */
+		wc = DIV_ROUND_UP(vmode->right_margin * (bpp >> 3),
+				  dsim->lanes);
+		hfp_wc = wc > MIPI_HFP_PKT_OVERHEAD ?
+			 wc - MIPI_HFP_PKT_OVERHEAD : vmode->right_margin;
+		wc = DIV_ROUND_UP(vmode->left_margin * (bpp >> 3),
+				  dsim->lanes);
+		hbp_wc = wc > MIPI_HBP_PKT_OVERHEAD ?
+			 wc - MIPI_HBP_PKT_OVERHEAD : vmode->left_margin;
+	} else {
+		hfp_wc = vmode->right_margin * (bpp >> 3) / dsim->lanes - 6;
+		hbp_wc = vmode->left_margin * (bpp >> 3) / dsim->lanes - 6;
+	}
+
+	mhporch |= MHPORCH_SET_MAINHFP(hfp_wc) |
+		   MHPORCH_SET_MAINHBP(hbp_wc);
+
+	dsim_write(dsim, mhporch, DSIM_MHPORCH);
+
+	/* calculate hsa word counts */
+	if (dsim->dsi_panel_drv) {
+		wc = DIV_ROUND_UP(vmode->hsync_len * (bpp >> 3),
+				  dsim->lanes);
+		hsa_wc = wc > MIPI_HSA_PKT_OVERHEAD ?
+			 wc - MIPI_HSA_PKT_OVERHEAD : vmode->hsync_len;
+	} else {
+		hsa_wc = vmode->hsync_len * (bpp >> 3) / dsim->lanes - 6;
+	}
+
+	msync |= MSYNC_SET_MAINVSA(vmode->vsync_len) |
+		 MSYNC_SET_MAINHSA(hsa_wc);
+
+	debug("hfp_wc %u hbp_wc %u hsa_wc %u\n", hfp_wc, hbp_wc, hsa_wc);
+
+	dsim_write(dsim, msync, DSIM_MSYNC);
+}
+
+static void sec_mipi_dsim_config_dpi(struct sec_mipi_dsim *dsim)
+{
+	uint32_t config = 0, rgb_status = 0, data_lanes_en;
+
+	if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO)
+		rgb_status &= ~RGB_STATUS_CMDMODE_INSEL;
+	else
+		rgb_status |= RGB_STATUS_CMDMODE_INSEL;
+
+	dsim_write(dsim, rgb_status, DSIM_RGB_STATUS);
+
+	if (dsim->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
+		config |= CONFIG_CLKLANE_STOP_START;
+
+	if (dsim->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH)
+		config |= CONFIG_MFLUSH_VS;
+
+	/* disable EoT packets in HS mode */
+	if (dsim->mode_flags & MIPI_DSI_MODE_EOT_PACKET)
+		config |= CONFIG_EOT_R03;
+
+	if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		config |= CONFIG_VIDEOMODE;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+			config |= CONFIG_BURSTMODE;
+
+		else if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+			config |= CONFIG_SYNCINFORM;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_AUTO_VERT)
+			config |= CONFIG_AUTOMODE;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HSE)
+			config |= CONFIG_HSEDISABLEMODE;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HFP)
+			config |= CONFIG_HFPDISABLEMODE;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HBP)
+			config |= CONFIG_HBPDISABLEMODE;
+
+		if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO_HSA)
+			config |= CONFIG_HSADISABLEMODE;
+	}
+
+	config |= CONFIG_SET_MAINVC(dsim->channel);
+
+	if (dsim->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		switch (dsim->format) {
+		case MIPI_DSI_FMT_RGB565:
+			config |= CONFIG_SET_MAINPIXFORMAT(0x4);
+			break;
+		case MIPI_DSI_FMT_RGB666_PACKED:
+			config |= CONFIG_SET_MAINPIXFORMAT(0x5);
+			break;
+		case MIPI_DSI_FMT_RGB666:
+			config |= CONFIG_SET_MAINPIXFORMAT(0x6);
+			break;
+		case MIPI_DSI_FMT_RGB888:
+			config |= CONFIG_SET_MAINPIXFORMAT(0x7);
+			break;
+		default:
+			config |= CONFIG_SET_MAINPIXFORMAT(0x7);
+			break;
+		}
+	}
+
+	/* config data lanes number and enable lanes */
+	data_lanes_en = (0x1 << dsim->lanes) - 1;
+	config |= CONFIG_SET_NUMOFDATLANE(dsim->lanes - 1);
+	config |= CONFIG_SET_LANEEN(0x1 | data_lanes_en << 1);
+
+	dsim_write(dsim, config, DSIM_CONFIG);
+
+	if (seco_fuse_GetModule() == SECO_FUSE_MODULE_TRIZEPS8MINI) {
+		if (seco_fuse_GetPCBrevision() > SECO_FUSE_PCBREV_V1R3) {
+			bx5_init();
+		}
+	}
+}
+
+static void sec_mipi_dsim_config_dphy(struct sec_mipi_dsim *dsim)
+{
+	uint32_t phytiming = 0, phytiming1 = 0, phytiming2 = 0, timeout = 0;
+	struct fb_videomode *vmode = &dsim->vmode;
+
+	/* TODO: add a PHY timing table arranged by the pll Fout */
+	if (vmode->pixclock == 6734) {
+		phytiming |= PHYTIMING_SET_M_TLPXCTL(6) |
+		             PHYTIMING_SET_M_THSEXITCTL(11);
+		dsim_write(dsim, phytiming, DSIM_PHYTIMING);
+
+		phytiming1 |= PHYTIMING1_SET_M_TCLKPRPRCTL(7)  |
+		              PHYTIMING1_SET_M_TCLKZEROCTL(38) |
+			      PHYTIMING1_SET_M_TCLKPOSTCTL(13) |
+			      PHYTIMING1_SET_M_TCLKTRAILCTL(8);
+		dsim_write(dsim, phytiming1, DSIM_PHYTIMING1);
+
+		phytiming2 |= PHYTIMING2_SET_M_THSPRPRCTL(8)  |
+		              PHYTIMING2_SET_M_THSZEROCTL(13) |
+			      PHYTIMING2_SET_M_THSTRAILCTL(11);
+		dsim_write(dsim, phytiming2, DSIM_PHYTIMING2);
+
+		timeout |= TIMEOUT_SET_BTAOUT(0xf) |
+		           TIMEOUT_SET_LPDRTOUT(0xf);
+		dsim_write(dsim, timeout, DSIM_TIMEOUT);
+	} else if (vmode->pixclock == 33300) {
+		dsim_write(dsim, 0x305, DSIM_PHYTIMING);
+		dsim_write(dsim, 0x3110904, DSIM_PHYTIMING1);
+		dsim_write(dsim, 0x30406, DSIM_PHYTIMING2);
+		dsim_write(dsim, 0xff00ff, DSIM_TIMEOUT);
+	} else if (vmode->pixclock == 16835) {
+		dsim_write(dsim, 0x204, DSIM_PHYTIMING);
+		dsim_write(dsim, 0x20f0903, DSIM_PHYTIMING1);
+		dsim_write(dsim, 0x30406, DSIM_PHYTIMING2);
+		dsim_write(dsim, 0xff00ff, DSIM_TIMEOUT);
+	} else if (vmode->pixclock == 24390) {
+		dsim_write(dsim, 0x103, DSIM_PHYTIMING);
+		dsim_write(dsim, 0x10a0802, DSIM_PHYTIMING1);
+		dsim_write(dsim, 0x20205, DSIM_PHYTIMING2);
+		dsim_write(dsim, 0xff00ff, DSIM_TIMEOUT);
+	} else {
+		printf("TODO: add config dphy calc \r\n");
+	}
+}
+
+static void sec_mipi_dsim_config_clkctrl(struct sec_mipi_dsim *dsim)
+{
+	uint32_t clkctrl = 0, data_lanes_en;
+	uint64_t byte_clk, esc_prescaler;
+
+	clkctrl |= CLKCTRL_TXREQUESTHSCLK;
+
+	/* using 1.5Gbps PHY */
+	clkctrl |= CLKCTRL_DPHY_SEL_1P5G;
+
+	clkctrl |= CLKCTRL_ESCCLKEN;
+
+	clkctrl &= ~CLKCTRL_PLLBYPASS;
+
+	clkctrl |= CLKCTRL_BYTECLKSRC_DPHY_PLL;
+
+	clkctrl |= CLKCTRL_BYTECLKEN;
+
+	data_lanes_en = (0x1 << dsim->lanes) - 1;
+	clkctrl |= CLKCTRL_SET_LANEESCCLKEN(0x1 | data_lanes_en << 1);
+
+	/* calculate esc prescaler from byte clock:
+	 * EscClk = ByteClk / EscPrescaler;
+	 */
+	byte_clk = dsim->bit_clk >> 3;
+	esc_prescaler = DIV_ROUND_UP_ULL(byte_clk, MAX_ESC_CLK_FREQ);
+
+	clkctrl |= CLKCTRL_SET_ESCPRESCALER(esc_prescaler);
+
+	dsim_write(dsim, clkctrl, DSIM_CLKCTRL);
+}
+
+static void sec_mipi_dsim_set_standby(struct sec_mipi_dsim *dsim, bool standby)
+{
+	uint32_t mdresol = 0;
+
+	mdresol = dsim_read(dsim, DSIM_MDRESOL);
+
+	if (standby)
+		mdresol |= MDRESOL_MAINSTANDBY;
+	else
+		mdresol &= ~MDRESOL_MAINSTANDBY;
+
+	dsim_write(dsim, mdresol, DSIM_MDRESOL);
+}
+
+static void sec_mipi_dsim_disable_clkctrl(struct sec_mipi_dsim *dsim)
+{
+	uint32_t clkctrl;
+
+	clkctrl = dsim_read(dsim, DSIM_CLKCTRL);
+
+	clkctrl &= ~CLKCTRL_TXREQUESTHSCLK;
+
+	clkctrl &= ~CLKCTRL_ESCCLKEN;
+
+	clkctrl &= ~CLKCTRL_BYTECLKEN;
+
+	dsim_write(dsim, clkctrl, DSIM_CLKCTRL);
+}
+
+static void sec_mipi_dsim_disable_pll(struct sec_mipi_dsim *dsim)
+{
+	uint32_t pllctrl;
+
+	pllctrl = dsim_read(dsim, DSIM_PLLCTRL);
+
+	pllctrl &= ~PLLCTRL_PLLEN;
+
+	dsim_write(dsim, pllctrl, DSIM_PLLCTRL);
+}
+
+/* For now, dsim only support one device attached */
+static int sec_mipi_dsim_bridge_attach(struct mipi_dsi_bridge_driver *bridge_driver,
+				       struct mipi_dsi_client_dev *dsi_dev)
+{
+	struct sec_mipi_dsim *dsim_host = (struct sec_mipi_dsim *)bridge_driver->driver_private;
+
+	if (!dsi_dev->lanes || dsi_dev->lanes > dsim_host->pdata->max_data_lanes) {
+		printf("invalid data lanes number\n");
+		return -EINVAL;
+	}
+
+	if (!(dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO) ||
+	    !((dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) ||
+	      (dsi_dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))) {
+		printf("unsupported dsi mode\n");
+		return -EINVAL;
+	}
+
+	if (dsi_dev->format != MIPI_DSI_FMT_RGB888 &&
+	    dsi_dev->format != MIPI_DSI_FMT_RGB565 &&
+	    dsi_dev->format != MIPI_DSI_FMT_RGB666 &&
+	    dsi_dev->format != MIPI_DSI_FMT_RGB666_PACKED) {
+		printf("unsupported pixel format: %#x\n", dsi_dev->format);
+		return -EINVAL;
+	}
+
+	if (!dsi_dev->name) {
+		printf("panel_device name is NULL.\n");
+		return -EFAULT;
+	}
+
+	if (dsim_host->dsi_panel_drv) {
+		if (strcmp(dsi_dev->name, dsim_host->dsi_panel_drv->name)) {
+			printf("The panel device name %s is not for LCD driver %s\n",
+			       dsi_dev->name, dsim_host->dsi_panel_drv->name);
+			return -EFAULT;
+		}
+	}
+
+	dsim_host->dsi_panel_dev = dsi_dev;
+
+	dsim_host->lanes = dsi_dev->lanes;
+	dsim_host->channel = dsi_dev->channel;
+	dsim_host->format = dsi_dev->format;
+	dsim_host->mode_flags = dsi_dev->mode_flags;
+
+	return 0;
+}
+
+static int sec_mipi_dsim_bridge_enable(struct mipi_dsi_bridge_driver *bridge_driver)
+{
+	int ret;
+	struct sec_mipi_dsim *dsim_host = (struct sec_mipi_dsim *)bridge_driver->driver_private;
+
+	/* At this moment, the dsim bridge's preceding encoder has
+	 * already been enabled. So the dsim can be configed here
+	 */
+
+	/* config main display mode */
+	sec_mipi_dsim_set_main_mode(dsim_host);
+
+	/* config dsim dpi */
+	sec_mipi_dsim_config_dpi(dsim_host);
+
+	/* config dsim pll */
+	ret = sec_mipi_dsim_config_pll(dsim_host);
+	if (ret) {
+		printf("dsim pll config failed: %d\n", ret);
+		return ret;
+	}
+
+	/* config dphy timings */
+	sec_mipi_dsim_config_dphy(dsim_host);
+
+	/* config esc clock, byte clock and etc */
+	sec_mipi_dsim_config_clkctrl(dsim_host);
+
+	/* enable data transfer of dsim */
+	sec_mipi_dsim_set_standby(dsim_host, true);
+
+	/* Call panel driver's setup */
+	if (dsim_host->dsi_panel_drv && dsim_host->dsi_panel_drv->dsi_client_setup) {
+		ret = dsim_host->dsi_panel_drv->dsi_client_setup(dsim_host->dsi_panel_dev);
+		if (ret < 0) {
+			printf("failed to init mipi lcd.\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int sec_mipi_dsim_bridge_disable(struct mipi_dsi_bridge_driver *bridge_driver)
+{
+	uint32_t intsrc;
+	struct sec_mipi_dsim *dsim_host = (struct sec_mipi_dsim *)bridge_driver->driver_private;
+
+	/* disable data transfer of dsim */
+	sec_mipi_dsim_set_standby(dsim_host, false);
+
+	/* disable esc clock & byte clock */
+	sec_mipi_dsim_disable_clkctrl(dsim_host);
+
+	/* disable dsim pll */
+	sec_mipi_dsim_disable_pll(dsim_host);
+
+	/* Clear all intsrc */
+	intsrc = dsim_read(dsim_host, DSIM_INTSRC);
+	dsim_write(dsim_host, intsrc, DSIM_INTSRC);
+
+	return 0;
+}
+
+static int sec_mipi_dsim_bridge_mode_set(struct mipi_dsi_bridge_driver *bridge_driver,
+					 struct fb_videomode *fbmode)
+{
+	int bpp;
+	uint64_t pix_clk, bit_clk;
+	struct sec_mipi_dsim *dsim_host = (struct sec_mipi_dsim *)bridge_driver->driver_private;
+
+	dsim_host->vmode = *fbmode;
+
+	bpp = mipi_dsi_pixel_format_to_bpp(dsim_host->format);
+	if (bpp < 0)
+		return -EINVAL;
+
+	pix_clk = PS2KHZ(fbmode->pixclock) * 1000;
+	bit_clk = DIV_ROUND_UP_ULL(pix_clk * bpp, dsim_host->lanes);
+
+	if (bit_clk > dsim_host->pdata->max_data_rate) {
+		printf("request bit clk freq exceeds lane's maximum value\n");
+		return -EINVAL;
+	}
+
+	dsim_host->pix_clk = DIV_ROUND_UP_ULL(pix_clk, 1000);
+	dsim_host->bit_clk = DIV_ROUND_UP_ULL(bit_clk, 1000);
+
+	if (dsim_host->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
+		/* TODO: add PMS calculate and check
+		 * Only support '1080p@60Hz' for now,
+		 * add other modes support later
+		 */
+		if (fbmode->pixclock == 6734)
+			dsim_host->pms = 0x4210;
+		else if (fbmode->pixclock == 33300)
+			dsim_host->pms = 0xA942;
+		else if (fbmode->pixclock == 16835)
+			dsim_host->pms = 0xA842;
+		else if (fbmode->pixclock == 24390)
+			dsim_host->pms = 0x13483;
+	}
+
+	debug("%s: bitclk %llu pixclk %llu\n", __func__, dsim_host->bit_clk, dsim_host->pix_clk);
+
+	return 0;
+}
+
+/* Add a LCD panel driver, will search the panel device to bind with them */
+int sec_mipi_dsim_bridge_add_client_driver(struct mipi_dsi_bridge_driver *bridge_driver,
+					   struct mipi_dsi_client_driver *panel_drv)
+{
+	struct sec_mipi_dsim *dsim_host = (struct sec_mipi_dsim *)bridge_driver->driver_private;
+
+	if (!panel_drv) {
+		printf("mipi_dsi_northwest_panel_driver is NULL.\n");
+		return -EFAULT;
+	}
+
+	if (!panel_drv->name) {
+		printf("mipi_dsi_northwest_panel_driver name is NULL.\n");
+		return -EFAULT;
+	}
+
+	if (dsim_host->dsi_panel_dev) {
+		if (strcmp(panel_drv->name, dsim_host->dsi_panel_dev->name)) {
+			printf("The panel driver name %s is not for LCD device %s\n",
+			       panel_drv->name, dsim_host->dsi_panel_dev->name);
+			return -EFAULT;
+		}
+	}
+
+	dsim_host->dsi_panel_drv = panel_drv;
+
+	return 0;
+}
+
+static int sec_mipi_dsim_bridge_pkt_write(struct mipi_dsi_bridge_driver *bridge_driver,
+					  u8 data_type, const u8 *buf, int len)
+{
+	struct sec_mipi_dsim *dsim_host = (struct sec_mipi_dsim *)bridge_driver->driver_private;
+
+#ifdef DEBUG
+	int i = 0;
+	printf("sec_mipi_dsim_bridge_pkt_write, data_type %u, len %d buf: \n", data_type, len);
+
+	if (len == 0)
+		len = 2;
+
+	for (i; i < len; i++) {
+		printf("0x%.2x ", buf[i]);
+	}
+	printf("\n");
+#endif
+
+	return sec_mipi_dsim_pkt_write(dsim_host, data_type, buf, len);
+}
+
+struct mipi_dsi_bridge_driver imx_sec_dsim_driver = {
+	.attach = sec_mipi_dsim_bridge_attach,
+	.enable = sec_mipi_dsim_bridge_enable,
+	.disable = sec_mipi_dsim_bridge_disable,
+	.mode_set = sec_mipi_dsim_bridge_mode_set,
+	.pkt_write = sec_mipi_dsim_bridge_pkt_write,
+	.add_client_driver = sec_mipi_dsim_bridge_add_client_driver,
+	.name = DRIVER_NAME,
+};
+
+int sec_mipi_dsim_setup(const struct sec_mipi_dsim_plat_data *plat_data)
+{
+	struct sec_mipi_dsim *dsim_host;
+
+	if (!plat_data) {
+		printf("Invalid platform data \n");
+		return -EINVAL;
+	}
+
+	dsim_host = (struct sec_mipi_dsim *)malloc(sizeof(struct sec_mipi_dsim));
+	if (!dsim_host) {
+		printf("failed to allocate sec_mipi_dsim object.\n");
+		return -ENOMEM;
+	}
+
+	dsim_host->base = (void __iomem *)plat_data->reg_base;
+	dsim_host->disp_mix_gpr_base = (void __iomem *)plat_data->gpr_base;
+	dsim_host->pdata = plat_data;
+	dsim_host->dsi_panel_drv = NULL;
+	dsim_host->dsi_panel_dev = NULL;
+
+#ifndef CONFIG_IMX8MP
+	/* Pull dsim out of reset */
+	disp_mix_dsim_soft_reset_release(dsim_host, true);
+	disp_mix_dsim_clks_enable(dsim_host, true);
+	disp_mix_dsim_lanes_reset(dsim_host, false);
+#endif
+
+	imx_sec_dsim_driver.driver_private = dsim_host;
+	return imx_mipi_dsi_bridge_register_driver(&imx_sec_dsim_driver);
+}
diff --git a/include/configs/seco_imx8mm_myon2.h b/include/configs/seco_imx8mm_myon2.h
index e8cb87cbe4bd52b8ac2d4dd4be6cdffd5c419b9f..c8a08f8ba5808042a3f7bbe7c166ff7b5fd5f27d 100644
--- a/include/configs/seco_imx8mm_myon2.h
+++ b/include/configs/seco_imx8mm_myon2.h
@@ -223,17 +223,20 @@
 
 #define CONFIG_MXC_USB_PORTSC  (PORT_PTS_UTMI | PORT_PTS_PTW)
 
-#ifdef CONFIG_DM_VIDEO
+#ifdef CONFIG_VIDEO
 #define CONFIG_VIDEO_MXS
 #define CONFIG_VIDEO_LOGO
 #define CONFIG_SPLASH_SCREEN
 #define CONFIG_SPLASH_SCREEN_ALIGN
+#define CONFIG_SPLASH_SOURCE
 #define CONFIG_CMD_BMP
 #define CONFIG_BMP_16BPP
 #define CONFIG_BMP_24BPP
 #define CONFIG_BMP_32BPP
 #define CONFIG_VIDEO_BMP_RLE8
 #define CONFIG_VIDEO_BMP_LOGO
+#define CONFIG_IMX_VIDEO_SKIP
+#define SPLASHIMAGE_ADDR		0x50000000
 #endif
 
 /* ____________________________________________________________________________
diff --git a/include/imx_mipi_dsi_bridge.h b/include/imx_mipi_dsi_bridge.h
new file mode 100644
index 0000000000000000000000000000000000000000..c03cef4bd7ec2580a0715a9079eb0ec591005b18
--- /dev/null
+++ b/include/imx_mipi_dsi_bridge.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2018 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __IMX_MIPI_DSIM_BRIDGE_H__
+#define __IMX_MIPI_DSIM_BRIDGE_H__
+
+#include <linux/fb.h>
+
+/* video mode */
+#define MIPI_DSI_MODE_VIDEO		BIT(0)
+/* video burst mode */
+#define MIPI_DSI_MODE_VIDEO_BURST	BIT(1)
+/* video pulse mode */
+#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE	BIT(2)
+/* enable auto vertical count mode */
+#define MIPI_DSI_MODE_VIDEO_AUTO_VERT	BIT(3)
+/* enable hsync-end packets in vsync-pulse and v-porch area */
+#define MIPI_DSI_MODE_VIDEO_HSE		BIT(4)
+/* disable hfront-porch area */
+#define MIPI_DSI_MODE_VIDEO_HFP		BIT(5)
+/* disable hback-porch area */
+#define MIPI_DSI_MODE_VIDEO_HBP		BIT(6)
+/* disable hsync-active area */
+#define MIPI_DSI_MODE_VIDEO_HSA		BIT(7)
+/* flush display FIFO on vsync pulse */
+#define MIPI_DSI_MODE_VSYNC_FLUSH	BIT(8)
+/* disable EoT packets in HS mode */
+#define MIPI_DSI_MODE_EOT_PACKET	BIT(9)
+/* device supports non-continuous clock behavior (DSI spec 5.6.1) */
+#define MIPI_DSI_CLOCK_NON_CONTINUOUS	BIT(10)
+/* transmit data in low power */
+#define MIPI_DSI_MODE_LPM		BIT(11)
+
+#define DSI_CMD_BUF_MAXSIZE		(128)
+
+enum mipi_dsi_pixel_format {
+	MIPI_DSI_FMT_RGB888,
+	MIPI_DSI_FMT_RGB666,
+	MIPI_DSI_FMT_RGB666_PACKED,
+	MIPI_DSI_FMT_RGB565,
+};
+
+struct mipi_dsi_client_dev {
+	unsigned int channel;
+	unsigned int lanes;
+	enum mipi_dsi_pixel_format format;
+	unsigned long mode_flags;
+	const char *name;
+};
+
+struct mipi_dsi_client_driver {
+	int (*dsi_client_setup)(struct mipi_dsi_client_dev *panel_dev);
+	const char *name;
+};
+
+struct mipi_dsi_bridge_driver {
+	int (*attach)(struct mipi_dsi_bridge_driver *bridge_driver,
+		      struct mipi_dsi_client_dev *dsi_dev);
+	int (*enable)(struct mipi_dsi_bridge_driver *bridge_driver);
+	int (*disable)(struct mipi_dsi_bridge_driver *bridge_driver);
+	int (*mode_set)(struct mipi_dsi_bridge_driver *bridge_driver, struct fb_videomode *pvmode);
+	int (*pkt_write)(struct mipi_dsi_bridge_driver *bridge_driver, u8 data_type, const u8 *buf,
+			 int len);
+	int (*add_client_driver)(struct mipi_dsi_bridge_driver *bridge_driver,
+				 struct mipi_dsi_client_driver *client_driver);
+	const char *name;
+	void *driver_private;
+};
+
+static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
+{
+	switch (fmt) {
+	case MIPI_DSI_FMT_RGB888:
+	case MIPI_DSI_FMT_RGB666:
+		return 24;
+
+	case MIPI_DSI_FMT_RGB666_PACKED:
+		return 18;
+
+	case MIPI_DSI_FMT_RGB565:
+		return 16;
+	}
+
+	return -EINVAL;
+}
+
+int imx_mipi_dsi_bridge_attach(struct mipi_dsi_client_dev *dsi_dev);
+int imx_mipi_dsi_bridge_mode_set(struct fb_videomode *pvmode);
+int imx_mipi_dsi_bridge_enable(void);
+int imx_mipi_dsi_bridge_disable(void);
+int imx_mipi_dsi_bridge_pkt_write(u8 data_type, const u8 *buf, int len);
+int imx_mipi_dsi_bridge_add_client_driver(struct mipi_dsi_client_driver *client_driver);
+int imx_mipi_dsi_bridge_register_driver(struct mipi_dsi_bridge_driver *driver);
+
+#endif /* __IMX_MIPI_DSIM_BRIDGE_H__ */
diff --git a/include/sec_mipi_dsim.h b/include/sec_mipi_dsim.h
new file mode 100644
index 0000000000000000000000000000000000000000..3716fa5ce99d1473b61cc245c899b014c97b7b4f
--- /dev/null
+++ b/include/sec_mipi_dsim.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2018 NXP
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __SEC_MIPI_DSIM_H__
+#define __SEC_MIPI_DSIM_H__
+
+struct sec_mipi_dsim_plat_data {
+	uint32_t version;
+	uint32_t max_data_lanes;
+	uint64_t max_data_rate;
+	ulong reg_base;
+	ulong gpr_base;
+};
+
+int sec_mipi_dsim_setup(const struct sec_mipi_dsim_plat_data *plat_data);
+
+#endif /* __SEC_MIPI_DSIM_H__ */