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