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