Merge tag 'drm-misc-next-2021-10-14' of git://anongit.freedesktop.org/drm/drm-misc...
[linux-2.6-microblaze.git] / drivers / gpu / drm / msm / hdmi / hdmi_phy_8996.c
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
29 struct 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
41 struct 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
73 struct 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
81 static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8996 *pll)
82 {
83         return platform_get_drvdata(pll->pdev);
84 }
85
86 static 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
92 static inline u32 hdmi_pll_read(struct hdmi_pll_8996 *pll, int offset)
93 {
94         return msm_readl(pll->mmio_qserdes_com + offset);
95 }
96
97 static 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
103 static 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
112 static 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
120 static 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
128 static 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
144 static 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
157 static 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
166 static 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
177 retry:
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
218 static 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
395 static 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
543 static 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
567 static 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
592 static 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
632 static 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
644 static 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
664 static 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
673 static 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
685 static const 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
694 static const char * const hdmi_pll_parents[] = {
695         "xo",
696 };
697
698 static const 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
706 int 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
748 static const char * const hdmi_phy_8996_reg_names[] = {
749         "vddio",
750         "vcca",
751 };
752
753 static const char * const hdmi_phy_8996_clk_names[] = {
754         "iface", "ref",
755 };
756
757 const 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 };