diff options
Diffstat (limited to 'resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4')
63 files changed, 8689 insertions, 0 deletions
diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/INFO b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/INFO new file mode 100644 index 00000000..ad7d12f4 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/INFO @@ -0,0 +1,4 @@ +# 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 diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/reused.list new file mode 100644 index 00000000..451d1b75 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_16mb/reused.list @@ -0,0 +1,7 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb//0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/reused.list new file mode 100644 index 00000000..59e0a36a --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_4mb/reused.list @@ -0,0 +1,7 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/INFO b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/INFO new file mode 100644 index 00000000..ad7d12f4 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/INFO @@ -0,0 +1,4 @@ +# 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 diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/reused.list new file mode 100644 index 00000000..59e0a36a --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/r400_8mb/reused.list @@ -0,0 +1,7 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/INFO b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/INFO new file mode 100644 index 00000000..9ef6d54a --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/INFO @@ -0,0 +1,8 @@ +# 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 diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/reused.list new file mode 100644 index 00000000..59e0a36a --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_16mb/reused.list @@ -0,0 +1,7 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/reused.list new file mode 100644 index 00000000..59e0a36a --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_4mb/reused.list @@ -0,0 +1,7 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch new file mode 100644 index 00000000..67420ca7 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch @@ -0,0 +1,601 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch new file mode 100644 index 00000000..49b9549a --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch @@ -0,0 +1,35 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch new file mode 100644 index 00000000..76463937 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch @@ -0,0 +1,27 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/INFO b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/INFO new file mode 100644 index 00000000..9ef6d54a --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/INFO @@ -0,0 +1,8 @@ +# 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 diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/reused.list new file mode 100644 index 00000000..4ea9a7ad --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/reused.list @@ -0,0 +1,4 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/INFO b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/INFO new file mode 100644 index 00000000..0537bbc8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/INFO @@ -0,0 +1,4 @@ +# 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 diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/reused.list new file mode 100644 index 00000000..59e0a36a --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_16mb/reused.list @@ -0,0 +1,7 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/reused.list new file mode 100644 index 00000000..59e0a36a --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_4mb/reused.list @@ -0,0 +1,7 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/INFO b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/INFO new file mode 100644 index 00000000..0537bbc8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/INFO @@ -0,0 +1,4 @@ +# 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 diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/reused.list new file mode 100644 index 00000000..59e0a36a --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t500_8mb/reused.list @@ -0,0 +1,7 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0001-Revert-hybrid-driver.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0002-make-256M-vram-the-default-for-gm45-laptops.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/t400_8mb/0003-hardcode-use-on-intel-integrated-graphic-device-on-t.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/INFO b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/INFO new file mode 100644 index 00000000..220b8583 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/INFO @@ -0,0 +1,5 @@ +# 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 diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/reused.list new file mode 100644 index 00000000..8a98e98c --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_16mb/reused.list @@ -0,0 +1,5 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-set-default-vram-to-256M.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/reused.list b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/reused.list new file mode 100644 index 00000000..8a98e98c --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_4mb/reused.list @@ -0,0 +1,5 @@ +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-set-default-vram-to-256M.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch +/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch new file mode 100644 index 00000000..8e5e1dca --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-NOTFORMERGE-ec-lenovo-h8-wlan-trackpoint-touchpad-bl.patch @@ -0,0 +1,88 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch new file mode 100644 index 00000000..046192dd --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-add-acpi-c3-cpu-c4-state-for-gm45-thinpads.patch @@ -0,0 +1,45 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch new file mode 100644 index 00000000..61b36eb6 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-gm45-gma.c-clean-up-some-registers.patch @@ -0,0 +1,229 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch new file mode 100644 index 00000000..d89e4884 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-nb-intel-gm45-Fix-IOMMU.patch @@ -0,0 +1,50 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-set-default-vram-to-256M.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-set-default-vram-to-256M.patch new file mode 100644 index 00000000..01124c34 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0001-set-default-vram-to-256M.patch @@ -0,0 +1,38 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch new file mode 100644 index 00000000..26632b7d --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0002-gm45-gma.c-use-screen-on-vga-connector-if-connected.patch @@ -0,0 +1,212 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch new file mode 100644 index 00000000..ef42f3e8 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0003-nb-gm45-gma.c-enable-VESA-framebuffer-mode-on-VGA-ou.patch @@ -0,0 +1,379 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch new file mode 100644 index 00000000..fb30c4c2 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/0004-gm45-gma.c-use-correct-id-string-for-fake-VBT.patch @@ -0,0 +1,31 @@ +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 + diff --git a/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/INFO b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/INFO new file mode 100644 index 00000000..220b8583 --- /dev/null +++ b/resources/libreboot/patch/coreboot/d83b0e9ac4174cca92ac2c3b83a7e8491a9a1ff4/grub/x200_8mb/INFO @@ -0,0 +1,5 @@ +# 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 |