Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/clk-provider.h>
0007 #include <linux/delay.h>
0008 
0009 #include "hdmi.h"
0010 
0011 #define HDMI_VCO_MAX_FREQ           12000000000UL
0012 #define HDMI_VCO_MIN_FREQ           8000000000UL
0013 
0014 #define HDMI_PCLK_MAX_FREQ          600000000
0015 #define HDMI_PCLK_MIN_FREQ          25000000
0016 
0017 #define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD    3400000000UL
0018 #define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD     1500000000UL
0019 #define HDMI_MID_FREQ_BIT_CLK_THRESHOLD     750000000UL
0020 #define HDMI_CORECLK_DIV            5
0021 #define HDMI_DEFAULT_REF_CLOCK          19200000
0022 #define HDMI_PLL_CMP_CNT            1024
0023 
0024 #define HDMI_PLL_POLL_MAX_READS         100
0025 #define HDMI_PLL_POLL_TIMEOUT_US        150
0026 
0027 #define HDMI_NUM_TX_CHANNEL         4
0028 
0029 struct hdmi_pll_8996 {
0030     struct platform_device *pdev;
0031     struct clk_hw clk_hw;
0032 
0033     /* pll mmio base */
0034     void __iomem *mmio_qserdes_com;
0035     /* tx channel base */
0036     void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL];
0037 };
0038 
0039 #define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8996, clk_hw)
0040 
0041 struct hdmi_8996_phy_pll_reg_cfg {
0042     u32 tx_lx_lane_mode[HDMI_NUM_TX_CHANNEL];
0043     u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL];
0044     u32 com_svs_mode_clk_sel;
0045     u32 com_hsclk_sel;
0046     u32 com_pll_cctrl_mode0;
0047     u32 com_pll_rctrl_mode0;
0048     u32 com_cp_ctrl_mode0;
0049     u32 com_dec_start_mode0;
0050     u32 com_div_frac_start1_mode0;
0051     u32 com_div_frac_start2_mode0;
0052     u32 com_div_frac_start3_mode0;
0053     u32 com_integloop_gain0_mode0;
0054     u32 com_integloop_gain1_mode0;
0055     u32 com_lock_cmp_en;
0056     u32 com_lock_cmp1_mode0;
0057     u32 com_lock_cmp2_mode0;
0058     u32 com_lock_cmp3_mode0;
0059     u32 com_core_clk_en;
0060     u32 com_coreclk_div;
0061     u32 com_vco_tune_ctrl;
0062 
0063     u32 tx_lx_tx_drv_lvl[HDMI_NUM_TX_CHANNEL];
0064     u32 tx_lx_tx_emp_post1_lvl[HDMI_NUM_TX_CHANNEL];
0065     u32 tx_lx_vmode_ctrl1[HDMI_NUM_TX_CHANNEL];
0066     u32 tx_lx_vmode_ctrl2[HDMI_NUM_TX_CHANNEL];
0067     u32 tx_lx_res_code_lane_tx[HDMI_NUM_TX_CHANNEL];
0068     u32 tx_lx_hp_pd_enables[HDMI_NUM_TX_CHANNEL];
0069 
0070     u32 phy_mode;
0071 };
0072 
0073 struct hdmi_8996_post_divider {
0074     u64 vco_freq;
0075     int hsclk_divsel;
0076     int vco_ratio;
0077     int tx_band_sel;
0078     int half_rate_mode;
0079 };
0080 
0081 static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8996 *pll)
0082 {
0083     return platform_get_drvdata(pll->pdev);
0084 }
0085 
0086 static inline void hdmi_pll_write(struct hdmi_pll_8996 *pll, int offset,
0087                   u32 data)
0088 {
0089     msm_writel(data, pll->mmio_qserdes_com + offset);
0090 }
0091 
0092 static inline u32 hdmi_pll_read(struct hdmi_pll_8996 *pll, int offset)
0093 {
0094     return msm_readl(pll->mmio_qserdes_com + offset);
0095 }
0096 
0097 static inline void hdmi_tx_chan_write(struct hdmi_pll_8996 *pll, int channel,
0098                       int offset, int data)
0099 {
0100      msm_writel(data, pll->mmio_qserdes_tx[channel] + offset);
0101 }
0102 
0103 static inline u32 pll_get_cpctrl(u64 frac_start, unsigned long ref_clk,
0104                  bool gen_ssc)
0105 {
0106     if ((frac_start != 0) || gen_ssc)
0107         return (11000000 / (ref_clk / 20));
0108 
0109     return 0x23;
0110 }
0111 
0112 static inline u32 pll_get_rctrl(u64 frac_start, bool gen_ssc)
0113 {
0114     if ((frac_start != 0) || gen_ssc)
0115         return 0x16;
0116 
0117     return 0x10;
0118 }
0119 
0120 static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc)
0121 {
0122     if ((frac_start != 0) || gen_ssc)
0123         return 0x28;
0124 
0125     return 0x1;
0126 }
0127 
0128 static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref_clk,
0129                      bool gen_ssc)
0130 {
0131     int digclk_divsel = bclk >= HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2;
0132     u64 base;
0133 
0134     if ((frac_start != 0) || gen_ssc)
0135         base = (64 * ref_clk) / HDMI_DEFAULT_REF_CLOCK;
0136     else
0137         base = (1022 * ref_clk) / 100;
0138 
0139     base <<= digclk_divsel;
0140 
0141     return (base <= 2046 ? base : 2046);
0142 }
0143 
0144 static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
0145 {
0146     u64 dividend = HDMI_PLL_CMP_CNT * fdata;
0147     u32 divisor = ref_clk * 10;
0148     u32 rem;
0149 
0150     rem = do_div(dividend, divisor);
0151     if (rem > (divisor >> 1))
0152         dividend++;
0153 
0154     return dividend - 1;
0155 }
0156 
0157 static inline u64 pll_cmp_to_fdata(u32 pll_cmp, unsigned long ref_clk)
0158 {
0159     u64 fdata = ((u64)pll_cmp) * ref_clk * 10;
0160 
0161     do_div(fdata, HDMI_PLL_CMP_CNT);
0162 
0163     return fdata;
0164 }
0165 
0166 static int pll_get_post_div(struct hdmi_8996_post_divider *pd, u64 bclk)
0167 {
0168     int ratio[] = { 2, 3, 4, 5, 6, 9, 10, 12, 14, 15, 20, 21, 25, 28, 35 };
0169     int hs_divsel[] = { 0, 4, 8, 12, 1, 5, 2, 9, 3, 13, 10, 7, 14, 11, 15 };
0170     int tx_band_sel[] = { 0, 1, 2, 3 };
0171     u64 vco_freq[60];
0172     u64 vco, vco_optimal;
0173     int half_rate_mode = 0;
0174     int vco_optimal_index, vco_freq_index;
0175     int i, j;
0176 
0177 retry:
0178     vco_optimal = HDMI_VCO_MAX_FREQ;
0179     vco_optimal_index = -1;
0180     vco_freq_index = 0;
0181     for (i = 0; i < 15; i++) {
0182         for (j = 0; j < 4; j++) {
0183             u32 ratio_mult = ratio[i] << tx_band_sel[j];
0184 
0185             vco = bclk >> half_rate_mode;
0186             vco *= ratio_mult;
0187             vco_freq[vco_freq_index++] = vco;
0188         }
0189     }
0190 
0191     for (i = 0; i < 60; i++) {
0192         u64 vco_tmp = vco_freq[i];
0193 
0194         if ((vco_tmp >= HDMI_VCO_MIN_FREQ) &&
0195             (vco_tmp <= vco_optimal)) {
0196             vco_optimal = vco_tmp;
0197             vco_optimal_index = i;
0198         }
0199     }
0200 
0201     if (vco_optimal_index == -1) {
0202         if (!half_rate_mode) {
0203             half_rate_mode = 1;
0204             goto retry;
0205         }
0206     } else {
0207         pd->vco_freq = vco_optimal;
0208         pd->tx_band_sel = tx_band_sel[vco_optimal_index % 4];
0209         pd->vco_ratio = ratio[vco_optimal_index / 4];
0210         pd->hsclk_divsel = hs_divsel[vco_optimal_index / 4];
0211 
0212         return 0;
0213     }
0214 
0215     return -EINVAL;
0216 }
0217 
0218 static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk,
0219              struct hdmi_8996_phy_pll_reg_cfg *cfg)
0220 {
0221     struct hdmi_8996_post_divider pd;
0222     u64 bclk;
0223     u64 tmds_clk;
0224     u64 dec_start;
0225     u64 frac_start;
0226     u64 fdata;
0227     u32 pll_divisor;
0228     u32 rem;
0229     u32 cpctrl;
0230     u32 rctrl;
0231     u32 cctrl;
0232     u32 integloop_gain;
0233     u32 pll_cmp;
0234     int i, ret;
0235 
0236     /* bit clk = 10 * pix_clk */
0237     bclk = ((u64)pix_clk) * 10;
0238 
0239     if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD)
0240         tmds_clk = pix_clk >> 2;
0241     else
0242         tmds_clk = pix_clk;
0243 
0244     ret = pll_get_post_div(&pd, bclk);
0245     if (ret)
0246         return ret;
0247 
0248     dec_start = pd.vco_freq;
0249     pll_divisor = 4 * ref_clk;
0250     do_div(dec_start, pll_divisor);
0251 
0252     frac_start = pd.vco_freq * (1 << 20);
0253 
0254     rem = do_div(frac_start, pll_divisor);
0255     frac_start -= dec_start * (1 << 20);
0256     if (rem > (pll_divisor >> 1))
0257         frac_start++;
0258 
0259     cpctrl = pll_get_cpctrl(frac_start, ref_clk, false);
0260     rctrl = pll_get_rctrl(frac_start, false);
0261     cctrl = pll_get_cctrl(frac_start, false);
0262     integloop_gain = pll_get_integloop_gain(frac_start, bclk,
0263                         ref_clk, false);
0264 
0265     fdata = pd.vco_freq;
0266     do_div(fdata, pd.vco_ratio);
0267 
0268     pll_cmp = pll_get_pll_cmp(fdata, ref_clk);
0269 
0270     DBG("VCO freq: %llu", pd.vco_freq);
0271     DBG("fdata: %llu", fdata);
0272     DBG("pix_clk: %lu", pix_clk);
0273     DBG("tmds clk: %llu", tmds_clk);
0274     DBG("HSCLK_SEL: %d", pd.hsclk_divsel);
0275     DBG("DEC_START: %llu", dec_start);
0276     DBG("DIV_FRAC_START: %llu", frac_start);
0277     DBG("PLL_CPCTRL: %u", cpctrl);
0278     DBG("PLL_RCTRL: %u", rctrl);
0279     DBG("PLL_CCTRL: %u", cctrl);
0280     DBG("INTEGLOOP_GAIN: %u", integloop_gain);
0281     DBG("TX_BAND: %d", pd.tx_band_sel);
0282     DBG("PLL_CMP: %u", pll_cmp);
0283 
0284     /* Convert these values to register specific values */
0285     if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD)
0286         cfg->com_svs_mode_clk_sel = 1;
0287     else
0288         cfg->com_svs_mode_clk_sel = 2;
0289 
0290     cfg->com_hsclk_sel = (0x20 | pd.hsclk_divsel);
0291     cfg->com_pll_cctrl_mode0 = cctrl;
0292     cfg->com_pll_rctrl_mode0 = rctrl;
0293     cfg->com_cp_ctrl_mode0 = cpctrl;
0294     cfg->com_dec_start_mode0 = dec_start;
0295     cfg->com_div_frac_start1_mode0 = (frac_start & 0xff);
0296     cfg->com_div_frac_start2_mode0 = ((frac_start & 0xff00) >> 8);
0297     cfg->com_div_frac_start3_mode0 = ((frac_start & 0xf0000) >> 16);
0298     cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xff);
0299     cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xf00) >> 8);
0300     cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xff);
0301     cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xff00) >> 8);
0302     cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16);
0303     cfg->com_lock_cmp_en = 0x0;
0304     cfg->com_core_clk_en = 0x2c;
0305     cfg->com_coreclk_div = HDMI_CORECLK_DIV;
0306     cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0;
0307     cfg->com_vco_tune_ctrl = 0x0;
0308 
0309     cfg->tx_lx_lane_mode[0] =
0310         cfg->tx_lx_lane_mode[2] = 0x43;
0311 
0312     cfg->tx_lx_hp_pd_enables[0] =
0313         cfg->tx_lx_hp_pd_enables[1] =
0314         cfg->tx_lx_hp_pd_enables[2] = 0x0c;
0315     cfg->tx_lx_hp_pd_enables[3] = 0x3;
0316 
0317     for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
0318         cfg->tx_lx_tx_band[i] = pd.tx_band_sel + 4;
0319 
0320     if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) {
0321         cfg->tx_lx_tx_drv_lvl[0] =
0322             cfg->tx_lx_tx_drv_lvl[1] =
0323             cfg->tx_lx_tx_drv_lvl[2] = 0x25;
0324         cfg->tx_lx_tx_drv_lvl[3] = 0x22;
0325 
0326         cfg->tx_lx_tx_emp_post1_lvl[0] =
0327             cfg->tx_lx_tx_emp_post1_lvl[1] =
0328             cfg->tx_lx_tx_emp_post1_lvl[2] = 0x23;
0329         cfg->tx_lx_tx_emp_post1_lvl[3] = 0x27;
0330 
0331         cfg->tx_lx_vmode_ctrl1[0] =
0332             cfg->tx_lx_vmode_ctrl1[1] =
0333             cfg->tx_lx_vmode_ctrl1[2] =
0334             cfg->tx_lx_vmode_ctrl1[3] = 0x00;
0335 
0336         cfg->tx_lx_vmode_ctrl2[0] =
0337             cfg->tx_lx_vmode_ctrl2[1] =
0338             cfg->tx_lx_vmode_ctrl2[2] = 0x0D;
0339 
0340         cfg->tx_lx_vmode_ctrl2[3] = 0x00;
0341     } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) {
0342         for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
0343             cfg->tx_lx_tx_drv_lvl[i] = 0x25;
0344             cfg->tx_lx_tx_emp_post1_lvl[i] = 0x23;
0345             cfg->tx_lx_vmode_ctrl1[i] = 0x00;
0346         }
0347 
0348         cfg->tx_lx_vmode_ctrl2[0] =
0349             cfg->tx_lx_vmode_ctrl2[1] =
0350             cfg->tx_lx_vmode_ctrl2[2] = 0x0D;
0351         cfg->tx_lx_vmode_ctrl2[3] = 0x00;
0352     } else {
0353         for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
0354             cfg->tx_lx_tx_drv_lvl[i] = 0x20;
0355             cfg->tx_lx_tx_emp_post1_lvl[i] = 0x20;
0356             cfg->tx_lx_vmode_ctrl1[i] = 0x00;
0357             cfg->tx_lx_vmode_ctrl2[i] = 0x0E;
0358         }
0359     }
0360 
0361     DBG("com_svs_mode_clk_sel = 0x%x", cfg->com_svs_mode_clk_sel);
0362     DBG("com_hsclk_sel = 0x%x", cfg->com_hsclk_sel);
0363     DBG("com_lock_cmp_en = 0x%x", cfg->com_lock_cmp_en);
0364     DBG("com_pll_cctrl_mode0 = 0x%x", cfg->com_pll_cctrl_mode0);
0365     DBG("com_pll_rctrl_mode0 = 0x%x", cfg->com_pll_rctrl_mode0);
0366     DBG("com_cp_ctrl_mode0 = 0x%x", cfg->com_cp_ctrl_mode0);
0367     DBG("com_dec_start_mode0 = 0x%x", cfg->com_dec_start_mode0);
0368     DBG("com_div_frac_start1_mode0 = 0x%x", cfg->com_div_frac_start1_mode0);
0369     DBG("com_div_frac_start2_mode0 = 0x%x", cfg->com_div_frac_start2_mode0);
0370     DBG("com_div_frac_start3_mode0 = 0x%x", cfg->com_div_frac_start3_mode0);
0371     DBG("com_integloop_gain0_mode0 = 0x%x", cfg->com_integloop_gain0_mode0);
0372     DBG("com_integloop_gain1_mode0 = 0x%x", cfg->com_integloop_gain1_mode0);
0373     DBG("com_lock_cmp1_mode0 = 0x%x", cfg->com_lock_cmp1_mode0);
0374     DBG("com_lock_cmp2_mode0 = 0x%x", cfg->com_lock_cmp2_mode0);
0375     DBG("com_lock_cmp3_mode0 = 0x%x", cfg->com_lock_cmp3_mode0);
0376     DBG("com_core_clk_en = 0x%x", cfg->com_core_clk_en);
0377     DBG("com_coreclk_div = 0x%x", cfg->com_coreclk_div);
0378     DBG("phy_mode = 0x%x", cfg->phy_mode);
0379 
0380     DBG("tx_l0_lane_mode = 0x%x", cfg->tx_lx_lane_mode[0]);
0381     DBG("tx_l2_lane_mode = 0x%x", cfg->tx_lx_lane_mode[2]);
0382 
0383     for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
0384         DBG("tx_l%d_tx_band = 0x%x", i, cfg->tx_lx_tx_band[i]);
0385         DBG("tx_l%d_tx_drv_lvl = 0x%x", i, cfg->tx_lx_tx_drv_lvl[i]);
0386         DBG("tx_l%d_tx_emp_post1_lvl = 0x%x", i,
0387             cfg->tx_lx_tx_emp_post1_lvl[i]);
0388         DBG("tx_l%d_vmode_ctrl1 = 0x%x", i, cfg->tx_lx_vmode_ctrl1[i]);
0389         DBG("tx_l%d_vmode_ctrl2 = 0x%x", i, cfg->tx_lx_vmode_ctrl2[i]);
0390     }
0391 
0392     return 0;
0393 }
0394 
0395 static int hdmi_8996_pll_set_clk_rate(struct clk_hw *hw, unsigned long rate,
0396                       unsigned long parent_rate)
0397 {
0398     struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
0399     struct hdmi_phy *phy = pll_get_phy(pll);
0400     struct hdmi_8996_phy_pll_reg_cfg cfg;
0401     int i, ret;
0402 
0403     memset(&cfg, 0x00, sizeof(cfg));
0404 
0405     ret = pll_calculate(rate, parent_rate, &cfg);
0406     if (ret) {
0407         DRM_ERROR("PLL calculation failed\n");
0408         return ret;
0409     }
0410 
0411     /* Initially shut down PHY */
0412     DBG("Disabling PHY");
0413     hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x0);
0414     udelay(500);
0415 
0416     /* Power up sequence */
0417     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x04);
0418 
0419     hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1);
0420     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20);
0421     hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX0_TX1_LANE_CTL, 0x0F);
0422     hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX2_TX3_LANE_CTL, 0x0F);
0423 
0424     for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
0425         hdmi_tx_chan_write(pll, i,
0426                    REG_HDMI_PHY_QSERDES_TX_LX_CLKBUF_ENABLE,
0427                    0x03);
0428         hdmi_tx_chan_write(pll, i,
0429                    REG_HDMI_PHY_QSERDES_TX_LX_TX_BAND,
0430                    cfg.tx_lx_tx_band[i]);
0431         hdmi_tx_chan_write(pll, i,
0432                    REG_HDMI_PHY_QSERDES_TX_LX_RESET_TSYNC_EN,
0433                    0x03);
0434     }
0435 
0436     hdmi_tx_chan_write(pll, 0, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE,
0437                cfg.tx_lx_lane_mode[0]);
0438     hdmi_tx_chan_write(pll, 2, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE,
0439                cfg.tx_lx_lane_mode[2]);
0440 
0441     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1E);
0442     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x07);
0443     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37);
0444     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02);
0445     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E);
0446 
0447     /* Bypass VCO calibration */
0448     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SVS_MODE_CLK_SEL,
0449                cfg.com_svs_mode_clk_sel);
0450 
0451     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_TRIM, 0x0F);
0452     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_IVCO, 0x0F);
0453     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_CTRL,
0454                cfg.com_vco_tune_ctrl);
0455 
0456     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x06);
0457 
0458     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_SELECT, 0x30);
0459     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_HSCLK_SEL,
0460                cfg.com_hsclk_sel);
0461     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP_EN,
0462                cfg.com_lock_cmp_en);
0463 
0464     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_CCTRL_MODE0,
0465                cfg.com_pll_cctrl_mode0);
0466     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_RCTRL_MODE0,
0467                cfg.com_pll_rctrl_mode0);
0468     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CP_CTRL_MODE0,
0469                cfg.com_cp_ctrl_mode0);
0470     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DEC_START_MODE0,
0471                cfg.com_dec_start_mode0);
0472     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0,
0473                cfg.com_div_frac_start1_mode0);
0474     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0,
0475                cfg.com_div_frac_start2_mode0);
0476     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0,
0477                cfg.com_div_frac_start3_mode0);
0478 
0479     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0,
0480                cfg.com_integloop_gain0_mode0);
0481     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0,
0482                cfg.com_integloop_gain1_mode0);
0483 
0484     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0,
0485                cfg.com_lock_cmp1_mode0);
0486     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0,
0487                cfg.com_lock_cmp2_mode0);
0488     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0,
0489                cfg.com_lock_cmp3_mode0);
0490 
0491     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00);
0492     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORE_CLK_EN,
0493                cfg.com_core_clk_en);
0494     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORECLK_DIV,
0495                cfg.com_coreclk_div);
0496     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CMN_CONFIG, 0x02);
0497 
0498     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESCODE_DIV_NUM, 0x15);
0499 
0500     /* TX lanes setup (TX 0/1/2/3) */
0501     for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
0502         hdmi_tx_chan_write(pll, i,
0503                    REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL,
0504                    cfg.tx_lx_tx_drv_lvl[i]);
0505         hdmi_tx_chan_write(pll, i,
0506                    REG_HDMI_PHY_QSERDES_TX_LX_TX_EMP_POST1_LVL,
0507                    cfg.tx_lx_tx_emp_post1_lvl[i]);
0508         hdmi_tx_chan_write(pll, i,
0509                    REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL1,
0510                    cfg.tx_lx_vmode_ctrl1[i]);
0511         hdmi_tx_chan_write(pll, i,
0512                    REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL2,
0513                    cfg.tx_lx_vmode_ctrl2[i]);
0514         hdmi_tx_chan_write(pll, i,
0515                    REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL_OFFSET,
0516                    0x00);
0517         hdmi_tx_chan_write(pll, i,
0518             REG_HDMI_PHY_QSERDES_TX_LX_RES_CODE_LANE_OFFSET,
0519             0x00);
0520         hdmi_tx_chan_write(pll, i,
0521             REG_HDMI_PHY_QSERDES_TX_LX_TRAN_DRVR_EMP_EN,
0522             0x03);
0523         hdmi_tx_chan_write(pll, i,
0524             REG_HDMI_PHY_QSERDES_TX_LX_PARRATE_REC_DETECT_IDLE_EN,
0525             0x40);
0526         hdmi_tx_chan_write(pll, i,
0527                    REG_HDMI_PHY_QSERDES_TX_LX_HP_PD_ENABLES,
0528                    cfg.tx_lx_hp_pd_enables[i]);
0529     }
0530 
0531     hdmi_phy_write(phy, REG_HDMI_8996_PHY_MODE, cfg.phy_mode);
0532     hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1F);
0533 
0534     /*
0535      * Ensure that vco configuration gets flushed to hardware before
0536      * enabling the PLL
0537      */
0538     wmb();
0539 
0540     return 0;
0541 }
0542 
0543 static int hdmi_8996_phy_ready_status(struct hdmi_phy *phy)
0544 {
0545     u32 nb_tries = HDMI_PLL_POLL_MAX_READS;
0546     unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
0547     u32 status;
0548     int phy_ready = 0;
0549 
0550     DBG("Waiting for PHY ready");
0551 
0552     while (nb_tries--) {
0553         status = hdmi_phy_read(phy, REG_HDMI_8996_PHY_STATUS);
0554         phy_ready = status & BIT(0);
0555 
0556         if (phy_ready)
0557             break;
0558 
0559         udelay(timeout);
0560     }
0561 
0562     DBG("PHY is %sready", phy_ready ? "" : "*not* ");
0563 
0564     return phy_ready;
0565 }
0566 
0567 static int hdmi_8996_pll_lock_status(struct hdmi_pll_8996 *pll)
0568 {
0569     u32 status;
0570     int nb_tries = HDMI_PLL_POLL_MAX_READS;
0571     unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
0572     int pll_locked = 0;
0573 
0574     DBG("Waiting for PLL lock");
0575 
0576     while (nb_tries--) {
0577         status = hdmi_pll_read(pll,
0578                        REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS);
0579         pll_locked = status & BIT(0);
0580 
0581         if (pll_locked)
0582             break;
0583 
0584         udelay(timeout);
0585     }
0586 
0587     DBG("HDMI PLL is %slocked", pll_locked ? "" : "*not* ");
0588 
0589     return pll_locked;
0590 }
0591 
0592 static int hdmi_8996_pll_prepare(struct clk_hw *hw)
0593 {
0594     struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
0595     struct hdmi_phy *phy = pll_get_phy(pll);
0596     int i, ret = 0;
0597 
0598     hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x1);
0599     udelay(100);
0600 
0601     hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19);
0602     udelay(100);
0603 
0604     ret = hdmi_8996_pll_lock_status(pll);
0605     if (!ret)
0606         return ret;
0607 
0608     for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
0609         hdmi_tx_chan_write(pll, i,
0610             REG_HDMI_PHY_QSERDES_TX_LX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN,
0611             0x6F);
0612 
0613     /* Disable SSC */
0614     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER1, 0x0);
0615     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER2, 0x0);
0616     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE1, 0x0);
0617     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE2, 0x0);
0618     hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_EN_CENTER, 0x2);
0619 
0620     ret = hdmi_8996_phy_ready_status(phy);
0621     if (!ret)
0622         return ret;
0623 
0624     /* Restart the retiming buffer */
0625     hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x18);
0626     udelay(1);
0627     hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19);
0628 
0629     return 0;
0630 }
0631 
0632 static long hdmi_8996_pll_round_rate(struct clk_hw *hw,
0633                      unsigned long rate,
0634                      unsigned long *parent_rate)
0635 {
0636     if (rate < HDMI_PCLK_MIN_FREQ)
0637         return HDMI_PCLK_MIN_FREQ;
0638     else if (rate > HDMI_PCLK_MAX_FREQ)
0639         return HDMI_PCLK_MAX_FREQ;
0640     else
0641         return rate;
0642 }
0643 
0644 static unsigned long hdmi_8996_pll_recalc_rate(struct clk_hw *hw,
0645                            unsigned long parent_rate)
0646 {
0647     struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
0648     u64 fdata;
0649     u32 cmp1, cmp2, cmp3, pll_cmp;
0650 
0651     cmp1 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0);
0652     cmp2 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0);
0653     cmp3 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0);
0654 
0655     pll_cmp = cmp1 | (cmp2 << 8) | (cmp3 << 16);
0656 
0657     fdata = pll_cmp_to_fdata(pll_cmp + 1, parent_rate);
0658 
0659     do_div(fdata, 10);
0660 
0661     return fdata;
0662 }
0663 
0664 static void hdmi_8996_pll_unprepare(struct clk_hw *hw)
0665 {
0666     struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
0667     struct hdmi_phy *phy = pll_get_phy(pll);
0668 
0669     hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x6);
0670     usleep_range(100, 150);
0671 }
0672 
0673 static int hdmi_8996_pll_is_enabled(struct clk_hw *hw)
0674 {
0675     struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
0676     u32 status;
0677     int pll_locked;
0678 
0679     status = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS);
0680     pll_locked = status & BIT(0);
0681 
0682     return pll_locked;
0683 }
0684 
0685 static const struct clk_ops hdmi_8996_pll_ops = {
0686     .set_rate = hdmi_8996_pll_set_clk_rate,
0687     .round_rate = hdmi_8996_pll_round_rate,
0688     .recalc_rate = hdmi_8996_pll_recalc_rate,
0689     .prepare = hdmi_8996_pll_prepare,
0690     .unprepare = hdmi_8996_pll_unprepare,
0691     .is_enabled = hdmi_8996_pll_is_enabled,
0692 };
0693 
0694 static const char * const hdmi_pll_parents[] = {
0695     "xo",
0696 };
0697 
0698 static const struct clk_init_data pll_init = {
0699     .name = "hdmipll",
0700     .ops = &hdmi_8996_pll_ops,
0701     .parent_names = hdmi_pll_parents,
0702     .num_parents = ARRAY_SIZE(hdmi_pll_parents),
0703     .flags = CLK_IGNORE_UNUSED,
0704 };
0705 
0706 int msm_hdmi_pll_8996_init(struct platform_device *pdev)
0707 {
0708     struct device *dev = &pdev->dev;
0709     struct hdmi_pll_8996 *pll;
0710     struct clk *clk;
0711     int i;
0712 
0713     pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
0714     if (!pll)
0715         return -ENOMEM;
0716 
0717     pll->pdev = pdev;
0718 
0719     pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll");
0720     if (IS_ERR(pll->mmio_qserdes_com)) {
0721         DRM_DEV_ERROR(dev, "failed to map pll base\n");
0722         return -ENOMEM;
0723     }
0724 
0725     for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
0726         char name[32];
0727 
0728         snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
0729 
0730         pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name);
0731         if (IS_ERR(pll->mmio_qserdes_tx[i])) {
0732             DRM_DEV_ERROR(dev, "failed to map pll base\n");
0733             return -ENOMEM;
0734         }
0735     }
0736     pll->clk_hw.init = &pll_init;
0737 
0738     clk = devm_clk_register(dev, &pll->clk_hw);
0739     if (IS_ERR(clk)) {
0740         DRM_DEV_ERROR(dev, "failed to register pll clock\n");
0741         return -EINVAL;
0742     }
0743 
0744     return 0;
0745 }
0746 
0747 static const char * const hdmi_phy_8996_reg_names[] = {
0748     "vddio",
0749     "vcca",
0750 };
0751 
0752 static const char * const hdmi_phy_8996_clk_names[] = {
0753     "iface", "ref",
0754 };
0755 
0756 const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg = {
0757     .type = MSM_HDMI_PHY_8996,
0758     .reg_names = hdmi_phy_8996_reg_names,
0759     .num_regs = ARRAY_SIZE(hdmi_phy_8996_reg_names),
0760     .clk_names = hdmi_phy_8996_clk_names,
0761     .num_clks = ARRAY_SIZE(hdmi_phy_8996_clk_names),
0762 };