Commit 34d9545b authored by Archit Taneja's avatar Archit Taneja Committed by Rob Clark
Browse files

drm/msm/dsi: Reset both PHYs before clock operation for dual DSI



In case of dual DSI, some registers in PHY1 have been programmed
during PLL0 clock's set_rate. The PHY1 reset called by host1 later
will silently reset those PHY1 registers. This change is to reset
and enable both PHYs before any PLL clock operation.

[Originally worked on by Hai Li <hali@codeaurora.org>. Fixed up
by Archit Taneja <architt@codeaurora.org>]

Signed-off-by: default avatarArchit Taneja <architt@codeaurora.org>
Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
parent 57bf4338
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer);
void msm_dsi_host_unregister(struct mipi_dsi_host *host);
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_destroy(struct mipi_dsi_host *host);
int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
					struct drm_device *dev);
+13 −12
Original line number Diff line number Diff line
@@ -691,17 +691,6 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host)
	return 0;
}

static void dsi_phy_sw_reset(struct msm_dsi_host *msm_host)
{
	DBG("");
	dsi_write(msm_host, REG_DSI_PHY_RESET, DSI_PHY_RESET_RESET);
	/* Make sure fully reset */
	wmb();
	udelay(1000);
	dsi_write(msm_host, REG_DSI_PHY_RESET, 0);
	udelay(100);
}

static void dsi_intr_ctrl(struct msm_dsi_host *msm_host, u32 mask, int enable)
{
	u32 intr;
@@ -2126,6 +2115,19 @@ exit:
	return ret;
}

void msm_dsi_host_reset_phy(struct mipi_dsi_host *host)
{
	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);

	DBG("");
	dsi_write(msm_host, REG_DSI_PHY_RESET, DSI_PHY_RESET_RESET);
	/* Make sure fully reset */
	wmb();
	udelay(1000);
	dsi_write(msm_host, REG_DSI_PHY_RESET, 0);
	udelay(100);
}

int msm_dsi_host_enable(struct mipi_dsi_host *host)
{
	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
@@ -2206,7 +2208,6 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
		goto fail_disable_reg;
	}

	dsi_phy_sw_reset(msm_host);
	ret = msm_dsi_manager_phy_enable(msm_host->id,
					msm_host->byte_clk_rate * 8,
					msm_host->esc_clk_rate,
+29 −3
Original line number Diff line number Diff line
@@ -669,13 +669,39 @@ int msm_dsi_manager_phy_enable(int id,
		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;

	ret = msm_dsi_phy_enable(phy, src_pll_id, bit_rate, esc_rate);
	/* 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);