#define DSI_MAX        2
 
 struct msm_dsi_phy_shared_timings;
+struct msm_dsi_phy_clk_request;
 
 enum msm_dsi_phy_type {
        MSM_DSI_PHY_28NM_HPM,
 void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge);
 struct drm_connector *msm_dsi_manager_connector_init(u8 id);
 struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id);
-int msm_dsi_manager_phy_enable(int id,
-               const unsigned long bit_rate, const unsigned long esc_rate,
-               struct msm_dsi_phy_shared_timings *shared_timing);
-void msm_dsi_manager_phy_disable(int id);
 int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg);
 bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len);
 void msm_dsi_manager_attach_dsi_device(int id, u32 device_flags);
                                        u32 dma_base, u32 len);
 int msm_dsi_host_enable(struct mipi_dsi_host *host);
 int msm_dsi_host_disable(struct mipi_dsi_host *host);
-int msm_dsi_host_power_on(struct mipi_dsi_host *host);
+int msm_dsi_host_power_on(struct mipi_dsi_host *host,
+                       struct msm_dsi_phy_shared_timings *phy_shared_timings);
 int msm_dsi_host_power_off(struct mipi_dsi_host *host);
 int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
                                        struct drm_display_mode *mode);
 int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
                        struct msm_dsi_pll *src_pll);
 void msm_dsi_host_reset_phy(struct mipi_dsi_host *host);
+void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host,
+       struct msm_dsi_phy_clk_request *clk_req);
 void msm_dsi_host_destroy(struct mipi_dsi_host *host);
 int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
                                        struct drm_device *dev);
        u32 clk_pre;
        bool clk_pre_inc_by_2;
 };
+
+struct msm_dsi_phy_clk_request {
+       unsigned long bitclk_rate;
+       unsigned long escclk_rate;
+};
+
 void msm_dsi_phy_driver_register(void);
 void msm_dsi_phy_driver_unregister(void);
 int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
-       const unsigned long bit_rate, const unsigned long esc_rate);
+                       struct msm_dsi_phy_clk_request *clk_req);
 void msm_dsi_phy_disable(struct msm_dsi_phy *phy);
 void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy,
                        struct msm_dsi_phy_shared_timings *shared_timing);
 
        udelay(100);
 }
 
+void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host,
+       struct msm_dsi_phy_clk_request *clk_req)
+{
+       struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+
+       clk_req->bitclk_rate = msm_host->byte_clk_rate * 8;
+       clk_req->escclk_rate = msm_host->esc_clk_rate;
+}
+
 int msm_dsi_host_enable(struct mipi_dsi_host *host)
 {
        struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
                        SFPB_GPREG_MASTER_PORT_EN(en));
 }
 
-int msm_dsi_host_power_on(struct mipi_dsi_host *host)
+int msm_dsi_host_power_on(struct mipi_dsi_host *host,
+                       struct msm_dsi_phy_shared_timings *phy_shared_timings)
 {
        struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
-       struct msm_dsi_phy_shared_timings phy_shared_timings;
        int ret = 0;
 
        mutex_lock(&msm_host->dev_mutex);
 
        msm_dsi_sfpb_config(msm_host, true);
 
-       ret = dsi_calc_clk_rate(msm_host);
-       if (ret) {
-               pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
-               goto unlock_ret;
-       }
-
        ret = dsi_host_regulator_enable(msm_host);
        if (ret) {
                pr_err("%s:Failed to enable vregs.ret=%d\n",
                goto unlock_ret;
        }
 
-       ret = dsi_bus_clk_enable(msm_host);
-       if (ret) {
-               pr_err("%s: failed to enable bus clocks, %d\n", __func__, ret);
-               goto fail_disable_reg;
-       }
-
-       ret = msm_dsi_manager_phy_enable(msm_host->id,
-                                       msm_host->byte_clk_rate * 8,
-                                       msm_host->esc_clk_rate,
-                                       &phy_shared_timings);
-       dsi_bus_clk_disable(msm_host);
-       if (ret) {
-               pr_err("%s: failed to enable phy, %d\n", __func__, ret);
-               goto fail_disable_reg;
-       }
-
        ret = dsi_clk_ctrl(msm_host, 1);
        if (ret) {
                pr_err("%s: failed to enable clocks. ret=%d\n", __func__, ret);
 
        dsi_timing_setup(msm_host);
        dsi_sw_reset(msm_host);
-       dsi_ctrl_config(msm_host, true, &phy_shared_timings);
+       dsi_ctrl_config(msm_host, true, phy_shared_timings);
 
        if (msm_host->disp_en_gpio)
                gpiod_set_value(msm_host->disp_en_gpio, 1);
 
        pinctrl_pm_select_sleep_state(&msm_host->pdev->dev);
 
-       msm_dsi_manager_phy_disable(msm_host->id);
-
        dsi_clk_ctrl(msm_host, 0);
 
        dsi_host_regulator_disable(msm_host);
                                        struct drm_display_mode *mode)
 {
        struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+       int ret;
 
        if (msm_host->mode) {
                drm_mode_destroy(msm_host->dev, msm_host->mode);
                return -ENOMEM;
        }
 
+       ret = dsi_calc_clk_rate(msm_host);
+       if (ret) {
+               pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
+               return ret;
+       }
+
        return 0;
 }
 
 
        return ret;
 }
 
+static int enable_phy(struct msm_dsi *msm_dsi, int src_pll_id,
+                     struct msm_dsi_phy_shared_timings *shared_timings)
+{
+       struct msm_dsi_phy_clk_request clk_req;
+       int ret;
+
+       msm_dsi_host_get_phy_clk_req(msm_dsi->host, &clk_req);
+
+       ret = msm_dsi_phy_enable(msm_dsi->phy, src_pll_id, &clk_req);
+       msm_dsi_phy_get_shared_timings(msm_dsi->phy, shared_timings);
+
+       return ret;
+}
+
+static int
+dsi_mgr_phy_enable(int id,
+                  struct msm_dsi_phy_shared_timings shared_timings[DSI_MAX])
+{
+       struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+       struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
+       struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
+       int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
+       int ret;
+
+       /* In case of dual DSI, some registers in PHY1 have been programmed
+        * during PLL0 clock's set_rate. The PHY1 reset called by host1 here
+        * will silently reset those PHY1 registers. Therefore we need to reset
+        * and enable both PHYs before any PLL clock operation.
+        */
+       if (IS_DUAL_DSI() && mdsi && sdsi) {
+               if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
+                       msm_dsi_host_reset_phy(mdsi->host);
+                       msm_dsi_host_reset_phy(sdsi->host);
+
+                       ret = enable_phy(mdsi, src_pll_id,
+                                        &shared_timings[DSI_CLOCK_MASTER]);
+                       if (ret)
+                               return ret;
+                       ret = enable_phy(sdsi, src_pll_id,
+                                        &shared_timings[DSI_CLOCK_SLAVE]);
+                       if (ret) {
+                               msm_dsi_phy_disable(mdsi->phy);
+                               return ret;
+                       }
+               }
+       } else {
+               msm_dsi_host_reset_phy(mdsi->host);
+               ret = enable_phy(msm_dsi, src_pll_id, &shared_timings[id]);
+               if (ret)
+                       return ret;
+       }
+
+       msm_dsi->phy_enabled = true;
+
+       return 0;
+}
+
+static void dsi_mgr_phy_disable(int id)
+{
+       struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+       struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
+       struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
+
+       /* disable DSI phy
+        * In dual-dsi configuration, the phy should be disabled for the
+        * first controller only when the second controller is disabled.
+        */
+       msm_dsi->phy_enabled = false;
+       if (IS_DUAL_DSI() && mdsi && sdsi) {
+               if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
+                       msm_dsi_phy_disable(sdsi->phy);
+                       msm_dsi_phy_disable(mdsi->phy);
+               }
+       } else {
+               msm_dsi_phy_disable(msm_dsi->phy);
+       }
+}
+
 struct dsi_connector {
        struct drm_connector base;
        int id;
        struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
        struct mipi_dsi_host *host = msm_dsi->host;
        struct drm_panel *panel = msm_dsi->panel;
+       struct msm_dsi_phy_shared_timings phy_shared_timings[DSI_MAX];
        bool is_dual_dsi = IS_DUAL_DSI();
        int ret;
 
        DBG("id=%d", id);
-       if (!msm_dsi_device_connected(msm_dsi) ||
-                       (is_dual_dsi && (DSI_1 == id)))
+       if (!msm_dsi_device_connected(msm_dsi))
                return;
 
-       ret = msm_dsi_host_power_on(host);
+       ret = dsi_mgr_phy_enable(id, phy_shared_timings);
+       if (ret)
+               goto phy_en_fail;
+
+       /* Do nothing with the host if it is DSI 1 in case of dual DSI */
+       if (is_dual_dsi && (DSI_1 == id))
+               return;
+
+       ret = msm_dsi_host_power_on(host, &phy_shared_timings[id]);
        if (ret) {
                pr_err("%s: power on host %d failed, %d\n", __func__, id, ret);
                goto host_on_fail;
        }
 
        if (is_dual_dsi && msm_dsi1) {
-               ret = msm_dsi_host_power_on(msm_dsi1->host);
+               ret = msm_dsi_host_power_on(msm_dsi1->host,
+                                           &phy_shared_timings[DSI_1]);
                if (ret) {
                        pr_err("%s: power on host1 failed, %d\n",
                                                        __func__, ret);
 host1_on_fail:
        msm_dsi_host_power_off(host);
 host_on_fail:
+       dsi_mgr_phy_disable(id);
+phy_en_fail:
        return;
 }
 
 
        DBG("id=%d", id);
 
-       if (!msm_dsi_device_connected(msm_dsi) ||
-                       (is_dual_dsi && (DSI_1 == id)))
+       if (!msm_dsi_device_connected(msm_dsi))
                return;
 
+       /*
+        * Do nothing with the host if it is DSI 1 in case of dual DSI.
+        * It is safe to call dsi_mgr_phy_disable() here because a single PHY
+        * won't be diabled until both PHYs request disable.
+        */
+       if (is_dual_dsi && (DSI_1 == id))
+               goto disable_phy;
+
        if (panel) {
                ret = drm_panel_disable(panel);
                if (ret)
                        pr_err("%s: host1 power off failed, %d\n",
                                                                __func__, ret);
        }
+
+disable_phy:
+       dsi_mgr_phy_disable(id);
 }
 
 static void dsi_mgr_bridge_mode_set(struct drm_bridge *bridge,
 {
 }
 
-int msm_dsi_manager_phy_enable(int id,
-               const unsigned long bit_rate, const unsigned long esc_rate,
-               struct msm_dsi_phy_shared_timings *shared_timings)
-{
-       struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
-       struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
-       struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
-       struct msm_dsi_phy *phy = msm_dsi->phy;
-       int src_pll_id = IS_DUAL_DSI() ? DSI_CLOCK_MASTER : id;
-       int ret;
-
-       /* In case of dual DSI, some registers in PHY1 have been programmed
-        * during PLL0 clock's set_rate. The PHY1 reset called by host1 here
-        * will silently reset those PHY1 registers. Therefore we need to reset
-        * and enable both PHYs before any PLL clock operation.
-        */
-       if (IS_DUAL_DSI() && mdsi && sdsi) {
-               if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
-                       msm_dsi_host_reset_phy(mdsi->host);
-                       msm_dsi_host_reset_phy(sdsi->host);
-                       ret = msm_dsi_phy_enable(mdsi->phy, src_pll_id,
-                                                bit_rate, esc_rate);
-                       if (ret)
-                               return ret;
-                       ret = msm_dsi_phy_enable(sdsi->phy, src_pll_id,
-                                                bit_rate, esc_rate);
-                       if (ret) {
-                               msm_dsi_phy_disable(mdsi->phy);
-                               return ret;
-                       }
-               }
-       } else {
-               msm_dsi_host_reset_phy(msm_dsi->host);
-               ret = msm_dsi_phy_enable(msm_dsi->phy, src_pll_id, bit_rate,
-                                                               esc_rate);
-               if (ret)
-                       return ret;
-       }
-
-       msm_dsi->phy_enabled = true;
-       msm_dsi_phy_get_shared_timings(phy, shared_timings);
-
-       return 0;
-}
-
-void msm_dsi_manager_phy_disable(int id)
-{
-       struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
-       struct msm_dsi *mdsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
-       struct msm_dsi *sdsi = dsi_mgr_get_dsi(DSI_CLOCK_SLAVE);
-       struct msm_dsi_phy *phy = msm_dsi->phy;
-
-       /* disable DSI phy
-        * In dual-dsi configuration, the phy should be disabled for the
-        * first controller only when the second controller is disabled.
-        */
-       msm_dsi->phy_enabled = false;
-       if (IS_DUAL_DSI() && mdsi && sdsi) {
-               if (!mdsi->phy_enabled && !sdsi->phy_enabled) {
-                       msm_dsi_phy_disable(sdsi->phy);
-                       msm_dsi_phy_disable(mdsi->phy);
-               }
-       } else {
-               msm_dsi_phy_disable(phy);
-       }
-}
-
 int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg)
 {
        struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 
 }
 
 int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing,
-       const unsigned long bit_rate, const unsigned long esc_rate)
+                            struct msm_dsi_phy_clk_request *clk_req)
 {
+       const unsigned long bit_rate = clk_req->bitclk_rate;
+       const unsigned long esc_rate = clk_req->escclk_rate;
        s32 ui, lpx;
        s32 tmax, tmin;
        s32 pcnt0 = 10;
 }
 
 int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
-       const unsigned long bit_rate, const unsigned long esc_rate)
+                       struct msm_dsi_phy_clk_request *clk_req)
 {
        struct device *dev = &phy->pdev->dev;
        int ret;
        if (!phy || !phy->cfg->ops.enable)
                return -EINVAL;
 
+       ret = dsi_phy_enable_resource(phy);
+       if (ret) {
+               dev_err(dev, "%s: resource enable failed, %d\n",
+                       __func__, ret);
+               goto res_en_fail;
+       }
+
        ret = dsi_phy_regulator_enable(phy);
        if (ret) {
                dev_err(dev, "%s: regulator enable failed, %d\n",
                        __func__, ret);
-               return ret;
+               goto reg_en_fail;
        }
 
-       ret = phy->cfg->ops.enable(phy, src_pll_id, bit_rate, esc_rate);
+       ret = phy->cfg->ops.enable(phy, src_pll_id, clk_req);
        if (ret) {
                dev_err(dev, "%s: phy enable failed, %d\n", __func__, ret);
-               dsi_phy_regulator_disable(phy);
-               return ret;
+               goto phy_en_fail;
        }
 
        /*
        if (phy->usecase != MSM_DSI_PHY_SLAVE) {
                ret = msm_dsi_pll_restore_state(phy->pll);
                if (ret) {
-                       pr_err("%s: failed to restore pll state\n", __func__);
-                       if (phy->cfg->ops.disable)
-                               phy->cfg->ops.disable(phy);
-                       dsi_phy_regulator_disable(phy);
-                       return ret;
+                       dev_err(dev, "%s: failed to restore pll state, %d\n",
+                               __func__, ret);
+                       goto pll_restor_fail;
                }
        }
 
+       return 0;
+
+pll_restor_fail:
+       if (phy->cfg->ops.disable)
+               phy->cfg->ops.disable(phy);
+phy_en_fail:
+       dsi_phy_regulator_disable(phy);
+reg_en_fail:
+       dsi_phy_disable_resource(phy);
+res_en_fail:
        return ret;
 }
 
        phy->cfg->ops.disable(phy);
 
        dsi_phy_regulator_disable(phy);
+       dsi_phy_disable_resource(phy);
 }
 
 void msm_dsi_phy_get_shared_timings(struct msm_dsi_phy *phy,
 
 struct msm_dsi_phy_ops {
        int (*init) (struct msm_dsi_phy *phy);
        int (*enable)(struct msm_dsi_phy *phy, int src_pll_id,
-               const unsigned long bit_rate, const unsigned long esc_rate);
+                       struct msm_dsi_phy_clk_request *clk_req);
        void (*disable)(struct msm_dsi_phy *phy);
 };
 
  * PHY internal functions
  */
 int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing,
-       const unsigned long bit_rate, const unsigned long esc_rate);
+       struct msm_dsi_phy_clk_request *clk_req);
 void msm_dsi_phy_set_src_pll(struct msm_dsi_phy *phy, int pll_id, u32 reg,
                                u32 bit_mask);
 int msm_dsi_phy_init_common(struct msm_dsi_phy *phy);
 
 }
 
 static int dsi_20nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
-               const unsigned long bit_rate, const unsigned long esc_rate)
+                               struct msm_dsi_phy_clk_request *clk_req)
 {
        struct msm_dsi_dphy_timing *timing = &phy->timing;
        int i;
 
        DBG("");
 
-       if (msm_dsi_dphy_timing_calc(timing, bit_rate, esc_rate)) {
+       if (msm_dsi_dphy_timing_calc(timing, clk_req)) {
                dev_err(&phy->pdev->dev,
                        "%s: D-PHY timing calculation failed\n", __func__);
                return -EINVAL;
 
 }
 
 static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
-               const unsigned long bit_rate, const unsigned long esc_rate)
+                               struct msm_dsi_phy_clk_request *clk_req)
 {
        struct msm_dsi_dphy_timing *timing = &phy->timing;
        int i;
 
        DBG("");
 
-       if (msm_dsi_dphy_timing_calc(timing, bit_rate, esc_rate)) {
+       if (msm_dsi_dphy_timing_calc(timing, clk_req)) {
                dev_err(&phy->pdev->dev,
                        "%s: D-PHY timing calculation failed\n", __func__);
                return -EINVAL;
 
 }
 
 static int dsi_28nm_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
-               const unsigned long bit_rate, const unsigned long esc_rate)
+                               struct msm_dsi_phy_clk_request *clk_req)
 {
        struct msm_dsi_dphy_timing *timing = &phy->timing;
        void __iomem *base = phy->base;
 
        DBG("");
 
-       if (msm_dsi_dphy_timing_calc(timing, bit_rate, esc_rate)) {
+       if (msm_dsi_dphy_timing_calc(timing, clk_req)) {
                dev_err(&phy->pdev->dev,
                        "%s: D-PHY timing calculation failed\n", __func__);
                return -EINVAL;