]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/video/omap2/dss/dsi.c
OMAP: DSS2: DSI: Add lane override functions
[mv-sheeva.git] / drivers / video / omap2 / dss / dsi.c
index 0a7f1a47f8e3b5fb0b30c369f971dd77146490b4..d05f8997e02b5bab63a5b2d3e27d28f67f2d7500 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 
-#include <plat/display.h>
+#include <video/omapdss.h>
 #include <plat/clock.h>
 
 #include "dss.h"
@@ -90,6 +90,7 @@ struct dsi_reg { u16 idx; };
 #define DSI_DSIPHY_CFG1                        DSI_REG(0x200 + 0x0004)
 #define DSI_DSIPHY_CFG2                        DSI_REG(0x200 + 0x0008)
 #define DSI_DSIPHY_CFG5                        DSI_REG(0x200 + 0x0014)
+#define DSI_DSIPHY_CFG10               DSI_REG(0x200 + 0x0028)
 
 /* DSI_PLL_CTRL_SCP */
 
@@ -208,6 +209,15 @@ enum dsi_vc_mode {
        DSI_VC_MODE_VP,
 };
 
+enum dsi_lane {
+       DSI_CLK_P       = 1 << 0,
+       DSI_CLK_N       = 1 << 1,
+       DSI_DATA1_P     = 1 << 2,
+       DSI_DATA1_N     = 1 << 3,
+       DSI_DATA2_P     = 1 << 4,
+       DSI_DATA2_N     = 1 << 5,
+};
+
 struct dsi_update_region {
        u16 x, y, w, h;
        struct omap_dss_device *device;
@@ -1009,7 +1019,7 @@ static unsigned long dsi_fclk_rate(void)
 {
        unsigned long r;
 
-       if (dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK) {
+       if (dss_get_dsi_clk_source() == OMAP_DSS_CLK_SRC_FCK) {
                /* DSI FCLK source is DSS_CLK_FCK */
                r = dss_clk_get_rate(DSS_CLK_FCK);
        } else {
@@ -1026,7 +1036,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev)
        unsigned lp_clk_div;
        unsigned long lp_clk;
 
-       lp_clk_div = dssdev->phy.dsi.div.lp_clk_div;
+       lp_clk_div = dssdev->clocks.dsi.lp_clk_div;
 
        if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max)
                return -EINVAL;
@@ -1059,6 +1069,11 @@ static int dsi_pll_power(enum dsi_pll_power_state state)
 {
        int t = 0;
 
+       /* DSI-PLL power command 0x3 is not working */
+       if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) &&
+                       state == DSI_PLL_POWER_ON_DIV)
+               state = DSI_PLL_POWER_ON_ALL;
+
        REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30);       /* PLL_PWR_CMD */
 
        /* PLL_PWR_STATUS */
@@ -1270,12 +1285,15 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
 {
        int r = 0;
        u32 l;
-       int f;
+       int f = 0;
        u8 regn_start, regn_end, regm_start, regm_end;
        u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
 
        DSSDBGF();
 
+       dsi.current_cinfo.use_sys_clk = cinfo->use_sys_clk;
+       dsi.current_cinfo.highfreq = cinfo->highfreq;
+
        dsi.current_cinfo.fint = cinfo->fint;
        dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr;
        dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk =
@@ -1309,12 +1327,12 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
        DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
 
        DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc,
-               dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
-               dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
+               dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
+               dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
                cinfo->dsi_pll_hsdiv_dispc_clk);
        DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi,
-               dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
-               dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
+               dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
+               dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
                cinfo->dsi_pll_hsdiv_dsi_clk);
 
        dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, &regn_start, &regn_end);
@@ -1341,19 +1359,19 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
        dsi_write_reg(DSI_PLL_CONFIGURATION1, l);
 
        BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max);
-       if (cinfo->fint < 1000000)
-               f = 0x3;
-       else if (cinfo->fint < 1250000)
-               f = 0x4;
-       else if (cinfo->fint < 1500000)
-               f = 0x5;
-       else if (cinfo->fint < 1750000)
-               f = 0x6;
-       else
-               f = 0x7;
+
+       if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
+               f = cinfo->fint < 1000000 ? 0x3 :
+                       cinfo->fint < 1250000 ? 0x4 :
+                       cinfo->fint < 1500000 ? 0x5 :
+                       cinfo->fint < 1750000 ? 0x6 :
+                       0x7;
+       }
 
        l = dsi_read_reg(DSI_PLL_CONFIGURATION2);
-       l = FLD_MOD(l, f, 4, 1);                /* DSI_PLL_FREQSEL */
+
+       if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
+               l = FLD_MOD(l, f, 4, 1);        /* DSI_PLL_FREQSEL */
        l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1,
                        11, 11);                /* DSI_PLL_CLKSEL */
        l = FLD_MOD(l, cinfo->highfreq,
@@ -1409,12 +1427,6 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
 
        DSSDBG("PLL init\n");
 
-#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
-       /*
-        * HACK: this is just a quick hack to get the USE_DSI_PLL
-        * option working. USE_DSI_PLL is itself a big hack, and
-        * should be removed.
-        */
        if (dsi.vdds_dsi_reg == NULL) {
                struct regulator *vdds_dsi;
 
@@ -1427,7 +1439,6 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
 
                dsi.vdds_dsi_reg = vdds_dsi;
        }
-#endif
 
        enable_clocks(1);
        dsi_enable_pll_clock(1);
@@ -1488,22 +1499,18 @@ void dsi_pll_uninit(void)
 
 void dsi_dump_clocks(struct seq_file *s)
 {
-       int clksel;
        struct dsi_clock_info *cinfo = &dsi.current_cinfo;
-       enum dss_clk_source dispc_clk_src, dsi_clk_src;
+       enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
 
        dispc_clk_src = dss_get_dispc_clk_source();
        dsi_clk_src = dss_get_dsi_clk_source();
 
        enable_clocks(1);
 
-       clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
-
        seq_printf(s,   "- DSI PLL -\n");
 
        seq_printf(s,   "dsi pll source = %s\n",
-                       clksel == 0 ?
-                       "dss_sys_clk" : "pclkfree");
+                       cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree");
 
        seq_printf(s,   "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
 
@@ -1515,7 +1522,7 @@ void dsi_dump_clocks(struct seq_file *s)
                        dss_feat_get_clk_source_name(dispc_clk_src),
                        cinfo->dsi_pll_hsdiv_dispc_clk,
                        cinfo->regm_dispc,
-                       dispc_clk_src == DSS_CLK_SRC_FCK ?
+                       dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
                        "off" : "on");
 
        seq_printf(s,   "%s (%s)\t%-16luregm_dsi %u\t(%s)\n",
@@ -1523,7 +1530,7 @@ void dsi_dump_clocks(struct seq_file *s)
                        dss_feat_get_clk_source_name(dsi_clk_src),
                        cinfo->dsi_pll_hsdiv_dsi_clk,
                        cinfo->regm_dsi,
-                       dsi_clk_src == DSS_CLK_SRC_FCK ?
+                       dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
                        "off" : "on");
 
        seq_printf(s,   "- DSI -\n");
@@ -1866,6 +1873,54 @@ static void dsi_complexio_timings(void)
        dsi_write_reg(DSI_DSIPHY_CFG2, r);
 }
 
+static void dsi_enable_lane_override(struct omap_dss_device *dssdev,
+               enum dsi_lane lanes)
+{
+       int clk_lane   = dssdev->phy.dsi.clk_lane;
+       int data1_lane = dssdev->phy.dsi.data1_lane;
+       int data2_lane = dssdev->phy.dsi.data2_lane;
+       int clk_pol    = dssdev->phy.dsi.clk_pol;
+       int data1_pol  = dssdev->phy.dsi.data1_pol;
+       int data2_pol  = dssdev->phy.dsi.data2_pol;
+
+       u32 l = 0;
+
+       if (lanes & DSI_CLK_P)
+               l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1));
+       if (lanes & DSI_CLK_N)
+               l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0));
+
+       if (lanes & DSI_DATA1_P)
+               l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1));
+       if (lanes & DSI_DATA1_N)
+               l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0));
+
+       if (lanes & DSI_DATA2_P)
+               l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1));
+       if (lanes & DSI_DATA2_N)
+               l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0));
+
+       /*
+        * Bits in REGLPTXSCPDAT4TO0DXDY:
+        * 17: DY0 18: DX0
+        * 19: DY1 20: DX1
+        * 21: DY2 22: DX2
+        */
+
+       /* Set the lane override configuration */
+       REG_FLD_MOD(DSI_DSIPHY_CFG10, l, 22, 17); /* REGLPTXSCPDAT4TO0DXDY */
+
+       /* Enable lane override */
+       REG_FLD_MOD(DSI_DSIPHY_CFG10, 1, 27, 27); /* ENLPTXSCPDAT */
+}
+
+static void dsi_disable_lane_override(void)
+{
+       /* Disable lane override */
+       REG_FLD_MOD(DSI_DSIPHY_CFG10, 0, 27, 27); /* ENLPTXSCPDAT */
+       /* Reset the lane override configuration */
+       REG_FLD_MOD(DSI_DSIPHY_CFG10, 0, 22, 17); /* REGLPTXSCPDAT4TO0DXDY */
+}
 
 static int dsi_complexio_init(struct omap_dss_device *dssdev)
 {
@@ -1873,9 +1928,6 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
 
        DSSDBG("dsi_complexio_init\n");
 
-       /* CIO_CLK_ICG, enable L3 clk to CIO */
-       REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
-
        /* A dummy read using the SCP interface to any DSIPHY register is
         * required after DSIPHY reset to complete the reset of the DSI complex
         * I/O. */
@@ -1900,10 +1952,12 @@ static int dsi_complexio_init(struct omap_dss_device *dssdev)
                goto err;
        }
 
-       if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
-               DSSERR("ComplexIO LDO power down.\n");
-               r = -ENODEV;
-               goto err;
+       if (dss_has_feature(FEAT_DSI_LDO_STATUS)) {
+               if (wait_for_bit_change(DSI_COMPLEXIO_CFG1, 21, 1) != 1) {
+                       DSSERR("ComplexIO LDO power down.\n");
+                       r = -ENODEV;
+                       goto err;
+               }
        }
 
        dsi_complexio_timings();
@@ -2034,6 +2088,114 @@ static int dsi_force_tx_stop_mode_io(void)
        return 0;
 }
 
+static bool dsi_vc_is_enabled(int channel)
+{
+       return REG_GET(DSI_VC_CTRL(channel), 0, 0);
+}
+
+static void dsi_packet_sent_handler_vp(void *data, u32 mask)
+{
+       const int channel = dsi.update_channel;
+       u8 bit = dsi.te_enabled ? 30 : 31;
+
+       if (REG_GET(DSI_VC_TE(channel), bit, bit) == 0)
+               complete((struct completion *)data);
+}
+
+static int dsi_sync_vc_vp(int channel)
+{
+       int r = 0;
+       u8 bit;
+
+       DECLARE_COMPLETION_ONSTACK(completion);
+
+       bit = dsi.te_enabled ? 30 : 31;
+
+       r = dsi_register_isr_vc(channel, dsi_packet_sent_handler_vp,
+               &completion, DSI_VC_IRQ_PACKET_SENT);
+       if (r)
+               goto err0;
+
+       /* Wait for completion only if TE_EN/TE_START is still set */
+       if (REG_GET(DSI_VC_TE(channel), bit, bit)) {
+               if (wait_for_completion_timeout(&completion,
+                               msecs_to_jiffies(10)) == 0) {
+                       DSSERR("Failed to complete previous frame transfer\n");
+                       r = -EIO;
+                       goto err1;
+               }
+       }
+
+       dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_vp,
+               &completion, DSI_VC_IRQ_PACKET_SENT);
+
+       return 0;
+err1:
+       dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_vp, &completion,
+               DSI_VC_IRQ_PACKET_SENT);
+err0:
+       return r;
+}
+
+static void dsi_packet_sent_handler_l4(void *data, u32 mask)
+{
+       const int channel = dsi.update_channel;
+
+       if (REG_GET(DSI_VC_CTRL(channel), 5, 5) == 0)
+               complete((struct completion *)data);
+}
+
+static int dsi_sync_vc_l4(int channel)
+{
+       int r = 0;
+
+       DECLARE_COMPLETION_ONSTACK(completion);
+
+       r = dsi_register_isr_vc(channel, dsi_packet_sent_handler_l4,
+               &completion, DSI_VC_IRQ_PACKET_SENT);
+       if (r)
+               goto err0;
+
+       /* Wait for completion only if TX_FIFO_NOT_EMPTY is still set */
+       if (REG_GET(DSI_VC_CTRL(channel), 5, 5)) {
+               if (wait_for_completion_timeout(&completion,
+                               msecs_to_jiffies(10)) == 0) {
+                       DSSERR("Failed to complete previous l4 transfer\n");
+                       r = -EIO;
+                       goto err1;
+               }
+       }
+
+       dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_l4,
+               &completion, DSI_VC_IRQ_PACKET_SENT);
+
+       return 0;
+err1:
+       dsi_unregister_isr_vc(channel, dsi_packet_sent_handler_l4,
+               &completion, DSI_VC_IRQ_PACKET_SENT);
+err0:
+       return r;
+}
+
+static int dsi_sync_vc(int channel)
+{
+       WARN_ON(!dsi_bus_is_locked());
+
+       WARN_ON(in_interrupt());
+
+       if (!dsi_vc_is_enabled(channel))
+               return 0;
+
+       switch (dsi.vc[channel].mode) {
+       case DSI_VC_MODE_VP:
+               return dsi_sync_vc_vp(channel);
+       case DSI_VC_MODE_L4:
+               return dsi_sync_vc_l4(channel);
+       default:
+               BUG();
+       }
+}
+
 static int dsi_vc_enable(int channel, bool enable)
 {
        DSSDBG("dsi_vc_enable channel %d, enable %d\n",
@@ -2070,6 +2232,8 @@ static void dsi_vc_initial_config(int channel)
        r = FLD_MOD(r, 1, 7, 7); /* CS_TX_EN */
        r = FLD_MOD(r, 1, 8, 8); /* ECC_TX_EN */
        r = FLD_MOD(r, 0, 9, 9); /* MODE_SPEED, high speed on/off */
+       if (dss_has_feature(FEAT_DSI_VC_OCP_WIDTH))
+               r = FLD_MOD(r, 3, 11, 10);      /* OCP_WIDTH = 32 bit */
 
        r = FLD_MOD(r, 4, 29, 27); /* DMA_RX_REQ_NB = no dma */
        r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */
@@ -2084,6 +2248,8 @@ static int dsi_vc_config_l4(int channel)
 
        DSSDBGF("%d", channel);
 
+       dsi_sync_vc(channel);
+
        dsi_vc_enable(channel, 0);
 
        /* VC_BUSY */
@@ -2094,6 +2260,10 @@ static int dsi_vc_config_l4(int channel)
 
        REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 1, 1); /* SOURCE, 0 = L4 */
 
+       /* DCS_CMD_ENABLE */
+       if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
+               REG_FLD_MOD(DSI_VC_CTRL(channel), 0, 30, 30);
+
        dsi_vc_enable(channel, 1);
 
        dsi.vc[channel].mode = DSI_VC_MODE_L4;
@@ -2108,6 +2278,8 @@ static int dsi_vc_config_vp(int channel)
 
        DSSDBGF("%d", channel);
 
+       dsi_sync_vc(channel);
+
        dsi_vc_enable(channel, 0);
 
        /* VC_BUSY */
@@ -2118,6 +2290,10 @@ static int dsi_vc_config_vp(int channel)
 
        REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 1, 1); /* SOURCE, 1 = video port */
 
+       /* DCS_CMD_ENABLE */
+       if (dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC))
+               REG_FLD_MOD(DSI_VC_CTRL(channel), 1, 30, 30);
+
        dsi_vc_enable(channel, 1);
 
        dsi.vc[channel].mode = DSI_VC_MODE_VP;
@@ -2773,8 +2949,11 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
        r = FLD_MOD(r, 2, 13, 12);      /* LINE_BUFFER, 2 lines */
        r = FLD_MOD(r, 1, 14, 14);      /* TRIGGER_RESET_MODE */
        r = FLD_MOD(r, 1, 19, 19);      /* EOT_ENABLE */
-       r = FLD_MOD(r, 1, 24, 24);      /* DCS_CMD_ENABLE */
-       r = FLD_MOD(r, 0, 25, 25);      /* DCS_CMD_CODE, 1=start, 0=continue */
+       if (!dss_has_feature(FEAT_DSI_DCS_CMD_CONFIG_VC)) {
+               r = FLD_MOD(r, 1, 24, 24);      /* DCS_CMD_ENABLE */
+               /* DCS_CMD_CODE, 1=start, 0=continue */
+               r = FLD_MOD(r, 0, 25, 25);
+       }
 
        dsi_write_reg(DSI_CTRL, r);
 
@@ -3093,17 +3272,8 @@ static void dsi_te_timeout(unsigned long arg)
 }
 #endif
 
-static void dsi_framedone_bta_callback(void *data, u32 mask);
-
 static void dsi_handle_framedone(int error)
 {
-       const int channel = dsi.update_channel;
-
-       dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
-                       NULL, DSI_VC_IRQ_BTA);
-
-       cancel_delayed_work(&dsi.framedone_timeout_work);
-
        /* SIDLEMODE back to smart-idle */
        dispc_enable_sidle();
 
@@ -3112,14 +3282,6 @@ static void dsi_handle_framedone(int error)
                REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
        }
 
-       /* RX_FIFO_NOT_EMPTY */
-       if (REG_GET(DSI_VC_CTRL(channel), 20, 20)) {
-               DSSERR("Received error during frame transfer:\n");
-               dsi_vc_flush_receive_data(channel);
-               if (!error)
-                       error = -EIO;
-       }
-
        dsi.framedone_callback(error, dsi.framedone_data);
 
        if (!error)
@@ -3140,61 +3302,20 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work)
        dsi_handle_framedone(-ETIMEDOUT);
 }
 
-static void dsi_framedone_bta_callback(void *data, u32 mask)
-{
-       dsi_handle_framedone(0);
-
-#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
-       dispc_fake_vsync_irq();
-#endif
-}
-
 static void dsi_framedone_irq_callback(void *data, u32 mask)
 {
-       const int channel = dsi.update_channel;
-       int r;
-
        /* Note: We get FRAMEDONE when DISPC has finished sending pixels and
         * turns itself off. However, DSI still has the pixels in its buffers,
         * and is sending the data.
         */
 
-       if (dsi.te_enabled) {
-               /* enable LP_RX_TO again after the TE */
-               REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */
-       }
+       __cancel_delayed_work(&dsi.framedone_timeout_work);
 
-       /* Send BTA after the frame. We need this for the TE to work, as TE
-        * trigger is only sent for BTAs without preceding packet. Thus we need
-        * to BTA after the pixel packets so that next BTA will cause TE
-        * trigger.
-        *
-        * This is not needed when TE is not in use, but we do it anyway to
-        * make sure that the transfer has been completed. It would be more
-        * optimal, but more complex, to wait only just before starting next
-        * transfer.
-        *
-        * Also, as there's no interrupt telling when the transfer has been
-        * done and the channel could be reconfigured, the only way is to
-        * busyloop until TE_SIZE is zero. With BTA we can do this
-        * asynchronously.
-        * */
-
-       r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback,
-                       NULL, DSI_VC_IRQ_BTA);
-       if (r) {
-               DSSERR("Failed to register BTA ISR\n");
-               dsi_handle_framedone(-EIO);
-               return;
-       }
+       dsi_handle_framedone(0);
 
-       r = dsi_vc_send_bta(channel);
-       if (r) {
-               DSSERR("BTA after framedone failed\n");
-               dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback,
-                               NULL, DSI_VC_IRQ_BTA);
-               dsi_handle_framedone(-EIO);
-       }
+#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
+       dispc_fake_vsync_irq();
+#endif
 }
 
 int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
@@ -3322,10 +3443,10 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
 
        /* we always use DSS_CLK_SYSCK as input clock */
        cinfo.use_sys_clk = true;
-       cinfo.regn  = dssdev->phy.dsi.div.regn;
-       cinfo.regm  = dssdev->phy.dsi.div.regm;
-       cinfo.regm_dispc = dssdev->phy.dsi.div.regm_dispc;
-       cinfo.regm_dsi = dssdev->phy.dsi.div.regm_dsi;
+       cinfo.regn  = dssdev->clocks.dsi.regn;
+       cinfo.regm  = dssdev->clocks.dsi.regm;
+       cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc;
+       cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi;
        r = dsi_calc_clock_rates(dssdev, &cinfo);
        if (r) {
                DSSERR("Failed to calc dsi clocks\n");
@@ -3349,8 +3470,8 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
 
        fck = dsi_get_pll_hsdiv_dispc_rate();
 
-       dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div;
-       dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div;
+       dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div;
+       dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div;
 
        r = dispc_calc_clock_rates(fck, &dispc_cinfo);
        if (r) {
@@ -3371,6 +3492,10 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 {
        int r;
 
+       /* The SCPClk is required for both PLL and CIO registers on OMAP4 */
+       /* CIO_CLK_ICG, enable L3 clk to CIO */
+       REG_FLD_MOD(DSI_CLK_CTRL, 1, 14, 14);
+
        _dsi_print_reset_status();
 
        r = dsi_pll_init(dssdev, true, true);
@@ -3381,8 +3506,10 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
        if (r)
                goto err1;
 
-       dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC);
-       dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI);
+       dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
+       dss_select_dsi_clk_source(dssdev->clocks.dsi.dsi_fclk_src);
+       dss_select_lcd_clk_source(dssdev->manager->id,
+                       dssdev->clocks.dispc.channel.lcd_clk_src);
 
        DSSDBG("PLL OK\n");
 
@@ -3418,8 +3545,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
 err3:
        dsi_complexio_uninit();
 err2:
-       dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
-       dss_select_dsi_clk_source(DSS_CLK_SRC_FCK);
+       dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+       dss_select_dsi_clk_source(OMAP_DSS_CLK_SRC_FCK);
 err1:
        dsi_pll_uninit();
 err0:
@@ -3435,8 +3562,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev)
        dsi_vc_enable(2, 0);
        dsi_vc_enable(3, 0);
 
-       dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
-       dss_select_dsi_clk_source(DSS_CLK_SRC_FCK);
+       dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+       dss_select_dsi_clk_source(OMAP_DSS_CLK_SRC_FCK);
        dsi_complexio_uninit();
        dsi_pll_uninit();
 }
@@ -3627,16 +3754,16 @@ void dsi_wait_pll_hsdiv_dispc_active(void)
 {
        if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1)
                DSSERR("%s (%s) not active\n",
-                       dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
-                       dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC));
+                       dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
+                       dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC));
 }
 
 void dsi_wait_pll_hsdiv_dsi_active(void)
 {
        if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1)
                DSSERR("%s (%s) not active\n",
-                       dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
-                       dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
+                       dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
+                       dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
 }
 
 static void dsi_calc_clock_param_ranges(void)