[coreboot-gerrit] Patch set updated for coreboot: 4882503 GOOGLE/SNOW: get graphics working

David Hendricks (dhendrix@chromium.org) gerrit at coreboot.org
Tue Apr 23 02:48:29 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 4882503f6a11413a4d8cb42e6e1ce87a36854999
Author: Ronald G. Minnich <rminnich at gmail.com>
Date:   Thu Apr 18 18:09:24 2013 -0700

    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 at gmail.com>
    Signed-off-by: David Hendricks <dhendrix at chromium.org>
---
 src/cpu/samsung/exynos5-common/exynos-fb.c  | 76 ++++++++++++++++++-----------
 src/cpu/samsung/exynos5-common/s5p-dp-reg.c | 11 ++---
 src/cpu/samsung/exynos5250/cpu.c            | 25 ++++++++--
 src/mainboard/google/snow/Kconfig           |  2 +
 src/mainboard/google/snow/ramstage.c        | 36 ++++++++++++++
 5 files changed, 113 insertions(+), 37 deletions(-)

diff --git a/src/cpu/samsung/exynos5-common/exynos-fb.c b/src/cpu/samsung/exynos5-common/exynos-fb.c
index 54a2d7a..00ff19e 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 60e1398..cce8c6d 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;
 	}
diff --git a/src/cpu/samsung/exynos5250/cpu.c b/src/cpu/samsung/exynos5250/cpu.c
index e122413..8bf0d49 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 54d13d3..09b51a7 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