Radeon mem map fix (#2): Need regression tests please

Benjamin Herrenschmidt benh at kernel.crashing.org
Sun Dec 18 22:36:38 PST 2005


On Mon, 2005-12-19 at 17:07 +1100, Benjamin Herrenschmidt wrote:

> 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

  .../...

And here's a new rev. of the patch that fixes a couple more things.

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 17:29:20.000000000 +1100
@@ -129,6 +129,8 @@
 static int RADEONValidateMergeModes(ScrnInfoPtr pScrn);
 static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode);
 static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn);
+static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save);
+static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save);
 
 /* psuedo xinerama support */
 
@@ -2252,83 +2254,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)
@@ -2704,22 +2715,28 @@
 
 	OUTREG(RADEON_CONFIG_MEMSIZE, pScrn->videoRam * 1024);
     } else {
-        /* There are different HDP mapping schemes depending on single/multi funciton setting,
-         * chip family, HDP mode, and the generation of HDP mapping scheme.
-         * To make things simple, we only allow maximum 128M addressable FB. Anything more than
-         * 128M is configured as invisible FB to CPU that can only be accessed from chip side.
-         */
+        /* There are different HDP mapping schemes depending on single/multi
+	 * funciton setting, chip family, HDP mode, and the generation of HDP
+	 * mapping scheme. To make things simple, we only allow maximum 128M
+	 * addressable FB. Anything more than 128M is configured as invisible
+	 * FB to CPU that can only be accessed from chip side.
+	 *
+	 * The above doesn't necessarily work. For example, I've seen machines
+	 * with 128Mb configured as 2x64Mb apertures. I'm now _always_ setting
+	 * RADEON_HOST_PATH_CNTL.
+	 */
         pScrn->videoRam      = INREG(RADEON_CONFIG_MEMSIZE) / 1024;
-        if (pScrn->videoRam > 128*1024) pScrn->videoRam = 128*1024;
-        if ((info->ChipFamily == CHIP_FAMILY_RV350) ||
-            (info->ChipFamily == CHIP_FAMILY_RV380) ||
-            (info->ChipFamily == CHIP_FAMILY_R420)) {
-	    OUTREGP (RADEON_HOST_PATH_CNTL, (1<<23), ~(1<<23));
-        }
+        if (pScrn->videoRam > 128*1024)
+	    pScrn->videoRam = 128*1024;
+	OUTREGP (RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL,
+		 ~RADEON_HDP_APER_CNTL);
     }
 
     /* 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
diff -urN xc-HEAD.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h
--- xc-HEAD.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h	2005-09-18 09:38:32.000000000 +1000
+++ xc-HEAD/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h	2005-12-19 17:27:24.000000000 +1100
@@ -812,6 +812,7 @@
 #define RADEON_HOST_DATA_LAST               0x17e0
 #define RADEON_HOST_PATH_CNTL               0x0130
 #       define RADEON_HDP_SOFT_RESET        (1 << 26)
+#       define RADEON_HDP_APER_CNTL         (1 << 23)
 #define RADEON_HTOTAL_CNTL                  0x0009 /* PLL */
 #define RADEON_HTOTAL2_CNTL                 0x002e /* PLL */
 





More information about the xorg mailing list