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