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