platform: msm_shared: add support for HDMI PLL

Add 28nm PLL support for HDMI to drive 74.25MHz pixel
clock for 720p@60Hz resolution.

Change-Id: I45fadf727e600f21e0c0925100ecace421c5a4c2
diff --git a/platform/msm_shared/hdmi_pll_28nm.c b/platform/msm_shared/hdmi_pll_28nm.c
new file mode 100644
index 0000000..02b69bb
--- /dev/null
+++ b/platform/msm_shared/hdmi_pll_28nm.c
@@ -0,0 +1,260 @@
+/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of The Linux Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <debug.h>
+#include <err.h>
+#include <reg.h>
+#include <smem.h>
+#include <bits.h>
+#include <msm_panel.h>
+#include <platform/timer.h>
+#include <platform/iomap.h>
+
+#define HDMI_PHY_BASE  0xFD922500
+#define HDMI_PLL_BASE  0xFD922700
+
+/* hdmi phy registers */
+#define HDMI_PHY_ANA_CFG0			(0x0000)
+#define HDMI_PHY_ANA_CFG1			(0x0004)
+#define HDMI_PHY_ANA_CFG2			(0x0008)
+#define HDMI_PHY_ANA_CFG3			(0x000C)
+#define HDMI_PHY_PD_CTRL0			(0x0010)
+#define HDMI_PHY_PD_CTRL1			(0x0014)
+#define HDMI_PHY_GLB_CFG			(0x0018)
+#define HDMI_PHY_DCC_CFG0			(0x001C)
+#define HDMI_PHY_DCC_CFG1			(0x0020)
+#define HDMI_PHY_TXCAL_CFG0			(0x0024)
+#define HDMI_PHY_TXCAL_CFG1			(0x0028)
+#define HDMI_PHY_TXCAL_CFG2			(0x002C)
+#define HDMI_PHY_TXCAL_CFG3			(0x0030)
+#define HDMI_PHY_BIST_CFG0			(0x0034)
+#define HDMI_PHY_BIST_CFG1			(0x0038)
+#define HDMI_PHY_BIST_PATN0			(0x003C)
+#define HDMI_PHY_BIST_PATN1			(0x0040)
+#define HDMI_PHY_BIST_PATN2			(0x0044)
+#define HDMI_PHY_BIST_PATN3			(0x0048)
+#define HDMI_PHY_STATUS				(0x005C)
+
+/* hdmi phy unified pll registers */
+#define HDMI_UNI_PLL_REFCLK_CFG			(0x0000)
+#define HDMI_UNI_PLL_POSTDIV1_CFG		(0x0004)
+#define HDMI_UNI_PLL_CHFPUMP_CFG		(0x0008)
+#define HDMI_UNI_PLL_VCOLPF_CFG			(0x000C)
+#define HDMI_UNI_PLL_VREG_CFG			(0x0010)
+#define HDMI_UNI_PLL_PWRGEN_CFG			(0x0014)
+#define HDMI_UNI_PLL_GLB_CFG			(0x0020)
+#define HDMI_UNI_PLL_POSTDIV2_CFG		(0x0024)
+#define HDMI_UNI_PLL_POSTDIV3_CFG		(0x0028)
+#define HDMI_UNI_PLL_LPFR_CFG			(0x002C)
+#define HDMI_UNI_PLL_LPFC1_CFG			(0x0030)
+#define HDMI_UNI_PLL_LPFC2_CFG			(0x0034)
+#define HDMI_UNI_PLL_SDM_CFG0			(0x0038)
+#define HDMI_UNI_PLL_SDM_CFG1			(0x003C)
+#define HDMI_UNI_PLL_SDM_CFG2			(0x0040)
+#define HDMI_UNI_PLL_SDM_CFG3			(0x0044)
+#define HDMI_UNI_PLL_SDM_CFG4			(0x0048)
+#define HDMI_UNI_PLL_SSC_CFG0			(0x004C)
+#define HDMI_UNI_PLL_SSC_CFG1			(0x0050)
+#define HDMI_UNI_PLL_SSC_CFG2			(0x0054)
+#define HDMI_UNI_PLL_SSC_CFG3			(0x0058)
+#define HDMI_UNI_PLL_LKDET_CFG0			(0x005C)
+#define HDMI_UNI_PLL_LKDET_CFG1			(0x0060)
+#define HDMI_UNI_PLL_LKDET_CFG2			(0x0064)
+#define HDMI_UNI_PLL_CAL_CFG0			(0x006C)
+#define HDMI_UNI_PLL_CAL_CFG1			(0x0070)
+#define HDMI_UNI_PLL_CAL_CFG2			(0x0074)
+#define HDMI_UNI_PLL_CAL_CFG3			(0x0078)
+#define HDMI_UNI_PLL_CAL_CFG4			(0x007C)
+#define HDMI_UNI_PLL_CAL_CFG5			(0x0080)
+#define HDMI_UNI_PLL_CAL_CFG6			(0x0084)
+#define HDMI_UNI_PLL_CAL_CFG7			(0x0088)
+#define HDMI_UNI_PLL_CAL_CFG8			(0x008C)
+#define HDMI_UNI_PLL_CAL_CFG9			(0x0090)
+#define HDMI_UNI_PLL_CAL_CFG10			(0x0094)
+#define HDMI_UNI_PLL_CAL_CFG11			(0x0098)
+#define HDMI_UNI_PLL_STATUS			(0x00C0)
+
+#define SW_RESET BIT(2)
+#define SW_RESET_PLL BIT(0)
+
+void hdmi_phy_reset(void)
+{
+	uint32_t phy_reset_polarity = 0x0;
+	uint32_t pll_reset_polarity = 0x0;
+	uint32_t val;
+
+	val = readl(HDMI_PHY_CTRL);
+
+	phy_reset_polarity = val >> 3 & 0x1;
+	pll_reset_polarity = val >> 1 & 0x1;
+
+	if (phy_reset_polarity == 0)
+		writel(val | SW_RESET, HDMI_PHY_CTRL);
+	else
+		writel(val & (~SW_RESET), HDMI_PHY_CTRL);
+
+	if (pll_reset_polarity == 0)
+		writel(val | SW_RESET_PLL, HDMI_PHY_CTRL);
+	else
+		writel(val & (~SW_RESET_PLL), HDMI_PHY_CTRL);
+
+	if (phy_reset_polarity == 0)
+		writel(val & (~SW_RESET), HDMI_PHY_CTRL);
+	else
+		writel(val | SW_RESET, HDMI_PHY_CTRL);
+
+	if (pll_reset_polarity == 0)
+		writel(val & (~SW_RESET_PLL), HDMI_PHY_CTRL);
+	else
+		writel(val | SW_RESET_PLL, HDMI_PHY_CTRL);
+}
+
+void hdmi_phy_init(void)
+{
+	writel(0x1B, HDMI_PHY_BASE + HDMI_PHY_ANA_CFG0);
+	writel(0xF2, HDMI_PHY_BASE + HDMI_PHY_ANA_CFG1);
+	writel(0x0,  HDMI_PHY_BASE + HDMI_PHY_BIST_CFG0);
+	writel(0x0,  HDMI_PHY_BASE + HDMI_PHY_BIST_PATN0);
+	writel(0x0,  HDMI_PHY_BASE + HDMI_PHY_BIST_PATN1);
+	writel(0x0,  HDMI_PHY_BASE + HDMI_PHY_BIST_PATN2);
+	writel(0x0,  HDMI_PHY_BASE + HDMI_PHY_BIST_PATN3);
+
+	writel(0x20, HDMI_PHY_BASE + HDMI_PHY_PD_CTRL1);
+}
+
+void hdmi_phy_powerdown(void)
+{
+	writel(0x7F, HDMI_PHY_BASE + HDMI_PHY_PD_CTRL0);
+}
+
+static uint32_t hdmi_poll_status(uint32_t addr)
+{
+	uint32_t count;
+
+	for (count = 20; count > 0; count--) {
+		if (readl(addr) & 0x1) {
+			return NO_ERROR;
+		}
+		udelay(100);
+	}
+	return ERR_TIMED_OUT;
+}
+
+void hdmi_vco_disable(void)
+{
+        writel(0x0, HDMI_PLL_BASE + HDMI_UNI_PLL_GLB_CFG);
+        udelay(5);
+        writel(0x0, HDMI_PHY_BASE + HDMI_PHY_GLB_CFG);
+}
+
+int hdmi_vco_enable(void)
+{
+        /* Global Enable */
+        writel(0x81, HDMI_PHY_BASE + HDMI_PHY_GLB_CFG);
+        /* Power up power gen */
+        writel(0x00, HDMI_PHY_BASE + HDMI_PHY_PD_CTRL0);
+        udelay(350);
+
+        /* PLL Power-Up */
+        writel(0x01, HDMI_PLL_BASE + HDMI_UNI_PLL_GLB_CFG);
+        udelay(5);
+
+        /* Power up PLL LDO */
+        writel(0x03, HDMI_PLL_BASE + HDMI_UNI_PLL_GLB_CFG);
+        udelay(350);
+
+        /* PLL Power-Up */
+        writel(0x0F, HDMI_PLL_BASE + HDMI_UNI_PLL_GLB_CFG);
+        udelay(350);
+
+        /* poll for PLL ready status */
+        if (hdmi_poll_status(HDMI_PLL_BASE + HDMI_UNI_PLL_STATUS)) {
+                dprintf(CRITICAL, "%s: hdmi phy pll failed to Lock\n",
+                       __func__);
+                hdmi_vco_disable();
+                return ERROR;
+        }
+
+        udelay(350);
+        /* poll for PHY ready status */
+        if (hdmi_poll_status(HDMI_PHY_BASE + HDMI_PHY_STATUS)) {
+                dprintf(CRITICAL, "%s: hdmi phy failed to Lock\n",
+                       __func__);
+                hdmi_vco_disable();
+                return ERROR;
+        }
+
+        return NO_ERROR;
+}
+
+uint32_t hdmi_pll_config(void)
+{
+	writel(0x81, HDMI_PHY_BASE + HDMI_PHY_GLB_CFG);
+	writel(0x01, HDMI_PLL_BASE + HDMI_UNI_PLL_GLB_CFG);
+	writel(0x01, HDMI_PLL_BASE + HDMI_UNI_PLL_REFCLK_CFG);
+	writel(0x19, HDMI_PLL_BASE + HDMI_UNI_PLL_VCOLPF_CFG);
+	writel(0x0E, HDMI_PLL_BASE + HDMI_UNI_PLL_LPFR_CFG);
+	writel(0x20, HDMI_PLL_BASE + HDMI_UNI_PLL_LPFC1_CFG);
+	writel(0x0D, HDMI_PLL_BASE + HDMI_UNI_PLL_LPFC2_CFG);
+	writel(0x00, HDMI_PLL_BASE + HDMI_UNI_PLL_SDM_CFG0);
+	writel(0x52, HDMI_PLL_BASE + HDMI_UNI_PLL_SDM_CFG1);
+	writel(0x00, HDMI_PLL_BASE + HDMI_UNI_PLL_SDM_CFG2);
+	writel(0x56, HDMI_PLL_BASE + HDMI_UNI_PLL_SDM_CFG3);
+	writel(0x00, HDMI_PLL_BASE + HDMI_UNI_PLL_SDM_CFG4);
+	writel(0x10, HDMI_PLL_BASE + HDMI_UNI_PLL_LKDET_CFG0);
+	writel(0x1A, HDMI_PLL_BASE + HDMI_UNI_PLL_LKDET_CFG1);
+	writel(0x05, HDMI_PLL_BASE + HDMI_UNI_PLL_LKDET_CFG2);
+	writel(0x01, HDMI_PLL_BASE + HDMI_UNI_PLL_POSTDIV1_CFG);
+	writel(0x00, HDMI_PLL_BASE + HDMI_UNI_PLL_POSTDIV2_CFG);
+	writel(0x00, HDMI_PLL_BASE + HDMI_UNI_PLL_POSTDIV3_CFG);
+	writel(0x01, HDMI_PLL_BASE + HDMI_UNI_PLL_CAL_CFG2);
+	writel(0x60, HDMI_PLL_BASE + HDMI_UNI_PLL_CAL_CFG8);
+	writel(0x00, HDMI_PLL_BASE + HDMI_UNI_PLL_CAL_CFG9);
+	writel(0xE6, HDMI_PLL_BASE + HDMI_UNI_PLL_CAL_CFG10);
+	writel(0x02, HDMI_PLL_BASE + HDMI_UNI_PLL_CAL_CFG11);
+	writel(0x1F, HDMI_PHY_BASE + HDMI_PHY_PD_CTRL0);
+	udelay(50);
+
+	writel(0x0F, HDMI_PLL_BASE + HDMI_UNI_PLL_GLB_CFG);
+	writel(0x00, HDMI_PHY_BASE + HDMI_PHY_PD_CTRL1);
+	writel(0x10, HDMI_PHY_BASE + HDMI_PHY_ANA_CFG2);
+	writel(0xDB, HDMI_PHY_BASE + HDMI_PHY_ANA_CFG0);
+	writel(0x43, HDMI_PHY_BASE + HDMI_PHY_ANA_CFG1);
+	writel(0x02, HDMI_PHY_BASE + HDMI_PHY_ANA_CFG2);
+	writel(0x00, HDMI_PHY_BASE + HDMI_PHY_ANA_CFG3);
+	writel(0x04, HDMI_PLL_BASE + HDMI_UNI_PLL_VREG_CFG);
+	writel(0xD0, HDMI_PHY_BASE + HDMI_PHY_DCC_CFG0);
+	writel(0x1A, HDMI_PHY_BASE + HDMI_PHY_DCC_CFG1);
+	writel(0x00, HDMI_PHY_BASE + HDMI_PHY_TXCAL_CFG0);
+	writel(0x00, HDMI_PHY_BASE + HDMI_PHY_TXCAL_CFG1);
+	writel(0x02, HDMI_PHY_BASE + HDMI_PHY_TXCAL_CFG2);
+	writel(0x05, HDMI_PHY_BASE + HDMI_PHY_TXCAL_CFG3);
+	udelay(200);
+}
+