Radeon mem map fix: Need regression tests please

Benjamin Herrenschmidt benh at kernel.crashing.org
Sun Dec 18 22:07:15 PST 2005


I think I've get something in shape for getting the radeon memory map
finally sane, removing all sort of hacks, and possibly fixing all sort
of weird bugs. It works best with the very latest radeon DRM fixes to
the same area but might well improve things all by itself.

However, due to the importance of the changes, that patch really need
some serious regression testing. That's also why I've left (after fixing
it so it builds) RADEON_DEBUG enabled so that in case of problem, there
will hopefully be some useful infos in the log.

So please test and let me know (both if it works, doesn't work, and if
it fixes a previously broken setup). It's not 7.0 material but I expect
to commit the patch (or a successor) to CVS right after that, and it
might hit a subsequence stable release as a bug fix.

Especially, test with & without DRI and that console switch works, to
vgacon or to framebuffer, or to whatever non-linux OSes have ...on
linux, with and without "UseFBDev" if you are using radeonfb too, etc...

Thanks in advance,
Ben.

diff -urN xc-HEAD.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon.h xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon.h
--- xc-HEAD.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon.h	2005-12-15 16:53:42.000000000 +1100
+++ xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon.h	2005-12-19 16:33:40.000000000 +1100
@@ -102,7 +102,7 @@
 
 /* ------------------------------------- */
 
-#define RADEON_DEBUG            0 /* Turn off debugging output               */
+#define RADEON_DEBUG            1 /* Turn off debugging output               */
 #define RADEON_IDLE_RETRY      16 /* Fall out of idle loops after this count */
 #define RADEON_TIMEOUT    2000000 /* Fall out of wait loops after this count */
 #define RADEON_MMIOSIZE   0x80000
@@ -116,13 +116,13 @@
 				   */
 
 #if RADEON_DEBUG
-#define RADEONTRACE(x)							\
+#define RADEONTRACE(x)						\
 do {									\
     ErrorF("(**) %s(%d): ", RADEON_NAME, pScrn->scrnIndex);		\
     ErrorF x;								\
-} while (0);
+} while(0)
 #else
-#define RADEONTRACE(x)
+#define RADEONTRACE(x) do { } while(0)
 #endif
 
 
@@ -147,10 +147,16 @@
     CARD32            cap0_trig_cntl;
     CARD32            cap1_trig_cntl;
     CARD32            bus_cntl;
-    CARD32            surface_cntl;
     CARD32            bios_4_scratch;
     CARD32            bios_5_scratch;
     CARD32            bios_6_scratch;
+    CARD32            surface_cntl;
+    CARD32            surfaces[8][3];
+    CARD32            mc_agp_location;
+    CARD32            mc_fb_location;
+    CARD32            display_base_addr;
+    CARD32            display2_base_addr;
+    CARD32            ov0_base_addr;
 
 				/* Other registers to save for VT switches */
     CARD32            dp_datatype;
@@ -158,8 +164,6 @@
     CARD32            clock_cntl_index;
     CARD32            amcgpio_en_reg;
     CARD32            amcgpio_mask;
-    
-    CARD32            surfaces[8][3];
 
 				/* CRTC registers */
     CARD32            crtc_gen_cntl;
@@ -326,6 +330,8 @@
     unsigned long     MMIOAddr;         /* MMIO region physical address      */
     unsigned long     BIOSAddr;         /* BIOS physical address             */
     unsigned int      fbLocation;
+    CARD32            mc_fb_location;
+    CARD32            mc_agp_location;
 
     unsigned char     *MMIO;            /* Map of MMIO region                */
     unsigned char     *FB;              /* Map of frame buffer               */
diff -urN xc-HEAD.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c
--- xc-HEAD.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c	2005-12-15 16:53:42.000000000 +1100
+++ xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c	2005-12-19 14:30:41.000000000 +1100
@@ -50,6 +50,7 @@
 
 				/* Driver data structures */
 #include "radeon.h"
+#include "radeon_version.h"
 #include "radeon_reg.h"
 #include "radeon_macros.h"
 #include "radeon_mergedfb.h"
diff -urN xc-HEAD.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c
--- xc-HEAD.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c	2005-12-15 16:53:42.000000000 +1100
+++ xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c	2005-12-19 14:38:46.000000000 +1100
@@ -1456,10 +1456,6 @@
 		       version->version_patchlevel);
 	   info->allowColorTiling = FALSE;
 	   info->tilingEnabled = FALSE;
-	   /* try to fix up already set mode, crt pitch, ddx major (hope that's ok to do here) */
-	   /* is this correct scrnIndex? flags? */
-	   RADEONSwitchMode(pScrn->scrnIndex, pScrn->currentMode, 0);
-	   pScrn->AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
 	   pDRIInfo->ddxDriverMajorVersion = RADEON_VERSION_MAJOR;
 	}
 	drmFreeVersion(version);
diff -urN xc-HEAD.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c
--- xc-HEAD.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c	2005-12-15 16:53:43.000000000 +1100
+++ xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c	2005-12-19 16:59:45.000000000 +1100
@@ -129,6 +129,7 @@
 static int RADEONValidateMergeModes(ScrnInfoPtr pScrn);
 static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode);
 static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn);
+static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save);
 
 /* psuedo xinerama support */
 
@@ -547,6 +548,8 @@
 static Bool RADEONMapMMIO(ScrnInfoPtr pScrn);
 static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn);
 
+static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save);
+
 RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn)
 {
     DevUnion     *pPriv;
@@ -2252,83 +2255,92 @@
     return TRUE;
 }
 
-/* Set up MC_FB_LOCATION and related registers */
-static void
-RADEONSetFBLocation(ScrnInfoPtr pScrn)
+static void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save,
+				      RADEONInfoPtr info)
 {
-    RADEONInfoPtr  info = RADEONPTR(pScrn);
-    RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+    save->mc_fb_location = info->mc_fb_location;
+    save->mc_agp_location = info->mc_agp_location;
+    save->display_base_addr = info->fbLocation;
+    save->display2_base_addr = info->fbLocation;
+    save->ov0_base_addr = info->fbLocation;
+}
+
+static void RADEONInitMemoryMap(ScrnInfoPtr pScrn)
+{
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);
     unsigned char *RADEONMMIO = info->MMIO;
-    CARD32 mc_fb_location;
-    CARD32 mc_agp_location = INREG(RADEON_MC_AGP_LOCATION);
-    CARD32 bus_cntl = INREG(RADEON_BUS_CNTL);
-    
-    OUTREG (RADEON_BUS_CNTL, bus_cntl | RADEON_BUS_MASTER_DIS);
-    RADEONWaitForIdleMMIO(pScrn);
+    unsigned long agp_size, agp_base, mem_size;
 
-    /* This function has many problems with newer cards.
-     * Even with older cards, all registers changed here are not
-     * restored properly when X quits, this will also cause 
-     * various problems, especially with radeonfb.
-     * Since we don't have DRI support for R300 and above cards, 
-     * we just hardcode these values for now.
-     * Need to revisit this whole function!!!
-     */
+    /* Default to existing values */
+    info->mc_fb_location = INREG(RADEON_MC_FB_LOCATION);
+    info->mc_agp_location = INREG(RADEON_MC_AGP_LOCATION);
 
-    if (info->IsIGP) {
-	mc_fb_location = INREG(RADEON_NB_TOM);
+    /* We shouldn't use info->videoRam here which might have been clipped
+     * but the real video RAM instead
+     */
+    mem_size = INREG(RADEON_CONFIG_MEMSIZE);
+    if (mem_size == 0)
+	    mem_size = 0x800000;
 
-	OUTREG(RADEON_GRPH2_BUFFER_CNTL,
-	       INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000);
 
-    } else
+    /* We won't try to change MC_FB_LOCATION when using fbdev */
+    if (!info->FBDev) {
+	if (info->IsIGP)
+	    info->mc_fb_location = INREG(RADEON_NB_TOM);
+	else
 #ifdef XF86DRI
-    if ( info->directRenderingEnabled && info->drmMinor < 10 ) {
-	mc_fb_location = (INREG(RADEON_CONFIG_APER_SIZE) - 1) & 0xffff0000U;
-    } else
+  /* Old DRI has restrictions on the memory map */
+	if ( info->directRenderingEnabled && info->drmMinor < 10 )
+	    info->mc_fb_location = (mem_size - 1) & 0xffff0000U;
+	else
 #endif
-    {
-	CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE);
-
-	mc_fb_location = (aper0_base >> 16)
-		       | ((aper0_base + (INREG(RADEON_CONFIG_APER_SIZE) - 1)
-			   ) & 0xffff0000U);
-    }
-
-    info->fbLocation = (mc_fb_location & 0xffff) << 16;
+	{
+	    CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE);
 
-    if (((mc_agp_location & 0xffff) << 16) !=
-	((mc_fb_location & 0xffff0000U) + 0x10000)) {
-	mc_agp_location = mc_fb_location & 0xffff0000U;
-	mc_agp_location |= (mc_agp_location + 0x10000) >> 16;
+	    info->mc_fb_location = (aper0_base >> 16) |
+		    ((aper0_base + mem_size - 1) & 0xffff0000U);
+	}
     }
+    info->fbLocation = (info->mc_fb_location & 0xffff) << 16;
 
-    RADEONWaitForIdleMMIO(pScrn);
+    /* Calculate AGP aperture location */
+    agp_size = ((info->mc_agp_location >> 16) -
+		(info->mc_agp_location & 0xffff) + 1) << 16;
+    agp_base = info->fbLocation + mem_size;
 
-    OUTREG(RADEON_MC_FB_LOCATION, mc_fb_location);
-    OUTREG(RADEON_MC_AGP_LOCATION, mc_agp_location);
-    OUTREG(RADEON_DISPLAY_BASE_ADDR, info->fbLocation);
-    if (info->HasCRTC2)
-	OUTREG(RADEON_DISPLAY2_BASE_ADDR, info->fbLocation);
-    OUTREG(RADEON_OV0_BASE_ADDR, info->fbLocation);
+    /* If there is no room up there for at least 16Mb, put AGP down to
+     * 0x80000000. This is an arbitrary value that should be good enough.
+     * In the future, we might want to use the real gartSize that will be
+     * requested, but at least that will give us some breathing space with
+     * the default value
+     */
+    if ((agp_base + 0x01000000) < info->fbLocation)
+	    agp_base = 0x80000000u;
 
-    OUTREG (RADEON_BUS_CNTL, bus_cntl);
-    RADEONWaitForIdleMMIO(pScrn);
+    /* Make sure AGP size is at least 4Mb for the sake of the memory mapping
+     * (even if we don't actually use it, to avoid leaving a dangling map
+     * or invalid setting in MC_AGP_LOCATION
+     */
+    if (agp_size < 0x400000)
+	    agp_size = 0x400000;
 
-    /* Set display0/1 priority up on r3/4xx in the memory controller for 
-     * high res modes if the user specifies HIGH for displaypriority 
-     * option.
+    /* We may need to crop the AGP size. Hopefully, it will be changed later
+     * on by the DRI init again, but for now, it's the firmware setting which
+     * might overflow.
      */
-    if ((info->DispPriority == 2) && IS_R300_VARIANT) {
-        CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER);
-	if (info->MergedFB || pRADEONEnt->HasSecondary) {
-	    mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */
-	} else {
-	    mc_init_misc_lat_timer |= 0x0100; /* display 0 only */
-	}
-	OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
-    }
+    while (agp_base > ((agp_base + agp_size) & 0xfffffffful))
+	    agp_size >>= 1; 
+
+    /* Ok, now set our various bits & pieces */
+    info->mc_agp_location = (agp_base >> 16) |
+	    ((agp_base + agp_size - 1) & 0xffff0000U);
 
+    RADEONTRACE(("RADEONInitMemoryMap() : \n"));
+    RADEONTRACE(("  mem_size         : 0x%08lx\n", mem_size));
+    RADEONTRACE(("  agp_size         : 0x%08lx\n", agp_size));
+    RADEONTRACE(("  agp_base         : 0x%08lx\n", agp_base));
+    RADEONTRACE(("  MC_FB_LOCATION   : 0x%08lx\n", info->mc_fb_location));
+    RADEONTRACE(("  MC_AGP_LOCATION  : 0x%08lx\n", info->mc_agp_location));
 }
 
 static void RADEONGetVRamType(ScrnInfoPtr pScrn)
@@ -2710,7 +2722,9 @@
          * 128M is configured as invisible FB to CPU that can only be accessed from chip side.
          */
         pScrn->videoRam      = INREG(RADEON_CONFIG_MEMSIZE) / 1024;
-        if (pScrn->videoRam > 128*1024) pScrn->videoRam = 128*1024;
+        if (pScrn->videoRam > 128*1024)
+	    pScrn->videoRam = 128*1024;
+	/* XXX FIX CRAP BELOW ! IT'S WRONG */
         if ((info->ChipFamily == CHIP_FAMILY_RV350) ||
             (info->ChipFamily == CHIP_FAMILY_RV380) ||
             (info->ChipFamily == CHIP_FAMILY_R420)) {
@@ -2719,7 +2733,10 @@
     }
 
     /* Some production boards of m6 will return 0 if it's 8 MB */
-    if (pScrn->videoRam == 0) pScrn->videoRam = 8192;
+    if (pScrn->videoRam == 0) {
+	pScrn->videoRam = 8192;
+	OUTREG(RADEON_CONFIG_MEMSIZE, 0x800000);
+    }
 
     /* Check chip errata */
     info->ChipErrata = 0;
@@ -5500,31 +5517,6 @@
             info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE;
 	}
     }
-
-    if (!info->IsSecondary) {
-	/* empty the surfaces */
-	unsigned char *RADEONMMIO = info->MMIO;
-	unsigned int i;
-	for (i = 0; i < 8; i++) {
-	    OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0);
-	    OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0);
-	    OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0);
-	}
-    }
-
-    if (info->FBDev) {
-	unsigned char *RADEONMMIO = info->MMIO;
-
-	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
-	info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL);
-    } else {
-	if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
-    }
-
-    RADEONSaveScreen(pScreen, SCREEN_SAVER_ON);
-
-    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
-
 				/* Visual setup */
     miClearVisualTypes();
     if (!miSetVisualTypes(pScrn->depth,
@@ -5586,6 +5578,40 @@
 	}
     }
 
+    hasDRI = info->directRenderingEnabled;
+#endif
+
+    /* Initialize the memory map, this basically calculates the values
+     * we'll use later on for MC_FB_LOCATION & MC_AGP_LOCATION
+     */
+    RADEONInitMemoryMap(pScrn);
+
+    if (!info->IsSecondary) {
+	/* empty the surfaces */
+	unsigned char *RADEONMMIO = info->MMIO;
+	unsigned int i;
+	for (i = 0; i < 8; i++) {
+	    OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0);
+	    OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0);
+	    OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0);
+	}
+    }
+
+    if (info->FBDev) {
+	unsigned char *RADEONMMIO = info->MMIO;
+
+	if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE;
+	RADEONSaveMemMapRegisters(pScrn, &info->ModeReg);
+	info->fbLocation = (info->ModeReg.mc_fb_location & 0xffff) << 16;
+	info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL);
+    } else {
+	if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
+    }
+
+    RADEONSaveScreen(pScreen, SCREEN_SAVER_ON);
+
+    pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
     /* Depth moves are disabled by default since they are extremely slow */
     info->depthMoves = xf86ReturnOptValBool(info->Options,
 						 OPTION_DEPTH_MOVE, FALSE);
@@ -5600,11 +5626,6 @@
 		   "Depth moves disabled by default\n");
     }
 
-    hasDRI = info->directRenderingEnabled;
-#endif
-
-    RADEONSetFBLocation(pScrn);
-
     if (!fbScreenInit(pScreen, info->FB,
 		      pScrn->virtualX, pScrn->virtualY,
 		      pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
@@ -5796,6 +5817,13 @@
 #endif /* USE_XAA */
 	}
     }
+
+    /* DRI final init might have changed the memory map, we need to adjust
+     * our local image to make sure we restore them properly on mode changes
+     * or VT switches
+     */
+    RADEONAdjustMemMapRegisters(pScrn, &info->ModeReg);
+
     if (info->directRenderingEnabled) {
 	if ((info->DispPriority == 1) && (info->cardType==CARD_AGP)) {
 	    /* we need to re-calculate bandwidth because of AGPMode difference. */ 
@@ -5835,7 +5863,103 @@
     return TRUE;
 }
 
-/* Write common registers (initialized to 0) */
+/* Write memory mapping registers */
+static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn,
+					 RADEONSavePtr restore)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    int i;
+
+    RADEONTRACE(("RADEONRestoreMemMapRegisters() : \n"));
+    RADEONTRACE(("  MC_FB_LOCATION   : 0x%08lx\n", restore->mc_fb_location));
+    RADEONTRACE(("  MC_AGP_LOCATION  : 0x%08lx\n", restore->mc_agp_location));
+
+    /* Write memory mapping registers only if their value change
+     * since we must ensure no access is done while they are
+     * reprogrammed
+     */
+    if (INREG(RADEON_MC_FB_LOCATION) != restore->mc_fb_location ||
+	INREG(RADEON_MC_AGP_LOCATION) != restore->mc_agp_location) {
+	CARD32 tmp;
+
+	RADEONTRACE(("  Map Changed ! Applying ...\n"));
+
+	/* Make sure engine is idle. We assume the CCE is stopped
+	 * at this point
+	 */
+	RADEONWaitForIdleMMIO(pScrn);
+
+	/* Stop display & memory access */
+	tmp = INREG(RADEON_CRTC_EXT_CNTL);
+	OUTREG(RADEON_CRTC_EXT_CNTL, tmp | RADEON_CRTC_DISPLAY_DIS);
+	tmp = INREG(RADEON_CRTC_GEN_CNTL);
+	tmp &= ~RADEON_CRTC_CUR_EN;
+	tmp |= RADEON_CRTC_DISP_REQ_EN_B;
+	OUTREG(RADEON_CRTC_GEN_CNTL, tmp);
+	if (info->HasCRTC2) {
+		tmp = INREG(RADEON_CRTC2_GEN_CNTL);
+		tmp &= ~RADEON_CRTC2_CUR_EN;
+		tmp |= RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_DISP_REQ_EN_B;
+		OUTREG(RADEON_CRTC2_GEN_CNTL, tmp);
+	}
+	tmp = INREG(RADEON_OV0_SCALE_CNTL);
+	tmp &= ~RADEON_SCALER_ENABLE;
+
+	/* Clear all surfaces */
+	for (i = 0; i < 8; i++) {
+	    OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0);
+	    OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0);
+	    OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0);
+	}
+
+	/* Make sure the chip settles down and set new map*/ 
+	usleep(100000);
+	OUTREG(RADEON_MC_FB_LOCATION, restore->mc_fb_location);
+ 	OUTREG(RADEON_MC_AGP_LOCATION, restore->mc_agp_location);
+	/* Make sure map fully reached the chip */
+	(void)INREG(RADEON_MC_FB_LOCATION);
+    }
+    
+    /* Restore base addresses */
+    OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr);
+    OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr);
+    OUTREG(RADEON_OV0_BASE_ADDR, restore->ov0_base_addr);
+}
+
+static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info   = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+    CARD32 fb, agp;
+    int fb_loc_changed;
+
+    fb = INREG(RADEON_MC_FB_LOCATION);
+    agp = INREG(RADEON_MC_AGP_LOCATION);
+    fb_loc_changed = (fb != info->mc_fb_location);
+
+    if (fb_loc_changed || agp != info->mc_agp_location) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "DRI init changed memory map, adjusting ...\n");
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "MC_FB_LOCATION  was: 0x%08lx is: 0x%08lx\n",
+		       info->mc_fb_location, fb);
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "MC_AGP_LOCATION was: 0x%08lx is: 0x%08lx\n",
+		       info->mc_agp_location, agp);
+	    info->mc_fb_location = fb;
+	    info->mc_agp_location = agp;
+	    info->fbLocation = (save->mc_fb_location & 0xffff) << 16;
+
+	    RADEONInitMemMapRegisters(pScrn, save, info);
+
+	    /* If MC_FB_LOCATION was changed, adjust the various offsets */
+	    if (fb_loc_changed)
+		    RADEONRestoreMemMapRegisters(pScrn, save);
+    }
+}
+
+/* Write common registers */
 static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn,
 					 RADEONSavePtr restore)
 {
@@ -5998,13 +6122,6 @@
     OUTREG(RADEON_FP_VERT_STRETCH,      restore->fp_vert_stretch);
     OUTREG(RADEON_FP_GEN_CNTL,          restore->fp_gen_cntl);
 
-    /* old AIW Radeon has some BIOS initialization problem
-     * with display buffer underflow, only occurs to DFP
-     */
-    if (!info->HasCRTC2)
-	OUTREG(RADEON_GRPH_BUFFER_CNTL,
-	       INREG(RADEON_GRPH_BUFFER_CNTL) & ~0x7f0000);
-
     if (info->IsMobility) {
 	OUTREG(RADEON_BIOS_4_SCRATCH, restore->bios_4_scratch);
 	OUTREG(RADEON_BIOS_5_SCRATCH, restore->bios_5_scratch);
@@ -6455,6 +6572,7 @@
 
     /* For Non-dual head card, we don't have private field in the Entity */
     if (!info->HasCRTC2) {
+	RADEONRestoreMemMapRegisters(pScrn, restore);
 	RADEONRestoreCommonRegisters(pScrn, restore);
 	RADEONRestoreCrtcRegisters(pScrn, restore);
 	RADEONRestoreFPRegisters(pScrn, restore);
@@ -6472,10 +6590,12 @@
      * order. Regardless the order of X server issuing the calls, we
      * have to ensure we set registers in the right order!!!  Otherwise
      * we may get a blank screen.
+     *
+     * We always restore MemMap first, the saverec should be up to date
+     * in all cases
      */
     if (info->IsSecondary) {
-	if (!pRADEONEnt->RestorePrimary  && !info->IsSwitching)
-	    RADEONRestoreCommonRegisters(pScrn, restore);
+	RADEONRestoreMemMapRegisters(pScrn, restore);
 	RADEONRestoreCrtc2Registers(pScrn, restore);
 	RADEONRestorePLL2Registers(pScrn, restore);
 
@@ -6486,15 +6606,14 @@
 	if (pRADEONEnt->RestorePrimary) {
 	    pRADEONEnt->RestorePrimary = FALSE;
 
+	    RADEONRestoreCommonRegisters(pScrn, &restore0);
 	    RADEONRestoreCrtcRegisters(pScrn, &restore0);
 	    RADEONRestoreFPRegisters(pScrn, &restore0);
 	    RADEONRestorePLLRegisters(pScrn, &restore0);
 	    pRADEONEnt->IsSecondaryRestored = FALSE;
 	}
     } else {
-	if (!pRADEONEnt->IsSecondaryRestored)
-	    RADEONRestoreCommonRegisters(pScrn, restore);
-
+	RADEONRestoreMemMapRegisters(pScrn, restore);
 	if (info->MergedFB) {
 	    RADEONRestoreCrtc2Registers(pScrn, restore);
 	    RADEONRestorePLL2Registers(pScrn, restore);
@@ -6504,6 +6623,7 @@
 	    info->IsSwitching) {
 	    pRADEONEnt->IsSecondaryRestored = FALSE;
 
+	    RADEONRestoreCommonRegisters(pScrn, restore);
 	    RADEONRestoreCrtcRegisters(pScrn, restore);
 	    RADEONRestoreFPRegisters(pScrn, restore);
 	    RADEONRestorePLLRegisters(pScrn, restore);
@@ -6518,6 +6638,19 @@
 #endif
 }
 
+/* Read memory map */
+static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
+{
+    RADEONInfoPtr  info       = RADEONPTR(pScrn);
+    unsigned char *RADEONMMIO = info->MMIO;
+
+    save->mc_fb_location     = INREG(RADEON_MC_FB_LOCATION);
+    save->mc_agp_location    = INREG(RADEON_MC_AGP_LOCATION);
+    save->display_base_addr  = INREG(RADEON_DISPLAY_BASE_ADDR);
+    save->display2_base_addr = INREG(RADEON_DISPLAY2_BASE_ADDR);
+    save->ov0_base_addr      = INREG(RADEON_OV0_BASE_ADDR);
+}
+
 /* Read common registers */
 static void RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
 {
@@ -6701,6 +6834,7 @@
     RADEONInfoPtr  info = RADEONPTR(pScrn);
 
     RADEONTRACE(("RADEONSaveMode(%p)\n", save));
+    RADEONSaveMemMapRegisters(pScrn, save);
     RADEONSaveCommonRegisters(pScrn, save);
     if (info->IsSecondary) {
 	RADEONSaveCrtc2Registers(pScrn, save);
@@ -6729,6 +6863,7 @@
 
     RADEONTRACE(("RADEONSave\n"));
     if (info->FBDev) {
+	RADEONSaveMemMapRegisters(pScrn, save);
 	fbdevHWSave(pScrn);
 	return;
     }
@@ -6912,6 +7047,22 @@
     int stop_req, max_stop_req;
     float read_return_rate, time_disp1_drop_priority;
 
+    /* 
+     * Set display0/1 priority up on r3/4xx in the memory controller for 
+     * high res modes if the user specifies HIGH for displaypriority 
+     * option.
+     */
+    if ((info->DispPriority == 2) && IS_R300_VARIANT) {
+        CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER);
+	if (info->MergedFB || pRADEONEnt->HasSecondary) {
+	    mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */
+	} else {
+	    mc_init_misc_lat_timer |= 0x0100; /* display 0 only */
+	}
+	OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
+    }
+
+
     /* R420 family not supported yet */
     if (info->ChipFamily == CHIP_FAMILY_R420) return; 
 
@@ -7820,8 +7971,9 @@
 }
 
 /* Define PLL registers for requested video mode */
-static void RADEONInitPLLRegisters(RADEONInfoPtr info, RADEONSavePtr save,
-                                  RADEONPLLPtr pll, double dot_clock)
+static void RADEONInitPLLRegisters(ScrnInfoPtr pScrn, RADEONInfoPtr info,
+				   RADEONSavePtr save, RADEONPLLPtr pll,
+				   double dot_clock)
 {
     unsigned long  freq = dot_clock * 100;
 
@@ -7885,8 +8037,9 @@
 }
 
 /* Define PLL2 registers for requested video mode */
-static void RADEONInitPLL2Registers(RADEONSavePtr save, RADEONPLLPtr pll,
-                                   double dot_clock, int no_odd_postdiv)
+static void RADEONInitPLL2Registers(ScrnInfoPtr pScrn, RADEONSavePtr save,
+				    RADEONPLLPtr pll, double dot_clock,
+				    int no_odd_postdiv)
 {
     unsigned long  freq = dot_clock * 100;
 
@@ -8014,11 +8167,12 @@
 
     info->Flags = mode->Flags;
 
+    RADEONInitMemMapRegisters(pScrn, save, info);
     RADEONInitCommonRegisters(save, info);
     if (info->IsSecondary) {
 	if (!RADEONInitCrtc2Registers(pScrn, save, mode, info))
 	    return FALSE;
-       RADEONInitPLL2Registers(save, &info->pll, dot_clock, info->DisplayType != MT_CRT);
+	RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->DisplayType != MT_CRT);
     } else if (info->MergedFB) {
         RADEONInitCommonRegisters(save, info);
         if (!RADEONInitCrtcRegisters(pScrn, save, 
@@ -8026,7 +8180,7 @@
             return FALSE;
         dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT1)->Clock / 1000.0;
         if (dot_clock) {
-            RADEONInitPLLRegisters(info, save, &info->pll, dot_clock);
+		RADEONInitPLLRegisters(pScrn, info, save, &info->pll, dot_clock);
         } else {
             save->ppll_ref_div = info->SavedReg.ppll_ref_div;
             save->ppll_div_3   = info->SavedReg.ppll_div_3;
@@ -8035,13 +8189,13 @@
         RADEONInitCrtc2Registers(pScrn, save, 
 			((RADEONMergedDisplayModePtr)mode->Private)->CRT2, info);
         dot_clock = (((RADEONMergedDisplayModePtr)mode->Private)->CRT2)->Clock / 1000.0;
-        RADEONInitPLL2Registers(save, &info->pll, dot_clock, info->MergeType != MT_CRT);
+        RADEONInitPLL2Registers(pScrn, save, &info->pll, dot_clock, info->MergeType != MT_CRT);
     } else {
 	if (!RADEONInitCrtcRegisters(pScrn, save, mode, info))
 	    return FALSE;
 	dot_clock = mode->Clock/1000.0;
 	if (dot_clock) {
-           RADEONInitPLLRegisters(info, save, &info->pll, dot_clock);
+		RADEONInitPLLRegisters(pScrn, info, save, &info->pll, dot_clock);
 	} else {
 	    save->ppll_ref_div = info->SavedReg.ppll_ref_div;
 	    save->ppll_div_3   = info->SavedReg.ppll_div_3;
@@ -8394,13 +8548,13 @@
     } else
 	if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
 
-    RADEONSetFBLocation(pScrn);
     if (!info->IsSecondary)
 	RADEONRestoreSurfaces(pScrn, &info->ModeReg);
 #ifdef XF86DRI
     if (info->directRenderingEnabled) {
 	/* get the Radeon back into shape after resume */
 	RADEONDRIResume(pScrn->pScreen);
+	RADEONAdjustMemMapRegisters(pScrn, &info->ModeReg);
     }
 #endif
     /* this will get XVideo going again, but only if XVideo was initialised






More information about the xorg mailing list