From dfdfbd3eefeb8aff04b7e8e2d6ebb46a51fe24ad Mon Sep 17 00:00:00 2001 From: Brecht Machiels Date: Fri, 23 Oct 2009 23:03:49 +0000 Subject: [PATCH] * added support for GM45 (might work for other chips in the G4 series) * added header for dealing with binary numbers and bitmasks (C++ templates) these "macro's" might not work well for long words, though git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33749 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../graphics/intel_extreme/intel_extreme.h | 44 ++++++++++- headers/private/shared/binary-utils.h | 77 +++++++++++++++++++ src/add-ons/accelerants/intel_extreme/Jamfile | 1 + .../accelerants/intel_extreme/mode.cpp | 15 +++- src/add-ons/kernel/busses/agp_gart/Jamfile | 1 + .../kernel/busses/agp_gart/intel_gart.cpp | 73 +++++++++++++++++- .../drivers/graphics/intel_extreme/Jamfile | 1 + .../drivers/graphics/intel_extreme/driver.cpp | 1 + .../graphics/intel_extreme/intel_extreme.cpp | 14 ++++ 9 files changed, 220 insertions(+), 7 deletions(-) create mode 100644 headers/private/shared/binary-utils.h diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 3fe8c8ddc8..0937c4b209 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -9,6 +9,7 @@ #define INTEL_EXTREME_H +#include "binary-utils.h" #include "lock.h" #include @@ -32,6 +33,7 @@ #define INTEL_TYPE_94x (INTEL_TYPE_9xx | 0x0080) #define INTEL_TYPE_96x (INTEL_TYPE_9xx | 0x0100) #define INTEL_TYPE_Gxx (INTEL_TYPE_9xx | 0x0200) +#define INTEL_TYPE_G4x (INTEL_TYPE_9xx | 0x0400) // models #define INTEL_TYPE_MOBILE 0x0008 #define INTEL_TYPE_915 (INTEL_TYPE_91x) @@ -40,6 +42,8 @@ #define INTEL_TYPE_965 (INTEL_TYPE_96x) #define INTEL_TYPE_965M (INTEL_TYPE_96x | INTEL_TYPE_MOBILE) #define INTEL_TYPE_G33 (INTEL_TYPE_Gxx) +#define INTEL_TYPE_G45 (INTEL_TYPE_G4x) +#define INTEL_TYPE_GM45 (INTEL_TYPE_G4x | INTEL_TYPE_MOBILE) #define DEVICE_NAME "intel_extreme" #define INTEL_ACCELERANT_NAME "intel_extreme.accelerant" @@ -179,13 +183,33 @@ struct intel_free_graphics_memory { // Register definitions, taken from X driver // PCI bridge memory management -#define INTEL_GRAPHICS_MEMORY_CONTROL 0x52 +#define INTEL_GRAPHICS_MEMORY_CONTROL 0x52 // GGC - (G)MCH Graphics Control Register #define MEMORY_CONTROL_ENABLED 0x0004 #define MEMORY_MASK 0x0001 #define STOLEN_MEMORY_MASK 0x0070 #define i965_GTT_MASK 0x000e #define G33_GTT_MASK 0x0300 +#define G4X_GGC_GGMS_MASK BITMASK(11,8) +#define G4X_GGC_GMS_MASK BITMASK(7,4) // also for G33, but + // probably not for + // older chips +#define G4X_GGMS_NONE (BINARY(0000) << 8) +#define G4X_GGMS_NO_IVT_1M (BINARY(0001) << 8) +#define G4X_GGMS_NO_IVT_2M (BINARY(0011) << 8) +#define G4X_GGMS_IVT_2M (BINARY(1001) << 8) +#define G4X_GGMS_IVT_3M (BINARY(1010) << 8) +#define G4X_GGMS_IVT_4M (BINARY(1011) << 8) + +#define G4X_GMS_32MB (BINARY(0101) << 4) +#define G4X_GMS_64MB (BINARY(0111) << 4) +#define G4X_GMS_128MB (BINARY(1000) << 4) +#define G4X_GMS_256MB (BINARY(1001) << 4) +#define G4X_GMS_96MB (BINARY(1010) << 4) +#define G4X_GMS_160MB (BINARY(1011) << 4) +#define G4X_GMS_224MB (BINARY(1100) << 4) +#define G4X_GMS_352MB (BINARY(1101) << 4) + // models i830 and up #define i830_LOCAL_MEMORY_ONLY 0x10 #define i830_STOLEN_512K 0x20 @@ -220,6 +244,24 @@ struct intel_free_graphics_memory { #define i965_GTT_512K (0 << 1) #define G33_GTT_1M (1 << 8) #define G33_GTT_2M (2 << 8) + +#define G4X_GTTMMADR 0x10 +#define G4X_GTTMMADR_MBA_MASK BITMASK(35,22) +#define G4X_GTTMMADR_MT_MASK BITMASK(2,2) +#define G4X_MMIO_SIZE (512ULL << 10) + +#define G4X_GMADR 0x18 +#define G4X_GMADR_MBA_512MB_MASK BITMASK(35,29) +#define G4X_GMADR_MBA_256MB_MASK BITMASK(35,28) +#define G4X_GMADR_AM_512MB_MASK BITMASK(28,4) +#define G4X_GMADR_AM_256MB_MASK BITMASK(27,4) +#define G4X_GMADR_MT_MASK BITMASK(2,2) + +#define G4X_MSAC 0x66 +#define G4X_MSAC_LHSAS_MASK BITMASK(2,1) +#define G4X_LHSAS_512MB (BINARY(11) << 1) +#define G4X_LHSAS_256MB (BINARY(01) << 1) + #define GTT_ENTRY_VALID 0x01 #define GTT_ENTRY_LOCAL_MEMORY 0x02 #define GTT_PAGE_SHIFT 12 diff --git a/headers/private/shared/binary-utils.h b/headers/private/shared/binary-utils.h new file mode 100644 index 0000000000..6aa2f2b510 --- /dev/null +++ b/headers/private/shared/binary-utils.h @@ -0,0 +1,77 @@ +/* + * Copyright 2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Brecht Machiels, brecht@mos6581.org + */ + +#ifndef _BINARY_UTILS_H +#define _BINARY_UTILS_H + + +/* macro for a one-bit bitmask +*/ + +#define BIT(n) (1ULL << n) + +/* macro/templates to create bitmasks +*/ + +#define BITMASK(high, low) ((unsigned long long)(BitMask::value)) + +template +struct BitMask +{ + enum { value = (BitMask::value + + (1ULL << h - l)) << l }; +}; + + +template<> +struct BitMask<-1,0> +{ + enum { value = 0ULL }; +}; + + +/* macro/templates to enter binary constants +*/ + +#define BINARY(binstring) ((unsigned long long)(Binary<0##binstring>::value)) + +// http://www.eptacom.net/pubblicazioni/pub_eng/binary.html +template struct Binary +{ + enum { value = (N % 8ULL) + 2ULL * Binary::value }; +}; + + +struct Binary<0> +{ + enum { value = 0ULL } ; +}; + + +/* macro/templates to determine offset + + NOTE: broken for high bit indices +*/ + +#define MASKOFFSET(mask) (MaskOffset::count) + +template +struct MaskOffset +{ + enum { count = MaskOffset<(mask >> 1), ((mask >> 1) & 1UL)>::count + 1 }; +}; + + +template +struct MaskOffset +{ + enum { count = 0 }; +}; + +#endif // _BINARY_UTILS_H + diff --git a/src/add-ons/accelerants/intel_extreme/Jamfile b/src/add-ons/accelerants/intel_extreme/Jamfile index 3b14351940..43415c362c 100644 --- a/src/add-ons/accelerants/intel_extreme/Jamfile +++ b/src/add-ons/accelerants/intel_extreme/Jamfile @@ -5,6 +5,7 @@ SetSubDirSupportedPlatformsBeOSCompatible ; UsePrivateHeaders graphics ; UsePrivateHeaders [ FDirName graphics intel_extreme ] ; UsePrivateHeaders [ FDirName graphics common ] ; +UsePrivateHeaders shared ; Addon intel_extreme.accelerant : accelerant.cpp diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 3639b00ee6..0d43b368d5 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -130,7 +130,8 @@ set_frame_buffer_base() surfaceRegister = INTEL_DISPLAY_B_SURFACE; } - if (sharedInfo.device_type.InGroup(INTEL_TYPE_96x)) { + if (sharedInfo.device_type.InGroup(INTEL_TYPE_96x) + || sharedInfo.device_type.InGroup(INTEL_TYPE_G4x)) { write32(baseRegister, mode.v_display_start * sharedInfo.bytes_per_row + mode.h_display_start * (sharedInfo.bits_per_pixel + 7) / 8); read32(baseRegister); @@ -217,7 +218,17 @@ 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.InFamily(INTEL_TYPE_9xx)) { + if (gInfo->shared_info->device_type.InGroup(INTEL_TYPE_G4x)) { + // single LVDS output + // NOTE: not sure these will work with CRT displays + static const pll_limits kLimits = { + // p, p1, p2, high, n, m, m1, m2 + { 28, 2, 14, false, 1, 104, 17, 5}, // min + {112, 8, 0, true, 3, 138, 23, 11}, // max + 200000, 1750000, 3500000 + }; + limits = kLimits; + } else if (gInfo->shared_info->device_type.InFamily(INTEL_TYPE_9xx)) { // TODO: support LVDS output limits as well // (Update: Output limits are adjusted in the computation (post2=7/14)) // Should move them here! diff --git a/src/add-ons/kernel/busses/agp_gart/Jamfile b/src/add-ons/kernel/busses/agp_gart/Jamfile index 34af1f0949..e7078ce150 100644 --- a/src/add-ons/kernel/busses/agp_gart/Jamfile +++ b/src/add-ons/kernel/busses/agp_gart/Jamfile @@ -7,6 +7,7 @@ UsePrivateHeaders [ FDirName kernel arch $(TARGET_ARCH) ] ; UsePrivateHeaders [ FDirName graphics intel_extreme ] ; UsePrivateHeaders [ FDirName graphics common ] ; UsePrivateHeaders drivers graphics kernel ; +UsePrivateHeaders shared ; KernelAddon intel : intel_gart.cpp diff --git a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp index 4f25bf33a3..325d0f0b3f 100644 --- a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp +++ b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp @@ -68,6 +68,8 @@ const struct supported_device { {0x29b0, 0x29b2, INTEL_TYPE_G33, "G33"}, {0x29c0, 0x29c2, INTEL_TYPE_G33, "Q35"}, {0x29d0, 0x29d2, INTEL_TYPE_G33, "Q33"}, + + {0x2a40, 0x2a42, INTEL_TYPE_GM45, "GM45"}, }; struct intel_info { @@ -146,6 +148,27 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) gttSize = 2 << 20; break; } + } else if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x) { + switch (memoryConfig & G4X_GGC_GGMS_MASK) { + case G4X_GGMS_NONE: + gttSize = 0; + break; + case G4X_GGMS_NO_IVT_1M: + gttSize = 1 << 20; + break; + case G4X_GGMS_NO_IVT_2M: + gttSize = 2 << 20; + break; + case G4X_GGMS_IVT_2M: + gttSize = 2 << 20; + break; + case G4X_GGMS_IVT_3M: + gttSize = 3 << 20; + break; + case G4X_GGMS_IVT_4M: + gttSize = 4 << 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 @@ -159,12 +182,14 @@ 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)); gttSize = frameBufferSize / 1024; } // TODO: test with different models! if (info.type == INTEL_TYPE_83x) { + // Older chips switch (memoryConfig & STOLEN_MEMORY_MASK) { case i830_LOCAL_MEMORY_ONLY: // TODO: determine its size! @@ -173,12 +198,42 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) case i830_STOLEN_512K: memorySize >>= 1; break; + case i830_STOLEN_1M: + // default case + break; case i830_STOLEN_8M: memorySize *= 8; break; } + } else if (info.type == INTEL_TYPE_G4x) { + switch (memoryConfig & G4X_GGC_GMS_MASK) { + case G4X_GMS_32MB: + memorySize *= 32; + break; + case G4X_GMS_64MB: + memorySize *= 64; + break; + case G4X_GMS_128MB: + memorySize *= 128; + break; + case G4X_GMS_256MB: + memorySize *= 256; + break; + case G4X_GMS_96MB: + memorySize *= 96; + break; + case G4X_GMS_160MB: + memorySize *= 160; + break; + case G4X_GMS_224MB: + memorySize *= 224; + break; + case G4X_GMS_352MB: + memorySize *= 352; + break; + } } else if (info.type == INTEL_TYPE_85x - || (info.type & INTEL_TYPE_9xx) != 0) { + || (info.type & INTEL_TYPE_9xx) == INTEL_TYPE_9xx) { switch (memoryConfig & STOLEN_MEMORY_MASK) { case i855_STOLEN_MEMORY_4M: memorySize *= 4; @@ -205,6 +260,9 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) memorySize *= 256; break; } + } else { + // TODO: error out! + memorySize = 4096; } stolenSize = memorySize - 4096; @@ -241,7 +299,7 @@ intel_map(intel_info &info) mmioIndex = 0; fbIndex = 2; } - + AreaKeeper mmioMapper; info.registers_area = mmioMapper.Map("intel GMCH mmio", (void *)info.display.u.h0.base_registers[mmioIndex], @@ -271,7 +329,10 @@ intel_map(intel_info &info) if (get_memory_map(scratchAddress, B_PAGE_SIZE, &entry, 1) != B_OK) return B_ERROR; - if ((info.type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) + if ((info.type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_G4x) + info.gtt_physical_base = info.display.u.h0.base_registers[mmioIndex] + + (2UL << 20); + else if ((info.type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) info.gtt_physical_base = get_pci_config(info.display, i915_GTT_BASE, 4); else { info.gtt_physical_base = read32(info.registers @@ -307,11 +368,15 @@ intel_map(intel_info &info) info.aperture_stolen_size = stolenSize; if (info.aperture_size == 0) info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex]; - + dprintf("intel_gart: detected %ld MB of stolen memory, aperture " "size %ld MB, GTT size %ld KB\n", (stolenSize + (1023 << 10)) >> 20, info.aperture_size >> 20, gttSize >> 10); + dprintf("intel_gart: GTT base = 0x%lx\n", info.gtt_physical_base); + dprintf("intel_gart: MMIO base = 0x%lx\n", info.display.u.h0.base_registers[mmioIndex]); + dprintf("intel_gart: GMR base = 0x%lx\n", info.aperture_physical_base); + AreaKeeper apertureMapper; info.aperture_area = apertureMapper.Map("intel graphics aperture", (void *)info.aperture_physical_base, info.aperture_size, diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile b/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile index 96b6872262..54e1a5e9f0 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/Jamfile @@ -5,6 +5,7 @@ SetSubDirSupportedPlatformsBeOSCompatible ; UsePrivateHeaders [ FDirName graphics intel_extreme ] ; UsePrivateHeaders [ FDirName graphics common ] ; UsePrivateHeaders graphics kernel ; +UsePrivateHeaders shared ; KernelAddon intel_extreme : driver.cpp diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp index 99e210b29c..c8c382cc4a 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp @@ -54,6 +54,7 @@ const struct supported_device { {0x29b2, INTEL_TYPE_G33, "G33G"}, {0x29c2, INTEL_TYPE_G33, "Q35G"}, {0x29d2, INTEL_TYPE_G33, "Q33G"}, + {0x2a42, INTEL_TYPE_GM45, "GM45"}, }; int32 api_version = B_CUR_DRIVER_API_VERSION; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp index b621e0c6bb..3f259e8352 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp @@ -238,11 +238,25 @@ intel_extreme_init(intel_info &info) primary.offset = (addr_t)primary.base - info.aperture_base; } + // Clock gating // Fix some problems on certain chips (taken from X driver) // TODO: clean this up 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_G4x)) { + dprintf("G4x clock gating\n"); + write32(info.registers + 0x6204, 0); + write32(info.registers + 0x6208, BIT(9) | BIT(7) | BIT(6)); + write32(info.registers + 0x6210, 0); + + uint32 dspclk_gate_val = BIT(28) | BIT(3) | BIT(2); + if ((info.device_type.type & INTEL_TYPE_MOBILE) == INTEL_TYPE_MOBILE) { + dprintf("G4x mobile clock gating\n"); + dspclk_gate_val |= BIT(18); + } + write32(info.registers + 0x6200, dspclk_gate_val) ; + } else { dprintf("i965 quirk\n"); write32(info.registers + 0x6204, (1L << 29) | (1L << 23));