Author: mmlr Date: 2011-10-13 11:07:33 +0200 (Thu, 13 Oct 2011) New Revision: 42839 Changeset: https://dev.haiku-os.org/changeset/42839 Modified: haiku/trunk/headers/private/graphics/intel_extreme/intel_extreme.h haiku/trunk/src/add-ons/accelerants/intel_extreme/hooks.cpp haiku/trunk/src/add-ons/accelerants/intel_extreme/mode.cpp haiku/trunk/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp haiku/trunk/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp haiku/trunk/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp Log: * 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. Modified: haiku/trunk/headers/private/graphics/intel_extreme/intel_extreme.h =================================================================== --- haiku/trunk/headers/private/graphics/intel_extreme/intel_extreme.h 2011-10-13 08:43:56 UTC (rev 42838) +++ haiku/trunk/headers/private/graphics/intel_extreme/intel_extreme.h 2011-10-13 09:07:33 UTC (rev 42839) @@ -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,7 +221,60 @@ #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 #define PAGE_TABLE_ENABLED 0x00000001 Modified: haiku/trunk/src/add-ons/accelerants/intel_extreme/hooks.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/intel_extreme/hooks.cpp 2011-10-13 08:43:56 UTC (rev 42838) +++ haiku/trunk/src/add-ons/accelerants/intel_extreme/hooks.cpp 2011-10-13 09:07:33 UTC (rev 42839) @@ -115,7 +115,8 @@ || 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; Modified: haiku/trunk/src/add-ons/accelerants/intel_extreme/mode.cpp =================================================================== --- haiku/trunk/src/add-ons/accelerants/intel_extreme/mode.cpp 2011-10-13 08:43:56 UTC (rev 42838) +++ haiku/trunk/src/add-ons/accelerants/intel_extreme/mode.cpp 2011-10-13 09:07:33 UTC (rev 42839) @@ -132,7 +132,8 @@ } 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 @@ 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 @@ } 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,10 +237,19 @@ // 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 { 10, 1, 10, false, 1, 104, 17, 5}, // min { 30, 3, 10, true, 4, 138, 23, 11}, // max 270000, 1750000, 3500000 @@ -312,8 +324,12 @@ 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 @@ 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 @@ 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 @@ // 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 @@ 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 @@ // 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 @@ | (((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 @@ | (((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 @@ 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 @@ | (((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 @@ & 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 @@ 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 @@ + (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 @@ + (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 @@ // 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 @@ | (((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 @@ 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 @@ ((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 @@ { 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; } Modified: haiku/trunk/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp 2011-10-13 08:43:56 UTC (rev 42838) +++ haiku/trunk/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp 2011-10-13 09:07:33 UTC (rev 42839) @@ -77,9 +77,11 @@ {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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 Modified: haiku/trunk/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp 2011-10-13 08:43:56 UTC (rev 42838) +++ haiku/trunk/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp 2011-10-13 09:07:33 UTC (rev 42839) @@ -69,9 +69,11 @@ {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; Modified: haiku/trunk/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp 2011-10-13 08:43:56 UTC (rev 42838) +++ haiku/trunk/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp 2011-10-13 09:07:33 UTC (rev 42839) @@ -257,6 +257,9 @@ 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);