clk: qcom: mdss: add support for HDMI pll on 8996

Added support for new HDMI pll present on 8996. Implemented dynamic
calculator for pll settings.

Change-Id: Ib0b728d9ffb44b753657292e387ee7b44e854122
Signed-off-by: Vinu Deokaran <vinud@codeaurora.org>
diff --git a/drivers/clk/qcom/mdss/Makefile b/drivers/clk/qcom/mdss/Makefile
index 373cf45..011f5e0 100644
--- a/drivers/clk/qcom/mdss/Makefile
+++ b/drivers/clk/qcom/mdss/Makefile
@@ -7,3 +7,4 @@
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-edp-pll-28hpm.o
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-hdmi-pll-28hpm.o
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-hdmi-pll-20nm.o
+obj-$(CONFIG_MSM_MDSS_PLL) += mdss-hdmi-pll-14nm.o
diff --git a/drivers/clk/qcom/mdss/mdss-hdmi-pll-14nm.c b/drivers/clk/qcom/mdss/mdss-hdmi-pll-14nm.c
new file mode 100644
index 0000000..87e68a5
--- /dev/null
+++ b/drivers/clk/qcom/mdss/mdss-hdmi-pll-14nm.c
@@ -0,0 +1,1644 @@
+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/clk/msm-clk-provider.h>
+#include <linux/clk/msm-clk.h>
+#include <linux/clk/msm-clock-generic.h>
+#include <dt-bindings/clock/msm-clocks-8996.h>
+
+#include "mdss-pll.h"
+#include "mdss-hdmi-pll.h"
+
+/* CONSTANTS */
+#define HDMI_BIT_CLK_TO_PIX_CLK_RATIO            10
+#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD         3400000000
+#define HDMI_CLKS_PLL_DIVSEL                     0
+#define HDMI_CORECLK_DIV                         5
+#define HDMI_REF_CLOCK                           19200000
+#define HDMI_64B_ERR_VAL                         0xFFFFFFFFFFFFFFFF
+
+#define HDMI_2000MHZ_BIT_CLK_HZ                  2000000000
+#define HDMI_1334MHZ_BIT_CLK_HZ                  1334000000
+#define HDMI_1000MHZ_BIT_CLK_HZ                  1000000000
+#define HDMI_667MHZ_BIT_CLK_HZ                   667000000
+#define HDMI_500MHZ_BIT_CLK_HZ                   500000000
+#define HDMI_334MHZ_BIT_CLK_HZ                   334000000
+#define HDMI_250MHZ_BIT_CLK_HZ                   250000000
+
+/* PLL REGISTERS */
+#define QSERDES_COM_ATB_SEL1                     (0x000)
+#define QSERDES_COM_ATB_SEL2                     (0x004)
+#define QSERDES_COM_FREQ_UPDATE                  (0x008)
+#define QSERDES_COM_BG_TIMER                     (0x00C)
+#define QSERDES_COM_SSC_EN_CENTER                (0x010)
+#define QSERDES_COM_SSC_ADJ_PER1                 (0x014)
+#define QSERDES_COM_SSC_ADJ_PER2                 (0x018)
+#define QSERDES_COM_SSC_PER1                     (0x01C)
+#define QSERDES_COM_SSC_PER2                     (0x020)
+#define QSERDES_COM_SSC_STEP_SIZE1               (0x024)
+#define QSERDES_COM_SSC_STEP_SIZE2               (0x028)
+#define QSERDES_COM_POST_DIV                     (0x02C)
+#define QSERDES_COM_POST_DIV_MUX                 (0x030)
+#define QSERDES_COM_BIAS_EN_CLKBUFLR_EN          (0x034)
+#define QSERDES_COM_CLK_ENABLE1                  (0x038)
+#define QSERDES_COM_SYS_CLK_CTRL                 (0x03C)
+#define QSERDES_COM_SYSCLK_BUF_ENBALE            (0x040)
+#define QSERDES_COM_PLL_EN                       (0x044)
+#define QSERDES_COM_PLL_IVCO                     (0x048)
+#define QSERDES_COM_LOCK_CMP1_MODE0              (0x04C)
+#define QSERDES_COM_LOCK_CMP2_MODE0              (0x050)
+#define QSERDES_COM_LOCK_CMP3_MODE0              (0x054)
+#define QSERDES_COM_LOCK_CMP1_MODE1              (0x058)
+#define QSERDES_COM_LOCK_CMP2_MODE1              (0x05C)
+#define QSERDES_COM_LOCK_CMP3_MODE1              (0x060)
+#define QSERDES_COM_LOCK_CMP1_MODE2              (0x064)
+#define QSERDES_COM_LOCK_CMP2_MODE2              (0x068)
+#define QSERDES_COM_LOCK_CMP3_MODE2              (0x06C)
+#define QSERDES_COM_BG_TRIM                      (0x070)
+#define QSERDES_COM_CLK_EP_DIV                   (0x074)
+#define QSERDES_COM_CP_CTRL_MODE0                (0x078)
+#define QSERDES_COM_CP_CTRL_MODE1                (0x07C)
+#define QSERDES_COM_CP_CTRL_MODE2                (0x080)
+#define QSERDES_COM_PLL_RCTRL_MODE0              (0x084)
+#define QSERDES_COM_PLL_RCTRL_MODE1              (0x088)
+#define QSERDES_COM_PLL_RCTRL_MODE2              (0x08C)
+#define QSERDES_COM_PLL_CCTRL_MODE0              (0x090)
+#define QSERDES_COM_PLL_CCTRL_MODE1              (0x094)
+#define QSERDES_COM_PLL_CCTRL_MODE2              (0x098)
+#define QSERDES_COM_PLL_CNTRL                    (0x09C)
+#define QSERDES_COM_PHASE_SEL_CTRL               (0x0A0)
+#define QSERDES_COM_PHASE_SEL_DC                 (0x0A4)
+#define QSERDES_COM_CORE_CLK_IN_SYNC_SEL         (0x0A8)
+#define QSERDES_COM_SYSCLK_EN_SEL                (0x0AC)
+#define QSERDES_COM_CML_SYSCLK_SEL               (0x0B0)
+#define QSERDES_COM_RESETSM_CNTRL                (0x0B4)
+#define QSERDES_COM_RESETSM_CNTRL2               (0x0B8)
+#define QSERDES_COM_RESTRIM_CTRL                 (0x0BC)
+#define QSERDES_COM_RESTRIM_CTRL2                (0x0C0)
+#define QSERDES_COM_RESCODE_DIV_NUM              (0x0C4)
+#define QSERDES_COM_LOCK_CMP_EN                  (0x0C8)
+#define QSERDES_COM_LOCK_CMP_CFG                 (0x0CC)
+#define QSERDES_COM_DEC_START_MODE0              (0x0D0)
+#define QSERDES_COM_DEC_START_MODE1              (0x0D4)
+#define QSERDES_COM_DEC_START_MODE2              (0x0D8)
+#define QSERDES_COM_DIV_FRAC_START1_MODE0        (0x0DC)
+#define QSERDES_COM_DIV_FRAC_START2_MODE0        (0x0E0)
+#define QSERDES_COM_DIV_FRAC_START3_MODE0        (0x0E4)
+#define QSERDES_COM_DIV_FRAC_START1_MODE1        (0x0E8)
+#define QSERDES_COM_DIV_FRAC_START2_MODE1        (0x0EC)
+#define QSERDES_COM_DIV_FRAC_START3_MODE1        (0x0F0)
+#define QSERDES_COM_DIV_FRAC_START1_MODE2        (0x0F4)
+#define QSERDES_COM_DIV_FRAC_START2_MODE2        (0x0F8)
+#define QSERDES_COM_DIV_FRAC_START3_MODE2        (0x0FC)
+#define QSERDES_COM_INTEGLOOP_INITVAL            (0x100)
+#define QSERDES_COM_INTEGLOOP_EN                 (0x104)
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE0        (0x108)
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE0        (0x10C)
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE1        (0x110)
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE1        (0x114)
+#define QSERDES_COM_INTEGLOOP_GAIN0_MODE2        (0x118)
+#define QSERDES_COM_INTEGLOOP_GAIN1_MODE2        (0x11C)
+#define QSERDES_COM_RES_TRIM_CONTROL2            (0x120)
+#define QSERDES_COM_VCO_TUNE_CTRL                (0x124)
+#define QSERDES_COM_VCO_TUNE_MAP                 (0x128)
+#define QSERDES_COM_VCO_TUNE1_MODE0              (0x12C)
+#define QSERDES_COM_VCO_TUNE2_MODE0              (0x130)
+#define QSERDES_COM_VCO_TUNE1_MODE1              (0x134)
+#define QSERDES_COM_VCO_TUNE2_MODE1              (0x138)
+#define QSERDES_COM_VCO_TUNE1_MODE2              (0x13C)
+#define QSERDES_COM_VCO_TUNE2_MODE2              (0x140)
+#define QSERDES_COM_VCO_TUNE_TIMER1              (0x144)
+#define QSERDES_COM_VCO_TUNE_TIMER2              (0x148)
+#define QSERDES_COM_SAR                          (0x14C)
+#define QSERDES_COM_SAR_CLK                      (0x150)
+#define QSERDES_COM_SAR_CODE_OUT_STATUS          (0x154)
+#define QSERDES_COM_SAR_CODE_READY_STATUS        (0x158)
+#define QSERDES_COM_CMN_STATUS                   (0x15C)
+#define QSERDES_COM_RESET_SM_STATUS              (0x160)
+#define QSERDES_COM_RESTRIM_CODE_STATUS          (0x164)
+#define QSERDES_COM_PLLCAL_CODE1_STATUS          (0x168)
+#define QSERDES_COM_PLLCAL_CODE2_STATUS          (0x16C)
+#define QSERDES_COM_BG_CTRL                      (0x170)
+#define QSERDES_COM_CLK_SELECT                   (0x174)
+#define QSERDES_COM_HSCLK_SEL                    (0x178)
+#define QSERDES_COM_INTEGLOOP_BINCODE_STATUS     (0x17C)
+#define QSERDES_COM_PLL_ANALOG                   (0x180)
+#define QSERDES_COM_CORECLK_DIV                  (0x184)
+#define QSERDES_COM_SW_RESET                     (0x188)
+#define QSERDES_COM_CORE_CLK_EN                  (0x18C)
+#define QSERDES_COM_C_READY_STATUS               (0x190)
+#define QSERDES_COM_CMN_CONFIG                   (0x194)
+#define QSERDES_COM_CMN_RATE_OVERRIDE            (0x198)
+#define QSERDES_COM_SVS_MODE_CLK_SEL             (0x19C)
+#define QSERDES_COM_DEBUG_BUS0                   (0x1A0)
+#define QSERDES_COM_DEBUG_BUS1                   (0x1A4)
+#define QSERDES_COM_DEBUG_BUS2                   (0x1A8)
+#define QSERDES_COM_DEBUG_BUS3                   (0x1AC)
+#define QSERDES_COM_DEBUG_BUS_SEL                (0x1B0)
+#define QSERDES_COM_CMN_MISC1                    (0x1B4)
+#define QSERDES_COM_CMN_MISC2                    (0x1B8)
+#define QSERDES_COM_CORECLK_DIV_MODE1            (0x1BC)
+#define QSERDES_COM_CORECLK_DIV_MODE2            (0x1C0)
+
+/* Tx Channel base addresses */
+#define HDMI_TX_L0_BASE_OFFSET                   (0x400)
+#define HDMI_TX_L1_BASE_OFFSET                   (0x600)
+#define HDMI_TX_L2_BASE_OFFSET                   (0x800)
+#define HDMI_TX_L3_BASE_OFFSET                   (0xA00)
+
+/* Tx Channel PHY registers */
+#define QSERDES_TX_L0_BIST_MODE_LANENO                    (0x000)
+#define QSERDES_TX_L0_BIST_INVERT                         (0x004)
+#define QSERDES_TX_L0_CLKBUF_ENABLE                       (0x008)
+#define QSERDES_TX_L0_CMN_CONTROL_ONE                     (0x00C)
+#define QSERDES_TX_L0_CMN_CONTROL_TWO                     (0x010)
+#define QSERDES_TX_L0_CMN_CONTROL_THREE                   (0x014)
+#define QSERDES_TX_L0_TX_EMP_POST1_LVL                    (0x018)
+#define QSERDES_TX_L0_TX_POST2_EMPH                       (0x01C)
+#define QSERDES_TX_L0_TX_BOOST_LVL_UP_DN                  (0x020)
+#define QSERDES_TX_L0_HP_PD_ENABLES                       (0x024)
+#define QSERDES_TX_L0_TX_IDLE_LVL_LARGE_AMP               (0x028)
+#define QSERDES_TX_L0_TX_DRV_LVL                          (0x02C)
+#define QSERDES_TX_L0_TX_DRV_LVL_OFFSET                   (0x030)
+#define QSERDES_TX_L0_RESET_TSYNC_EN                      (0x034)
+#define QSERDES_TX_L0_PRE_STALL_LDO_BOOST_EN              (0x038)
+#define QSERDES_TX_L0_TX_BAND                             (0x03C)
+#define QSERDES_TX_L0_SLEW_CNTL                           (0x040)
+#define QSERDES_TX_L0_INTERFACE_SELECT                    (0x044)
+#define QSERDES_TX_L0_LPB_EN                              (0x048)
+#define QSERDES_TX_L0_RES_CODE_LANE_TX                    (0x04C)
+#define QSERDES_TX_L0_RES_CODE_LANE_RX                    (0x050)
+#define QSERDES_TX_L0_RES_CODE_LANE_OFFSET                (0x054)
+#define QSERDES_TX_L0_PERL_LENGTH1                        (0x058)
+#define QSERDES_TX_L0_PERL_LENGTH2                        (0x05C)
+#define QSERDES_TX_L0_SERDES_BYP_EN_OUT                   (0x060)
+#define QSERDES_TX_L0_DEBUG_BUS_SEL                       (0x064)
+#define QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN    (0x068)
+#define QSERDES_TX_L0_TX_POL_INV                          (0x06C)
+#define QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN          (0x070)
+#define QSERDES_TX_L0_BIST_PATTERN1                       (0x074)
+#define QSERDES_TX_L0_BIST_PATTERN2                       (0x078)
+#define QSERDES_TX_L0_BIST_PATTERN3                       (0x07C)
+#define QSERDES_TX_L0_BIST_PATTERN4                       (0x080)
+#define QSERDES_TX_L0_BIST_PATTERN5                       (0x084)
+#define QSERDES_TX_L0_BIST_PATTERN6                       (0x088)
+#define QSERDES_TX_L0_BIST_PATTERN7                       (0x08C)
+#define QSERDES_TX_L0_BIST_PATTERN8                       (0x090)
+#define QSERDES_TX_L0_LANE_MODE                           (0x094)
+#define QSERDES_TX_L0_IDAC_CAL_LANE_MODE                  (0x098)
+#define QSERDES_TX_L0_IDAC_CAL_LANE_MODE_CONFIGURATION    (0x09C)
+#define QSERDES_TX_L0_ATB_SEL1                            (0x0A0)
+#define QSERDES_TX_L0_ATB_SEL2                            (0x0A4)
+#define QSERDES_TX_L0_RCV_DETECT_LVL                      (0x0A8)
+#define QSERDES_TX_L0_RCV_DETECT_LVL_2                    (0x0AC)
+#define QSERDES_TX_L0_PRBS_SEED1                          (0x0B0)
+#define QSERDES_TX_L0_PRBS_SEED2                          (0x0B4)
+#define QSERDES_TX_L0_PRBS_SEED3                          (0x0B8)
+#define QSERDES_TX_L0_PRBS_SEED4                          (0x0BC)
+#define QSERDES_TX_L0_RESET_GEN                           (0x0C0)
+#define QSERDES_TX_L0_RESET_GEN_MUXES                     (0x0C4)
+#define QSERDES_TX_L0_TRAN_DRVR_EMP_EN                    (0x0C8)
+#define QSERDES_TX_L0_TX_INTERFACE_MODE                   (0x0CC)
+#define QSERDES_TX_L0_PWM_CTRL                            (0x0D0)
+#define QSERDES_TX_L0_PWM_ENCODED_OR_DATA                 (0x0D4)
+#define QSERDES_TX_L0_PWM_GEAR_1_DIVIDER_BAND2            (0x0D8)
+#define QSERDES_TX_L0_PWM_GEAR_2_DIVIDER_BAND2            (0x0DC)
+#define QSERDES_TX_L0_PWM_GEAR_3_DIVIDER_BAND2            (0x0E0)
+#define QSERDES_TX_L0_PWM_GEAR_4_DIVIDER_BAND2            (0x0E4)
+#define QSERDES_TX_L0_PWM_GEAR_1_DIVIDER_BAND0_1          (0x0E8)
+#define QSERDES_TX_L0_PWM_GEAR_2_DIVIDER_BAND0_1          (0x0EC)
+#define QSERDES_TX_L0_PWM_GEAR_3_DIVIDER_BAND0_1          (0x0F0)
+#define QSERDES_TX_L0_PWM_GEAR_4_DIVIDER_BAND0_1          (0x0F4)
+#define QSERDES_TX_L0_VMODE_CTRL1                         (0x0F8)
+#define QSERDES_TX_L0_VMODE_CTRL2                         (0x0FC)
+#define QSERDES_TX_L0_TX_ALOG_INTF_OBSV_CNTL              (0x100)
+#define QSERDES_TX_L0_BIST_STATUS                         (0x104)
+#define QSERDES_TX_L0_BIST_ERROR_COUNT1                   (0x108)
+#define QSERDES_TX_L0_BIST_ERROR_COUNT2                   (0x10C)
+#define QSERDES_TX_L0_TX_ALOG_INTF_OBSV                   (0x110)
+
+/* HDMI PHY REGISTERS */
+#define HDMI_PHY_BASE_OFFSET                  (0xC00)
+
+#define HDMI_PHY_CFG                          (0x00)
+#define HDMI_PHY_PD_CTL                       (0x04)
+#define HDMI_PHY_MODE                         (0x08)
+#define HDMI_PHY_MISR_CLEAR                   (0x0C)
+#define HDMI_PHY_TX0_TX1_BIST_CFG0            (0x10)
+#define HDMI_PHY_TX0_TX1_BIST_CFG1            (0x14)
+#define HDMI_PHY_TX0_TX1_PRBS_SEED_BYTE0      (0x18)
+#define HDMI_PHY_TX0_TX1_PRBS_SEED_BYTE1      (0x1C)
+#define HDMI_PHY_TX0_TX1_BIST_PATTERN0        (0x20)
+#define HDMI_PHY_TX0_TX1_BIST_PATTERN1        (0x24)
+#define HDMI_PHY_TX2_TX3_BIST_CFG0            (0x28)
+#define HDMI_PHY_TX2_TX3_BIST_CFG1            (0x2C)
+#define HDMI_PHY_TX2_TX3_PRBS_SEED_BYTE0      (0x30)
+#define HDMI_PHY_TX2_TX3_PRBS_SEED_BYTE1      (0x34)
+#define HDMI_PHY_TX2_TX3_BIST_PATTERN0        (0x38)
+#define HDMI_PHY_TX2_TX3_BIST_PATTERN1        (0x3C)
+#define HDMI_PHY_DEBUG_BUS_SEL                (0x40)
+#define HDMI_PHY_TXCAL_CFG0                   (0x44)
+#define HDMI_PHY_TXCAL_CFG1                   (0x48)
+#define HDMI_PHY_TX0_TX1_LANE_CTL             (0x4C)
+#define HDMI_PHY_TX2_TX3_LANE_CTL             (0x50)
+#define HDMI_PHY_LANE_BIST_CONFIG             (0x54)
+#define HDMI_PHY_CLOCK                        (0x58)
+#define HDMI_PHY_MISC1                        (0x5C)
+#define HDMI_PHY_MISC2                        (0x60)
+#define HDMI_PHY_TX0_TX1_BIST_STATUS0         (0x64)
+#define HDMI_PHY_TX0_TX1_BIST_STATUS1         (0x68)
+#define HDMI_PHY_TX0_TX1_BIST_STATUS2         (0x6C)
+#define HDMI_PHY_TX2_TX3_BIST_STATUS0         (0x70)
+#define HDMI_PHY_TX2_TX3_BIST_STATUS1         (0x74)
+#define HDMI_PHY_TX2_TX3_BIST_STATUS2         (0x78)
+#define HDMI_PHY_PRE_MISR_STATUS0             (0x7C)
+#define HDMI_PHY_PRE_MISR_STATUS1             (0x80)
+#define HDMI_PHY_PRE_MISR_STATUS2             (0x84)
+#define HDMI_PHY_PRE_MISR_STATUS3             (0x88)
+#define HDMI_PHY_POST_MISR_STATUS0            (0x8C)
+#define HDMI_PHY_POST_MISR_STATUS1            (0x90)
+#define HDMI_PHY_POST_MISR_STATUS2            (0x94)
+#define HDMI_PHY_POST_MISR_STATUS3            (0x98)
+#define HDMI_PHY_STATUS                       (0x9C)
+#define HDMI_PHY_MISC3_STATUS                 (0xA0)
+#define HDMI_PHY_MISC4_STATUS                 (0xA4)
+#define HDMI_PHY_DEBUG_BUS0                   (0xA8)
+#define HDMI_PHY_DEBUG_BUS1                   (0xAC)
+#define HDMI_PHY_DEBUG_BUS2                   (0xB0)
+#define HDMI_PHY_DEBUG_BUS3                   (0xB4)
+#define HDMI_PHY_PHY_REVISION_ID0             (0xB8)
+#define HDMI_PHY_PHY_REVISION_ID1             (0xBC)
+#define HDMI_PHY_PHY_REVISION_ID2             (0xC0)
+#define HDMI_PHY_PHY_REVISION_ID3             (0xC4)
+
+#define HDMI_PLL_POLL_MAX_READS                2500
+#define HDMI_PLL_POLL_TIMEOUT_US               50
+
+enum hdmi_pll_freqs {
+	HDMI_PCLK_25200_KHZ,
+	HDMI_PCLK_27027_KHZ,
+	HDMI_PCLK_27000_KHZ,
+	HDMI_PCLK_74250_KHZ,
+	HDMI_PCLK_148500_KHZ,
+	HDMI_PCLK_154000_KHZ,
+	HDMI_PCLK_268500_KHZ,
+	HDMI_PCLK_297000_KHZ,
+	HDMI_PCLK_594000_KHZ,
+	HDMI_PCLK_MAX
+};
+
+struct hdmi_14nm_phy_pll_reg_cfg {
+	u32 tx_l0_tx_band;
+	u32 tx_l1_tx_band;
+	u32 tx_l2_tx_band;
+	u32 tx_l3_tx_band;
+	u32 com_svs_mode_clk_sel;
+	u32 com_hsclk_sel;
+	u32 com_pll_cctrl_mode0;
+	u32 com_pll_rctrl_mode0;
+	u32 com_cp_ctrl_mode0;
+	u32 com_dec_start_mode0;
+	u32 com_div_frac_start1_mode0;
+	u32 com_div_frac_start2_mode0;
+	u32 com_div_frac_start3_mode0;
+	u32 com_integloop_gain0_mode0;
+	u32 com_integloop_gain1_mode0;
+	u32 com_lock_cmp1_mode0;
+	u32 com_lock_cmp2_mode0;
+	u32 com_lock_cmp3_mode0;
+	u32 com_core_clk_en;
+	u32 com_coreclk_div;
+
+	u32 tx_l0_tx_drv_lvl;
+	u32 tx_l0_tx_emp_post1_lvl;
+	u32 tx_l1_tx_drv_lvl;
+	u32 tx_l1_tx_emp_post1_lvl;
+	u32 tx_l2_tx_drv_lvl;
+	u32 tx_l2_tx_emp_post1_lvl;
+	u32 tx_l3_tx_drv_lvl;
+	u32 tx_l3_tx_emp_post1_lvl;
+	u32 tx_l0_vmode_ctrl1;
+	u32 tx_l0_vmode_ctrl2;
+	u32 tx_l1_vmode_ctrl1;
+	u32 tx_l1_vmode_ctrl2;
+	u32 tx_l2_vmode_ctrl1;
+	u32 tx_l2_vmode_ctrl2;
+	u32 tx_l3_vmode_ctrl1;
+	u32 tx_l3_vmode_ctrl2;
+
+	u32 phy_mode;
+};
+
+static const u32 supported_freq_lut[HDMI_PCLK_MAX] = {
+	25200000,
+	27000000,
+	27027000,
+	74250000,
+	148500000,
+	154000000,
+	268500000,
+	297000000,
+	594000000
+};
+
+static const struct hdmi_14nm_phy_pll_reg_cfg reg_cfg_lut[HDMI_PCLK_MAX] = {
+
+	/* 25200 KHz */
+	{
+		.tx_l0_tx_band                  = 0x7,
+		.tx_l1_tx_band                  = 0x7,
+		.tx_l2_tx_band                  = 0x7,
+		.tx_l3_tx_band                  = 0x7,
+		.com_svs_mode_clk_sel           = 0x0,
+		.com_hsclk_sel                  = 0x2B,
+		.com_pll_cctrl_mode0            = 0x1,
+		.com_pll_rctrl_mode0            = 0x10,
+		.com_cp_ctrl_mode0              = 0x23,
+		.com_dec_start_mode0            = 0x69,
+		.com_div_frac_start1_mode0      = 0x0,
+		.com_div_frac_start2_mode0      = 0x0,
+		.com_div_frac_start3_mode0      = 0x0,
+		.com_integloop_gain0_mode0      = 0xC4,
+		.com_integloop_gain1_mode0      = 0x0,
+		.com_lock_cmp1_mode0            = 0xFF,
+		.com_lock_cmp2_mode0            = 0x29,
+		.com_lock_cmp3_mode0            = 0x0,
+		.com_core_clk_en                = 0x6C,
+		.com_coreclk_div                = 0x5,
+
+		.tx_l0_tx_drv_lvl               = 0x15,
+		.tx_l0_tx_emp_post1_lvl         = 0x10,
+		.tx_l1_tx_drv_lvl               = 0x15,
+		.tx_l1_tx_emp_post1_lvl         = 0x10,
+		.tx_l2_tx_drv_lvl               = 0x15,
+		.tx_l2_tx_emp_post1_lvl         = 0x10,
+		.tx_l3_tx_drv_lvl               = 0x15,
+		.tx_l3_tx_emp_post1_lvl         = 0x10,
+		.tx_l0_vmode_ctrl1              = 0x0,
+		.tx_l0_vmode_ctrl2              = 0xD,
+		.tx_l1_vmode_ctrl1              = 0x0,
+		.tx_l1_vmode_ctrl2              = 0xD,
+		.tx_l2_vmode_ctrl1              = 0x0,
+		.tx_l2_vmode_ctrl2              = 0xD,
+		.tx_l3_vmode_ctrl1              = 0x0,
+		.tx_l3_vmode_ctrl2              = 0xD,
+
+		.phy_mode                       = 0x0,
+	},
+	/* 27000 KHz */
+	{
+		.tx_l0_tx_band                  = 0x7,
+		.tx_l1_tx_band                  = 0x7,
+		.tx_l2_tx_band                  = 0x7,
+		.tx_l3_tx_band                  = 0x7,
+		.com_svs_mode_clk_sel           = 0x0,
+		.com_hsclk_sel                  = 0x2B,
+		.com_pll_cctrl_mode0            = 0x28,
+		.com_pll_rctrl_mode0            = 0x22,
+		.com_cp_ctrl_mode0              = 0xB,
+		.com_dec_start_mode0            = 0x70,
+		.com_div_frac_start1_mode0      = 0x0,
+		.com_div_frac_start2_mode0      = 0x0,
+		.com_div_frac_start3_mode0      = 0x8,
+		.com_integloop_gain0_mode0      = 0x80,
+		.com_integloop_gain1_mode0      = 0x0,
+		.com_lock_cmp1_mode0            = 0xFF,
+		.com_lock_cmp2_mode0            = 0x2C,
+		.com_lock_cmp3_mode0            = 0x0,
+		.com_core_clk_en                = 0x6C,
+		.com_coreclk_div                = 0x5,
+
+		.tx_l0_tx_drv_lvl               = 0x15,
+		.tx_l0_tx_emp_post1_lvl         = 0x10,
+		.tx_l1_tx_drv_lvl               = 0x15,
+		.tx_l1_tx_emp_post1_lvl         = 0x10,
+		.tx_l2_tx_drv_lvl               = 0x15,
+		.tx_l2_tx_emp_post1_lvl         = 0x10,
+		.tx_l3_tx_drv_lvl               = 0x15,
+		.tx_l3_tx_emp_post1_lvl         = 0x10,
+		.tx_l0_vmode_ctrl1              = 0x0,
+		.tx_l0_vmode_ctrl2              = 0xD,
+		.tx_l1_vmode_ctrl1              = 0x0,
+		.tx_l1_vmode_ctrl2              = 0xD,
+		.tx_l2_vmode_ctrl1              = 0x0,
+		.tx_l2_vmode_ctrl2              = 0xD,
+		.tx_l3_vmode_ctrl1              = 0x0,
+		.tx_l3_vmode_ctrl2              = 0xD,
+
+		.phy_mode                       = 0x0,
+	},
+	/* 27027 KHz */
+	{
+		.tx_l0_tx_band                  = 0x7,
+		.tx_l1_tx_band                  = 0x7,
+		.tx_l2_tx_band                  = 0x7,
+		.tx_l3_tx_band                  = 0x7,
+		.com_svs_mode_clk_sel           = 0x0,
+		.com_hsclk_sel                  = 0x2B,
+		.com_pll_cctrl_mode0            = 0x28,
+		.com_pll_rctrl_mode0            = 0x16,
+		.com_cp_ctrl_mode0              = 0xB,
+		.com_dec_start_mode0            = 0x70,
+		.com_div_frac_start1_mode0      = 0xCD,
+		.com_div_frac_start2_mode0      = 0xCC,
+		.com_div_frac_start3_mode0      = 0x9,
+		.com_integloop_gain0_mode0      = 0x80,
+		.com_integloop_gain1_mode0      = 0x0,
+		.com_lock_cmp1_mode0            = 0x0B,
+		.com_lock_cmp2_mode0            = 0x2D,
+		.com_lock_cmp3_mode0            = 0x0,
+		.com_core_clk_en                = 0x6C,
+		.com_coreclk_div                = 0x5,
+
+		.tx_l0_tx_drv_lvl               = 0x15,
+		.tx_l0_tx_emp_post1_lvl         = 0x10,
+		.tx_l1_tx_drv_lvl               = 0x15,
+		.tx_l1_tx_emp_post1_lvl         = 0x10,
+		.tx_l2_tx_drv_lvl               = 0x15,
+		.tx_l2_tx_emp_post1_lvl         = 0x10,
+		.tx_l3_tx_drv_lvl               = 0x15,
+		.tx_l3_tx_emp_post1_lvl         = 0x10,
+		.tx_l0_vmode_ctrl1              = 0x0,
+		.tx_l0_vmode_ctrl2              = 0xD,
+		.tx_l1_vmode_ctrl1              = 0x0,
+		.tx_l1_vmode_ctrl2              = 0xD,
+		.tx_l2_vmode_ctrl1              = 0x0,
+		.tx_l2_vmode_ctrl2              = 0xD,
+		.tx_l3_vmode_ctrl1              = 0x0,
+		.tx_l3_vmode_ctrl2              = 0xD,
+
+		.phy_mode                       = 0x0,
+	},
+	/* 74250 KHz */
+	{
+		.tx_l0_tx_band                  = 0x06,
+		.tx_l1_tx_band                  = 0x06,
+		.tx_l2_tx_band                  = 0x06,
+		.tx_l3_tx_band                  = 0x06,
+		.com_svs_mode_clk_sel           = 0x00,
+		.com_hsclk_sel                  = 0x2A,
+		.com_pll_cctrl_mode0            = 0x28,
+		.com_pll_rctrl_mode0            = 0x16,
+		.com_cp_ctrl_mode0              = 0x0B,
+		.com_dec_start_mode0            = 0x74,
+		.com_div_frac_start1_mode0      = 0x00,
+		.com_div_frac_start2_mode0      = 0x40,
+		.com_div_frac_start3_mode0      = 0x00,
+		.com_integloop_gain0_mode0      = 0x80,
+		.com_integloop_gain1_mode0      = 0x00,
+		.com_lock_cmp1_mode0            = 0xDF,
+		.com_lock_cmp2_mode0            = 0x3D,
+		.com_lock_cmp3_mode0            = 0x00,
+		.com_core_clk_en                = 0x6C,
+		.com_coreclk_div                = 0x05,
+
+		.tx_l0_tx_drv_lvl               = 0x15,
+		.tx_l0_tx_emp_post1_lvl         = 0x10,
+		.tx_l1_tx_drv_lvl               = 0x15,
+		.tx_l1_tx_emp_post1_lvl         = 0x10,
+		.tx_l2_tx_drv_lvl               = 0x15,
+		.tx_l2_tx_emp_post1_lvl         = 0x10,
+		.tx_l3_tx_drv_lvl               = 0x15,
+		.tx_l3_tx_emp_post1_lvl         = 0x10,
+		.tx_l0_vmode_ctrl1              = 0x00,
+		.tx_l0_vmode_ctrl2              = 0x0D,
+		.tx_l1_vmode_ctrl1              = 0x00,
+		.tx_l1_vmode_ctrl2              = 0x0D,
+		.tx_l2_vmode_ctrl1              = 0x00,
+		.tx_l2_vmode_ctrl2              = 0x0D,
+		.tx_l3_vmode_ctrl1              = 0x00,
+		.tx_l3_vmode_ctrl2              = 0x0D,
+
+		.phy_mode                       = 0x00,
+	},
+	/* 148500 KHz */
+	{
+		.tx_l0_tx_band                  = 0x05,
+		.tx_l1_tx_band                  = 0x05,
+		.tx_l2_tx_band                  = 0x05,
+		.tx_l3_tx_band                  = 0x05,
+		.com_svs_mode_clk_sel           = 0x00,
+		.com_hsclk_sel                  = 0x2A,
+		.com_pll_cctrl_mode0            = 0x28,
+		.com_pll_rctrl_mode0            = 0x16,
+		.com_cp_ctrl_mode0              = 0x0B,
+		.com_dec_start_mode0            = 0x74,
+		.com_div_frac_start1_mode0      = 0x00,
+		.com_div_frac_start2_mode0      = 0x40,
+		.com_div_frac_start3_mode0      = 0x00,
+		.com_integloop_gain0_mode0      = 0x80,
+		.com_integloop_gain1_mode0      = 0x00,
+		.com_lock_cmp1_mode0            = 0xDF,
+		.com_lock_cmp2_mode0            = 0x3D,
+		.com_lock_cmp3_mode0            = 0x00,
+		.com_core_clk_en                = 0x6C,
+		.com_coreclk_div                = 0x05,
+
+		.tx_l0_tx_drv_lvl               = 0x15,
+		.tx_l0_tx_emp_post1_lvl         = 0x10,
+		.tx_l1_tx_drv_lvl               = 0x15,
+		.tx_l1_tx_emp_post1_lvl         = 0x10,
+		.tx_l2_tx_drv_lvl               = 0x15,
+		.tx_l2_tx_emp_post1_lvl         = 0x10,
+		.tx_l3_tx_drv_lvl               = 0x15,
+		.tx_l3_tx_emp_post1_lvl         = 0x10,
+		.tx_l0_vmode_ctrl1              = 0x00,
+		.tx_l0_vmode_ctrl2              = 0x0D,
+		.tx_l1_vmode_ctrl1              = 0x00,
+		.tx_l1_vmode_ctrl2              = 0x0D,
+		.tx_l2_vmode_ctrl1              = 0x00,
+		.tx_l2_vmode_ctrl2              = 0x0D,
+		.tx_l3_vmode_ctrl1              = 0x00,
+		.tx_l3_vmode_ctrl2              = 0x0D,
+
+		.phy_mode                       = 0x00,
+	},
+	/* 154000 KHz */
+	{
+		.tx_l0_tx_band                  = 0x05,
+		.tx_l1_tx_band                  = 0x05,
+		.tx_l2_tx_band                  = 0x05,
+		.tx_l3_tx_band                  = 0x05,
+		.com_svs_mode_clk_sel           = 0x00,
+		.com_hsclk_sel                  = 0x2A,
+		.com_pll_cctrl_mode0            = 0x28,
+		.com_pll_rctrl_mode0            = 0x16,
+		.com_cp_ctrl_mode0              = 0x0B,
+		.com_dec_start_mode0            = 0x78,
+		.com_div_frac_start1_mode0      = 0x00,
+		.com_div_frac_start2_mode0      = 0x00,
+		.com_div_frac_start3_mode0      = 0x05,
+		.com_integloop_gain0_mode0      = 0x80,
+		.com_integloop_gain1_mode0      = 0x00,
+		.com_lock_cmp1_mode0            = 0x2A,
+		.com_lock_cmp2_mode0            = 0x40,
+		.com_lock_cmp3_mode0            = 0x00,
+		.com_core_clk_en                = 0x6C,
+		.com_coreclk_div                = 0x05,
+
+		.tx_l0_tx_drv_lvl               = 0x15,
+		.tx_l0_tx_emp_post1_lvl         = 0x10,
+		.tx_l1_tx_drv_lvl               = 0x15,
+		.tx_l1_tx_emp_post1_lvl         = 0x10,
+		.tx_l2_tx_drv_lvl               = 0x15,
+		.tx_l2_tx_emp_post1_lvl         = 0x10,
+		.tx_l3_tx_drv_lvl               = 0x15,
+		.tx_l3_tx_emp_post1_lvl         = 0x10,
+		.tx_l0_vmode_ctrl1              = 0x00,
+		.tx_l0_vmode_ctrl2              = 0x0D,
+		.tx_l1_vmode_ctrl1              = 0x00,
+		.tx_l1_vmode_ctrl2              = 0x0D,
+		.tx_l2_vmode_ctrl1              = 0x00,
+		.tx_l2_vmode_ctrl2              = 0x0D,
+		.tx_l3_vmode_ctrl1              = 0x00,
+		.tx_l3_vmode_ctrl2              = 0x0D,
+
+		.phy_mode                       = 0x00,
+	},
+	/* 268500 KHz */
+	{
+		.tx_l0_tx_band                  = 0x04,
+		.tx_l1_tx_band                  = 0x04,
+		.tx_l2_tx_band                  = 0x04,
+		.tx_l3_tx_band                  = 0x04,
+		.com_svs_mode_clk_sel           = 0x00,
+		.com_hsclk_sel                  = 0x2B,
+		.com_pll_cctrl_mode0            = 0x28,
+		.com_pll_rctrl_mode0            = 0x16,
+		.com_cp_ctrl_mode0              = 0x0B,
+		.com_dec_start_mode0            = 0x8B,
+		.com_div_frac_start1_mode0      = 0x00,
+		.com_div_frac_start2_mode0      = 0x80,
+		.com_div_frac_start3_mode0      = 0x0D,
+		.com_integloop_gain0_mode0      = 0x80,
+		.com_integloop_gain1_mode0      = 0x00,
+		.com_lock_cmp1_mode0            = 0xEF,
+		.com_lock_cmp2_mode0            = 0x37,
+		.com_lock_cmp3_mode0            = 0x00,
+		.com_core_clk_en                = 0x6C,
+		.com_coreclk_div                = 0x05,
+
+		.tx_l0_tx_drv_lvl               = 0x15,
+		.tx_l0_tx_emp_post1_lvl         = 0x10,
+		.tx_l1_tx_drv_lvl               = 0x15,
+		.tx_l1_tx_emp_post1_lvl         = 0x10,
+		.tx_l2_tx_drv_lvl               = 0x15,
+		.tx_l2_tx_emp_post1_lvl         = 0x10,
+		.tx_l3_tx_drv_lvl               = 0x15,
+		.tx_l3_tx_emp_post1_lvl         = 0x10,
+		.tx_l0_vmode_ctrl1              = 0x00,
+		.tx_l0_vmode_ctrl2              = 0x0D,
+		.tx_l1_vmode_ctrl1              = 0x00,
+		.tx_l1_vmode_ctrl2              = 0x0D,
+		.tx_l2_vmode_ctrl1              = 0x00,
+		.tx_l2_vmode_ctrl2              = 0x0D,
+		.tx_l3_vmode_ctrl1              = 0x00,
+		.tx_l3_vmode_ctrl2              = 0x0D,
+
+		.phy_mode                       = 0x00,
+	},
+	/* 297000 KHz */
+	{
+		.tx_l0_tx_band                  = 0x04,
+		.tx_l1_tx_band                  = 0x04,
+		.tx_l2_tx_band                  = 0x04,
+		.tx_l3_tx_band                  = 0x04,
+		.com_svs_mode_clk_sel           = 0x00,
+		.com_hsclk_sel                  = 0x2A,
+		.com_pll_cctrl_mode0            = 0x28,
+		.com_pll_rctrl_mode0            = 0x16,
+		.com_cp_ctrl_mode0              = 0x0B,
+		.com_dec_start_mode0            = 0x74,
+		.com_div_frac_start1_mode0      = 0x00,
+		.com_div_frac_start2_mode0      = 0x40,
+		.com_div_frac_start3_mode0      = 0x00,
+		.com_integloop_gain0_mode0      = 0x80,
+		.com_integloop_gain1_mode0      = 0x00,
+		.com_lock_cmp1_mode0            = 0xDF,
+		.com_lock_cmp2_mode0            = 0x3D,
+		.com_lock_cmp3_mode0            = 0x00,
+		.com_core_clk_en                = 0x6C,
+		.com_coreclk_div                = 0x05,
+
+		.tx_l0_tx_drv_lvl               = 0x15,
+		.tx_l0_tx_emp_post1_lvl         = 0x10,
+		.tx_l1_tx_drv_lvl               = 0x15,
+		.tx_l1_tx_emp_post1_lvl         = 0x10,
+		.tx_l2_tx_drv_lvl               = 0x15,
+		.tx_l2_tx_emp_post1_lvl         = 0x10,
+		.tx_l3_tx_drv_lvl               = 0x15,
+		.tx_l3_tx_emp_post1_lvl         = 0x10,
+		.tx_l0_vmode_ctrl1              = 0x00,
+		.tx_l0_vmode_ctrl2              = 0x0D,
+		.tx_l1_vmode_ctrl1              = 0x00,
+		.tx_l1_vmode_ctrl2              = 0x0D,
+		.tx_l2_vmode_ctrl1              = 0x00,
+		.tx_l2_vmode_ctrl2              = 0x0D,
+		.tx_l3_vmode_ctrl1              = 0x00,
+		.tx_l3_vmode_ctrl2              = 0x0D,
+
+		.phy_mode                       = 0x00,
+	},
+	/* 594000 KHz */
+	{
+		.tx_l0_tx_band                  = 0x04,
+		.tx_l1_tx_band                  = 0x04,
+		.tx_l2_tx_band                  = 0x04,
+		.tx_l3_tx_band                  = 0x04,
+		.com_svs_mode_clk_sel           = 0x00,
+		.com_hsclk_sel                  = 0x29,
+		.com_pll_cctrl_mode0            = 0x28,
+		.com_pll_rctrl_mode0            = 0x16,
+		.com_cp_ctrl_mode0              = 0x0B,
+		.com_dec_start_mode0            = 0x9A,
+		.com_div_frac_start1_mode0      = 0x00,
+		.com_div_frac_start2_mode0      = 0x00,
+		.com_div_frac_start3_mode0      = 0x0B,
+		.com_integloop_gain0_mode0      = 0x80,
+		.com_integloop_gain1_mode0      = 0x00,
+		.com_lock_cmp1_mode0            = 0xBF,
+		.com_lock_cmp2_mode0            = 0x7B,
+		.com_lock_cmp3_mode0            = 0x00,
+		.com_core_clk_en                = 0x6C,
+		.com_coreclk_div                = 0x05,
+
+		.tx_l0_tx_drv_lvl               = 0x19,
+		.tx_l0_tx_emp_post1_lvl         = 0x10,
+		.tx_l1_tx_drv_lvl               = 0x15,
+		.tx_l1_tx_emp_post1_lvl         = 0x10,
+		.tx_l2_tx_drv_lvl               = 0x15,
+		.tx_l2_tx_emp_post1_lvl         = 0x10,
+		.tx_l3_tx_drv_lvl               = 0x15,
+		.tx_l3_tx_emp_post1_lvl         = 0x10,
+		.tx_l0_vmode_ctrl1              = 0x00,
+		.tx_l0_vmode_ctrl2              = 0x0D,
+		.tx_l1_vmode_ctrl1              = 0x00,
+		.tx_l1_vmode_ctrl2              = 0x0D,
+		.tx_l2_vmode_ctrl1              = 0x00,
+		.tx_l2_vmode_ctrl2              = 0x0D,
+		.tx_l3_vmode_ctrl1              = 0x00,
+		.tx_l3_vmode_ctrl2              = 0x0D,
+
+		.phy_mode                       = 0x10,
+	},
+};
+
+static inline struct hdmi_pll_vco_clk *to_hdmi_14nm_vco_clk(struct clk *clk)
+{
+	return container_of(clk, struct hdmi_pll_vco_clk, c);
+}
+
+static inline u64 hdmi_14nm_get_post_div_lt_2g(u64 bclk)
+{
+	if (bclk >= HDMI_1334MHZ_BIT_CLK_HZ)
+		return 3;
+	else if (bclk >= HDMI_1000MHZ_BIT_CLK_HZ)
+		return 4;
+	else if (bclk >= HDMI_667MHZ_BIT_CLK_HZ)
+		return 3;
+	else if (bclk >= HDMI_500MHZ_BIT_CLK_HZ)
+		return 4;
+	else if (bclk >= HDMI_334MHZ_BIT_CLK_HZ)
+		return 3;
+	else if (bclk >= HDMI_250MHZ_BIT_CLK_HZ)
+		return 4;
+
+	return HDMI_64B_ERR_VAL;
+}
+
+static inline u64 hdmi_14nm_get_coreclk_div_lt_2g(u64 bclk)
+{
+	if (bclk >= HDMI_1334MHZ_BIT_CLK_HZ)
+		return 1;
+	else if (bclk >= HDMI_1000MHZ_BIT_CLK_HZ)
+		return 1;
+	else if (bclk >= HDMI_667MHZ_BIT_CLK_HZ)
+		return 2;
+	else if (bclk >= HDMI_500MHZ_BIT_CLK_HZ)
+		return 2;
+	else if (bclk >= HDMI_334MHZ_BIT_CLK_HZ)
+		return 3;
+	else if (bclk >= HDMI_250MHZ_BIT_CLK_HZ)
+		return 3;
+
+	return HDMI_64B_ERR_VAL;
+}
+
+static inline u64 hdmi_14nm_get_coreclk_div_ratio(u64 clks_pll_divsel,
+						  u64 coreclk_div)
+{
+	if (clks_pll_divsel == 0)
+		return coreclk_div*2;
+	else if (clks_pll_divsel == 1)
+		return coreclk_div*4;
+
+	return HDMI_64B_ERR_VAL;
+}
+
+static inline u64 hdmi_14nm_get_tx_band(u64 bclk)
+{
+	if (bclk >= HDMI_2000MHZ_BIT_CLK_HZ)
+		return 0;
+	if (bclk >= HDMI_1000MHZ_BIT_CLK_HZ)
+		return 1;
+	if (bclk >= HDMI_500MHZ_BIT_CLK_HZ)
+		return 2;
+	if (bclk >= HDMI_250MHZ_BIT_CLK_HZ)
+		return 3;
+
+	return HDMI_64B_ERR_VAL;
+}
+
+static inline u64 hdmi_14nm_get_hsclk(u64 fdata)
+{
+	if (fdata >= 8000000000)
+		return 0;
+	else if (fdata >= 4000000000)
+		return 1;
+	else if (fdata >= 2700000000)
+		return 2;
+	else if (fdata >= 2000000000)
+		return 3;
+
+	return HDMI_64B_ERR_VAL;
+}
+
+static inline u64 hdmi_14nm_get_cpctrl(u64 frac_start, bool gen_ssc)
+{
+	if ((frac_start != 0) ||
+	    (gen_ssc == true))
+		/*
+		 * This should be ROUND(11/(19.2/20))).
+		 * Since ref clock does not change, hardcoding to 11
+		 */
+		return 0xB;
+
+	return 0x23;
+}
+
+static inline u64 hdmi_14nm_get_rctrl(u64 frac_start, bool gen_ssc)
+{
+	if ((frac_start != 0) || (gen_ssc == true))
+		return 0x16;
+
+	return 0x10;
+}
+
+static inline u64 hdmi_14nm_get_cctrl(u64 frac_start, bool gen_ssc)
+{
+	if ((frac_start != 0) || (gen_ssc == true))
+		return 0x28;
+
+	return 0x1;
+}
+
+static inline u64 hdmi_14nm_get_integloop_gain(u64 frac_start, bool gen_ssc)
+{
+	if ((frac_start != 0) || (gen_ssc == true))
+		return 0x80;
+
+	return 0xC4;
+}
+
+static inline u64 hdmi_14nm_get_vco_tune(u64 fdata, u64 div)
+{
+	u64 vco_tune;
+
+	vco_tune = fdata * div;
+	do_div(vco_tune, 1000000);
+	vco_tune = 13000 - vco_tune - 256;
+	do_div(vco_tune, 5);
+
+	return vco_tune;
+}
+
+static inline u64 hdmi_14nm_get_pll_cmp(u64 pll_cmp_cnt, u64 core_clk)
+{
+	u64 pll_cmp;
+	u64 rem;
+
+	pll_cmp = pll_cmp_cnt * core_clk;
+	rem = do_div(pll_cmp, HDMI_REF_CLOCK);
+	if (rem > (HDMI_REF_CLOCK >> 1))
+		pll_cmp++;
+	pll_cmp -= 1;
+
+	return pll_cmp;
+}
+
+static int hdmi_14nm_calculate(u32 pix_clk,
+			       struct hdmi_14nm_phy_pll_reg_cfg *cfg)
+{
+	int rc = -EINVAL;
+	u64 fdata, clk_divtx, tmds_clk;
+	u64 bclk;
+	u64 post_div_gt_2g;
+	u64 post_div_lt_2g;
+	u64 coreclk_div1_lt_2g;
+	u64 core_clk_div_ratio;
+	u64 core_clk;
+	u64 pll_cmp;
+	u64 tx_band;
+	u64 tx_band_div_ratio;
+	u64 hsclk;
+	u64 dec_start;
+	u64 frac_start;
+	u64 pll_divisor = 4 * HDMI_REF_CLOCK;
+	u64 cpctrl;
+	u64 rctrl;
+	u64 cctrl;
+	u64 integloop_gain;
+	u64 vco_tune;
+	u64 vco_freq;
+	u64 rem;
+
+	/* FDATA, CLK_DIVTX, PIXEL_CLK, TMDS_CLK */
+	bclk = ((u64)pix_clk) * HDMI_BIT_CLK_TO_PIX_CLK_RATIO;
+
+	if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD)
+		tmds_clk = bclk/4;
+	else
+		tmds_clk = bclk;
+
+	post_div_lt_2g = hdmi_14nm_get_post_div_lt_2g(bclk);
+	if (post_div_lt_2g == HDMI_64B_ERR_VAL)
+		goto fail;
+
+	coreclk_div1_lt_2g = hdmi_14nm_get_coreclk_div_lt_2g(bclk);
+
+	core_clk_div_ratio = hdmi_14nm_get_coreclk_div_ratio(
+				HDMI_CLKS_PLL_DIVSEL, HDMI_CORECLK_DIV);
+
+	tx_band = hdmi_14nm_get_tx_band(bclk);
+	if (tx_band == HDMI_64B_ERR_VAL)
+		goto fail;
+
+	tx_band_div_ratio = 1 << tx_band;
+
+	if (bclk >= HDMI_2000MHZ_BIT_CLK_HZ) {
+		fdata = bclk;
+		hsclk = hdmi_14nm_get_hsclk(fdata);
+		if (hsclk == HDMI_64B_ERR_VAL)
+			goto fail;
+
+		post_div_gt_2g = (hsclk <= 3) ? (hsclk + 1) : HDMI_64B_ERR_VAL;
+		if (post_div_gt_2g == HDMI_64B_ERR_VAL)
+			goto fail;
+
+		vco_freq = bclk * (post_div_gt_2g * tx_band_div_ratio);
+		clk_divtx = vco_freq;
+		do_div(clk_divtx, post_div_gt_2g);
+	} else {
+		vco_freq = bclk * (post_div_lt_2g * tx_band_div_ratio);
+		fdata = vco_freq;
+		do_div(fdata, post_div_lt_2g);
+		hsclk = hdmi_14nm_get_hsclk(fdata);
+		if (hsclk == HDMI_64B_ERR_VAL)
+			goto fail;
+
+		clk_divtx = vco_freq;
+		do_div(clk_divtx, post_div_lt_2g);
+		post_div_gt_2g = (hsclk <= 3) ? (hsclk + 1) : HDMI_64B_ERR_VAL;
+		if (post_div_gt_2g == HDMI_64B_ERR_VAL)
+			goto fail;
+
+	}
+
+	/* Decimal and fraction values */
+	dec_start = fdata * post_div_gt_2g;
+	do_div(dec_start, pll_divisor);
+	frac_start = ((pll_divisor - (((dec_start + 1) * pll_divisor) -
+			(fdata * post_div_gt_2g))) * (1 << 20));
+	rem = do_div(frac_start, pll_divisor);
+	/* Round off frac_start to closest integer */
+	if (rem >= (pll_divisor >> 1))
+		frac_start++;
+
+	cpctrl = hdmi_14nm_get_cpctrl(frac_start, false);
+	rctrl = hdmi_14nm_get_rctrl(frac_start, false);
+	cctrl = hdmi_14nm_get_cctrl(frac_start, false);
+	integloop_gain = hdmi_14nm_get_integloop_gain(frac_start, false);
+	vco_tune = hdmi_14nm_get_vco_tune(fdata, post_div_gt_2g);
+
+	core_clk = clk_divtx;
+	do_div(core_clk, core_clk_div_ratio);
+	pll_cmp = hdmi_14nm_get_pll_cmp(1024, core_clk);
+
+	/* Debug dump */
+	pr_debug("%s: VCO freq: %llu\n", __func__, vco_freq);
+	pr_debug("%s: fdata: %llu\n", __func__, fdata);
+	pr_debug("%s: CLK_DIVTX: %llu\n", __func__, clk_divtx);
+	pr_debug("%s: pix_clk: %d\n", __func__, pix_clk);
+	pr_debug("%s: tmds clk: %llu\n", __func__, tmds_clk);
+	pr_debug("%s: HSCLK_SEL: %llu\n", __func__, hsclk);
+	pr_debug("%s: DEC_START: %llu\n", __func__, dec_start);
+	pr_debug("%s: DIV_FRAC_START: %llu\n", __func__, frac_start);
+	pr_debug("%s: PLL_CPCTRL: %llu\n", __func__, cpctrl);
+	pr_debug("%s: PLL_RCTRL: %llu\n", __func__, rctrl);
+	pr_debug("%s: PLL_CCTRL: %llu\n", __func__, cctrl);
+	pr_debug("%s: INTEGLOOP_GAIN: %llu\n", __func__, integloop_gain);
+	pr_debug("%s: VCO_TUNE: %llu\n", __func__, vco_tune);
+	pr_debug("%s: TX_BAND: %llu\n", __func__, tx_band);
+	pr_debug("%s: PLL_CMP: %llu\n", __func__, pll_cmp);
+
+	/* Convert these values to register specific values */
+	cfg->tx_l0_tx_band = tx_band + 4;
+	cfg->tx_l1_tx_band = tx_band + 4;
+	cfg->tx_l2_tx_band = tx_band + 4;
+	cfg->tx_l3_tx_band = tx_band + 4;
+
+	cfg->com_svs_mode_clk_sel = 0;
+	cfg->com_hsclk_sel = (0x28 | hsclk);
+	cfg->com_pll_cctrl_mode0 = cctrl;
+	cfg->com_pll_rctrl_mode0 = rctrl;
+	cfg->com_cp_ctrl_mode0 = cpctrl;
+	cfg->com_dec_start_mode0 = dec_start;
+	cfg->com_div_frac_start1_mode0 = (frac_start & 0xFF);
+	cfg->com_div_frac_start2_mode0 = ((frac_start & 0xFF00) >> 8);
+	cfg->com_div_frac_start3_mode0 = ((frac_start & 0xF0000) >> 16);
+	cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xFF);
+	cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xF00) >> 8);
+	cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xFF);
+	cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xFF00) >> 8);
+	cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16);
+	cfg->com_core_clk_en = (0x6C | (HDMI_CLKS_PLL_DIVSEL << 4));
+	cfg->com_coreclk_div = HDMI_CORECLK_DIV;
+
+	if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) {
+		cfg->tx_l0_tx_drv_lvl = 0x19;
+		cfg->tx_l0_tx_emp_post1_lvl = 0x13;
+		cfg->tx_l1_tx_drv_lvl = 0x19;
+		cfg->tx_l1_tx_emp_post1_lvl = 0x13;
+		cfg->tx_l2_tx_drv_lvl = 0x19;
+		cfg->tx_l2_tx_emp_post1_lvl = 0x13;
+		cfg->tx_l3_tx_drv_lvl = 0x19;
+		cfg->tx_l3_tx_emp_post1_lvl = 0x10;
+		cfg->tx_l0_vmode_ctrl1 = 0x00;
+		cfg->tx_l0_vmode_ctrl2 = 0x0D;
+		cfg->tx_l1_vmode_ctrl1 = 0x00;
+		cfg->tx_l1_vmode_ctrl2 = 0x0D;
+		cfg->tx_l2_vmode_ctrl1 = 0x00;
+		cfg->tx_l2_vmode_ctrl2 = 0x0D;
+		cfg->tx_l3_vmode_ctrl1 = 0x00;
+		cfg->tx_l3_vmode_ctrl2 = 0x0D;
+	} else {
+		cfg->tx_l0_tx_drv_lvl = 0x15;
+		cfg->tx_l0_tx_emp_post1_lvl = 0x10;
+		cfg->tx_l1_tx_drv_lvl = 0x15;
+		cfg->tx_l1_tx_emp_post1_lvl = 0x10;
+		cfg->tx_l2_tx_drv_lvl = 0x15;
+		cfg->tx_l2_tx_emp_post1_lvl = 0x10;
+		cfg->tx_l3_tx_drv_lvl = 0x15;
+		cfg->tx_l3_tx_emp_post1_lvl = 0x10;
+		cfg->tx_l0_vmode_ctrl1 = 0x00;
+		cfg->tx_l0_vmode_ctrl2 = 0x0D;
+		cfg->tx_l1_vmode_ctrl1 = 0x00;
+		cfg->tx_l1_vmode_ctrl2 = 0x0D;
+		cfg->tx_l2_vmode_ctrl1 = 0x00;
+		cfg->tx_l2_vmode_ctrl2 = 0x0D;
+		cfg->tx_l3_vmode_ctrl1 = 0x00;
+		cfg->tx_l3_vmode_ctrl2 = 0x0D;
+	}
+
+	cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0;
+	pr_debug("HDMI 14NM PLL: PLL Settings\n");
+	pr_debug("PLL PARAM: tx_l0_tx_band = 0x%x\n", cfg->tx_l0_tx_band);
+	pr_debug("PLL PARAM: tx_l1_tx_band = 0x%x\n", cfg->tx_l1_tx_band);
+	pr_debug("PLL PARAM: tx_l2_tx_band = 0x%x\n", cfg->tx_l2_tx_band);
+	pr_debug("PLL PARAM: tx_l3_tx_band = 0x%x\n", cfg->tx_l3_tx_band);
+	pr_debug("PLL PARAM: com_svs_mode_clk_sel = 0x%x\n",
+						cfg->com_svs_mode_clk_sel);
+	pr_debug("PLL PARAM: com_hsclk_sel = 0x%x\n", cfg->com_hsclk_sel);
+	pr_debug("PLL PARAM: com_pll_cctrl_mode0 = 0x%x\n",
+						cfg->com_pll_cctrl_mode0);
+	pr_debug("PLL PARAM: com_pll_rctrl_mode0 = 0x%x\n",
+						cfg->com_pll_rctrl_mode0);
+	pr_debug("PLL PARAM: com_cp_ctrl_mode0 = 0x%x\n",
+						cfg->com_cp_ctrl_mode0);
+	pr_debug("PLL PARAM: com_dec_start_mode0 = 0x%x\n",
+						cfg->com_dec_start_mode0);
+	pr_debug("PLL PARAM: com_div_frac_start1_mode0 = 0x%x\n",
+						cfg->com_div_frac_start1_mode0);
+	pr_debug("PLL PARAM: com_div_frac_start2_mode0 = 0x%x\n",
+						cfg->com_div_frac_start2_mode0);
+	pr_debug("PLL PARAM: com_div_frac_start3_mode0 = 0x%x\n",
+						cfg->com_div_frac_start3_mode0);
+	pr_debug("PLL PARAM: com_integloop_gain0_mode0 = 0x%x\n",
+						cfg->com_integloop_gain0_mode0);
+	pr_debug("PLL PARAM: com_integloop_gain1_mode0 = 0x%x\n",
+						cfg->com_integloop_gain1_mode0);
+	pr_debug("PLL PARAM: com_lock_cmp1_mode0 = 0x%x\n",
+						cfg->com_lock_cmp1_mode0);
+	pr_debug("PLL PARAM: com_lock_cmp2_mode0 = 0x%x\n",
+						cfg->com_lock_cmp2_mode0);
+	pr_debug("PLL PARAM: com_lock_cmp3_mode0 = 0x%x\n",
+						cfg->com_lock_cmp3_mode0);
+	pr_debug("PLL PARAM: com_core_clk_en = 0x%x\n", cfg->com_core_clk_en);
+	pr_debug("PLL PARAM: com_coreclk_div = 0x%x\n", cfg->com_coreclk_div);
+
+	pr_debug("PLL PARAM: l0_tx_drv_lvl = 0x%x\n", cfg->tx_l0_tx_drv_lvl);
+	pr_debug("PLL PARAM: l0_tx_emp_post1_lvl = 0x%x\n",
+						cfg->tx_l0_tx_emp_post1_lvl);
+	pr_debug("PLL PARAM: l1_tx_drv_lvl = 0x%x\n", cfg->tx_l1_tx_drv_lvl);
+	pr_debug("PLL PARAM: l1_tx_emp_post1_lvl = 0x%x\n",
+						cfg->tx_l1_tx_emp_post1_lvl);
+	pr_debug("PLL PARAM: l2_tx_drv_lvl = 0x%x\n", cfg->tx_l2_tx_drv_lvl);
+	pr_debug("PLL PARAM: l2_tx_emp_post1_lvl = 0x%x\n",
+						cfg->tx_l2_tx_emp_post1_lvl);
+	pr_debug("PLL PARAM: l3_tx_drv_lvl = 0x%x\n", cfg->tx_l3_tx_drv_lvl);
+	pr_debug("PLL PARAM: l3_tx_emp_post1_lvl = 0x%x\n",
+						cfg->tx_l3_tx_emp_post1_lvl);
+
+	pr_debug("PLL PARAM: l0_vmode_ctrl1 = 0x%x\n", cfg->tx_l0_vmode_ctrl1);
+	pr_debug("PLL PARAM: l0_vmode_ctrl2 = 0x%x\n", cfg->tx_l0_vmode_ctrl2);
+	pr_debug("PLL PARAM: l1_vmode_ctrl1 = 0x%x\n", cfg->tx_l1_vmode_ctrl1);
+	pr_debug("PLL PARAM: l1_vmode_ctrl2 = 0x%x\n", cfg->tx_l1_vmode_ctrl2);
+	pr_debug("PLL PARAM: l2_vmode_ctrl1 = 0x%x\n", cfg->tx_l2_vmode_ctrl1);
+	pr_debug("PLL PARAM: l2_vmode_ctrl2 = 0x%x\n", cfg->tx_l2_vmode_ctrl2);
+	pr_debug("PLL PARAM: l3_vmode_ctrl1 = 0x%x\n", cfg->tx_l3_vmode_ctrl1);
+	pr_debug("PLL PARAM: l3_vmode_ctrl2 = 0x%x\n", cfg->tx_l3_vmode_ctrl2);
+
+	pr_debug("PLL PARAM: phy_mode = 0x%x\n", cfg->phy_mode);
+	rc = 0;
+fail:
+	return rc;
+}
+
+static int hdmi_14nm_phy_pll_set_clk_rate(struct clk *c, u32 tmds_clk)
+{
+	u32 i = 0;
+	int rc = 0;
+	struct hdmi_pll_vco_clk *vco = to_hdmi_14nm_vco_clk(c);
+	struct mdss_pll_resources *io = vco->priv;
+	struct hdmi_14nm_phy_pll_reg_cfg cfg = {0};
+
+	for (i = 0; i < HDMI_PCLK_MAX; i++) {
+		if ((supported_freq_lut[i] >= (tmds_clk - 2000)) &&
+		    (supported_freq_lut[i] <= (tmds_clk + 2000))) {
+			pr_debug("%s: found clk %d\n", __func__, tmds_clk);
+			break;
+		}
+	}
+
+	if (i >= HDMI_PCLK_MAX) {
+		pr_debug("%s: pixel clock %d is not present in LUT\n", __func__,
+						       tmds_clk);
+
+		rc = hdmi_14nm_calculate(tmds_clk, &cfg);
+		if (rc) {
+			pr_err("%s: PLL calculation failed\n", __func__);
+			return rc;
+		}
+	} else {
+		cfg = reg_cfg_lut[i];
+	}
+
+	/* Initially shut down PHY */
+	pr_debug("%s: Disabling PHY\n", __func__);
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_PD_CTL, 0x0);
+	udelay(1000);
+
+	/* Power up sequence */
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_PD_CTL, 0x1);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_RESETSM_CNTRL, 0x20);
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_TX0_TX1_LANE_CTL, 0x0F);
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_TX2_TX3_LANE_CTL, 0x0F);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+				     QSERDES_TX_L0_CLKBUF_ENABLE, 0x03);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+				     QSERDES_TX_L0_CLKBUF_ENABLE, 0x03);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+				     QSERDES_TX_L0_CLKBUF_ENABLE, 0x03);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+				     QSERDES_TX_L0_CLKBUF_ENABLE, 0x03);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+		     QSERDES_TX_L0_TX_BAND, cfg.tx_l0_tx_band);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+		     QSERDES_TX_L0_TX_BAND, cfg.tx_l1_tx_band);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+		     QSERDES_TX_L0_TX_BAND, cfg.tx_l2_tx_band);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+		     QSERDES_TX_L0_TX_BAND, cfg.tx_l3_tx_band);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+			       QSERDES_TX_L0_RESET_TSYNC_EN, 0x03);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+			       QSERDES_TX_L0_RESET_TSYNC_EN, 0x03);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+			       QSERDES_TX_L0_RESET_TSYNC_EN, 0x03);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+			       QSERDES_TX_L0_RESET_TSYNC_EN, 0x03);
+
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x07);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SYSCLK_EN_SEL, 0x37);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SYS_CLK_CTRL, 0x02);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CLK_ENABLE1, 0x0E);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_BG_CTRL, 0x06);
+
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SVS_MODE_CLK_SEL,
+					cfg.com_svs_mode_clk_sel);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CLK_SELECT, 0x30);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_HSCLK_SEL,
+		       cfg.com_hsclk_sel);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP_EN, 0x00);
+
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_CCTRL_MODE0,
+		       cfg.com_pll_cctrl_mode0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_PLL_RCTRL_MODE0,
+		       cfg.com_pll_rctrl_mode0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CP_CTRL_MODE0,
+		       cfg.com_cp_ctrl_mode0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DEC_START_MODE0,
+		       cfg.com_dec_start_mode0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START1_MODE0,
+		       cfg.com_div_frac_start1_mode0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START2_MODE0,
+		       cfg.com_div_frac_start2_mode0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_DIV_FRAC_START3_MODE0,
+		       cfg.com_div_frac_start3_mode0);
+
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_INTEGLOOP_GAIN0_MODE0,
+			cfg.com_integloop_gain0_mode0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_INTEGLOOP_GAIN1_MODE0,
+			cfg.com_integloop_gain1_mode0);
+
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP1_MODE0,
+			cfg.com_lock_cmp1_mode0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP2_MODE0,
+			cfg.com_lock_cmp2_mode0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_LOCK_CMP3_MODE0,
+			cfg.com_lock_cmp3_mode0);
+
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_VCO_TUNE_MAP, 0x00);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CORE_CLK_EN,
+		       cfg.com_core_clk_en);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CORECLK_DIV,
+		       cfg.com_coreclk_div);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_CMN_CONFIG, 0x02);
+
+	/* TX lanes setup (TX 0/1/2/3) */
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_DRV_LVL,
+		       cfg.tx_l0_tx_drv_lvl);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_EMP_POST1_LVL,
+		       cfg.tx_l0_tx_emp_post1_lvl);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_DRV_LVL,
+		       cfg.tx_l1_tx_drv_lvl);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_EMP_POST1_LVL,
+		       cfg.tx_l1_tx_emp_post1_lvl);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_DRV_LVL,
+		       cfg.tx_l2_tx_drv_lvl);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_EMP_POST1_LVL,
+		       cfg.tx_l2_tx_emp_post1_lvl);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_DRV_LVL,
+		       cfg.tx_l3_tx_drv_lvl);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_EMP_POST1_LVL,
+		       cfg.tx_l3_tx_emp_post1_lvl);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+		       QSERDES_TX_L0_VMODE_CTRL1,
+		       cfg.tx_l0_vmode_ctrl1);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+		       QSERDES_TX_L0_VMODE_CTRL2,
+		       cfg.tx_l0_vmode_ctrl2);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+		       QSERDES_TX_L0_VMODE_CTRL1,
+		       cfg.tx_l1_vmode_ctrl1);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+		       QSERDES_TX_L0_VMODE_CTRL2,
+		       cfg.tx_l1_vmode_ctrl2);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+		       QSERDES_TX_L0_VMODE_CTRL1,
+		       cfg.tx_l2_vmode_ctrl1);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+		       QSERDES_TX_L0_VMODE_CTRL2,
+		       cfg.tx_l2_vmode_ctrl2);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+		       QSERDES_TX_L0_VMODE_CTRL1,
+		       cfg.tx_l3_vmode_ctrl1);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+		       QSERDES_TX_L0_VMODE_CTRL2,
+		       cfg.tx_l3_vmode_ctrl2);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_DRV_LVL_OFFSET, 0x00);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_DRV_LVL_OFFSET, 0x00);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_DRV_LVL_OFFSET, 0x00);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+		       QSERDES_TX_L0_TX_DRV_LVL_OFFSET, 0x00);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+		       QSERDES_TX_L0_RES_CODE_LANE_OFFSET, 0x00);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+		       QSERDES_TX_L0_RES_CODE_LANE_OFFSET, 0x00);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+		       QSERDES_TX_L0_RES_CODE_LANE_OFFSET, 0x00);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+		       QSERDES_TX_L0_RES_CODE_LANE_OFFSET, 0x00);
+
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_TXCAL_CFG0, 0x00);
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_TXCAL_CFG1, 0x05);
+
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_MODE, cfg.phy_mode);
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_PD_CTL, 0x1F);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+			QSERDES_TX_L0_TRAN_DRVR_EMP_EN, 0x03);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+			QSERDES_TX_L0_TRAN_DRVR_EMP_EN, 0x03);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+			QSERDES_TX_L0_TRAN_DRVR_EMP_EN, 0x03);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+			QSERDES_TX_L0_TRAN_DRVR_EMP_EN, 0x03);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+			QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN, 0x40);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+			QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN, 0x40);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+			QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN, 0x40);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+			QSERDES_TX_L0_PARRATE_REC_DETECT_IDLE_EN, 0x40);
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+		       QSERDES_TX_L0_HP_PD_ENABLES, 0x0C);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+		       QSERDES_TX_L0_HP_PD_ENABLES, 0x0C);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+		       QSERDES_TX_L0_HP_PD_ENABLES, 0x0C);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+		       QSERDES_TX_L0_HP_PD_ENABLES, 0x03);
+
+	/*
+	 * Ensure that vco configuration gets flushed to hardware before
+	 * enabling the PLL
+	 */
+	wmb();
+	return 0;
+}
+
+static int hdmi_14nm_phy_ready_status(struct mdss_pll_resources *io)
+{
+	u32 status;
+	int phy_ready = 0;
+	int rc;
+
+	rc = mdss_pll_resource_enable(io, true);
+	if (rc) {
+		pr_err("%s: pll resource can't be enabled\n", __func__);
+		return rc;
+	}
+
+	pr_debug("%s: Waiting for PHY Ready\n", __func__);
+
+	/* Poll for PHY read status */
+	if (!readl_poll_timeout_atomic(
+		(io->phy_base + HDMI_PHY_STATUS),
+		status, ((status & BIT(0)) == 1),
+		HDMI_PLL_POLL_MAX_READS,
+		HDMI_PLL_POLL_TIMEOUT_US)) {
+		pr_debug("%s: PHY READY\n", __func__);
+		phy_ready = 1;
+	} else {
+		pr_debug("%s: PHY READY TIMEOUT\n", __func__);
+		phy_ready = 0;
+	}
+
+	mdss_pll_resource_enable(io, false);
+
+	return phy_ready;
+}
+
+static int hdmi_14nm_pll_lock_status(struct mdss_pll_resources *io)
+{
+	u32 status;
+	int pll_locked = 0;
+	int rc;
+
+	rc = mdss_pll_resource_enable(io, true);
+	if (rc) {
+		pr_err("%s: pll resource can't be enabled\n", __func__);
+		return rc;
+	}
+
+	pr_debug("%s: Waiting for PLL lock\n", __func__);
+
+	if (!readl_poll_timeout_atomic(
+		(io->pll_base + QSERDES_COM_C_READY_STATUS),
+		status, ((status & BIT(0)) == 1),
+		HDMI_PLL_POLL_MAX_READS,
+		HDMI_PLL_POLL_TIMEOUT_US)) {
+		pr_debug("%s: C READY\n", __func__);
+		pll_locked = 1;
+	} else {
+		pr_debug("%s: C READY TIMEOUT\n", __func__);
+		pll_locked = 0;
+	}
+
+	mdss_pll_resource_enable(io, false);
+
+	return pll_locked;
+}
+
+static int hdmi_14nm_vco_enable(struct clk *c)
+{
+	int rc;
+	struct hdmi_pll_vco_clk *vco = to_hdmi_14nm_vco_clk(c);
+	struct mdss_pll_resources *io = vco->priv;
+
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x1);
+	udelay(1);
+
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x19);
+	udelay(1);
+
+	rc = hdmi_14nm_pll_lock_status(io);
+	if (!rc) {
+		pr_err("%s: PLL not locked\n", __func__);
+		return rc;
+	}
+
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L0_BASE_OFFSET,
+		       QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN,
+		       0x6F);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L1_BASE_OFFSET,
+		       QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN,
+		       0x6F);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L2_BASE_OFFSET,
+		       QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN,
+		       0x6F);
+	MDSS_PLL_REG_W(io->pll_base + HDMI_TX_L3_BASE_OFFSET,
+		       QSERDES_TX_L0_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN,
+		       0x6F);
+
+	/* Disable SSC */
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_PER1, 0x0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_PER2, 0x0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_STEP_SIZE1, 0x0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_STEP_SIZE2, 0x0);
+	MDSS_PLL_REG_W(io->pll_base, QSERDES_COM_SSC_EN_CENTER, 0x2);
+
+	rc = hdmi_14nm_phy_ready_status(io);
+	if (!rc) {
+		pr_err("%s: PHY not READY\n", __func__);
+		return rc;
+	}
+
+	/* Restart the retiming buffer */
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x18);
+	udelay(1);
+	MDSS_PLL_REG_W(io->phy_base, HDMI_PHY_CFG, 0x19);
+
+	io->pll_on = true;
+	return 0;
+}
+
+static int hdmi_14nm_vco_set_rate(struct clk *c, unsigned long rate)
+{
+	struct hdmi_pll_vco_clk *vco = to_hdmi_14nm_vco_clk(c);
+	struct mdss_pll_resources *io = vco->priv;
+	void __iomem		*pll_base;
+	void __iomem		*phy_base;
+	unsigned int set_power_dwn = 0;
+	int rc;
+
+	rc = mdss_pll_resource_enable(io, true);
+	if (rc) {
+		pr_err("pll resource can't be enabled\n");
+		return rc;
+	}
+
+	if (io->pll_on)
+		set_power_dwn = 1;
+
+	pll_base = io->pll_base;
+	phy_base = io->phy_base;
+
+	pr_debug("rate=%ld\n", rate);
+
+	rc = hdmi_14nm_phy_pll_set_clk_rate(c, rate);
+	if (rc)
+		pr_err("%s: Failed to set clk rate\n", __func__);
+
+	mdss_pll_resource_enable(io, false);
+
+	if (set_power_dwn)
+		hdmi_14nm_vco_enable(c);
+
+	vco->rate = rate;
+	vco->rate_set = true;
+
+	return 0;
+}
+
+static unsigned long hdmi_14nm_vco_get_rate(struct clk *c)
+{
+	unsigned long freq = 0;
+
+	return freq;
+}
+
+static long hdmi_14nm_vco_round_rate(struct clk *c, unsigned long rate)
+{
+	unsigned long rrate = rate;
+
+	pr_debug("rrate=%ld\n", rrate);
+
+	return rrate;
+}
+
+static int hdmi_14nm_vco_prepare(struct clk *c)
+{
+	struct hdmi_pll_vco_clk *vco = to_hdmi_14nm_vco_clk(c);
+	struct mdss_pll_resources *io = vco->priv;
+	int ret = 0;
+
+	pr_debug("rate=%ld\n", vco->rate);
+
+	if (!vco->rate_set && vco->rate)
+		ret = hdmi_14nm_vco_set_rate(c, vco->rate);
+
+	if (!ret) {
+		ret = mdss_pll_resource_enable(io, true);
+		if (ret)
+			pr_err("pll resource can't be enabled\n");
+	}
+
+	return ret;
+}
+
+static void hdmi_14nm_vco_unprepare(struct clk *c)
+{
+	struct hdmi_pll_vco_clk *vco = to_hdmi_14nm_vco_clk(c);
+	struct mdss_pll_resources *io = vco->priv;
+
+	vco->rate_set = false;
+
+	if (!io) {
+		pr_err("Invalid input parameter\n");
+		return;
+	}
+
+	if (!io->pll_on &&
+		mdss_pll_resource_enable(io, true)) {
+		pr_err("pll resource can't be enabled\n");
+		return;
+	}
+
+	io->handoff_resources = false;
+	mdss_pll_resource_enable(io, false);
+	io->pll_on = false;
+}
+
+static enum handoff hdmi_14nm_vco_handoff(struct clk *c)
+{
+	enum handoff ret = HANDOFF_DISABLED_CLK;
+	struct hdmi_pll_vco_clk *vco = to_hdmi_14nm_vco_clk(c);
+	struct mdss_pll_resources *io = vco->priv;
+
+	if (is_gdsc_disabled(io))
+		return HANDOFF_DISABLED_CLK;
+
+	if (mdss_pll_resource_enable(io, true)) {
+		pr_err("pll resource can't be enabled\n");
+		return ret;
+	}
+
+	io->handoff_resources = true;
+
+	if (hdmi_14nm_pll_lock_status(io)) {
+		if (hdmi_14nm_phy_ready_status(io)) {
+			io->pll_on = true;
+			c->rate = hdmi_14nm_vco_get_rate(c);
+			ret = HANDOFF_ENABLED_CLK;
+		} else {
+			io->handoff_resources = false;
+			mdss_pll_resource_enable(io, false);
+			pr_debug("%s: PHY not ready\n", __func__);
+		}
+	} else {
+		io->handoff_resources = false;
+		mdss_pll_resource_enable(io, false);
+		pr_debug("%s: PLL not locked\n", __func__);
+	}
+
+	pr_debug("done, ret=%d\n", ret);
+	return ret;
+}
+
+static const struct clk_ops hdmi_14nm_vco_clk_ops = {
+	.enable = hdmi_14nm_vco_enable,
+	.set_rate = hdmi_14nm_vco_set_rate,
+	.get_rate = hdmi_14nm_vco_get_rate,
+	.round_rate = hdmi_14nm_vco_round_rate,
+	.prepare = hdmi_14nm_vco_prepare,
+	.unprepare = hdmi_14nm_vco_unprepare,
+	.handoff = hdmi_14nm_vco_handoff,
+};
+
+static struct hdmi_pll_vco_clk hdmi_vco_clk = {
+	.c = {
+		.dbg_name = "hdmi_14nm_vco_clk",
+		.ops = &hdmi_14nm_vco_clk_ops,
+		CLK_INIT(hdmi_vco_clk.c),
+	},
+};
+
+static struct clk_lookup hdmipllcc_8996[] = {
+	CLK_LIST(hdmi_vco_clk),
+};
+
+int hdmi_14nm_pll_clock_register(struct platform_device *pdev,
+				 struct mdss_pll_resources *pll_res)
+{
+	int rc = -ENOTSUPP;
+
+	if (!pll_res || !pll_res->phy_base || !pll_res->pll_base) {
+		pr_err("%s: Invalid input parameters\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	/* Set client data for vco, mux and div clocks */
+	hdmi_vco_clk.priv = pll_res;
+
+	rc = of_msm_clock_register(pdev->dev.of_node, hdmipllcc_8996,
+					ARRAY_SIZE(hdmipllcc_8996));
+	if (rc) {
+		pr_err("%s: Clock register failed rc=%d\n", __func__, rc);
+		rc = -EPROBE_DEFER;
+	} else {
+		pr_debug("%s SUCCESS\n", __func__);
+	}
+
+	return rc;
+}
diff --git a/drivers/clk/qcom/mdss/mdss-hdmi-pll.h b/drivers/clk/qcom/mdss/mdss-hdmi-pll.h
index 612b7c4..59d7f10 100644
--- a/drivers/clk/qcom/mdss/mdss-hdmi-pll.h
+++ b/drivers/clk/qcom/mdss/mdss-hdmi-pll.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -38,4 +38,7 @@
 
 int hdmi_20nm_pll_clock_register(struct platform_device *pdev,
 				struct mdss_pll_resources *pll_res);
+
+int hdmi_14nm_pll_clock_register(struct platform_device *pdev,
+				 struct mdss_pll_resources *pll_res);
 #endif
diff --git a/drivers/clk/qcom/mdss/mdss-pll.c b/drivers/clk/qcom/mdss/mdss-pll.c
index cd27c41..d040c52 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.c
+++ b/drivers/clk/qcom/mdss/mdss-pll.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -154,6 +154,8 @@
 		pll_res->pll_interface_type = MDSS_HDMI_PLL_20NM;
 	} else if (!strcmp(compatible_stream, "qcom,mdss_hdmi_pll_8992")) {
 		pll_res->pll_interface_type = MDSS_HDMI_PLL_20NM;
+	} else if (!strcmp(compatible_stream, "qcom,mdss_hdmi_pll_8996")) {
+		pll_res->pll_interface_type = MDSS_HDMI_PLL_14NM;
 	} else {
 		goto err;
 	}
@@ -194,6 +196,9 @@
 	case MDSS_HDMI_PLL_20NM:
 		rc = hdmi_20nm_pll_clock_register(pdev, pll_res);
 		break;
+	case MDSS_HDMI_PLL_14NM:
+		rc = hdmi_14nm_pll_clock_register(pdev, pll_res);
+		break;
 	case MDSS_UNKNOWN_PLL:
 	default:
 		rc = -EINVAL;
@@ -395,6 +400,7 @@
 	{.compatible = "qcom,mdss_hdmi_pll_8994"},
 	{.compatible = "qcom,mdss_dsi_pll_8992"},
 	{.compatible = "qcom,mdss_hdmi_pll_8992"},
+	{.compatible = "qcom,mdss_hdmi_pll_8996"},
 	{.compatible = "qcom,mdss_dsi_pll_8916"},
 	{.compatible = "qcom,mdss_dsi_pll_8939"},
 	{.compatible = "qcom,mdss_dsi_pll_8909"},
diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h
index 057d173..92c27bc 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.h
+++ b/drivers/clk/qcom/mdss/mdss-pll.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,7 @@
 	MDSS_EDP_PLL,
 	MDSS_HDMI_PLL,
 	MDSS_HDMI_PLL_20NM,
+	MDSS_HDMI_PLL_14NM,
 	MDSS_UNKNOWN_PLL,
 };