Arthur Heymans (arthur@aheymans.xyz) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18141
-gerrit
commit 79eedc7019970cefae4e25fe5cd61502d608ce16 Author: Arthur Heymans arthur@aheymans.xyz Date: Sat Jan 14 22:31:54 2017 +0100
nb/i945/gma.c: Refactor panel setup
This reuses some of gm45 code to set up panel. Panel start and stop delays and pwm frequency can now be set in devicetree. Linux does not make the difference between 945gm and gm45 for panel delays, so it is safe to assume the semantics of those registers are the same.
The core display clock is computed according to "Mobile IntelĀ® 945 Express Chipset Family" Datasheet.
This selects Legacy backlight mode since most targets have some smm code that rely on this.
This sets the same backlight frequency as vendor bios on Thinkpad X60 and T60.
TESTED on Lenovo Thinkpad X60
Change-Id: I1c47b68eecc19624ee534598c22da183bc89425d Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- src/drivers/intel/gma/i915_reg.h | 2 +- src/mainboard/apple/macbook21/devicetree.cb | 7 ++- src/mainboard/lenovo/t60/devicetree.cb | 7 ++- src/mainboard/lenovo/x60/devicetree.cb | 7 ++- src/northbridge/intel/gm45/gma.c | 8 +-- src/northbridge/intel/i945/chip.h | 10 +++- src/northbridge/intel/i945/gma.c | 78 +++++++++++++++++++++++++---- 7 files changed, 99 insertions(+), 20 deletions(-)
diff --git a/src/drivers/intel/gma/i915_reg.h b/src/drivers/intel/gma/i915_reg.h index 2ee5748..dee6865 100644 --- a/src/drivers/intel/gma/i915_reg.h +++ b/src/drivers/intel/gma/i915_reg.h @@ -62,7 +62,7 @@ #define GCFGC 0xf0 /* 915+ only */ #define GC_LOW_FREQUENCY_ENABLE (1 << 7) #define GC_DISPLAY_CLOCK_190_200_MHZ (0 << 4) -#define GC_DISPLAY_CLOCK_333_MHZ (4 << 4) +#define GC_DISPLAY_CLOCK_333_320_MHZ (4 << 4) #define GC_DISPLAY_CLOCK_MASK (7 << 4) #define GM45_GC_RENDER_CLOCK_MASK (0xf << 0) #define GM45_GC_RENDER_CLOCK_266_MHZ (8 << 0) diff --git a/src/mainboard/apple/macbook21/devicetree.cb b/src/mainboard/apple/macbook21/devicetree.cb index f37e768..b6e61eb 100644 --- a/src/mainboard/apple/macbook21/devicetree.cb +++ b/src/mainboard/apple/macbook21/devicetree.cb @@ -22,7 +22,12 @@ chip northbridge/intel/i945
register "gpu_hotplug" = "0x00000220" register "gpu_lvds_use_spread_spectrum_clock" = "1" - register "gpu_backlight" = "0x1290128" + register "pwm_freq" = "180" + register "gpu_panel_power_up_delay" = "250" + register "gpu_panel_power_backlight_on_delay" = "2380" + register "gpu_panel_power_down_delay" = "250" + register "gpu_panel_power_backlight_off_delay" = "2380" + register "gpu_panel_power_cycle_delay" = "2"
device cpu_cluster 0 on chip cpu/intel/socket_mFCPGA478 diff --git a/src/mainboard/lenovo/t60/devicetree.cb b/src/mainboard/lenovo/t60/devicetree.cb index f66455b..6ad054c 100644 --- a/src/mainboard/lenovo/t60/devicetree.cb +++ b/src/mainboard/lenovo/t60/devicetree.cb @@ -22,7 +22,12 @@ chip northbridge/intel/i945
register "gpu_hotplug" = "0x00000220" register "gpu_lvds_use_spread_spectrum_clock" = "1" - register "gpu_backlight" = "0x1280128" + register "pwm_freq" = "275" + register "gpu_panel_power_up_delay" = "250" + register "gpu_panel_power_backlight_on_delay" = "2380" + register "gpu_panel_power_down_delay" = "250" + register "gpu_panel_power_backlight_off_delay" = "2380" + register "gpu_panel_power_cycle_delay" = "2"
device cpu_cluster 0 on chip cpu/intel/socket_mFCPGA478 diff --git a/src/mainboard/lenovo/x60/devicetree.cb b/src/mainboard/lenovo/x60/devicetree.cb index 0ac9273..28b63d3 100644 --- a/src/mainboard/lenovo/x60/devicetree.cb +++ b/src/mainboard/lenovo/x60/devicetree.cb @@ -22,7 +22,12 @@ chip northbridge/intel/i945
register "gpu_hotplug" = "0x00000220" register "gpu_lvds_use_spread_spectrum_clock" = "1" - register "gpu_backlight" = "0x1290128" + register "pwm_freq" = "180" + register "gpu_panel_power_up_delay" = "250" + register "gpu_panel_power_backlight_on_delay" = "2380" + register "gpu_panel_power_down_delay" = "250" + register "gpu_panel_power_backlight_off_delay" = "2380" + register "gpu_panel_power_cycle_delay" = "2"
device cpu_cluster 0 on chip cpu/intel/socket_mFCPGA478 diff --git a/src/northbridge/intel/gm45/gma.c b/src/northbridge/intel/gm45/gma.c index 4886bb2..cbb8451 100644 --- a/src/northbridge/intel/gm45/gma.c +++ b/src/northbridge/intel/gm45/gma.c @@ -203,8 +203,8 @@ static void gma_init_lvds(const struct northbridge_intel_gm45_config *info, printk(BIOS_DEBUG, "Pixel N=%d, M1=%d, M2=%d, P1=%d\n", pixel_n, pixel_m1, pixel_m2, pixel_p1); printk(BIOS_DEBUG, "Pixel clock %d kHz\n", - BASE_FREQUENCY * (5 * (pixel_m1 + 2) + (pixel_m2 + 2) / - (pixel_n + 2) / (pixel_p1 * pixel_p2))); + BASE_FREQUENCY * (5 * (pixel_m1 + 2) + (pixel_m2 + 2)) / + (pixel_n + 2) / (pixel_p1 * pixel_p2));
write32(mmio + LVDS, (hpolarity << 20) | (vpolarity << 21) @@ -479,8 +479,8 @@ static void gma_init_vga(const struct northbridge_intel_gm45_config *info, printk(BIOS_SPEW, "Pixel N=%d, M1=%d, M2=%d, P1=%d, P2=%d\n", pixel_n, pixel_m1, pixel_m2, pixel_p1, pixel_p2); printk(BIOS_SPEW, "Pixel clock %d kHz\n", - BASE_FREQUENCY * (5 * (pixel_m1 + 2) + (pixel_m2 + 2) / - (pixel_n + 2) / (pixel_p1 * pixel_p2))); + BASE_FREQUENCY * (5 * (pixel_m1 + 2) + (pixel_m2 + 2)) / + (pixel_n + 2) / (pixel_p1 * pixel_p2));
mdelay(1); write32(mmio + FP0(0), (pixel_n << 16) diff --git a/src/northbridge/intel/i945/chip.h b/src/northbridge/intel/i945/chip.h index 8eaa5b4..716e291 100644 --- a/src/northbridge/intel/i945/chip.h +++ b/src/northbridge/intel/i945/chip.h @@ -4,8 +4,16 @@ #include <drivers/intel/gma/i915.h>
struct northbridge_intel_i945_config { + /* In units of 100us timer */ + u16 gpu_panel_power_up_delay; /* T1+T2 time sequence */ + u16 gpu_panel_power_down_delay; /* T3 time sequence */ + u16 gpu_panel_power_backlight_on_delay; /* T5 time sequence */ + u16 gpu_panel_power_backlight_off_delay; /* Tx time sequence */ + /* In units of 0.1s based on unit of the reference divider.*/ + u8 gpu_panel_power_cycle_delay; + u32 gpu_hotplug; - u32 gpu_backlight; + u32 pwm_freq; int gpu_lvds_use_spread_spectrum_clock; struct i915_gpu_controller_info gfx; int pci_mmio_size; diff --git a/src/northbridge/intel/i945/gma.c b/src/northbridge/intel/i945/gma.c index b9a37e4..3807cce 100644 --- a/src/northbridge/intel/i945/gma.c +++ b/src/northbridge/intel/i945/gma.c @@ -292,17 +292,6 @@ static int intel_gma_init_lvds(struct northbridge_intel_i945_config *conf, write32(pmmio + DSPSIZE(0), (hactive - 1) | ((vactive - 1) << 16)); write32(pmmio + DSPPOS(0), 0);
- /* Backlight init. */ - write32(pmmio + FW_BLC_SELF, FW_BLC_SELF_EN_MASK); - write32(pmmio + FW_BLC, 0x011d011a); - write32(pmmio + FW_BLC2, 0x00000102); - write32(pmmio + FW_BLC_SELF, FW_BLC_SELF_EN_MASK); - write32(pmmio + FW_BLC_SELF, 0x0001003f); - write32(pmmio + FW_BLC, 0x011d0109); - write32(pmmio + FW_BLC2, 0x00000102); - write32(pmmio + FW_BLC_SELF, FW_BLC_SELF_EN_MASK); - write32(pmmio + BLC_PWM_CTL, conf->gpu_backlight); - edid.bytes_per_line = (edid.bytes_per_line + 63) & ~63; write32(pmmio + DSPADDR(0), 0); write32(pmmio + DSPSURF(0), 0); @@ -579,6 +568,68 @@ static int probe_edid(u8 *pmmio, u8 slave) return 1; }
+static u32 get_cdclk(struct device *const dev) +{ + u16 gcfgc = pci_read_config16(dev, GCFGC); + + if (gcfgc & GC_LOW_FREQUENCY_ENABLE) + return 133333333; + else { + switch (gcfgc & GC_DISPLAY_CLOCK_MASK) { + case GC_DISPLAY_CLOCK_333_320_MHZ: + return 320000000; + default: + case GC_DISPLAY_CLOCK_190_200_MHZ: + return 200000000; + } + } +} + +static u32 freq_to_blc_pwm_ctl(struct device *const dev, + u16 pwm_freq) +{ + u32 blc_mod; + + /* Set duty cycle to 100% due to use of legacy backlight control */ + blc_mod = get_cdclk(dev) / (32 * pwm_freq); + return BLM_LEGACY_MODE | ((blc_mod / 2) << 17) | ((blc_mod / 2) << 1); +} + + +static void panel_setup(void *mmio, struct device *const dev) +{ + const struct northbridge_intel_i945_config *const conf = dev->chip_info; + + u32 reg32; + + /* Setup Panel Power On Delays */ + reg32 = (conf->gpu_panel_power_up_delay & 0x1fff) << 16; + reg32 |= (conf->gpu_panel_power_backlight_on_delay & 0x1fff); + write32(mmio + PP_ON_DELAYS, reg32); + + /* Setup Panel Power Off Delays */ + reg32 = (conf->gpu_panel_power_down_delay & 0x1fff) << 16; + reg32 |= (conf->gpu_panel_power_backlight_off_delay & 0x1fff); + write32(mmio + PP_OFF_DELAYS, reg32); + + /* Setup Panel Power Cycle Delay */ + reg32 = (get_cdclk(dev) / 20000 - 1) << PP_REFERENCE_DIVIDER_SHIFT; + reg32 |= conf->gpu_panel_power_cycle_delay & 0x1f; + write32(mmio + PP_DIVISOR, reg32); + + /* Backlight init. */ + write32(mmio + FW_BLC_SELF, FW_BLC_SELF_EN_MASK); + write32(mmio + FW_BLC, 0x011d011a); + write32(mmio + FW_BLC2, 0x00000102); + write32(mmio + FW_BLC_SELF, FW_BLC_SELF_EN_MASK); + write32(mmio + FW_BLC_SELF, 0x0001003f); + write32(mmio + FW_BLC, 0x011d0109); + write32(mmio + FW_BLC2, 0x00000102); + write32(mmio + FW_BLC_SELF, FW_BLC_SELF_EN_MASK); + if (conf->pwm_freq) + write32(mmio + BLC_PWM_CTL, freq_to_blc_pwm_ctl(dev, + conf->pwm_freq)); +}
static void gma_func0_init(struct device *dev) { @@ -596,6 +647,7 @@ static void gma_func0_init(struct device *dev) pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ if (IS_ENABLED(CONFIG_MAINBOARD_DO_NATIVE_VGA_INIT)) { /* This should probably run before post VBIOS init. */ printk(BIOS_SPEW, "Initializing VGA without OPROM.\n"); @@ -623,6 +675,10 @@ static void gma_func0_init(struct device *dev) err = intel_gma_init_lvds(conf, pci_read_config32(dev, 0x5c) & ~0xf, iobase, mmiobase, graphics_base); + + if (IS_ENABLED(CONFIG_NORTHBRIDGE_INTEL_SUBTYPE_I945GM)) + panel_setup(mmiobase, dev); + if (err == 0) gfx_set_init_done(1); /* Linux relies on VBT for panel info. */