diff options
author | Ronald G. Minnich <rminnich@gmail.com> | 2013-04-18 18:09:24 -0700 |
---|---|---|
committer | Ronald G. Minnich <rminnich@gmail.com> | 2013-04-23 04:41:23 +0200 |
commit | 2810afa57de26871c99e1c5bb7b3c2fbdcaf4f98 (patch) | |
tree | 9c547e62c566cfa3953ecd77562df3ef9c357c71 /src/cpu/samsung/exynos5-common | |
parent | 2c88cc0696be2b01ebd4df6f7593d8658c8fe419 (diff) |
GOOGLE/SNOW: get graphics working
This adds support for display bring-up on Snow. It
includes framebuffer initialization and LCD enable functions.
Change-Id: I16e711c97e9d02c916824f621e2313297448732b
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Signed-off-by: David Hendricks <dhendrix@chromium.org>
Reviewed-on: http://review.coreboot.org/3116
Tested-by: build bot (Jenkins)
Diffstat (limited to 'src/cpu/samsung/exynos5-common')
-rw-r--r-- | src/cpu/samsung/exynos5-common/exynos-fb.c | 76 | ||||
-rw-r--r-- | src/cpu/samsung/exynos5-common/s5p-dp-reg.c | 11 |
2 files changed, 53 insertions, 34 deletions
diff --git a/src/cpu/samsung/exynos5-common/exynos-fb.c b/src/cpu/samsung/exynos5-common/exynos-fb.c index 54a2d7a469..00ff19ee15 100644 --- a/src/cpu/samsung/exynos5-common/exynos-fb.c +++ b/src/cpu/samsung/exynos5-common/exynos-fb.c @@ -27,6 +27,7 @@ #include <arch/io.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <console/console.h> #include <cpu/samsung/exynos5250/cpu.h> #include <cpu/samsung/exynos5250/power.h> @@ -41,6 +42,28 @@ #include "cpu/samsung/exynos5250/s5p-dp.h" #include "s5p-dp-core.h" +/* + * Here is the rough outline of how we bring up the display: + * 1. Upon power-on Sink generates a hot plug detection pulse thru HPD + * 2. Source determines video mode by reading DPCD receiver capability field + * (DPCD 00000h to 0000Dh) including eDP CP capability register (DPCD + * 0000Dh). + * 3. Sink replies DPCD receiver capability field. + * 4. Source starts EDID read thru I2C-over-AUX. + * 5. Sink replies EDID thru I2C-over-AUX. + * 6. Source determines link configuration, such as MAX_LINK_RATE and + * MAX_LANE_COUNT. Source also determines which type of eDP Authentication + * method to use and writes DPCD link configuration field (DPCD 00100h to + * 0010Ah) including eDP configuration set (DPCD 0010Ah). + * 7. Source starts link training. Sink does clock recovery and equalization. + * 8. Source reads DPCD link status field (DPCD 00200h to 0020Bh). + * 9. Sink replies DPCD link status field. If main link is not stable, Source + * repeats Step 7. + * 10. Source sends MSA (Main Stream Attribute) data. Sink extracts video + * parameters and recovers stream clock. + * 11. Source sends video data. + */ + /* To help debug any init errors here, define a list of possible errors */ enum { ERR_PLL_NOT_UNLOCKED = 2, @@ -126,10 +149,8 @@ void fb_init(vidinfo_t *panel_info, void *lcdbase, { unsigned int val; u32 fbsize; - struct exynos5_fimd *fimd = - samsung_get_base_fimd(); - struct exynos5_disp_ctrl *disp_ctrl = - samsung_get_base_disp_ctrl(); + struct exynos5_fimd *fimd = samsung_get_base_fimd(); + struct exynos5_disp_ctrl *disp_ctrl = samsung_get_base_disp_ctrl(); writel(pd->ivclk | pd->fixvclk, &disp_ctrl->vidcon1); val = ENVID_ON | ENVID_F_ON | (pd->clkval_f << CLKVAL_F_OFFSET); @@ -191,7 +212,7 @@ static int s5p_dp_config_video(struct s5p_dp_device *dp, struct video_info *video_info) { int timeout = 0; - u32 start; + u32 start, end; struct exynos5_dp *base = dp->base; s5p_dp_config_video_slave_mode(dp, video_info); @@ -206,16 +227,18 @@ static int s5p_dp_config_video(struct s5p_dp_device *dp, return -ERR_PLL_NOT_UNLOCKED; } - start = get_timer(0); + start = timer_us(); + end = start + STREAM_ON_TIMEOUT*1000; do { if (s5p_dp_is_slave_video_stream_clock_on(dp) == 0) { timeout++; break; } - } while (get_timer(start) <= STREAM_ON_TIMEOUT); + } while (timer_us() < end); if (!timeout) { - printk(BIOS_DEBUG, "Video Clock Not ok\n"); + printk(BIOS_ERR, "Video Clock Not ok after %uus.\n", + timer_us() - start); return -ERR_VIDEO_CLOCK_BAD; } @@ -255,7 +278,6 @@ static int s5p_dp_enable_rx_to_enhanced_mode(struct s5p_dp_device *dp) printk(BIOS_DEBUG, "DPCD read error\n"); return -ERR_DPCD_READ_ERROR1; } - if (s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, DPCD_ENHANCED_FRAME_EN | (data & DPCD_LANE_COUNT_SET_MASK))) { @@ -408,6 +430,7 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, unsigned int max_lane, unsigned int max_rate) { + int pll_is_locked = 0; u32 data; u32 start; int lane; @@ -417,14 +440,15 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, clrbits_le32(&base->video_ctl_1, VIDEO_EN); start = get_timer(0); - while (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + while ((pll_is_locked = s5p_dp_get_pll_lock_status(dp)) == PLL_UNLOCKED) { if (get_timer(start) > PLL_LOCK_TIMEOUT) { /* Ignore this error, and try to continue */ printk(BIOS_ERR, "PLL is not locked yet.\n"); break; } } - + printk(BIOS_SPEW, "PLL is %slocked\n", + pll_is_locked == PLL_LOCKED ? "": "not "); /* Reset Macro */ setbits_le32(&base->dp_phy_test, MACRO_RST); @@ -448,6 +472,9 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, s5p_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); s5p_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); + printk(BIOS_SPEW, "%s: rate 0x%x, lane_count %d\n", __func__, + dp->link_train.link_rate, dp->link_train.lane_count); + if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) && (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { printk(BIOS_DEBUG, "Rx Max Link Rate is abnormal :%x !\n", @@ -480,13 +507,14 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, /* Start HW link training */ writel(HW_TRAINING_EN, &base->dp_hw_link_training); - /* Wait unitl HW link training done */ + /* Wait until HW link training done */ s5p_dp_wait_hw_link_training_done(dp); /* Get hardware link training status */ data = readl(&base->dp_hw_link_training); + printk(BIOS_SPEW, "hardware link training status: 0x%08x\n", data); if (data != 0) { - printk(BIOS_DEBUG, " H/W link training failure: 0x%x\n", data); + printk(BIOS_ERR, " H/W link training failure: 0x%x\n", data); return -ERR_LINK_TRAINING_FAILURE; } @@ -497,6 +525,8 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp, data = readl(&base->lane_count_set); dp->link_train.lane_count = data; + printk(BIOS_SPEW, "Done training: Link bandwidth: 0x%x, lane_count: %d\n", + dp->link_train.link_rate, data); return 0; } @@ -510,24 +540,19 @@ int dp_controller_init(struct s5p_dp_device *dp_device) struct s5p_dp_device *dp = dp_device; struct exynos5_dp *base; - //dp->base = (struct exynos5_dp *)addr; - /* yes. we're a snow. Yet somehow our config is from a development kit? - * This Must Change */ - //dp->video_info = &smdk5250_dp_config; - clock_init_dp_clock(); power_enable_dp_phy(); ret = s5p_dp_init_dp(dp); if (ret) { - printk(BIOS_DEBUG, "%s: Could not initialize dp\n", __func__); + printk(BIOS_ERR, "%s: Could not initialize dp\n", __func__); return ret; } ret = s5p_dp_hw_link_training(dp, dp->video_info->lane_count, dp->video_info->link_rate); if (ret) { - printk(BIOS_DEBUG, "unable to do link train\n"); + printk(BIOS_ERR, "unable to do link train\n"); return ret; } /* Minimum delay after H/w Link training */ @@ -535,13 +560,13 @@ int dp_controller_init(struct s5p_dp_device *dp_device) ret = s5p_dp_enable_scramble(dp); if (ret) { - printk(BIOS_DEBUG, "unable to set scramble mode\n"); + printk(BIOS_ERR, "unable to set scramble mode\n"); return ret; } ret = s5p_dp_enable_rx_to_enhanced_mode(dp); if (ret) { - printk(BIOS_DEBUG, "unable to set enhanced mode\n"); + printk(BIOS_ERR, "unable to set enhanced mode\n"); return ret; } @@ -556,7 +581,7 @@ int dp_controller_init(struct s5p_dp_device *dp_device) s5p_dp_init_video(dp); ret = s5p_dp_config_video(dp, dp->video_info); if (ret) { - printk(BIOS_DEBUG, "unable to config video\n"); + printk(BIOS_ERR, "unable to config video\n"); return ret; } @@ -576,10 +601,5 @@ int lcd_ctrl_init(vidinfo_t *panel_info, fimd_bypass(); fb_init(panel_info, lcdbase, panel_data); - printk(BIOS_SPEW, - "fb_init(%p, %p, %p) done\n", panel_info, lcdbase, panel_data); - - /* Enable flushing after LCD writes if requested */ - // forget it. lcd_set_flush_dcache(1); return ret; } diff --git a/src/cpu/samsung/exynos5-common/s5p-dp-reg.c b/src/cpu/samsung/exynos5-common/s5p-dp-reg.c index 60e1398ba4..cce8c6d212 100644 --- a/src/cpu/samsung/exynos5-common/s5p-dp-reg.c +++ b/src/cpu/samsung/exynos5-common/s5p-dp-reg.c @@ -129,7 +129,8 @@ int s5p_dp_init_analog_func(struct s5p_dp_device *dp) start = get_timer(0); while (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { if (get_timer(start) > PLL_LOCK_TIMEOUT) { - printk(BIOS_DEBUG, "%s: PLL is not locked yet\n", __func__); + printk(BIOS_ERR, "%s: PLL is not locked\n", + __func__); return -1; } } @@ -176,9 +177,6 @@ int s5p_dp_start_aux_transaction(struct s5p_dp_device *dp) /* Enable AUX CH operation */ setbits_le32(&base->aux_ch_ctl_2, AUX_EN); - printk(BIOS_DEBUG, "%s: base: 0x%p, &base->aux_ch_ctl_2: 0x%p, aux_ch_ctl_2: 0x%08x\n", - __func__, base, &base->aux_ch_ctl_2, readl(&base->aux_ch_ctl_2)); - /* Is AUX CH command reply received? */ reg = readl(&base->dp_int_sta); while (!(reg & RPLY_RECEIV)) @@ -189,8 +187,9 @@ int s5p_dp_start_aux_transaction(struct s5p_dp_device *dp) /* Clear interrupt source for AUX CH access error */ reg = readl(&base->dp_int_sta); - printk(BIOS_DEBUG, "%s: dp_int_sta: 0x%02x\n", __func__, reg); if (reg & AUX_ERR) { + printk(BIOS_ERR, "%s: AUX_ERR encountered, dp_int_sta: " + "0x%02x\n", __func__, reg); writel(AUX_ERR, &base->dp_int_sta); return -1; } @@ -198,7 +197,7 @@ int s5p_dp_start_aux_transaction(struct s5p_dp_device *dp) /* Check AUX CH error access status */ reg = readl(&base->dp_int_sta); if ((reg & AUX_STATUS_MASK) != 0) { - printk(BIOS_DEBUG, "AUX CH error happens: %d\n\n", + printk(BIOS_ERR, "AUX CH error happens: %d\n\n", reg & AUX_STATUS_MASK); return -1; } |