diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 593e9a4..d711bf1 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -134,4 +134,20 @@ config DRM_ITE_IT6263
 	---help---
 	  ITE IT6263 bridge chip driver.
 
+config DRM_TI_SN65DSI84
+	tristate "SN65DSI84 DSI to LVDS bridge (old)"
+	select REGMAP_I2C
+	select DRM_MIPI_DSI
+	---help---
+	  Support for the Texas Intruments SN65DSI84 bridge.
+
+config DRM_TI_SN65DSI83
+	tristate "SN65DSI83/4 DSI to LVDS bridge (suggested)"
+	select REGMAP_I2C
+	select DRM_MIPI_DSI
+	---help---
+	  Support for the Texas Intruments SN65DSI84 and SN65DSI83 bridges.
+
+source "drivers/gpu/drm/bridge/sn65dsi83/Kconfig"
+
 endmenu
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index d684dce..9ddbb4c 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -16,3 +16,5 @@ obj-$(CONFIG_DRM_ITE_IT6263) += it6263.o
 obj-$(CONFIG_DRM_NWL_DSI) += nwl-dsi.o
 obj-$(CONFIG_DRM_SEC_MIPI_DSIM) += sec-dsim.o
 obj-$(CONFIG_DRM_NXP_SEIKO_43WVFIG) += nxp-seiko-43wvfig.o
+obj-$(CONFIG_DRM_TI_SN65DSI83) += sn65dsi83.o
+obj-$(CONFIG_DRM_I2C_SN65DSI83) += sn65dsi83/
diff --git a/drivers/gpu/drm/bridge/sec-dsim.c b/drivers/gpu/drm/bridge/sec-dsim.c
index 0fa4e09..175d4ce 100644
--- a/drivers/gpu/drm/bridge/sec-dsim.c
+++ b/drivers/gpu/drm/bridge/sec-dsim.c
@@ -495,14 +495,14 @@ static int sec_mipi_dsim_host_attach(struct mipi_dsi_host *host,
 
 	if (dsim->channel)
 		return -EINVAL;
-
+/*
 	if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)		||
 	    !((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)	||
 	      (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))) {
 		dev_err(dev, "unsupported dsi mode\n");
 		return -EINVAL;
 	}
-
+*/
 	if (dsi->format != MIPI_DSI_FMT_RGB888 &&
 	    dsi->format != MIPI_DSI_FMT_RGB565 &&
 	    dsi->format != MIPI_DSI_FMT_RGB666 &&
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/Kconfig b/drivers/gpu/drm/bridge/sn65dsi83/Kconfig
new file mode 100644
index 0000000..1d8f37f
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/Kconfig
@@ -0,0 +1,7 @@
+config DRM_I2C_SN65DSI83
+	bool "SN65DSI83 mipi dsi to lvds bridge"
+	depends on OF
+	select DRM_MIPI_DSI
+	default y
+	help
+	  Support for the sn65dsi83 MIPI DSI to LVDS bridge
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/Makefile b/drivers/gpu/drm/bridge/sn65dsi83/Makefile
new file mode 100644
index 0000000..dee7f49
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/Makefile
@@ -0,0 +1,2 @@
+sn65dsi83-objs := sn65dsi83_drv.o sn65dsi83_brg.o
+obj-$(CONFIG_DRM_I2C_SN65DSI83) := sn65dsi83.o
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.c b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.c
new file mode 100755
index 0000000..41580c5
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2018 CopuLab Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/slab.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_connector.h>
+#include <video/mipi_display.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include "sn65dsi83_brg.h"
+
+/* Register addresses */
+
+#define SN65DSI83_SOFT_RESET         0x09
+#define SN65DSI83_CORE_PLL           0x0A
+    #define LVDS_CLK_RANGE_SHIFT    1
+    #define HS_CLK_SRC_SHIFT        0
+
+#define SN65DSI83_PLL_DIV            0x0B
+    #define DSI_CLK_DIV_SHIFT       3
+
+#define SN65DSI83_PLL_EN             0x0D
+#define SN65DSI83_DSI_CFG            0x10
+    #define CHA_DSI_LANES_SHIFT    3
+
+#define SN65DSI83_DSI_EQ              0x11
+#define SN65DSI83_CHA_DSI_CLK_RNG     0x12
+#define SN65DSI83_CHB_DSI_CLK_RNG     0x13
+#define SN65DSI83_LVDS_MODE           0x18
+    #define DE_NEG_POLARITY_SHIFT 7
+    #define HS_NEG_POLARITY_SHIFT 6
+    #define VS_NEG_POLARITY_SHIFT 5
+    #define LVDS_LINK_CFG_SHIFT   4
+    #define CHA_24BPP_MODE_SHIFT  3
+    #define CHA_24BPP_FMT1_SHIFT  1
+
+#define SN65DSI83_LVDS_SIGN           0x19
+#define SN65DSI83_LVDS_TERM           0x1A
+#define SN65DSI83_LVDS_CM_ADJ         0x1B
+#define SN65DSI83_CHA_LINE_LEN_LO     0x20
+#define SN65DSI83_CHA_LINE_LEN_HI     0x21
+#define SN65DSI83_CHB_LINE_LEN_LO     0x22
+#define SN65DSI83_CHB_LINE_LEN_HI     0x23
+#define SN65DSI83_CHA_VERT_LINES_LO   0x24
+#define SN65DSI83_CHA_VERT_LINES_HI   0x25
+#define SN65DSI83_CHB_VERT_LINES_LO   0x26
+#define SN65DSI83_CHB_VERT_LINES_HI   0x27
+#define SN65DSI83_CHA_SYNC_DELAY_LO   0x28
+#define SN65DSI83_CHA_SYNC_DELAY_HI   0x29
+#define SN65DSI83_CHB_SYNC_DELAY_LO   0x2A
+#define SN65DSI83_CHB_SYNC_DELAY_HI   0x2B
+#define SN65DSI83_CHA_HSYNC_WIDTH_LO  0x2C
+#define SN65DSI83_CHA_HSYNC_WIDTH_HI  0x2D
+#define SN65DSI83_CHB_HSYNC_WIDTH_LO  0x2E
+#define SN65DSI83_CHB_HSYNC_WIDTH_HI  0x2F
+#define SN65DSI83_CHA_VSYNC_WIDTH_LO  0x30
+#define SN65DSI83_CHA_VSYNC_WIDTH_HI  0x31
+#define SN65DSI83_CHB_VSYNC_WIDTH_LO  0x32
+#define SN65DSI83_CHB_VSYNC_WIDTH_HI  0x33
+#define SN65DSI83_CHA_HORZ_BACKPORCH  0x34
+#define SN65DSI83_CHB_HORZ_BACKPORCH  0x35
+#define SN65DSI83_CHA_VERT_BACKPORCH  0x36
+#define SN65DSI83_CHB_VERT_BACKPORCH  0x37
+#define SN65DSI83_CHA_HORZ_FRONTPORCH 0x38
+#define SN65DSI83_CHB_HORZ_FRONTPORCH 0x39
+#define SN65DSI83_CHA_VERT_FRONTPORCH 0x3A
+#define SN65DSI83_CHB_VERT_FRONTPORCH 0x3B
+#define SN65DSI83_CHA_ERR             0xE5
+#define SN65DSI83_TEST_PATTERN        0x3C
+#define SN65DSI83_REG_3D              0x3D
+#define SN65DSI83_REG_3E              0x3E
+
+static int sn65dsi83_brg_power_on(struct sn65dsi83_brg *brg)
+{
+    dev_info(&brg->client->dev,"%s\n",__func__);
+    gpiod_set_value_cansleep(brg->gpio_enable, 1);
+    /* Wait for 1ms for the internal voltage regulator to stabilize */
+    msleep(1);
+
+    return 0;
+}
+
+static void sn65dsi83_brg_power_off(struct sn65dsi83_brg *brg)
+{
+    dev_info(&brg->client->dev,"%s\n",__func__);
+    gpiod_set_value_cansleep(brg->gpio_enable, 0);
+    /*
+     * The EN pin must be held low for at least 10 ms
+     * before being asserted high
+     */
+    msleep(10);
+}
+
+static int sn65dsi83_write(struct i2c_client *client, u8 reg, u8 val)
+{
+    int ret;
+
+    ret = i2c_smbus_write_byte_data(client, reg, val);
+
+    if (ret)
+        dev_err(&client->dev, "failed to write at 0x%02x", reg);
+
+    dev_dbg(&client->dev, "%s: write reg 0x%02x data 0x%02x", __func__, reg, val);
+
+    return ret;
+}
+#define SN65DSI83_WRITE(reg,val) sn65dsi83_write(client, (reg) , (val))
+
+static int sn65dsi83_read(struct i2c_client *client, u8 reg)
+{
+    int ret;
+
+    dev_info(&client->dev, "client 0x%p", client);
+    ret = i2c_smbus_read_byte_data(client, reg);
+
+    if (ret < 0) {
+        dev_err(&client->dev, "failed reading at 0x%02x", reg);
+        return ret;
+    }
+
+    dev_dbg(&client->dev, "%s: read reg 0x%02x data 0x%02x", __func__, reg, ret);
+
+    return ret;
+}
+#define SN65DSI83_READ(reg) sn65dsi83_read(client, (reg))
+
+static int sn65dsi83_brg_start_stream(struct sn65dsi83_brg *brg)
+{
+    int regval;
+    struct i2c_client *client = I2C_CLIENT(brg);
+
+    dev_info(&client->dev,"%s\n",__func__);
+    /* Set the PLL_EN bit (CSR 0x0D.0) */
+    SN65DSI83_WRITE(SN65DSI83_PLL_EN, 0x1);
+    /* Wait for the PLL_LOCK bit to be set (CSR 0x0A.7) */
+    msleep(200);
+
+    /* Perform SW reset to apply changes */
+    SN65DSI83_WRITE(SN65DSI83_SOFT_RESET, 0x01);
+
+    /* Read CHA Error register */
+    regval = SN65DSI83_READ(SN65DSI83_CHA_ERR);
+    dev_info(&client->dev, "CHA (0x%02x) = 0x%02x",
+         SN65DSI83_CHA_ERR, regval);
+
+	SN65DSI83_WRITE(SN65DSI83_CHA_ERR, 0xff);
+    regval = SN65DSI83_READ(SN65DSI83_CHA_ERR);
+    dev_info(&client->dev, "CHA (0x%02x) = 0x%02x",
+         SN65DSI83_CHA_ERR, regval);
+    msleep(10);
+
+    regval = SN65DSI83_READ(SN65DSI83_CHA_ERR);
+    dev_info(&client->dev, "CHA (0x%02x) = 0x%02x",
+         SN65DSI83_CHA_ERR, regval);
+
+    return 0;
+}
+
+static void sn65dsi83_brg_stop_stream(struct sn65dsi83_brg *brg)
+{
+    struct i2c_client *client = I2C_CLIENT(brg);
+    dev_info(&client->dev,"%s\n",__func__);
+    /* Clear the PLL_EN bit (CSR 0x0D.0) */
+    SN65DSI83_WRITE(SN65DSI83_PLL_EN, 0x00);
+}
+
+static int sn65dsi83_calk_clk_range(int min_regval, int max_regval,
+                unsigned long min_clk, unsigned long inc,
+                unsigned long target_clk)
+{
+    int regval = min_regval;
+    unsigned long clk = min_clk;
+
+    while (regval <= max_regval) {
+        if ((clk <= target_clk) && (target_clk < (clk + inc)))
+            return regval;
+
+        regval++;
+        clk += inc;
+    }
+
+    return -1;
+}
+
+#define ABS(X) ((X) < 0 ? (-1 * (X)) : (X))
+static int sn65dsi83_calk_div(int min_regval, int max_regval, int min_div,
+                int inc, unsigned long source_clk,
+                unsigned long target_clk)
+{
+    int regval = min_regval;
+    int div = min_div;
+    unsigned long curr_delta;
+    unsigned long prev_delta = ABS(DIV_ROUND_UP(source_clk, div) -
+                    target_clk);
+
+    while (regval <= max_regval) {
+        curr_delta = ABS(DIV_ROUND_UP(source_clk, div) - target_clk);
+        if (curr_delta > prev_delta)
+            return --regval;
+
+        regval++;
+        div += inc;
+    }
+
+    return -1;
+}
+
+static int sn65dsi83_brg_configure(struct sn65dsi83_brg *brg)
+{
+    int regval = 0;
+    struct i2c_client *client = I2C_CLIENT(brg);
+    struct videomode *vm = VM(brg);
+
+    u32 dsi_clk = (((PIXCLK * BPP(brg)) / DSI_LANES(brg)) >> 1);
+
+    dev_info(&client->dev, "DSI clock [ %u ] Hz\n",dsi_clk);
+    dev_info(&client->dev, "GeoMetry [ %d x %d ] Hz\n",HACTIVE,VACTIVE);
+
+    /* Reset PLL_EN and SOFT_RESET registers */
+	SN65DSI83_WRITE(SN65DSI83_SOFT_RESET,0x00);
+	SN65DSI83_WRITE(SN65DSI83_PLL_EN,0x00);
+	
+#if 0  /* disabled */
+
+    /* LVDS clock setup */
+    if  ((25000000 <= PIXCLK) && (PIXCLK < 37500000))
+        regval = 0;
+    else
+        regval = sn65dsi83_calk_clk_range(0x01, 0x05, 37500000, 25000000,
+                    PIXCLK);
+
+    if (regval < 0) {
+        dev_err(&client->dev, "failed to configure LVDS clock");
+        return -EINVAL;
+    }
+
+    regval = (regval << LVDS_CLK_RANGE_SHIFT);
+    regval |= (1 << HS_CLK_SRC_SHIFT); /* Use DSI clock */
+    SN65DSI83_WRITE(SN65DSI83_CORE_PLL,regval);
+
+    /* DSI clock range */
+    regval = sn65dsi83_calk_clk_range(0x08, 0x64, 40000000, 5000000, dsi_clk);
+    if (regval < 0) {
+        dev_err(&client->dev, "failed to configure DSI clock range\n");
+        return -EINVAL;
+    }
+    SN65DSI83_WRITE(SN65DSI83_CHA_DSI_CLK_RNG,regval);
+
+    /* DSI clock divider */
+    regval = sn65dsi83_calk_div(0x0, 0x18, 1, 1, dsi_clk, PIXCLK);
+    if (regval < 0) {
+        dev_err(&client->dev, "failed to calculate DSI clock divider");
+        return -EINVAL;
+    }
+    regval = regval << DSI_CLK_DIV_SHIFT;
+    SN65DSI83_WRITE(SN65DSI83_PLL_DIV,regval);
+    /* Configure DSI_LANES  */
+    regval = SN65DSI83_READ(SN65DSI83_DSI_CFG);
+    regval &= ~(3 << CHA_DSI_LANES_SHIFT);
+    regval |= ((4 - DSI_LANES(brg)) << CHA_DSI_LANES_SHIFT);
+	printk("DSI lanes = %d.... val = 0x%x\n", (int)DSI_LANES(brg), regval);
+    SN65DSI83_WRITE(SN65DSI83_DSI_CFG,regval);
+    /* CHA_DSI_DATA_EQ - No Equalization */
+    /* CHA_DSI_CLK_EQ  - No Equalization */
+    SN65DSI83_WRITE(SN65DSI83_DSI_EQ,0x00);
+    /* Video formats */
+    regval = 0;
+    if (FLAGS & DISPLAY_FLAGS_HSYNC_LOW)
+        regval |= (1 << HS_NEG_POLARITY_SHIFT);
+
+    if (FLAGS & DISPLAY_FLAGS_VSYNC_LOW)
+        regval |= (1 << VS_NEG_POLARITY_SHIFT);
+
+    if (BPP(brg) == 24)
+        regval |= (1 << CHA_24BPP_MODE_SHIFT);
+
+    if (FORMAT(brg) == 1)
+        regval |= (1 << CHA_24BPP_FMT1_SHIFT);
+
+    regval |= (1 << LVDS_LINK_CFG_SHIFT);
+	printk("SN65DSI83_LVDS_MODE = 0x%x\n", regval);
+    SN65DSI83_WRITE(SN65DSI83_LVDS_MODE,regval);
+    /* Voltage and pins */
+    SN65DSI83_WRITE(SN65DSI83_LVDS_SIGN,0x00);
+    SN65DSI83_WRITE(SN65DSI83_LVDS_TERM,0x03);
+    SN65DSI83_WRITE(SN65DSI83_LVDS_CM_ADJ,0x00);
+    /* Configure sync delay to minimal allowed value */
+    SN65DSI83_WRITE(SN65DSI83_CHA_SYNC_DELAY_LO,0x21);
+    SN65DSI83_WRITE(SN65DSI83_CHA_SYNC_DELAY_HI,0x00);
+    /* Geometry */
+    SN65DSI83_WRITE(SN65DSI83_CHA_LINE_LEN_LO,LOW(HACTIVE));
+    SN65DSI83_WRITE(SN65DSI83_CHA_LINE_LEN_HI,HIGH(HACTIVE));
+    SN65DSI83_WRITE(SN65DSI83_CHA_VERT_LINES_LO,LOW(VACTIVE));
+    SN65DSI83_WRITE(SN65DSI83_CHA_VERT_LINES_HI,HIGH(VACTIVE));
+    SN65DSI83_WRITE(SN65DSI83_CHA_HSYNC_WIDTH_LO,LOW(HPW));
+    SN65DSI83_WRITE(SN65DSI83_CHA_HSYNC_WIDTH_HI,HIGH(HPW));
+    SN65DSI83_WRITE(SN65DSI83_CHA_VSYNC_WIDTH_LO,LOW(VPW));
+    SN65DSI83_WRITE(SN65DSI83_CHA_VSYNC_WIDTH_HI,HIGH(VPW));
+    SN65DSI83_WRITE(SN65DSI83_CHA_HORZ_BACKPORCH,LOW(HBP));
+    SN65DSI83_WRITE(SN65DSI83_CHA_VERT_BACKPORCH,LOW(VBP));
+    SN65DSI83_WRITE(SN65DSI83_CHA_HORZ_FRONTPORCH,LOW(HFP));
+    SN65DSI83_WRITE(SN65DSI83_CHA_VERT_FRONTPORCH,LOW(VFP));
+    SN65DSI83_WRITE(SN65DSI83_TEST_PATTERN,0x00);
+    SN65DSI83_WRITE(SN65DSI83_REG_3D,0x00);
+    SN65DSI83_WRITE(SN65DSI83_REG_3E,0x00);
+#endif 
+
+
+/* add by alex ,2019-08-19 */
+	SN65DSI83_WRITE(0x09,0x00);
+	SN65DSI83_WRITE(0x0A,0x05);
+	SN65DSI83_WRITE(0x0B,0x28);
+	SN65DSI83_WRITE(0x0D,0x00);
+	SN65DSI83_WRITE(0x10,0x26);
+	SN65DSI83_WRITE(0x11,0x00);
+	SN65DSI83_WRITE(0x12,0x52);
+	SN65DSI83_WRITE(0x13,0x00);
+	SN65DSI83_WRITE(0x18,0x6c);
+	SN65DSI83_WRITE(0x19,0x00);
+	SN65DSI83_WRITE(0x1A,0x03);
+	SN65DSI83_WRITE(0x1B,0x00);
+	SN65DSI83_WRITE(0x20,0x00);
+	SN65DSI83_WRITE(0x21,0x0a);
+	SN65DSI83_WRITE(0x22,0x00);
+	SN65DSI83_WRITE(0x23,0x00);
+	SN65DSI83_WRITE(0x24,0x00);
+	SN65DSI83_WRITE(0x25,0x00);
+	SN65DSI83_WRITE(0x26,0x00);
+	SN65DSI83_WRITE(0x27,0x00);
+	SN65DSI83_WRITE(0x28,0x20);
+	SN65DSI83_WRITE(0x29,0x00);
+	SN65DSI83_WRITE(0x2A,0x00);
+	SN65DSI83_WRITE(0x2B,0x00);
+	SN65DSI83_WRITE(0x2C,0x36);
+	SN65DSI83_WRITE(0x2D,0x00);
+	SN65DSI83_WRITE(0x2E,0x00);
+	SN65DSI83_WRITE(0x2F,0x00);
+    SN65DSI83_WRITE(0x30,0x0a);
+    SN65DSI83_WRITE(0x31,0x00);
+	SN65DSI83_WRITE(0x32,0x00);
+	SN65DSI83_WRITE(0x33,0x00);
+	SN65DSI83_WRITE(0x34,0x4b);
+	SN65DSI83_WRITE(0x35,0x00);
+	SN65DSI83_WRITE(0x36,0x00);
+	SN65DSI83_WRITE(0x37,0x00);
+	SN65DSI83_WRITE(0x38,0x00);
+	SN65DSI83_WRITE(0x39,0x00);
+	SN65DSI83_WRITE(0x3a,0x00);
+	SN65DSI83_WRITE(0x3b,0x00);
+    SN65DSI83_WRITE(0x3c,0x00);
+	SN65DSI83_WRITE(0x3D,0x00);
+    SN65DSI83_WRITE(0x3E,0x00);
+
+    /* mute channel B */
+//    SN65DSI83_WRITE(SN65DSI83_CHB_DSI_CLK_RNG, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_LINE_LEN_LO, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_LINE_LEN_HI, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_VERT_LINES_LO, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_VERT_LINES_HI, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_SYNC_DELAY_LO, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_SYNC_DELAY_HI, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_HSYNC_WIDTH_LO, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_HSYNC_WIDTH_HI, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_VSYNC_WIDTH_LO, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_VSYNC_WIDTH_HI, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_HORZ_BACKPORCH, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_VERT_BACKPORCH, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_HORZ_FRONTPORCH, 0x00);
+//    SN65DSI83_WRITE(SN65DSI83_CHB_VERT_FRONTPORCH, 0x00);
+    return 0;
+}
+
+static int sn65dsi83_brg_setup(struct sn65dsi83_brg *brg)
+{
+    struct i2c_client *client = I2C_CLIENT(brg);
+    dev_info(&client->dev,"%s\n",__func__);
+    sn65dsi83_brg_power_on(brg);
+    return sn65dsi83_brg_configure(brg);
+}
+
+static int sn65dsi83_brg_reset(struct sn65dsi83_brg *brg)
+{
+    /* Soft Reset reg value at power on should be 0x00 */
+    struct i2c_client *client = I2C_CLIENT(brg);
+    int ret = SN65DSI83_READ(SN65DSI83_SOFT_RESET);
+    dev_info(&client->dev,"%s\n",__func__);
+    if (ret != 0x00) {
+        dev_err(&client->dev,"Failed to reset the device");
+        return -ENODEV;
+    }
+    return 0;
+}
+
+static struct sn65dsi83_brg_funcs brg_func = {
+    .power_on = sn65dsi83_brg_power_on,
+    .power_off = sn65dsi83_brg_power_off,
+    .setup = sn65dsi83_brg_setup,
+    .reset = sn65dsi83_brg_reset,
+    .start_stream = sn65dsi83_brg_start_stream,
+    .stop_stream = sn65dsi83_brg_stop_stream,
+};
+
+static struct sn65dsi83_brg brg = {
+    .funcs = &brg_func,
+};
+
+struct sn65dsi83_brg *sn65dsi83_brg_get(void) {
+    return &brg;
+}
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.h b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.h
new file mode 100644
index 0000000..9f23df8
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_brg.h
@@ -0,0 +1,55 @@
+#ifndef _SN65DSI83_BRG_H__
+#define _SN65DSI83_BRG_H__
+
+#include <linux/i2c.h>
+#include <linux/gpio/consumer.h>
+#include <video/videomode.h>
+
+struct sn65dsi83_brg;
+struct sn65dsi83_brg_funcs {
+    int (*power_on)(struct sn65dsi83_brg *sn65dsi8383_brg);
+    void (*power_off)(struct sn65dsi83_brg *sn65dsi8383_brg);
+    int (*reset)(struct sn65dsi83_brg *sn65dsi8383_brg);
+    int (*setup)(struct sn65dsi83_brg *sn65dsi8383_brg);
+    int (*start_stream)(struct sn65dsi83_brg *sn65dsi8383_brg);
+    void (*stop_stream)(struct sn65dsi83_brg *sn65dsi8383_brg);
+};
+
+struct sn65dsi83_brg {
+    struct i2c_client *client;
+    struct gpio_desc *gpio_enable;
+    /* Bridge Panel Parameters */
+    struct videomode vm;
+    u32 width_mm;
+    u32 height_mm;
+    u32 format;
+    u32 bpp;
+
+    u8 num_dsi_lanes;
+    struct sn65dsi83_brg_funcs *funcs;
+};
+struct sn65dsi83_brg *sn65dsi83_brg_get(void);
+
+#define I2C_DEVICE(A) &(A)->client->dev
+#define I2C_CLIENT(A) (A)->client
+#define VM(A) &(A)->vm
+#define BPP(A) (A)->bpp
+#define FORMAT(A) (A)->format
+#define DSI_LANES(A) (A)->num_dsi_lanes
+
+/* The caller has to have a vm structure defined */
+#define PIXCLK vm->pixelclock
+#define HACTIVE vm->hactive
+#define HFP vm->hfront_porch
+#define HBP vm->hback_porch
+#define HPW vm->hsync_len
+#define VACTIVE vm->vactive
+#define VFP vm->vfront_porch
+#define VBP vm->vback_porch
+#define VPW vm->vsync_len
+#define FLAGS vm->flags
+
+#define HIGH(A) (((A) >> 8) & 0xFF)
+#define LOW(A)  ((A)  & 0xFF)
+
+#endif /* _SN65DSI83_BRG_H__ */
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_drv.c b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_drv.c
new file mode 100644
index 0000000..403e2a2
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_drv.c
@@ -0,0 +1,434 @@
+/*
+ * Licensed under the GPL-2.
+ * Copyright 2019 MYiR Devices
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/slab.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc_helper.h>
+#include <video/mipi_display.h>
+#include <video/of_videomode.h>
+#include <video/videomode.h>
+
+#include "sn65dsi83_timing.h"
+#include "sn65dsi83_brg.h"
+
+struct sn65dsi83 {
+    u8 channel_id;
+    enum drm_connector_status status;
+    bool powered;
+    struct drm_display_mode curr_mode;
+    struct drm_bridge bridge;
+    struct drm_connector connector;
+    struct device_node *host_node;
+    struct mipi_dsi_device *dsi;
+    struct sn65dsi83_brg *brg;
+};
+
+static int sn65dsi83_attach_dsi(struct sn65dsi83 *sn65dsi83);
+#define DRM_DEVICE(A) A->dev->dev
+/* Connector funcs */
+static struct sn65dsi83 *connector_to_sn65dsi83(struct drm_connector *connector)
+{
+    return container_of(connector, struct sn65dsi83, connector);
+}
+
+static int sn65dsi83_connector_get_modes(struct drm_connector *connector)
+{
+    struct sn65dsi83 *sn65dsi83 = connector_to_sn65dsi83(connector);
+    struct sn65dsi83_brg *brg = sn65dsi83->brg;
+    struct device *dev = connector->dev->dev;
+    struct drm_display_mode *mode;
+    u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+    u32 *bus_flags = &connector->display_info.bus_flags;
+    int ret;
+
+    dev_info(dev, "%s\n",__func__);
+    mode = drm_mode_create(connector->dev);
+    if (!mode) {
+        DRM_DEV_ERROR(dev, "Failed to create display mode!\n");
+        return 0;
+    }
+
+    drm_display_mode_from_videomode(&brg->vm, mode);
+    mode->width_mm = brg->width_mm;
+    mode->height_mm = brg->height_mm;
+    mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+
+    drm_mode_probed_add(connector, mode);
+    drm_mode_connector_list_update(connector);
+
+    connector->display_info.width_mm = mode->width_mm;
+    connector->display_info.height_mm = mode->height_mm;
+
+    if (brg->vm.flags & DISPLAY_FLAGS_DE_HIGH)
+        *bus_flags |= DRM_BUS_FLAG_DE_HIGH;
+    if (brg->vm.flags & DISPLAY_FLAGS_DE_LOW)
+        *bus_flags |= DRM_BUS_FLAG_DE_LOW;
+    if (brg->vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+        *bus_flags |= DRM_BUS_FLAG_PIXDATA_NEGEDGE;
+    if (brg->vm.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
+        *bus_flags |= DRM_BUS_FLAG_PIXDATA_POSEDGE;
+
+    ret = drm_display_info_set_bus_formats(&connector->display_info,
+                           &bus_format, 1);
+    if (ret)
+        return ret;
+
+    return 1;
+}
+
+static enum drm_mode_status
+sn65dsi83_connector_mode_valid(struct drm_connector *connector,
+                 struct drm_display_mode *mode)
+{
+    struct sn65dsi83 *sn65dsi83 = connector_to_sn65dsi83(connector);
+    struct device *dev = connector->dev->dev;
+	if (mode->clock > ( sn65dsi83->brg->vm.pixelclock / 1000 ))
+		return MODE_CLOCK_HIGH;
+
+    dev_info(dev, "%s: mode: %d*%d@%d is valid\n",__func__,
+            mode->hdisplay,mode->vdisplay,mode->clock);
+
+	//drm_kms_helper_hotplug_event(connector->dev);
+    return MODE_OK;
+}
+
+static struct drm_connector_helper_funcs sn65dsi83_connector_helper_funcs = {
+    .get_modes = sn65dsi83_connector_get_modes,
+    .mode_valid = sn65dsi83_connector_mode_valid,
+};
+
+static enum drm_connector_status
+sn65dsi83_connector_detect(struct drm_connector *connector, bool force)
+{
+    struct sn65dsi83 *sn65dsi83 = connector_to_sn65dsi83(connector);
+    struct device *dev = connector->dev->dev;
+    enum drm_connector_status status;
+    dev_info(dev, "%s\n",__func__);
+
+    status = connector_status_connected;
+    sn65dsi83->status = status;
+    return status;
+}
+
+static int sn65dsi83_drm_helper_connector_dpms(struct drm_connector *connector, int mode)
+{
+	drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+	drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+	return 0;
+}
+
+static struct drm_connector_funcs sn65dsi83_connector_funcs = {
+//    .dpms = drm_atomic_helper_connector_dpms,
+	.dpms = sn65dsi83_drm_helper_connector_dpms,
+    .fill_modes = drm_helper_probe_single_connector_modes,
+    .detect = sn65dsi83_connector_detect,
+    .destroy = drm_connector_cleanup,
+    .reset = drm_atomic_helper_connector_reset,
+    .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+    .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+/* Bridge funcs */
+static struct sn65dsi83 *bridge_to_sn65dsi83(struct drm_bridge *bridge)
+{
+    return container_of(bridge, struct sn65dsi83, bridge);
+}
+
+static void sn65dsi83_bridge_enable(struct drm_bridge *bridge)
+{
+    struct sn65dsi83 *sn65dsi83 = bridge_to_sn65dsi83(bridge);
+    dev_info(DRM_DEVICE(bridge),"%s\n",__func__);
+    sn65dsi83->brg->funcs->setup(sn65dsi83->brg);
+    sn65dsi83->brg->funcs->start_stream(sn65dsi83->brg);
+}
+
+static void sn65dsi83_bridge_disable(struct drm_bridge *bridge)
+{
+    struct sn65dsi83 *sn65dsi83 = bridge_to_sn65dsi83(bridge);
+    dev_info(DRM_DEVICE(bridge),"%s\n",__func__);
+    sn65dsi83->brg->funcs->stop_stream(sn65dsi83->brg);
+    sn65dsi83->brg->funcs->power_off(sn65dsi83->brg);
+}
+
+static void sn65dsi83_bridge_mode_set(struct drm_bridge *bridge,
+                    struct drm_display_mode *mode,
+                    struct drm_display_mode *adj_mode)
+{
+    struct sn65dsi83 *sn65dsi83 = bridge_to_sn65dsi83(bridge);
+    dev_info(DRM_DEVICE(bridge), "%s: mode: %d*%d@%d\n",__func__,
+            mode->hdisplay,mode->vdisplay,mode->clock);
+    drm_mode_copy(&sn65dsi83->curr_mode, adj_mode);
+}
+
+static int sn65dsi83_bridge_attach(struct drm_bridge *bridge)
+{
+    struct sn65dsi83 *sn65dsi83 = bridge_to_sn65dsi83(bridge);
+    int ret;
+
+    dev_info(DRM_DEVICE(bridge),"%s\n",__func__);
+    if (!bridge->encoder) {
+        DRM_ERROR("Parent encoder object not found");
+        return -ENODEV;
+    }
+
+    sn65dsi83->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
+
+    ret = drm_connector_init(bridge->dev, &sn65dsi83->connector,
+                 &sn65dsi83_connector_funcs,
+                 DRM_MODE_CONNECTOR_DSI);
+    if (ret) {
+        DRM_ERROR("Failed to initialize connector with drm\n");
+        return ret;
+    }
+    drm_connector_helper_add(&sn65dsi83->connector,
+                 &sn65dsi83_connector_helper_funcs);
+    drm_mode_connector_attach_encoder(&sn65dsi83->connector, bridge->encoder);
+
+    ret = sn65dsi83_attach_dsi(sn65dsi83);
+
+	// MM
+	//drm_bridge_enable(bridge);
+    return ret;
+}
+
+static struct drm_bridge_funcs sn65dsi83_bridge_funcs = {
+    .enable = sn65dsi83_bridge_enable,
+    .disable = sn65dsi83_bridge_disable,
+    .mode_set = sn65dsi83_bridge_mode_set,
+    .attach = sn65dsi83_bridge_attach,
+};
+
+static int sn65dsi83_parse_dt(struct device_node *np,
+    struct sn65dsi83 *sn65dsi83)
+{
+    struct device *dev = &sn65dsi83->brg->client->dev;
+    u32 num_lanes = 4, bpp = 24, format = 2, width = 149, height = 93;
+    struct device_node *endpoint;
+
+	dev_dbg(dev, "sn65dsi83_parse_dt\n");
+
+    endpoint = of_graph_get_next_endpoint(np, NULL);
+    if (!endpoint)
+        return -ENODEV;
+
+    sn65dsi83->host_node = of_graph_get_remote_port_parent(endpoint);
+    if (!sn65dsi83->host_node) {
+        of_node_put(endpoint);
+        return -ENODEV;
+    }
+
+	dev_dbg(dev, "sn65dsi83_parse_dt... parsing dt\n");
+    of_property_read_u32(np, "ti,dsi-lanes", &num_lanes);
+    of_property_read_u32(np, "ti,lvds-format", &format);
+    of_property_read_u32(np, "ti,lvds-bpp", &bpp);
+    of_property_read_u32(np, "ti,width-mm", &width);
+    of_property_read_u32(np, "ti,height-mm", &height);
+
+    if (num_lanes < 1 || num_lanes > 4) {
+        dev_err(dev, "Invalid dsi-lanes: %d\n", num_lanes);
+        return -EINVAL;
+    }
+    sn65dsi83->brg->num_dsi_lanes = num_lanes;
+
+    sn65dsi83->brg->gpio_enable = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
+    if (IS_ERR(sn65dsi83->brg->gpio_enable)) {
+        dev_err(dev, "failed to parse enable gpio");
+        return PTR_ERR(sn65dsi83->brg->gpio_enable);
+    }
+
+    sn65dsi83->brg->format = format;
+    sn65dsi83->brg->bpp = bpp;
+
+    sn65dsi83->brg->width_mm = width;
+    sn65dsi83->brg->height_mm = height;
+
+    /* Read default timing if there is not device tree node for */
+    if ((of_get_videomode(np, &sn65dsi83->brg->vm, 0)) < 0)
+	{
+		 dev_dbg(dev, "******** panel_default_timing\n");  
+        videomode_from_timing(&panel_default_timing, &sn65dsi83->brg->vm);
+	}
+
+    of_node_put(endpoint);
+    of_node_put(sn65dsi83->host_node);
+
+    return 0;
+}
+
+static int sn65dsi83_probe(struct i2c_client *i2c,
+    const struct i2c_device_id *id)
+{
+    struct sn65dsi83 *sn65dsi83;
+    struct device *dev = &i2c->dev;
+    int ret;
+
+    dev_info(dev,"%s\n",__func__);
+    if (!dev->of_node)
+        return -EINVAL;
+
+    sn65dsi83 = devm_kzalloc(dev, sizeof(*sn65dsi83), GFP_KERNEL);
+    if (!sn65dsi83)
+        return -ENOMEM;
+
+    /* Initialize it before DT parser */
+    sn65dsi83->brg = sn65dsi83_brg_get();
+    sn65dsi83->brg->client = i2c;
+
+    sn65dsi83->powered = false;
+    sn65dsi83->status = connector_status_disconnected;
+
+    i2c_set_clientdata(i2c, sn65dsi83);
+
+    ret = sn65dsi83_parse_dt(dev->of_node, sn65dsi83);
+    if (ret)
+        return ret;
+
+    sn65dsi83->brg->funcs->power_off(sn65dsi83->brg);
+    sn65dsi83->brg->funcs->power_on(sn65dsi83->brg);
+    ret  = sn65dsi83->brg->funcs->reset(sn65dsi83->brg);
+    if (ret != 0x00) {
+        dev_err(dev, "Failed to reset the device");
+        return -ENODEV;
+    }
+    sn65dsi83->brg->funcs->power_off(sn65dsi83->brg);
+
+
+    sn65dsi83->bridge.funcs = &sn65dsi83_bridge_funcs;
+    sn65dsi83->bridge.of_node = dev->of_node;
+
+    ret = drm_bridge_add(&sn65dsi83->bridge);
+    if (ret) {
+        dev_err(dev, "failed to add sn65dsi83 bridge\n");
+    }
+
+    dev_info(dev,"%s done\n",__func__);
+
+    return ret;
+}
+
+static int sn65dsi83_attach_dsi(struct sn65dsi83 *sn65dsi83)
+{
+    struct device *dev = &sn65dsi83->brg->client->dev;
+    struct mipi_dsi_host *host;
+    struct mipi_dsi_device *dsi;
+    int ret = 0;
+    const struct mipi_dsi_device_info info = { .type = "sn65dsi83",
+                           .channel = 0,
+                           .node = NULL,
+                         };
+
+    dev_info(dev, "%s\n",__func__);
+    host = of_find_mipi_dsi_host_by_node(sn65dsi83->host_node);
+    if (!host) {
+        dev_err(dev, "failed to find dsi host\n");
+        return -EPROBE_DEFER;
+    }
+
+    dsi = mipi_dsi_device_register_full(host, &info);
+    if (IS_ERR(dsi)) {
+        dev_err(dev, "failed to create dsi device\n");
+        ret = PTR_ERR(dsi);
+        return -ENODEV;
+    }
+
+    sn65dsi83->dsi = dsi;
+
+    dsi->lanes = sn65dsi83->brg->num_dsi_lanes;
+    dsi->format = MIPI_DSI_FMT_RGB888;
+//    dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_HSE |
+//               MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_VIDEO_BURST;
+
+  dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_HSE;
+//	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+//			  MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
+
+    ret = mipi_dsi_attach(dsi);
+    if (ret < 0) {
+        dev_err(dev, "failed to attach dsi to host\n");
+        mipi_dsi_device_unregister(dsi);
+    }
+
+    return ret;
+}
+
+static void sn65dsi83_detach_dsi(struct sn65dsi83 *sn65dsi83)
+{
+    struct device *dev = &sn65dsi83->brg->client->dev;
+    dev_info(dev, "%s\n",__func__);
+    mipi_dsi_detach(sn65dsi83->dsi);
+    mipi_dsi_device_unregister(sn65dsi83->dsi);
+}
+
+static int sn65dsi83_remove(struct i2c_client *i2c)
+{
+    struct sn65dsi83 *sn65dsi83 = i2c_get_clientdata(i2c);
+    struct device *dev = &sn65dsi83->brg->client->dev;
+    dev_info(dev, "%s\n",__func__);
+
+    sn65dsi83_detach_dsi(sn65dsi83);
+    drm_bridge_remove(&sn65dsi83->bridge);
+
+    return 0;
+}
+
+static const struct i2c_device_id sn65dsi83_i2c_ids[] = {
+    { "sn65dsi83", 0 },
+    { }
+};
+MODULE_DEVICE_TABLE(i2c, sn65dsi83_i2c_ids);
+
+static const struct of_device_id sn65dsi83_of_ids[] = {
+    { .compatible = "ti,sn65dsi83" },
+    { }
+};
+MODULE_DEVICE_TABLE(of, sn65dsi83_of_ids);
+
+static struct mipi_dsi_driver sn65dsi83_dsi_driver = {
+    .driver.name = "sn65dsi83",
+};
+
+static struct i2c_driver sn65dsi83_driver = {
+    .driver = {
+        .name = "sn65dsi83",
+        .of_match_table = sn65dsi83_of_ids,
+    },
+    .id_table = sn65dsi83_i2c_ids,
+    .probe = sn65dsi83_probe,
+    .remove = sn65dsi83_remove,
+};
+
+static int __init sn65dsi83_init(void)
+{
+    if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
+        mipi_dsi_driver_register(&sn65dsi83_dsi_driver);
+
+    return i2c_add_driver(&sn65dsi83_driver);
+}
+module_init(sn65dsi83_init);
+
+static void __exit sn65dsi83_exit(void)
+{
+    i2c_del_driver(&sn65dsi83_driver);
+
+    if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
+        mipi_dsi_driver_unregister(&sn65dsi83_dsi_driver);
+}
+module_exit(sn65dsi83_exit);
+
+MODULE_AUTHOR("alex.hu");
+MODULE_DESCRIPTION("SN65DSI bridge driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_timing.h b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_timing.h
new file mode 100755
index 0000000..9840f7f
--- /dev/null
+++ b/drivers/gpu/drm/bridge/sn65dsi83/sn65dsi83_timing.h
@@ -0,0 +1,33 @@
+#ifndef __SN65DSI83_TIMING_H__
+#define __SN65DSI83_TIMING_H__
+
+/* Default Video Parameters */
+#define PIXCLK_INIT 54000000
+
+#define HACTIVE_INIT 1280
+#define HPW_INIT 2
+#define HBP_INIT 6
+#define HFP_INIT 5
+
+#define VACTIVE_INIT 1024
+#define VPW_INIT 1
+#define VBP_INIT 2
+#define VFP_INIT 3
+
+static const struct display_timing panel_default_timing = {
+    .pixelclock = { PIXCLK_INIT, PIXCLK_INIT, PIXCLK_INIT },
+    .hactive = { HACTIVE_INIT, HACTIVE_INIT, HACTIVE_INIT },
+    .hfront_porch = { HFP_INIT, HFP_INIT, HFP_INIT },
+    .hsync_len = { HPW_INIT, HPW_INIT, HPW_INIT },
+    .hback_porch = { HBP_INIT, HBP_INIT, HBP_INIT },
+    .vactive = { VACTIVE_INIT, VACTIVE_INIT, VACTIVE_INIT },
+    .vfront_porch = { VFP_INIT, VFP_INIT, VFP_INIT },
+    .vsync_len = { VPW_INIT, VPW_INIT, VPW_INIT },
+    .vback_porch = { VBP_INIT, VBP_INIT, VBP_INIT },
+    .flags = DISPLAY_FLAGS_HSYNC_LOW |
+         DISPLAY_FLAGS_VSYNC_LOW |
+         DISPLAY_FLAGS_DE_LOW |
+         DISPLAY_FLAGS_PIXDATA_NEGEDGE,
+};
+
+#endif /* __SN65DSI83_TIMING_H__ */
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 9a0db26..8e27e90 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -921,15 +921,17 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
 		crtc = new_conn_state->crtc;
 		if ((!crtc && old_conn_state->crtc) ||
 		    (crtc && drm_atomic_crtc_needs_modeset(crtc->state))) {
-			int mode = DRM_MODE_DPMS_OFF;
+			int mode = DRM_MODE_DPMS_ON;	// always ON
 
 			if (crtc && crtc->state->active)
 				mode = DRM_MODE_DPMS_ON;
 
 			connector->dpms = mode;
+			drm_notifier_call_chain(mode, connector->dev); //MM
 		}
 	}
 
+
 	/* set new links */
 	for_each_new_connector_in_state(old_state, connector, new_conn_state, i) {
 		if (!new_conn_state->crtc)
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c
deleted file mode 100644
index 044d5fb..0000000
--- a/drivers/gpu/drm/mxsfb/mxsfb_out.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2016 Marek Vasut <marex@denx.de>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/of_graph.h>
-
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_cma_helper.h>
-#include <drm/drm_gem_cma_helper.h>
-#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_plane_helper.h>
-#include <drm/drm_simple_kms_helper.h>
-#include <drm/drmP.h>
-
-#include "mxsfb_drv.h"
-
-static struct mxsfb_drm_private *
-drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
-{
-	return container_of(connector, struct mxsfb_drm_private,
-			    panel_connector);
-}
-
-static int mxsfb_panel_get_modes(struct drm_connector *connector)
-{
-	struct mxsfb_drm_private *mxsfb =
-			drm_connector_to_mxsfb_drm_private(connector);
-
-	if (mxsfb->panel)
-		return mxsfb->panel->funcs->get_modes(mxsfb->panel);
-
-	return 0;
-}
-
-static const struct
-drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
-	.get_modes = mxsfb_panel_get_modes,
-};
-
-static enum drm_connector_status
-mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
-{
-	struct mxsfb_drm_private *mxsfb =
-			drm_connector_to_mxsfb_drm_private(connector);
-
-	if (mxsfb->panel)
-		return connector_status_connected;
-
-	return connector_status_disconnected;
-}
-
-static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
-{
-	struct mxsfb_drm_private *mxsfb =
-			drm_connector_to_mxsfb_drm_private(connector);
-
-	if (mxsfb->panel)
-		drm_panel_detach(mxsfb->panel);
-
-	drm_connector_unregister(connector);
-	drm_connector_cleanup(connector);
-}
-
-static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
-	.detect			= mxsfb_panel_connector_detect,
-	.fill_modes		= drm_helper_probe_single_connector_modes,
-	.destroy		= mxsfb_panel_connector_destroy,
-	.reset			= drm_atomic_helper_connector_reset,
-	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
-};
-
-int mxsfb_create_output(struct drm_device *drm)
-{
-	struct mxsfb_drm_private *mxsfb = drm->dev_private;
-	int ret;
-
-	ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, &mxsfb->panel, &mxsfb->bridge);
-	if (ret)
-		return ret;
-
-	if (mxsfb->panel) {
-		mxsfb->connector = &mxsfb->panel_connector;
-		mxsfb->connector->dpms = DRM_MODE_DPMS_OFF;
-		mxsfb->connector->polled = 0;
-		drm_connector_helper_add(mxsfb->connector,
-				&mxsfb_panel_connector_helper_funcs);
-		ret = drm_connector_init(drm, mxsfb->connector,
-					 &mxsfb_panel_connector_funcs,
-					 DRM_MODE_CONNECTOR_Unknown);
-	}
-
-	return ret;
-}
