drivers/wifi: Remove unnecessary data structure copy
[coreboot2.git] / src / soc / samsung / exynos5250 / fb.c
blobab097e294eb91e80f5f83e4d3cfb455cf6437903
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 /* LCD driver for Exynos */
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>
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.
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 */
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 */
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 */
57 ERR_NO_FDT_NODE,
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.
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,
76 int lcd_line_length;
77 int lcd_color_fg;
78 int lcd_color_bg;
80 void *lcd_console_address; /* Start of console buffer */
82 short console_col;
83 short console_row;
85 /* Bypass FIMD of DISP1_BLK */
86 static void fimd_bypass(void)
88 setbits32(&exynos_sysreg->disp1blk_cfg, FIMDBYPASS_DISP1);
89 exynos_sysreg->disp1blk_cfg &= ~FIMDBYPASS_DISP1;
93 * Initialize display controller.
95 * @param lcdbase pointer to the base address of framebuffer.
96 * @param pd pointer to the main panel_data structure
98 void fb_init(unsigned long int fb_size, void *lcdbase,
99 struct exynos5_fimd_panel *pd)
101 unsigned int val;
103 fb_size = ALIGN_UP(fb_size, 4096);
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);
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);
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);
119 val = ((pd->xres - 1) << HOZVAL_OFFSET) |
120 ((pd->yres - 1) << LINEVAL_OFFSET);
121 write32(&exynos_disp_ctrl->vidtcon2, val);
123 write32(&exynos_fimd->vidw00add0b0, (unsigned int)lcdbase);
124 write32(&exynos_fimd->vidw00add1b0, (unsigned int)lcdbase + fb_size);
126 write32(&exynos_fimd->vidw00add2, pd->xres * 2);
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);
133 setbits32(&exynos_fimd->shadowcon, CHANNEL0_EN);
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);
139 /* DPCLKCON_ENABLE */
140 write32(&exynos_fimd->dpclkcon, 1 << 1);
144 * Configure DP in slave mode and wait for video stream.
146 * param dp pointer to main s5p-dp structure
147 * param video_info pointer to main video_info structure.
148 * return status
150 static int s5p_dp_config_video(struct s5p_dp_device *dp,
151 struct video_info *video_info)
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);
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);
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;
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;
174 } while (!stopwatch_expired(&sw));
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;
182 /* Set to use the register calculated M/N video */
183 s5p_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
185 clrbits32(&base->video_ctl_10, FORMAT_SEL);
187 /* Disable video mute */
188 clrbits32(&base->video_ctl_1, HDCP_VIDEO_MUTE);
190 /* Configure video slave mode */
191 s5p_dp_enable_video_master(dp);
193 /* Enable video */
194 setbits32(&base->video_ctl_1, VIDEO_EN);
195 timeout = s5p_dp_is_video_stream_on(dp);
197 if (timeout) {
198 printk(BIOS_DEBUG, "Video Stream Not on\n");
199 return -ERR_VIDEO_STREAM_BAD;
202 return 0;
206 * Set DP to enhanced mode. We use this for EVT1
207 * param dp pointer to main s5p-dp structure
208 * return status
210 static int s5p_dp_enable_rx_to_enhanced_mode(struct s5p_dp_device *dp)
212 u8 data;
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;
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;
225 return 0;
229 * Enable scrambles mode. We use this for EVT1
230 * param dp pointer to main s5p-dp structure
231 * return status
233 static int s5p_dp_enable_scramble(struct s5p_dp_device *dp)
235 u8 data;
236 struct exynos5_dp *base = dp->base;
238 clrbits32(&base->dp_training_ptn_set, SCRAMBLING_DISABLE);
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;
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;
252 return 0;
256 * Reset DP and prepare DP for init training
257 * param dp pointer to main s5p-dp structure
259 static int s5p_dp_init_dp(struct s5p_dp_device *dp)
261 int ret, i;
262 struct exynos5_dp *base = dp->base;
264 for (i = 0; i < DP_INIT_TRIES; i++) {
265 s5p_dp_reset(dp);
267 /* SW defined function Normal operation */
268 clrbits32(&base->func_en_1, SW_FUNC_EN_N);
270 ret = s5p_dp_init_analog_func(dp);
271 if (!ret)
272 break;
274 udelay(5000);
275 printk(BIOS_DEBUG, "LCD retry init, attempt=%d ret=%d\n", i, ret);
277 if (i == DP_INIT_TRIES) {
278 printk(BIOS_DEBUG, "LCD initialization failed, ret=%d\n", ret);
279 return ret;
282 s5p_dp_init_aux(dp);
284 return ret;
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
294 static int s5p_dp_set_lane_lane_pre_emphasis(struct s5p_dp_device *dp,
295 int pre_emphasis, int lane)
297 u32 reg;
298 struct exynos5_dp *base = dp->base;
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;
309 case 2:
310 write32(&base->ln2_link_trn_ctl, reg);
311 break;
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;
320 return 0;
324 * Read supported bandwidth type
325 * param dp pointer to main s5p-dp structure
326 * param bandwidth pointer to variable holding bandwidth type
328 static void s5p_dp_get_max_rx_bandwidth(struct s5p_dp_device *dp,
329 u8 *bandwidth)
331 u8 data;
334 * For DP rev.1.1, Maximum link rate of Main Link lanes
335 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
337 s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
338 *bandwidth = data;
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
346 static void s5p_dp_get_max_rx_lane_count(struct s5p_dp_device *dp,
347 u8 *lane_count)
349 u8 data;
352 * For DP rev.1.1, Maximum number of Main Link lanes
353 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
355 s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
356 *lane_count = data & DPCD_MAX_LANE_COUNT_MASK;
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
366 static int s5p_dp_hw_link_training(struct s5p_dp_device *dp,
367 unsigned int max_lane,
368 unsigned int max_rate)
370 int pll_is_locked = 0;
371 u32 data;
372 int lane;
373 struct stopwatch sw;
374 struct exynos5_dp *base = dp->base;
376 /* Stop Video */
377 clrbits32(&base->video_ctl_1, VIDEO_EN);
379 stopwatch_init_msecs_expire(&sw, PLL_LOCK_TIMEOUT);
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;
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);
393 /* 10 us is the minimum reset time. */
394 udelay(10);
396 clrbits32(&base->dp_phy_test, MACRO_RST);
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;
406 /* All DP analog module power up */
407 write32(&base->dp_phy_pd, 0x00);
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);
413 printk(BIOS_SPEW, "%s: rate 0x%x, lane_count %d\n", __func__,
414 dp->link_train.link_rate, dp->link_train.lane_count);
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;
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;
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;
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);
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);
445 /* Start HW link training */
446 write32(&base->dp_hw_link_training, HW_TRAINING_EN);
448 /* Wait until HW link training done */
449 s5p_dp_wait_hw_link_training_done(dp);
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;
459 /* Get Link Bandwidth */
460 data = read32(&base->link_bw_set);
462 dp->link_train.link_rate = data;
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);
469 return 0;
473 * Initialize DP display
475 int dp_controller_init(struct s5p_dp_device *dp_device)
477 int ret;
478 struct s5p_dp_device *dp = dp_device;
479 struct exynos5_dp *base;
481 clock_init_dp_clock();
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;
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;
496 /* Minimum delay after H/w Link training */
497 udelay(1000);
499 ret = s5p_dp_enable_scramble(dp);
500 if (ret) {
501 printk(BIOS_ERR, "unable to set scramble mode\n");
502 return ret;
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;
511 base = dp->base;
512 /* Enable enhanced mode */
513 setbits32(&base->sys_ctl_4, ENHANCED);
515 write32(&base->lane_count_set, dp->link_train.lane_count);
516 write32(&base->link_bw_set, dp->link_train.link_rate);
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;
525 return 0;
529 * Init the LCD controller
531 * @param panel_data
532 * @param lcdbase Base address of LCD frame buffer
533 * @return 0 if ok, -ve error code on error
535 int lcd_ctrl_init(unsigned long int fb_size,
536 struct exynos5_fimd_panel *panel_data, void *lcdbase)
538 int ret = 0;
540 fimd_bypass();
541 fb_init(fb_size, lcdbase, panel_data);
542 return ret;