linux/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 and
   6 * only version 2 as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 */
  13
  14#include <linux/clk-provider.h>
  15
  16#include "hdmi.h"
  17
  18#define HDMI_VCO_MAX_FREQ                       12000000000UL
  19#define HDMI_VCO_MIN_FREQ                       8000000000UL
  20
  21#define HDMI_PCLK_MAX_FREQ                      600000000
  22#define HDMI_PCLK_MIN_FREQ                      25000000
  23
  24#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD        3400000000UL
  25#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD         1500000000UL
  26#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD         750000000UL
  27#define HDMI_CORECLK_DIV                        5
  28#define HDMI_DEFAULT_REF_CLOCK                  19200000
  29#define HDMI_PLL_CMP_CNT                        1024
  30
  31#define HDMI_PLL_POLL_MAX_READS                 100
  32#define HDMI_PLL_POLL_TIMEOUT_US                150
  33
  34#define HDMI_NUM_TX_CHANNEL                     4
  35
  36struct hdmi_pll_8996 {
  37        struct platform_device *pdev;
  38        struct clk_hw clk_hw;
  39
  40        /* pll mmio base */
  41        void __iomem *mmio_qserdes_com;
  42        /* tx channel base */
  43        void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL];
  44};
  45
  46#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8996, clk_hw)
  47
  48struct hdmi_8996_phy_pll_reg_cfg {
  49        u32 tx_lx_lane_mode[HDMI_NUM_TX_CHANNEL];
  50        u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL];
  51        u32 com_svs_mode_clk_sel;
  52        u32 com_hsclk_sel;
  53        u32 com_pll_cctrl_mode0;
  54        u32 com_pll_rctrl_mode0;
  55        u32 com_cp_ctrl_mode0;
  56        u32 com_dec_start_mode0;
  57        u32 com_div_frac_start1_mode0;
  58        u32 com_div_frac_start2_mode0;
  59        u32 com_div_frac_start3_mode0;
  60        u32 com_integloop_gain0_mode0;
  61        u32 com_integloop_gain1_mode0;
  62        u32 com_lock_cmp_en;
  63        u32 com_lock_cmp1_mode0;
  64        u32 com_lock_cmp2_mode0;
  65        u32 com_lock_cmp3_mode0;
  66        u32 com_core_clk_en;
  67        u32 com_coreclk_div;
  68        u32 com_vco_tune_ctrl;
  69
  70        u32 tx_lx_tx_drv_lvl[HDMI_NUM_TX_CHANNEL];
  71        u32 tx_lx_tx_emp_post1_lvl[HDMI_NUM_TX_CHANNEL];
  72        u32 tx_lx_vmode_ctrl1[HDMI_NUM_TX_CHANNEL];
  73        u32 tx_lx_vmode_ctrl2[HDMI_NUM_TX_CHANNEL];
  74        u32 tx_lx_res_code_lane_tx[HDMI_NUM_TX_CHANNEL];
  75        u32 tx_lx_hp_pd_enables[HDMI_NUM_TX_CHANNEL];
  76
  77        u32 phy_mode;
  78};
  79
  80struct hdmi_8996_post_divider {
  81        u64 vco_freq;
  82        int hsclk_divsel;
  83        int vco_ratio;
  84        int tx_band_sel;
  85        int half_rate_mode;
  86};
  87
  88static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8996 *pll)
  89{
  90        return platform_get_drvdata(pll->pdev);
  91}
  92
  93static inline void hdmi_pll_write(struct hdmi_pll_8996 *pll, int offset,
  94                                  u32 data)
  95{
  96        msm_writel(data, pll->mmio_qserdes_com + offset);
  97}
  98
  99static inline u32 hdmi_pll_read(struct hdmi_pll_8996 *pll, int offset)
 100{
 101        return msm_readl(pll->mmio_qserdes_com + offset);
 102}
 103
 104static inline void hdmi_tx_chan_write(struct hdmi_pll_8996 *pll, int channel,
 105                                      int offset, int data)
 106{
 107         msm_writel(data, pll->mmio_qserdes_tx[channel] + offset);
 108}
 109
 110static inline u32 pll_get_cpctrl(u64 frac_start, unsigned long ref_clk,
 111                                 bool gen_ssc)
 112{
 113        if ((frac_start != 0) || gen_ssc)
 114                return (11000000 / (ref_clk / 20));
 115
 116        return 0x23;
 117}
 118
 119static inline u32 pll_get_rctrl(u64 frac_start, bool gen_ssc)
 120{
 121        if ((frac_start != 0) || gen_ssc)
 122                return 0x16;
 123
 124        return 0x10;
 125}
 126
 127static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc)
 128{
 129        if ((frac_start != 0) || gen_ssc)
 130                return 0x28;
 131
 132        return 0x1;
 133}
 134
 135static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref_clk,
 136                                         bool gen_ssc)
 137{
 138        int digclk_divsel = bclk >= HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2;
 139        u64 base;
 140
 141        if ((frac_start != 0) || gen_ssc)
 142                base = (64 * ref_clk) / HDMI_DEFAULT_REF_CLOCK;
 143        else
 144                base = (1022 * ref_clk) / 100;
 145
 146        base <<= digclk_divsel;
 147
 148        return (base <= 2046 ? base : 2046);
 149}
 150
 151static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
 152{
 153        u64 dividend = HDMI_PLL_CMP_CNT * fdata;
 154        u32 divisor = ref_clk * 10;
 155        u32 rem;
 156
 157        rem = do_div(dividend, divisor);
 158        if (rem > (divisor >> 1))
 159                dividend++;
 160
 161        return dividend - 1;
 162}
 163
 164static inline u64 pll_cmp_to_fdata(u32 pll_cmp, unsigned long ref_clk)
 165{
 166        u64 fdata = ((u64)pll_cmp) * ref_clk * 10;
 167
 168        do_div(fdata, HDMI_PLL_CMP_CNT);
 169
 170        return fdata;
 171}
 172
 173static int pll_get_post_div(struct hdmi_8996_post_divider *pd, u64 bclk)
 174{
 175        int ratio[] = { 2, 3, 4, 5, 6, 9, 10, 12, 14, 15, 20, 21, 25, 28, 35 };
 176        int hs_divsel[] = { 0, 4, 8, 12, 1, 5, 2, 9, 3, 13, 10, 7, 14, 11, 15 };
 177        int tx_band_sel[] = { 0, 1, 2, 3 };
 178        u64 vco_freq[60];
 179        u64 vco, vco_optimal;
 180        int half_rate_mode = 0;
 181        int vco_optimal_index, vco_freq_index;
 182        int i, j;
 183
 184retry:
 185        vco_optimal = HDMI_VCO_MAX_FREQ;
 186        vco_optimal_index = -1;
 187        vco_freq_index = 0;
 188        for (i = 0; i < 15; i++) {
 189                for (j = 0; j < 4; j++) {
 190                        u32 ratio_mult = ratio[i] << tx_band_sel[j];
 191
 192                        vco = bclk >> half_rate_mode;
 193                        vco *= ratio_mult;
 194                        vco_freq[vco_freq_index++] = vco;
 195                }
 196        }
 197
 198        for (i = 0; i < 60; i++) {
 199                u64 vco_tmp = vco_freq[i];
 200
 201                if ((vco_tmp >= HDMI_VCO_MIN_FREQ) &&
 202                    (vco_tmp <= vco_optimal)) {
 203                        vco_optimal = vco_tmp;
 204                        vco_optimal_index = i;
 205                }
 206        }
 207
 208        if (vco_optimal_index == -1) {
 209                if (!half_rate_mode) {
 210                        half_rate_mode = 1;
 211                        goto retry;
 212                }
 213        } else {
 214                pd->vco_freq = vco_optimal;
 215                pd->tx_band_sel = tx_band_sel[vco_optimal_index % 4];
 216                pd->vco_ratio = ratio[vco_optimal_index / 4];
 217                pd->hsclk_divsel = hs_divsel[vco_optimal_index / 4];
 218
 219                return 0;
 220        }
 221
 222        return -EINVAL;
 223}
 224
 225static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk,
 226                         struct hdmi_8996_phy_pll_reg_cfg *cfg)
 227{
 228        struct hdmi_8996_post_divider pd;
 229        u64 bclk;
 230        u64 tmds_clk;
 231        u64 dec_start;
 232        u64 frac_start;
 233        u64 fdata;
 234        u32 pll_divisor;
 235        u32 rem;
 236        u32 cpctrl;
 237        u32 rctrl;
 238        u32 cctrl;
 239        u32 integloop_gain;
 240        u32 pll_cmp;
 241        int i, ret;
 242
 243        /* bit clk = 10 * pix_clk */
 244        bclk = ((u64)pix_clk) * 10;
 245
 246        if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD)
 247                tmds_clk = pix_clk >> 2;
 248        else
 249                tmds_clk = pix_clk;
 250
 251        ret = pll_get_post_div(&pd, bclk);
 252        if (ret)
 253                return ret;
 254
 255        dec_start = pd.vco_freq;
 256        pll_divisor = 4 * ref_clk;
 257        do_div(dec_start, pll_divisor);
 258
 259        frac_start = pd.vco_freq * (1 << 20);
 260
 261        rem = do_div(frac_start, pll_divisor);
 262        frac_start -= dec_start * (1 << 20);
 263        if (rem > (pll_divisor >> 1))
 264                frac_start++;
 265
 266        cpctrl = pll_get_cpctrl(frac_start, ref_clk, false);
 267        rctrl = pll_get_rctrl(frac_start, false);
 268        cctrl = pll_get_cctrl(frac_start, false);
 269        integloop_gain = pll_get_integloop_gain(frac_start, bclk,
 270                                                ref_clk, false);
 271
 272        fdata = pd.vco_freq;
 273        do_div(fdata, pd.vco_ratio);
 274
 275        pll_cmp = pll_get_pll_cmp(fdata, ref_clk);
 276
 277        DBG("VCO freq: %llu", pd.vco_freq);
 278        DBG("fdata: %llu", fdata);
 279        DBG("pix_clk: %lu", pix_clk);
 280        DBG("tmds clk: %llu", tmds_clk);
 281        DBG("HSCLK_SEL: %d", pd.hsclk_divsel);
 282        DBG("DEC_START: %llu", dec_start);
 283        DBG("DIV_FRAC_START: %llu", frac_start);
 284        DBG("PLL_CPCTRL: %u", cpctrl);
 285        DBG("PLL_RCTRL: %u", rctrl);
 286        DBG("PLL_CCTRL: %u", cctrl);
 287        DBG("INTEGLOOP_GAIN: %u", integloop_gain);
 288        DBG("TX_BAND: %d", pd.tx_band_sel);
 289        DBG("PLL_CMP: %u", pll_cmp);
 290
 291        /* Convert these values to register specific values */
 292        if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD)
 293                cfg->com_svs_mode_clk_sel = 1;
 294        else
 295                cfg->com_svs_mode_clk_sel = 2;
 296
 297        cfg->com_hsclk_sel = (0x20 | pd.hsclk_divsel);
 298        cfg->com_pll_cctrl_mode0 = cctrl;
 299        cfg->com_pll_rctrl_mode0 = rctrl;
 300        cfg->com_cp_ctrl_mode0 = cpctrl;
 301        cfg->com_dec_start_mode0 = dec_start;
 302        cfg->com_div_frac_start1_mode0 = (frac_start & 0xff);
 303        cfg->com_div_frac_start2_mode0 = ((frac_start & 0xff00) >> 8);
 304        cfg->com_div_frac_start3_mode0 = ((frac_start & 0xf0000) >> 16);
 305        cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xff);
 306        cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xf00) >> 8);
 307        cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xff);
 308        cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xff00) >> 8);
 309        cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16);
 310        cfg->com_lock_cmp_en = 0x0;
 311        cfg->com_core_clk_en = 0x2c;
 312        cfg->com_coreclk_div = HDMI_CORECLK_DIV;
 313        cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0;
 314        cfg->com_vco_tune_ctrl = 0x0;
 315
 316        cfg->tx_lx_lane_mode[0] =
 317                cfg->tx_lx_lane_mode[2] = 0x43;
 318
 319        cfg->tx_lx_hp_pd_enables[0] =
 320                cfg->tx_lx_hp_pd_enables[1] =
 321                cfg->tx_lx_hp_pd_enables[2] = 0x0c;
 322        cfg->tx_lx_hp_pd_enables[3] = 0x3;
 323
 324        for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
 325                cfg->tx_lx_tx_band[i] = pd.tx_band_sel + 4;
 326
 327        if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) {
 328                cfg->tx_lx_tx_drv_lvl[0] =
 329                        cfg->tx_lx_tx_drv_lvl[1] =
 330                        cfg->tx_lx_tx_drv_lvl[2] = 0x25;
 331                cfg->tx_lx_tx_drv_lvl[3] = 0x22;
 332
 333                cfg->tx_lx_tx_emp_post1_lvl[0] =
 334                        cfg->tx_lx_tx_emp_post1_lvl[1] =
 335                        cfg->tx_lx_tx_emp_post1_lvl[2] = 0x23;
 336                cfg->tx_lx_tx_emp_post1_lvl[3] = 0x27;
 337
 338                cfg->tx_lx_vmode_ctrl1[0] =
 339                        cfg->tx_lx_vmode_ctrl1[1] =
 340                        cfg->tx_lx_vmode_ctrl1[2] =
 341                        cfg->tx_lx_vmode_ctrl1[3] = 0x00;
 342
 343                cfg->tx_lx_vmode_ctrl2[0] =
 344                        cfg->tx_lx_vmode_ctrl2[1] =
 345                        cfg->tx_lx_vmode_ctrl2[2] = 0x0D;
 346
 347                cfg->tx_lx_vmode_ctrl2[3] = 0x00;
 348        } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) {
 349                for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
 350                        cfg->tx_lx_tx_drv_lvl[i] = 0x25;
 351                        cfg->tx_lx_tx_emp_post1_lvl[i] = 0x23;
 352                        cfg->tx_lx_vmode_ctrl1[i] = 0x00;
 353                }
 354
 355                cfg->tx_lx_vmode_ctrl2[0] =
 356                        cfg->tx_lx_vmode_ctrl2[1] =
 357                        cfg->tx_lx_vmode_ctrl2[2] = 0x0D;
 358                cfg->tx_lx_vmode_ctrl2[3] = 0x00;
 359        } else {
 360                for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
 361                        cfg->tx_lx_tx_drv_lvl[i] = 0x20;
 362                        cfg->tx_lx_tx_emp_post1_lvl[i] = 0x20;
 363                        cfg->tx_lx_vmode_ctrl1[i] = 0x00;
 364                        cfg->tx_lx_vmode_ctrl2[i] = 0x0E;
 365                }
 366        }
 367
 368        DBG("com_svs_mode_clk_sel = 0x%x", cfg->com_svs_mode_clk_sel);
 369        DBG("com_hsclk_sel = 0x%x", cfg->com_hsclk_sel);
 370        DBG("com_lock_cmp_en = 0x%x", cfg->com_lock_cmp_en);
 371        DBG("com_pll_cctrl_mode0 = 0x%x", cfg->com_pll_cctrl_mode0);
 372        DBG("com_pll_rctrl_mode0 = 0x%x", cfg->com_pll_rctrl_mode0);
 373        DBG("com_cp_ctrl_mode0 = 0x%x", cfg->com_cp_ctrl_mode0);
 374        DBG("com_dec_start_mode0 = 0x%x", cfg->com_dec_start_mode0);
 375        DBG("com_div_frac_start1_mode0 = 0x%x", cfg->com_div_frac_start1_mode0);
 376        DBG("com_div_frac_start2_mode0 = 0x%x", cfg->com_div_frac_start2_mode0);
 377        DBG("com_div_frac_start3_mode0 = 0x%x", cfg->com_div_frac_start3_mode0);
 378        DBG("com_integloop_gain0_mode0 = 0x%x", cfg->com_integloop_gain0_mode0);
 379        DBG("com_integloop_gain1_mode0 = 0x%x", cfg->com_integloop_gain1_mode0);
 380        DBG("com_lock_cmp1_mode0 = 0x%x", cfg->com_lock_cmp1_mode0);
 381        DBG("com_lock_cmp2_mode0 = 0x%x", cfg->com_lock_cmp2_mode0);
 382        DBG("com_lock_cmp3_mode0 = 0x%x", cfg->com_lock_cmp3_mode0);
 383        DBG("com_core_clk_en = 0x%x", cfg->com_core_clk_en);
 384        DBG("com_coreclk_div = 0x%x", cfg->com_coreclk_div);
 385        DBG("phy_mode = 0x%x", cfg->phy_mode);
 386
 387        DBG("tx_l0_lane_mode = 0x%x", cfg->tx_lx_lane_mode[0]);
 388        DBG("tx_l2_lane_mode = 0x%x", cfg->tx_lx_lane_mode[2]);
 389
 390        for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
 391                DBG("tx_l%d_tx_band = 0x%x", i, cfg->tx_lx_tx_band[i]);
 392                DBG("tx_l%d_tx_drv_lvl = 0x%x", i, cfg->tx_lx_tx_drv_lvl[i]);
 393                DBG("tx_l%d_tx_emp_post1_lvl = 0x%x", i,
 394                    cfg->tx_lx_tx_emp_post1_lvl[i]);
 395                DBG("tx_l%d_vmode_ctrl1 = 0x%x", i, cfg->tx_lx_vmode_ctrl1[i]);
 396                DBG("tx_l%d_vmode_ctrl2 = 0x%x", i, cfg->tx_lx_vmode_ctrl2[i]);
 397        }
 398
 399        return 0;
 400}
 401
 402static int hdmi_8996_pll_set_clk_rate(struct clk_hw *hw, unsigned long rate,
 403                                      unsigned long parent_rate)
 404{
 405        struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
 406        struct hdmi_phy *phy = pll_get_phy(pll);
 407        struct hdmi_8996_phy_pll_reg_cfg cfg;
 408        int i, ret;
 409
 410        memset(&cfg, 0x00, sizeof(cfg));
 411
 412        ret = pll_calculate(rate, parent_rate, &cfg);
 413        if (ret) {
 414                DRM_ERROR("PLL calculation failed\n");
 415                return ret;
 416        }
 417
 418        /* Initially shut down PHY */
 419        DBG("Disabling PHY");
 420        hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x0);
 421        udelay(500);
 422
 423        /* Power up sequence */
 424        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x04);
 425
 426        hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1);
 427        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20);
 428        hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX0_TX1_LANE_CTL, 0x0F);
 429        hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX2_TX3_LANE_CTL, 0x0F);
 430
 431        for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
 432                hdmi_tx_chan_write(pll, i,
 433                                   REG_HDMI_PHY_QSERDES_TX_LX_CLKBUF_ENABLE,
 434                                   0x03);
 435                hdmi_tx_chan_write(pll, i,
 436                                   REG_HDMI_PHY_QSERDES_TX_LX_TX_BAND,
 437                                   cfg.tx_lx_tx_band[i]);
 438                hdmi_tx_chan_write(pll, i,
 439                                   REG_HDMI_PHY_QSERDES_TX_LX_RESET_TSYNC_EN,
 440                                   0x03);
 441        }
 442
 443        hdmi_tx_chan_write(pll, 0, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE,
 444                           cfg.tx_lx_lane_mode[0]);
 445        hdmi_tx_chan_write(pll, 2, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE,
 446                           cfg.tx_lx_lane_mode[2]);
 447
 448        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1E);
 449        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x07);
 450        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37);
 451        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02);
 452        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E);
 453
 454        /* Bypass VCO calibration */
 455        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SVS_MODE_CLK_SEL,
 456                       cfg.com_svs_mode_clk_sel);
 457
 458        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_TRIM, 0x0F);
 459        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_IVCO, 0x0F);
 460        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_CTRL,
 461                       cfg.com_vco_tune_ctrl);
 462
 463        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x06);
 464
 465        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_SELECT, 0x30);
 466        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_HSCLK_SEL,
 467                       cfg.com_hsclk_sel);
 468        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP_EN,
 469                       cfg.com_lock_cmp_en);
 470
 471        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_CCTRL_MODE0,
 472                       cfg.com_pll_cctrl_mode0);
 473        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_RCTRL_MODE0,
 474                       cfg.com_pll_rctrl_mode0);
 475        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CP_CTRL_MODE0,
 476                       cfg.com_cp_ctrl_mode0);
 477        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DEC_START_MODE0,
 478                       cfg.com_dec_start_mode0);
 479        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0,
 480                       cfg.com_div_frac_start1_mode0);
 481        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0,
 482                       cfg.com_div_frac_start2_mode0);
 483        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0,
 484                       cfg.com_div_frac_start3_mode0);
 485
 486        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0,
 487                       cfg.com_integloop_gain0_mode0);
 488        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0,
 489                       cfg.com_integloop_gain1_mode0);
 490
 491        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0,
 492                       cfg.com_lock_cmp1_mode0);
 493        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0,
 494                       cfg.com_lock_cmp2_mode0);
 495        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0,
 496                       cfg.com_lock_cmp3_mode0);
 497
 498        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00);
 499        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORE_CLK_EN,
 500                       cfg.com_core_clk_en);
 501        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORECLK_DIV,
 502                       cfg.com_coreclk_div);
 503        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CMN_CONFIG, 0x02);
 504
 505        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESCODE_DIV_NUM, 0x15);
 506
 507        /* TX lanes setup (TX 0/1/2/3) */
 508        for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
 509                hdmi_tx_chan_write(pll, i,
 510                                   REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL,
 511                                   cfg.tx_lx_tx_drv_lvl[i]);
 512                hdmi_tx_chan_write(pll, i,
 513                                   REG_HDMI_PHY_QSERDES_TX_LX_TX_EMP_POST1_LVL,
 514                                   cfg.tx_lx_tx_emp_post1_lvl[i]);
 515                hdmi_tx_chan_write(pll, i,
 516                                   REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL1,
 517                                   cfg.tx_lx_vmode_ctrl1[i]);
 518                hdmi_tx_chan_write(pll, i,
 519                                   REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL2,
 520                                   cfg.tx_lx_vmode_ctrl2[i]);
 521                hdmi_tx_chan_write(pll, i,
 522                                   REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL_OFFSET,
 523                                   0x00);
 524                hdmi_tx_chan_write(pll, i,
 525                        REG_HDMI_PHY_QSERDES_TX_LX_RES_CODE_LANE_OFFSET,
 526                        0x00);
 527                hdmi_tx_chan_write(pll, i,
 528                        REG_HDMI_PHY_QSERDES_TX_LX_TRAN_DRVR_EMP_EN,
 529                        0x03);
 530                hdmi_tx_chan_write(pll, i,
 531                        REG_HDMI_PHY_QSERDES_TX_LX_PARRATE_REC_DETECT_IDLE_EN,
 532                        0x40);
 533                hdmi_tx_chan_write(pll, i,
 534                                   REG_HDMI_PHY_QSERDES_TX_LX_HP_PD_ENABLES,
 535                                   cfg.tx_lx_hp_pd_enables[i]);
 536        }
 537
 538        hdmi_phy_write(phy, REG_HDMI_8996_PHY_MODE, cfg.phy_mode);
 539        hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1F);
 540
 541        /*
 542         * Ensure that vco configuration gets flushed to hardware before
 543         * enabling the PLL
 544         */
 545        wmb();
 546
 547        return 0;
 548}
 549
 550static int hdmi_8996_phy_ready_status(struct hdmi_phy *phy)
 551{
 552        u32 nb_tries = HDMI_PLL_POLL_MAX_READS;
 553        unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
 554        u32 status;
 555        int phy_ready = 0;
 556
 557        DBG("Waiting for PHY ready");
 558
 559        while (nb_tries--) {
 560                status = hdmi_phy_read(phy, REG_HDMI_8996_PHY_STATUS);
 561                phy_ready = status & BIT(0);
 562
 563                if (phy_ready)
 564                        break;
 565
 566                udelay(timeout);
 567        }
 568
 569        DBG("PHY is %sready", phy_ready ? "" : "*not* ");
 570
 571        return phy_ready;
 572}
 573
 574static int hdmi_8996_pll_lock_status(struct hdmi_pll_8996 *pll)
 575{
 576        u32 status;
 577        int nb_tries = HDMI_PLL_POLL_MAX_READS;
 578        unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US;
 579        int pll_locked = 0;
 580
 581        DBG("Waiting for PLL lock");
 582
 583        while (nb_tries--) {
 584                status = hdmi_pll_read(pll,
 585                                       REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS);
 586                pll_locked = status & BIT(0);
 587
 588                if (pll_locked)
 589                        break;
 590
 591                udelay(timeout);
 592        }
 593
 594        DBG("HDMI PLL is %slocked", pll_locked ? "" : "*not* ");
 595
 596        return pll_locked;
 597}
 598
 599static int hdmi_8996_pll_prepare(struct clk_hw *hw)
 600{
 601        struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
 602        struct hdmi_phy *phy = pll_get_phy(pll);
 603        int i, ret = 0;
 604
 605        hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x1);
 606        udelay(100);
 607
 608        hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19);
 609        udelay(100);
 610
 611        ret = hdmi_8996_pll_lock_status(pll);
 612        if (!ret)
 613                return ret;
 614
 615        for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++)
 616                hdmi_tx_chan_write(pll, i,
 617                        REG_HDMI_PHY_QSERDES_TX_LX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN,
 618                        0x6F);
 619
 620        /* Disable SSC */
 621        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER1, 0x0);
 622        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER2, 0x0);
 623        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE1, 0x0);
 624        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE2, 0x0);
 625        hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_EN_CENTER, 0x2);
 626
 627        ret = hdmi_8996_phy_ready_status(phy);
 628        if (!ret)
 629                return ret;
 630
 631        /* Restart the retiming buffer */
 632        hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x18);
 633        udelay(1);
 634        hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19);
 635
 636        return 0;
 637}
 638
 639static long hdmi_8996_pll_round_rate(struct clk_hw *hw,
 640                                     unsigned long rate,
 641                                     unsigned long *parent_rate)
 642{
 643        if (rate < HDMI_PCLK_MIN_FREQ)
 644                return HDMI_PCLK_MIN_FREQ;
 645        else if (rate > HDMI_PCLK_MAX_FREQ)
 646                return HDMI_PCLK_MAX_FREQ;
 647        else
 648                return rate;
 649}
 650
 651static unsigned long hdmi_8996_pll_recalc_rate(struct clk_hw *hw,
 652                                               unsigned long parent_rate)
 653{
 654        struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
 655        u64 fdata;
 656        u32 cmp1, cmp2, cmp3, pll_cmp;
 657
 658        cmp1 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0);
 659        cmp2 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0);
 660        cmp3 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0);
 661
 662        pll_cmp = cmp1 | (cmp2 << 8) | (cmp3 << 16);
 663
 664        fdata = pll_cmp_to_fdata(pll_cmp + 1, parent_rate);
 665
 666        do_div(fdata, 10);
 667
 668        return fdata;
 669}
 670
 671static void hdmi_8996_pll_unprepare(struct clk_hw *hw)
 672{
 673}
 674
 675static int hdmi_8996_pll_is_enabled(struct clk_hw *hw)
 676{
 677        struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw);
 678        u32 status;
 679        int pll_locked;
 680
 681        status = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS);
 682        pll_locked = status & BIT(0);
 683
 684        return pll_locked;
 685}
 686
 687static struct clk_ops hdmi_8996_pll_ops = {
 688        .set_rate = hdmi_8996_pll_set_clk_rate,
 689        .round_rate = hdmi_8996_pll_round_rate,
 690        .recalc_rate = hdmi_8996_pll_recalc_rate,
 691        .prepare = hdmi_8996_pll_prepare,
 692        .unprepare = hdmi_8996_pll_unprepare,
 693        .is_enabled = hdmi_8996_pll_is_enabled,
 694};
 695
 696static const char * const hdmi_pll_parents[] = {
 697        "xo",
 698};
 699
 700static struct clk_init_data pll_init = {
 701        .name = "hdmipll",
 702        .ops = &hdmi_8996_pll_ops,
 703        .parent_names = hdmi_pll_parents,
 704        .num_parents = ARRAY_SIZE(hdmi_pll_parents),
 705        .flags = CLK_IGNORE_UNUSED,
 706};
 707
 708int msm_hdmi_pll_8996_init(struct platform_device *pdev)
 709{
 710        struct device *dev = &pdev->dev;
 711        struct hdmi_pll_8996 *pll;
 712        struct clk *clk;
 713        int i;
 714
 715        pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
 716        if (!pll)
 717                return -ENOMEM;
 718
 719        pll->pdev = pdev;
 720
 721        pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll", "HDMI_PLL");
 722        if (IS_ERR(pll->mmio_qserdes_com)) {
 723                dev_err(dev, "failed to map pll base\n");
 724                return -ENOMEM;
 725        }
 726
 727        for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
 728                char name[32], label[32];
 729
 730                snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
 731                snprintf(label, sizeof(label), "HDMI_TX_L%d", i);
 732
 733                pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name, label);
 734                if (IS_ERR(pll->mmio_qserdes_tx[i])) {
 735                        dev_err(dev, "failed to map pll base\n");
 736                        return -ENOMEM;
 737                }
 738        }
 739        pll->clk_hw.init = &pll_init;
 740
 741        clk = devm_clk_register(dev, &pll->clk_hw);
 742        if (IS_ERR(clk)) {
 743                dev_err(dev, "failed to register pll clock\n");
 744                return -EINVAL;
 745        }
 746
 747        return 0;
 748}
 749
 750static const char * const hdmi_phy_8996_reg_names[] = {
 751        "vddio",
 752        "vcca",
 753};
 754
 755static const char * const hdmi_phy_8996_clk_names[] = {
 756        "mmagic_iface_clk",
 757        "iface_clk",
 758        "ref_clk",
 759};
 760
 761const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg = {
 762        .type = MSM_HDMI_PHY_8996,
 763        .reg_names = hdmi_phy_8996_reg_names,
 764        .num_regs = ARRAY_SIZE(hdmi_phy_8996_reg_names),
 765        .clk_names = hdmi_phy_8996_clk_names,
 766        .num_clks = ARRAY_SIZE(hdmi_phy_8996_clk_names),
 767};
 768