* Add preliminary support for one SandyBridge mobile integrated graphics device
(the one in my new ThinkPad X1). The PLL is still off a bit so it has a few blurry stripes, but EDID and mode setting basically works. * Starting with IronLake the north/south bridge or (G)MCH/ICH setup was moved into a platform control hub (PCH) which means that many registers previously located in the GMCH are now in the PCH and have a new address. * I'm committing this mostly because this way the additions are more easy to follow. It is a bit messy and I'll clean it up more and possibly make it a bit more generic. Also most of these changes actually apply to IronLake and up and aren't SandyBridge specific, so a few of those additions will still get a broader scope and new chips will be added. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42839 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c6e876fc85
commit
e436a27e5f
@ -18,13 +18,13 @@
|
||||
|
||||
#define VENDOR_ID_INTEL 0x8086
|
||||
|
||||
#define INTEL_TYPE_FAMILY_MASK 0xf000
|
||||
#define INTEL_TYPE_GROUP_MASK 0xfff0
|
||||
#define INTEL_TYPE_MODEL_MASK 0xffff
|
||||
#define INTEL_TYPE_FAMILY_MASK 0x000f0000
|
||||
#define INTEL_TYPE_GROUP_MASK 0x000ffff0
|
||||
#define INTEL_TYPE_MODEL_MASK 0x000fffff
|
||||
// families
|
||||
#define INTEL_TYPE_7xx 0x1000
|
||||
#define INTEL_TYPE_8xx 0x2000
|
||||
#define INTEL_TYPE_9xx 0x4000
|
||||
#define INTEL_TYPE_7xx 0x00010000
|
||||
#define INTEL_TYPE_8xx 0x00020000
|
||||
#define INTEL_TYPE_9xx 0x00040000
|
||||
// groups
|
||||
#define INTEL_TYPE_83x (INTEL_TYPE_8xx | 0x0010)
|
||||
#define INTEL_TYPE_85x (INTEL_TYPE_8xx | 0x0020)
|
||||
@ -34,6 +34,7 @@
|
||||
#define INTEL_TYPE_Gxx (INTEL_TYPE_9xx | 0x0200)
|
||||
#define INTEL_TYPE_G4x (INTEL_TYPE_9xx | 0x0400)
|
||||
#define INTEL_TYPE_IGD (INTEL_TYPE_9xx | 0x0800)
|
||||
#define INTEL_TYPE_SNB (INTEL_TYPE_9xx | 0x1000)
|
||||
// models
|
||||
#define INTEL_TYPE_MOBILE 0x0008
|
||||
#define INTEL_TYPE_915 (INTEL_TYPE_91x)
|
||||
@ -47,6 +48,8 @@
|
||||
#define INTEL_TYPE_GM45 (INTEL_TYPE_G4x | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_IGDG (INTEL_TYPE_IGD)
|
||||
#define INTEL_TYPE_IGDGM (INTEL_TYPE_IGD | INTEL_TYPE_MOBILE)
|
||||
#define INTEL_TYPE_SNBG (INTEL_TYPE_SNB)
|
||||
#define INTEL_TYPE_SNBGM (INTEL_TYPE_SNB | INTEL_TYPE_MOBILE)
|
||||
|
||||
#define DEVICE_NAME "intel_extreme"
|
||||
#define INTEL_ACCELERANT_NAME "intel_extreme.accelerant"
|
||||
@ -218,6 +221,59 @@ struct intel_free_graphics_memory {
|
||||
#define G4X_STOLEN_MEMORY_224MB 0xc0
|
||||
#define G4X_STOLEN_MEMORY_352MB 0xd0
|
||||
|
||||
// PCH - Platform Control Hub - Newer hardware moves from a MCH/ICH based setup
|
||||
// to a PCH based one, that means anything that used to communicate via (G)MCH
|
||||
// registers needs to use different ones on PCH based platforms (Ironlake and
|
||||
// up, SandyBridge, etc.).
|
||||
#define PCH_DE_INTERRUPT_ENABLE 0x4400c // INTEL_INTERRUPT_ENABLED
|
||||
#define PCH_DISPLAY_A_ANALOG_PORT 0xe1100 // INTEL_DISPLAY_A_ANALOG_PORT
|
||||
#define PCH_DISPLAY_LVDS_PORT 0xe1180 // INTEL_DISPLAY_LVDS_PORT
|
||||
#define PCH_I2C_IO_A 0xc5010 // INTEL_I2C_IO_A
|
||||
#define PCH_I2C_IO_C 0xc5018 // INTEL_I2C_IO_C
|
||||
#define PCH_DISPLAY_A_PLL 0xc6014 // INTEL_DISPLAY_A_PLL
|
||||
#define PCH_DISPLAY_B_PLL 0xc6018 // INTEL_DISPLAY_B_PLL
|
||||
#define PCH_DISPLAY_A_PLL_DIVISOR_0 0xc6040 // INTEL_DISPLAY_A_PLL_DIVISOR_0
|
||||
#define PCH_DISPLAY_A_PLL_DIVISOR_1 0xc6044 // INTEL_DISPLAY_A_PLL_DIVISOR_1
|
||||
#define PCH_DISPLAY_B_PLL_DIVISOR_0 0xc6048 // INTEL_DISPLAY_B_PLL_DIVISOR_0
|
||||
#define PCH_DISPLAY_B_PLL_DIVISOR_1 0xc604c // INTEL_DISPLAY_B_PLL_DIVISOR_1
|
||||
#define PCH_TRANSCODER_A_HTOTAL 0xe0000 // INTEL_DISPLAY_A_HTOTAL
|
||||
#define PCH_TRANSCODER_A_HBLANK 0xe0004 // INTEL_DISPLAY_A_HBLANK
|
||||
#define PCH_TRANSCODER_A_HSYNC 0xe0008 // INTEL_DISPLAY_A_HSYNC
|
||||
#define PCH_TRANSCODER_A_VTOTAL 0xe000c // INTEL_DISPLAY_A_VTOTAL
|
||||
#define PCH_TRANSCODER_A_VBLANK 0xe0010 // INTEL_DISPLAY_A_VBLANK
|
||||
#define PCH_TRANSCODER_A_VSYNC 0xe0014 // INTEL_DISPLAY_A_VSYNC
|
||||
#define PCH_TRANSCODER_B_HTOTAL 0xe1000 // INTEL_DISPLAY_B_HTOTAL
|
||||
#define PCH_TRANSCODER_B_HBLANK 0xe1004 // INTEL_DISPLAY_B_HBLANK
|
||||
#define PCH_TRANSCODER_B_HSYNC 0xe1008 // INTEL_DISPLAY_B_HSYNC
|
||||
#define PCH_TRANSCODER_B_VTOTAL 0xe100c // INTEL_DISPLAY_B_VTOTAL
|
||||
#define PCH_TRANSCODER_B_VBLANK 0xe1010 // INTEL_DISPLAY_B_VBLANK
|
||||
#define PCH_TRANSCODER_B_VSYNC 0xe1014 // INTEL_DISPLAY_B_VSYNC
|
||||
|
||||
// SandyBridge (SNB)
|
||||
#define SNB_GRAPHICS_MEMORY_CONTROL 0x50
|
||||
|
||||
#define SNB_STOLEN_MEMORY_MASK 0xf8
|
||||
#define SNB_STOLEN_MEMORY_32MB (1 << 3)
|
||||
#define SNB_STOLEN_MEMORY_64MB (2 << 3)
|
||||
#define SNB_STOLEN_MEMORY_96MB (3 << 3)
|
||||
#define SNB_STOLEN_MEMORY_128MB (4 << 3)
|
||||
#define SNB_STOLEN_MEMORY_160MB (5 << 3)
|
||||
#define SNB_STOLEN_MEMORY_192MB (6 << 3)
|
||||
#define SNB_STOLEN_MEMORY_224MB (7 << 3)
|
||||
#define SNB_STOLEN_MEMORY_256MB (8 << 3)
|
||||
#define SNB_STOLEN_MEMORY_288MB (9 << 3)
|
||||
#define SNB_STOLEN_MEMORY_320MB (10 << 3)
|
||||
#define SNB_STOLEN_MEMORY_352MB (11 << 3)
|
||||
#define SNB_STOLEN_MEMORY_384MB (12 << 3)
|
||||
#define SNB_STOLEN_MEMORY_416MB (13 << 3)
|
||||
#define SNB_STOLEN_MEMORY_448MB (14 << 3)
|
||||
#define SNB_STOLEN_MEMORY_480MB (15 << 3)
|
||||
#define SNB_STOLEN_MEMORY_512MB (16 << 3)
|
||||
|
||||
#define SNB_GTT_SIZE_MASK (3 << 8)
|
||||
#define SNB_GTT_SIZE_NONE (0 << 8)
|
||||
#define SNB_GTT_SIZE_1MB (1 << 8)
|
||||
#define SNB_GTT_SIZE_2MB (2 << 8)
|
||||
|
||||
// graphics page translation table
|
||||
#define INTEL_PAGE_TABLE_CONTROL 0x02020
|
||||
|
@ -115,7 +115,8 @@ get_accelerant_hook(uint32 feature, void *data)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_94x)
|
||||
|| gInfo->shared_info->device_type.IsModel(INTEL_TYPE_965M)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD))
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)
|
||||
|| gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB))
|
||||
return NULL;
|
||||
|
||||
return (void*)intel_allocate_overlay_buffer;
|
||||
|
@ -132,7 +132,8 @@ set_frame_buffer_base()
|
||||
}
|
||||
|
||||
if (sharedInfo.device_type.InGroup(INTEL_TYPE_96x)
|
||||
|| sharedInfo.device_type.InGroup(INTEL_TYPE_G4x)) {
|
||||
|| sharedInfo.device_type.InGroup(INTEL_TYPE_G4x)
|
||||
|| sharedInfo.device_type.InGroup(INTEL_TYPE_SNB)) {
|
||||
write32(baseRegister, mode.v_display_start * sharedInfo.bytes_per_row
|
||||
+ mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8);
|
||||
read32(baseRegister);
|
||||
@ -153,8 +154,10 @@ set_frame_buffer_base()
|
||||
status_t
|
||||
create_mode_list(void)
|
||||
{
|
||||
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
|
||||
|
||||
i2c_bus bus;
|
||||
bus.cookie = (void*)INTEL_I2C_IO_A;
|
||||
bus.cookie = (void*)(isSNB ? PCH_I2C_IO_A : INTEL_I2C_IO_A);
|
||||
bus.set_signals = &set_i2c_signals;
|
||||
bus.get_signals = &get_i2c_signals;
|
||||
ddc2_init_timing(&bus);
|
||||
@ -166,7 +169,7 @@ create_mode_list(void)
|
||||
} else {
|
||||
TRACE(("intel_extreme: getting EDID on port A (analog) failed : %s. "
|
||||
"Trying on port C (lvds)\n", strerror(error)));
|
||||
bus.cookie = (void*)INTEL_I2C_IO_C;
|
||||
bus.cookie = (void*)(isSNB ? PCH_I2C_IO_C : INTEL_I2C_IO_C);
|
||||
error = ddc2_read_edid1(&bus, &gInfo->edid_info, NULL, NULL);
|
||||
if (error == B_OK) {
|
||||
edid_dump(&gInfo->edid_info);
|
||||
@ -234,7 +237,16 @@ get_pll_limits(pll_limits &limits)
|
||||
// Note, the limits are taken from the X driver; they have not yet been
|
||||
// tested
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x)) {
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB)) {
|
||||
// TODO: support LVDS output limits as well
|
||||
static const pll_limits kLimits = {
|
||||
// p, p1, p2, high, n, m, m1, m2
|
||||
{ 5, 1, 10, false, 1, 79, 12, 5}, // min
|
||||
{ 80, 8, 5, true, 5, 127, 22, 9}, // max
|
||||
225000, 1760000, 3510000
|
||||
};
|
||||
limits = kLimits;
|
||||
} else if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x)) {
|
||||
// TODO: support LVDS output limits as well
|
||||
static const pll_limits kLimits = {
|
||||
// p, p1, p2, high, n, m, m1, m2
|
||||
@ -312,8 +324,12 @@ compute_pll_divisors(const display_mode ¤t, pll_divisors& divisors,
|
||||
|
||||
TRACE(("required MHz: %g\n", requestedPixelClock));
|
||||
|
||||
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
|
||||
|
||||
if (isLVDS) {
|
||||
if ((read32(INTEL_DISPLAY_LVDS_PORT) & LVDS_CLKB_POWER_MASK)
|
||||
int targetRegister
|
||||
= isSNB ? PCH_DISPLAY_LVDS_PORT : INTEL_DISPLAY_LVDS_PORT;
|
||||
if ((read32(targetRegister) & LVDS_CLKB_POWER_MASK)
|
||||
== LVDS_CLKB_POWER_UP)
|
||||
divisors.post2 = LVDS_POST2_RATE_FAST;
|
||||
else
|
||||
@ -402,6 +418,26 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister)
|
||||
vSyncRegister = INTEL_DISPLAY_B_VSYNC;
|
||||
imageSizeRegister = INTEL_DISPLAY_B_IMAGE_SIZE;
|
||||
controlRegister = INTEL_DISPLAY_B_CONTROL;
|
||||
} else if (pllRegister == PCH_DISPLAY_A_PLL) {
|
||||
pllDivisor = read32((pll & DISPLAY_PLL_DIVISOR_1) != 0
|
||||
? PCH_DISPLAY_A_PLL_DIVISOR_1 : PCH_DISPLAY_A_PLL_DIVISOR_0);
|
||||
|
||||
hTotalRegister = PCH_TRANSCODER_A_HTOTAL;
|
||||
vTotalRegister = PCH_TRANSCODER_A_VTOTAL;
|
||||
hSyncRegister = PCH_TRANSCODER_A_HSYNC;
|
||||
vSyncRegister = PCH_TRANSCODER_A_VSYNC;
|
||||
imageSizeRegister = INTEL_DISPLAY_A_IMAGE_SIZE;
|
||||
controlRegister = INTEL_DISPLAY_A_CONTROL;
|
||||
} else if (pllRegister == PCH_DISPLAY_B_PLL) {
|
||||
pllDivisor = read32((pll & DISPLAY_PLL_DIVISOR_1) != 0
|
||||
? PCH_DISPLAY_B_PLL_DIVISOR_1 : PCH_DISPLAY_B_PLL_DIVISOR_0);
|
||||
|
||||
hTotalRegister = PCH_TRANSCODER_B_HTOTAL;
|
||||
vTotalRegister = PCH_TRANSCODER_B_VTOTAL;
|
||||
hSyncRegister = PCH_TRANSCODER_B_HSYNC;
|
||||
vSyncRegister = PCH_TRANSCODER_B_VSYNC;
|
||||
imageSizeRegister = INTEL_DISPLAY_B_IMAGE_SIZE;
|
||||
controlRegister = INTEL_DISPLAY_B_CONTROL;
|
||||
} else {
|
||||
// TODO: not supported
|
||||
return;
|
||||
@ -529,9 +565,12 @@ retrieve_current_mode(display_mode& mode, uint32 pllRegister)
|
||||
void
|
||||
save_lvds_mode(void)
|
||||
{
|
||||
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
|
||||
|
||||
// dump currently programmed mode.
|
||||
display_mode biosMode;
|
||||
retrieve_current_mode(biosMode, INTEL_DISPLAY_B_PLL);
|
||||
retrieve_current_mode(biosMode,
|
||||
isSNB ? PCH_DISPLAY_B_PLL : INTEL_DISPLAY_B_PLL);
|
||||
gInfo->lvds_panel_mode = biosMode;
|
||||
}
|
||||
|
||||
@ -645,7 +684,7 @@ intel_set_display_mode(display_mode *mode)
|
||||
// centering, since the data from propose_display_mode will not actually be
|
||||
// used as is in this case.
|
||||
if (sanitize_display_mode(target)) {
|
||||
TRACE(("intel_extreme: invalid mode set!"));
|
||||
TRACE(("intel_extreme: invalid mode set!\n"));
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
@ -710,6 +749,9 @@ if (first) {
|
||||
write32(INTEL_VGA_DISPLAY_CONTROL, VGA_DISPLAY_DISABLED);
|
||||
read32(INTEL_VGA_DISPLAY_CONTROL);
|
||||
|
||||
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
|
||||
int targetRegister;
|
||||
|
||||
if ((gInfo->head_mode & HEAD_MODE_B_DIGITAL) != 0) {
|
||||
// For LVDS panels, we actually always set the native mode in hardware
|
||||
// Then we use the panel fitter to scale the picture to that.
|
||||
@ -761,9 +803,11 @@ if (first) {
|
||||
|
||||
// Compute bitmask from p1 value
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
|
||||
dpll |= (1 << (divisors.post1 - 1)) << DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT;
|
||||
dpll |= (1 << (divisors.post1 - 1))
|
||||
<< DISPLAY_PLL_IGD_POST1_DIVISOR_SHIFT;
|
||||
} else {
|
||||
dpll |= (1 << (divisors.post1 - 1)) << DISPLAY_PLL_POST1_DIVISOR_SHIFT;
|
||||
dpll |= (1 << (divisors.post1 - 1))
|
||||
<< DISPLAY_PLL_POST1_DIVISOR_SHIFT;
|
||||
}
|
||||
switch (divisors.post2) {
|
||||
case 5:
|
||||
@ -785,7 +829,8 @@ if (first) {
|
||||
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
|
||||
} else {
|
||||
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
|
||||
write32(isSNB ? PCH_DISPLAY_B_PLL_DIVISOR_0
|
||||
: INTEL_DISPLAY_B_PLL_DIVISOR_0,
|
||||
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_N_DIVISOR_MASK)
|
||||
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT)
|
||||
@ -793,13 +838,16 @@ if (first) {
|
||||
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_M2_DIVISOR_MASK));
|
||||
}
|
||||
write32(INTEL_DISPLAY_B_PLL, dpll & ~DISPLAY_PLL_ENABLED);
|
||||
read32(INTEL_DISPLAY_B_PLL);
|
||||
targetRegister = isSNB ? PCH_DISPLAY_B_PLL : INTEL_DISPLAY_B_PLL;
|
||||
write32(targetRegister, dpll & ~DISPLAY_PLL_ENABLED);
|
||||
read32(targetRegister);
|
||||
spin(150);
|
||||
}
|
||||
|
||||
uint32 lvds = read32(INTEL_DISPLAY_LVDS_PORT)
|
||||
| LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
|
||||
targetRegister
|
||||
= isSNB ? PCH_DISPLAY_LVDS_PORT : INTEL_DISPLAY_LVDS_PORT;
|
||||
uint32 lvds = read32(targetRegister) | LVDS_PORT_EN
|
||||
| LVDS_A0A2_CLKA_POWER_UP | LVDS_PIPEB_SELECT;
|
||||
|
||||
lvds |= LVDS_18BIT_DITHER;
|
||||
// TODO: do not do this if the connected panel is 24-bit
|
||||
@ -815,8 +863,8 @@ if (first) {
|
||||
else
|
||||
lvds &= ~( LVDS_B0B3PAIRS_POWER_UP | LVDS_CLKB_POWER_UP);
|
||||
|
||||
write32(INTEL_DISPLAY_LVDS_PORT, lvds);
|
||||
read32(INTEL_DISPLAY_LVDS_PORT);
|
||||
write32(targetRegister, lvds);
|
||||
read32(targetRegister);
|
||||
|
||||
if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_IGD)) {
|
||||
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
|
||||
@ -825,7 +873,8 @@ if (first) {
|
||||
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
|
||||
} else {
|
||||
write32(INTEL_DISPLAY_B_PLL_DIVISOR_0,
|
||||
write32(isSNB ? PCH_DISPLAY_B_PLL_DIVISOR_0
|
||||
: INTEL_DISPLAY_B_PLL_DIVISOR_0,
|
||||
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_N_DIVISOR_MASK)
|
||||
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT)
|
||||
@ -834,8 +883,9 @@ if (first) {
|
||||
& DISPLAY_PLL_M2_DIVISOR_MASK));
|
||||
}
|
||||
|
||||
write32(INTEL_DISPLAY_B_PLL, dpll);
|
||||
read32(INTEL_DISPLAY_B_PLL);
|
||||
targetRegister = isSNB ? PCH_DISPLAY_B_PLL : INTEL_DISPLAY_B_PLL;
|
||||
write32(targetRegister, dpll);
|
||||
read32(targetRegister);
|
||||
|
||||
// Wait for the clocks to stabilize
|
||||
spin(150);
|
||||
@ -855,9 +905,9 @@ if (first) {
|
||||
write32(INTEL_DISPLAY_B_PLL_MULTIPLIER_DIVISOR, (0 << 24)
|
||||
| ((pixelMultiply - 1) << 8));
|
||||
} else
|
||||
write32(INTEL_DISPLAY_B_PLL, dpll);
|
||||
write32(targetRegister, dpll);
|
||||
|
||||
read32(INTEL_DISPLAY_B_PLL);
|
||||
read32(targetRegister);
|
||||
spin(150);
|
||||
|
||||
// update timing parameters
|
||||
@ -878,14 +928,14 @@ if (first) {
|
||||
+ (hardwareTarget.timing.h_total
|
||||
- target.timing.h_display) / 2;
|
||||
|
||||
write32(INTEL_DISPLAY_B_HTOTAL,
|
||||
write32(isSNB ? PCH_TRANSCODER_B_HTOTAL : INTEL_DISPLAY_B_HTOTAL,
|
||||
((uint32)(hardwareTarget.timing.h_total - 1) << 16)
|
||||
| ((uint32)target.timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_B_HBLANK,
|
||||
write32(isSNB ? PCH_TRANSCODER_B_HBLANK : INTEL_DISPLAY_B_HBLANK,
|
||||
((uint32)(hardwareTarget.timing.h_total - borderWidth / 2 - 1)
|
||||
<< 16)
|
||||
| ((uint32)target.timing.h_display + borderWidth / 2 - 1));
|
||||
write32(INTEL_DISPLAY_B_HSYNC,
|
||||
write32(isSNB ? PCH_TRANSCODER_B_HSYNC : INTEL_DISPLAY_B_HSYNC,
|
||||
((uint32)(syncCenter + syncWidth / 2 - 1) << 16)
|
||||
| ((uint32)syncCenter - syncWidth / 2 - 1));
|
||||
|
||||
@ -899,16 +949,16 @@ if (first) {
|
||||
+ (hardwareTarget.timing.v_total
|
||||
- target.timing.v_display) / 2;
|
||||
|
||||
write32(INTEL_DISPLAY_B_VTOTAL,
|
||||
write32(isSNB ? PCH_TRANSCODER_B_VTOTAL : INTEL_DISPLAY_B_VTOTAL,
|
||||
((uint32)(hardwareTarget.timing.v_total - 1) << 16)
|
||||
| ((uint32)target.timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_B_VBLANK,
|
||||
write32(isSNB ? PCH_TRANSCODER_B_VBLANK : INTEL_DISPLAY_B_VBLANK,
|
||||
((uint32)(hardwareTarget.timing.v_total - borderHeight / 2 - 1)
|
||||
<< 16)
|
||||
| ((uint32)target.timing.v_display
|
||||
+ borderHeight / 2 - 1));
|
||||
write32(INTEL_DISPLAY_B_VSYNC, ((uint32)(syncCenter
|
||||
+ syncHeight / 2 - 1) << 16)
|
||||
write32(isSNB ? PCH_TRANSCODER_B_VSYNC : INTEL_DISPLAY_B_VSYNC,
|
||||
((uint32)(syncCenter + syncHeight / 2 - 1) << 16)
|
||||
| ((uint32)syncCenter - syncHeight / 2 - 1));
|
||||
|
||||
// This is useful for debugging: it sets the border to red, so you
|
||||
@ -916,23 +966,23 @@ if (first) {
|
||||
// sync)
|
||||
// write32(0x61020, 0x00FF0000);
|
||||
} else {
|
||||
write32(INTEL_DISPLAY_B_HTOTAL,
|
||||
write32(isSNB ? PCH_TRANSCODER_B_HTOTAL : INTEL_DISPLAY_B_HTOTAL,
|
||||
((uint32)(target.timing.h_total - 1) << 16)
|
||||
| ((uint32)target.timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_B_HBLANK,
|
||||
write32(isSNB ? PCH_TRANSCODER_B_HBLANK : INTEL_DISPLAY_B_HBLANK,
|
||||
((uint32)(target.timing.h_total - 1) << 16)
|
||||
| ((uint32)target.timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_B_HSYNC, (
|
||||
(uint32)(target.timing.h_sync_end - 1) << 16)
|
||||
write32(isSNB ? PCH_TRANSCODER_B_HSYNC : INTEL_DISPLAY_B_HSYNC,
|
||||
((uint32)(target.timing.h_sync_end - 1) << 16)
|
||||
| ((uint32)target.timing.h_sync_start - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_B_VTOTAL,
|
||||
write32(isSNB ? PCH_TRANSCODER_B_VTOTAL : INTEL_DISPLAY_B_VTOTAL,
|
||||
((uint32)(target.timing.v_total - 1) << 16)
|
||||
| ((uint32)target.timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_B_VBLANK,
|
||||
write32(isSNB ? PCH_TRANSCODER_B_VBLANK : INTEL_DISPLAY_B_VBLANK,
|
||||
((uint32)(target.timing.v_total - 1) << 16)
|
||||
| ((uint32)target.timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_B_VSYNC, (
|
||||
write32(isSNB ? PCH_TRANSCODER_B_VSYNC : INTEL_DISPLAY_B_VSYNC, (
|
||||
(uint32)(target.timing.v_sync_end - 1) << 16)
|
||||
| ((uint32)target.timing.v_sync_start - 1));
|
||||
}
|
||||
@ -966,7 +1016,8 @@ if (first) {
|
||||
| (((divisors.m2 - 2) << DISPLAY_PLL_M2_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_IGD_M2_DIVISOR_MASK));
|
||||
} else {
|
||||
write32(INTEL_DISPLAY_A_PLL_DIVISOR_0,
|
||||
write32(isSNB ? PCH_DISPLAY_A_PLL_DIVISOR_0
|
||||
: INTEL_DISPLAY_A_PLL_DIVISOR_0,
|
||||
(((divisors.n - 2) << DISPLAY_PLL_N_DIVISOR_SHIFT)
|
||||
& DISPLAY_PLL_N_DIVISOR_MASK)
|
||||
| (((divisors.m1 - 2) << DISPLAY_PLL_M1_DIVISOR_SHIFT)
|
||||
@ -1008,31 +1059,32 @@ if (first) {
|
||||
pll |= DISPLAY_PLL_POST1_DIVIDE_2;
|
||||
}
|
||||
|
||||
write32(INTEL_DISPLAY_A_PLL, pll);
|
||||
read32(INTEL_DISPLAY_A_PLL);
|
||||
targetRegister = isSNB ? PCH_DISPLAY_A_PLL : INTEL_DISPLAY_A_PLL;
|
||||
write32(targetRegister, pll);
|
||||
read32(targetRegister);
|
||||
spin(150);
|
||||
write32(INTEL_DISPLAY_A_PLL, pll);
|
||||
read32(INTEL_DISPLAY_A_PLL);
|
||||
write32(targetRegister, pll);
|
||||
read32(targetRegister);
|
||||
spin(150);
|
||||
|
||||
// update timing parameters
|
||||
write32(INTEL_DISPLAY_A_HTOTAL,
|
||||
write32(isSNB ? PCH_TRANSCODER_A_HTOTAL : INTEL_DISPLAY_A_HTOTAL,
|
||||
((uint32)(target.timing.h_total - 1) << 16)
|
||||
| ((uint32)target.timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_A_HBLANK,
|
||||
write32(isSNB ? PCH_TRANSCODER_A_HBLANK : INTEL_DISPLAY_A_HBLANK,
|
||||
((uint32)(target.timing.h_total - 1) << 16)
|
||||
| ((uint32)target.timing.h_display - 1));
|
||||
write32(INTEL_DISPLAY_A_HSYNC,
|
||||
write32(isSNB ? PCH_TRANSCODER_A_HSYNC : INTEL_DISPLAY_A_HSYNC,
|
||||
((uint32)(target.timing.h_sync_end - 1) << 16)
|
||||
| ((uint32)target.timing.h_sync_start - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_A_VTOTAL,
|
||||
write32(isSNB ? PCH_TRANSCODER_A_VTOTAL : INTEL_DISPLAY_A_VTOTAL,
|
||||
((uint32)(target.timing.v_total - 1) << 16)
|
||||
| ((uint32)target.timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_A_VBLANK,
|
||||
write32(isSNB ? PCH_TRANSCODER_A_VBLANK : INTEL_DISPLAY_A_VBLANK,
|
||||
((uint32)(target.timing.v_total - 1) << 16)
|
||||
| ((uint32)target.timing.v_display - 1));
|
||||
write32(INTEL_DISPLAY_A_VSYNC,
|
||||
write32(isSNB ? PCH_TRANSCODER_A_VSYNC : INTEL_DISPLAY_A_VSYNC,
|
||||
((uint32)(target.timing.v_sync_end - 1) << 16)
|
||||
| ((uint32)target.timing.v_sync_start - 1));
|
||||
|
||||
@ -1040,8 +1092,10 @@ if (first) {
|
||||
((uint32)(target.timing.h_display - 1) << 16)
|
||||
| ((uint32)target.timing.v_display - 1));
|
||||
|
||||
write32(INTEL_DISPLAY_A_ANALOG_PORT,
|
||||
(read32(INTEL_DISPLAY_A_ANALOG_PORT)
|
||||
targetRegister
|
||||
= isSNB ? PCH_DISPLAY_A_ANALOG_PORT : INTEL_DISPLAY_A_ANALOG_PORT;
|
||||
write32(targetRegister,
|
||||
(read32(targetRegister)
|
||||
& ~(DISPLAY_MONITOR_POLARITY_MASK
|
||||
| DISPLAY_MONITOR_VGA_POLARITY))
|
||||
| ((target.timing.flags & B_POSITIVE_HSYNC) != 0
|
||||
@ -1097,7 +1151,9 @@ intel_get_display_mode(display_mode *_currentMode)
|
||||
{
|
||||
TRACE(("intel_get_display_mode()\n"));
|
||||
|
||||
retrieve_current_mode(*_currentMode, INTEL_DISPLAY_A_PLL);
|
||||
bool isSNB = gInfo->shared_info->device_type.InGroup(INTEL_TYPE_SNB);
|
||||
retrieve_current_mode(*_currentMode,
|
||||
isSNB ? PCH_DISPLAY_A_PLL : INTEL_DISPLAY_A_PLL);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -77,9 +77,11 @@ const struct supported_device {
|
||||
{0x2e30, 0x2e32, INTEL_TYPE_G45, "G41"},
|
||||
{0x2e40, 0x2e42, INTEL_TYPE_G45, "B43"},
|
||||
{0x2e90, 0x2e92, INTEL_TYPE_G45, "B43"},
|
||||
|
||||
|
||||
{0xa000, 0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"},
|
||||
{0xa010, 0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"},
|
||||
|
||||
{0x0104, 0x0126, INTEL_TYPE_SNBGM, "SNBGM"},
|
||||
};
|
||||
|
||||
struct intel_info {
|
||||
@ -131,8 +133,11 @@ static void
|
||||
determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize)
|
||||
{
|
||||
// read stolen memory from the PCI configuration of the PCI bridge
|
||||
uint16 memoryConfig = get_pci_config(info.bridge,
|
||||
INTEL_GRAPHICS_MEMORY_CONTROL, 2);
|
||||
uint8 controlRegister = INTEL_GRAPHICS_MEMORY_CONTROL;
|
||||
if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB)
|
||||
controlRegister = SNB_GRAPHICS_MEMORY_CONTROL;
|
||||
|
||||
uint16 memoryConfig = get_pci_config(info.bridge, controlRegister, 2);
|
||||
size_t memorySize = 1 << 20; // 1 MB
|
||||
gttSize = 0;
|
||||
stolenSize = 0;
|
||||
@ -178,6 +183,18 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize)
|
||||
gttSize = 4 << 20;
|
||||
break;
|
||||
}
|
||||
} else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) {
|
||||
switch (memoryConfig & SNB_GTT_SIZE_MASK) {
|
||||
case SNB_GTT_SIZE_NONE:
|
||||
gttSize = 0;
|
||||
break;
|
||||
case SNB_GTT_SIZE_1MB:
|
||||
gttSize = 1 << 20;
|
||||
break;
|
||||
case SNB_GTT_SIZE_2MB:
|
||||
gttSize = 2 << 20;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// older models have the GTT as large as their frame buffer mapping
|
||||
// TODO: check if the i9xx version works with the i8xx chips as well
|
||||
@ -191,7 +208,7 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize)
|
||||
} else if ((info.type & INTEL_TYPE_9xx) != 0)
|
||||
frameBufferSize = info.display.u.h0.base_register_sizes[2];
|
||||
|
||||
TRACE(("frame buffer size %lu MB\n", frameBufferSize >> 20));
|
||||
TRACE("frame buffer size %lu MB\n", frameBufferSize >> 20);
|
||||
gttSize = frameBufferSize / 1024;
|
||||
}
|
||||
|
||||
@ -214,6 +231,57 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize)
|
||||
memorySize *= 8;
|
||||
break;
|
||||
}
|
||||
} else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) {
|
||||
switch (memoryConfig & SNB_STOLEN_MEMORY_MASK) {
|
||||
case SNB_STOLEN_MEMORY_32MB:
|
||||
memorySize *= 32;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_64MB:
|
||||
memorySize *= 64;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_96MB:
|
||||
memorySize *= 96;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_128MB:
|
||||
memorySize *= 128;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_160MB:
|
||||
memorySize *= 160;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_192MB:
|
||||
memorySize *= 192;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_224MB:
|
||||
memorySize *= 224;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_256MB:
|
||||
memorySize *= 256;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_288MB:
|
||||
memorySize *= 288;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_320MB:
|
||||
memorySize *= 320;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_352MB:
|
||||
memorySize *= 352;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_384MB:
|
||||
memorySize *= 384;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_416MB:
|
||||
memorySize *= 416;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_448MB:
|
||||
memorySize *= 448;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_480MB:
|
||||
memorySize *= 480;
|
||||
break;
|
||||
case SNB_STOLEN_MEMORY_512MB:
|
||||
memorySize *= 512;
|
||||
break;
|
||||
}
|
||||
} else if (info.type == INTEL_TYPE_85x
|
||||
|| (info.type & INTEL_TYPE_9xx) == INTEL_TYPE_9xx) {
|
||||
switch (memoryConfig & STOLEN_MEMORY_MASK) {
|
||||
@ -325,7 +393,8 @@ intel_map(intel_info &info)
|
||||
return B_ERROR;
|
||||
|
||||
if ((info.type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) {
|
||||
if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x) {
|
||||
if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x
|
||||
|| (info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_SNB) {
|
||||
info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex]
|
||||
+ (2UL << 20);
|
||||
} else
|
||||
|
@ -69,9 +69,11 @@ const struct supported_device {
|
||||
{0x2e32, INTEL_TYPE_G45, "G41"},
|
||||
{0x2e42, INTEL_TYPE_G45, "B43"},
|
||||
{0x2e92, INTEL_TYPE_G45, "B43"},
|
||||
|
||||
|
||||
{0xa001, INTEL_TYPE_IGDG, "Atom_Dx10"},
|
||||
{0xa011, INTEL_TYPE_IGDGM, "Atom_N4x0"},
|
||||
|
||||
{0x0126, INTEL_TYPE_SNBGM, "SNBGM"},
|
||||
};
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
@ -257,6 +257,9 @@ intel_extreme_init(intel_info &info)
|
||||
if (info.pci->device_id == 0x2a02 || info.pci->device_id == 0x2a12) {
|
||||
dprintf("i965GM/i965GME quirk\n");
|
||||
write32(info.registers + 0x6204, (1L << 29));
|
||||
} else if (info.device_type.InGroup(INTEL_TYPE_SNB)) {
|
||||
dprintf("SNB clock gating\n");
|
||||
write32(info.registers + 0x42020, (1L << 28) | (1L << 7) | (1L << 5));
|
||||
} else if (info.device_type.InGroup(INTEL_TYPE_G4x)) {
|
||||
dprintf("G4x clock gating\n");
|
||||
write32(info.registers + 0x6204, 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user