code:
From c82d4fa874322d70dec0e9d28c050e4c351de157 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Fri, 2 Sep 2016 23:14:54 +0200
Subject: [PATCH 1/5] move DIV_ROUND macros to commonlib

DIV_ROUND_CLOSEST and DIV_ROUND_UP are useful macros for other
architectures. This patch moves them from soc/nvidia/tegra/types.h
to commonlib/include/commonlib/helpers.h .

Change-Id: I54521d9b197934cef8e352f9a5c4823015d85f01
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>

diff --git a/src/commonlib/include/commonlib/helpers.h b/src/commonlib/include/commonlib/helpers.h
index 0318e44..0b2395b 100644
--- a/src/commonlib/include/commonlib/helpers.h
+++ b/src/commonlib/include/commonlib/helpers.h
@@ -34,6 +34,22 @@
 #define ABS(a) (((a) < 0) ? (-(a)) : (a))
 #define CEIL_DIV(a, b)  (((a) + (b) - 1) / (b))
 #define IS_POWER_OF_2(x)  (((x) & ((x) - 1)) == 0)
+#define DIV_ROUND_UP(x, y)  (((x) + (y) - 1) / (y))
+/*
+ * Divide positive or negative dividend by positive divisor and round
+ * to closest integer. Result is undefined for negative divisors and
+ * for negative dividends if the divisor variable type is unsigned.
+ */
+#define DIV_ROUND_CLOSEST(x, divisor)(			\
+{							\
+	typeof(x) __x = x;				\
+	typeof(divisor) __d = divisor;			\
+	(((typeof(x))-1) > 0 ||				\
+	 ((typeof(divisor))-1) > 0 || (__x) > 0) ?	\
+		(((__x) + ((__d) / 2)) / (__d)) :	\
+		(((__x) - ((__d) / 2)) / (__d));	\
+}							\
+)

 /* Standard units. */
 #define KiB (1<<10)
diff --git a/src/soc/nvidia/tegra/types.h b/src/soc/nvidia/tegra/types.h
index dab474d..bfeebae 100644
--- a/src/soc/nvidia/tegra/types.h
+++ b/src/soc/nvidia/tegra/types.h
@@ -51,22 +51,4 @@
 	(type *)( (char *)__mptr - offsetof(type,member) );})
 #endif

-#define DIV_ROUND_UP(x, y)  (((x) + (y) - 1) / (y))
-
-/*
- * Divide positive or negative dividend by positive divisor and round
- * to closest integer. Result is undefined for negative divisors and
- * for negative dividends if the divisor variable type is unsigned.
- */
-#define DIV_ROUND_CLOSEST(x, divisor)(			\
-{							\
-	typeof(x) __x = x;				\
-	typeof(divisor) __d = divisor;			\
-	(((typeof(x))-1) > 0 ||				\
-	 ((typeof(divisor))-1) > 0 || (__x) > 0) ?	\
-		(((__x) + ((__d) / 2)) / (__d)) :	\
-		(((__x) - ((__d) / 2)) / (__d));	\
-}							\
-)
-
 #endif /* __TEGRA_MISC_TYPES_H__ */
diff --git a/src/soc/nvidia/tegra210/addressmap.c b/src/soc/nvidia/tegra210/addressmap.c
index e803e1b..b47c5c5 100644
--- a/src/soc/nvidia/tegra210/addressmap.c
+++ b/src/soc/nvidia/tegra210/addressmap.c
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <symbols.h>
 #include <soc/nvidia/tegra/types.h>
+#include <commonlib/helpers.h>

 static uintptr_t tz_base_mib;
 static const size_t tz_size_mib = CONFIG_TRUSTZONE_CARVEOUT_SIZE_MB;
diff --git a/src/soc/nvidia/tegra210/dsi.c b/src/soc/nvidia/tegra210/dsi.c
index 3b771c9..5504b4d 100644
--- a/src/soc/nvidia/tegra210/dsi.c
+++ b/src/soc/nvidia/tegra210/dsi.c
@@ -32,6 +32,7 @@
 #include <soc/tegra_dsi.h>
 #include <soc/mipi-phy.h>
 #include "jdi_25x18_display/panel-jdi-lpm102a188a.h"
+#include <commonlib/helpers.h>

 struct tegra_mipi_device mipi_device_data[NUM_DSI];

--
2.9.3


code:
From f09ce5870025a98b6e497fd232adffde468c735a Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Fri, 2 Sep 2016 22:35:32 +0200
Subject: [PATCH 2/5] i945/gma.c use latest linux code to calculate divisors.

The code to compute n, m1, m2, p1 divisors is not correct in coreboot and
on some targets hits a working mode at lower refresh rate, which is why
display is working on some targets.
This patch also fixes reference frequency.

This patch reuses linux code to correctly compute divisors.

The result is that some previously not working displays (Lenovo T60 with
1024x786, 1400x1050, 2048x1536)

TESTED on T60 with 1024x786.

Change-Id: I2c7f3bb0024ac005029eaebe3ecdc70c38ac777e
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>

diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c
index 02caa0a..d1d68d4 100644
--- a/src/northbridge/intel/i945/gma.c
+++ b/src/northbridge/intel/i945/gma.c
@@ -26,6 +26,8 @@
 #include <string.h>
 #include <pc80/vga.h>
 #include <pc80/vga_io.h>
+#include <commonlib/helpers.h>
+

 #include "i945.h"
 #include "chip.h"
@@ -43,7 +45,7 @@
 #define PGETBL_CTL	0x2020
 #define PGETBL_ENABLED	0x00000001

-#define BASE_FREQUENCY 120000
+#define BASE_FREQUENCY 100000

 #if CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT

@@ -85,10 +87,10 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf,
 	u8 edid_data[128];
 	unsigned long temp;
 	int hpolarity, vpolarity;
-	u32 candp1, candn;
-	u32 best_delta = 0xffffffff;
+	u32 err_most = 0xffffffff;
 	u32 target_frequency;
 	u32 pixel_p1 = 1;
+	u32 pixel_p2;
 	u32 pixel_n = 1;
 	u32 pixel_m1 = 1;
 	u32 pixel_m2 = 1;
@@ -158,43 +160,37 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf,
 	write32(pmmio + PORT_HOTPLUG_EN, conf->gpu_hotplug);
 	write32(pmmio + INSTPM, 0x08000000 | INSTPM_AGPBUSY_DIS);

-	target_frequency = mode->lvds_dual_channel ? mode->pixel_clock
-		: (2 * mode->pixel_clock);
-
-	/* Find suitable divisors.  */
-	for (candp1 = 1; candp1 <= 8; candp1++) {
-		for (candn = 5; candn <= 10; candn++) {
-			u32 cur_frequency;
-			u32 m; /* 77 - 131.  */
-			u32 denom; /* 35 - 560.  */
-			u32 current_delta;
-
-			denom = candn * candp1 * 7;
-			/* Doesnt overflow for up to
-			   5000000 kHz = 5 GHz.  */
-			m = (target_frequency * denom
-			     + BASE_FREQUENCY / 2) / BASE_FREQUENCY;
-
-			if (m < 77 || m > 131)
-				continue;
-
-			cur_frequency = (BASE_FREQUENCY * m) / denom;
-			if (target_frequency > cur_frequency)
-				current_delta = target_frequency - cur_frequency;
-			else
-				current_delta = cur_frequency - target_frequency;
-
-			if (best_delta > current_delta) {
-				best_delta = current_delta;
-				pixel_n = candn;
-				pixel_p1 = candp1;
-				pixel_m2 = ((m + 3) % 5) + 7;
-				pixel_m1 = (m - pixel_m2) / 5;
+	pixel_p2 = mode->lvds_dual_channel ? 7 : 14;
+	target_frequency = mode->pixel_clock;
+
+	/* Find suitable divisors, m1, m2, p1, n.  */
+	/* refclock * (5 * (m1 + 2) + (m1 + 2)) / (n + 2) / p1 / p2 */
+	/* should be closest to target frequency as possible */
+	u32 candn, candm1, candm2, candp1;
+	for (candm1 = 8; candm1 <= 18; candm1++) {
+		for (candm2 = 3; candm2 <= 7; candm2++) {
+			for (candn = 1; candn <= 6; candn++) {
+				for (candp1 = 1; candp1 <= 8; candp1++) {
+					u32 m = 5 * (candm1 + 2) + (candm2 + 2);
+					u32 p = candp1 * pixel_p2;
+					u32 vco = DIV_ROUND_CLOSEST(BASE_FREQUENCY * m, candn + 2);
+					u32 dot = DIV_ROUND_CLOSEST(vco, p);
+					u32 this_err = ABS(dot - target_frequency);
+					if ((m < 70) || (m > 120))
+						continue;
+					if (this_err < err_most) {
+						err_most = this_err;
+						pixel_n = candn;
+						pixel_m1 = candm1;
+						pixel_m2 = candm2;
+						pixel_p1 = candp1;
+					}
+				}
 			}
 		}
 	}

-	if (best_delta == 0xffffffff) {
+	if (err_most == 0xffffffff) {
 		printk (BIOS_ERR, "Couldn't find GFX clock divisors\n");
 		return -1;
 	}
@@ -216,8 +212,8 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf,
 	printk(BIOS_DEBUG, "Pixel N=%d, M1=%d, M2=%d, P1=%d\n",
 	       pixel_n, pixel_m1, pixel_m2, pixel_p1);
 	printk(BIOS_DEBUG, "Pixel clock %d kHz\n",
-	       BASE_FREQUENCY * (5 * pixel_m1 + pixel_m2) / pixel_n
-	       / (pixel_p1 * 7));
+	       BASE_FREQUENCY * (5 * (pixel_m1 + 2) + (pixel_m2 + 2)) /
+	       (pixel_n + 2) / (pixel_p1 * pixel_p2));

 #if !IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)
 	write32(pmmio + PF_WIN_SZ(0), vactive | (hactive << 16));
@@ -242,8 +238,8 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf,
 	write32(pmmio + PP_CONTROL, PANEL_UNLOCK_REGS
 		| (read32(pmmio + PP_CONTROL) & ~PANEL_UNLOCK_MASK));
 	write32(pmmio + FP0(1),
-		((pixel_n - 2) << 16)
-		| ((pixel_m1 - 2) << 8) | pixel_m2);
+		(pixel_n << 16)
+		| (pixel_m1 << 8) | pixel_m2);
 	write32(pmmio + DPLL(1),
 		DPLL_VGA_MODE_DIS |
 		DPLL_VCO_ENABLE | DPLLB_MODE_LVDS
@@ -252,8 +248,7 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf,
 		| (conf->gpu_lvds_use_spread_spectrum_clock
 		   ? DPLL_INTEGRATED_CLOCK_VLV | DPLL_INTEGRATED_CRI_CLK_VLV
 		   : 0)
-		| (pixel_p1 << 16)
-		| (pixel_p1));
+		| (0x10000 << pixel_p1));
 	mdelay(1);
 	write32(pmmio + DPLL(1),
 		DPLL_VGA_MODE_DIS |
@@ -261,8 +256,7 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf,
 		| (mode->lvds_dual_channel ? DPLLB_LVDS_P2_CLOCK_DIV_7
 		   : DPLLB_LVDS_P2_CLOCK_DIV_14)
 		| ((conf->gpu_lvds_use_spread_spectrum_clock ? 3 : 0) << 13)
-		| (pixel_p1 << 16)
-		| (pixel_p1));
+		| (0x10000 << pixel_p1));
 	mdelay(1);
 	write32(pmmio + HTOTAL(1),
 		((hactive + right_border + hblank - 1) << 16)
--
2.9.3

repo_name: exotime/libreboot

license: mit


code:
From 09546d389511350d1b33b3c6bd9230de8bbbe317 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Mon, 5 Sep 2016 22:46:11 +0200
Subject: [PATCH 3/5] i945/gma.c: add native VGA init

This reuses the intel pineview native graphic initialization
to have output on the VGA connector of i945 devices.

The behavior is the same as with the vbios blob.
It uses the external VGA display if it is connected.

Change-Id: I7eaee87d16df2e5c9ebeaaff01d36ec1aa4ea495
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>

diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c
index d1d68d4..37674d7 100644
--- a/src/northbridge/intel/i945/gma.c
+++ b/src/northbridge/intel/i945/gma.c
@@ -78,7 +78,7 @@ static int gtt_setup(void *mmiobase)
 	return 0;
 }

-static int intel_gma_init(struct northbridge_intel_i945_config *conf,
+static int intel_gma_init_lvds(struct northbridge_intel_i945_config *conf,
 			  unsigned int pphysbase, unsigned int piobase,
 			  void *pmmio, unsigned int pgfx)
 {
@@ -382,6 +382,194 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf,
 #endif
 	return 0;
 }
+
+static int intel_gma_init_vga(struct northbridge_intel_i945_config *conf,
+			  unsigned int pphysbase, unsigned int piobase,
+			  void *pmmio, unsigned int pgfx)
+{
+	int i;
+	u32 hactive, vactive;
+	u16 reg16;
+	u32 uma_size;
+
+	printk(BIOS_SPEW, "pmmio %x addrport %x physbase %x\n",
+		(u32)pmmio, piobase, pphysbase);
+
+	gtt_setup(pmmio);
+
+	/* Disable VGA.  */
+	write32(pmmio + VGACNTRL, VGA_DISP_DISABLE);
+
+	/* Disable pipes.  */
+	write32(pmmio + PIPECONF(0), 0);
+	write32(pmmio + PIPECONF(1), 0);
+
+	write32(pmmio + INSTPM, 0x800);
+
+	vga_gr_write(0x18, 0);
+
+	write32(pmmio + VGA0, 0x200074);
+	write32(pmmio + VGA1, 0x200074);
+
+	write32(pmmio + DSPFW3, 0x7f3f00c1 & ~PINEVIEW_SELF_REFRESH_EN);
+	write32(pmmio + DSPCLK_GATE_D, 0);
+	write32(pmmio + FW_BLC, 0x03060106);
+	write32(pmmio + FW_BLC2, 0x00000306);
+
+	write32(pmmio + ADPA, ADPA_DAC_ENABLE
+			| ADPA_PIPE_A_SELECT
+			| ADPA_USE_VGA_HVPOLARITY
+			| ADPA_VSYNC_CNTL_ENABLE
+			| ADPA_HSYNC_CNTL_ENABLE
+			| ADPA_DPMS_ON
+			);
+
+	write32(pmmio + 0x7041c, 0x0);
+
+	write32(pmmio + DPLL_MD(0), 0x3);
+	write32(pmmio + DPLL_MD(1), 0x3);
+	write32(pmmio + DSPCNTR(1), 0x1000000);
+	write32(pmmio + PIPESRC(1), 0x027f01df);
+
+	vga_misc_write(0x67);
+	const u8 cr[] = { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+		    0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
+		    0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
+		    0xff
+	};
+	vga_cr_write(0x11, 0);
+
+	for (i = 0; i <= 0x18; i++)
+		vga_cr_write(i, cr[i]);
+
+	// Disable screen memory to prevent garbage from appearing.
+	vga_sr_write(1, vga_sr_read(1) | 0x20);
+	hactive = 640;
+	vactive = 400;
+
+	mdelay(1);
+	write32(pmmio + DPLL(0),
+		DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
+		| DPLL_VGA_MODE_DIS
+		| DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
+		| 0x400601
+		);
+	mdelay(1);
+	write32(pmmio + DPLL(0),
+		DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
+		| DPLL_VGA_MODE_DIS
+		| DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
+		| 0x400601
+		);
+
+	write32(pmmio + ADPA, ADPA_DAC_ENABLE
+			| ADPA_PIPE_A_SELECT
+			| ADPA_USE_VGA_HVPOLARITY
+			| ADPA_VSYNC_CNTL_ENABLE
+			| ADPA_HSYNC_CNTL_ENABLE
+			| ADPA_DPMS_ON
+			);
+
+	write32(pmmio + HTOTAL(0),
+		((hactive - 1) << 16)
+		| (hactive - 1));
+	write32(pmmio + HBLANK(0),
+		((hactive - 1) << 16)
+		| (hactive - 1));
+	write32(pmmio + HSYNC(0),
+		((hactive - 1) << 16)
+		| (hactive - 1));
+
+	write32(pmmio + VTOTAL(0), ((vactive - 1) << 16)
+		| (vactive - 1));
+	write32(pmmio + VBLANK(0), ((vactive - 1) << 16)
+		| (vactive - 1));
+	write32(pmmio + VSYNC(0),
+		((vactive - 1) << 16)
+		| (vactive - 1));
+
+	write32(pmmio + PF_WIN_POS(0), 0);
+
+	write32(pmmio + PIPESRC(0), (639 << 16) | 399);
+	write32(pmmio + PF_CTL(0),PF_ENABLE | PF_FILTER_MED_3x3);
+	write32(pmmio + PF_WIN_SZ(0), vactive | (hactive << 16));
+	write32(pmmio + PFIT_CONTROL, 0x0);
+
+	mdelay(1);
+
+	write32(pmmio + FDI_RX_CTL(0), 0x00002040);
+	mdelay(1);
+	write32(pmmio + FDI_RX_CTL(0), 0x80002050);
+	write32(pmmio + FDI_TX_CTL(0), 0x00044000);
+	mdelay(1);
+	write32(pmmio + FDI_TX_CTL(0), 0x80044000);
+	write32(pmmio + PIPECONF(0), PIPECONF_ENABLE | PIPECONF_BPP_6 | PIPECONF_DITHER_EN);
+
+	write32(pmmio + VGACNTRL, 0x0);
+	write32(pmmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888);
+	mdelay(1);
+
+	write32(pmmio + ADPA, ADPA_DAC_ENABLE
+			| ADPA_PIPE_A_SELECT
+			| ADPA_USE_VGA_HVPOLARITY
+			| ADPA_VSYNC_CNTL_ENABLE
+			| ADPA_HSYNC_CNTL_ENABLE
+			| ADPA_DPMS_ON
+			);
+
+	write32(pmmio + DSPFW3, 0x7f3f00c1);
+	write32(pmmio + MI_MODE, 0x200 | VS_TIMER_DISPATCH);
+	write32(pmmio + CACHE_MODE_0, (0x6820 | (1 << 9)) & ~(1 << 5));
+	write32(pmmio + CACHE_MODE_1, 0x380 & ~(1 << 9));
+
+	/* Set up GTT.  */
+
+	reg16 = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0, 0)), GGC);
+	uma_size = 0;
+	if (!(reg16 & 2)) {
+		uma_size = decode_igd_memory_size((reg16 >> 4) & 7);
+		printk(BIOS_DEBUG, "%dM UMA\n", uma_size >> 10);
+	}
+
+	for (i = 0; i < (uma_size - 256) / 4; i++)
+	{
+		outl((i << 2) | 1, piobase);
+		outl(pphysbase + (i << 12) + 1, piobase + 4);
+	}
+
+	/* Clear interrupts. */
+	write32(pmmio + DEIIR, 0xffffffff);
+	write32(pmmio + SDEIIR, 0xffffffff);
+	write32(pmmio + IIR, 0xffffffff);
+	write32(pmmio + IMR, 0xffffffff);
+	write32(pmmio + EIR, 0xffffffff);
+
+	vga_textmode_init();
+
+	/* Enable screen memory.  */
+	vga_sr_write(1, vga_sr_read(1) & ~0x20);
+
+	return 0;
+
+}
+
+/* compare the header of the vga edid header */
+/* if vga is not connected it should have a correct header */
+static int vga_connected(u8 *pmmio) {
+	u8 vga_edid[128];
+	u8 header[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
+	intel_gmbus_read_edid(pmmio + GMBUS0, 2, 0x50, vga_edid, 128);
+	intel_gmbus_stop(pmmio + GMBUS0);
+	for (int i = 0; i < 8; i++) {
+		if (vga_edid[i] != header[i]) {
+			printk(BIOS_DEBUG, "VGA not connected. Using LVDS display\n");
+			return 0;
+		}
+	}
+	printk(BIOS_SPEW, "VGA display connected\n");
+	return 1;
+}
+
 #endif

 static void gma_func0_init(struct device *dev)
@@ -423,7 +611,11 @@ static void gma_func0_init(struct device *dev)
 	);

 	int err;
-	err = intel_gma_init(conf, pci_read_config32(dev, 0x5c) & ~0xf,
+	if (vga_connected(mmiobase))
+		err = intel_gma_init_vga(conf, pci_read_config32(dev, 0x5c) & ~0xf,
+					iobase, mmiobase, graphics_base);
+	else
+		err = intel_gma_init_lvds(conf, pci_read_config32(dev, 0x5c) & ~0xf,
 			     iobase, mmiobase, graphics_base);
 	if (err == 0)
 		gfx_set_init_done(1);
--
2.9.3


code:
From d80a39744d7aad734e8d53f2b2d6cb6b5eeee834 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Tue, 6 Sep 2016 23:03:04 +0200
Subject: [PATCH 4/5] mb/intel/d945gclf: Allow use of native graphic init

Adds pci device id to native graphic init and add a Native graphic init
option in Kconfig.

Change-Id: I136122daef70547830bcc87f568406be7162461f
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>

diff --git a/src/mainboard/intel/d945gclf/Kconfig b/src/mainboard/intel/d945gclf/Kconfig
index 429a304..a83e613 100644
--- a/src/mainboard/intel/d945gclf/Kconfig
+++ b/src/mainboard/intel/d945gclf/Kconfig
@@ -29,6 +29,8 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select HAVE_ACPI_RESUME
 	select BOARD_ROMSIZE_KB_512
 	select CHANNEL_XOR_RANDOMIZATION
+	select MAINBOARD_HAS_NATIVE_VGA_INIT
+	select INTEL_EDID

 config MAINBOARD_DIR
 	string
diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c
index 37674d7..abe7dd6 100644
--- a/src/northbridge/intel/i945/gma.c
+++ b/src/northbridge/intel/i945/gma.c
@@ -716,7 +716,7 @@ static struct device_operations gma_func1_ops = {
 	.ops_pci		= &gma_pci_ops,
 };

-static const unsigned short pci_device_ids[] = { 0x27a2, 0x27ae, 0 };
+static const unsigned short pci_device_ids[] = { 0x27a2, 0x27ae, 0x2772, 0 };

 static const struct pci_driver i945_gma_func0_driver __pci_driver = {
 	.ops	= &gma_func0_ops,
--
2.9.3


code:
From 603387a7650a80c92f1064f17fbbf06d60c06f30 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Tue, 6 Sep 2016 23:53:32 +0200
Subject: [PATCH 5/5] i945/gma.c: Only init LVDS if it is present on the device

Some devices have no LVDS output but if no VGA is connected or
no edid can be found, it will try to init LVDS.

This patch makes sure only devices that have an LVDS connector can use LVDS
graphic initialisation.

Change-Id: Ie15631514535bab6c881c1f52e9edbfb8aaa5db7
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>

diff --git a/src/mainboard/apple/macbook21/Kconfig b/src/mainboard/apple/macbook21/Kconfig
index e653c08..8ba3d77 100644
--- a/src/mainboard/apple/macbook21/Kconfig
+++ b/src/mainboard/apple/macbook21/Kconfig
@@ -35,6 +35,10 @@ config DCACHE_RAM_SIZE
 	hex
 	default 0x8000

+config HAS_LVDS
+	bool
+	default y
+
 if BOARD_APPLE_MACBOOK21

 config MAINBOARD_PART_NUMBER
diff --git a/src/mainboard/getac/p470/Kconfig b/src/mainboard/getac/p470/Kconfig
index ea68bed..e74b70c 100644
--- a/src/mainboard/getac/p470/Kconfig
+++ b/src/mainboard/getac/p470/Kconfig
@@ -64,4 +64,8 @@ config VGA_BIOS_FILE
 	string
 	default "getac-pci8086,27a2.rom"

+config HAS_LVDS
+	bool
+	default y
+
 endif # BOARD_GETAC_P470
diff --git a/src/mainboard/lenovo/t60/Kconfig b/src/mainboard/lenovo/t60/Kconfig
index 52eeda3..e5a7554 100644
--- a/src/mainboard/lenovo/t60/Kconfig
+++ b/src/mainboard/lenovo/t60/Kconfig
@@ -54,4 +54,8 @@ config SEABIOS_PS2_TIMEOUT
 	int
 	default 3000

+config HAS_LVDS
+	bool
+	default y
+
 endif
diff --git a/src/mainboard/lenovo/x60/Kconfig b/src/mainboard/lenovo/x60/Kconfig
index ab4b58e..152e6b2 100644
--- a/src/mainboard/lenovo/x60/Kconfig
+++ b/src/mainboard/lenovo/x60/Kconfig
@@ -61,4 +61,8 @@ config SEABIOS_PS2_TIMEOUT
 	int
 	default 3000

+config HAS_LVDS
+	bool
+	default y
+
 endif
diff --git a/src/northbridge/intel/i945/Kconfig b/src/northbridge/intel/i945/Kconfig
index 6e8d35b..ae7961f 100644
--- a/src/northbridge/intel/i945/Kconfig
+++ b/src/northbridge/intel/i945/Kconfig
@@ -71,4 +71,8 @@ config CHECK_SLFRCS_ON_RESUME
 	  On other boards the check always creates a false positive,
 	  effectively making it impossible to resume.

+config HAS_LVDS
+	bool
+	default n
+
 endif
diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c
index abe7dd6..be299f4 100644
--- a/src/northbridge/intel/i945/gma.c
+++ b/src/northbridge/intel/i945/gma.c
@@ -611,7 +611,7 @@ static void gma_func0_init(struct device *dev)
 	);

 	int err;
-	if (vga_connected(mmiobase))
+	if (!CONFIG_HAS_LVDS || vga_connected(mmiobase))
 		err = intel_gma_init_vga(conf, pci_read_config32(dev, 0x5c) & ~0xf,
 					iobase, mmiobase, graphics_base);
 	else
--
2.9.3


code:
From 9659556d9edbba6c3530ed1d0630add30419210f Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Sun, 4 Sep 2016 16:01:11 +0200
Subject: [PATCH 1/2] x4x/gma.c: Add VESA native resolution mode

This patch implements native resolution, VESA mode, on the VGA output of
x4x.

It relies on EDID to modeset, but has a fallback-mode (640 x 480 @
60Hz) if this is no EDID could be found. This fallback mode only works in textmode
since in VESA mode some payloads (grub2) rely on VBE info, which is being
generated from an EDID.

Change-Id: I247ea7171ba3c5dc3b209d00e4dcb2d2069abd75
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
---
 src/northbridge/intel/x4x/gma.c | 282 ++++++++++++++++++++++++++++++++++------
 1 file changed, 242 insertions(+), 40 deletions(-)

diff --git a/src/northbridge/intel/x4x/gma.c b/src/northbridge/intel/x4x/gma.c
index 2679026..118f98d 100644
--- a/src/northbridge/intel/x4x/gma.c
+++ b/src/northbridge/intel/x4x/gma.c
@@ -26,24 +26,68 @@
 #include <cpu/x86/msr.h>
 #include <cpu/x86/mtrr.h>
 #include <kconfig.h>
+#include <commonlib/helpers.h>

 #include "drivers/intel/gma/i915_reg.h"
 #include "chip.h"
 #include "x4x.h"
 #include <drivers/intel/gma/intel_bios.h>
+#include <drivers/intel/gma/edid.h>
 #include <drivers/intel/gma/i915.h>
 #include <pc80/vga.h>
 #include <pc80/vga_io.h>

+#define BASE_FREQUENCY 96000
+
+static u8 edid_is_null(u8 *edid, u32 edid_size)
+{
+	u32 i;
+	for (i = 0; i < edid_size; i++) {
+		if (*(edid + i) != 0)
+			return 0;
+	}
+	return 1;
+}
 static void intel_gma_init(const struct northbridge_intel_x4x_config *info,
-			   u8 *mmio)
+			u8 *mmio, u32 physbase, u16 piobase, u32 lfb)
 {

+
 	int i;
-	u32 hactive, vactive;
+	u8 edid_data[128];
+	struct edid edid;
+	struct edid_mode *mode;
+	u8 edid_not_found;
+
+	/* Initialise mode variables for 640 x 480 @ 60Hz */
+	u32 hactive = 640, vactive = 480;
+	u32 right_border = 0, bottom_border = 0;
+	int hpolarity = 0, vpolarity = 0;
+	u32 hsync = 96, vsync = 2;
+	u32 hblank = 160, vblank = 45;
+	u32 hfront_porch = 16, vfront_porch = 10;
+	u32 target_frequency = 25175;
+
+	u32 err_most = 0xffffffff;
+	u32 pixel_p1 = 1;
+	u32 pixel_n = 1;
+	u32 pixel_m1 = 1;
+	u32 pixel_m2 = 1;
+	u32 link_frequency = info->gfx.link_frequency_270_mhz ? 270000 : 162000;
+	u32 data_m1;
+	u32 data_n1 = 0x00800000;
+	u32 link_m1;
+	u32 link_n1 = 0x00040000;
+

 	vga_gr_write(0x18, 0);

+	/* Set up GTT */
+	for (i = 0; i < 0x1000; i++) {
+		outl((i << 2) | 1, piobase);
+		outl(physbase + (i << 12) + 1, piobase + 4);
+	}
+
 	write32(mmio + VGA0, 0x31108);
 	write32(mmio + VGA1, 0x31406);

@@ -73,107 +117,258 @@ static void intel_gma_init(const struct northbridge_intel_x4x_config *info,
 	for (i = 0; i <= 0x18; i++)
 		vga_cr_write(i, cr[i]);

+	udelay(1);
+
+	intel_gmbus_read_edid(mmio + GMBUS0, 2, 0x50, edid_data, 128);
+	intel_gmbus_stop(mmio + GMBUS0);
+	decode_edid(edid_data,
+		    sizeof(edid_data), &edid);
+	mode = &edid.mode;
+
+
 	/* Disable screen memory to prevent garbage from appearing.  */
 	vga_sr_write(1, vga_sr_read(1) | 0x20);

-	hactive = 640;
-	vactive = 400;
+	edid_not_found = edid_is_null(edid_data, sizeof(edid_data));
+	if (!edid_not_found) {
+		printk(BIOS_DEBUG, "EDID is not null");
+		hactive = edid.x_resolution;
+		vactive = edid.y_resolution;
+		right_border = mode->hborder;
+		bottom_border = mode->vborder;
+		hpolarity = (mode->phsync == '-');
+		vpolarity = (mode->pvsync == '-');
+		vsync = mode->vspw;
+		hsync = mode->hspw;
+		vblank = mode->vbl;
+		hblank = mode->hbl;
+		hfront_porch = mode->hso;
+		vfront_porch = mode->vso;
+		target_frequency = mode->pixel_clock;
+	} else
+		printk(BIOS_DEBUG, "EDID is null, using 640 x 480 @ 60Hz mode");
+
+	if (IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)) {
+		vga_sr_write(1, 1);
+		vga_sr_write(0x2, 0xf);
+		vga_sr_write(0x3, 0x0);
+		vga_sr_write(0x4, 0xe);
+		vga_gr_write(0, 0x0);
+		vga_gr_write(1, 0x0);
+		vga_gr_write(2, 0x0);
+		vga_gr_write(3, 0x0);
+		vga_gr_write(4, 0x0);
+		vga_gr_write(5, 0x0);
+		vga_gr_write(6, 0x5);
+		vga_gr_write(7, 0xf);
+		vga_gr_write(0x10, 0x1);
+		vga_gr_write(0x11, 0);
+
+		edid.bytes_per_line = (edid.bytes_per_line + 63) & ~63;
+
+		write32(mmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE
+			| DISPPLANE_BGRX888);
+		write32(mmio + DSPADDR(0), 0);
+		write32(mmio + DSPSTRIDE(0), edid.bytes_per_line);
+		write32(mmio + DSPSURF(0), 0);
+		for (i = 0; i < 0x100; i++)
+			write32(mmio + LGC_PALETTE(0) + 4 * i, i * 0x010101);
+	} else {
+		vga_textmode_init();
+	}
+
+	u32 candn, candm1, candm2, candp1;
+	for (candn = 1; candn <= 4; candn++) {
+		for (candm1 = 23; candm1 >= 16; candm1--) {
+			for (candm2 = 11; candm2 >= 5; candm2--) {
+				for (candp1 = 8; candp1 >= 1; candp1--) {
+					u32 m = 5 * (candm1 + 2) + (candm2 + 2);
+					u32 p = candp1 * 10; /* 10 == p2 */
+					u32 vco = DIV_ROUND_CLOSEST(
+						BASE_FREQUENCY * m, candn + 2);
+					u32 dot = DIV_ROUND_CLOSEST(vco, p);
+					u32 this_err = ABS(dot - target_frequency);
+					if (this_err < err_most) {
+						err_most = this_err;
+						pixel_n = candn;
+						pixel_m1 = candm1;
+						pixel_m2 = candm2;
+						pixel_p1 = candp1;
+					}
+				}
+			}
+		}
+	}
+
+	if (err_most == 0xffffffff) {
+		printk(BIOS_ERR, "Couldn't find GFX clock divisors\n");
+		return;
+	}
+
+	link_m1 = ((uint64_t)link_n1 * mode->pixel_clock) / link_frequency;
+	data_m1 = ((uint64_t)data_n1 * 18 * mode->pixel_clock)
+		/ (link_frequency * 8 * 4);
+
+	printk(BIOS_INFO, "bringing up panel at resolution %d x %d\n",
+	       hactive, vactive);
+	printk(BIOS_DEBUG, "Borders %d x %d\n",
+	       right_border, bottom_border);
+	printk(BIOS_DEBUG, "Blank %d x %d\n",
+	       hblank, vblank);
+	printk(BIOS_DEBUG, "Sync %d x %d\n",
+	       hsync, vsync);
+	printk(BIOS_DEBUG, "Front porch %d x %d\n",
+	       hfront_porch, vfront_porch);
+	printk(BIOS_DEBUG, (info->gfx.use_spread_spectrum_clock
+			    ? "Spread spectrum clock\n" : "DREF clock\n"));
+	printk(BIOS_DEBUG, "Polarities %d, %d\n",
+	       hpolarity, vpolarity);
+	printk(BIOS_DEBUG, "Data M1=%d, N1=%d\n",
+	       data_m1, data_n1);
+	printk(BIOS_DEBUG, "Link frequency %d kHz\n",
+	       link_frequency);
+	printk(BIOS_DEBUG, "Link M1=%d, N1=%d\n",
+	       link_m1, link_n1);
+	printk(BIOS_DEBUG, "Pixel N=%d, M1=%d, M2=%d, P1=%d\n",
+	       pixel_n, pixel_m1, pixel_m2, pixel_p1);
+	printk(BIOS_DEBUG, "Pixel clock %d kHz\n",
+	       BASE_FREQUENCY * (5 * (pixel_m1 + 2) + (pixel_m2 + 2)) /
+		(pixel_n + 2) / (pixel_p1 * 10));

 	mdelay(1);
-	write32(mmio + FP0(0), 0x31108);
-	write32(mmio + DPLL(0),
-		DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
-		| DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
-		| 0x10601
-		);
+	write32(mmio + FP0(0), (pixel_n << 16)
+		| (pixel_m1 << 8) | pixel_m2);
+	write32(mmio + DPLL(0), DPLL_VCO_ENABLE
+		| DPLL_VGA_MODE_DIS | DPLLB_MODE_DAC_SERIAL
+		| (0x10000 << (pixel_p1 - 1))
+		| (6 << 9));
+
 	mdelay(1);
-	write32(mmio + DPLL(0),
-		DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
-		| DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
-		| 0x10601
-		);
+	write32(mmio + DPLL(0), DPLL_VCO_ENABLE
+		| DPLL_VGA_MODE_DIS | DPLLB_MODE_DAC_SERIAL
+		| (0x10000 << (pixel_p1 - 1))
+		| (6 << 9));

 	write32(mmio + ADPA, ADPA_DAC_ENABLE
 			| ADPA_PIPE_A_SELECT
 			| ADPA_CRT_HOTPLUG_MONITOR_COLOR
 			| ADPA_CRT_HOTPLUG_ENABLE
-			| ADPA_USE_VGA_HVPOLARITY
 			| ADPA_VSYNC_CNTL_ENABLE
 			| ADPA_HSYNC_CNTL_ENABLE
 			| ADPA_DPMS_ON
-			);
+			| (vpolarity ? ADPA_VSYNC_ACTIVE_LOW :
+			   ADPA_VSYNC_ACTIVE_HIGH)
+			| (hpolarity ? ADPA_HSYNC_ACTIVE_LOW :
+			   ADPA_HSYNC_ACTIVE_HIGH));

 	write32(mmio + HTOTAL(0),
-		((hactive - 1) << 16)
+		((hactive + right_border + hblank - 1) << 16)
 		| (hactive - 1));
 	write32(mmio + HBLANK(0),
-		((hactive - 1) << 16)
-		| (hactive - 1));
+		((hactive + right_border + hblank - 1) << 16)
+		| (hactive + right_border - 1));
 	write32(mmio + HSYNC(0),
-		((hactive - 1) << 16)
-		| (hactive - 1));
+		((hactive + right_border + hfront_porch + hsync - 1) << 16)
+		| (hactive + right_border + hfront_porch - 1));

-	write32(mmio + VTOTAL(0), ((vactive - 1) << 16)
-		| (vactive - 1));
-	write32(mmio + VBLANK(0), ((vactive - 1) << 16)
+	write32(mmio + VTOTAL(0), ((vactive + bottom_border + vblank - 1) << 16)
 		| (vactive - 1));
+	write32(mmio + VBLANK(0), ((vactive + bottom_border + vblank - 1) << 16)
+		| (vactive + bottom_border - 1));
 	write32(mmio + VSYNC(0),
-		((vactive - 1) << 16)
-		| (vactive - 1));
+		((vactive + bottom_border + vfront_porch + vsync - 1) << 16)
+		| (vactive + bottom_border + vfront_porch - 1));

 	write32(mmio + PIPECONF(0), PIPECONF_DISABLE);

 	write32(mmio + PF_WIN_POS(0), 0);
-
-	write32(mmio + PIPESRC(0), (639 << 16) | 399);
-	write32(mmio + PF_CTL(0),PF_ENABLE | PF_FILTER_MED_3x3);
-	write32(mmio + PF_WIN_SZ(0), vactive | (hactive << 16));
-	write32(mmio + PFIT_CONTROL, 0xa0000000);
+	if (IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)) {
+		write32(mmio + PIPESRC(0), ((hactive - 1) << 16)
+			| (vactive - 1));
+		write32(mmio + PF_CTL(0), 0);
+		write32(mmio + PF_WIN_SZ(0), 0);
+		write32(mmio + PFIT_CONTROL, 0);
+	} else {
+		write32(mmio + PIPESRC(0), (639 << 16) | 399);
+		write32(mmio + PF_CTL(0), PF_ENABLE | PF_FILTER_MED_3x3);
+		write32(mmio + PF_WIN_SZ(0), vactive | (hactive << 16));
+		write32(mmio + PFIT_CONTROL, 0x80000000);
+	}

 	mdelay(1);

+	write32(mmio + PIPE_DATA_M1(0), 0x7e000000 | data_m1);
+	write32(mmio + PIPE_DATA_N1(0), data_n1);
+	write32(mmio + PIPE_LINK_M1(0), link_m1);
+	write32(mmio + PIPE_LINK_N1(0), link_n1);
+
 	write32(mmio + 0x000f000c, 0x00002040);
 	mdelay(1);
 	write32(mmio + 0x000f000c, 0x00002050);
 	write32(mmio + 0x00060100, 0x00044000);
 	mdelay(1);
+	write32(mmio + PIPECONF(0), PIPECONF_BPP_6);
+	write32(mmio + 0x000f0008, 0x00000040);
+	write32(mmio + 0x000f000c, 0x00022050);
+	write32(mmio + PIPECONF(0), PIPECONF_BPP_6 | PIPECONF_DITHER_EN);
 	write32(mmio + PIPECONF(0), PIPECONF_ENABLE
 			| PIPECONF_BPP_6 | PIPECONF_DITHER_EN);

-	write32(mmio + VGACNTRL, 0x0);
-	write32(mmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888);
-	mdelay(1);
+	if (IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)) {
+		write32(mmio + VGACNTRL, VGA_DISP_DISABLE);
+		write32(mmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE
+			| DISPPLANE_BGRX888);
+		mdelay(1);
+	} else {
+		write32(mmio + VGACNTRL, 0xc4008e);
+	}

 	write32(mmio + ADPA, ADPA_DAC_ENABLE
 			| ADPA_PIPE_A_SELECT
 			| ADPA_CRT_HOTPLUG_MONITOR_COLOR
 			| ADPA_CRT_HOTPLUG_ENABLE
-			| ADPA_USE_VGA_HVPOLARITY
 			| ADPA_VSYNC_CNTL_ENABLE
 			| ADPA_HSYNC_CNTL_ENABLE
 			| ADPA_DPMS_ON
-			);
+			| (vpolarity ? ADPA_VSYNC_ACTIVE_LOW :
+			   ADPA_VSYNC_ACTIVE_HIGH)
+			| (hpolarity ? ADPA_HSYNC_ACTIVE_LOW :
+			   ADPA_HSYNC_ACTIVE_HIGH));

-	vga_textmode_init();
+	write32(mmio + PP_CONTROL, PANEL_POWER_ON | PANEL_POWER_RESET);

-	/* Enable screen memory.  */
+	/* Enable screen memory. */
 	vga_sr_write(1, vga_sr_read(1) & ~0x20);

 	/* Clear interrupts. */
 	write32(mmio + DEIIR, 0xffffffff);
 	write32(mmio + SDEIIR, 0xffffffff);
+
+	if (IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)) {
+		memset((void *) lfb, 0,
+			hactive * vactive * 4);
+		set_vbe_mode_info_valid(&edid, lfb);
+	}
 }

 static void native_init(struct device *dev)
 {
+	struct resource *lfb_res;
+	struct resource *pio_res;
+	u32 physbase;
 	struct resource *gtt_res = find_resource(dev, PCI_BASE_ADDRESS_0);
 	struct northbridge_intel_x4x_config *conf = dev->chip_info;

+	lfb_res = find_resource(dev, PCI_BASE_ADDRESS_2);
+	pio_res = find_resource(dev, PCI_BASE_ADDRESS_4);
+	physbase = pci_read_config32(dev, 0x5c) & ~0xf;
+
 	if (gtt_res && gtt_res->base) {
 		printk(BIOS_SPEW,
 			"Initializing VGA without OPROM. MMIO 0x%llx\n",
 			gtt_res->base);
-		intel_gma_init(conf, res2mmio(gtt_res, 0, 0));
+		intel_gma_init(conf, res2mmio(gtt_res, 0, 0),
+			physbase, pio_res->base, lfb_res->base);
 	}

 	/* Linux relies on VBT for panel info.  */
@@ -182,6 +377,7 @@ static void native_init(struct device *dev)

 static void gma_func0_init(struct device *dev)
 {
+	u16 reg16;
 	u32 reg32;

 	/* IGD needs to be Bus Master */
@@ -189,6 +385,12 @@ static void gma_func0_init(struct device *dev)
 	reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
 	pci_write_config32(dev, PCI_COMMAND, reg32);

+	/* configure GMBUSFREQ */
+	reg16 = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x2,0)), 0xcc);
+	reg16 &= ~0x1ff;
+	reg16 |= 0xbc;
+	pci_write_config16(dev_find_slot(0, PCI_DEVFN(0x2,0)), 0xcc, reg16);
+
 	if (IS_ENABLED(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT))
 		native_init(dev);
 	else
--
2.9.3


code:
From f9a84edfc672424c9dcaa0a71ad0751c2355c3d0 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Mon, 5 Sep 2016 12:07:57 +0200
Subject: [PATCH 2/2] gigabyte/ga-g41m-es2l: add VESA mode to Kconfig

This patch adds MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG to the
gigabyte/ga-g41m-es2l Kconfig to allow selecting between textmode and
vesamode in menuconfig.

Change-Id: I84b61118fa0419d49d2498b66029711cdce97576
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
---
 src/mainboard/gigabyte/ga-g41m-es2l/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/mainboard/gigabyte/ga-g41m-es2l/Kconfig b/src/mainboard/gigabyte/ga-g41m-es2l/Kconfig
index 6452f4d..281d498 100644
--- a/src/mainboard/gigabyte/ga-g41m-es2l/Kconfig
+++ b/src/mainboard/gigabyte/ga-g41m-es2l/Kconfig
@@ -26,6 +26,7 @@ config BOARD_SPECIFIC_OPTIONS
 	select BOARD_ROMSIZE_KB_1024
 	select INTEL_EDID
 	select MAINBOARD_HAS_NATIVE_VGA_INIT
+	select MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG
 	select PCIEXP_ASPM
 	select PCIEXP_CLK_PM
 	select PCIEXP_L1_SUB_STATE
--
2.9.3


code:
From 51dc727c71bbb10519a670b83b67a84f704e003a Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Mon, 22 Aug 2016 17:58:46 +0200
Subject: [PATCH 1/2] gm45/gma.c: use screen on vga connector if connected

The intel x4x and gm45 have very similar integrated graphic devices.
Currently the x4x native graphic init enables VGA, while gm45 can output
on LVDS.

This patch reuses the x4x graphic initialisation code
to enable output on VGA in gm45 in a way that the behavior is similar to vbios:
If no VGA display is connected the internal LVDS screen is used.
If an external screen is detected on the VGA port it will be used instead.

Change-Id: I7e9ff793a5384ad8b4220fb1c0d9b28e6cee8391
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
---
 src/northbridge/intel/gm45/gma.c | 157 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 153 insertions(+), 4 deletions(-)

diff --git a/src/northbridge/intel/gm45/gma.c b/src/northbridge/intel/gm45/gma.c
index d5f6471..74c9bc3 100644
--- a/src/northbridge/intel/gm45/gma.c
+++ b/src/northbridge/intel/gm45/gma.c
@@ -47,7 +47,7 @@ void gtt_write(u32 reg, u32 data)
 	write32(res2mmio(gtt_res, reg, 0), data);
 }

-static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
+static void gma_init_lvds(const struct northbridge_intel_gm45_config *info,
 			   u8 *mmio, u32 physbase, u16 piobase, u32 lfb)
 {

@@ -101,7 +101,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
 		    sizeof(edid_data), &edid);
 	mode = &edid.mode;

-	/* Disable screen memory to prevent garbage from appearing.  */
+	/* Disable screen memory to prevent garbage from appearing. */
 	vga_sr_write(1, vga_sr_read(1) | 0x20);

 	hactive = edid.x_resolution;
@@ -344,6 +344,152 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
 	}
 }

+static void gma_init_vga(const struct northbridge_intel_gm45_config *info,
+			   u8 *mmio)
+{
+
+	int i;
+	u32 hactive, vactive;
+
+	vga_gr_write(0x18, 0);
+
+	write32(mmio + VGA0, 0x31108);
+	write32(mmio + VGA1, 0x31406);
+
+	write32(mmio + ADPA, ADPA_DAC_ENABLE
+			| ADPA_PIPE_A_SELECT
+			| ADPA_CRT_HOTPLUG_MONITOR_COLOR
+			| ADPA_CRT_HOTPLUG_ENABLE
+			| ADPA_USE_VGA_HVPOLARITY
+			| ADPA_VSYNC_CNTL_ENABLE
+			| ADPA_HSYNC_CNTL_ENABLE
+			| ADPA_DPMS_ON
+			);
+
+	write32(mmio + 0x7041c, 0x0);
+	write32(mmio + DPLL_MD(0), 0x3);
+	write32(mmio + DPLL_MD(1), 0x3);
+
+	vga_misc_write(0x67);
+
+	const u8 cr[] = { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
+		    0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
+		    0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
+		    0xff
+	};
+	vga_cr_write(0x11, 0);
+
+	for (i = 0; i <= 0x18; i++)
+		vga_cr_write(i, cr[i]);
+
+	/* Disable screen memory to prevent garbage from appearing.  */
+	vga_sr_write(1, vga_sr_read(1) | 0x20);
+
+	hactive = 640;
+	vactive = 400;
+
+	mdelay(1);
+	write32(mmio + FP0(0), 0x31108);
+	write32(mmio + DPLL(0),
+		DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
+		| DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
+		| 0x10601
+		);
+	mdelay(1);
+	write32(mmio + DPLL(0),
+		DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
+		| DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
+		| 0x10601
+		);
+
+	write32(mmio + ADPA, ADPA_DAC_ENABLE
+			| ADPA_PIPE_A_SELECT
+			| ADPA_CRT_HOTPLUG_MONITOR_COLOR
+			| ADPA_CRT_HOTPLUG_ENABLE
+			| ADPA_USE_VGA_HVPOLARITY
+			| ADPA_VSYNC_CNTL_ENABLE
+			| ADPA_HSYNC_CNTL_ENABLE
+			| ADPA_DPMS_ON
+			);
+
+	write32(mmio + HTOTAL(0),
+		((hactive - 1) << 16)
+		| (hactive - 1));
+	write32(mmio + HBLANK(0),
+		((hactive - 1) << 16)
+		| (hactive - 1));
+	write32(mmio + HSYNC(0),
+		((hactive - 1) << 16)
+		| (hactive - 1));
+
+	write32(mmio + VTOTAL(0), ((vactive - 1) << 16)
+		| (vactive - 1));
+	write32(mmio + VBLANK(0), ((vactive - 1) << 16)
+		| (vactive - 1));
+	write32(mmio + VSYNC(0),
+		((vactive - 1) << 16)
+		| (vactive - 1));
+
+	write32(mmio + PIPECONF(0), PIPECONF_DISABLE);
+
+	write32(mmio + PF_WIN_POS(0), 0);
+
+	write32(mmio + PIPESRC(0), (639 << 16) | 399);
+	write32(mmio + PF_CTL(0), PF_ENABLE | PF_FILTER_MED_3x3);
+	write32(mmio + PF_WIN_SZ(0), vactive | (hactive << 16));
+	write32(mmio + PFIT_CONTROL, 0xa0000000);
+
+	mdelay(1);
+
+	write32(mmio + 0x000f000c, 0x00002040);
+	mdelay(1);
+	write32(mmio + 0x000f000c, 0x00002050);
+	write32(mmio + 0x00060100, 0x00044000);
+	mdelay(1);
+	write32(mmio + PIPECONF(0), PIPECONF_ENABLE
+			| PIPECONF_BPP_6 | PIPECONF_DITHER_EN);
+
+	write32(mmio + VGACNTRL, 0x0);
+	write32(mmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888);
+	mdelay(1);
+
+	write32(mmio + ADPA, ADPA_DAC_ENABLE
+			| ADPA_PIPE_A_SELECT
+			| ADPA_CRT_HOTPLUG_MONITOR_COLOR
+			| ADPA_CRT_HOTPLUG_ENABLE
+			| ADPA_USE_VGA_HVPOLARITY
+			| ADPA_VSYNC_CNTL_ENABLE
+			| ADPA_HSYNC_CNTL_ENABLE
+			| ADPA_DPMS_ON
+			);
+
+	vga_textmode_init();
+
+	/* Enable screen memory.  */
+	vga_sr_write(1, vga_sr_read(1) & ~0x20);
+
+	/* Clear interrupts. */
+	write32(mmio + DEIIR, 0xffffffff);
+	write32(mmio + SDEIIR, 0xffffffff);
+}
+
+/* compare the header of the vga edid header */
+/* if vga is not connected it should not have a correct header */
+static u8 vga_connected(u8 *mmio)
+{
+	u8 vga_edid[128];
+	u8 header[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
+	intel_gmbus_read_edid(mmio + GMBUS0, 2, 0x50, vga_edid, 128);
+	for (int i = 0; i < 8; i++) {
+		if (vga_edid[i] != header[i]) {
+			printk(BIOS_DEBUG, "VGA not connected. Using LVDS display\n");
+			return 0;
+		}
+	}
+	printk(BIOS_SPEW, "VGA display connected\n");
+	return 1;
+}
+
 static void gma_pm_init_post_vbios(struct device *const dev)
 {
 	const struct northbridge_intel_gm45_config *const conf = dev->chip_info;
@@ -419,8 +565,11 @@ static void gma_func0_init(struct device *dev)
 			printk(BIOS_SPEW,
 			       "Initializing VGA without OPROM. MMIO 0x%llx\n",
 			       gtt_res->base);
-			intel_gma_init(conf, res2mmio(gtt_res, 0, 0), physbase,
-				       pio_res->base, lfb_res->base);
+			if (vga_connected(res2mmio(gtt_res, 0, 0)))
+				gma_init_vga(conf, res2mmio(gtt_res, 0, 0));
+			else
+				gma_init_lvds(conf, res2mmio(gtt_res, 0, 0),
+					physbase, pio_res->base, lfb_res->base);
 		}

 		/* Linux relies on VBT for panel info.  */
--
2.9.3


code:
From 44423cb3e0118b04739f89409e71a0ed1622ccd2 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Sat, 27 Aug 2016 01:09:19 +0200
Subject: [PATCH 2/2] nb/gm45/gma.c: enable VESA framebuffer mode on VGA output

This implements "Keep VESA framebuffer" behavior on VGA output of gm45.
This patch reuses Linux code to compute vga divisors.

Change-Id: I2db5dd9bb1a7e309ca763b1559b89f7f5c8e6d3d
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
---
 src/northbridge/intel/gm45/gma.c | 251 ++++++++++++++++++++++++++++++++-------
 1 file changed, 209 insertions(+), 42 deletions(-)

diff --git a/src/northbridge/intel/gm45/gma.c b/src/northbridge/intel/gm45/gma.c
index 74c9bc3..efaa210 100644
--- a/src/northbridge/intel/gm45/gma.c
+++ b/src/northbridge/intel/gm45/gma.c
@@ -25,6 +25,7 @@
 #include <cpu/x86/msr.h>
 #include <cpu/x86/mtrr.h>
 #include <kconfig.h>
+#include <commonlib/helpers.h>

 #include "drivers/intel/gma/i915_reg.h"
 #include "chip.h"
@@ -35,6 +36,8 @@
 #include <pc80/vga.h>
 #include <pc80/vga_io.h>

+#define BASE_FREQUECY 96000
+
 static struct resource *gtt_res = NULL;

 u32 gtt_read(u32 reg)
@@ -345,14 +348,38 @@ static void gma_init_lvds(const struct northbridge_intel_gm45_config *info,
 }

 static void gma_init_vga(const struct northbridge_intel_gm45_config *info,
-			   u8 *mmio)
+			 u8 *mmio, u32 physbase, u16 piobase, u32 lfb)
 {

 	int i;
-	u32 hactive, vactive;
+	u8 edid_data[128];
+	struct edid edid;
+	struct edid_mode *mode;
+	u32 hactive, vactive, right_border, bottom_border;
+	int hpolarity, vpolarity;
+	u32 vsync, hsync, vblank, hblank, hfront_porch, vfront_porch;
+	u32 target_frequency;
+	u32 smallest_err = 0xffffffff;
+	u32 pixel_p1 = 1;
+	u32 pixel_n = 1;
+	u32 pixel_m1 = 1;
+	u32 pixel_m2 = 1;
+	u32 link_frequency = info->gfx.link_frequency_270_mhz ? 270000 : 162000;
+	u32 data_m1;
+	u32 data_n1 = 0x00800000;
+	u32 link_m1;
+	u32 link_n1 = 0x00040000;
+

 	vga_gr_write(0x18, 0);

+	/* Setup GTT.  */
+	for (i = 0; i < 0x2000; i++) {
+		outl((i << 2) | 1, piobase);
+		outl(physbase + (i << 12) + 1, piobase + 4);
+	}
+
+
 	write32(mmio + VGA0, 0x31108);
 	write32(mmio + VGA1, 0x31406);

@@ -363,8 +390,7 @@ static void gma_init_vga(const struct northbridge_intel_gm45_config *info,
 			| ADPA_USE_VGA_HVPOLARITY
 			| ADPA_VSYNC_CNTL_ENABLE
 			| ADPA_HSYNC_CNTL_ENABLE
-			| ADPA_DPMS_ON
-			);
+			| ADPA_DPMS_ON);

 	write32(mmio + 0x7041c, 0x0);
 	write32(mmio + DPLL_MD(0), 0x3);
@@ -382,95 +408,234 @@ static void gma_init_vga(const struct northbridge_intel_gm45_config *info,
 	for (i = 0; i <= 0x18; i++)
 		vga_cr_write(i, cr[i]);

+	udelay(1);
+
+	intel_gmbus_read_edid(mmio + GMBUS0, 2, 0x50, edid_data, 128);
+	intel_gmbus_stop(mmio + GMBUS0);
+	decode_edid(edid_data,
+		    sizeof(edid_data), &edid);
+	mode = &edid.mode;
+
+
 	/* Disable screen memory to prevent garbage from appearing.  */
 	vga_sr_write(1, vga_sr_read(1) | 0x20);

-	hactive = 640;
-	vactive = 400;
+	hactive = edid.x_resolution;
+	vactive = edid.y_resolution;
+	right_border = mode->hborder;
+	bottom_border = mode->vborder;
+	hpolarity = (mode->phsync == '-');
+	vpolarity = (mode->pvsync == '-');
+	vsync = mode->vspw;
+	hsync = mode->hspw;
+	vblank = mode->vbl;
+	hblank = mode->hbl;
+	hfront_porch = mode->hso;
+	vfront_porch = mode->vso;
+	target_frequency = mode->pixel_clock;
+
+	if (IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)) {
+		vga_sr_write(1, 1);
+		vga_sr_write(0x2, 0xf);
+		vga_sr_write(0x3, 0x0);
+		vga_sr_write(0x4, 0xe);
+		vga_gr_write(0, 0x0);
+		vga_gr_write(1, 0x0);
+		vga_gr_write(2, 0x0);
+		vga_gr_write(3, 0x0);
+		vga_gr_write(4, 0x0);
+		vga_gr_write(5, 0x0);
+		vga_gr_write(6, 0x5);
+		vga_gr_write(7, 0xf);
+		vga_gr_write(0x10, 0x1);
+		vga_gr_write(0x11, 0);
+
+		edid.bytes_per_line = (edid.bytes_per_line + 63) & ~63;
+
+		write32(mmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE
+			| DISPPLANE_BGRX888);
+		write32(mmio + DSPADDR(0), 0);
+		write32(mmio + DSPSTRIDE(0), edid.bytes_per_line);
+		write32(mmio + DSPSURF(0), 0);
+		for (i = 0; i < 0x100; i++)
+			write32(mmio + LGC_PALETTE(0) + 4 * i, i * 0x010101);
+	} else {
+		vga_textmode_init();
+	}
+
+	u32 candn, candm1, candm2, candp1;
+	for (candn = 1; candn <= 4; candn++) {
+		for (candm1 = 23; candm1 >= 17; candm1--) {
+			for (candm2 = 11; candm2 >= 5; candm2--) {
+				for (candp1 = 8; candp1 >= 1; candp1--) {
+					u32 m = 5 * (candm1 + 2) + (candm2 + 2);
+					u32 p = candp1 * 10; /* 10 == p2 */
+					u32 vco = DIV_ROUND_CLOSEST(BASE_FREQUECY * m, candn + 2);
+					u32 dot = DIV_ROUND_CLOSEST(vco, p);
+					u32 this_err = ABS(dot - target_frequency);
+					if (this_err < smallest_err) {
+						smallest_err= this_err;
+						pixel_n = candn;
+						pixel_m1 = candm1;
+						pixel_m2 = candm2;
+						pixel_p1 = candp1;
+					}
+				}
+			}
+		}
+	}
+
+	if (smallest_err == 0xffffffff) {
+		printk(BIOS_ERR, "Couldn't find GFX clock divisors\n");
+		return;
+	}
+
+	link_m1 = ((uint64_t)link_n1 * mode->pixel_clock) / link_frequency;
+	data_m1 = ((uint64_t)data_n1 * 18 * mode->pixel_clock)
+		/ (link_frequency * 8 * 4);
+
+	printk(BIOS_INFO, "bringing up panel at resolution %d x %d\n",
+	       hactive, vactive);
+	printk(BIOS_DEBUG, "Borders %d x %d\n",
+	       right_border, bottom_border);
+	printk(BIOS_DEBUG, "Blank %d x %d\n",
+	       hblank, vblank);
+	printk(BIOS_DEBUG, "Sync %d x %d\n",
+	       hsync, vsync);
+	printk(BIOS_DEBUG, "Front porch %d x %d\n",
+	       hfront_porch, vfront_porch);
+	printk(BIOS_DEBUG, (info->gfx.use_spread_spectrum_clock
+			    ? "Spread spectrum clock\n" : "DREF clock\n"));
+	printk(BIOS_DEBUG, "Polarities %d, %d\n",
+	       hpolarity, vpolarity);
+	printk(BIOS_DEBUG, "Data M1=%d, N1=%d\n",
+	       data_m1, data_n1);
+	printk(BIOS_DEBUG, "Link frequency %d kHz\n",
+	       link_frequency);
+	printk(BIOS_DEBUG, "Link M1=%d, N1=%d\n",
+	       link_m1, link_n1);
+	printk(BIOS_DEBUG, "Pixel N=%d, M1=%d, M2=%d, P1=%d\n",
+	       pixel_n, pixel_m1, pixel_m2, pixel_p1);
+	printk(BIOS_DEBUG, "Pixel clock %d kHz\n",
+		BASE_FREQUECY * (5 * (pixel_m1 + 2) + (pixel_m2 + 2) / (pixel_n + 2)
+		/ (pixel_p1 * 10)));

 	mdelay(1);
-	write32(mmio + FP0(0), 0x31108);
-	write32(mmio + DPLL(0),
-		DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
-		| DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
-		| 0x10601
-		);
+	write32(mmio + FP0(0), (pixel_n << 16)
+		| (pixel_m1 << 8) | pixel_m2);
+	write32(mmio + DPLL(0), DPLL_VCO_ENABLE
+		| DPLL_VGA_MODE_DIS | DPLLB_MODE_DAC_SERIAL
+		| (0x10000 << (pixel_p1 - 1))
+		| (6 << 9));
+
 	mdelay(1);
-	write32(mmio + DPLL(0),
-		DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL
-		| DPLL_DAC_SERIAL_P2_CLOCK_DIV_10
-		| 0x10601
-		);
+	write32(mmio + DPLL(0), DPLL_VCO_ENABLE
+		| DPLL_VGA_MODE_DIS | DPLLB_MODE_DAC_SERIAL
+		| (0x10000 << (pixel_p1 - 1))
+		| (6 << 9));

 	write32(mmio + ADPA, ADPA_DAC_ENABLE
 			| ADPA_PIPE_A_SELECT
 			| ADPA_CRT_HOTPLUG_MONITOR_COLOR
 			| ADPA_CRT_HOTPLUG_ENABLE
-			| ADPA_USE_VGA_HVPOLARITY
 			| ADPA_VSYNC_CNTL_ENABLE
 			| ADPA_HSYNC_CNTL_ENABLE
 			| ADPA_DPMS_ON
-			);
+			| (vpolarity ? ADPA_VSYNC_ACTIVE_LOW :
+			   ADPA_VSYNC_ACTIVE_HIGH)
+			| (hpolarity ? ADPA_HSYNC_ACTIVE_LOW :
+			   ADPA_HSYNC_ACTIVE_HIGH));

 	write32(mmio + HTOTAL(0),
-		((hactive - 1) << 16)
+		((hactive + right_border + hblank - 1) << 16)
 		| (hactive - 1));
 	write32(mmio + HBLANK(0),
-		((hactive - 1) << 16)
-		| (hactive - 1));
+		((hactive + right_border + hblank - 1) << 16)
+		| (hactive + right_border - 1));
 	write32(mmio + HSYNC(0),
-		((hactive - 1) << 16)
-		| (hactive - 1));
+		((hactive + right_border + hfront_porch + hsync - 1) << 16)
+		| (hactive + right_border + hfront_porch - 1));

-	write32(mmio + VTOTAL(0), ((vactive - 1) << 16)
-		| (vactive - 1));
-	write32(mmio + VBLANK(0), ((vactive - 1) << 16)
+	write32(mmio + VTOTAL(0), ((vactive + bottom_border + vblank - 1) << 16)
 		| (vactive - 1));
+	write32(mmio + VBLANK(0), ((vactive + bottom_border + vblank - 1) << 16)
+		| (vactive + bottom_border - 1));
 	write32(mmio + VSYNC(0),
-		((vactive - 1) << 16)
-		| (vactive - 1));
+		((vactive + bottom_border + vfront_porch + vsync - 1) << 16)
+		| (vactive + bottom_border + vfront_porch - 1));

 	write32(mmio + PIPECONF(0), PIPECONF_DISABLE);

 	write32(mmio + PF_WIN_POS(0), 0);
-
-	write32(mmio + PIPESRC(0), (639 << 16) | 399);
-	write32(mmio + PF_CTL(0), PF_ENABLE | PF_FILTER_MED_3x3);
-	write32(mmio + PF_WIN_SZ(0), vactive | (hactive << 16));
-	write32(mmio + PFIT_CONTROL, 0xa0000000);
+	if (IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)) {
+		write32(mmio + PIPESRC(0), ((hactive - 1) << 16)
+			| (vactive - 1));
+		write32(mmio + PF_CTL(0), 0);
+		write32(mmio + PF_WIN_SZ(0), 0);
+		write32(mmio + PFIT_CONTROL, 0);
+	} else {
+		write32(mmio + PIPESRC(0), (639 << 16) | 399);
+		write32(mmio + PF_CTL(0), PF_ENABLE | PF_FILTER_MED_3x3);
+		write32(mmio + PF_WIN_SZ(0), vactive | (hactive << 16));
+		write32(mmio + PFIT_CONTROL, 0x80000000);
+	}

 	mdelay(1);

+	write32(mmio + PIPE_DATA_M1(0), 0x7e000000 | data_m1);
+	write32(mmio + PIPE_DATA_N1(0), data_n1);
+	write32(mmio + PIPE_LINK_M1(0), link_m1);
+	write32(mmio + PIPE_LINK_N1(0), link_n1);
+
 	write32(mmio + 0x000f000c, 0x00002040);
 	mdelay(1);
 	write32(mmio + 0x000f000c, 0x00002050);
 	write32(mmio + 0x00060100, 0x00044000);
 	mdelay(1);
+	write32(mmio + PIPECONF(0), PIPECONF_BPP_6);
+	write32(mmio + 0x000f0008, 0x00000040);
+	write32(mmio + 0x000f000c, 0x00022050);
+	write32(mmio + PIPECONF(0), PIPECONF_BPP_6 | PIPECONF_DITHER_EN);
 	write32(mmio + PIPECONF(0), PIPECONF_ENABLE
 			| PIPECONF_BPP_6 | PIPECONF_DITHER_EN);

-	write32(mmio + VGACNTRL, 0x0);
-	write32(mmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888);
-	mdelay(1);
+	if (IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)) {
+		write32(mmio + VGACNTRL, VGA_DISP_DISABLE);
+		write32(mmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE
+			| DISPPLANE_BGRX888);
+		mdelay(1);
+	} else {
+		write32(mmio + VGACNTRL, 0xc4008e);
+	}

 	write32(mmio + ADPA, ADPA_DAC_ENABLE
 			| ADPA_PIPE_A_SELECT
 			| ADPA_CRT_HOTPLUG_MONITOR_COLOR
 			| ADPA_CRT_HOTPLUG_ENABLE
-			| ADPA_USE_VGA_HVPOLARITY
 			| ADPA_VSYNC_CNTL_ENABLE
 			| ADPA_HSYNC_CNTL_ENABLE
 			| ADPA_DPMS_ON
-			);
+			| (vpolarity ? ADPA_VSYNC_ACTIVE_LOW :
+			   ADPA_VSYNC_ACTIVE_HIGH)
+			| (hpolarity ? ADPA_HSYNC_ACTIVE_LOW :
+			   ADPA_HSYNC_ACTIVE_HIGH));

-	vga_textmode_init();
+	write32(mmio + PP_CONTROL, PANEL_POWER_ON | PANEL_POWER_RESET);

-	/* Enable screen memory.  */
+	/* Enable screen memory. */
 	vga_sr_write(1, vga_sr_read(1) & ~0x20);

 	/* Clear interrupts. */
 	write32(mmio + DEIIR, 0xffffffff);
 	write32(mmio + SDEIIR, 0xffffffff);
+
+	if (IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)) {
+		memset((void *) lfb, 0,
+			edid.x_resolution * edid.y_resolution * 4);
+		set_vbe_mode_info_valid(&edid, lfb);
+	}
+
+
 }

 /* compare the header of the vga edid header */
@@ -480,6 +645,7 @@ static u8 vga_connected(u8 *mmio)
 	u8 vga_edid[128];
 	u8 header[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
 	intel_gmbus_read_edid(mmio + GMBUS0, 2, 0x50, vga_edid, 128);
+	intel_gmbus_stop(mmio + GMBUS0);
 	for (int i = 0; i < 8; i++) {
 		if (vga_edid[i] != header[i]) {
 			printk(BIOS_DEBUG, "VGA not connected. Using LVDS display\n");
@@ -566,7 +732,8 @@ static void gma_func0_init(struct device *dev)
 			       "Initializing VGA without OPROM. MMIO 0x%llx\n",
 			       gtt_res->base);
 			if (vga_connected(res2mmio(gtt_res, 0, 0)))
-				gma_init_vga(conf, res2mmio(gtt_res, 0, 0));
+				gma_init_vga(conf, res2mmio(gtt_res, 0, 0),
+					physbase, pio_res->base, lfb_res->base);
 			else
 				gma_init_lvds(conf, res2mmio(gtt_res, 0, 0),
 					physbase, pio_res->base, lfb_res->base);
--
2.9.3


code:
From d7fe366539f2a492b4a64030618506690bfbb232 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Thu, 8 Sep 2016 22:21:54 +0200
Subject: [PATCH] gm45/gma.c: use correct id string for fake VBT

The correct id string for gm45 is "$VBT CANTIGA        ".
This can be found in the gm45 option rom:
"strings vbios.bin | grep VBT".

Change-Id: Icd67a87dac774b4b3c211511c784c4fb4e2ea97c
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
---
 src/northbridge/intel/gm45/gma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/northbridge/intel/gm45/gma.c b/src/northbridge/intel/gm45/gma.c
index d5f6471..19bd944 100644
--- a/src/northbridge/intel/gm45/gma.c
+++ b/src/northbridge/intel/gm45/gma.c
@@ -425,7 +425,7 @@ static void gma_func0_init(struct device *dev)

 		/* Linux relies on VBT for panel info.  */
 		generate_fake_intel_oprom(&conf->gfx, dev,
-					  "$VBT IRONLAKE-MOBILE");
+					  "$VBT CANTIGA        ");
 	}
 }

--
2.9.3


code:
# NOTE: remove this when updating coreboot. This has been merged upstream
printf "ThinkPad R400 support (clone of the T400)\n"
git am "../resources/libreboot/patch/misc/0007-lenovo-r400-Add-clone-of-Lenovo-T400.patch"
# git fetch http://review.coreboot.org/coreboot refs/changes/93/8393/5 && git cherry-pick FETCH_HEAD


code:
# NOTE: merged upstream already
printf "mainboard/lenovo/t400: Add initial hybrid graphics support\n"
git am "../resources/libreboot/patch/misc/0001-mainboard-lenovo-t400-Add-initial-hybrid-graphics-su.patch"
# git fetch http://review.coreboot.org/coreboot refs/changes/19/9319/18 && git cherry-pick FETCH_HEAD

printf "NOTFORMERGE: lenovo/t400: hard-code enable integrated-only video\n"
git am "../resources/libreboot/patch/misc/0002-NOTFORMERGE-lenovo-t400-hard-code-enable-integrated-.patch"
# git fetch http://review.coreboot.org/coreboot refs/changes/50/10550/1 && git cherry-pick FETCH_HEAD


code:
From fbbc8d6a278c733eca475c17cbf95a8946e2c173 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Thu, 4 Aug 2016 11:00:13 +0200
Subject: [PATCH 1/3] Revert "drivers/lenovo: Add hybrid graphics driver"

This reverts commit 5919ba42ed0ce5b1b13717514698444232c6036c.

Change-Id: I027581ef769ca8232e72f89738c1bdec13f62687

diff --git a/src/drivers/lenovo/Kconfig b/src/drivers/lenovo/Kconfig
index f8eddf2..f20f3b2 100644
--- a/src/drivers/lenovo/Kconfig
+++ b/src/drivers/lenovo/Kconfig
@@ -27,16 +27,3 @@ config DIGITIZER_ABSENT
 endchoice

 endif
-
-config DRIVERS_LENOVO_HYBRID_GRAPHICS
-	bool
-	default n
-
-config HYBRID_GRAPHICS_GPIO_NUM
-	depends on DRIVERS_LENOVO_HYBRID_GRAPHICS
-	int
-	default 52
-	help
-	  Set a default GPIO that sets the panel LVDS signal routing to
-	  integrated or discrete GPU.
-
diff --git a/src/drivers/lenovo/Makefile.inc b/src/drivers/lenovo/Makefile.inc
index 66f8594..c50db5b 100644
--- a/src/drivers/lenovo/Makefile.inc
+++ b/src/drivers/lenovo/Makefile.inc
@@ -1,2 +1 @@
 ramstage-$(CONFIG_DRIVERS_LENOVO_WACOM) += wacom.c
-ramstage-$(CONFIG_DRIVERS_LENOVO_HYBRID_GRAPHICS) += hybrid_graphics.c
diff --git a/src/drivers/lenovo/hybrid_graphics.c b/src/drivers/lenovo/hybrid_graphics.c
deleted file mode 100644
index 9b46646..0000000
--- a/src/drivers/lenovo/hybrid_graphics.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2015-2016 Patrick Rudolph
- * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <types.h>
-#include <string.h>
-#include <option.h>
-#include <device/device.h>
-#include <device/pci_def.h>
-#include <device/pci_ops.h>
-#include <device/pci_ids.h>
-#include <device/pci.h>
-#include <console/console.h>
-#include <southbridge/intel/common/gpio.h>
-
-/* Hybrid graphics allows to connect LVDS interface to either iGPU
- * or dGPU depending on GPIO level.
- * Nvidia is calling this functionality "muxed Optimus".
- * Some devices, like T430s, only support "muxless Optimus" where the
- * Intel GPU is always connected to the panel.
- * As it is only linked on lenovo and only executed if the GPU exists
- * we know for sure that the dGPU is there and connected to first PEG slot.
- *
- * Note: Once native gfx init is done for AMD or Nvida graphic
- *       cards, merge this code.
- */
-
-#define HYBRID_GRAPHICS_INTEGRATED 0
-#define HYBRID_GRAPHICS_DISCRETE 1
-
-static void hybrid_graphics_disable_peg(struct device *dev)
-{
-	struct device *peg_dev;
-
-	/* connect LVDS interface to iGPU */
-	set_gpio(CONFIG_HYBRID_GRAPHICS_GPIO_NUM, GPIO_LEVEL_HIGH);
-	printk(BIOS_DEBUG, "Hybrid graphics: Switching panel to integrated GPU.\n");
-	dev->enabled = 0;
-
-	/* Disable PEG10 */
-	peg_dev = dev_find_slot(0, PCI_DEVFN(1, 0));
-	if (peg_dev)
-		peg_dev->enabled = 0;
-
-	printk(BIOS_DEBUG, "Hybrid graphics: Disabled PEG10.\n");
-}
-
-/* Called before VGA enable bits are set and only if dGPU
- * is present. Enable/disable VGA devices here. */
-static void hybrid_graphics_enable_peg(struct device *dev)
-{
-	u8 hybrid_graphics_mode;
-
-	hybrid_graphics_mode = HYBRID_GRAPHICS_INTEGRATED;
-	get_option(&hybrid_graphics_mode, "hybrid_graphics_mode");
-
-	if (hybrid_graphics_mode == HYBRID_GRAPHICS_DISCRETE) {
-		/* connect LVDS interface to dGPU */
-		set_gpio(CONFIG_HYBRID_GRAPHICS_GPIO_NUM, GPIO_LEVEL_LOW);
-		printk(BIOS_DEBUG, "Hybrid graphics: Switching panel to discrete GPU.\n");
-		dev->enabled = 1;
-
-		/* Disable IGD */
-		dev = dev_find_slot(0, PCI_DEVFN(2, 0));
-		if (dev && dev->ops->disable)
-			dev->ops->disable(dev);
-		dev->enabled = 0;
-
-		printk(BIOS_DEBUG, "Hybrid graphics: Disabled IGD.\n");
-	} else
-		hybrid_graphics_disable_peg(dev);
-}
-
-static struct pci_operations pci_dev_ops_pci = {
-	.set_subsystem = pci_dev_set_subsystem,
-};
-
-struct device_operations hybrid_graphics_ops = {
-	.read_resources   = pci_dev_read_resources,
-	.set_resources    = pci_dev_set_resources,
-	.enable_resources = pci_dev_enable_resources,
-	.init             = pci_dev_init,
-	.scan_bus         = 0,
-	.enable           = hybrid_graphics_enable_peg,
-	.disable          = hybrid_graphics_disable_peg,
-	.ops_pci          = &pci_dev_ops_pci,
-};
-
-static const unsigned short pci_device_ids_nvidia[] = {
-		0x0ffc, /* Nvidia NVS Quadro K1000m Lenovo W530 */
-		0x0def, /* NVidia NVS 5400m Lenovo T430/T530 */
-		0x0dfc, /* NVidia NVS 5200m Lenovo T430s */
-		0x1056, /* NVidia NVS 4200m Lenovo T420/T520 */
-		0x1057, /* NVidia NVS 4200m Lenovo T420/T520 */
-		0x0a6c, /* NVidia NVS 3100m Lenovo T410/T510 */
-		0 };
-
-static const struct pci_driver hybrid_peg_nvidia __pci_driver = {
-	.ops	 = &hybrid_graphics_ops,
-	.vendor	 = PCI_VENDOR_ID_NVIDIA,
-	.devices = pci_device_ids_nvidia,
-};
-
-static const unsigned short pci_device_ids_amd[] = {
-		0x9591, /* ATI Mobility Radeon HD 3650 Lenovo T500/W500 */
-		0x95c4, /* ATI Mobility Radeon HD 3470 Lenovo T400/R400 */
-		0 };
-
-static const struct pci_driver hybrid_peg_amd __pci_driver = {
-	.ops	 = &hybrid_graphics_ops,
-	.vendor	 = PCI_VENDOR_ID_ATI,
-	.devices = pci_device_ids_amd,
-};
diff --git a/src/mainboard/lenovo/t400/Kconfig b/src/mainboard/lenovo/t400/Kconfig
index a444bf8..d74a813 100644
--- a/src/mainboard/lenovo/t400/Kconfig
+++ b/src/mainboard/lenovo/t400/Kconfig
@@ -22,7 +22,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG
 	select INTEL_INT15
 	select SUPERIO_NSC_PC87382
-	select DRIVERS_LENOVO_HYBRID_GRAPHICS

 config MAINBOARD_DIR
 	string
diff --git a/src/mainboard/lenovo/t400/cmos.default b/src/mainboard/lenovo/t400/cmos.default
index 5cf3e63..ac9f96d 100644
--- a/src/mainboard/lenovo/t400/cmos.default
+++ b/src/mainboard/lenovo/t400/cmos.default
@@ -13,5 +13,3 @@ sticky_fn=Disable
 power_management_beeps=Enable
 low_battery_beep=Enable
 sata_mode=AHCI
-hybrid_graphics_mode=Integrated Only
-gfx_uma_size=32M
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t400/cmos.layout b/src/mainboard/lenovo/t400/cmos.layout
index b4b7766..e1a088d 100644
--- a/src/mainboard/lenovo/t400/cmos.layout
+++ b/src/mainboard/lenovo/t400/cmos.layout
@@ -77,8 +77,7 @@ entries
 940         1       e       1        uwb

 # coreboot config options: northbridge
-944         2       e       12       hybrid_graphics_mode
-946         4       e       11       gfx_uma_size
+941         4       e       11       gfx_uma_size

 # coreboot config options: EC
 952         8       h       0        volume
diff --git a/src/mainboard/lenovo/t420/cmos.default b/src/mainboard/lenovo/t420/cmos.default
index 3a82c97..1b8e212 100644
--- a/src/mainboard/lenovo/t420/cmos.default
+++ b/src/mainboard/lenovo/t420/cmos.default
@@ -14,4 +14,3 @@ fn_ctrl_swap=Disable
 sticky_fn=Disable
 trackpoint=Enable
 hyper_threading=Enable
-hybrid_graphics_mode=Integrated Only
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t420/cmos.layout b/src/mainboard/lenovo/t420/cmos.layout
index 58a4abe..bf0f195 100644
--- a/src/mainboard/lenovo/t420/cmos.layout
+++ b/src/mainboard/lenovo/t420/cmos.layout
@@ -77,8 +77,7 @@ entries

 # coreboot config options: northbridge
 432          3       e       11       gfx_uma_size
-435          2        e       12       hybrid_graphics_mode
-#437         3        r       0        unused
+#435          5       r       0        unused

 440          8       h       0        volume

@@ -136,8 +135,6 @@ enumerations
 11    4     160M
 11    5     192M
 11    6     224M
-12    0     Integrated Only
-12    1     Discrete Only

 # -----------------------------------------------------------------
 checksums
diff --git a/src/mainboard/lenovo/t420s/Kconfig b/src/mainboard/lenovo/t420s/Kconfig
index feacb51..935e659 100644
--- a/src/mainboard/lenovo/t420s/Kconfig
+++ b/src/mainboard/lenovo/t420s/Kconfig
@@ -18,7 +18,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select INTEL_INT15
 	select SANDYBRIDGE_IVYBRIDGE_LVDS
 	select MAINBOARD_HAS_LPC_TPM
-	select DRIVERS_LENOVO_HYBRID_GRAPHICS

 	# Workaround for EC/KBC IRQ1.
 	select SERIRQ_CONTINUOUS_MODE
diff --git a/src/mainboard/lenovo/t420s/cmos.default b/src/mainboard/lenovo/t420s/cmos.default
index 3a82c97..1b8e212 100644
--- a/src/mainboard/lenovo/t420s/cmos.default
+++ b/src/mainboard/lenovo/t420s/cmos.default
@@ -14,4 +14,3 @@ fn_ctrl_swap=Disable
 sticky_fn=Disable
 trackpoint=Enable
 hyper_threading=Enable
-hybrid_graphics_mode=Integrated Only
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t420s/cmos.layout b/src/mainboard/lenovo/t420s/cmos.layout
index 3521849..43628406 100644
--- a/src/mainboard/lenovo/t420s/cmos.layout
+++ b/src/mainboard/lenovo/t420s/cmos.layout
@@ -77,8 +77,7 @@ entries

 # coreboot config options: northbridge
 432          3       e       11       gfx_uma_size
-435          2       e       12       hybrid_graphics_mode
-#437         3       r       0        unused
+#435         5       r       0        unused

 440          8       h       0        volume

@@ -136,8 +135,6 @@ enumerations
 11    4     160M
 11    5     192M
 11    6     224M
-12    0     Integrated Only
-12    1     Discrete Only

 # -----------------------------------------------------------------
 checksums
diff --git a/src/mainboard/lenovo/t520/Kconfig b/src/mainboard/lenovo/t520/Kconfig
index ee5dd81..c70581a 100644
--- a/src/mainboard/lenovo/t520/Kconfig
+++ b/src/mainboard/lenovo/t520/Kconfig
@@ -18,7 +18,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select INTEL_INT15
 	select SANDYBRIDGE_IVYBRIDGE_LVDS
 	select MAINBOARD_HAS_LPC_TPM
-	select DRIVERS_LENOVO_HYBRID_GRAPHICS

 	# Workaround for EC/KBC IRQ1.
 	select SERIRQ_CONTINUOUS_MODE
diff --git a/src/mainboard/lenovo/t520/cmos.default b/src/mainboard/lenovo/t520/cmos.default
index ad7dcf5..00e8863 100644
--- a/src/mainboard/lenovo/t520/cmos.default
+++ b/src/mainboard/lenovo/t520/cmos.default
@@ -15,4 +15,3 @@ sticky_fn=Disable
 trackpoint=Enable
 hyper_threading=Enable
 backlight=Both
-hybrid_graphics_mode=Integrated Only
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t520/cmos.layout b/src/mainboard/lenovo/t520/cmos.layout
index 044c310..2cf3629 100644
--- a/src/mainboard/lenovo/t520/cmos.layout
+++ b/src/mainboard/lenovo/t520/cmos.layout
@@ -77,8 +77,7 @@ entries

 # coreboot config options: northbridge
 432         3        e      11        gfx_uma_size
-435         2        e       12       hybrid_graphics_mode
-#437        3        r       0        unused
+#435        5        r       0        unused
 440         8        h       0        volume

 # SandyBridge MRC Scrambler Seed values
@@ -135,8 +134,6 @@ enumerations
 11    4	    160M
 11    5	    192M
 11    6	    224M
-12    0     Integrated Only
-12    1     Discrete Only
 # -----------------------------------------------------------------
 checksums

diff --git a/src/mainboard/lenovo/t530/Kconfig b/src/mainboard/lenovo/t530/Kconfig
index 76147fc..030c01f 100644
--- a/src/mainboard/lenovo/t530/Kconfig
+++ b/src/mainboard/lenovo/t530/Kconfig
@@ -21,7 +21,6 @@ config BOARD_SPECIFIC_OPTIONS # dummy
 	select SANDYBRIDGE_IVYBRIDGE_LVDS
 	select ENABLE_VMX
 	select MAINBOARD_HAS_LPC_TPM
-	select DRIVERS_LENOVO_HYBRID_GRAPHICS

 	# Workaround for EC/KBC IRQ1.
 	select SERIRQ_CONTINUOUS_MODE
diff --git a/src/mainboard/lenovo/t530/cmos.default b/src/mainboard/lenovo/t530/cmos.default
index ad7dcf5..00e8863 100644
--- a/src/mainboard/lenovo/t530/cmos.default
+++ b/src/mainboard/lenovo/t530/cmos.default
@@ -15,4 +15,3 @@ sticky_fn=Disable
 trackpoint=Enable
 hyper_threading=Enable
 backlight=Both
-hybrid_graphics_mode=Integrated Only
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t530/cmos.layout b/src/mainboard/lenovo/t530/cmos.layout
index 0e28bdd..e21c197 100644
--- a/src/mainboard/lenovo/t530/cmos.layout
+++ b/src/mainboard/lenovo/t530/cmos.layout
@@ -77,8 +77,7 @@ entries

 # coreboot config options: northbridge
 432         3        e      11        gfx_uma_size
-435         2        e       12       hybrid_graphics_mode
-#437        3        r       0        unused
+#435        5        r       0        unused

 440          8       h       0        volume

@@ -136,9 +135,6 @@ enumerations
 11    4	    160M
 11    5	    192M
 11    6	    224M
-12    0     Integrated Only
-12    1     Discrete Only
-
 # -----------------------------------------------------------------
 checksums

diff --git a/src/southbridge/intel/i82801ix/Kconfig b/src/southbridge/intel/i82801ix/Kconfig
index b3e5069..2822774 100644
--- a/src/southbridge/intel/i82801ix/Kconfig
+++ b/src/southbridge/intel/i82801ix/Kconfig
@@ -23,7 +23,6 @@ config SOUTHBRIDGE_INTEL_I82801IX
 	select USE_WATCHDOG_ON_BOOT
 	select HAVE_SMI_HANDLER
 	select HAVE_USBDEBUG_OPTIONS
-	select SOUTHBRIDGE_INTEL_COMMON_GPIO

 if SOUTHBRIDGE_INTEL_I82801IX

--
2.9.2

From 90f5f34629ff88506bb803988da1552f3373d4f0 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Thu, 4 Aug 2016 11:01:53 +0200
Subject: [PATCH 2/3] Revert "Revert "mainboard/lenovo/t400: Add initial hybrid
 graphics support""

This reverts commit 14d1a93e444b91311eeed2a25953bf6c0779cdcb.

Change-Id: I965ea55bddb7cf919e7b02ecf8e160c9ad3ea3d4

diff --git a/src/mainboard/lenovo/t400/cmos.default b/src/mainboard/lenovo/t400/cmos.default
index ac9f96d..98ce970 100644
--- a/src/mainboard/lenovo/t400/cmos.default
+++ b/src/mainboard/lenovo/t400/cmos.default
@@ -13,3 +13,4 @@ sticky_fn=Disable
 power_management_beeps=Enable
 low_battery_beep=Enable
 sata_mode=AHCI
+hybrid_graphics_mode=Integrated Only
\ No newline at end of file
diff --git a/src/mainboard/lenovo/t400/cmos.layout b/src/mainboard/lenovo/t400/cmos.layout
index e1a088d..b4b7766 100644
--- a/src/mainboard/lenovo/t400/cmos.layout
+++ b/src/mainboard/lenovo/t400/cmos.layout
@@ -77,7 +77,8 @@ entries
 940         1       e       1        uwb

 # coreboot config options: northbridge
-941         4       e       11       gfx_uma_size
+944         2       e       12       hybrid_graphics_mode
+946         4       e       11       gfx_uma_size

 # coreboot config options: EC
 952         8       h       0        volume
diff --git a/src/mainboard/lenovo/t400/romstage.c b/src/mainboard/lenovo/t400/romstage.c
index f518775..fcc545b 100644
--- a/src/mainboard/lenovo/t400/romstage.c
+++ b/src/mainboard/lenovo/t400/romstage.c
@@ -1,6 +1,7 @@
 /*
  * This file is part of the coreboot project.
  *
+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
  * Copyright (C) 2012 secunet Security Networks AG
  *
  * This program is free software; you can redistribute it and/or
@@ -34,6 +35,118 @@
 #define LPC_DEV PCI_DEV(0, 0x1f, 0)
 #define MCH_DEV PCI_DEV(0, 0, 0)

+#define HYBRID_GRAPHICS_INTEGRATED_ONLY 0
+#define HYBRID_GRAPHICS_DISCRETE_ONLY 1
+#define HYBRID_GRAPHICS_SWITCHABLE 2
+
+#define HYBRID_GRAPHICS_GP_LVL_BITS 0x004a0000
+#define HYBRID_GRAPHICS_GP_LVL2_BITS 0x00020000
+
+#define HYBRID_GRAPHICS_DETECT_GP_BITS 0x00000010
+
+#define HYBRID_GRAPHICS_INT_CLAIM_VGA 0x2
+#define HYBRID_GRAPHICS_SEC_VGA_EN 0x2
+
+static void hybrid_graphics_configure_switchable_graphics(bool enable)
+{
+	uint32_t tmp;
+
+	if (enable) {
+		/* Disable integrated graphics legacy VGA cycles */
+		tmp = pci_read_config16(MCH_DEV, D0F0_GGC);
+		pci_write_config16(MCH_DEV, D0F0_GGC, tmp | HYBRID_GRAPHICS_INT_CLAIM_VGA);
+
+		/* Enable secondary VGA controller */
+		tmp = pci_read_config16(MCH_DEV, D0F0_DEVEN);
+		pci_write_config16(MCH_DEV, D0F0_DEVEN, tmp | HYBRID_GRAPHICS_SEC_VGA_EN);
+	}
+	else {
+		/* Enable integrated graphics legacy VGA cycles */
+		tmp = pci_read_config16(MCH_DEV, D0F0_GGC);
+		pci_write_config16(MCH_DEV, D0F0_GGC, tmp & ~HYBRID_GRAPHICS_INT_CLAIM_VGA);
+
+		/* Disable secondary VGA controller */
+		tmp = pci_read_config16(MCH_DEV, D0F0_DEVEN);
+		pci_write_config16(MCH_DEV, D0F0_DEVEN, tmp & ~HYBRID_GRAPHICS_SEC_VGA_EN);
+	}
+}
+
+static void hybrid_graphics_set_up_gpio(void)
+{
+	uint32_t tmp;
+
+	/* Enable hybrid graphics GPIO lines */
+	tmp = inl(DEFAULT_GPIOBASE + GP_IO_USE_SEL);
+	tmp = tmp | HYBRID_GRAPHICS_GP_LVL_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_IO_USE_SEL);
+
+	tmp = inl(DEFAULT_GPIOBASE + GP_IO_USE_SEL2);
+	tmp = tmp | HYBRID_GRAPHICS_GP_LVL2_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_IO_USE_SEL2);
+
+	/* Set hybrid graphics control GPIO lines to output */
+	tmp = inl(DEFAULT_GPIOBASE + GP_IO_SEL);
+	tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_IO_SEL);
+
+	tmp = inl(DEFAULT_GPIOBASE + GP_IO_SEL2);
+	tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL2_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_IO_SEL2);
+
+	/* Set hybrid graphics detect GPIO lines to input */
+	tmp = inl(DEFAULT_GPIOBASE + GP_IO_SEL);
+	tmp = tmp | HYBRID_GRAPHICS_DETECT_GP_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_IO_SEL);
+}
+
+static bool hybrid_graphics_installed(void)
+{
+	if (inl(DEFAULT_GPIOBASE + GP_LVL) & HYBRID_GRAPHICS_DETECT_GP_BITS)
+		return false;
+	else
+		return true;
+}
+
+static void hybrid_graphics_switch_to_integrated_graphics(void)
+{
+	uint32_t tmp;
+
+	/* Disable switchable graphics */
+	hybrid_graphics_configure_switchable_graphics(false);
+
+	/* Configure muxes */
+	tmp = inl(DEFAULT_GPIOBASE + GP_LVL);
+	tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_LVL);
+
+	tmp = inl(DEFAULT_GPIOBASE + GP_LVL2);
+	tmp = tmp & ~HYBRID_GRAPHICS_GP_LVL2_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_LVL2);
+}
+
+static void hybrid_graphics_switch_to_discrete_graphics(void)
+{
+	uint32_t tmp;
+
+	/* Disable switchable graphics */
+	hybrid_graphics_configure_switchable_graphics(false);
+
+	/* Configure muxes */
+	tmp = inl(DEFAULT_GPIOBASE + GP_LVL);
+	tmp = tmp | HYBRID_GRAPHICS_GP_LVL_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_LVL);
+
+	tmp = inl(DEFAULT_GPIOBASE + GP_LVL2);
+	tmp = tmp | HYBRID_GRAPHICS_GP_LVL2_BITS;
+	outl(tmp, DEFAULT_GPIOBASE + GP_LVL2);
+}
+
+static void hybrid_graphics_switch_to_dual_graphics(void)
+{
+	/* Enable switchable graphics */
+	hybrid_graphics_configure_switchable_graphics(true);
+}
+
 static void default_southbridge_gpio_setup(void)
 {
 	outl(0x197e23fe, DEFAULT_GPIOBASE + GP_IO_USE_SEL);
@@ -95,6 +208,31 @@ void mainboard_romstage_entry(unsigned long bist)

 	default_southbridge_gpio_setup();

+	uint8_t hybrid_graphics_mode = HYBRID_GRAPHICS_INTEGRATED_ONLY;
+	get_option(&hybrid_graphics_mode, "hybrid_graphics_mode");
+
+	/* Set up hybrid graphics */
+	hybrid_graphics_set_up_gpio();
+	if (hybrid_graphics_installed()) {
+		/* Select appropriate hybrid graphics device */
+		printk(BIOS_DEBUG, "Hybrid graphics available, setting mode %d\n", hybrid_graphics_mode);
+		if (hybrid_graphics_mode == HYBRID_GRAPHICS_INTEGRATED_ONLY)
+			hybrid_graphics_switch_to_integrated_graphics();
+		else if (hybrid_graphics_mode == HYBRID_GRAPHICS_DISCRETE_ONLY)
+			hybrid_graphics_switch_to_discrete_graphics();
+		else if (hybrid_graphics_mode == HYBRID_GRAPHICS_SWITCHABLE)
+			hybrid_graphics_switch_to_integrated_graphics();
+			/* Switchable graphics are fully enabled after raminit */
+			/* FIXME
+			 * Enabling switchable graphics prevents bootup!
+			 * Debug and fix appropriately...
+			 */
+	}
+	else {
+		printk(BIOS_DEBUG, "Hybrid graphics not installed\n");
+		hybrid_graphics_switch_to_integrated_graphics();
+	}
+
 	/* ASPM related setting, set early by original BIOS. */
 	DMIBAR16(0x204) &= ~(3 << 10);

@@ -174,6 +312,11 @@ void mainboard_romstage_entry(unsigned long bist)
 	outl(inl(DEFAULT_GPIOBASE + 0x38) & ~0x400, DEFAULT_GPIOBASE + 0x38);

 	cbmem_initted = !cbmem_recovery(s3resume);
+
+	if (hybrid_graphics_installed())
+		if (hybrid_graphics_mode == HYBRID_GRAPHICS_SWITCHABLE)
+			hybrid_graphics_switch_to_dual_graphics();
+
 #if CONFIG_HAVE_ACPI_RESUME
 	/* If there is no high memory area, we didn't boot before, so
 	 * this is not a resume. In that case we just create the cbmem toc.
--
2.9.2


code:
From 873402fb594f06e748563ebf3abc7970613b9bda Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Mon, 8 Aug 2016 23:55:13 +0200
Subject: [PATCH] make 256M vram the default for gm45 laptops

Change-Id: Id213807d1ed3260846118f69b459bcad7a146c30

diff --git a/src/mainboard/lenovo/t400/cmos.default b/src/mainboard/lenovo/t400/cmos.default
index 98ce970..90d796f 100644
--- a/src/mainboard/lenovo/t400/cmos.default
+++ b/src/mainboard/lenovo/t400/cmos.default
@@ -13,4 +13,5 @@ sticky_fn=Disable
 power_management_beeps=Enable
 low_battery_beep=Enable
 sata_mode=AHCI
-hybrid_graphics_mode=Integrated Only
\ No newline at end of file
+hybrid_graphics_mode=Integrated Only
+gfx_uma_size=256M
\ No newline at end of file
diff --git a/src/mainboard/lenovo/x200/cmos.default b/src/mainboard/lenovo/x200/cmos.default
index 1d7b420..ec7ab46 100644
--- a/src/mainboard/lenovo/x200/cmos.default
+++ b/src/mainboard/lenovo/x200/cmos.default
@@ -13,4 +13,4 @@ sticky_fn=Disable
 power_management_beeps=Enable
 low_battery_beep=Enable
 sata_mode=AHCI
-gfx_uma_size=32M
\ No newline at end of file
+gfx_uma_size=256M
\ No newline at end of file
--
2.9.2


code:
From 99b8fb271fd244d8e349ca956819c7e1b3420d80 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Mon, 8 Aug 2016 21:51:34 +0200
Subject: [PATCH] hardcode use on intel integrated graphic device on t400

Change-Id: I2ff2d93b024866063715d26aedf510a9753a5445
---
 src/mainboard/lenovo/t400/romstage.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/mainboard/lenovo/t400/romstage.c b/src/mainboard/lenovo/t400/romstage.c
index 147131f..1316d69 100644
--- a/src/mainboard/lenovo/t400/romstage.c
+++ b/src/mainboard/lenovo/t400/romstage.c
@@ -208,7 +208,8 @@ void main(unsigned long bist)
 	default_southbridge_gpio_setup();

 	uint8_t hybrid_graphics_mode = HYBRID_GRAPHICS_INTEGRATED_ONLY;
-	get_option(&hybrid_graphics_mode, "hybrid_graphics_mode");
+	/* hardcode use of integrated graphic device for libreboot */
+	/* get_option(&hybrid_graphics_mode, "hybrid_graphics_mode"); */

 	/* Set up hybrid graphics */
 	hybrid_graphics_set_up_gpio();
--
2.9.2


code:
# NOTE: remove this when updating coreboot. This has been merged upstream
printf "ThinkPad T500 (depends on T400 patch)\n"
git am "../resources/libreboot/patch/misc/0008-lenovo-t500-Add-clone-of-Lenovo-T400.patch"
# git fetch http://review.coreboot.org/coreboot refs/changes/45/10545/1 && git cherry-pick FETCH_HEAD


code:
# NOTE: remove this when updating to the latest version of coreboot. this patch
# makes the patch below redundant: https://review.coreboot.org/#/c/12814/
printf "northbridge/gm45/raminit.c: enable GS45 high-perf (i.e. add X200S support to libreboot)\n"
git am "../resources/libreboot/patch/misc/0006-northbridge-gm45-raminit.c-enable-GS45-high-performa.patch"
# git fetch http://review.coreboot.org/coreboot refs/changes/35/11135/3 && git cherry-pick FETCH_HEAD


code:
From 63db6e96d846b8cab2df30afdccc6b6b18232e33 Mon Sep 17 00:00:00 2001
From: Leah Rowe <info@minifree.org>
Date: Mon, 13 Oct 2014 00:14:53 +0100
Subject: [PATCH] NOTFORMERGE: ec/lenovo/h8:
 wlan/trackpoint/touchpad/bluetooth/wwan

Permanently enable them.

Change-Id: Ic76ab9ab9c865f30312378e18af58bece6c3260a
Signed-off-by: Leah Rowe <info@minifree.org>
---
 src/ec/lenovo/h8/h8.c     | 21 +++++++++++----------
 src/ec/lenovo/pmh7/pmh7.c | 11 ++++-------
 2 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/src/ec/lenovo/h8/h8.c b/src/ec/lenovo/h8/h8.c
index 943bdd4..32285ac 100644
--- a/src/ec/lenovo/h8/h8.c
+++ b/src/ec/lenovo/h8/h8.c
@@ -252,9 +252,11 @@ static void h8_enable(struct device *dev)

 	ec_write(H8_FAN_CONTROL, H8_FAN_CONTROL_AUTO);

-	if (get_option(&val, "wlan") != CB_SUCCESS)
-		val = 1;
-	h8_wlan_enable(val);
+	// Permanently enable wifi
+	// Intel wifi could be a security risk because it uses firmware. Wlan chip has DMA
+	// and could leak data over a side-channel. Using another manufacturer is recommended.
+	// see http://libreboot.org/docs/index.html#recommended_wifi
+	h8_wlan_enable(1);

 	h8_trackpoint_enable(1);
 	h8_usb_power_enable(1);
@@ -262,14 +264,13 @@ static void h8_enable(struct device *dev)
 	if (get_option(&val, "volume") == CB_SUCCESS && !acpi_is_wakeup_s3())
 		ec_write(H8_VOLUME_CONTROL, val);

-	if (get_option(&val, "bluetooth") != CB_SUCCESS)
-		val = 1;
-	h8_bluetooth_enable(val);
-
-	if (get_option(&val, "wwan") != CB_SUCCESS)
-		val = 1;
+	// Permanently enable bluetooth.
+	// NOTE: bluetooth is a potential security risk. Physical removal of the bluetooth module is recommended.
+	h8_bluetooth_enable(1);

-	h8_wwan_enable(val);
+	// Permanently enable wwan.
+	// NOTE: wwan is a security risk (remove access plus DMA). Physical removal of both the wwan and sim card is recommended.
+	h8_wwan_enable(1);

 	if (conf->has_uwb) {
 		if (get_option(&val, "uwb") != CB_SUCCESS)
diff --git a/src/ec/lenovo/pmh7/pmh7.c b/src/ec/lenovo/pmh7/pmh7.c
index b2c3c08..1570cd6 100644
--- a/src/ec/lenovo/pmh7/pmh7.c
+++ b/src/ec/lenovo/pmh7/pmh7.c
@@ -102,7 +102,6 @@ static void enable_dev(struct device *dev)
 {
 	struct ec_lenovo_pmh7_config *conf = dev->chip_info;
 	struct resource *resource;
-	u8 val;

 	resource = new_resource(dev, EC_LENOVO_PMH7_INDEX);
 	resource->flags = IORESOURCE_IO | IORESOURCE_FIXED;
@@ -114,13 +113,11 @@ static void enable_dev(struct device *dev)
 	pmh7_backlight_enable(conf->backlight_enable);
 	pmh7_dock_event_enable(conf->dock_event_enable);

-	if (get_option(&val, "touchpad") != CB_SUCCESS)
-		val = 1;
-	pmh7_touchpad_enable(val);
+	// Permanently enable touchpad
+	pmh7_touchpad_enable(1);

-	if (get_option(&val, "trackpoint") != CB_SUCCESS)
-		val = 1;
-	pmh7_trackpoint_enable(val);
+	// Permanently enable trackpoint
+	pmh7_trackpoint_enable(1);
 }

 struct chip_operations ec_lenovo_pmh7_ops = {
--
1.9.1


code:
From c63113e56ad2d5f6b318a837e4345e0e962a5c1b Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Wed, 4 May 2016 22:49:07 +0200
Subject: [PATCH 1/1] add acpi c3 / cpu  c4 state for gm45 thinpads

---
 src/mainboard/lenovo/t400/cstates.c | 5 +++++
 src/mainboard/lenovo/x200/cstates.c | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/src/mainboard/lenovo/t400/cstates.c b/src/mainboard/lenovo/t400/cstates.c
index 827f76e..7d92d6f 100644
--- a/src/mainboard/lenovo/t400/cstates.c
+++ b/src/mainboard/lenovo/t400/cstates.c
@@ -27,6 +27,11 @@ static acpi_cstate_t cst_entries[] = {
 		/* acpi C2 / cpu C2 */
 		2, 0x01,  500,
 		{ ACPI_ADDRESS_SPACE_FIXED, 1, 2, { 1 }, 0x10, 0 }
+	},
+	{
+	        /* acpi C3 / cpu C4 */
+		3, 0x02,  300,
+		{ ACPI_ADDRESS_SPACE_FIXED, 1, 2, { 1 }, 0x30, 0 }
 	},
 };

diff --git a/src/mainboard/lenovo/x200/cstates.c b/src/mainboard/lenovo/x200/cstates.c
index 827f76e..7d92d6f 100644
--- a/src/mainboard/lenovo/x200/cstates.c
+++ b/src/mainboard/lenovo/x200/cstates.c
@@ -27,6 +27,11 @@ static acpi_cstate_t cst_entries[] = {
 		/* acpi C2 / cpu C2 */
 		2, 0x01,  500,
 		{ ACPI_ADDRESS_SPACE_FIXED, 1, 2, { 1 }, 0x10, 0 }
+	},
+	{
+	        /* acpi C3 / cpu C4 */
+		3, 0x02,  300,
+		{ ACPI_ADDRESS_SPACE_FIXED, 1, 2, { 1 }, 0x30, 0 }
 	},
 };

--
2.8.2


code:
From 79f4b168666e484191ed3196dffe691953ee783b Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Mon, 15 Aug 2016 00:04:34 +0200
Subject: [PATCH] gm45/gma.c: clean up some registers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

According to "G45: Volume 3: Display Register
Intel ® 965G Express Chipset Family and Intel ®
G35 Express Chipset Graphics Controller" some registries
are set incorrectly in gm45/gma.c.

Some values are changed after comparing them with the values
the i915 linux kernel (3.13 was used) module sets while modesetting.
The values were obtained using 'intel_reg' from intel-gpu-tools,
during a normal boot and with 'nomodeset' as a kernel argument.

Some registers that don't exist on gm45 are set in gma.c, which is
probably the result of copying code from a more recent intel
northbridge.

The result is that that gm45 laptops with wxga displays still work as
before. Laptops with wxga+ displays previously did not display anything
and now have a horizontal 20% strip of working display.

TEST: build with native graphic init and flash on a gm45 target, like
lenovo x200.

Change-Id: If66b60c7189997c558270f9e474851fe7e2219f1
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
---
 src/northbridge/intel/gm45/gma.c | 110 +++++++--------------------------------
 1 file changed, 18 insertions(+), 92 deletions(-)

diff --git a/src/northbridge/intel/gm45/gma.c b/src/northbridge/intel/gm45/gma.c
index a89f9bb..b02c89b 100644
--- a/src/northbridge/intel/gm45/gma.c
+++ b/src/northbridge/intel/gm45/gma.c
@@ -47,60 +47,6 @@ void gtt_write(u32 reg, u32 data)
 	write32(res2mmio(gtt_res, reg, 0), data);
 }

-static void power_port(u8 *mmio)
-{
-	read32(mmio + 0x00061100); // = 0x00000000
-	write32(mmio + 0x00061100, 0x00000000);
-	write32(mmio + 0x00061100, 0x00010000);
-	read32(mmio + 0x00061100); // = 0x00010000
-	read32(mmio + 0x00061100); // = 0x00010000
-	read32(mmio + 0x00061100); // = 0x00000000
-	write32(mmio + 0x00061100, 0x00000000);
-	read32(mmio + 0x00061100); // = 0x00000000
-	read32(mmio + 0x00064200); // = 0x0000001c
-	write32(mmio + 0x00064210, 0x8004003e);
-	write32(mmio + 0x00064214, 0x80060002);
-	write32(mmio + 0x00064218, 0x01000000);
-	read32(mmio + 0x00064210); // = 0x5144003e
-	write32(mmio + 0x00064210, 0x5344003e);
-	read32(mmio + 0x00064210); // = 0x0144003e
-	write32(mmio + 0x00064210, 0x8074003e);
-	read32(mmio + 0x00064210); // = 0x5144003e
-	read32(mmio + 0x00064210); // = 0x5144003e
-	write32(mmio + 0x00064210, 0x5344003e);
-	read32(mmio + 0x00064210); // = 0x0144003e
-	write32(mmio + 0x00064210, 0x8074003e);
-	read32(mmio + 0x00064210); // = 0x5144003e
-	read32(mmio + 0x00064210); // = 0x5144003e
-	write32(mmio + 0x00064210, 0x5344003e);
-	read32(mmio + 0x00064210); // = 0x0144003e
-	write32(mmio + 0x00064210, 0x8074003e);
-	read32(mmio + 0x00064210); // = 0x5144003e
-	read32(mmio + 0x00064210); // = 0x5144003e
-	write32(mmio + 0x00064210, 0x5344003e);
-	write32(mmio + 0x00064f00, 0x0100030c);
-	write32(mmio + 0x00064f04, 0x00b8230c);
-	write32(mmio + 0x00064f08, 0x06f8930c);
-	write32(mmio + 0x00064f0c, 0x09f8e38e);
-	write32(mmio + 0x00064f10, 0x00b8030c);
-	write32(mmio + 0x00064f14, 0x0b78830c);
-	write32(mmio + 0x00064f18, 0x0ff8d3cf);
-	write32(mmio + 0x00064f1c, 0x01e8030c);
-	write32(mmio + 0x00064f20, 0x0ff863cf);
-	write32(mmio + 0x00064f24, 0x0ff803cf);
-	write32(mmio + 0x000c4030, 0x00001000);
-	read32(mmio + 0x00044000); // = 0x00000000
-	write32(mmio + 0x00044030, 0x00001000);
-	read32(mmio + 0x00061150); // = 0x0000001c
-	write32(mmio + 0x00061150, 0x0000089c);
-	write32(mmio + 0x000fcc00, 0x01986f00);
-	write32(mmio + 0x000fcc0c, 0x01986f00);
-	write32(mmio + 0x000fcc18, 0x01986f00);
-	write32(mmio + 0x000fcc24, 0x01986f00);
-	read32(mmio + 0x00044000); // = 0x00000000
-	read32(mmio + LVDS); // = 0x40000002
-}
-
 static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
 			   u8 *mmio, u32 physbase, u16 piobase, u32 lfb)
 {
@@ -150,8 +96,6 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
 	for (i = 0; i <= 0x18; i++)
 		vga_cr_write(i, cr[i]);

-	power_port(mmio);
-
 	intel_gmbus_read_edid(mmio + GMBUS0, 3, 0x50, edid_data, 128);
 	decode_edid(edid_data,
 		    sizeof(edid_data), &edid);
@@ -277,28 +221,32 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
 		(hpolarity << 20) | (vpolarity << 21)
 		| (mode->lvds_dual_channel ? LVDS_CLOCK_B_POWERUP_ALL
 		   | LVDS_CLOCK_BOTH_POWERUP_ALL : 0)
-		| LVDS_BORDER_ENABLE | LVDS_CLOCK_A_POWERUP_ALL);
+		| LVDS_ENABLE_DITHER
+		| LVDS_CLOCK_A_POWERUP_ALL
+		| LVDS_PIPE(0));
 	mdelay(1);
 	write32(mmio + PP_CONTROL, PANEL_UNLOCK_REGS
 		| (read32(mmio + PP_CONTROL) & ~PANEL_UNLOCK_MASK));
 	write32(mmio + FP0(0),
 		((pixel_n - 2) << 16)
-		| ((pixel_m1 - 2) << 8) | pixel_m2);
+		| ((pixel_m1 - 2) << 8) | (pixel_m2 - 2));
 	write32(mmio + DPLL(0),
 		DPLL_VCO_ENABLE | DPLLB_MODE_LVDS
+		| DPLL_VGA_MODE_DIS
 		| (mode->lvds_dual_channel ? DPLLB_LVDS_P2_CLOCK_DIV_7
 		   : DPLLB_LVDS_P2_CLOCK_DIV_14)
 		| (0x10000 << (pixel_p1 - 1))
 		| ((info->gfx.use_spread_spectrum_clock ? 3 : 0) << 13)
-		| (0x1 << (pixel_p1 - 1)));
+		| (6 << 9));
 	mdelay(1);
 	write32(mmio + DPLL(0),
 		DPLL_VCO_ENABLE | DPLLB_MODE_LVDS
+		| DPLL_VGA_MODE_DIS
 		| (mode->lvds_dual_channel ? DPLLB_LVDS_P2_CLOCK_DIV_7
 		   : DPLLB_LVDS_P2_CLOCK_DIV_14)
 		| (0x10000 << (pixel_p1 - 1))
 		| ((info->gfx.use_spread_spectrum_clock ? 3 : 0) << 13)
-		| (0x1 << (pixel_p1 - 1)));
+		| (6 << 9));
 	/* Re-lock the registers.  */
 	write32(mmio + PP_CONTROL,
 		(read32(mmio + PP_CONTROL) & ~PANEL_UNLOCK_MASK));
@@ -307,7 +255,9 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
 		(hpolarity << 20) | (vpolarity << 21)
 		| (mode->lvds_dual_channel ? LVDS_CLOCK_B_POWERUP_ALL
 		   | LVDS_CLOCK_BOTH_POWERUP_ALL : 0)
-		| LVDS_BORDER_ENABLE | LVDS_CLOCK_A_POWERUP_ALL);
+		| LVDS_CLOCK_A_POWERUP_ALL
+		| LVDS_ENABLE_DITHER
+		| LVDS_PIPE(0));

 	write32(mmio + HTOTAL(0),
 		((hactive + right_border + hblank - 1) << 16)
@@ -324,7 +274,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
 	write32(mmio + VBLANK(0), ((vactive + bottom_border + vblank - 1) << 16)
 		| (vactive + bottom_border - 1));
 	write32(mmio + VSYNC(0),
-		(vactive + bottom_border + vfront_porch + vsync - 1)
+		((vactive + bottom_border + vfront_porch + vsync - 1) << 16)
 		| (vactive + bottom_border + vfront_porch - 1));

 	write32(mmio + PIPECONF(0), PIPECONF_DISABLE);
@@ -335,7 +285,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
 			| (vactive - 1));
 		write32(mmio + PF_CTL(0), 0);
 		write32(mmio + PF_WIN_SZ(0), 0);
-		write32(mmio + PFIT_CONTROL, 0x20000000);
+		write32(mmio + PFIT_CONTROL, 0);
 	} else {
 		write32(mmio + PIPESRC(0), (639 << 16) | 399);
 		write32(mmio + PF_CTL(0), PF_ENABLE | PF_FILTER_MED_3x3);
@@ -362,7 +312,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
 	write32(mmio + PIPECONF(0), PIPECONF_ENABLE | PIPECONF_BPP_6 | PIPECONF_DITHER_EN);

 	if (IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)) {
-		write32(mmio + VGACNTRL, 0xc4008e | VGA_DISP_DISABLE);
+		write32(mmio + VGACNTRL, VGA_DISP_DISABLE);
 		write32(mmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE
 			| DISPPLANE_BGRX888);
 		mdelay(1);
@@ -370,37 +320,13 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
 		write32(mmio + VGACNTRL, 0xc4008e);
 	}

-	write32(mmio + TRANS_HTOTAL(0),
-		((hactive + right_border + hblank - 1) << 16)
-		| (hactive - 1));
-	write32(mmio + TRANS_HBLANK(0),
-		((hactive + right_border + hblank - 1) << 16)
-		| (hactive + right_border - 1));
-	write32(mmio + TRANS_HSYNC(0),
-		((hactive + right_border + hfront_porch + hsync - 1) << 16)
-		| (hactive + right_border + hfront_porch - 1));
-
-	write32(mmio + TRANS_VTOTAL(0),
-		((vactive + bottom_border + vblank - 1) << 16)
-		| (vactive - 1));
-	write32(mmio + TRANS_VBLANK(0),
-		((vactive + bottom_border + vblank - 1) << 16)
-		| (vactive + bottom_border - 1));
-	write32(mmio + TRANS_VSYNC(0),
-		(vactive + bottom_border + vfront_porch + vsync - 1)
-		| (vactive + bottom_border + vfront_porch - 1));
-
-	write32(mmio + 0x00060100, 0xb01c4000);
-	write32(mmio + 0x000f000c, 0xb01a2050);
-	mdelay(1);
-	write32(mmio + TRANSCONF(0), TRANS_ENABLE | TRANS_6BPC
-		);
-	write32(mmio + LVDS,
-		LVDS_PORT_ENABLE
+	write32(mmio + LVDS, LVDS_PORT_ENABLE
 		| (hpolarity << 20) | (vpolarity << 21)
 		| (mode->lvds_dual_channel ? LVDS_CLOCK_B_POWERUP_ALL
 		   | LVDS_CLOCK_BOTH_POWERUP_ALL : 0)
-		| LVDS_BORDER_ENABLE | LVDS_CLOCK_A_POWERUP_ALL);
+		| LVDS_CLOCK_A_POWERUP_ALL
+		| LVDS_ENABLE_DITHER
+		| LVDS_PIPE(0));

 	write32(mmio + PP_CONTROL, PANEL_POWER_ON | PANEL_POWER_RESET);

--
2.9.3


code:
From 0821d0290e7e17e375ffdb48a86b56504db4f77e Mon Sep 17 00:00:00 2001
From: Damien Zammit <damien@zamaudio.com>
Date: Sat, 27 Aug 2016 00:35:48 +1000
Subject: [PATCH] nb/intel/gm45: Fix IOMMU

Previously the ME was being reported as present in ACPI
even when it's firmware was missing.  Now we do a check via the pci device
(HECI) to verify if the ME is there or not.

Note that this test could fail if ME is present but disabled in devicetree,
but in that case you won't see it in the lspci tree anyway so it shouldn't
be an issue.

Change-Id: Ib692d476d85236b4886ecf3d6e6814229f441de0
Signed-off-by: Damien Zammit <damien@zamaudio.com>
---
 src/northbridge/intel/gm45/acpi.c  | 3 ++-
 src/northbridge/intel/gm45/iommu.c | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/northbridge/intel/gm45/acpi.c b/src/northbridge/intel/gm45/acpi.c
index 8990c3b..b90afca 100644
--- a/src/northbridge/intel/gm45/acpi.c
+++ b/src/northbridge/intel/gm45/acpi.c
@@ -72,7 +72,8 @@ unsigned long acpi_fill_mcfg(unsigned long current)

 static unsigned long acpi_fill_dmar(unsigned long current)
 {
-	int me_active = (dev_find_slot(0, PCI_DEVFN(3, 0)) != NULL);
+	int me_active = (dev_find_slot(0, PCI_DEVFN(3, 0)) != NULL) &&
+		(pci_read_config8(dev_find_slot(0, PCI_DEVFN(3, 0)), PCI_CLASS_REVISION) != 0xff);
 	int stepping = pci_read_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), PCI_CLASS_REVISION);

 	unsigned long tmp = current;
diff --git a/src/northbridge/intel/gm45/iommu.c b/src/northbridge/intel/gm45/iommu.c
index 10548f4..0c3c18e 100644
--- a/src/northbridge/intel/gm45/iommu.c
+++ b/src/northbridge/intel/gm45/iommu.c
@@ -40,6 +40,8 @@ void init_iommu()
 	}
 	if (me_active) {
 		MCHBAR32(0x10) = IOMMU_BASE3 | 1; /* ME  @ 0:3.0-3 */
+	} else {
+		MCHBAR32(0x10) = 0; /* disable IOMMU for ME */
 	}
 	MCHBAR32(0x20) = IOMMU_BASE4 | 1; /* all other DMA sources */

--
2.9.3


code:
From c98d8745d4dca650709e76269cf014e5ffbc1443 Mon Sep 17 00:00:00 2001
From: Arthur Heymans <arthur@aheymans.xyz>
Date: Tue, 9 Aug 2016 00:54:37 +0200
Subject: [PATCH] set default vram to 256M

Change-Id: Ife906c47f32493d9a647a4f12f25982623eba189
---
 src/mainboard/lenovo/t400/cmos.default | 2 +-
 src/mainboard/lenovo/x200/cmos.default | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/mainboard/lenovo/t400/cmos.default b/src/mainboard/lenovo/t400/cmos.default
index 5cf3e63..90d796f 100644
--- a/src/mainboard/lenovo/t400/cmos.default
+++ b/src/mainboard/lenovo/t400/cmos.default
@@ -14,4 +14,4 @@ power_management_beeps=Enable
 low_battery_beep=Enable
 sata_mode=AHCI
 hybrid_graphics_mode=Integrated Only
-gfx_uma_size=32M
\ No newline at end of file
+gfx_uma_size=256M
\ No newline at end of file
diff --git a/src/mainboard/lenovo/x200/cmos.default b/src/mainboard/lenovo/x200/cmos.default
index 1d7b420..ec7ab46 100644
--- a/src/mainboard/lenovo/x200/cmos.default
+++ b/src/mainboard/lenovo/x200/cmos.default
@@ -13,4 +13,4 @@ sticky_fn=Disable
 power_management_beeps=Enable
 low_battery_beep=Enable
 sata_mode=AHCI
-gfx_uma_size=32M
\ No newline at end of file
+gfx_uma_size=256M
\ No newline at end of file
--
2.9.2


code:
From 388f9dbe66f6834013d478eeffe154d59ca6c239 Mon Sep 17 00:00:00 2001
From: Leah Rowe <info@minifree.org>
Date: Tue, 8 Mar 2016 07:21:33 +0000
Subject: [PATCH] HOTFIX: AMD fam10h/fam15h: don't use microcode updates

There were build issues in libreboot. We don't use microcode updates anyway.
When selecting no microcode updates in menuconfig, build failed because
coreboot for these boards was still trying to add microcode.
---
 src/cpu/Makefile.inc                           | 34 +-------------------------
 src/cpu/amd/family_10h-family_15h/Kconfig      |  1 -
 src/cpu/amd/family_10h-family_15h/Makefile.inc | 10 --------
 3 files changed, 1 insertion(+), 44 deletions(-)

diff --git a/src/cpu/Makefile.inc b/src/cpu/Makefile.inc
index 046c418..ef0e236 100644
--- a/src/cpu/Makefile.inc
+++ b/src/cpu/Makefile.inc
@@ -17,36 +17,4 @@ $(eval $(call create_class_compiler,cpu_microcode,x86_32))
 ## Rules for building the microcode blob in CBFS
 ################################################################################

-ifneq ($(CONFIG_CPU_MICROCODE_MULTIPLE_FILES), y)
-cbfs-files-$(CONFIG_CPU_MICROCODE_CBFS_GENERATE)  += cpu_microcode_blob.bin
-endif
-
-ifeq ($(CONFIG_CPU_MICROCODE_CBFS_EXTERNAL_HEADER),y)
-cbfs-files-y  += cpu_microcode_blob.bin
-cpu_microcode_blob.bin-file = $(objgenerated)/microcode.bin
-
-$(objgenerated)/microcode.bin:
-	echo "   util/scripts/ucode_h_to_bin.sh $(objgenerated)/microcode.bin \"$(CONFIG_CPU_MICROCODE_HEADER_FILES)\""
-	util/scripts/ucode_h_to_bin.sh $(objgenerated)/microcode.bin $(CONFIG_CPU_MICROCODE_HEADER_FILES)
-endif
-
-# We just mash all microcode binaries together into one binary to rule them all.
-# This approach assumes that the microcode binaries are properly padded, and
-# their headers specify the correct size. This works fairly well on isolatied
-# updates, such as Intel and some AMD microcode, but won't work very well if the
-# updates are wrapped in a container, like AMD's microcode update container. If
-# there is only one microcode binary (i.e. one container), then we don't have
-# this issue, and this rule will continue to work.
-$(obj)/cpu_microcode_blob.bin: $$(cpu_microcode_bins)
-	@printf "    MICROCODE  $(subst $(obj)/,,$(@))\n"
-	@echo $(cpu_microcode_bins)
-	cat /dev/null $+ > $@
-
-cpu_microcode_blob.bin-file ?= $(obj)/cpu_microcode_blob.bin
-cpu_microcode_blob.bin-type := microcode
-
-ifneq ($(CONFIG_CPU_MICROCODE_CBFS_LOC),)
-cpu_microcode_blob.bin-position := $(CONFIG_CPU_MICROCODE_CBFS_LOC)
-else
-cpu_microcode_blob.bin-align := 16
-endif
+# What? Nope! We don't do that in libreboot.
diff --git a/src/cpu/amd/family_10h-family_15h/Kconfig b/src/cpu/amd/family_10h-family_15h/Kconfig
index 14ab1cd..3f873a1 100644
--- a/src/cpu/amd/family_10h-family_15h/Kconfig
+++ b/src/cpu/amd/family_10h-family_15h/Kconfig
@@ -11,7 +11,6 @@ config CPU_AMD_MODEL_10XXX
 	select UDELAY_LAPIC
 	select HAVE_MONOTONIC_TIMER
 	select SUPPORT_CPU_UCODE_IN_CBFS
-	select CPU_MICROCODE_MULTIPLE_FILES

 if CPU_AMD_MODEL_10XXX

diff --git a/src/cpu/amd/family_10h-family_15h/Makefile.inc b/src/cpu/amd/family_10h-family_15h/Makefile.inc
index f10f732..a295475 100644
--- a/src/cpu/amd/family_10h-family_15h/Makefile.inc
+++ b/src/cpu/amd/family_10h-family_15h/Makefile.inc
@@ -9,13 +9,3 @@ romstage-y += ram_calc.c
 ramstage-y += ram_calc.c
 ramstage-y += monotonic_timer.c
 ramstage-$(CONFIG_HAVE_ACPI_TABLES) += powernow_acpi.c
-
-# Microcode for Family 10h, 11h, 12h, and 14h
-cbfs-files-$(CONFIG_CPU_MICROCODE_MULTIPLE_FILES) += microcode_amd.bin
-microcode_amd.bin-file := 3rdparty/blobs/cpu/amd/family_10h-family_14h/microcode_amd.bin
-microcode_amd.bin-type := microcode
-
-# Microcode for Family 15h
-cbfs-files-$(CONFIG_CPU_MICROCODE_MULTIPLE_FILES) += microcode_amd_fam15h.bin
-microcode_amd_fam15h.bin-file := 3rdparty/blobs/cpu/amd/family_15h/microcode_amd_fam15h.bin
-microcode_amd_fam15h.bin-type := microcode
--
1.9.1


code:
From ea0c2d76c4f16eccaafcb2c0741f76825505bafc Mon Sep 17 00:00:00 2001
From: Nico Huber <nico.huber@secunet.com>
Date: Thu, 22 Dec 2016 16:05:54 +0100
Subject: [PATCH] DONOTMERGE buildgcc: Build GMP `--with-pic` if GCC defaults to `-pie`

Change-Id: I5f3185af9c8d599379a628e18724b217b88be974
Signed-off-by: Nico Huber <nico.huber@secunet.com>
---

diff --git a/util/crossgcc/buildgcc b/util/crossgcc/buildgcc
index 97c38b8..4eefd43 100755
--- a/util/crossgcc/buildgcc
+++ b/util/crossgcc/buildgcc
@@ -515,6 +515,13 @@
 }

 build_GMP() {
+	# Check if GCC enables `-pie` by default (likely on Debian Stretch).
+	# We have to use `--with-pic` then.
+	if "${CC}" -dumpspecs 2>/dev/null | grep -q '[{;][[:space:]]*:-pie\>'
+	then
+		OPTIONS="$OPTIONS --with-pic"
+	fi
+
 	CC="$CC" ../${GMP_DIR}/configure --disable-shared --enable-fat \
 		--prefix=$TARGETDIR $OPTIONS \
 		|| touch .failed


code:
--- Makefile	2015-11-18 23:49:40.900093793 +0100
+++ Makefile.new	2015-11-19 00:08:37.392634002 +0100
@@ -15,3 +15,3 @@
 CFLAGS= -Wall -march=i486 -m32 -O1 -fomit-frame-pointer -fno-builtin \
-	-ffreestanding -fPIC $(SMP_FL) -fno-stack-protector
+	-ffreestanding -fPIC $(SMP_FL) -fno-stack-protector -fgnu89-inline

@@ -23,3 +23,2 @@
 all: clean memtest.bin memtest
-		 scp memtest.bin root@192.168.0.12:/srv/tftp/mt86plus


code:
--- config.h	2015-11-18 23:49:27.696700200 +0100
+++ config.h.new	2015-11-19 00:08:55.799401157 +0100
@@ -19,3 +19,3 @@
 /* BEEP_MODE - Beep on error. Default off, Change to 1 to enable */
-#define BEEP_MODE 0
+#define BEEP_MODE 1

@@ -37,3 +37,3 @@
 /* SERIAL_BAUD_RATE - Baud rate for the serial console */
-#define SERIAL_BAUD_RATE 9600
+#define SERIAL_BAUD_RATE 115200


code:
#!/bin/bash

#  helper script: clean the dependencies that were built in bucts
#
#	Copyright (C) 2014, 2015 Leah Rowe <info@minifree.org>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

# This script assumes that the current working directory is the root
# of libreboot_src or libreboot git

[ "x${DEBUG+set}" = 'xset' ] && set -v
set -u -e

# clean bucts
# --------------------------------------------------------

printf "Cleaning the previous build of bucts\n"

cd "bucts/"
make clean

printf "\n\n"

# done. go back to main directory.
cd "../"