xref: /linux/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c (revision 7fc7f25419f5a6b09199ba4b5026b94ef184fa79)
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 struct clk_init_data pll_init = {
695 	.name = "hdmipll",
696 	.ops = &hdmi_8996_pll_ops,
697 	.parent_data = (const struct clk_parent_data[]){
698 		{ .fw_name = "xo", .name = "xo_board" },
699 	},
700 	.num_parents = 1,
701 	.flags = CLK_IGNORE_UNUSED,
702 };
703 
704 int msm_hdmi_pll_8996_init(struct platform_device *pdev)
705 {
706 	struct device *dev = &pdev->dev;
707 	struct hdmi_pll_8996 *pll;
708 	int i, ret;
709 
710 	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
711 	if (!pll)
712 		return -ENOMEM;
713 
714 	pll->pdev = pdev;
715 
716 	pll->mmio_qserdes_com = msm_ioremap(pdev, "hdmi_pll");
717 	if (IS_ERR(pll->mmio_qserdes_com)) {
718 		DRM_DEV_ERROR(dev, "failed to map pll base\n");
719 		return -ENOMEM;
720 	}
721 
722 	for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) {
723 		char name[32];
724 
725 		snprintf(name, sizeof(name), "hdmi_tx_l%d", i);
726 
727 		pll->mmio_qserdes_tx[i] = msm_ioremap(pdev, name);
728 		if (IS_ERR(pll->mmio_qserdes_tx[i])) {
729 			DRM_DEV_ERROR(dev, "failed to map pll base\n");
730 			return -ENOMEM;
731 		}
732 	}
733 	pll->clk_hw.init = &pll_init;
734 
735 	ret = devm_clk_hw_register(dev, &pll->clk_hw);
736 	if (ret) {
737 		DRM_DEV_ERROR(dev, "failed to register pll clock\n");
738 		return ret;
739 	}
740 
741 	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_hw);
742 	if (ret) {
743 		DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__, ret);
744 		return ret;
745 	}
746 
747 	return 0;
748 }
749 
750 static const char * const hdmi_phy_8996_reg_names[] = {
751 	"vddio",
752 	"vcca",
753 };
754 
755 static const char * const hdmi_phy_8996_clk_names[] = {
756 	"iface", "ref",
757 };
758 
759 const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg = {
760 	.type = MSM_HDMI_PHY_8996,
761 	.reg_names = hdmi_phy_8996_reg_names,
762 	.num_regs = ARRAY_SIZE(hdmi_phy_8996_reg_names),
763 	.clk_names = hdmi_phy_8996_clk_names,
764 	.num_clks = ARRAY_SIZE(hdmi_phy_8996_clk_names),
765 };
766