diff options
author | Leah Rowe <info@minifree.org> | 2016-09-09 22:16:12 +0100 |
---|---|---|
committer | 4 of 7 (Leah Rowe) info@minifree.org <info@minifree.org> | 2017-01-21 18:53:37 +0000 |
commit | 892299378727e22a3bc41de06e65a410b71ea243 (patch) | |
tree | 27940529ab1536e476d1354bf968423b5b28c1ff /resources | |
parent | dec843a5ae15ec791f293ea9c6fe27e4e0ba9b41 (diff) | |
download | librebootfr-892299378727e22a3bc41de06e65a410b71ea243.tar.gz librebootfr-892299378727e22a3bc41de06e65a410b71ea243.zip |
i945: add support for external monitors in grub (patch from Arthur Heymans)
Diffstat (limited to 'resources')
6 files changed, 1245 insertions, 0 deletions
diff --git a/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/macbook21/0005-i945-gma.c-use-latest-linux-code-to-calculate-diviso.patch b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/macbook21/0005-i945-gma.c-use-latest-linux-code-to-calculate-diviso.patch new file mode 100644 index 00000000..884b2829 --- /dev/null +++ b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/macbook21/0005-i945-gma.c-use-latest-linux-code-to-calculate-diviso.patch @@ -0,0 +1,174 @@ +From 34f8cdbc30f1fdf4700c73aad26e0fc159af70ab Mon Sep 17 00:00:00 2001 +From: Arthur Heymans <arthur@aheymans.xyz> +Date: Fri, 2 Sep 2016 22:35:32 +0200 +Subject: [PATCH 1/2] i945/gma.c use latest linux code to calculate divisors. + +The code to compute n, m1, m2, p1 divisors is not correct in coreboot and +on some targets hits a working mode at lower refresh rate, which is why +display is working on some targets. +This patch also fixes reference frequency. + +This patch reuses linux code to correctly compute divisors. + +The result is that some previously not working displays (Lenovo T60 with +1024x786, 1400x1050, 2048x1536) + +TESTED on T60 with 1024x786. + +Change-Id: I2c7f3bb0024ac005029eaebe3ecdc70c38ac777e +Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> +--- + src/northbridge/intel/i945/gma.c | 82 +++++++++++++++++++--------------------- + 1 file changed, 38 insertions(+), 44 deletions(-) + +diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c +index 02caa0a..3f0b5b4 100644 +--- a/src/northbridge/intel/i945/gma.c ++++ b/src/northbridge/intel/i945/gma.c +@@ -26,6 +26,8 @@ + #include <string.h> + #include <pc80/vga.h> + #include <pc80/vga_io.h> ++#include <commonlib/helpers.h> ++ + + #include "i945.h" + #include "chip.h" +@@ -43,7 +45,7 @@ + #define PGETBL_CTL 0x2020 + #define PGETBL_ENABLED 0x00000001 + +-#define BASE_FREQUENCY 120000 ++#define BASE_FREQUENCY 100000 + + #if CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT + +@@ -85,10 +87,10 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + u8 edid_data[128]; + unsigned long temp; + int hpolarity, vpolarity; +- u32 candp1, candn; +- u32 best_delta = 0xffffffff; ++ u32 smallest_err = 0xffffffff; + u32 target_frequency; + u32 pixel_p1 = 1; ++ u32 pixel_p2; + u32 pixel_n = 1; + u32 pixel_m1 = 1; + u32 pixel_m2 = 1; +@@ -158,43 +160,37 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + write32(pmmio + PORT_HOTPLUG_EN, conf->gpu_hotplug); + write32(pmmio + INSTPM, 0x08000000 | INSTPM_AGPBUSY_DIS); + +- target_frequency = mode->lvds_dual_channel ? mode->pixel_clock +- : (2 * mode->pixel_clock); +- +- /* Find suitable divisors. */ +- for (candp1 = 1; candp1 <= 8; candp1++) { +- for (candn = 5; candn <= 10; candn++) { +- u32 cur_frequency; +- u32 m; /* 77 - 131. */ +- u32 denom; /* 35 - 560. */ +- u32 current_delta; +- +- denom = candn * candp1 * 7; +- /* Doesnt overflow for up to +- 5000000 kHz = 5 GHz. */ +- m = (target_frequency * denom +- + BASE_FREQUENCY / 2) / BASE_FREQUENCY; +- +- if (m < 77 || m > 131) +- continue; +- +- cur_frequency = (BASE_FREQUENCY * m) / denom; +- if (target_frequency > cur_frequency) +- current_delta = target_frequency - cur_frequency; +- else +- current_delta = cur_frequency - target_frequency; +- +- if (best_delta > current_delta) { +- best_delta = current_delta; +- pixel_n = candn; +- pixel_p1 = candp1; +- pixel_m2 = ((m + 3) % 5) + 7; +- pixel_m1 = (m - pixel_m2) / 5; ++ pixel_p2 = mode->lvds_dual_channel ? 7 : 14; ++ target_frequency = mode->pixel_clock; ++ ++ /* Find suitable divisors, m1, m2, p1, n. */ ++ /* refclock * (5 * (m1 + 2) + (m1 + 2)) / (n + 2) / p1 / p2 */ ++ /* should be closest to target frequency as possible */ ++ u32 candn, candm1, candm2, candp1; ++ for (candm1 = 8; candm1 <= 18; candm1++) { ++ for (candm2 = 3; candm2 <= 7; candm2++) { ++ for (candn = 1; candn <= 6; candn++) { ++ for (candp1 = 1; candp1 <= 8; candp1++) { ++ u32 m = 5 * (candm1 + 2) + (candm2 + 2); ++ u32 p = candp1 * pixel_p2; ++ u32 vco = DIV_ROUND_CLOSEST(BASE_FREQUENCY * m, candn + 2); ++ u32 dot = DIV_ROUND_CLOSEST(vco, p); ++ u32 this_err = ABS(dot - target_frequency); ++ if ((m < 70) || (m > 120)) ++ continue; ++ if (this_err < smallest_err) { ++ smallest_err = this_err; ++ pixel_n = candn; ++ pixel_m1 = candm1; ++ pixel_m2 = candm2; ++ pixel_p1 = candp1; ++ } ++ } + } + } + } + +- if (best_delta == 0xffffffff) { ++ if (smallest_err == 0xffffffff) { + printk (BIOS_ERR, "Couldn't find GFX clock divisors\n"); + return -1; + } +@@ -216,8 +212,8 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + printk(BIOS_DEBUG, "Pixel N=%d, M1=%d, M2=%d, P1=%d\n", + pixel_n, pixel_m1, pixel_m2, pixel_p1); + printk(BIOS_DEBUG, "Pixel clock %d kHz\n", +- BASE_FREQUENCY * (5 * pixel_m1 + pixel_m2) / pixel_n +- / (pixel_p1 * 7)); ++ BASE_FREQUENCY * (5 * (pixel_m1 + 2) + (pixel_m2 + 2)) / ++ (pixel_n + 2) / (pixel_p1 * pixel_p2)); + + #if !IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE) + write32(pmmio + PF_WIN_SZ(0), vactive | (hactive << 16)); +@@ -242,8 +238,8 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + write32(pmmio + PP_CONTROL, PANEL_UNLOCK_REGS + | (read32(pmmio + PP_CONTROL) & ~PANEL_UNLOCK_MASK)); + write32(pmmio + FP0(1), +- ((pixel_n - 2) << 16) +- | ((pixel_m1 - 2) << 8) | pixel_m2); ++ (pixel_n << 16) ++ | (pixel_m1 << 8) | pixel_m2); + write32(pmmio + DPLL(1), + DPLL_VGA_MODE_DIS | + DPLL_VCO_ENABLE | DPLLB_MODE_LVDS +@@ -252,8 +248,7 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + | (conf->gpu_lvds_use_spread_spectrum_clock + ? DPLL_INTEGRATED_CLOCK_VLV | DPLL_INTEGRATED_CRI_CLK_VLV + : 0) +- | (pixel_p1 << 16) +- | (pixel_p1)); ++ | (0x10000 << pixel_p1)); + mdelay(1); + write32(pmmio + DPLL(1), + DPLL_VGA_MODE_DIS | +@@ -261,8 +256,7 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + | (mode->lvds_dual_channel ? DPLLB_LVDS_P2_CLOCK_DIV_7 + : DPLLB_LVDS_P2_CLOCK_DIV_14) + | ((conf->gpu_lvds_use_spread_spectrum_clock ? 3 : 0) << 13) +- | (pixel_p1 << 16) +- | (pixel_p1)); ++ | (0x10000 << pixel_p1)); + mdelay(1); + write32(pmmio + HTOTAL(1), + ((hactive + right_border + hblank - 1) << 16) +-- +2.9.3 + diff --git a/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/macbook21/0006-i945-gma.c-add-native-VGA-init.patch b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/macbook21/0006-i945-gma.c-add-native-VGA-init.patch new file mode 100644 index 00000000..26eed5b4 --- /dev/null +++ b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/macbook21/0006-i945-gma.c-add-native-VGA-init.patch @@ -0,0 +1,241 @@ +From 7ed0951bcf59dfd8b1893232b674455ff8f03f83 Mon Sep 17 00:00:00 2001 +From: Arthur Heymans <arthur@aheymans.xyz> +Date: Mon, 5 Sep 2016 22:46:11 +0200 +Subject: [PATCH 2/2] i945/gma.c: add native VGA init + +This reuses the Intel Pineview native graphic initialization +to have output on the VGA connector of i945 devices. + +The behavior is the same as with the vendor VBIOS BLOB. +It uses the external VGA display if it is connected. + +Change-Id: I7eaee87d16df2e5c9ebeaaff01d36ec1aa4ea495 +Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> +--- + src/northbridge/intel/i945/gma.c | 196 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 194 insertions(+), 2 deletions(-) + +diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c +index 3f0b5b4..ac19d5a 100644 +--- a/src/northbridge/intel/i945/gma.c ++++ b/src/northbridge/intel/i945/gma.c +@@ -78,7 +78,7 @@ static int gtt_setup(void *mmiobase) + return 0; + } + +-static int intel_gma_init(struct northbridge_intel_i945_config *conf, ++static int intel_gma_init_lvds(struct northbridge_intel_i945_config *conf, + unsigned int pphysbase, unsigned int piobase, + void *pmmio, unsigned int pgfx) + { +@@ -382,6 +382,194 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + #endif + return 0; + } ++ ++static int intel_gma_init_vga(struct northbridge_intel_i945_config *conf, ++ unsigned int pphysbase, unsigned int piobase, ++ void *pmmio, unsigned int pgfx) ++{ ++ int i; ++ u32 hactive, vactive; ++ u16 reg16; ++ u32 uma_size; ++ ++ printk(BIOS_SPEW, "pmmio %x addrport %x physbase %x\n", ++ (u32)pmmio, piobase, pphysbase); ++ ++ gtt_setup(pmmio); ++ ++ /* Disable VGA. */ ++ write32(pmmio + VGACNTRL, VGA_DISP_DISABLE); ++ ++ /* Disable pipes. */ ++ write32(pmmio + PIPECONF(0), 0); ++ write32(pmmio + PIPECONF(1), 0); ++ ++ write32(pmmio + INSTPM, 0x800); ++ ++ vga_gr_write(0x18, 0); ++ ++ write32(pmmio + VGA0, 0x200074); ++ write32(pmmio + VGA1, 0x200074); ++ ++ write32(pmmio + DSPFW3, 0x7f3f00c1 & ~PINEVIEW_SELF_REFRESH_EN); ++ write32(pmmio + DSPCLK_GATE_D, 0); ++ write32(pmmio + FW_BLC, 0x03060106); ++ write32(pmmio + FW_BLC2, 0x00000306); ++ ++ write32(pmmio + ADPA, ADPA_DAC_ENABLE ++ | ADPA_PIPE_A_SELECT ++ | ADPA_USE_VGA_HVPOLARITY ++ | ADPA_VSYNC_CNTL_ENABLE ++ | ADPA_HSYNC_CNTL_ENABLE ++ | ADPA_DPMS_ON ++ ); ++ ++ write32(pmmio + 0x7041c, 0x0); ++ ++ write32(pmmio + DPLL_MD(0), 0x3); ++ write32(pmmio + DPLL_MD(1), 0x3); ++ write32(pmmio + DSPCNTR(1), 0x1000000); ++ write32(pmmio + PIPESRC(1), 0x027f01df); ++ ++ vga_misc_write(0x67); ++ const u8 cr[] = { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, ++ 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, ++ 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, ++ 0xff ++ }; ++ vga_cr_write(0x11, 0); ++ ++ for (i = 0; i <= 0x18; i++) ++ vga_cr_write(i, cr[i]); ++ ++ // Disable screen memory to prevent garbage from appearing. ++ vga_sr_write(1, vga_sr_read(1) | 0x20); ++ hactive = 640; ++ vactive = 400; ++ ++ mdelay(1); ++ write32(pmmio + DPLL(0), ++ DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL ++ | DPLL_VGA_MODE_DIS ++ | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 ++ | 0x400601 ++ ); ++ mdelay(1); ++ write32(pmmio + DPLL(0), ++ DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL ++ | DPLL_VGA_MODE_DIS ++ | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 ++ | 0x400601 ++ ); ++ ++ write32(pmmio + ADPA, ADPA_DAC_ENABLE ++ | ADPA_PIPE_A_SELECT ++ | ADPA_USE_VGA_HVPOLARITY ++ | ADPA_VSYNC_CNTL_ENABLE ++ | ADPA_HSYNC_CNTL_ENABLE ++ | ADPA_DPMS_ON ++ ); ++ ++ write32(pmmio + HTOTAL(0), ++ ((hactive - 1) << 16) ++ | (hactive - 1)); ++ write32(pmmio + HBLANK(0), ++ ((hactive - 1) << 16) ++ | (hactive - 1)); ++ write32(pmmio + HSYNC(0), ++ ((hactive - 1) << 16) ++ | (hactive - 1)); ++ ++ write32(pmmio + VTOTAL(0), ((vactive - 1) << 16) ++ | (vactive - 1)); ++ write32(pmmio + VBLANK(0), ((vactive - 1) << 16) ++ | (vactive - 1)); ++ write32(pmmio + VSYNC(0), ++ ((vactive - 1) << 16) ++ | (vactive - 1)); ++ ++ write32(pmmio + PF_WIN_POS(0), 0); ++ ++ write32(pmmio + PIPESRC(0), (639 << 16) | 399); ++ write32(pmmio + PF_CTL(0),PF_ENABLE | PF_FILTER_MED_3x3); ++ write32(pmmio + PF_WIN_SZ(0), vactive | (hactive << 16)); ++ write32(pmmio + PFIT_CONTROL, 0x0); ++ ++ mdelay(1); ++ ++ write32(pmmio + FDI_RX_CTL(0), 0x00002040); ++ mdelay(1); ++ write32(pmmio + FDI_RX_CTL(0), 0x80002050); ++ write32(pmmio + FDI_TX_CTL(0), 0x00044000); ++ mdelay(1); ++ write32(pmmio + FDI_TX_CTL(0), 0x80044000); ++ write32(pmmio + PIPECONF(0), PIPECONF_ENABLE | PIPECONF_BPP_6 | PIPECONF_DITHER_EN); ++ ++ write32(pmmio + VGACNTRL, 0x0); ++ write32(pmmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888); ++ mdelay(1); ++ ++ write32(pmmio + ADPA, ADPA_DAC_ENABLE ++ | ADPA_PIPE_A_SELECT ++ | ADPA_USE_VGA_HVPOLARITY ++ | ADPA_VSYNC_CNTL_ENABLE ++ | ADPA_HSYNC_CNTL_ENABLE ++ | ADPA_DPMS_ON ++ ); ++ ++ write32(pmmio + DSPFW3, 0x7f3f00c1); ++ write32(pmmio + MI_MODE, 0x200 | VS_TIMER_DISPATCH); ++ write32(pmmio + CACHE_MODE_0, (0x6820 | (1 << 9)) & ~(1 << 5)); ++ write32(pmmio + CACHE_MODE_1, 0x380 & ~(1 << 9)); ++ ++ /* Set up GTT. */ ++ ++ reg16 = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0, 0)), GGC); ++ uma_size = 0; ++ if (!(reg16 & 2)) { ++ uma_size = decode_igd_memory_size((reg16 >> 4) & 7); ++ printk(BIOS_DEBUG, "%dM UMA\n", uma_size >> 10); ++ } ++ ++ for (i = 0; i < (uma_size - 256) / 4; i++) ++ { ++ outl((i << 2) | 1, piobase); ++ outl(pphysbase + (i << 12) + 1, piobase + 4); ++ } ++ ++ /* Clear interrupts. */ ++ write32(pmmio + DEIIR, 0xffffffff); ++ write32(pmmio + SDEIIR, 0xffffffff); ++ write32(pmmio + IIR, 0xffffffff); ++ write32(pmmio + IMR, 0xffffffff); ++ write32(pmmio + EIR, 0xffffffff); ++ ++ vga_textmode_init(); ++ ++ /* Enable screen memory. */ ++ vga_sr_write(1, vga_sr_read(1) & ~0x20); ++ ++ return 0; ++ ++} ++ ++/* compare the header of the vga edid header */ ++/* if vga is not connected it should have a correct header */ ++static int vga_connected(u8 *pmmio) { ++ u8 vga_edid[128]; ++ u8 header[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; ++ intel_gmbus_read_edid(pmmio + GMBUS0, 2, 0x50, vga_edid, 128); ++ intel_gmbus_stop(pmmio + GMBUS0); ++ for (int i = 0; i < 8; i++) { ++ if (vga_edid[i] != header[i]) { ++ printk(BIOS_DEBUG, "VGA not connected. Using LVDS display\n"); ++ return 0; ++ } ++ } ++ printk(BIOS_SPEW, "VGA display connected\n"); ++ return 1; ++} ++ + #endif + + static void gma_func0_init(struct device *dev) +@@ -423,7 +611,11 @@ static void gma_func0_init(struct device *dev) + ); + + int err; +- err = intel_gma_init(conf, pci_read_config32(dev, 0x5c) & ~0xf, ++ if (vga_connected(mmiobase)) ++ err = intel_gma_init_vga(conf, pci_read_config32(dev, 0x5c) & ~0xf, ++ iobase, mmiobase, graphics_base); ++ else ++ err = intel_gma_init_lvds(conf, pci_read_config32(dev, 0x5c) & ~0xf, + iobase, mmiobase, graphics_base); + if (err == 0) + gfx_set_init_done(1); +-- +2.9.3 + diff --git a/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/t60/0005-i945-gma.c-use-latest-linux-code-to-calculate-diviso.patch b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/t60/0005-i945-gma.c-use-latest-linux-code-to-calculate-diviso.patch new file mode 100644 index 00000000..884b2829 --- /dev/null +++ b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/t60/0005-i945-gma.c-use-latest-linux-code-to-calculate-diviso.patch @@ -0,0 +1,174 @@ +From 34f8cdbc30f1fdf4700c73aad26e0fc159af70ab Mon Sep 17 00:00:00 2001 +From: Arthur Heymans <arthur@aheymans.xyz> +Date: Fri, 2 Sep 2016 22:35:32 +0200 +Subject: [PATCH 1/2] i945/gma.c use latest linux code to calculate divisors. + +The code to compute n, m1, m2, p1 divisors is not correct in coreboot and +on some targets hits a working mode at lower refresh rate, which is why +display is working on some targets. +This patch also fixes reference frequency. + +This patch reuses linux code to correctly compute divisors. + +The result is that some previously not working displays (Lenovo T60 with +1024x786, 1400x1050, 2048x1536) + +TESTED on T60 with 1024x786. + +Change-Id: I2c7f3bb0024ac005029eaebe3ecdc70c38ac777e +Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> +--- + src/northbridge/intel/i945/gma.c | 82 +++++++++++++++++++--------------------- + 1 file changed, 38 insertions(+), 44 deletions(-) + +diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c +index 02caa0a..3f0b5b4 100644 +--- a/src/northbridge/intel/i945/gma.c ++++ b/src/northbridge/intel/i945/gma.c +@@ -26,6 +26,8 @@ + #include <string.h> + #include <pc80/vga.h> + #include <pc80/vga_io.h> ++#include <commonlib/helpers.h> ++ + + #include "i945.h" + #include "chip.h" +@@ -43,7 +45,7 @@ + #define PGETBL_CTL 0x2020 + #define PGETBL_ENABLED 0x00000001 + +-#define BASE_FREQUENCY 120000 ++#define BASE_FREQUENCY 100000 + + #if CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT + +@@ -85,10 +87,10 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + u8 edid_data[128]; + unsigned long temp; + int hpolarity, vpolarity; +- u32 candp1, candn; +- u32 best_delta = 0xffffffff; ++ u32 smallest_err = 0xffffffff; + u32 target_frequency; + u32 pixel_p1 = 1; ++ u32 pixel_p2; + u32 pixel_n = 1; + u32 pixel_m1 = 1; + u32 pixel_m2 = 1; +@@ -158,43 +160,37 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + write32(pmmio + PORT_HOTPLUG_EN, conf->gpu_hotplug); + write32(pmmio + INSTPM, 0x08000000 | INSTPM_AGPBUSY_DIS); + +- target_frequency = mode->lvds_dual_channel ? mode->pixel_clock +- : (2 * mode->pixel_clock); +- +- /* Find suitable divisors. */ +- for (candp1 = 1; candp1 <= 8; candp1++) { +- for (candn = 5; candn <= 10; candn++) { +- u32 cur_frequency; +- u32 m; /* 77 - 131. */ +- u32 denom; /* 35 - 560. */ +- u32 current_delta; +- +- denom = candn * candp1 * 7; +- /* Doesnt overflow for up to +- 5000000 kHz = 5 GHz. */ +- m = (target_frequency * denom +- + BASE_FREQUENCY / 2) / BASE_FREQUENCY; +- +- if (m < 77 || m > 131) +- continue; +- +- cur_frequency = (BASE_FREQUENCY * m) / denom; +- if (target_frequency > cur_frequency) +- current_delta = target_frequency - cur_frequency; +- else +- current_delta = cur_frequency - target_frequency; +- +- if (best_delta > current_delta) { +- best_delta = current_delta; +- pixel_n = candn; +- pixel_p1 = candp1; +- pixel_m2 = ((m + 3) % 5) + 7; +- pixel_m1 = (m - pixel_m2) / 5; ++ pixel_p2 = mode->lvds_dual_channel ? 7 : 14; ++ target_frequency = mode->pixel_clock; ++ ++ /* Find suitable divisors, m1, m2, p1, n. */ ++ /* refclock * (5 * (m1 + 2) + (m1 + 2)) / (n + 2) / p1 / p2 */ ++ /* should be closest to target frequency as possible */ ++ u32 candn, candm1, candm2, candp1; ++ for (candm1 = 8; candm1 <= 18; candm1++) { ++ for (candm2 = 3; candm2 <= 7; candm2++) { ++ for (candn = 1; candn <= 6; candn++) { ++ for (candp1 = 1; candp1 <= 8; candp1++) { ++ u32 m = 5 * (candm1 + 2) + (candm2 + 2); ++ u32 p = candp1 * pixel_p2; ++ u32 vco = DIV_ROUND_CLOSEST(BASE_FREQUENCY * m, candn + 2); ++ u32 dot = DIV_ROUND_CLOSEST(vco, p); ++ u32 this_err = ABS(dot - target_frequency); ++ if ((m < 70) || (m > 120)) ++ continue; ++ if (this_err < smallest_err) { ++ smallest_err = this_err; ++ pixel_n = candn; ++ pixel_m1 = candm1; ++ pixel_m2 = candm2; ++ pixel_p1 = candp1; ++ } ++ } + } + } + } + +- if (best_delta == 0xffffffff) { ++ if (smallest_err == 0xffffffff) { + printk (BIOS_ERR, "Couldn't find GFX clock divisors\n"); + return -1; + } +@@ -216,8 +212,8 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + printk(BIOS_DEBUG, "Pixel N=%d, M1=%d, M2=%d, P1=%d\n", + pixel_n, pixel_m1, pixel_m2, pixel_p1); + printk(BIOS_DEBUG, "Pixel clock %d kHz\n", +- BASE_FREQUENCY * (5 * pixel_m1 + pixel_m2) / pixel_n +- / (pixel_p1 * 7)); ++ BASE_FREQUENCY * (5 * (pixel_m1 + 2) + (pixel_m2 + 2)) / ++ (pixel_n + 2) / (pixel_p1 * pixel_p2)); + + #if !IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE) + write32(pmmio + PF_WIN_SZ(0), vactive | (hactive << 16)); +@@ -242,8 +238,8 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + write32(pmmio + PP_CONTROL, PANEL_UNLOCK_REGS + | (read32(pmmio + PP_CONTROL) & ~PANEL_UNLOCK_MASK)); + write32(pmmio + FP0(1), +- ((pixel_n - 2) << 16) +- | ((pixel_m1 - 2) << 8) | pixel_m2); ++ (pixel_n << 16) ++ | (pixel_m1 << 8) | pixel_m2); + write32(pmmio + DPLL(1), + DPLL_VGA_MODE_DIS | + DPLL_VCO_ENABLE | DPLLB_MODE_LVDS +@@ -252,8 +248,7 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + | (conf->gpu_lvds_use_spread_spectrum_clock + ? DPLL_INTEGRATED_CLOCK_VLV | DPLL_INTEGRATED_CRI_CLK_VLV + : 0) +- | (pixel_p1 << 16) +- | (pixel_p1)); ++ | (0x10000 << pixel_p1)); + mdelay(1); + write32(pmmio + DPLL(1), + DPLL_VGA_MODE_DIS | +@@ -261,8 +256,7 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + | (mode->lvds_dual_channel ? DPLLB_LVDS_P2_CLOCK_DIV_7 + : DPLLB_LVDS_P2_CLOCK_DIV_14) + | ((conf->gpu_lvds_use_spread_spectrum_clock ? 3 : 0) << 13) +- | (pixel_p1 << 16) +- | (pixel_p1)); ++ | (0x10000 << pixel_p1)); + mdelay(1); + write32(pmmio + HTOTAL(1), + ((hactive + right_border + hblank - 1) << 16) +-- +2.9.3 + diff --git a/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/t60/0006-i945-gma.c-add-native-VGA-init.patch b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/t60/0006-i945-gma.c-add-native-VGA-init.patch new file mode 100644 index 00000000..26eed5b4 --- /dev/null +++ b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/t60/0006-i945-gma.c-add-native-VGA-init.patch @@ -0,0 +1,241 @@ +From 7ed0951bcf59dfd8b1893232b674455ff8f03f83 Mon Sep 17 00:00:00 2001 +From: Arthur Heymans <arthur@aheymans.xyz> +Date: Mon, 5 Sep 2016 22:46:11 +0200 +Subject: [PATCH 2/2] i945/gma.c: add native VGA init + +This reuses the Intel Pineview native graphic initialization +to have output on the VGA connector of i945 devices. + +The behavior is the same as with the vendor VBIOS BLOB. +It uses the external VGA display if it is connected. + +Change-Id: I7eaee87d16df2e5c9ebeaaff01d36ec1aa4ea495 +Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> +--- + src/northbridge/intel/i945/gma.c | 196 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 194 insertions(+), 2 deletions(-) + +diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c +index 3f0b5b4..ac19d5a 100644 +--- a/src/northbridge/intel/i945/gma.c ++++ b/src/northbridge/intel/i945/gma.c +@@ -78,7 +78,7 @@ static int gtt_setup(void *mmiobase) + return 0; + } + +-static int intel_gma_init(struct northbridge_intel_i945_config *conf, ++static int intel_gma_init_lvds(struct northbridge_intel_i945_config *conf, + unsigned int pphysbase, unsigned int piobase, + void *pmmio, unsigned int pgfx) + { +@@ -382,6 +382,194 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + #endif + return 0; + } ++ ++static int intel_gma_init_vga(struct northbridge_intel_i945_config *conf, ++ unsigned int pphysbase, unsigned int piobase, ++ void *pmmio, unsigned int pgfx) ++{ ++ int i; ++ u32 hactive, vactive; ++ u16 reg16; ++ u32 uma_size; ++ ++ printk(BIOS_SPEW, "pmmio %x addrport %x physbase %x\n", ++ (u32)pmmio, piobase, pphysbase); ++ ++ gtt_setup(pmmio); ++ ++ /* Disable VGA. */ ++ write32(pmmio + VGACNTRL, VGA_DISP_DISABLE); ++ ++ /* Disable pipes. */ ++ write32(pmmio + PIPECONF(0), 0); ++ write32(pmmio + PIPECONF(1), 0); ++ ++ write32(pmmio + INSTPM, 0x800); ++ ++ vga_gr_write(0x18, 0); ++ ++ write32(pmmio + VGA0, 0x200074); ++ write32(pmmio + VGA1, 0x200074); ++ ++ write32(pmmio + DSPFW3, 0x7f3f00c1 & ~PINEVIEW_SELF_REFRESH_EN); ++ write32(pmmio + DSPCLK_GATE_D, 0); ++ write32(pmmio + FW_BLC, 0x03060106); ++ write32(pmmio + FW_BLC2, 0x00000306); ++ ++ write32(pmmio + ADPA, ADPA_DAC_ENABLE ++ | ADPA_PIPE_A_SELECT ++ | ADPA_USE_VGA_HVPOLARITY ++ | ADPA_VSYNC_CNTL_ENABLE ++ | ADPA_HSYNC_CNTL_ENABLE ++ | ADPA_DPMS_ON ++ ); ++ ++ write32(pmmio + 0x7041c, 0x0); ++ ++ write32(pmmio + DPLL_MD(0), 0x3); ++ write32(pmmio + DPLL_MD(1), 0x3); ++ write32(pmmio + DSPCNTR(1), 0x1000000); ++ write32(pmmio + PIPESRC(1), 0x027f01df); ++ ++ vga_misc_write(0x67); ++ const u8 cr[] = { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, ++ 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, ++ 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, ++ 0xff ++ }; ++ vga_cr_write(0x11, 0); ++ ++ for (i = 0; i <= 0x18; i++) ++ vga_cr_write(i, cr[i]); ++ ++ // Disable screen memory to prevent garbage from appearing. ++ vga_sr_write(1, vga_sr_read(1) | 0x20); ++ hactive = 640; ++ vactive = 400; ++ ++ mdelay(1); ++ write32(pmmio + DPLL(0), ++ DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL ++ | DPLL_VGA_MODE_DIS ++ | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 ++ | 0x400601 ++ ); ++ mdelay(1); ++ write32(pmmio + DPLL(0), ++ DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL ++ | DPLL_VGA_MODE_DIS ++ | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 ++ | 0x400601 ++ ); ++ ++ write32(pmmio + ADPA, ADPA_DAC_ENABLE ++ | ADPA_PIPE_A_SELECT ++ | ADPA_USE_VGA_HVPOLARITY ++ | ADPA_VSYNC_CNTL_ENABLE ++ | ADPA_HSYNC_CNTL_ENABLE ++ | ADPA_DPMS_ON ++ ); ++ ++ write32(pmmio + HTOTAL(0), ++ ((hactive - 1) << 16) ++ | (hactive - 1)); ++ write32(pmmio + HBLANK(0), ++ ((hactive - 1) << 16) ++ | (hactive - 1)); ++ write32(pmmio + HSYNC(0), ++ ((hactive - 1) << 16) ++ | (hactive - 1)); ++ ++ write32(pmmio + VTOTAL(0), ((vactive - 1) << 16) ++ | (vactive - 1)); ++ write32(pmmio + VBLANK(0), ((vactive - 1) << 16) ++ | (vactive - 1)); ++ write32(pmmio + VSYNC(0), ++ ((vactive - 1) << 16) ++ | (vactive - 1)); ++ ++ write32(pmmio + PF_WIN_POS(0), 0); ++ ++ write32(pmmio + PIPESRC(0), (639 << 16) | 399); ++ write32(pmmio + PF_CTL(0),PF_ENABLE | PF_FILTER_MED_3x3); ++ write32(pmmio + PF_WIN_SZ(0), vactive | (hactive << 16)); ++ write32(pmmio + PFIT_CONTROL, 0x0); ++ ++ mdelay(1); ++ ++ write32(pmmio + FDI_RX_CTL(0), 0x00002040); ++ mdelay(1); ++ write32(pmmio + FDI_RX_CTL(0), 0x80002050); ++ write32(pmmio + FDI_TX_CTL(0), 0x00044000); ++ mdelay(1); ++ write32(pmmio + FDI_TX_CTL(0), 0x80044000); ++ write32(pmmio + PIPECONF(0), PIPECONF_ENABLE | PIPECONF_BPP_6 | PIPECONF_DITHER_EN); ++ ++ write32(pmmio + VGACNTRL, 0x0); ++ write32(pmmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888); ++ mdelay(1); ++ ++ write32(pmmio + ADPA, ADPA_DAC_ENABLE ++ | ADPA_PIPE_A_SELECT ++ | ADPA_USE_VGA_HVPOLARITY ++ | ADPA_VSYNC_CNTL_ENABLE ++ | ADPA_HSYNC_CNTL_ENABLE ++ | ADPA_DPMS_ON ++ ); ++ ++ write32(pmmio + DSPFW3, 0x7f3f00c1); ++ write32(pmmio + MI_MODE, 0x200 | VS_TIMER_DISPATCH); ++ write32(pmmio + CACHE_MODE_0, (0x6820 | (1 << 9)) & ~(1 << 5)); ++ write32(pmmio + CACHE_MODE_1, 0x380 & ~(1 << 9)); ++ ++ /* Set up GTT. */ ++ ++ reg16 = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0, 0)), GGC); ++ uma_size = 0; ++ if (!(reg16 & 2)) { ++ uma_size = decode_igd_memory_size((reg16 >> 4) & 7); ++ printk(BIOS_DEBUG, "%dM UMA\n", uma_size >> 10); ++ } ++ ++ for (i = 0; i < (uma_size - 256) / 4; i++) ++ { ++ outl((i << 2) | 1, piobase); ++ outl(pphysbase + (i << 12) + 1, piobase + 4); ++ } ++ ++ /* Clear interrupts. */ ++ write32(pmmio + DEIIR, 0xffffffff); ++ write32(pmmio + SDEIIR, 0xffffffff); ++ write32(pmmio + IIR, 0xffffffff); ++ write32(pmmio + IMR, 0xffffffff); ++ write32(pmmio + EIR, 0xffffffff); ++ ++ vga_textmode_init(); ++ ++ /* Enable screen memory. */ ++ vga_sr_write(1, vga_sr_read(1) & ~0x20); ++ ++ return 0; ++ ++} ++ ++/* compare the header of the vga edid header */ ++/* if vga is not connected it should have a correct header */ ++static int vga_connected(u8 *pmmio) { ++ u8 vga_edid[128]; ++ u8 header[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; ++ intel_gmbus_read_edid(pmmio + GMBUS0, 2, 0x50, vga_edid, 128); ++ intel_gmbus_stop(pmmio + GMBUS0); ++ for (int i = 0; i < 8; i++) { ++ if (vga_edid[i] != header[i]) { ++ printk(BIOS_DEBUG, "VGA not connected. Using LVDS display\n"); ++ return 0; ++ } ++ } ++ printk(BIOS_SPEW, "VGA display connected\n"); ++ return 1; ++} ++ + #endif + + static void gma_func0_init(struct device *dev) +@@ -423,7 +611,11 @@ static void gma_func0_init(struct device *dev) + ); + + int err; +- err = intel_gma_init(conf, pci_read_config32(dev, 0x5c) & ~0xf, ++ if (vga_connected(mmiobase)) ++ err = intel_gma_init_vga(conf, pci_read_config32(dev, 0x5c) & ~0xf, ++ iobase, mmiobase, graphics_base); ++ else ++ err = intel_gma_init_lvds(conf, pci_read_config32(dev, 0x5c) & ~0xf, + iobase, mmiobase, graphics_base); + if (err == 0) + gfx_set_init_done(1); +-- +2.9.3 + diff --git a/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/x60/0005-i945-gma.c-use-latest-linux-code-to-calculate-diviso.patch b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/x60/0005-i945-gma.c-use-latest-linux-code-to-calculate-diviso.patch new file mode 100644 index 00000000..884b2829 --- /dev/null +++ b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/x60/0005-i945-gma.c-use-latest-linux-code-to-calculate-diviso.patch @@ -0,0 +1,174 @@ +From 34f8cdbc30f1fdf4700c73aad26e0fc159af70ab Mon Sep 17 00:00:00 2001 +From: Arthur Heymans <arthur@aheymans.xyz> +Date: Fri, 2 Sep 2016 22:35:32 +0200 +Subject: [PATCH 1/2] i945/gma.c use latest linux code to calculate divisors. + +The code to compute n, m1, m2, p1 divisors is not correct in coreboot and +on some targets hits a working mode at lower refresh rate, which is why +display is working on some targets. +This patch also fixes reference frequency. + +This patch reuses linux code to correctly compute divisors. + +The result is that some previously not working displays (Lenovo T60 with +1024x786, 1400x1050, 2048x1536) + +TESTED on T60 with 1024x786. + +Change-Id: I2c7f3bb0024ac005029eaebe3ecdc70c38ac777e +Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> +--- + src/northbridge/intel/i945/gma.c | 82 +++++++++++++++++++--------------------- + 1 file changed, 38 insertions(+), 44 deletions(-) + +diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c +index 02caa0a..3f0b5b4 100644 +--- a/src/northbridge/intel/i945/gma.c ++++ b/src/northbridge/intel/i945/gma.c +@@ -26,6 +26,8 @@ + #include <string.h> + #include <pc80/vga.h> + #include <pc80/vga_io.h> ++#include <commonlib/helpers.h> ++ + + #include "i945.h" + #include "chip.h" +@@ -43,7 +45,7 @@ + #define PGETBL_CTL 0x2020 + #define PGETBL_ENABLED 0x00000001 + +-#define BASE_FREQUENCY 120000 ++#define BASE_FREQUENCY 100000 + + #if CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT + +@@ -85,10 +87,10 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + u8 edid_data[128]; + unsigned long temp; + int hpolarity, vpolarity; +- u32 candp1, candn; +- u32 best_delta = 0xffffffff; ++ u32 smallest_err = 0xffffffff; + u32 target_frequency; + u32 pixel_p1 = 1; ++ u32 pixel_p2; + u32 pixel_n = 1; + u32 pixel_m1 = 1; + u32 pixel_m2 = 1; +@@ -158,43 +160,37 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + write32(pmmio + PORT_HOTPLUG_EN, conf->gpu_hotplug); + write32(pmmio + INSTPM, 0x08000000 | INSTPM_AGPBUSY_DIS); + +- target_frequency = mode->lvds_dual_channel ? mode->pixel_clock +- : (2 * mode->pixel_clock); +- +- /* Find suitable divisors. */ +- for (candp1 = 1; candp1 <= 8; candp1++) { +- for (candn = 5; candn <= 10; candn++) { +- u32 cur_frequency; +- u32 m; /* 77 - 131. */ +- u32 denom; /* 35 - 560. */ +- u32 current_delta; +- +- denom = candn * candp1 * 7; +- /* Doesnt overflow for up to +- 5000000 kHz = 5 GHz. */ +- m = (target_frequency * denom +- + BASE_FREQUENCY / 2) / BASE_FREQUENCY; +- +- if (m < 77 || m > 131) +- continue; +- +- cur_frequency = (BASE_FREQUENCY * m) / denom; +- if (target_frequency > cur_frequency) +- current_delta = target_frequency - cur_frequency; +- else +- current_delta = cur_frequency - target_frequency; +- +- if (best_delta > current_delta) { +- best_delta = current_delta; +- pixel_n = candn; +- pixel_p1 = candp1; +- pixel_m2 = ((m + 3) % 5) + 7; +- pixel_m1 = (m - pixel_m2) / 5; ++ pixel_p2 = mode->lvds_dual_channel ? 7 : 14; ++ target_frequency = mode->pixel_clock; ++ ++ /* Find suitable divisors, m1, m2, p1, n. */ ++ /* refclock * (5 * (m1 + 2) + (m1 + 2)) / (n + 2) / p1 / p2 */ ++ /* should be closest to target frequency as possible */ ++ u32 candn, candm1, candm2, candp1; ++ for (candm1 = 8; candm1 <= 18; candm1++) { ++ for (candm2 = 3; candm2 <= 7; candm2++) { ++ for (candn = 1; candn <= 6; candn++) { ++ for (candp1 = 1; candp1 <= 8; candp1++) { ++ u32 m = 5 * (candm1 + 2) + (candm2 + 2); ++ u32 p = candp1 * pixel_p2; ++ u32 vco = DIV_ROUND_CLOSEST(BASE_FREQUENCY * m, candn + 2); ++ u32 dot = DIV_ROUND_CLOSEST(vco, p); ++ u32 this_err = ABS(dot - target_frequency); ++ if ((m < 70) || (m > 120)) ++ continue; ++ if (this_err < smallest_err) { ++ smallest_err = this_err; ++ pixel_n = candn; ++ pixel_m1 = candm1; ++ pixel_m2 = candm2; ++ pixel_p1 = candp1; ++ } ++ } + } + } + } + +- if (best_delta == 0xffffffff) { ++ if (smallest_err == 0xffffffff) { + printk (BIOS_ERR, "Couldn't find GFX clock divisors\n"); + return -1; + } +@@ -216,8 +212,8 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + printk(BIOS_DEBUG, "Pixel N=%d, M1=%d, M2=%d, P1=%d\n", + pixel_n, pixel_m1, pixel_m2, pixel_p1); + printk(BIOS_DEBUG, "Pixel clock %d kHz\n", +- BASE_FREQUENCY * (5 * pixel_m1 + pixel_m2) / pixel_n +- / (pixel_p1 * 7)); ++ BASE_FREQUENCY * (5 * (pixel_m1 + 2) + (pixel_m2 + 2)) / ++ (pixel_n + 2) / (pixel_p1 * pixel_p2)); + + #if !IS_ENABLED(CONFIG_FRAMEBUFFER_KEEP_VESA_MODE) + write32(pmmio + PF_WIN_SZ(0), vactive | (hactive << 16)); +@@ -242,8 +238,8 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + write32(pmmio + PP_CONTROL, PANEL_UNLOCK_REGS + | (read32(pmmio + PP_CONTROL) & ~PANEL_UNLOCK_MASK)); + write32(pmmio + FP0(1), +- ((pixel_n - 2) << 16) +- | ((pixel_m1 - 2) << 8) | pixel_m2); ++ (pixel_n << 16) ++ | (pixel_m1 << 8) | pixel_m2); + write32(pmmio + DPLL(1), + DPLL_VGA_MODE_DIS | + DPLL_VCO_ENABLE | DPLLB_MODE_LVDS +@@ -252,8 +248,7 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + | (conf->gpu_lvds_use_spread_spectrum_clock + ? DPLL_INTEGRATED_CLOCK_VLV | DPLL_INTEGRATED_CRI_CLK_VLV + : 0) +- | (pixel_p1 << 16) +- | (pixel_p1)); ++ | (0x10000 << pixel_p1)); + mdelay(1); + write32(pmmio + DPLL(1), + DPLL_VGA_MODE_DIS | +@@ -261,8 +256,7 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + | (mode->lvds_dual_channel ? DPLLB_LVDS_P2_CLOCK_DIV_7 + : DPLLB_LVDS_P2_CLOCK_DIV_14) + | ((conf->gpu_lvds_use_spread_spectrum_clock ? 3 : 0) << 13) +- | (pixel_p1 << 16) +- | (pixel_p1)); ++ | (0x10000 << pixel_p1)); + mdelay(1); + write32(pmmio + HTOTAL(1), + ((hactive + right_border + hblank - 1) << 16) +-- +2.9.3 + diff --git a/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/x60/0006-i945-gma.c-add-native-VGA-init.patch b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/x60/0006-i945-gma.c-add-native-VGA-init.patch new file mode 100644 index 00000000..26eed5b4 --- /dev/null +++ b/resources/libreboot/patch/coreboot/2a3434757ef425dbdfedf1fc69e1a033a6e7310d/grub/x60/0006-i945-gma.c-add-native-VGA-init.patch @@ -0,0 +1,241 @@ +From 7ed0951bcf59dfd8b1893232b674455ff8f03f83 Mon Sep 17 00:00:00 2001 +From: Arthur Heymans <arthur@aheymans.xyz> +Date: Mon, 5 Sep 2016 22:46:11 +0200 +Subject: [PATCH 2/2] i945/gma.c: add native VGA init + +This reuses the Intel Pineview native graphic initialization +to have output on the VGA connector of i945 devices. + +The behavior is the same as with the vendor VBIOS BLOB. +It uses the external VGA display if it is connected. + +Change-Id: I7eaee87d16df2e5c9ebeaaff01d36ec1aa4ea495 +Signed-off-by: Arthur Heymans <arthur@aheymans.xyz> +--- + src/northbridge/intel/i945/gma.c | 196 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 194 insertions(+), 2 deletions(-) + +diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c +index 3f0b5b4..ac19d5a 100644 +--- a/src/northbridge/intel/i945/gma.c ++++ b/src/northbridge/intel/i945/gma.c +@@ -78,7 +78,7 @@ static int gtt_setup(void *mmiobase) + return 0; + } + +-static int intel_gma_init(struct northbridge_intel_i945_config *conf, ++static int intel_gma_init_lvds(struct northbridge_intel_i945_config *conf, + unsigned int pphysbase, unsigned int piobase, + void *pmmio, unsigned int pgfx) + { +@@ -382,6 +382,194 @@ static int intel_gma_init(struct northbridge_intel_i945_config *conf, + #endif + return 0; + } ++ ++static int intel_gma_init_vga(struct northbridge_intel_i945_config *conf, ++ unsigned int pphysbase, unsigned int piobase, ++ void *pmmio, unsigned int pgfx) ++{ ++ int i; ++ u32 hactive, vactive; ++ u16 reg16; ++ u32 uma_size; ++ ++ printk(BIOS_SPEW, "pmmio %x addrport %x physbase %x\n", ++ (u32)pmmio, piobase, pphysbase); ++ ++ gtt_setup(pmmio); ++ ++ /* Disable VGA. */ ++ write32(pmmio + VGACNTRL, VGA_DISP_DISABLE); ++ ++ /* Disable pipes. */ ++ write32(pmmio + PIPECONF(0), 0); ++ write32(pmmio + PIPECONF(1), 0); ++ ++ write32(pmmio + INSTPM, 0x800); ++ ++ vga_gr_write(0x18, 0); ++ ++ write32(pmmio + VGA0, 0x200074); ++ write32(pmmio + VGA1, 0x200074); ++ ++ write32(pmmio + DSPFW3, 0x7f3f00c1 & ~PINEVIEW_SELF_REFRESH_EN); ++ write32(pmmio + DSPCLK_GATE_D, 0); ++ write32(pmmio + FW_BLC, 0x03060106); ++ write32(pmmio + FW_BLC2, 0x00000306); ++ ++ write32(pmmio + ADPA, ADPA_DAC_ENABLE ++ | ADPA_PIPE_A_SELECT ++ | ADPA_USE_VGA_HVPOLARITY ++ | ADPA_VSYNC_CNTL_ENABLE ++ | ADPA_HSYNC_CNTL_ENABLE ++ | ADPA_DPMS_ON ++ ); ++ ++ write32(pmmio + 0x7041c, 0x0); ++ ++ write32(pmmio + DPLL_MD(0), 0x3); ++ write32(pmmio + DPLL_MD(1), 0x3); ++ write32(pmmio + DSPCNTR(1), 0x1000000); ++ write32(pmmio + PIPESRC(1), 0x027f01df); ++ ++ vga_misc_write(0x67); ++ const u8 cr[] = { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, ++ 0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, ++ 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3, ++ 0xff ++ }; ++ vga_cr_write(0x11, 0); ++ ++ for (i = 0; i <= 0x18; i++) ++ vga_cr_write(i, cr[i]); ++ ++ // Disable screen memory to prevent garbage from appearing. ++ vga_sr_write(1, vga_sr_read(1) | 0x20); ++ hactive = 640; ++ vactive = 400; ++ ++ mdelay(1); ++ write32(pmmio + DPLL(0), ++ DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL ++ | DPLL_VGA_MODE_DIS ++ | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 ++ | 0x400601 ++ ); ++ mdelay(1); ++ write32(pmmio + DPLL(0), ++ DPLL_VCO_ENABLE | DPLLB_MODE_DAC_SERIAL ++ | DPLL_VGA_MODE_DIS ++ | DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 ++ | 0x400601 ++ ); ++ ++ write32(pmmio + ADPA, ADPA_DAC_ENABLE ++ | ADPA_PIPE_A_SELECT ++ | ADPA_USE_VGA_HVPOLARITY ++ | ADPA_VSYNC_CNTL_ENABLE ++ | ADPA_HSYNC_CNTL_ENABLE ++ | ADPA_DPMS_ON ++ ); ++ ++ write32(pmmio + HTOTAL(0), ++ ((hactive - 1) << 16) ++ | (hactive - 1)); ++ write32(pmmio + HBLANK(0), ++ ((hactive - 1) << 16) ++ | (hactive - 1)); ++ write32(pmmio + HSYNC(0), ++ ((hactive - 1) << 16) ++ | (hactive - 1)); ++ ++ write32(pmmio + VTOTAL(0), ((vactive - 1) << 16) ++ | (vactive - 1)); ++ write32(pmmio + VBLANK(0), ((vactive - 1) << 16) ++ | (vactive - 1)); ++ write32(pmmio + VSYNC(0), ++ ((vactive - 1) << 16) ++ | (vactive - 1)); ++ ++ write32(pmmio + PF_WIN_POS(0), 0); ++ ++ write32(pmmio + PIPESRC(0), (639 << 16) | 399); ++ write32(pmmio + PF_CTL(0),PF_ENABLE | PF_FILTER_MED_3x3); ++ write32(pmmio + PF_WIN_SZ(0), vactive | (hactive << 16)); ++ write32(pmmio + PFIT_CONTROL, 0x0); ++ ++ mdelay(1); ++ ++ write32(pmmio + FDI_RX_CTL(0), 0x00002040); ++ mdelay(1); ++ write32(pmmio + FDI_RX_CTL(0), 0x80002050); ++ write32(pmmio + FDI_TX_CTL(0), 0x00044000); ++ mdelay(1); ++ write32(pmmio + FDI_TX_CTL(0), 0x80044000); ++ write32(pmmio + PIPECONF(0), PIPECONF_ENABLE | PIPECONF_BPP_6 | PIPECONF_DITHER_EN); ++ ++ write32(pmmio + VGACNTRL, 0x0); ++ write32(pmmio + DSPCNTR(0), DISPLAY_PLANE_ENABLE | DISPPLANE_BGRX888); ++ mdelay(1); ++ ++ write32(pmmio + ADPA, ADPA_DAC_ENABLE ++ | ADPA_PIPE_A_SELECT ++ | ADPA_USE_VGA_HVPOLARITY ++ | ADPA_VSYNC_CNTL_ENABLE ++ | ADPA_HSYNC_CNTL_ENABLE ++ | ADPA_DPMS_ON ++ ); ++ ++ write32(pmmio + DSPFW3, 0x7f3f00c1); ++ write32(pmmio + MI_MODE, 0x200 | VS_TIMER_DISPATCH); ++ write32(pmmio + CACHE_MODE_0, (0x6820 | (1 << 9)) & ~(1 << 5)); ++ write32(pmmio + CACHE_MODE_1, 0x380 & ~(1 << 9)); ++ ++ /* Set up GTT. */ ++ ++ reg16 = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0, 0)), GGC); ++ uma_size = 0; ++ if (!(reg16 & 2)) { ++ uma_size = decode_igd_memory_size((reg16 >> 4) & 7); ++ printk(BIOS_DEBUG, "%dM UMA\n", uma_size >> 10); ++ } ++ ++ for (i = 0; i < (uma_size - 256) / 4; i++) ++ { ++ outl((i << 2) | 1, piobase); ++ outl(pphysbase + (i << 12) + 1, piobase + 4); ++ } ++ ++ /* Clear interrupts. */ ++ write32(pmmio + DEIIR, 0xffffffff); ++ write32(pmmio + SDEIIR, 0xffffffff); ++ write32(pmmio + IIR, 0xffffffff); ++ write32(pmmio + IMR, 0xffffffff); ++ write32(pmmio + EIR, 0xffffffff); ++ ++ vga_textmode_init(); ++ ++ /* Enable screen memory. */ ++ vga_sr_write(1, vga_sr_read(1) & ~0x20); ++ ++ return 0; ++ ++} ++ ++/* compare the header of the vga edid header */ ++/* if vga is not connected it should have a correct header */ ++static int vga_connected(u8 *pmmio) { ++ u8 vga_edid[128]; ++ u8 header[8] = {0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; ++ intel_gmbus_read_edid(pmmio + GMBUS0, 2, 0x50, vga_edid, 128); ++ intel_gmbus_stop(pmmio + GMBUS0); ++ for (int i = 0; i < 8; i++) { ++ if (vga_edid[i] != header[i]) { ++ printk(BIOS_DEBUG, "VGA not connected. Using LVDS display\n"); ++ return 0; ++ } ++ } ++ printk(BIOS_SPEW, "VGA display connected\n"); ++ return 1; ++} ++ + #endif + + static void gma_func0_init(struct device *dev) +@@ -423,7 +611,11 @@ static void gma_func0_init(struct device *dev) + ); + + int err; +- err = intel_gma_init(conf, pci_read_config32(dev, 0x5c) & ~0xf, ++ if (vga_connected(mmiobase)) ++ err = intel_gma_init_vga(conf, pci_read_config32(dev, 0x5c) & ~0xf, ++ iobase, mmiobase, graphics_base); ++ else ++ err = intel_gma_init_lvds(conf, pci_read_config32(dev, 0x5c) & ~0xf, + iobase, mmiobase, graphics_base); + if (err == 0) + gfx_set_init_done(1); +-- +2.9.3 + |