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 082722b0fca450c92d03faa369285238b4a027fb Author: Arthur Heymans arthur@aheymans.xyz Date: Sat Jan 14 22:31:54 2017 +0100
[WIP] nb/i945/gma.c: Set pwm backlight frequency instead of using magic numbers
The core display clock on 945gm is fixed on 400MHz according to linux src.
This assumes that the BLC_PWM_CTL reg has similar semantics as later Intel chipsets namely: pwm_freq = cdclock / (128 * (BLC_PWM_CTL[31:17] << 1)).
It reduces default pwm freq on 945gm board since it was unreasonably high (> 10000Hz). This value should be fine for LED backlit display (1000Hz) but since all those boards have CCFL by default a lower value might be desired (~100Hz).
Most board currently have smm code that rely on legacy mode operation of blacklight duty cycle.
It reuses some gm45 code to set up panel.
UNTESTED
Change-Id: I1c47b68eecc19624ee534598c22da183bc89425d Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- src/mainboard/apple/macbook21/devicetree.cb | 2 +- src/mainboard/lenovo/t60/devicetree.cb | 2 +- src/mainboard/lenovo/x60/devicetree.cb | 2 +- src/northbridge/intel/i945/chip.h | 7 ++- src/northbridge/intel/i945/gma.c | 88 +++++++++++++++++++++++++---- 5 files changed, 86 insertions(+), 15 deletions(-)
diff --git a/src/mainboard/apple/macbook21/devicetree.cb b/src/mainboard/apple/macbook21/devicetree.cb index f37e768..d8a5b40 100644 --- a/src/mainboard/apple/macbook21/devicetree.cb +++ b/src/mainboard/apple/macbook21/devicetree.cb @@ -22,7 +22,7 @@ chip northbridge/intel/i945
register "gpu_hotplug" = "0x00000220" register "gpu_lvds_use_spread_spectrum_clock" = "1" - register "gpu_backlight" = "0x1290128" + register "pwm_freq" = "1000"
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..6ef95d5 100644 --- a/src/mainboard/lenovo/t60/devicetree.cb +++ b/src/mainboard/lenovo/t60/devicetree.cb @@ -22,7 +22,7 @@ chip northbridge/intel/i945
register "gpu_hotplug" = "0x00000220" register "gpu_lvds_use_spread_spectrum_clock" = "1" - register "gpu_backlight" = "0x1280128" + register "pwm_freq" = "1000"
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..1e99379 100644 --- a/src/mainboard/lenovo/x60/devicetree.cb +++ b/src/mainboard/lenovo/x60/devicetree.cb @@ -22,7 +22,7 @@ chip northbridge/intel/i945
register "gpu_hotplug" = "0x00000220" register "gpu_lvds_use_spread_spectrum_clock" = "1" - register "gpu_backlight" = "0x1290128" + register "pwm_freq" = "1000"
device cpu_cluster 0 on chip cpu/intel/socket_mFCPGA478 diff --git a/src/northbridge/intel/i945/chip.h b/src/northbridge/intel/i945/chip.h index 8eaa5b4..5bbda81 100644 --- a/src/northbridge/intel/i945/chip.h +++ b/src/northbridge/intel/i945/chip.h @@ -4,8 +4,13 @@ #include <drivers/intel/gma/i915.h>
struct northbridge_intel_i945_config { + 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 */ + u8 gpu_panel_power_cycle_delay; /* T4 time sequence */ 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..ef57b20 100644 --- a/src/northbridge/intel/i945/gma.c +++ b/src/northbridge/intel/i945/gma.c @@ -46,6 +46,20 @@ #define PGETBL_ENABLED 0x00000001
#define BASE_FREQUENCY 100000 +#define CORE_DISPLAY_CLOCK 400000 +#define DEFAULT_PWM 1000 + +static struct resource *gtt_res = NULL; + +u32 gtt_read(u32 reg) +{ + return read32(res2mmio(gtt_res, reg, 0)); +} + +void gtt_write(u32 reg, u32 data) +{ + write32(res2mmio(gtt_res, reg, 0), data); +}
static int gtt_setup(void *mmiobase) { @@ -292,17 +306,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 +582,64 @@ static int probe_edid(u8 *pmmio, u8 slave) return 1; }
+static u32 freq_to_blc_pwm_ctl(struct device *const dev, + u16 pwm_freq) +{ + u32 blc_mod; + + blc_mod = CORE_DISPLAY_CLOCK / (128 * pwm_freq); + + return BLM_LEGACY_MODE | ((blc_mod / 2) << 17) | ((blc_mod / 2) << 1); +} + + +static void panel_setup(struct device *const dev) +{ + const struct northbridge_intel_i945_config *const conf = dev->chip_info; + + u32 reg32; + + /* Setup Panel Power On Delays */ + reg32 = gtt_read(PP_ON_DELAYS); + if (!reg32) { + reg32 = (conf->gpu_panel_power_up_delay & 0x1fff) << 16; + reg32 |= (conf->gpu_panel_power_backlight_on_delay & 0x1fff); + gtt_write(PP_ON_DELAYS, reg32); + } + + /* Setup Panel Power Off Delays */ + reg32 = gtt_read(PP_OFF_DELAYS); + if (!reg32) { + reg32 = (conf->gpu_panel_power_down_delay & 0x1fff) << 16; + reg32 |= (conf->gpu_panel_power_backlight_off_delay & 0x1fff); + gtt_write(PP_OFF_DELAYS, reg32); + } + + /* Setup Panel Power Cycle Delay */ + if (conf->gpu_panel_power_cycle_delay) { + reg32 = (CORE_DISPLAY_CLOCK / 20000 - 1) + << PP_REFERENCE_DIVIDER_SHIFT; + reg32 |= conf->gpu_panel_power_cycle_delay & 0x1f; + gtt_write(PP_DIVISOR, reg32); + } + + /* Backlight init. */ + gtt_write(FW_BLC_SELF, FW_BLC_SELF_EN_MASK); + gtt_write(FW_BLC, 0x011d011a); + gtt_write(FW_BLC2, 0x00000102); + gtt_write(FW_BLC_SELF, FW_BLC_SELF_EN_MASK); + gtt_write(FW_BLC_SELF, 0x0001003f); + gtt_write(FW_BLC, 0x011d0109); + gtt_write(FW_BLC2, 0x00000102); + gtt_write(FW_BLC_SELF, FW_BLC_SELF_EN_MASK); + if (conf->pwm_freq == 0) { + reg32 = BLM_LEGACY_MODE | 0x01280128; + gtt_write(BLC_PWM_CTL, freq_to_blc_pwm_ctl(dev, DEFAULT_PWM)); + } else { + gtt_write(BLC_PWM_CTL, freq_to_blc_pwm_ctl(dev, + conf->pwm_freq)); + } +}
static void gma_func0_init(struct device *dev) { @@ -596,6 +657,8 @@ static void gma_func0_init(struct device *dev) pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ gtt_res = find_resource(dev, PCI_BASE_ADDRESS_0); + 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 +686,9 @@ static void gma_func0_init(struct device *dev) err = intel_gma_init_lvds(conf, pci_read_config32(dev, 0x5c) & ~0xf, iobase, mmiobase, graphics_base); + + panel_setup(dev); + if (err == 0) gfx_set_init_done(1); /* Linux relies on VBT for panel info. */