* 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
This commit is contained in:
Brecht Machiels 2009-10-23 23:03:49 +00:00
parent bd56fd8a4c
commit dfdfbd3eef
9 changed files with 220 additions and 7 deletions

View File

@ -9,6 +9,7 @@
#define INTEL_EXTREME_H
#include "binary-utils.h"
#include "lock.h"
#include <Accelerant.h>
@ -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

View File

@ -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<high, low>::value))
template<int h, int l>
struct BitMask
{
enum { value = (BitMask<h-l-1,0>::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<const unsigned long long N> struct Binary
{
enum { value = (N % 8ULL) + 2ULL * Binary<N / 8ULL>::value };
};
struct Binary<0>
{
enum { value = 0ULL } ;
};
/* macro/templates to determine offset
NOTE: broken for high bit indices
*/
#define MASKOFFSET(mask) (MaskOffset<mask, (mask & 1UL)>::count)
template<const unsigned long mask, unsigned int firstBit>
struct MaskOffset
{
enum { count = MaskOffset<(mask >> 1), ((mask >> 1) & 1UL)>::count + 1 };
};
template<const unsigned long mask>
struct MaskOffset<mask, 1>
{
enum { count = 0 };
};
#endif // _BINARY_UTILS_H

View File

@ -5,6 +5,7 @@ SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders graphics ;
UsePrivateHeaders [ FDirName graphics intel_extreme ] ;
UsePrivateHeaders [ FDirName graphics common ] ;
UsePrivateHeaders shared ;
Addon intel_extreme.accelerant :
accelerant.cpp

View File

@ -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!

View File

@ -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 <agp_gart>intel :
intel_gart.cpp

View File

@ -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 &gttSize, 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 &gttSize, 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 &gttSize, 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 &gttSize, 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,

View File

@ -5,6 +5,7 @@ SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders [ FDirName graphics intel_extreme ] ;
UsePrivateHeaders [ FDirName graphics common ] ;
UsePrivateHeaders graphics kernel ;
UsePrivateHeaders shared ;
KernelAddon intel_extreme :
driver.cpp

View File

@ -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;

View File

@ -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));