msm_fb: HDMI: Update HPD logic to address HDMI PLL related issues

In the current implementation, the regulators pertaining to the
HDMI core are turned off/on as part of the configuration of the
HDP circuitry. As a result, the regulator that powers the HDMI
PLL is turned off before the HDMI clocks on the PLL are disabled.
This might lead to the PLL not getting locked when it is re-enabled.

This change turns on and off the regulators and clocks in proper
sequence.

CRs-Fixed: 360135
CRs-Fixed: 358598
Change-Id: Ie3630b543e78e83dc565edc32239935135ca4ca5
Signed-off-by: Aravind Venkateswaran <aravindh@codeaurora.org>
Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-dss-8960.c b/arch/arm/mach-msm/clock-dss-8960.c
index 8331899..7f3646f 100644
--- a/arch/arm/mach-msm/clock-dss-8960.c
+++ b/arch/arm/mach-msm/clock-dss-8960.c
@@ -97,6 +97,7 @@
 {
 	unsigned int val;
 	u32 ahb_en_reg, ahb_enabled;
+	unsigned int timeout_count;
 
 	ahb_en_reg = readl_relaxed(AHB_EN_REG);
 	ahb_enabled = ahb_en_reg & BIT(4);
@@ -110,6 +111,12 @@
 	writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
 	writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
 	writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
+	/* Wait for a short time before de-asserting
+	 * to allow the hardware to complete its job.
+	 * This much of delay should be fine for hardware
+	 * to assert and de-assert.
+	 */
+	udelay(10);
 	/* De-assert PLL S/W reset */
 	writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
 
@@ -118,6 +125,11 @@
 	/* Assert PHY S/W reset */
 	writel_relaxed(val, HDMI_PHY_REG_12);
 	val &= ~BIT(5);
+	/* Wait for a short time before de-asserting
+	   to allow the hardware to complete its job.
+	   This much of delay should be fine for hardware
+	   to assert and de-assert. */
+	udelay(10);
 	/* De-assert PHY S/W reset */
 	writel_relaxed(val, HDMI_PHY_REG_12);
 	writel_relaxed(0x3f, HDMI_PHY_REG_2);
@@ -135,8 +147,32 @@
 	writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
 	writel_relaxed(0x80, HDMI_PHY_REG_2);
 
-	while (!(readl_relaxed(HDMI_PHY_PLL_STATUS0) & BIT(0)))
-		cpu_relax();
+	timeout_count = 1000;
+	while (!(readl_relaxed(HDMI_PHY_PLL_STATUS0) & BIT(0)) &&
+			timeout_count) {
+		if (--timeout_count == 0) {
+			/*
+			 * PLL has still not locked.
+			 * Do a software reset and try again
+			 * Assert PLL S/W reset first
+			 */
+			writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
+
+			/* Wait for a short time before de-asserting
+			 * to allow the hardware to complete its job.
+			 * This much of delay should be fine for hardware
+			 * to assert and de-assert.
+			 */
+			udelay(10);
+			writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
+			timeout_count = 1000;
+
+			pr_err("%s: PLL not locked after %d iterations\n",
+				__func__, timeout_count);
+			pr_err("%s: Asserting PLL S/W reset & trying again\n",
+				__func__);
+		}
+	}
 
 	if (!ahb_enabled)
 		writel_relaxed(ahb_en_reg & ~BIT(4), AHB_EN_REG);