blob: ab097e294eb91e80f5f83e4d3cfb455cf6437903 [file] [log] [blame]
Angel Pons1ddb8942020-04-04 18:51:26 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Ronald G. Minnich6bde1492013-03-01 10:18:14 -08002
Stefan Reinauer08dc3572013-05-14 16:57:50 -07003/* LCD driver for Exynos */
4
Kyösti Mälkki13f66502019-03-03 08:01:05 +02005#include <device/mmio.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -07006#include <console/console.h>
Julius Wernerfa938c72013-08-29 14:17:36 -07007#include <delay.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -07008#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>
David Hendricks0bb875b2013-05-02 14:23:51 -070014#include <timer.h>
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080015
Ronald G. Minnich2810afa2013-04-18 18:09:24 -070016/*
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
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080038/* To help debug any init errors here, define a list of possible errors */
39enum {
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};
Stefan Reinauerb98dec02013-05-14 13:32:33 -070059/* 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.
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080061 */
62enum 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
76int lcd_line_length;
77int lcd_color_fg;
78int lcd_color_bg;
79
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080080void *lcd_console_address; /* Start of console buffer */
81
82short console_col;
83short console_row;
84
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080085/* Bypass FIMD of DISP1_BLK */
86static void fimd_bypass(void)
87{
Julius Werner55009af2019-12-02 22:03:27 -080088 setbits32(&exynos_sysreg->disp1blk_cfg, FIMDBYPASS_DISP1);
Julius Wernerfa938c72013-08-29 14:17:36 -070089 exynos_sysreg->disp1blk_cfg &= ~FIMDBYPASS_DISP1;
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080090}
91
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080092/*
93 * Initialize display controller.
94 *
95 * @param lcdbase pointer to the base address of framebuffer.
Martin Roth5f066b22015-01-04 16:47:39 -070096 * @param pd pointer to the main panel_data structure
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080097 */
Gabe Black1e797bd2013-05-18 15:58:46 -070098void fb_init(unsigned long int fb_size, void *lcdbase,
99 struct exynos5_fimd_panel *pd)
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800100{
101 unsigned int val;
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800102
Elyes Haouasd6b6b222022-10-10 12:34:21 +0200103 fb_size = ALIGN_UP(fb_size, 4096);
Gabe Black1e797bd2013-05-18 15:58:46 -0700104
Julius Werner2f37bd62015-02-19 14:51:15 -0800105 write32(&exynos_disp_ctrl->vidcon1, pd->ivclk | pd->fixvclk);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800106 val = ENVID_ON | ENVID_F_ON | (pd->clkval_f << CLKVAL_F_OFFSET);
Julius Werner2f37bd62015-02-19 14:51:15 -0800107 write32(&exynos_fimd->vidcon0, val);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800108
109 val = (pd->vsync << VSYNC_PULSE_WIDTH_OFFSET) |
110 (pd->lower_margin << V_FRONT_PORCH_OFFSET) |
111 (pd->upper_margin << V_BACK_PORCH_OFFSET);
Julius Werner2f37bd62015-02-19 14:51:15 -0800112 write32(&exynos_disp_ctrl->vidtcon0, val);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800113
114 val = (pd->hsync << HSYNC_PULSE_WIDTH_OFFSET) |
115 (pd->right_margin << H_FRONT_PORCH_OFFSET) |
116 (pd->left_margin << H_BACK_PORCH_OFFSET);
Julius Werner2f37bd62015-02-19 14:51:15 -0800117 write32(&exynos_disp_ctrl->vidtcon1, val);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800118
119 val = ((pd->xres - 1) << HOZVAL_OFFSET) |
120 ((pd->yres - 1) << LINEVAL_OFFSET);
Julius Werner2f37bd62015-02-19 14:51:15 -0800121 write32(&exynos_disp_ctrl->vidtcon2, val);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800122
Julius Werner2f37bd62015-02-19 14:51:15 -0800123 write32(&exynos_fimd->vidw00add0b0, (unsigned int)lcdbase);
124 write32(&exynos_fimd->vidw00add1b0, (unsigned int)lcdbase + fb_size);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800125
Julius Werner2f37bd62015-02-19 14:51:15 -0800126 write32(&exynos_fimd->vidw00add2, pd->xres * 2);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800127
128 val = ((pd->xres - 1) << OSD_RIGHTBOTX_F_OFFSET);
129 val |= ((pd->yres - 1) << OSD_RIGHTBOTY_F_OFFSET);
Julius Werner2f37bd62015-02-19 14:51:15 -0800130 write32(&exynos_fimd->vidosd0b, val);
131 write32(&exynos_fimd->vidosd0c, pd->xres * pd->yres);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800132
Julius Werner55009af2019-12-02 22:03:27 -0800133 setbits32(&exynos_fimd->shadowcon, CHANNEL0_EN);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800134
135 val = BPPMODE_F_RGB_16BIT_565 << BPPMODE_F_OFFSET;
136 val |= ENWIN_F_ENABLE | HALF_WORD_SWAP_EN;
Julius Werner2f37bd62015-02-19 14:51:15 -0800137 write32(&exynos_fimd->wincon0, val);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800138
139 /* DPCLKCON_ENABLE */
Julius Werner2f37bd62015-02-19 14:51:15 -0800140 write32(&exynos_fimd->dpclkcon, 1 << 1);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800141}
142
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800143/*
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 */
150static int s5p_dp_config_video(struct s5p_dp_device *dp,
151 struct video_info *video_info)
152{
153 int timeout = 0;
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800154 struct exynos5_dp *base = dp->base;
Aaron Durbin43933462014-09-24 10:27:29 -0500155 struct stopwatch sw;
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800156 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) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700164 printk(BIOS_DEBUG, "PLL is not locked yet.\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800165 return -ERR_PLL_NOT_UNLOCKED;
166 }
167
Aaron Durbin43933462014-09-24 10:27:29 -0500168 stopwatch_init_msecs_expire(&sw, STREAM_ON_TIMEOUT);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800169 do {
170 if (s5p_dp_is_slave_video_stream_clock_on(dp) == 0) {
171 timeout++;
172 break;
173 }
Aaron Durbin43933462014-09-24 10:27:29 -0500174 } while (!stopwatch_expired(&sw));
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800175
176 if (!timeout) {
Rob Barnesd522f382022-09-12 06:31:47 -0600177 printk(BIOS_ERR, "Video Clock Not ok after %lldus.\n",
Aaron Durbin43933462014-09-24 10:27:29 -0500178 stopwatch_duration_usecs(&sw));
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800179 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
Julius Werner55009af2019-12-02 22:03:27 -0800185 clrbits32(&base->video_ctl_10, FORMAT_SEL);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800186
187 /* Disable video mute */
Julius Werner55009af2019-12-02 22:03:27 -0800188 clrbits32(&base->video_ctl_1, HDCP_VIDEO_MUTE);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800189
190 /* Configure video slave mode */
191 s5p_dp_enable_video_master(dp);
192
193 /* Enable video */
Julius Werner55009af2019-12-02 22:03:27 -0800194 setbits32(&base->video_ctl_1, VIDEO_EN);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800195 timeout = s5p_dp_is_video_stream_on(dp);
196
197 if (timeout) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700198 printk(BIOS_DEBUG, "Video Stream Not on\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800199 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 */
210static 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)) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700215 printk(BIOS_DEBUG, "DPCD read error\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800216 return -ERR_DPCD_READ_ERROR1;
217 }
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800218 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))) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700221 printk(BIOS_DEBUG, "DPCD write error\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800222 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 */
233static int s5p_dp_enable_scramble(struct s5p_dp_device *dp)
234{
235 u8 data;
236 struct exynos5_dp *base = dp->base;
237
Julius Werner55009af2019-12-02 22:03:27 -0800238 clrbits32(&base->dp_training_ptn_set, SCRAMBLING_DISABLE);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800239
240 if (s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET,
241 &data)) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700242 printk(BIOS_DEBUG, "DPCD read error\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800243 return -ERR_DPCD_READ_ERROR2;
244 }
245
246 if (s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET,
Ronald G. Minnich798f6642013-04-09 14:29:42 -0700247 (u8)(data & ~DPCD_SCRAMBLING_DISABLED))) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700248 printk(BIOS_DEBUG, "DPCD write error\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800249 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 */
259static 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 */
Julius Werner55009af2019-12-02 22:03:27 -0800268 clrbits32(&base->func_en_1, SW_FUNC_EN_N);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800269
270 ret = s5p_dp_init_analog_func(dp);
271 if (!ret)
272 break;
273
274 udelay(5000);
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700275 printk(BIOS_DEBUG, "LCD retry init, attempt=%d ret=%d\n", i, ret);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800276 }
277 if (i == DP_INIT_TRIES) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700278 printk(BIOS_DEBUG, "LCD initialization failed, ret=%d\n", ret);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800279 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 */
294static 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:
Julius Werner2f37bd62015-02-19 14:51:15 -0800303 write32(&base->ln0_link_trn_ctl, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800304 break;
305 case 1:
Julius Werner2f37bd62015-02-19 14:51:15 -0800306 write32(&base->ln1_link_trn_ctl, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800307 break;
308
309 case 2:
Julius Werner2f37bd62015-02-19 14:51:15 -0800310 write32(&base->ln2_link_trn_ctl, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800311 break;
312
313 case 3:
Julius Werner2f37bd62015-02-19 14:51:15 -0800314 write32(&base->ln3_link_trn_ctl, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800315 break;
316 default:
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700317 printk(BIOS_DEBUG, "%s: Invalid lane %d\n", __func__, lane);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800318 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 */
328static 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 */
346static 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 */
366static int s5p_dp_hw_link_training(struct s5p_dp_device *dp,
367 unsigned int max_lane,
368 unsigned int max_rate)
369{
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700370 int pll_is_locked = 0;
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800371 u32 data;
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800372 int lane;
Aaron Durbin43933462014-09-24 10:27:29 -0500373 struct stopwatch sw;
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800374 struct exynos5_dp *base = dp->base;
375
376 /* Stop Video */
Julius Werner55009af2019-12-02 22:03:27 -0800377 clrbits32(&base->video_ctl_1, VIDEO_EN);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800378
Aaron Durbin43933462014-09-24 10:27:29 -0500379 stopwatch_init_msecs_expire(&sw, PLL_LOCK_TIMEOUT);
Gabe Black9b764a02013-07-30 15:11:35 -0700380
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700381 while ((pll_is_locked = s5p_dp_get_pll_lock_status(dp)) == PLL_UNLOCKED) {
Aaron Durbin43933462014-09-24 10:27:29 -0500382 if (stopwatch_expired(&sw)) {
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800383 /* Ignore this error, and try to continue */
384 printk(BIOS_ERR, "PLL is not locked yet.\n");
385 break;
386 }
387 }
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700388 printk(BIOS_SPEW, "PLL is %slocked\n",
389 pll_is_locked == PLL_LOCKED ? "": "not ");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800390 /* Reset Macro */
Julius Werner55009af2019-12-02 22:03:27 -0800391 setbits32(&base->dp_phy_test, MACRO_RST);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800392
393 /* 10 us is the minimum reset time. */
394 udelay(10);
395
Julius Werner55009af2019-12-02 22:03:27 -0800396 clrbits32(&base->dp_phy_test, MACRO_RST);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800397
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,
Ronald G. Minnich798f6642013-04-09 14:29:42 -0700401 PRE_EMPHASIS_LEVEL_0, lane)) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700402 printk(BIOS_DEBUG, "Unable to set pre emphasis level\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800403 return -ERR_PRE_EMPHASIS_LEVELS;
404 }
405
406 /* All DP analog module power up */
Julius Werner2f37bd62015-02-19 14:51:15 -0800407 write32(&base->dp_phy_pd, 0x00);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800408
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
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700413 printk(BIOS_SPEW, "%s: rate 0x%x, lane_count %d\n", __func__,
414 dp->link_train.link_rate, dp->link_train.lane_count);
415
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800416 if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
417 (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700418 printk(BIOS_DEBUG, "Rx Max Link Rate is abnormal :%x !\n",
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800419 dp->link_train.link_rate);
420 /* Not Retrying */
421 return -ERR_LINK_RATE_ABNORMAL;
422 }
423
424 if (dp->link_train.lane_count == 0) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700425 printk(BIOS_DEBUG, "Rx Max Lane count is abnormal :%x !\n",
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800426 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*/
Julius Werner2f37bd62015-02-19 14:51:15 -0800438 write32(&base->lane_count_set, dp->link_train.lane_count);
439 write32(&base->link_bw_set, dp->link_train.link_rate);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800440
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 */
Julius Werner2f37bd62015-02-19 14:51:15 -0800446 write32(&base->dp_hw_link_training, HW_TRAINING_EN);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800447
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700448 /* Wait until HW link training done */
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800449 s5p_dp_wait_hw_link_training_done(dp);
450
451 /* Get hardware link training status */
Julius Werner2f37bd62015-02-19 14:51:15 -0800452 data = read32(&base->dp_hw_link_training);
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700453 printk(BIOS_SPEW, "hardware link training status: 0x%08x\n", data);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800454 if (data != 0) {
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700455 printk(BIOS_ERR, " H/W link training failure: 0x%x\n", data);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800456 return -ERR_LINK_TRAINING_FAILURE;
457 }
458
459 /* Get Link Bandwidth */
Julius Werner2f37bd62015-02-19 14:51:15 -0800460 data = read32(&base->link_bw_set);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800461
462 dp->link_train.link_rate = data;
463
Julius Werner2f37bd62015-02-19 14:51:15 -0800464 data = read32(&base->lane_count_set);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800465 dp->link_train.lane_count = data;
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700466 printk(BIOS_SPEW, "Done training: Link bandwidth: 0x%x, lane_count: %d\n",
467 dp->link_train.link_rate, data);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800468
469 return 0;
470}
471
472/*
473 * Initialize DP display
474 */
David Hendrickscd4c8c12013-04-12 16:02:44 -0700475int dp_controller_init(struct s5p_dp_device *dp_device)
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800476{
477 int ret;
478 struct s5p_dp_device *dp = dp_device;
479 struct exynos5_dp *base;
480
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800481 clock_init_dp_clock();
482
483 power_enable_dp_phy();
484 ret = s5p_dp_init_dp(dp);
485 if (ret) {
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700486 printk(BIOS_ERR, "%s: Could not initialize dp\n", __func__);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800487 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) {
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700493 printk(BIOS_ERR, "unable to do link train\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800494 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) {
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700501 printk(BIOS_ERR, "unable to set scramble mode\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800502 return ret;
503 }
504
505 ret = s5p_dp_enable_rx_to_enhanced_mode(dp);
506 if (ret) {
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700507 printk(BIOS_ERR, "unable to set enhanced mode\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800508 return ret;
509 }
510
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800511 base = dp->base;
512 /* Enable enhanced mode */
Julius Werner55009af2019-12-02 22:03:27 -0800513 setbits32(&base->sys_ctl_4, ENHANCED);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800514
Julius Werner2f37bd62015-02-19 14:51:15 -0800515 write32(&base->lane_count_set, dp->link_train.lane_count);
516 write32(&base->link_bw_set, dp->link_train.link_rate);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800517
518 s5p_dp_init_video(dp);
519 ret = s5p_dp_config_video(dp, dp->video_info);
520 if (ret) {
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700521 printk(BIOS_ERR, "unable to config video\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800522 return ret;
523 }
524
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800525 return 0;
526}
527
528/**
529 * Init the LCD controller
530 *
Martin Roth49348182016-07-06 10:17:19 -0600531 * @param panel_data
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800532 * @param lcdbase Base address of LCD frame buffer
533 * @return 0 if ok, -ve error code on error
534 */
Gabe Black1e797bd2013-05-18 15:58:46 -0700535int lcd_ctrl_init(unsigned long int fb_size,
536 struct exynos5_fimd_panel *panel_data, void *lcdbase)
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800537{
538 int ret = 0;
539
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800540 fimd_bypass();
Gabe Black1e797bd2013-05-18 15:58:46 -0700541 fb_init(fb_size, lcdbase, panel_data);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800542 return ret;
543}