xref: /aosp_15_r20/external/coreboot/src/soc/qualcomm/sc7180/display/dsi_phy.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <delay.h>
5 #include <device/mmio.h>
6 #include <edid.h>
7 #include <lib.h>
8 #include <soc/clock.h>
9 #include <soc/display/dsi_phy.h>
10 #include <soc/display/mdssreg.h>
11 #include <soc/display/display_resources.h>
12 #include <string.h>
13 #include <timer.h>
14 
15 #define HAL_DSI_PHY_PLL_READY_TIMEOUT_MS               150           /* ~15 ms */
16 #define HAL_DSI_PHY_REFGEN_TIMEOUT_MS                  150           /* ~15 ms */
17 
18 #define DSI_MAX_REFRESH_RATE       95
19 #define DSI_MIN_REFRESH_RATE       15
20 
21 #define HAL_DSI_PLL_VCO_MIN_MHZ_2_2_0               1000
22 
23 #define S_DIV_ROUND_UP(n, d)	\
24 	(((n) >= 0) ? (((n) + (d) - 1) / (d)) : (((n) - (d) + 1) / (d)))
25 
26 #define mult_frac(x, numer, denom)(			\
27 {							\
28 	typeof(x) quot = (x) / (denom);			\
29 	typeof(x) rem  = (x) % (denom);			\
30 	(quot * (numer)) + ((rem * (numer)) / (denom));	\
31 }							\
32 )
33 
34 struct dsi_phy_divider_lut_entry_type {
35 	uint16_t        pll_post_div;
36 	uint16_t        phy_post_div;
37 };
38 
39 /* PLL divider LUTs */
40 static struct dsi_phy_divider_lut_entry_type pll_dividerlut_dphy[] = {
41 /* pll post div will always be power of 2 */
42 	{ 2, 11 },
43 	{ 4, 5 },
44 	{ 2, 9 },
45 	{ 8, 2 },
46 	{ 1, 15 },
47 	{ 2, 7 },
48 	{ 1, 13 },
49 	{ 4, 3 },
50 	{ 1, 11 },
51 	{ 2, 5 },
52 	{ 1, 9 },
53 	{ 8, 1 },
54 	{ 1, 7 },
55 	{ 2, 3 },
56 	{ 1, 5 },
57 	{ 4, 1 },
58 	{ 1, 3 },
59 	{ 2, 1 },
60 	{ 1, 1 }
61 };
62 
63 enum dsi_laneid_type {
64 	DSI_LANEID_0 = 0,
65 	DSI_LANEID_1,
66 	DSI_LANEID_2,
67 	DSI_LANEID_3,
68 	DSI_LANEID_CLK,
69 	DSI_LANEID_MAX,
70 	DSI_LANEID_FORCE_32BIT = 0x7FFFFFFF
71 };
72 
73 struct dsi_phy_configtype {
74 	uint32_t desired_bitclk_freq;
75 	uint32_t bits_per_pixel;
76 	uint32_t num_data_lanes;
77 	uint32_t pclk_divnumerator;
78 	uint32_t pclk_divdenominator;
79 
80 	/* pixel clk source select */
81 	uint32_t phy_post_div;
82 	uint32_t pll_post_div;
83 };
84 
linear_inter(s32 tmax,s32 tmin,s32 percent,s32 min_result,bool even)85 static inline s32 linear_inter(s32 tmax, s32 tmin, s32 percent,
86 				s32 min_result, bool even)
87 {
88 	s32 v;
89 
90 	v = (tmax - tmin) * percent;
91 	v = S_DIV_ROUND_UP(v, 100) + tmin;
92 	if (even && (v & 0x1))
93 		return MAX(min_result, v - 1);
94 
95 	return MAX(min_result, v);
96 }
97 
mdss_dsi_phy_reset(void)98 static void mdss_dsi_phy_reset(void)
99 {
100 	write32(&dsi0_phy->phy_cmn_ctrl1, 0x40);
101 	udelay(100);
102 	write32(&dsi0_phy->phy_cmn_ctrl1, 0x0);
103 }
104 
mdss_dsi_power_down(void)105 static void mdss_dsi_power_down(void)
106 {
107 	/* power up DIGTOP & PLL */
108 	write32(&dsi0_phy->phy_cmn_ctrl0, 0x60);
109 
110 	/* Disable PLL */
111 	write32(&dsi0_phy->phy_cmn_pll_ctrl, 0x0);
112 
113 	/* Resync re-time FIFO OFF*/
114 	write32(&dsi0_phy->phy_cmn_rbuf_ctrl, 0x0);
115 }
116 
mdss_dsi_phy_setup_lanephy(enum dsi_laneid_type lane)117 static void mdss_dsi_phy_setup_lanephy(enum dsi_laneid_type lane)
118 {
119 	uint32_t reg_val = 0;
120 	uint32_t lprx_ctrl = 0;
121 	uint32_t hstx_strength = 0x88;
122 	uint32_t data_strength_lp_n = 0x5;
123 	uint32_t data_strength_lp_p = 0x5;
124 	uint32_t pemph_bottom = 0;
125 	uint32_t pemph_top = 0;
126 	uint32_t strength_override = 0;
127 	uint32_t clk_lane = 0;
128 
129 	if (lane == DSI_LANEID_CLK)
130 		clk_lane = 1;
131 	else
132 		clk_lane = 0;
133 
134 	if (lane == DSI_LANEID_0)
135 		lprx_ctrl = 3;
136 
137 	/*
138 	 * DSIPHY_STR_LP_N
139 	 * DSIPHY_STR_LP_P
140 	 */
141 	reg_val = ((data_strength_lp_n << 0x4) & 0xf0) |
142 		   (data_strength_lp_p & 0x0f);
143 
144 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_lptx_str_ctrl, reg_val);
145 
146 	/*
147 	 * DSIPHY_LPRX_EN
148 	 * DSIPHY_CDRX_EN
149 	 * Transition from 0 to 1 for DLN0-3 CLKLN stays 0
150 	 */
151 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_lprx_ctrl, 0x0);
152 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_lprx_ctrl, lprx_ctrl);
153 
154 	/* Pin Swap */
155 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_pin_swap, 0x0);
156 
157 	/*
158 	 * DSIPHY_HSTX_STR_HSTOP
159 	 * DSIPHY_HSTX_STR_HSBOT
160 	 */
161 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_hstx_str_ctrl, hstx_strength);
162 
163 	/* PGM Delay */
164 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_cfg[0], 0x0);
165 
166 	/* DLN0_CFG1 */
167 	reg_val = (strength_override << 0x5) & 0x20;
168 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_cfg[1], reg_val);
169 
170 	/* DLN0_CFG2 */
171 	reg_val = ((pemph_bottom << 0x04) & 0xf0) |
172 		   (pemph_top & 0x0f);
173 
174 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_cfg[2], reg_val);
175 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_offset_top_ctrl, 0x0);
176 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_offset_bot_ctrl, 0x0);
177 
178 	/*
179 	 * DSIPHY_LPRX_DLY
180 	 * IS_CKLANE
181 	 */
182 	reg_val = (clk_lane << 0x07) & 0x80;
183 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_cfg[3], reg_val);
184 
185 	reg_val = 0;
186 	if (lane == DSI_LANEID_CLK)
187 		reg_val = 1;
188 
189 	write32(&dsi0_phy->phy_ln_regs[lane].dln0_tx_dctrl, reg_val);
190 }
191 
mdss_dsi_calculate_phy_timings(struct msm_dsi_phy_ctrl * timing,struct dsi_phy_configtype * phy_cfg)192 static void mdss_dsi_calculate_phy_timings(struct msm_dsi_phy_ctrl *timing,
193 					   struct dsi_phy_configtype *phy_cfg)
194 {
195 	const unsigned long bit_rate = phy_cfg->desired_bitclk_freq;
196 	s32 ui, ui_x8;
197 	s32 tmax, tmin;
198 	s32 pcnt0 = 50;
199 	s32 pcnt1 = 50;
200 	s32 pcnt2 = 10;
201 	s32 pcnt3 = 30;
202 	s32 pcnt4 = 10;
203 	s32 pcnt5 = 2;
204 	s32 coeff = 1000; /* Precision, should avoid overflow */
205 	s32 hb_en, hb_en_ckln;
206 	s32 temp;
207 
208 	if (!bit_rate)
209 		return;
210 
211 	hb_en = 0;
212 	timing->half_byte_clk_en = 0;
213 	hb_en_ckln = 0;
214 
215 	ui = mult_frac(1000000, coeff, bit_rate / 1000);
216 	ui_x8 = ui << 3;
217 
218 	temp = S_DIV_ROUND_UP(38 * coeff, ui_x8);
219 	tmin = MAX(temp, 0);
220 	temp = (95 * coeff) / ui_x8;
221 	tmax = MAX(temp, 0);
222 	timing->clk_prepare = linear_inter(tmax, tmin, pcnt0, 0, false);
223 
224 	temp = 300 * coeff - (timing->clk_prepare << 3) * ui;
225 	tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
226 	tmax = (tmin > 255) ? 511 : 255;
227 	timing->clk_zero = linear_inter(tmax, tmin, pcnt5, 0, false);
228 
229 	tmin = DIV_ROUND_UP(60 * coeff + 3 * ui, ui_x8);
230 	temp = 105 * coeff + 12 * ui - 20 * coeff;
231 	tmax = (temp + 3 * ui) / ui_x8;
232 	timing->clk_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
233 
234 	temp = S_DIV_ROUND_UP(40 * coeff + 4 * ui, ui_x8);
235 	tmin = MAX(temp, 0);
236 	temp = (85 * coeff + 6 * ui) / ui_x8;
237 	tmax = MAX(temp, 0);
238 	timing->hs_prepare = linear_inter(tmax, tmin, pcnt1, 0, false);
239 
240 	temp = 145 * coeff + 10 * ui - (timing->hs_prepare << 3) * ui;
241 	tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
242 	tmax = 255;
243 	timing->hs_zero = linear_inter(tmax, tmin, pcnt4, 0, false);
244 
245 	tmin = DIV_ROUND_UP(60 * coeff + 4 * ui, ui_x8) - 1;
246 	temp = 105 * coeff + 12 * ui - 20 * coeff;
247 	tmax = (temp / ui_x8) - 1;
248 	timing->hs_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
249 
250 	temp = 50 * coeff + ((hb_en << 2) - 8) * ui;
251 	timing->hs_rqst = S_DIV_ROUND_UP(temp, ui_x8);
252 
253 	tmin = DIV_ROUND_UP(100 * coeff, ui_x8) - 1;
254 	tmax = 255;
255 	timing->hs_exit = linear_inter(tmax, tmin, pcnt2, 0, false);
256 
257 	temp = 50 * coeff + ((hb_en_ckln << 2) - 8) * ui;
258 	timing->hs_rqst = S_DIV_ROUND_UP(temp, ui_x8);
259 
260 	temp = 60 * coeff + 52 * ui - 43 * ui;
261 	tmin = DIV_ROUND_UP(temp, ui_x8) - 1;
262 	tmax = 63;
263 	timing->clk_post = linear_inter(tmax, tmin, pcnt2, 0, false);
264 
265 	temp = 8 * ui + (timing->clk_prepare << 3) * ui;
266 	temp += (((timing->clk_zero + 3) << 3) + 11) * ui;
267 	temp += hb_en_ckln ? (((timing->hs_rqst << 3) + 4) * ui) :
268 			(((timing->hs_rqst << 3) + 8) * ui);
269 	tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
270 	tmax = 63;
271 	if (tmin > tmax) {
272 		temp = linear_inter(tmax << 1, tmin, pcnt2, 0, false);
273 		timing->clk_pre = temp >> 1;
274 		timing->clk_pre_inc_by_2 = 1;
275 	} else {
276 		timing->clk_pre = linear_inter(tmax, tmin, pcnt2, 0, false);
277 		timing->clk_pre_inc_by_2 = 0;
278 	}
279 
280 	timing->ta_go = 3;
281 	timing->ta_sure = 0;
282 	timing->ta_get = 4;
283 
284 	printk(BIOS_INFO, "PHY timings: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
285 		timing->clk_pre, timing->clk_post,
286 		timing->clk_pre_inc_by_2, timing->clk_zero,
287 		timing->clk_trail, timing->clk_prepare, timing->hs_exit,
288 		timing->hs_zero, timing->hs_prepare, timing->hs_trail,
289 		timing->hs_rqst);
290 }
291 
mdss_dsi_phy_timings(struct msm_dsi_phy_ctrl * phy_timings)292 static enum cb_err mdss_dsi_phy_timings(struct msm_dsi_phy_ctrl *phy_timings)
293 {
294 	uint32_t reg_val = 0;
295 
296 	/*
297 	 * Step 4 Common block including GlobalTiming Parameters
298 	 * BYTECLK_SEL
299 	 */
300 	reg_val = (0x02 << 3) & 0x18;
301 	write32(&dsi0_phy->phy_cmn_glbl_ctrl, reg_val);
302 
303 	/* VREG_CTRL */
304 	write32(&dsi0_phy->phy_cmn_vreg_ctrl, 0x59);
305 
306 	/*HALFBYTECLK_EN*/
307 	write32(&dsi0_phy->phy_cmn_timing_ctrl[0], phy_timings->half_byte_clk_en);
308 
309 	/* T_CLK_ZERO */
310 	write32(&dsi0_phy->phy_cmn_timing_ctrl[1], phy_timings->clk_zero);
311 
312 	/* T_CLK_PREPARE */
313 	write32(&dsi0_phy->phy_cmn_timing_ctrl[2], phy_timings->clk_prepare);
314 
315 	/* T_CLK_TRAIL */
316 	write32(&dsi0_phy->phy_cmn_timing_ctrl[3], phy_timings->clk_trail);
317 
318 	/* T_HS_EXIT */
319 	write32(&dsi0_phy->phy_cmn_timing_ctrl[4], phy_timings->hs_exit);
320 
321 	/* T_HS_ZERO */
322 	write32(&dsi0_phy->phy_cmn_timing_ctrl[5], phy_timings->hs_zero);
323 
324 	/* T_HS_PREPARE */
325 	write32(&dsi0_phy->phy_cmn_timing_ctrl[6], phy_timings->hs_prepare);
326 
327 	/* T_HS_TRAIL */
328 	write32(&dsi0_phy->phy_cmn_timing_ctrl[7], phy_timings->hs_trail);
329 
330 	/* T_HS_RQST */
331 	write32(&dsi0_phy->phy_cmn_timing_ctrl[8], phy_timings->hs_rqst);
332 
333 	/* T_TA_GO & T_TA_SURE */
334 	write32(&dsi0_phy->phy_cmn_timing_ctrl[9],
335 			phy_timings->ta_sure << 3 | phy_timings->ta_go);
336 
337 	/* T_TA_GET */
338 	write32(&dsi0_phy->phy_cmn_timing_ctrl[10], phy_timings->ta_get);
339 
340 	/*DSIPHY_TRIG3_CMD*/
341 	write32(&dsi0_phy->phy_cmn_timing_ctrl[11], 0x0);
342 
343 	/* DSI clock out timing ctrl T_CLK_PRE & T_CLK_POST*/
344 	reg_val = ((phy_timings->clk_post << 8) | phy_timings->clk_pre);
345 	write32(&dsi0->clkout_timing_ctrl, reg_val);
346 
347 	/* DCTRL */
348 	write32(&dsi0_phy->phy_cmn_ctrl2, 0x40);
349 
350 	return CB_SUCCESS;
351 }
352 
dsi_phy_waitforrefgen(void)353 static enum cb_err dsi_phy_waitforrefgen(void)
354 {
355 	uint32_t timeout = HAL_DSI_PHY_REFGEN_TIMEOUT_MS;
356 	uint32_t refgen  = 0;
357 	enum cb_err ret = CB_SUCCESS;
358 
359 	while (!refgen) {
360 		refgen = (read32(&dsi0_phy->phy_cmn_phy_status) & 0x1);
361 		if (!refgen) {
362 			udelay(100);
363 			timeout--;
364 			if (!timeout) {
365 				/* timeout while polling the lock status */
366 				ret = CB_ERR;
367 				break;
368 			}
369 		}
370 	}
371 
372 	return ret;
373 }
374 
mdss_dsi_phy_commit(void)375 static enum cb_err mdss_dsi_phy_commit(void)
376 {
377 	enum cb_err ret = CB_SUCCESS;
378 
379 	ret = dsi_phy_waitforrefgen();
380 	if (ret) {
381 		printk(BIOS_ERR, "%s: waitforrefgen error\n", __func__);
382 		return ret;
383 	}
384 
385 	mdss_dsi_power_down();
386 
387 	/* Remove PLL, DIG and all lanes from pwrdn */
388 	write32(&dsi0_phy->phy_cmn_ctrl0, 0x7F);
389 
390 	/* Lane enable */
391 	write32(&dsi0_phy->phy_cmn_dsi_lane_ctrl0, 0x1F);
392 
393 	mdss_dsi_phy_setup_lanephy(DSI_LANEID_0);
394 	mdss_dsi_phy_setup_lanephy(DSI_LANEID_1);
395 	mdss_dsi_phy_setup_lanephy(DSI_LANEID_2);
396 	mdss_dsi_phy_setup_lanephy(DSI_LANEID_3);
397 	mdss_dsi_phy_setup_lanephy(DSI_LANEID_CLK);
398 
399 	return ret;
400 }
401 
mdss_dsi_phy_setup(void)402 static void mdss_dsi_phy_setup(void)
403 {
404 	/* First reset phy */
405 	mdss_dsi_phy_reset();
406 
407 	/* commit phy settings */
408 	mdss_dsi_phy_commit();
409 }
410 
dsi_phy_resync_fifo(void)411 static void dsi_phy_resync_fifo(void)
412 {
413 	/* Resync FIFO*/
414 	write32(&dsi0_phy->phy_cmn_rbuf_ctrl, 0x1);
415 }
416 
dsi_phy_pll_global_clk_enable(bool enable)417 static void dsi_phy_pll_global_clk_enable(bool enable)
418 {
419 	uint32_t clk_cfg = read32(&dsi0_phy->phy_cmn_clk_cfg1);
420 	uint32_t clk_enable = 0;
421 
422 	/* Set CLK_EN */
423 	if (enable)
424 		clk_enable = 1;
425 
426 	clk_cfg &= ~0x20;
427 	clk_cfg |= ((clk_enable << 0x5) & 0x20);
428 
429 	/* clk cfg1 */
430 	write32(&dsi0_phy->phy_cmn_clk_cfg1, clk_cfg);
431 }
432 
dsi_phy_pll_lock_detect(void)433 static enum cb_err dsi_phy_pll_lock_detect(void)
434 {
435 	enum cb_err ret = CB_SUCCESS;
436 
437 	/* Enable PLL */
438 	write32(&dsi0_phy->phy_cmn_pll_ctrl, 0x1);
439 
440 	/* Wait for Lock */
441 	if (!wait_us(15000, read32(&phy_pll_qlink->pll_common_status_one) & 0x1)) {
442 		/* timeout while polling the lock status */
443 		ret = CB_ERR;
444 		printk(BIOS_ERR, "dsi pll lock detect timedout, error.\n");
445 	}
446 
447 	return ret;
448 }
449 
dsi_phy_toggle_dln3_tx_dctrl(void)450 static void dsi_phy_toggle_dln3_tx_dctrl(void)
451 {
452 	uint32_t reg_val = 0;
453 
454 	reg_val = read32(&dsi0_phy->phy_ln_regs[DSI_LANEID_3].dln0_tx_dctrl);
455 
456 	/* clear bit 0 and keep all other bits including bit 2 */
457 	reg_val &= ~0x01;
458 
459 	/* toggle bit 0 */
460 	write32(&dsi0_phy->phy_ln_regs[DSI_LANEID_3].dln0_tx_dctrl, (0x01 | reg_val));
461 	write32(&dsi0_phy->phy_ln_regs[DSI_LANEID_3].dln0_tx_dctrl, 0x4);
462 }
463 
dsi_phy_pll_set_source(void)464 static void dsi_phy_pll_set_source(void)
465 {
466 	uint32_t clk_cfg = read32(&dsi0_phy->phy_cmn_clk_cfg1);
467 	uint32_t dsi_clksel = 1;
468 
469 	clk_cfg &= ~0x03;
470 	clk_cfg |= ((dsi_clksel) & 0x3);
471 
472 	/* clk cfg1 */
473 	write32(&dsi0_phy->phy_cmn_clk_cfg1, clk_cfg);
474 }
475 
dsi_phy_pll_bias_enable(bool enable)476 static void dsi_phy_pll_bias_enable(bool enable)
477 {
478 	uint32_t reg_val = 0;
479 
480 	/* Set BIAS_EN_MUX, BIAS_EN */
481 	if (enable)
482 		reg_val = (0x01 << 6) | (0x01 << 7);
483 
484 	/* pll system muxes */
485 	write32(&phy_pll_qlink->pll_system_muxes, reg_val);
486 }
487 
dsi_phy_mnd_divider(struct dsi_phy_configtype * phy_cfg)488 static void dsi_phy_mnd_divider(struct dsi_phy_configtype *phy_cfg)
489 {
490 	uint32_t m_val = 1;
491 	uint32_t n_val = 1;
492 
493 	if (phy_cfg->bits_per_pixel == 18) {
494 		switch (phy_cfg->num_data_lanes) {
495 		case 1:
496 		case 2:
497 			m_val = 2;
498 			n_val = 3;
499 			break;
500 		case 4:
501 			m_val = 4;
502 			n_val = 9;
503 			break;
504 		default:
505 			break;
506 		}
507 	} else if ((phy_cfg->bits_per_pixel == 16) &&
508 			(phy_cfg->num_data_lanes == 3)) {
509 		m_val = 3;
510 		n_val = 8;
511 	} else if ((phy_cfg->bits_per_pixel == 30) &&
512 			(phy_cfg->num_data_lanes == 4)) {
513 		m_val = 2;
514 		n_val = 3;
515 	}
516 
517 	/*Save M/N info */
518 	phy_cfg->pclk_divnumerator = m_val;
519 	phy_cfg->pclk_divdenominator = n_val;
520 }
521 
dsi_phy_dsiclk_divider(struct dsi_phy_configtype * phy_cfg)522 static uint32_t dsi_phy_dsiclk_divider(struct dsi_phy_configtype *phy_cfg)
523 {
524 	uint32_t m_val = phy_cfg->pclk_divnumerator;
525 	uint32_t n_val = phy_cfg->pclk_divdenominator;
526 	uint32_t div_ctrl = 0;
527 
528 	div_ctrl = (m_val * phy_cfg->bits_per_pixel) /
529 	       (n_val * phy_cfg->num_data_lanes * 2);
530 
531 	return div_ctrl;
532 }
533 
534 
dsi_phy_calc_clk_divider(struct dsi_phy_configtype * phy_cfg)535 static unsigned long dsi_phy_calc_clk_divider(struct dsi_phy_configtype *phy_cfg)
536 {
537 	bool div_found = false;
538 	uint32_t div_ctrl = 0;
539 	uint32_t reg_val = 0;
540 	uint32_t pll_post_div = 0;
541 	uint32_t phy_post_div = 0;
542 	uint64_t vco_freq_hz = 0;
543 	uint64_t fval = 0;
544 	uint64_t pll_output_freq_hz;
545 	uint64_t desired_bitclk_hz;
546 	uint64_t min_vco_freq_hz = 0;
547 	uint32_t lut_max;
548 	int i;
549 	struct dsi_phy_divider_lut_entry_type *lut;
550 
551 	/* use 1000Mhz */
552 	min_vco_freq_hz = (HAL_DSI_PLL_VCO_MIN_MHZ_2_2_0 * 1000000);
553 
554 	dsi_phy_mnd_divider(phy_cfg);
555 
556 	/* Desired clock in MHz */
557 	desired_bitclk_hz = (uint64_t)phy_cfg->desired_bitclk_freq;
558 
559 	/* D Phy */
560 	lut = pll_dividerlut_dphy;
561 	lut_max = ARRAY_SIZE(pll_dividerlut_dphy);
562 	lut += (lut_max - 1);
563 
564 	/* PLL Post Div - from LUT
565 	 * Check the LUT in reverse order
566 	 */
567 	for (i = lut_max - 1; i >= 0; i--, lut--) {
568 		fval = (uint64_t)lut->phy_post_div *
569 				(uint64_t)lut->pll_post_div;
570 		if (fval) {
571 			if ((desired_bitclk_hz * fval) > min_vco_freq_hz) {
572 				/* Range found */
573 				pll_post_div = lut->pll_post_div;
574 				phy_post_div = lut->phy_post_div;
575 				div_found = true;
576 				break;
577 			}
578 		}
579 	}
580 
581 	if (div_found) {
582 		phy_cfg->pll_post_div = pll_post_div;
583 		phy_cfg->phy_post_div = phy_post_div;
584 
585 		/*div_ctrl_7_4 */
586 		div_ctrl = dsi_phy_dsiclk_divider(phy_cfg);
587 
588 		/* DIV_CTRL_7_4 DIV_CTRL_3_0
589 		 * (DIV_CTRL_3_0 = PHY post divider ratio)
590 		 */
591 		reg_val = (div_ctrl << 0x04) & 0xf0;
592 		reg_val |= (phy_post_div & 0x0f);
593 		write32(&dsi0_phy->phy_cmn_clk_cfg0, reg_val);
594 
595 		/* PLL output frequency = desired_bitclk_hz * phy_post_div */
596 		pll_output_freq_hz = desired_bitclk_hz * phy_post_div;
597 
598 		/* VCO output freq*/
599 		vco_freq_hz = pll_output_freq_hz * pll_post_div;
600 	}
601 
602 	return (unsigned long)vco_freq_hz;
603 }
604 
dsi_phy_pll_outputdiv_rate(struct dsi_phy_configtype * pll_cfg)605 static void dsi_phy_pll_outputdiv_rate(struct dsi_phy_configtype *pll_cfg)
606 {
607 	/* Output divider */
608 	uint32_t pll_post_div = 0;
609 	uint32_t reg_val = 0;
610 
611 	pll_post_div = log2(pll_cfg->pll_post_div);
612 	reg_val = pll_post_div & 0x3;
613 	write32(&phy_pll_qlink->pll_outdiv_rate, reg_val);
614 }
615 
dsi_phy_pll_calcandcommit(struct dsi_phy_configtype * phy_cfg)616 static enum cb_err dsi_phy_pll_calcandcommit(struct dsi_phy_configtype *phy_cfg)
617 {
618 	unsigned long vco_freq_hz;
619 	enum cb_err ret = CB_SUCCESS;
620 
621 	/* validate input parameters */
622 	if (!phy_cfg) {
623 		return CB_ERR;
624 	} else if ((phy_cfg->bits_per_pixel != 16) &&
625 		   (phy_cfg->bits_per_pixel != 18) &&
626 		   (phy_cfg->bits_per_pixel != 24)) {
627 		/* Unsupported pixel bit depth */
628 		return CB_ERR;
629 	} else if ((phy_cfg->num_data_lanes == 0) ||
630 		   (phy_cfg->num_data_lanes > 4)) {
631 		/* Illegal number of DSI data lanes */
632 		return CB_ERR;
633 	}
634 
635 	vco_freq_hz = dsi_phy_calc_clk_divider(phy_cfg);
636 	if (!vco_freq_hz) {
637 		/* bitclock too low  - unsupported */
638 		printk(BIOS_ERR, "vco_freq_hz is 0, unsupported\n");
639 		return CB_ERR;
640 	}
641 
642 	/* Enable PLL bias */
643 	dsi_phy_pll_bias_enable(true);
644 
645 	/* Set byte clk source */
646 	dsi_phy_pll_set_source();
647 
648 	dsi_phy_pll_outputdiv_rate(phy_cfg);
649 	dsi_phy_pll_vco_10nm_set_rate(vco_freq_hz);
650 	dsi_phy_toggle_dln3_tx_dctrl();
651 
652 	/* Steps 6,7 Start PLL & Lock */
653 	if (ret == CB_SUCCESS)
654 		ret = dsi_phy_pll_lock_detect();
655 
656 	/* Step 8 - Resync Data Paths */
657 	if (ret == CB_SUCCESS) {
658 		/* Global clock enable */
659 		dsi_phy_pll_global_clk_enable(true);
660 
661 		/* Resync FIFOs */
662 		dsi_phy_resync_fifo();
663 	}
664 
665 	return ret;
666 }
667 
dsi_calc_desired_bitclk(struct edid * edid,uint32_t num_lines,uint32_t bpp)668 static uint32_t dsi_calc_desired_bitclk(struct edid *edid, uint32_t num_lines, uint32_t bpp)
669 {
670 	uint64_t desired_bclk = 0;
671 	uint32_t pixel_clock_in_hz;
672 
673 	pixel_clock_in_hz = edid->mode.pixel_clock * KHz;
674 	if (num_lines) {
675 		desired_bclk = pixel_clock_in_hz * (uint64_t)bpp;
676 		desired_bclk = desired_bclk/(uint64_t)(num_lines);
677 	}
678 
679 	printk(BIOS_INFO, "Desired bitclock: %uHz\n", (uint32_t)desired_bclk);
680 	return (uint32_t)desired_bclk;
681 }
682 
mdss_dsi_phy_pll_setup(struct edid * edid,uint32_t num_of_lanes,uint32_t bpp)683 static enum cb_err mdss_dsi_phy_pll_setup(struct edid *edid,
684 					  uint32_t num_of_lanes, uint32_t bpp)
685 {
686 	struct dsi_phy_configtype phy_cfg;
687 	struct msm_dsi_phy_ctrl phy_timings;
688 	enum cb_err ret;
689 
690 	/* Setup the PhyStructure */
691 	memset(&phy_cfg, 0, sizeof(struct dsi_phy_configtype));
692 	memset(&phy_timings, 0, sizeof(struct msm_dsi_phy_ctrl));
693 
694 	phy_cfg.bits_per_pixel = bpp;
695 	phy_cfg.num_data_lanes = num_of_lanes;
696 
697 	/* desired DSI PLL bit clk freq in Hz */
698 	phy_cfg.desired_bitclk_freq = dsi_calc_desired_bitclk(edid, num_of_lanes, bpp);
699 
700 	ret = dsi_phy_pll_calcandcommit(&phy_cfg);
701 	if (ret)
702 		return ret;
703 	mdss_dsi_calculate_phy_timings(&phy_timings, &phy_cfg);
704 	ret = mdss_dsi_phy_timings(&phy_timings);
705 
706 	return ret;
707 }
708 
enable_dsi_clk(void)709 static enum cb_err enable_dsi_clk(void)
710 {
711 	enum cb_err ret;
712 	uint32_t i = 0;
713 	struct mdp_external_clock_entry clks[] = {
714 		{.clk_type = MDSS_CLK_ESC0, .clk_secondary_source = 1},
715 		{.clk_type = MDSS_CLK_PCLK0, .clk_source = 1},
716 		{.clk_type = MDSS_CLK_BYTE0, .clk_source = 1},
717 		{.clk_type = MDSS_CLK_BYTE0_INTF, .clk_source = 1,
718 				.clk_div = 1, .source_div = 2},
719 	};
720 
721 	for (i = 0; i < ARRAY_SIZE(clks); i++) {
722 		/* Set Ext Source */
723 		ret = mdss_clock_configure(clks[i].clk_type,
724 				   clks[i].clk_source,
725 				   clks[i].clk_div,
726 				   clks[i].clk_pll_m,
727 				   clks[i].clk_pll_n,
728 				   clks[i].clk_pll_2d);
729 		if (ret) {
730 			printk(BIOS_ERR,
731 			       "mdss_clock_configure failed for %u\n",
732 			       clks[i].clk_type);
733 			return CB_ERR;
734 		}
735 
736 		ret = mdss_clock_enable(clks[i].clk_type);
737 		if (ret) {
738 			printk(BIOS_ERR,
739 			       "mdss_clock_enable failed for %u\n",
740 			       clks[i].clk_type);
741 			return CB_ERR;
742 		}
743 	}
744 
745 	return ret;
746 }
747 
mdss_dsi_phy_10nm_init(struct edid * edid,uint32_t num_of_lanes,uint32_t bpp)748 enum cb_err mdss_dsi_phy_10nm_init(struct edid *edid, uint32_t num_of_lanes, uint32_t bpp)
749 {
750 	enum cb_err ret;
751 
752 	/* Phy set up */
753 	mdss_dsi_phy_setup();
754 	ret = mdss_dsi_phy_pll_setup(edid, num_of_lanes, bpp);
755 	enable_dsi_clk();
756 
757 	return ret;
758 }
759