[coreboot-gerrit] Patch set updated for coreboot: a278543 GOOGLE/SNOW: get graphics working
David Hendricks (dhendrix@chromium.org)
gerrit at coreboot.org
Sun Apr 21 02:52:49 CEST 2013
David Hendricks (dhendrix at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/3116
-gerrit
commit a2785438a20105e0665ba6e2578ecf57d92f5a19
Author: Ronald G. Minnich <rminnich at gmail.com>
Date: Thu Apr 18 18:09:24 2013 -0700
GOOGLE/SNOW: get graphics working
This adds preliminary 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 at gmail.com>
Signed-off-by: David Hendricks <dhendrix at chromium.org>
---
src/cpu/samsung/exynos5-common/exynos-fb.c | 84 ++++++++++++++++++++++++-----
src/cpu/samsung/exynos5-common/s5p-dp-reg.c | 10 ++--
src/cpu/samsung/exynos5250/cpu.c | 25 +++++++--
src/mainboard/google/snow/Kconfig | 2 +
src/mainboard/google/snow/ramstage.c | 36 +++++++++++++
5 files changed, 138 insertions(+), 19 deletions(-)
diff --git a/src/cpu/samsung/exynos5-common/exynos-fb.c b/src/cpu/samsung/exynos5-common/exynos-fb.c
index 54a2d7a..cdb5881 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,38 +149,54 @@ 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();
+
+ printk(BIOS_SPEW, "%s: fimd %p disp_ctrl %p\n",
+ __func__, fimd, disp_ctrl);
+ printk(BIOS_SPEW, "pd %p\n", pd);
+ printk(BIOS_SPEW, "lcdbase %p\n", lcdbase);
+ printk(BIOS_SPEW, "pd->xres %d pd->yres %d\n", pd->xres, pd->yres);
+ printk(BIOS_SPEW, "Write %08x to %p\n",
+ pd->ivclk | pd->fixvclk, &disp_ctrl->vidcon1);
writel(pd->ivclk | pd->fixvclk, &disp_ctrl->vidcon1);
val = ENVID_ON | ENVID_F_ON | (pd->clkval_f << CLKVAL_F_OFFSET);
+ printk(BIOS_SPEW, "Write %08x to fimd->vidcon0\n", val);
writel(val, &fimd->vidcon0);
val = (pd->vsync << VSYNC_PULSE_WIDTH_OFFSET) |
(pd->lower_margin << V_FRONT_PORCH_OFFSET) |
(pd->upper_margin << V_BACK_PORCH_OFFSET);
+ printk(BIOS_SPEW, "Write %08x to %p\n", val, &disp_ctrl->vidtcon0);
writel(val, &disp_ctrl->vidtcon0);
val = (pd->hsync << HSYNC_PULSE_WIDTH_OFFSET) |
(pd->right_margin << H_FRONT_PORCH_OFFSET) |
(pd->left_margin << H_BACK_PORCH_OFFSET);
+ printk(BIOS_SPEW, "Write %08x to %p\n", val, &disp_ctrl->vidtcon1);
writel(val, &disp_ctrl->vidtcon1);
val = ((pd->xres - 1) << HOZVAL_OFFSET) |
((pd->yres - 1) << LINEVAL_OFFSET);
+ printk(BIOS_SPEW, "Write %08x to %p\n", val, &disp_ctrl->vidtcon2);
writel(val, &disp_ctrl->vidtcon2);
+ printk(BIOS_SPEW, "Write %08x to %p\n",
+ (unsigned int)lcdbase, &fimd->vidw00add0b0);
writel((unsigned int)lcdbase, &fimd->vidw00add0b0);
fbsize = calc_fbsize(panel_info);
+ printk(BIOS_SPEW, "Write %08x to %p\n",
+ (unsigned int)fbsize, &fimd->vidw00add1b0);
writel((unsigned int)lcdbase + fbsize, &fimd->vidw00add1b0);
+ printk(BIOS_SPEW, "Write %08x to %p\n",
+ (unsigned int)pd->xres*2, &fimd->vidw00add0b0);
writel(pd->xres * 2, &fimd->vidw00add2);
val = ((pd->xres - 1) << OSD_RIGHTBOTX_F_OFFSET);
val |= ((pd->yres - 1) << OSD_RIGHTBOTY_F_OFFSET);
+ printk(BIOS_SPEW, "Write %08x to %p\n", val, &fimd->vidosd0b);
writel(val, &fimd->vidosd0b);
writel(pd->xres * pd->yres, &fimd->vidosd0c);
@@ -165,6 +204,7 @@ void fb_init(vidinfo_t *panel_info, void *lcdbase,
val = BPPMODE_F_RGB_16BIT_565 << BPPMODE_F_OFFSET;
val |= ENWIN_F_ENABLE | HALF_WORD_SWAP_EN;
+ printk(BIOS_SPEW, "Write %08x to %p\n", val, &fimd->wincon0);
writel(val, &fimd->wincon0);
/* DPCLKCON_ENABLE */
@@ -191,7 +231,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 +246,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_DEBUG, "Video Clock Not ok after %uus.\n",
+ timer_us() - start);
return -ERR_VIDEO_CLOCK_BAD;
}
@@ -255,7 +297,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 +449,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 +459,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 +491,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",
@@ -470,21 +516,27 @@ static int s5p_dp_hw_link_training(struct s5p_dp_device *dp,
dp->link_train.link_rate = max_rate;
/* Set link rate and count as you want to establish*/
+ printk(BIOS_SPEW, "Set link rate and count\n");
writel(dp->link_train.lane_count, &base->lane_count_set);
writel(dp->link_train.link_rate, &base->link_bw_set);
/* Set sink to D0 (Sink Not Ready) mode. */
+ printk(BIOS_SPEW, "Set sink rate to D0\n");
s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
DPCD_SET_POWER_STATE_D0);
/* Start HW link training */
+ printk(BIOS_SPEW, "Start Link hardware training\n");
writel(HW_TRAINING_EN, &base->dp_hw_link_training);
- /* Wait unitl HW link training done */
+ /* Wait until HW link training done */
+ printk(BIOS_SPEW, "Wait until HW link training done\n");
s5p_dp_wait_hw_link_training_done(dp);
+ printk(BIOS_SPEW, "HW link training done\n");
/* 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);
return -ERR_LINK_TRAINING_FAILURE;
@@ -497,6 +549,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;
}
@@ -533,12 +587,14 @@ int dp_controller_init(struct s5p_dp_device *dp_device)
/* Minimum delay after H/w Link training */
udelay(1000);
+ printk(BIOS_DEBUG, "call s5p_dp_enable_scramble\n");
ret = s5p_dp_enable_scramble(dp);
if (ret) {
printk(BIOS_DEBUG, "unable to set scramble mode\n");
return ret;
}
+ printk(BIOS_DEBUG, "call s5p_dp_enable_rx_to_enhanced_mode\n");
ret = s5p_dp_enable_rx_to_enhanced_mode(dp);
if (ret) {
printk(BIOS_DEBUG, "unable to set enhanced mode\n");
@@ -553,7 +609,9 @@ int dp_controller_init(struct s5p_dp_device *dp_device)
writel(dp->link_train.lane_count, &base->lane_count_set);
writel(dp->link_train.link_rate, &base->link_bw_set);
+ printk(BIOS_DEBUG, "call s5p_dp_init_video\n");
s5p_dp_init_video(dp);
+ printk(BIOS_DEBUG, "call s5p_dp_config_video\n");
ret = s5p_dp_config_video(dp, dp->video_info);
if (ret) {
printk(BIOS_DEBUG, "unable to config video\n");
diff --git a/src/cpu/samsung/exynos5-common/s5p-dp-reg.c b/src/cpu/samsung/exynos5-common/s5p-dp-reg.c
index 60e1398..6b5cd69 100644
--- a/src/cpu/samsung/exynos5-common/s5p-dp-reg.c
+++ b/src/cpu/samsung/exynos5-common/s5p-dp-reg.c
@@ -102,6 +102,8 @@ unsigned int s5p_dp_get_pll_lock_status(struct s5p_dp_device *dp)
u32 reg;
reg = readl(&dp->base->dp_debug_ctl);
+ printk(BIOS_SPEW, "%s: reg is 0x%x, PLL_LOCK is 0x%x\n",
+ __func__, reg, PLL_LOCK);
if (reg & PLL_LOCK)
return PLL_LOCKED;
else
@@ -129,7 +131,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_DEBUG, "%s: PLL is not locked\n",
+ __func__);
return -1;
}
}
@@ -176,8 +179,9 @@ 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));
+ 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);
diff --git a/src/cpu/samsung/exynos5250/cpu.c b/src/cpu/samsung/exynos5250/cpu.c
index 09b670e..677b0f4 100644
--- a/src/cpu/samsung/exynos5250/cpu.c
+++ b/src/cpu/samsung/exynos5250/cpu.c
@@ -5,6 +5,7 @@
#include <console/console.h>
#include <device/device.h>
#include <cbmem.h>
+#include <arch/cache.h>
#include <cpu/samsung/exynos5250/fimd.h>
#include <cpu/samsung/exynos5-common/s5p-dp-core.h>
#include "chip.h"
@@ -32,7 +33,6 @@ static void exynos_displayport_init(device_t dev)
unsigned long int fb_size;
u32 lcdbase;
- printk(BIOS_SPEW, "%s: dev 0x%p, conf 0x%p\n", __func__, dev, conf);
memset(&vi, 0, sizeof(vi));
memset(&panel, 0, sizeof(panel));
@@ -61,16 +61,35 @@ static void exynos_displayport_init(device_t dev)
* The size is a magic number from hardware. Allocate enough for the
* frame buffer and color map.
*/
- fb_size = conf->xres * conf->yres * sizeof(unsigned long);
+ fb_size = conf->xres * conf->yres * (conf->bpp / 8);
lcdbase = (uintptr_t)cbmem_add(CBMEM_ID_CONSOLE, fb_size + 64*KiB);
printk(BIOS_SPEW, "lcd colormap base is %p\n", (void *)(lcdbase));
mmio_resource(dev, 0, lcdbase/KiB, 64);
vi.cmap = (void *)lcdbase;
+ /*
+ * We need to clean and invalidate the framebuffer region and disable
+ * caching as well. We assume that our dcache <--> memory address
+ * space is identity-mapped in 1MB chunks, so align accordingly.
+ *
+ * Note: We may want to do something clever to ensure the framebuffer
+ * region is aligned such that we don't change dcache policy for other
+ * stuff inadvertantly.
+ *
+ * FIXME: Is disabling/re-enabling the MMU entirely necessary?
+ */
+ uint32_t lower = ALIGN_DOWN(lcdbase, MiB);
+ uint32_t upper = ALIGN_UP(lcdbase + fb_size + 64*KiB, MiB);
+ dcache_clean_invalidate_by_mva(lower, upper - lower);
+ dcache_mmu_disable();
+ mmu_config_range(lower/MiB, (upper - lower)/MiB, DCACHE_OFF);
+ dcache_mmu_enable();
+
lcdbase += 64*KiB;
mmio_resource(dev, 1, lcdbase/KiB, fb_size + (KiB-1)/KiB);
printk(BIOS_DEBUG,
- "Initializing exynos VGA, base %p\n",(void *)lcdbase);
+ "Initializing exynos VGA, base %p\n", (void *)lcdbase);
+ memset((void *)lcdbase, 0, fb_size); /* clear the framebuffer */
ret = lcd_ctrl_init(&vi, &panel, (void *)lcdbase);
}
diff --git a/src/mainboard/google/snow/Kconfig b/src/mainboard/google/snow/Kconfig
index 6d3d7c8..c28a986 100644
--- a/src/mainboard/google/snow/Kconfig
+++ b/src/mainboard/google/snow/Kconfig
@@ -33,6 +33,8 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select EXYNOS_DISPLAYPORT
select CHROMEOS
select DRIVER_TI_TPS65090
+ select MAINBOARD_HAS_NATIVE_VGA_INIT
+ select MAINBOARD_DO_NATIVE_VGA_INIT
config MAINBOARD_DIR
string
diff --git a/src/mainboard/google/snow/ramstage.c b/src/mainboard/google/snow/ramstage.c
index 1cd84e8..c2c9374 100644
--- a/src/mainboard/google/snow/ramstage.c
+++ b/src/mainboard/google/snow/ramstage.c
@@ -23,6 +23,7 @@
#include <drivers/ti/tps65090/tps65090.h>
#include <cbmem.h>
#include <delay.h>
+#include <boot/coreboot_tables.h>
#include <arch/cache.h>
#include <arch/exception.h>
#include <arch/gpio.h>
@@ -41,6 +42,41 @@
#define DRAM_SIZE CONFIG_DRAM_SIZE_MB
#define DRAM_END (DRAM_START + DRAM_SIZE) /* plus one... */
+int vbe_mode_info_valid(void);
+int vbe_mode_info_valid(void)
+{
+ return 1;
+}
+
+void fill_lb_framebuffer(struct lb_framebuffer *framebuffer);
+void fill_lb_framebuffer(struct lb_framebuffer *framebuffer)
+{
+ /*
+ * The address returned points at the LCD colormap base. The
+ * 64KiB offset points at the LCD base.
+ */
+ framebuffer->physical_address =
+ (u32)cbmem_find(CBMEM_ID_CONSOLE) + 64*KiB;
+ printk(BIOS_SPEW, "%s: framebuffer->physical address is 0x%llx\n",
+ __func__, framebuffer->physical_address);
+
+ framebuffer->x_resolution = 1366;
+ framebuffer->y_resolution = 768;
+ framebuffer->bits_per_pixel = 16;
+ framebuffer->bytes_per_line =
+ (framebuffer->x_resolution * framebuffer->bits_per_pixel) / 8;
+
+ framebuffer->red_mask_pos = 11;
+ framebuffer->red_mask_size = 5;
+ framebuffer->green_mask_pos = 6;
+ framebuffer->green_mask_size = 5;
+ framebuffer->blue_mask_pos = 0;
+ framebuffer->blue_mask_size = 5;
+ framebuffer->reserved_mask_pos = 0;
+ framebuffer->reserved_mask_size = 0;
+}
+
+
void hardwaremain(int boot_complete);
void main(void)
{
More information about the coreboot-gerrit
mailing list