xref: /aosp_15_r20/external/coreboot/src/soc/samsung/exynos5250/fb.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /* LCD driver for Exynos */
4 
5 #include <device/mmio.h>
6 #include <console/console.h>
7 #include <delay.h>
8 #include <soc/dp.h>
9 #include <soc/dp-core.h>
10 #include <soc/fimd.h>
11 #include <soc/i2c.h>
12 #include <soc/power.h>
13 #include <soc/sysreg.h>
14 #include <timer.h>
15 
16 /*
17  * Here is the rough outline of how we bring up the display:
18  *  1. Upon power-on Sink generates a hot plug detection pulse thru HPD
19  *  2. Source determines video mode by reading DPCD receiver capability field
20  *     (DPCD 00000h to 0000Dh) including eDP CP capability register (DPCD
21  *     0000Dh).
22  *  3. Sink replies DPCD receiver capability field.
23  *  4. Source starts EDID read thru I2C-over-AUX.
24  *  5. Sink replies EDID thru I2C-over-AUX.
25  *  6. Source determines link configuration, such as MAX_LINK_RATE and
26  *     MAX_LANE_COUNT. Source also determines which type of eDP Authentication
27  *     method to use and writes DPCD link configuration field (DPCD 00100h to
28  *     0010Ah) including eDP configuration set (DPCD 0010Ah).
29  *  7. Source starts link training. Sink does clock recovery and equalization.
30  *  8. Source reads DPCD link status field (DPCD 00200h to 0020Bh).
31  *  9. Sink replies DPCD link status field. If main link is not stable, Source
32  *     repeats Step 7.
33  * 10. Source sends MSA (Main Stream Attribute) data. Sink extracts video
34  *     parameters and recovers stream clock.
35  * 11. Source sends video data.
36  */
37 
38 /* To help debug any init errors here, define a list of possible errors */
39 enum {
40 	ERR_PLL_NOT_UNLOCKED = 2,
41 	ERR_VIDEO_CLOCK_BAD,
42 	ERR_VIDEO_STREAM_BAD,
43 	ERR_DPCD_READ_ERROR1,		/* 5 */
44 
45 	ERR_DPCD_WRITE_ERROR1,
46 	ERR_DPCD_READ_ERROR2,
47 	ERR_DPCD_WRITE_ERROR2,
48 	ERR_INVALID_LANE,
49 	ERR_PLL_NOT_LOCKED,		/* 10 */
50 
51 	ERR_PRE_EMPHASIS_LEVELS,
52 	ERR_LINK_RATE_ABNORMAL,
53 	ERR_MAX_LANE_COUNT_ABNORMAL,
54 	ERR_LINK_TRAINING_FAILURE,
55 	ERR_MISSING_DP_BASE,		/* 15 */
56 
57 	ERR_NO_FDT_NODE,
58 };
59 /* ok, this is stupid, but we're going to leave the variables in here until we
60  * know it works. One cleanup task at a time.
61  */
62 enum stage_t {
63 	STAGE_START = 0,
64 	STAGE_LCD_VDD,
65 	STAGE_BRIDGE_SETUP,
66 	STAGE_BRIDGE_INIT,
67 	STAGE_BRIDGE_RESET,
68 	STAGE_HOTPLUG,
69 	STAGE_DP_CONTROLLER,
70 	STAGE_BACKLIGHT_VDD,
71 	STAGE_BACKLIGHT_PWM,
72 	STAGE_BACKLIGHT_EN,
73 	STAGE_DONE,
74 };
75 
76 int lcd_line_length;
77 int lcd_color_fg;
78 int lcd_color_bg;
79 
80 void *lcd_console_address;	/* Start of console buffer */
81 
82 short console_col;
83 short console_row;
84 
85 /* Bypass FIMD of DISP1_BLK */
fimd_bypass(void)86 static void fimd_bypass(void)
87 {
88 	setbits32(&exynos_sysreg->disp1blk_cfg, FIMDBYPASS_DISP1);
89 	exynos_sysreg->disp1blk_cfg &= ~FIMDBYPASS_DISP1;
90 }
91 
92 /*
93  * Initialize display controller.
94  *
95  * @param lcdbase	pointer to the base address of framebuffer.
96  * @param pd		pointer to the main panel_data structure
97  */
fb_init(unsigned long int fb_size,void * lcdbase,struct exynos5_fimd_panel * pd)98 void fb_init(unsigned long int fb_size, void *lcdbase,
99 	     struct exynos5_fimd_panel *pd)
100 {
101 	unsigned int val;
102 
103 	fb_size = ALIGN_UP(fb_size, 4096);
104 
105 	write32(&exynos_disp_ctrl->vidcon1, pd->ivclk | pd->fixvclk);
106 	val = ENVID_ON | ENVID_F_ON | (pd->clkval_f << CLKVAL_F_OFFSET);
107 	write32(&exynos_fimd->vidcon0, val);
108 
109 	val = (pd->vsync << VSYNC_PULSE_WIDTH_OFFSET) |
110 		(pd->lower_margin << V_FRONT_PORCH_OFFSET) |
111 		(pd->upper_margin << V_BACK_PORCH_OFFSET);
112 	write32(&exynos_disp_ctrl->vidtcon0, val);
113 
114 	val = (pd->hsync << HSYNC_PULSE_WIDTH_OFFSET) |
115 		(pd->right_margin << H_FRONT_PORCH_OFFSET) |
116 		(pd->left_margin << H_BACK_PORCH_OFFSET);
117 	write32(&exynos_disp_ctrl->vidtcon1, val);
118 
119 	val = ((pd->xres - 1) << HOZVAL_OFFSET) |
120 		((pd->yres - 1) << LINEVAL_OFFSET);
121 	write32(&exynos_disp_ctrl->vidtcon2, val);
122 
123 	write32(&exynos_fimd->vidw00add0b0, (unsigned int)lcdbase);
124 	write32(&exynos_fimd->vidw00add1b0, (unsigned int)lcdbase + fb_size);
125 
126 	write32(&exynos_fimd->vidw00add2, pd->xres * 2);
127 
128 	val = ((pd->xres - 1) << OSD_RIGHTBOTX_F_OFFSET);
129 	val |= ((pd->yres - 1) << OSD_RIGHTBOTY_F_OFFSET);
130 	write32(&exynos_fimd->vidosd0b, val);
131 	write32(&exynos_fimd->vidosd0c, pd->xres * pd->yres);
132 
133 	setbits32(&exynos_fimd->shadowcon, CHANNEL0_EN);
134 
135 	val = BPPMODE_F_RGB_16BIT_565 << BPPMODE_F_OFFSET;
136 	val |= ENWIN_F_ENABLE | HALF_WORD_SWAP_EN;
137 	write32(&exynos_fimd->wincon0, val);
138 
139 	/* DPCLKCON_ENABLE */
140 	write32(&exynos_fimd->dpclkcon, 1 << 1);
141 }
142 
143 /*
144  * Configure DP in slave mode and wait for video stream.
145  *
146  * param dp		pointer to main s5p-dp structure
147  * param video_info	pointer to main video_info structure.
148  * return		status
149  */
s5p_dp_config_video(struct s5p_dp_device * dp,struct video_info * video_info)150 static int s5p_dp_config_video(struct s5p_dp_device *dp,
151 			       struct video_info *video_info)
152 {
153 	int timeout = 0;
154 	struct exynos5_dp *base = dp->base;
155 	struct stopwatch sw;
156 	s5p_dp_config_video_slave_mode(dp, video_info);
157 
158 	s5p_dp_set_video_color_format(dp, video_info->color_depth,
159 				      video_info->color_space,
160 				      video_info->dynamic_range,
161 				      video_info->ycbcr_coeff);
162 
163 	if (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
164 		printk(BIOS_DEBUG, "PLL is not locked yet.\n");
165 		return -ERR_PLL_NOT_UNLOCKED;
166 	}
167 
168 	stopwatch_init_msecs_expire(&sw, STREAM_ON_TIMEOUT);
169 	do {
170 		if (s5p_dp_is_slave_video_stream_clock_on(dp) == 0) {
171 			timeout++;
172 			break;
173 		}
174 	} while (!stopwatch_expired(&sw));
175 
176 	if (!timeout) {
177 		printk(BIOS_ERR, "Video Clock Not ok after %lldus.\n",
178 				stopwatch_duration_usecs(&sw));
179 		return -ERR_VIDEO_CLOCK_BAD;
180 	}
181 
182 	/* Set to use the register calculated M/N video */
183 	s5p_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
184 
185 	clrbits32(&base->video_ctl_10, FORMAT_SEL);
186 
187 	/* Disable video mute */
188 	clrbits32(&base->video_ctl_1, HDCP_VIDEO_MUTE);
189 
190 	/* Configure video slave mode */
191 	s5p_dp_enable_video_master(dp);
192 
193 	/* Enable video */
194 	setbits32(&base->video_ctl_1, VIDEO_EN);
195 	timeout = s5p_dp_is_video_stream_on(dp);
196 
197 	if (timeout) {
198 		printk(BIOS_DEBUG, "Video Stream Not on\n");
199 		return -ERR_VIDEO_STREAM_BAD;
200 	}
201 
202 	return 0;
203 }
204 
205 /*
206  * Set DP to enhanced mode. We use this for EVT1
207  * param dp	pointer to main s5p-dp structure
208  * return	status
209  */
s5p_dp_enable_rx_to_enhanced_mode(struct s5p_dp_device * dp)210 static int s5p_dp_enable_rx_to_enhanced_mode(struct s5p_dp_device *dp)
211 {
212 	u8 data;
213 
214 	if (s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data)) {
215 		printk(BIOS_DEBUG, "DPCD read error\n");
216 		return -ERR_DPCD_READ_ERROR1;
217 	}
218 	if (s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
219 				      DPCD_ENHANCED_FRAME_EN |
220 				      (data & DPCD_LANE_COUNT_SET_MASK))) {
221 		printk(BIOS_DEBUG, "DPCD write error\n");
222 		return -ERR_DPCD_WRITE_ERROR1;
223 	}
224 
225 	return 0;
226 }
227 
228 /*
229  * Enable scrambles mode. We use this for EVT1
230  * param dp	pointer to main s5p-dp structure
231  * return	status
232  */
s5p_dp_enable_scramble(struct s5p_dp_device * dp)233 static int s5p_dp_enable_scramble(struct s5p_dp_device *dp)
234 {
235 	u8 data;
236 	struct exynos5_dp *base = dp->base;
237 
238 	clrbits32(&base->dp_training_ptn_set, SCRAMBLING_DISABLE);
239 
240 	if (s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET,
241 				       &data)) {
242 		printk(BIOS_DEBUG, "DPCD read error\n");
243 		return -ERR_DPCD_READ_ERROR2;
244 	}
245 
246 	if (s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET,
247 			      (u8)(data & ~DPCD_SCRAMBLING_DISABLED))) {
248 		printk(BIOS_DEBUG, "DPCD write error\n");
249 		return -ERR_DPCD_WRITE_ERROR2;
250 	}
251 
252 	return 0;
253 }
254 
255 /*
256  * Reset DP and prepare DP for init training
257  * param dp	pointer to main s5p-dp structure
258  */
s5p_dp_init_dp(struct s5p_dp_device * dp)259 static int s5p_dp_init_dp(struct s5p_dp_device *dp)
260 {
261 	int ret, i;
262 	struct exynos5_dp *base = dp->base;
263 
264 	for (i = 0; i < DP_INIT_TRIES; i++) {
265 		s5p_dp_reset(dp);
266 
267 		/* SW defined function Normal operation */
268 		clrbits32(&base->func_en_1, SW_FUNC_EN_N);
269 
270 		ret = s5p_dp_init_analog_func(dp);
271 		if (!ret)
272 			break;
273 
274 		udelay(5000);
275 		printk(BIOS_DEBUG, "LCD retry init, attempt=%d ret=%d\n", i, ret);
276 	}
277 	if (i == DP_INIT_TRIES) {
278 		printk(BIOS_DEBUG, "LCD initialization failed, ret=%d\n", ret);
279 		return ret;
280 	}
281 
282 	s5p_dp_init_aux(dp);
283 
284 	return ret;
285 }
286 
287 /*
288  * Set pre-emphasis level
289  * param dp		pointer to main s5p-dp structure
290  * param pre_emphasis	pre-emphasis level
291  * param lane		lane number(0 - 3)
292  * return		status
293  */
s5p_dp_set_lane_lane_pre_emphasis(struct s5p_dp_device * dp,int pre_emphasis,int lane)294 static int s5p_dp_set_lane_lane_pre_emphasis(struct s5p_dp_device *dp,
295 					     int pre_emphasis, int lane)
296 {
297 	u32 reg;
298 	struct exynos5_dp *base = dp->base;
299 
300 	reg = pre_emphasis << PRE_EMPHASIS_SET_SHIFT;
301 	switch (lane) {
302 	case 0:
303 		write32(&base->ln0_link_trn_ctl, reg);
304 		break;
305 	case 1:
306 		write32(&base->ln1_link_trn_ctl, reg);
307 		break;
308 
309 	case 2:
310 		write32(&base->ln2_link_trn_ctl, reg);
311 		break;
312 
313 	case 3:
314 		write32(&base->ln3_link_trn_ctl, reg);
315 		break;
316 	default:
317 		printk(BIOS_DEBUG, "%s: Invalid lane %d\n", __func__, lane);
318 		return -ERR_INVALID_LANE;
319 	}
320 	return 0;
321 }
322 
323 /*
324  * Read supported bandwidth type
325  * param dp		pointer to main s5p-dp structure
326  * param bandwidth	pointer to variable holding bandwidth type
327  */
s5p_dp_get_max_rx_bandwidth(struct s5p_dp_device * dp,u8 * bandwidth)328 static void s5p_dp_get_max_rx_bandwidth(struct s5p_dp_device *dp,
329 					u8 *bandwidth)
330 {
331 	u8 data;
332 
333 	/*
334 	 * For DP rev.1.1, Maximum link rate of Main Link lanes
335 	 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
336 	 */
337 	s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
338 	*bandwidth = data;
339 }
340 
341 /*
342  * Reset DP and prepare DP for init training
343  * param dp		pointer to main s5p-dp structure
344  * param lane_count	pointer to variable holding no of lanes
345  */
s5p_dp_get_max_rx_lane_count(struct s5p_dp_device * dp,u8 * lane_count)346 static void s5p_dp_get_max_rx_lane_count(struct s5p_dp_device *dp,
347 					 u8 *lane_count)
348 {
349 	u8 data;
350 
351 	/*
352 	 * For DP rev.1.1, Maximum number of Main Link lanes
353 	 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
354 	 */
355 	s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
356 	*lane_count = data & DPCD_MAX_LANE_COUNT_MASK;
357 }
358 
359 /*
360  * DP H/w Link Training. Set DPCD link rate and bandwidth.
361  * param dp		pointer to main s5p-dp structure
362  * param max_lane	No of lanes
363  * param max_rate	bandwidth
364  * return status
365  */
s5p_dp_hw_link_training(struct s5p_dp_device * dp,unsigned int max_lane,unsigned int max_rate)366 static int s5p_dp_hw_link_training(struct s5p_dp_device *dp,
367 				   unsigned int max_lane,
368 				   unsigned int max_rate)
369 {
370 	int pll_is_locked = 0;
371 	u32 data;
372 	int lane;
373 	struct stopwatch sw;
374 	struct exynos5_dp *base = dp->base;
375 
376 	/* Stop Video */
377 	clrbits32(&base->video_ctl_1, VIDEO_EN);
378 
379 	stopwatch_init_msecs_expire(&sw, PLL_LOCK_TIMEOUT);
380 
381 	while ((pll_is_locked = s5p_dp_get_pll_lock_status(dp)) == PLL_UNLOCKED) {
382 		if (stopwatch_expired(&sw)) {
383 			/* Ignore this error, and try to continue */
384 			printk(BIOS_ERR, "PLL is not locked yet.\n");
385 			break;
386 		}
387 	}
388 	printk(BIOS_SPEW, "PLL is %slocked\n",
389 			pll_is_locked == PLL_LOCKED ? "": "not ");
390 	/* Reset Macro */
391 	setbits32(&base->dp_phy_test, MACRO_RST);
392 
393 	/* 10 us is the minimum reset time. */
394 	udelay(10);
395 
396 	clrbits32(&base->dp_phy_test, MACRO_RST);
397 
398 	/* Set TX pre-emphasis to minimum */
399 	for (lane = 0; lane < max_lane; lane++)
400 		if (s5p_dp_set_lane_lane_pre_emphasis(dp,
401 					      PRE_EMPHASIS_LEVEL_0, lane)) {
402 			printk(BIOS_DEBUG, "Unable to set pre emphasis level\n");
403 			return -ERR_PRE_EMPHASIS_LEVELS;
404 		}
405 
406 	/* All DP analog module power up */
407 	write32(&base->dp_phy_pd, 0x00);
408 
409 	/* Initialize by reading RX's DPCD */
410 	s5p_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
411 	s5p_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
412 
413 	printk(BIOS_SPEW, "%s: rate 0x%x, lane_count %d\n", __func__,
414 		dp->link_train.link_rate, dp->link_train.lane_count);
415 
416 	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
417 	    (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
418 		printk(BIOS_DEBUG, "Rx Max Link Rate is abnormal :%x !\n",
419 		      dp->link_train.link_rate);
420 		/* Not Retrying */
421 		return -ERR_LINK_RATE_ABNORMAL;
422 	}
423 
424 	if (dp->link_train.lane_count == 0) {
425 		printk(BIOS_DEBUG, "Rx Max Lane count is abnormal :%x !\n",
426 		      dp->link_train.lane_count);
427 		/* Not retrying */
428 		return -ERR_MAX_LANE_COUNT_ABNORMAL;
429 	}
430 
431 	/* Setup TX lane count & rate */
432 	if (dp->link_train.lane_count > max_lane)
433 		dp->link_train.lane_count = max_lane;
434 	if (dp->link_train.link_rate > max_rate)
435 		dp->link_train.link_rate = max_rate;
436 
437 	/* Set link rate and count as you want to establish*/
438 	write32(&base->lane_count_set, dp->link_train.lane_count);
439 	write32(&base->link_bw_set, dp->link_train.link_rate);
440 
441 	/* Set sink to D0 (Sink Not Ready) mode. */
442 	s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
443 				  DPCD_SET_POWER_STATE_D0);
444 
445 	/* Start HW link training */
446 	write32(&base->dp_hw_link_training, HW_TRAINING_EN);
447 
448 	/* Wait until HW link training done */
449 	s5p_dp_wait_hw_link_training_done(dp);
450 
451 	/* Get hardware link training status */
452 	data = read32(&base->dp_hw_link_training);
453 	printk(BIOS_SPEW, "hardware link training status: 0x%08x\n", data);
454 	if (data != 0) {
455 		printk(BIOS_ERR, " H/W link training failure: 0x%x\n", data);
456 		return -ERR_LINK_TRAINING_FAILURE;
457 	}
458 
459 	/* Get Link Bandwidth */
460 	data = read32(&base->link_bw_set);
461 
462 	dp->link_train.link_rate = data;
463 
464 	data = read32(&base->lane_count_set);
465 	dp->link_train.lane_count = data;
466 	printk(BIOS_SPEW, "Done training: Link bandwidth: 0x%x, lane_count: %d\n",
467 		dp->link_train.link_rate, data);
468 
469 	return 0;
470 }
471 
472 /*
473  * Initialize DP display
474  */
dp_controller_init(struct s5p_dp_device * dp_device)475 int dp_controller_init(struct s5p_dp_device *dp_device)
476 {
477 	int ret;
478 	struct s5p_dp_device *dp = dp_device;
479 	struct exynos5_dp *base;
480 
481 	clock_init_dp_clock();
482 
483 	power_enable_dp_phy();
484 	ret = s5p_dp_init_dp(dp);
485 	if (ret) {
486 		printk(BIOS_ERR, "%s: Could not initialize dp\n", __func__);
487 		return ret;
488 	}
489 
490 	ret = s5p_dp_hw_link_training(dp, dp->video_info->lane_count,
491 				      dp->video_info->link_rate);
492 	if (ret) {
493 		printk(BIOS_ERR, "unable to do link train\n");
494 		return ret;
495 	}
496 	/* Minimum delay after H/w Link training */
497 	udelay(1000);
498 
499 	ret = s5p_dp_enable_scramble(dp);
500 	if (ret) {
501 		printk(BIOS_ERR, "unable to set scramble mode\n");
502 		return ret;
503 	}
504 
505 	ret = s5p_dp_enable_rx_to_enhanced_mode(dp);
506 	if (ret) {
507 		printk(BIOS_ERR, "unable to set enhanced mode\n");
508 		return ret;
509 	}
510 
511 	base = dp->base;
512 	/* Enable enhanced mode */
513 	setbits32(&base->sys_ctl_4, ENHANCED);
514 
515 	write32(&base->lane_count_set, dp->link_train.lane_count);
516 	write32(&base->link_bw_set, dp->link_train.link_rate);
517 
518 	s5p_dp_init_video(dp);
519 	ret = s5p_dp_config_video(dp, dp->video_info);
520 	if (ret) {
521 		printk(BIOS_ERR, "unable to config video\n");
522 		return ret;
523 	}
524 
525 	return 0;
526 }
527 
528 /**
529  * Init the LCD controller
530  *
531  * @param panel_data
532  * @param lcdbase	Base address of LCD frame buffer
533  * @return 0 if ok, -ve error code on error
534  */
lcd_ctrl_init(unsigned long int fb_size,struct exynos5_fimd_panel * panel_data,void * lcdbase)535 int lcd_ctrl_init(unsigned long int fb_size,
536 		  struct exynos5_fimd_panel *panel_data, void *lcdbase)
537 {
538 	int ret = 0;
539 
540 	fimd_bypass();
541 	fb_init(fb_size, lcdbase, panel_data);
542 	return ret;
543 }
544