summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2006-11-29 15:06:32 -0800
committerEric Anholt <eric@anholt.net>2006-11-29 15:06:32 -0800
commitb6fc8df9a52f5fe1b4d26ae06bc4d48235b44a67 (patch)
treef900773d3c287c46f7f879a72630de03b236b65e
parent359dc81c07901665da0f86c573c096fa1661cdd2 (diff)
Properly detect the GTT size on the G965.
In the past, the GTT has always been sized just large enough to map the whole graphics aperture. However, apparently on the G965 that isn't the case, and it is actually 512KB on hardware with a 256MB aperture. This resulted in X not bothering to allocate memory for 256KB that it thought was already mapped into stolen memory, and thus garbage rendering (particularly visible in large video modes that displayed this unallocated memory). The kernel happens to get the right answer by hardwiring a 512KB GTT size already, but that may not be true on future hardware. Instead, we use a convenient field in PGETBL_CTL that's specifically for the GTT size rather than the aperture size, which gets us the answer we want.
-rw-r--r--src/i810_reg.h5
-rw-r--r--src/i830_driver.c34
2 files changed, 35 insertions, 4 deletions
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 53a063fc..9c6e0dd2 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -499,6 +499,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define PGETBL_ADDR_MASK 0xFFFFF000
#define PGETBL_ENABLE_MASK 0x00000001
#define PGETBL_ENABLED 0x00000001
+/** Added in 965G, this field has the actual size of the global GTT */
+#define PGETBL_SIZE_MASK 0x0000000e
+#define PGETBL_SIZE_512KB (0 << 1)
+#define PGETBL_SIZE_256KB (1 << 1)
+#define PGETBL_SIZE_128KB (2 << 1)
/* Register containing pge table error results, p276
*/
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 39ffa542..55610f5e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -394,7 +394,7 @@ I830DetectMemory(ScrnInfoPtr pScrn)
I830Ptr pI830 = I830PTR(pScrn);
PCITAG bridge;
CARD16 gmch_ctrl;
- int memsize = 0;
+ int memsize = 0, gtt_size;
int range;
#if 0
VbeInfoBlock *vbeInfo;
@@ -403,9 +403,35 @@ I830DetectMemory(ScrnInfoPtr pScrn)
bridge = pciTag(0, 0, 0); /* This is always the host bridge */
gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL);
- /* We need to reduce the stolen size, by the GTT and the popup.
- * The GTT varying according the the FbMapSize and the popup is 4KB */
- range = (pI830->FbMapSize / (1024*1024)) + 4;
+ if (IS_I965G(pI830)) {
+ /* The 965 may have a GTT that is actually larger than is necessary
+ * to cover the aperture, so check the hardware's reporting of the
+ * GTT size.
+ */
+ switch (INREG(PGETBL_CTL) & PGETBL_SIZE_MASK) {
+ case PGETBL_SIZE_512KB:
+ gtt_size = 512;
+ break;
+ case PGETBL_SIZE_256KB:
+ gtt_size = 256;
+ break;
+ case PGETBL_SIZE_128KB:
+ gtt_size = 128;
+ break;
+ default:
+ FatalError("Unknown GTT size value: %08x\n", (int)INREG(PGETBL_CTL));
+ }
+ } else {
+ /* Older chipsets only had GTT appropriately sized for the aperture. */
+ gtt_size = pI830->FbMapSize / (1024*1024);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "detected %d kB GTT.\n", gtt_size);
+
+ /* The stolen memory has the GTT at the top, and the 4KB popup below that.
+ * Everything else can be freely used by the graphics driver.
+ */
+ range = gtt_size + 4;
if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) {
switch (gmch_ctrl & I830_GMCH_GMS_MASK) {