Find patches attached or in the
feature/gm45-lvds-second-channel-solution branch of my repository:

    http://git.pehjota.net/libreboot/libreboot.git/
    git://git.pehjota.net/libreboot/libreboot.git

On GM45-based systems with a 1680x1050, 1440x900, or 1920x1200 display,
the display isn't properly enabled in part because the boards'
devicetree.cb files have hardcoded single-channel LVDS configurations.
So normally there is no output on such displays in either GRUB or Linux
(unless the devicetree.cb is manually changed before building the ROM or
the GRUB configuration boots Linux with "lvds_channel_mode=2" in its
command line.  With this change, there should be display output in
Linux, but still not in GRUB.

I've tested that the coreboot patch compiles, but I don't have any
affected systems on which to test the ROMs.  If anyone on this list has
a ThinkPad R400, T400, or T500 with a high-resolution (higher than
1280x800) display and some time to build and test a ROM, I'd appreciate
some testing of this change (be sure to temporarily remove your
libreboot_grub.cfg file if you have one that boots Linux with
"lvds_channel_mode=2").

Thanks,
-- 
Patrick "P. J." McDermott
  http://www.pehjota.net/
Lead Developer, ProteanOS
  http://www.proteanos.com/
>From d62b568caac667c42f3dca6e0335aaf4a2e9c083 Mon Sep 17 00:00:00 2001
From: "P. J. McDermott" <[email protected]>
Date: Sun, 20 Sep 2015 07:47:18 -0400
Subject: [PATCH 1/3] docs/hcl/gm45_lcd.html: Describe solution to LVDS
 channels problem

---
 docs/hcl/gm45_lcd.html | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/docs/hcl/gm45_lcd.html b/docs/hcl/gm45_lcd.html
index 137bc68..29b31ec 100644
--- a/docs/hcl/gm45_lcd.html
+++ b/docs/hcl/gm45_lcd.html
@@ -64,6 +64,43 @@
 				lvds_channel_mode:Specify LVDS channel mode (0=probe BIOS [default], 1=single-channel, 2=dual-channel) (int)
 				- from /sbin/modinfo i915
 			</p>
+		<h1>
+			Proper solution to LVDS second channel enablement problem
+		</h1>
+			<p>
+				The definition of <b>register "gfx.lvds_dual_channel" = "0"</b> in
+				<b>coreboot/src/mainboard/lenovo/t400/devicetree.cb</b> in libreboot affects the
+				<b>int lvds_dual_channel</b> member of a <b>struct i915_gpu_controller_info</b>
+				(defined in <b>coreboot/src/drivers/intel/gma/i915.h</b>) named <b>gfx</b> in a
+				<b>struct northbridge_intel_gm45_config</b> (defined in
+				<b>coreboot/src/northbridge/intel/gm45/chip.h</b>).  That
+				<b>gfx.lvds_dual_channel</b> in that <b>struct northbridge_intel_gm45_config</b>
+				affects various registers set in <b>intel_gma_init()</b> in
+				<b>coreboot/src/northbridge/intel/gm45/gma.c</b>.
+			</p>
+			<p>
+				A proper solution would likely be as follows:
+			</p>
+			<ul>
+				<li>
+					Remove <b>gfx.lvds_dual_channel</b> from the <b>devicetree.cb</b> files of
+					GM45-based mainboards.
+				</li>
+				<li>
+					In <b>intel_gma_init()</b> in <b>coreboot/src/northbridge/intel/gm45/gma.c</b>,
+					somehow detect whether both LVDS channels should be used (maybe if the
+					resolution as obtained from the decoded EDID data is greater than 1280x800
+					pixels) and set a local variable <b>lvds_dual_channel</b> accordingly.  Use that
+					variable instead of <b>info->gfx.lvds_dual_channel</b>.
+				</li>
+			</ul>
+			<p>
+				Note that this doesn't completely solve the problem for those dual-channel
+				displays and that GRUB still won't have graphics output.  More work is still
+				needed to investigate why coreboot's graphics initialization code for GM45
+				doesn't properly handle dual-channel displays (but the code for Sandy/Ivy Bridge
+				apparently does, as does Linux's i915 driver) and resolve that.
+			</p>
 	</div>
 
 	<div class="section">
-- 
2.1.4

>From a2f0fcccdf5213f89e9833ef4280f982c7689264 Mon Sep 17 00:00:00 2001
From: "P. J. McDermott" <[email protected]>
Date: Sun, 20 Sep 2015 09:00:29 -0400
Subject: [PATCH 2/3] coreboot-libre: Add patch to enable second LVDS channel

---
 ...-intel-gm45-Automatically-enable-second-L.patch | 129 +++++++++++++++++++++
 resources/scripts/helpers/download/coreboot        |   3 +
 2 files changed, 132 insertions(+)
 create mode 100644 resources/libreboot/patch/0014-northbridge-intel-gm45-Automatically-enable-second-L.patch

diff --git a/resources/libreboot/patch/0014-northbridge-intel-gm45-Automatically-enable-second-L.patch b/resources/libreboot/patch/0014-northbridge-intel-gm45-Automatically-enable-second-L.patch
new file mode 100644
index 0000000..6dd05d9
--- /dev/null
+++ b/resources/libreboot/patch/0014-northbridge-intel-gm45-Automatically-enable-second-L.patch
@@ -0,0 +1,129 @@
+From 11cbc9cc777afcf7553e698dd326d4292c3312d4 Mon Sep 17 00:00:00 2001
+From: "P. J. McDermott" <[email protected]>
+Date: Sun, 20 Sep 2015 08:50:38 -0400
+Subject: [PATCH] northbridge/intel/gm45: Automatically enable second LVDS
+ channel
+
+This is not a static board-specific option, so it should be detected
+instead of specified in devicetree.cb.
+
+Signed-off-by: P. J. McDermott <[email protected]>
+---
+ src/mainboard/lenovo/t400/devicetree.cb |  1 -
+ src/mainboard/lenovo/x200/devicetree.cb |  1 -
+ src/northbridge/intel/gm45/gma.c        | 26 +++++++++++++++++++-------
+ 3 files changed, 19 insertions(+), 9 deletions(-)
+
+diff --git a/src/mainboard/lenovo/t400/devicetree.cb b/src/mainboard/lenovo/t400/devicetree.cb
+index c3fffe8..cf6157c 100644
+--- a/src/mainboard/lenovo/t400/devicetree.cb
++++ b/src/mainboard/lenovo/t400/devicetree.cb
+@@ -4,7 +4,6 @@ chip northbridge/intel/gm45
+ 	register "gfx.did" = "{ 0x80000100, 0x80000240, 0x80000410, 0x80000410, 0x00000005 }"
+ 
+ 	register "gfx.use_spread_spectrum_clock" = "1"
+-	register "gfx.lvds_dual_channel" = "0"
+ 	register "gfx.link_frequency_270_mhz" = "1"
+ 	register "gfx.lvds_num_lanes" = "4"
+ 
+diff --git a/src/mainboard/lenovo/x200/devicetree.cb b/src/mainboard/lenovo/x200/devicetree.cb
+index cb4a021..007141c 100644
+--- a/src/mainboard/lenovo/x200/devicetree.cb
++++ b/src/mainboard/lenovo/x200/devicetree.cb
+@@ -4,7 +4,6 @@ chip northbridge/intel/gm45
+ 	register "gfx.did" = "{ 0x80000100, 0x80000240, 0x80000410, 0x80000410, 0x00000005 }"
+ 
+ 	register "gfx.use_spread_spectrum_clock" = "1"
+-	register "gfx.lvds_dual_channel" = "0"
+ 	register "gfx.link_frequency_270_mhz" = "1"
+ 	register "gfx.lvds_num_lanes" = "4"
+ 
+diff --git a/src/northbridge/intel/gm45/gma.c b/src/northbridge/intel/gm45/gma.c
+index f29b9b1..a695800 100644
+--- a/src/northbridge/intel/gm45/gma.c
++++ b/src/northbridge/intel/gm45/gma.c
+@@ -112,6 +112,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
+ 	u32 hactive, vactive, right_border, bottom_border;
+ 	int hpolarity, vpolarity;
+ 	u32 vsync, hsync, vblank, hblank, hfront_porch, vfront_porch;
++	int lvds_dual_channel;
+ 	u32 candp1, candn;
+ 	u32 best_delta = 0xffffffff;
+ 	u32 target_frequency;
+@@ -172,7 +173,18 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
+ 	hfront_porch = edid.hso;
+ 	vfront_porch = edid.vso;
+ 
+-	target_frequency = info->gfx.lvds_dual_channel ? edid.pixel_clock
++	/*
++	 * Detect whether second LVDS channel should be enabled.
++	 * This currently assumes that any display larger than 1280x800 pixels
++	 * needs both channels, which seems approximately true.
++	 */
++	if (hactive * vactive > 1280 * 800) {
++		lvds_dual_channel = 1;
++	} else {
++		lvds_dual_channel = 0;
++	}
++
++	target_frequency = lvds_dual_channel ? edid.pixel_clock
+ 		: (2 * edid.pixel_clock);
+ #if IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE)
+ 	vga_sr_write(1, 1);
+@@ -257,7 +269,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
+ 	printk(BIOS_DEBUG, (info->gfx.use_spread_spectrum_clock
+ 			    ? "Spread spectrum clock\n" : "DREF clock\n"));
+ 	printk(BIOS_DEBUG,
+-	       info->gfx.lvds_dual_channel ? "Dual channel\n" : "Single channel\n");
++	       lvds_dual_channel ? "Dual channel\n" : "Single channel\n");
+ 	printk(BIOS_DEBUG, "Polarities %d, %d\n",
+ 	       hpolarity, vpolarity);
+ 	printk(BIOS_DEBUG, "Data M1=%d, N1=%d\n",
+@@ -274,7 +286,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
+ 
+ 	write32(mmio + LVDS,
+ 		(hpolarity << 20) | (vpolarity << 21)
+-		| (info->gfx.lvds_dual_channel ? LVDS_CLOCK_B_POWERUP_ALL
++		| (lvds_dual_channel ? LVDS_CLOCK_B_POWERUP_ALL
+ 		   | LVDS_CLOCK_BOTH_POWERUP_ALL : 0)
+ 		| LVDS_BORDER_ENABLE | LVDS_CLOCK_A_POWERUP_ALL);
+ 	mdelay(1);
+@@ -285,7 +297,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
+ 		| ((pixel_m1 - 2) << 8) | pixel_m2);
+ 	write32(mmio + DPLL(0),
+ 		DPLL_VCO_ENABLE | DPLLB_MODE_LVDS
+-		| (info->gfx.lvds_dual_channel ? DPLLB_LVDS_P2_CLOCK_DIV_7
++		| (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)
+@@ -293,7 +305,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
+ 	mdelay(1);
+ 	write32(mmio + DPLL(0),
+ 		DPLL_VCO_ENABLE | DPLLB_MODE_LVDS
+-		| (info->gfx.lvds_dual_channel ? DPLLB_LVDS_P2_CLOCK_DIV_7
++		| (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)
+@@ -304,7 +316,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
+ 
+ 	write32(mmio + LVDS,
+ 		(hpolarity << 20) | (vpolarity << 21)
+-		| (info->gfx.lvds_dual_channel ? LVDS_CLOCK_B_POWERUP_ALL
++		| (lvds_dual_channel ? LVDS_CLOCK_B_POWERUP_ALL
+ 		   | LVDS_CLOCK_BOTH_POWERUP_ALL : 0)
+ 		| LVDS_BORDER_ENABLE | LVDS_CLOCK_A_POWERUP_ALL);
+ 
+@@ -395,7 +407,7 @@ static void intel_gma_init(const struct northbridge_intel_gm45_config *info,
+ 	write32(mmio + LVDS,
+ 		LVDS_PORT_ENABLE
+ 		| (hpolarity << 20) | (vpolarity << 21)
+-		| (info->gfx.lvds_dual_channel ? LVDS_CLOCK_B_POWERUP_ALL
++		| (lvds_dual_channel ? LVDS_CLOCK_B_POWERUP_ALL
+ 		   | LVDS_CLOCK_BOTH_POWERUP_ALL : 0)
+ 		| LVDS_BORDER_ENABLE | LVDS_CLOCK_A_POWERUP_ALL);
+ 
+-- 
+2.1.4
+
diff --git a/resources/scripts/helpers/download/coreboot b/resources/scripts/helpers/download/coreboot
index 21d86de..295c7f1 100755
--- a/resources/scripts/helpers/download/coreboot
+++ b/resources/scripts/helpers/download/coreboot
@@ -135,6 +135,9 @@ printf "ec/lenovo/h8: re-factor handling of power_management_beeps\n"
 # git fetch http://review.coreboot.org/coreboot refs/changes/31/10531/8 && git cherry-pick FETCH_HEAD
 git am "../resources/libreboot/patch/0013-ec-lenovo-h8-re-factor-handling-of-power_management_.patch"
 
+printf "northbridge/intel/gm45: Automatically enable second LVDS channel\n"
+git am "../resources/libreboot/patch/0014-northbridge-intel-gm45-Automatically-enable-second-L.patch"
+
 # Run coreboot-libre deblob scripts
 # ------------------------------------------------------------------------------
 
-- 
2.1.4

>From 793c4e5cff6b68ac4cd9ae4a6872ac899087f9fa Mon Sep 17 00:00:00 2001
From: "P. J. McDermott" <[email protected]>
Date: Sun, 20 Sep 2015 09:33:38 -0400
Subject: [PATCH 3/3] docs/hcl/gm45_lcd.html: Update LVDS channels section

---
 docs/hcl/gm45_lcd.html | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/docs/hcl/gm45_lcd.html b/docs/hcl/gm45_lcd.html
index 29b31ec..9aae1ea 100644
--- a/docs/hcl/gm45_lcd.html
+++ b/docs/hcl/gm45_lcd.html
@@ -95,6 +95,9 @@
 				</li>
 			</ul>
 			<p>
+				Libreboot includes a patch to coreboot that does this.
+			</p>
+			<p>
 				Note that this doesn't completely solve the problem for those dual-channel
 				displays and that GRUB still won't have graphics output.  More work is still
 				needed to investigate why coreboot's graphics initialization code for GM45
-- 
2.1.4

Reply via email to