Update ivybridge graphics initialization

- Add config options to set backlight registers
- Update powermeter weight tables for IvyBridge GT1 and
add a new table for GT2 SKU
- Fix a few registers used during GPU PM init sequence

Change-Id: I1500bc07e3ba1bc10c77e7856089e716489dc07a
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: http://review.coreboot.org/973
Tested-by: build bot (Jenkins)
This commit is contained in:
Duncan Laurie 2012-04-09 12:05:18 -07:00 committed by Stefan Reinauer
parent c908fc762c
commit dd585b8825
2 changed files with 213 additions and 99 deletions

View File

@ -35,6 +35,9 @@ struct northbridge_intel_sandybridge_config {
u16 gpu_panel_power_down_delay; /* T3 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_on_delay; /* T5 time sequence */
u16 gpu_panel_power_backlight_off_delay; /* Tx time sequence */ u16 gpu_panel_power_backlight_off_delay; /* Tx time sequence */
u32 gpu_cpu_backlight; /* CPU Backlight PWM value */
u32 gpu_pch_backlight; /* PCH Backlight PWM value */
}; };
extern struct chip_operations northbridge_intel_sandybridge_ops; extern struct chip_operations northbridge_intel_sandybridge_ops;

View File

@ -27,6 +27,169 @@
#include "chip.h" #include "chip.h"
#include "sandybridge.h" #include "sandybridge.h"
struct gt_powermeter {
u16 reg;
u32 value;
};
struct gt_powermeter snb_pm_gt1[] = {
{ 0xa200, 0xcc000000 },
{ 0xa204, 0x07000040 },
{ 0xa208, 0x0000fe00 },
{ 0xa20c, 0x00000000 },
{ 0xa210, 0x17000000 },
{ 0xa214, 0x00000021 },
{ 0xa218, 0x0817fe19 },
{ 0xa21c, 0x00000000 },
{ 0xa220, 0x00000000 },
{ 0xa224, 0xcc000000 },
{ 0xa228, 0x07000040 },
{ 0xa22c, 0x0000fe00 },
{ 0xa230, 0x00000000 },
{ 0xa234, 0x17000000 },
{ 0xa238, 0x00000021 },
{ 0xa23c, 0x0817fe19 },
{ 0xa240, 0x00000000 },
{ 0xa244, 0x00000000 },
{ 0xa248, 0x8000421e },
{ 0 }
};
struct gt_powermeter snb_pm_gt2[] = {
{ 0xa200, 0x330000a6 },
{ 0xa204, 0x402d0031 },
{ 0xa208, 0x00165f83 },
{ 0xa20c, 0xf1000000 },
{ 0xa210, 0x00000000 },
{ 0xa214, 0x00160016 },
{ 0xa218, 0x002a002b },
{ 0xa21c, 0x00000000 },
{ 0xa220, 0x00000000 },
{ 0xa224, 0x330000a6 },
{ 0xa228, 0x402d0031 },
{ 0xa22c, 0x00165f83 },
{ 0xa230, 0xf1000000 },
{ 0xa234, 0x00000000 },
{ 0xa238, 0x00160016 },
{ 0xa23c, 0x002a002b },
{ 0xa240, 0x00000000 },
{ 0xa244, 0x00000000 },
{ 0xa248, 0x8000421e },
{ 0 }
};
struct gt_powermeter ivb_pm_gt1[] = {
{ 0xa800, 0x10000000 },
{ 0xa804, 0x00033800 },
{ 0xa808, 0x00000902 },
{ 0xa80c, 0x0c002f00 },
{ 0xa810, 0x12000400 },
{ 0xa814, 0x00000000 },
{ 0xa818, 0x00d20800 },
{ 0xa81c, 0x00000002 },
{ 0xa820, 0x03004b02 },
{ 0xa824, 0x00000600 },
{ 0xa828, 0x07000773 },
{ 0xa82c, 0x00000000 },
{ 0xa830, 0x00010032 },
{ 0xa834, 0x1520040d },
{ 0xa838, 0x00020105 },
{ 0xa83c, 0x00083700 },
{ 0xa840, 0x0000151d },
{ 0xa844, 0x00000000 },
{ 0xa848, 0x20001b00 },
{ 0xa84c, 0x0a000010 },
{ 0xa850, 0x00000000 },
{ 0xa854, 0x00000008 },
{ 0xa858, 0x00000008 },
{ 0xa85c, 0x00000000 },
{ 0xa860, 0x00020000 },
{ 0xa248, 0x0000221e },
{ 0xa900, 0x00000000 },
{ 0xa904, 0x00003500 },
{ 0xa908, 0x00000000 },
{ 0xa90c, 0x0c000000 },
{ 0xa910, 0x12000500 },
{ 0xa914, 0x00000000 },
{ 0xa918, 0x00b20000 },
{ 0xa91c, 0x00000000 },
{ 0xa920, 0x08004b02 },
{ 0xa924, 0x00000200 },
{ 0xa928, 0x07000820 },
{ 0xa92c, 0x00000000 },
{ 0xa930, 0x00030000 },
{ 0xa934, 0x050f020d },
{ 0xa938, 0x00020300 },
{ 0xa93c, 0x00903900 },
{ 0xa940, 0x00000000 },
{ 0xa944, 0x00000000 },
{ 0xa948, 0x20001b00 },
{ 0xa94c, 0x0a000010 },
{ 0xa950, 0x00000000 },
{ 0xa954, 0x00000008 },
{ 0xa960, 0x00110000 },
{ 0xaa3c, 0x00003900 },
{ 0xaa54, 0x00000008 },
{ 0xaa60, 0x00110000 },
{ 0 }
};
struct gt_powermeter ivb_pm_gt2[] = {
{ 0xa800, 0x20000000 },
{ 0xa804, 0x000e3800 },
{ 0xa808, 0x00000806 },
{ 0xa80c, 0x0c002f00 },
{ 0xa810, 0x0c000800 },
{ 0xa814, 0x00000000 },
{ 0xa818, 0x00d20d00 },
{ 0xa81c, 0x000000ff },
{ 0xa820, 0x03004b02 },
{ 0xa824, 0x00000600 },
{ 0xa828, 0x07000773 },
{ 0xa82c, 0x00000000 },
{ 0xa830, 0x00020032 },
{ 0xa834, 0x1520040d },
{ 0xa838, 0x00020105 },
{ 0xa83c, 0x00083700 },
{ 0xa840, 0x000016ff },
{ 0xa844, 0x00000000 },
{ 0xa848, 0xff000000 },
{ 0xa84c, 0x0a000010 },
{ 0xa850, 0x00000004 },
{ 0xa854, 0x00000008 },
{ 0xa858, 0x00000018 },
{ 0xa85c, 0x00000000 },
{ 0xa860, 0x00020000 },
{ 0xa248, 0x0000221e },
{ 0xa900, 0x00000000 },
{ 0xa904, 0x00003800 },
{ 0xa908, 0x00000000 },
{ 0xa90c, 0x0c000000 },
{ 0xa910, 0x12000500 },
{ 0xa914, 0x00000000 },
{ 0xa918, 0x00b20000 },
{ 0xa91c, 0x00000000 },
{ 0xa920, 0x08004b02 },
{ 0xa924, 0x00000200 },
{ 0xa928, 0x07000820 },
{ 0xa92c, 0x00000000 },
{ 0xa930, 0x00030000 },
{ 0xa934, 0x050f020d },
{ 0xa938, 0x00020300 },
{ 0xa93c, 0x00903900 },
{ 0xa940, 0x00000000 },
{ 0xa944, 0x00000000 },
{ 0xa948, 0x20001b00 },
{ 0xa94c, 0x0a000010 },
{ 0xa950, 0x00000000 },
{ 0xa954, 0x00000008 },
{ 0xa960, 0x00110000 },
{ 0xaa3c, 0x00003900 },
{ 0xaa54, 0x00000008 },
{ 0xaa60, 0x00110000 },
{ 0 }
};
/* some vga option roms are used for several chipsets but they only have one /* some vga option roms are used for several chipsets but they only have one
* PCI ID in their header. If we encounter such an option rom, we need to do * PCI ID in their header. If we encounter such an option rom, we need to do
* the mapping ourselfes * the mapping ourselfes
@ -63,6 +226,12 @@ static inline void gtt_write(u32 reg, u32 data)
write32(gtt_res->base + reg, data); write32(gtt_res->base + reg, data);
} }
static inline void gtt_write_powermeter(struct gt_powermeter *pm)
{
for (; pm && pm->reg; pm++)
gtt_write(pm->reg, pm->value);
}
#define GTT_RETRY 1000 #define GTT_RETRY 1000
static int gtt_poll(u32 reg, u32 mask, u32 value) static int gtt_poll(u32 reg, u32 mask, u32 value)
{ {
@ -98,7 +267,7 @@ static void gma_pm_init_pre_vbios(struct device *dev)
} else { } else {
gtt_write(0xa180, 1 << 5); gtt_write(0xa180, 1 << 5);
gtt_write(0xa188, 0xffff0001); gtt_write(0xa188, 0xffff0001);
if (!gtt_poll(0x130090, (1 << 0), (1 << 0))) if (!gtt_poll(0x130040, (1 << 0), (1 << 0)))
return; return;
} }
@ -111,112 +280,35 @@ static void gma_pm_init_pre_vbios(struct device *dev)
if (bridge_silicon_revision() >= IVB_STEP_A0) { if (bridge_silicon_revision() >= IVB_STEP_A0) {
/* Display Reset Acknowledge Settings */ /* Display Reset Acknowledge Settings */
gtt_write(0xa18c, 0x00000001);
reg32 = gtt_read(0x45010); reg32 = gtt_read(0x45010);
reg32 |= (1 << 1) | (1 << 0); reg32 |= (1 << 1) | (1 << 0);
gtt_write(0x45010, reg32); gtt_write(0x45010, reg32);
} }
/* 2: Get GT SKU from GTT+0x911c[13] */ /* 2: Get GT SKU from GTT+0x911c[13] */
reg32 = gtt_read(0x911c);
if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) { if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) {
reg32 = gtt_read(0x911c);
if (reg32 & (1 << 13)) { if (reg32 & (1 << 13)) {
printk(BIOS_DEBUG, "GT1 Power Meter Weights\n"); printk(BIOS_DEBUG, "SNB GT1 Power Meter Weights\n");
gtt_write(0xa200, 0xcc000000); gtt_write_powermeter(snb_pm_gt1);
gtt_write(0xa204, 0x07000040);
gtt_write(0xa208, 0x0000fe00);
gtt_write(0xa20c, 0x00000000);
gtt_write(0xa210, 0x17000000);
gtt_write(0xa214, 0x00000021);
gtt_write(0xa218, 0x0817fe19);
gtt_write(0xa21c, 0x00000000);
gtt_write(0xa220, 0x00000000);
gtt_write(0xa224, 0xcc000000);
gtt_write(0xa228, 0x07000040);
gtt_write(0xa22c, 0x0000fe00);
gtt_write(0xa230, 0x00000000);
gtt_write(0xa234, 0x17000000);
gtt_write(0xa238, 0x00000021);
gtt_write(0xa23c, 0x0817fe19);
gtt_write(0xa240, 0x00000000);
gtt_write(0xa244, 0x00000000);
gtt_write(0xa248, 0x8000421e);
} else { } else {
printk(BIOS_DEBUG, "GT2 Power Meter Weights\n"); printk(BIOS_DEBUG, "SNB GT2 Power Meter Weights\n");
gtt_write(0xa200, 0x330000a6); gtt_write_powermeter(snb_pm_gt2);
gtt_write(0xa204, 0x402d0031);
gtt_write(0xa208, 0x00165f83);
gtt_write(0xa20c, 0xf1000000);
gtt_write(0xa210, 0x00000000);
gtt_write(0xa214, 0x00160016);
gtt_write(0xa218, 0x002a002b);
gtt_write(0xa21c, 0x00000000);
gtt_write(0xa220, 0x00000000);
gtt_write(0xa224, 0x330000a6);
gtt_write(0xa228, 0x402d0031);
gtt_write(0xa22c, 0x00165f83);
gtt_write(0xa230, 0xf1000000);
gtt_write(0xa234, 0x00000000);
gtt_write(0xa238, 0x00160016);
gtt_write(0xa23c, 0x002a002b);
gtt_write(0xa240, 0x00000000);
gtt_write(0xa244, 0x00000000);
gtt_write(0xa248, 0x8000421e);
} }
} else { } else {
printk(BIOS_DEBUG, "IVB GT Power Meter Weights\n"); u32 unit = MCHBAR32(0x5938) & 0xf;
gtt_write(0xa800, 0x00000000); u32 tdp = MCHBAR32(0x5930) & 0x7fff;
gtt_write(0xa804, 0x00023800); tdp /= (1 << unit);
gtt_write(0xa808, 0x00000902);
gtt_write(0xa80c, 0x0c002f00); if ((tdp <= 17) && !(reg32 & (1 << 13))) {
gtt_write(0xa810, 0x12000500); /* <=17W ULV and GT2 SKU */
gtt_write(0xa814, 0x00000000); printk(BIOS_DEBUG, "IVB GT2 Power Meter Weights\n");
gtt_write(0xa818, 0x00b20000); gtt_write_powermeter(ivb_pm_gt2);
gtt_write(0xa81c, 0x00000002); } else {
gtt_write(0xa820, 0x03004b02); /* GT1 SKU */
gtt_write(0xa824, 0x00000600); printk(BIOS_DEBUG, "IVB GT1 Power Meter Weights\n");
gtt_write(0xa828, 0x07000773); gtt_write_powermeter(ivb_pm_gt1);
gtt_write(0xa82c, 0x00000000); }
gtt_write(0xa830, 0x00010000);
gtt_write(0xa834, 0x0510020d);
gtt_write(0xa838, 0x00020100);
gtt_write(0xa83c, 0x00103700);
gtt_write(0xa840, 0x0000001d);
gtt_write(0xa844, 0x00000000);
gtt_write(0xa848, 0x20001b00);
gtt_write(0xa84c, 0x0a000010);
gtt_write(0xa850, 0x00000000);
gtt_write(0xa854, 0x00000008);
gtt_write(0xa858, 0x00000000);
gtt_write(0xa85c, 0x00000000);
gtt_write(0xa860, 0x00040000);
gtt_write(0xa248, 0x0000221e);
gtt_write(0xa900, 0x00000000);
gtt_write(0xa904, 0x00003500);
gtt_write(0xa908, 0x00000000);
gtt_write(0xa90c, 0x0c000000);
gtt_write(0xa910, 0x12000500);
gtt_write(0xa914, 0x00000000);
gtt_write(0xa918, 0x00b20000);
gtt_write(0xa91c, 0x00000000);
gtt_write(0xa920, 0x08004b02);
gtt_write(0xa924, 0x00000400);
gtt_write(0xa928, 0x07000820);
gtt_write(0xa92c, 0x00000000);
gtt_write(0xa930, 0x00030000);
gtt_write(0xa934, 0x050f020d);
gtt_write(0xa938, 0x00020300);
gtt_write(0xa93c, 0x00903900);
gtt_write(0xa940, 0x00000000);
gtt_write(0xa944, 0x00000000);
gtt_write(0xa948, 0x20001b00);
gtt_write(0xa94c, 0x0a000010);
gtt_write(0xa950, 0x00000000);
gtt_write(0xa954, 0x00000008);
gtt_write(0xa960, 0x00110000);
gtt_write(0xaa3c, 0x00003900);
gtt_write(0xaa54, 0x00000008);
gtt_write(0xaa60, 0x00110000);
} }
/* 3: Gear ratio map */ /* 3: Gear ratio map */
@ -339,9 +431,18 @@ static void gma_pm_init_post_vbios(struct device *dev)
printk(BIOS_DEBUG, "GT Power Management Init (post VBIOS)\n"); printk(BIOS_DEBUG, "GT Power Management Init (post VBIOS)\n");
/* 15: Deassert Force Wake */ /* 15: Deassert Force Wake */
gtt_write(0xa18c, gtt_read(0xa18c) & ~1); if (bridge_silicon_revision() < IVB_STEP_C0) {
if (!gtt_poll(0x130090, (1 << 0), (0 << 0))) gtt_write(0xa18c, gtt_read(0xa18c) & ~1);
return; if (!gtt_poll(0x130090, (1 << 0), (0 << 0))) {
return;
}
} else {
gtt_write(0xa188, 0x1fffe);
if (!gtt_poll(0x130040, (1 << 0), (0 << 0))) {
return;
}
gtt_write(0xa188, gtt_read(0xa188) | 1);
}
/* 16: SW RC Control */ /* 16: SW RC Control */
gtt_write(0xa094, 0x00060000); gtt_write(0xa094, 0x00060000);
@ -379,6 +480,16 @@ static void gma_pm_init_post_vbios(struct device *dev)
reg32 |= conf->gpu_panel_power_cycle_delay & 0xff; reg32 |= conf->gpu_panel_power_cycle_delay & 0xff;
gtt_write(0xc7210, reg32); gtt_write(0xc7210, reg32);
} }
/* Enable Backlight if needed */
if (conf->gpu_cpu_backlight) {
gtt_write(0x48250, (1 << 31));
gtt_write(0x48254, conf->gpu_cpu_backlight);
}
if (conf->gpu_pch_backlight) {
gtt_write(0xc8250, (1 << 31));
gtt_write(0xc8254, conf->gpu_pch_backlight);
}
} }
static void gma_func0_init(struct device *dev) static void gma_func0_init(struct device *dev)