summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-03-16 03:14:11 +0000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-03-16 03:14:11 +0000
commitbb1cb23516f2a835bc8ba4f4bb168dad75429c35 (patch)
treef71a0291794d03c178d1d906b153a31fbc1b886e /src
parent6a7111d0b4408cc6862be2c4f39e731e081ffea4 (diff)
Add various workarounds that seem to fix some remaning lockup scenarios I'm
experiencing with the driver when setting the memory map. Some of the magic delays are a bit dodgy but they seem to work, I suppose I can't do better now without help from ATI. Also removed some really too noisy debug messages.
Diffstat (limited to 'src')
-rw-r--r--src/radeon_driver.c180
-rw-r--r--src/radeon_reg.h5
2 files changed, 148 insertions, 37 deletions
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index 6a004cf6..6f210472 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -1,5 +1,5 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c,v 1.117 2004/02/19 22:38:12 tsi Exp $ */
-/* $XdotOrg: driver/xf86-video-ati/src/radeon_driver.c,v 1.92.2.6 2006/03/13 00:14:15 benh Exp $ */
+/* $XdotOrg: driver/xf86-video-ati/src/radeon_driver.c,v 1.92.2.7 2006/03/15 04:12:43 benh Exp $ */
/*
* Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
* VA Linux Systems Inc., Fremont, California.
@@ -870,8 +870,14 @@ void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 crtc_gen_cntl;
int i;
+ crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL);
+ if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) ||
+ !(crtc_gen_cntl & RADEON_CRTC_EN))
+ return;
+
/* Clear the CRTC_VBLANK_SAVE bit */
OUTREG(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR);
@@ -887,7 +893,13 @@ void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 crtc2_gen_cntl;
int i;
+
+ crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
+ if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) ||
+ !(crtc2_gen_cntl & RADEON_CRTC2_EN))
+ return;
/* Clear the CRTC2_VBLANK_SAVE bit */
OUTREG(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR);
@@ -5168,8 +5180,6 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors,
int idx, j;
unsigned char r, g, b;
- RADEONTRACE(("RADEONLoadPalette !\n"));
-
#ifdef XF86DRI
if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0);
#endif
@@ -5288,8 +5298,6 @@ static void RADEONLoadPalette(ScrnInfoPtr pScrn, int numColors,
#ifdef XF86DRI
if (info->CPStarted && pScrn->pScreen) DRIUnlock(pScrn->pScreen);
#endif
-
- RADEONTRACE(("LoadPalette() end\n"));
}
static void RADEONBlockHandler(int i, pointer blockData,
@@ -6091,6 +6099,10 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen,
RADEONTRACE(("Initializing Xv\n"));
RADEONInitVideo(pScreen);
+ if(info->MergedFB)
+ /* need this here to fix up sarea values */
+ RADEONAdjustFrameMerged(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
/* Provide SaveScreen & wrap BlockHandler and CloseScreen */
/* Wrap CloseScreen */
info->CloseScreen = pScreen->CloseScreen;
@@ -6126,7 +6138,9 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn,
*/
if (INREG(RADEON_MC_FB_LOCATION) != restore->mc_fb_location ||
INREG(RADEON_MC_AGP_LOCATION) != restore->mc_agp_location) {
- CARD32 tmp;
+ CARD32 crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl=0, ov0_scale_cntl;
+ CARD32 old_mc_status, status_idle;
+ int timeout;
RADEONTRACE((" Map Changed ! Applying ...\n"));
@@ -6135,39 +6149,92 @@ static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn,
*/
RADEONWaitForIdleMMIO(pScrn);
+ if (info->IsIGP)
+ goto igp_no_mcfb;
+
+ /* Capture MC_STATUS in case things go wrong ... */
+ old_mc_status = INREG(RADEON_MC_STATUS);
+
/* 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);
+ ov0_scale_cntl = INREG(RADEON_OV0_SCALE_CNTL);
+ OUTREG(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE);
+ crtc_ext_cntl = INREG(RADEON_CRTC_EXT_CNTL);
+ OUTREG(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS);
+ crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL);
+ RADEONWaitForVerticalSync(pScrn);
+ OUTREG(RADEON_CRTC_GEN_CNTL,
+ (crtc_gen_cntl
+ & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN | RADEON_CRTC_EN))
+ | RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN);
+
+ if (info->HasCRTC2) {
+ crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL);
+ RADEONWaitForVerticalSync2(pScrn);
+ OUTREG(RADEON_CRTC2_GEN_CNTL,
+ (crtc2_gen_cntl
+ & ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN |
+ RADEON_CRTC2_EN))
+ | RADEON_CRTC2_DISP_REQ_EN_B | RADEON_CRTC2_EN);
+ }
+
+ /* Make sure the chip settles down (paranoid !) */
+ usleep(100000);
+
+ /* Wait for MC idle */
+ if (IS_R300_VARIANT)
+ status_idle = R300_MC_IDLE;
+ else
+ status_idle = RADEON_MC_IDLE;
+
+ while (!(INREG(RADEON_MC_STATUS) & status_idle)) {
+ if (++timeout > 1000000) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Timeout trying to update memory controller settings !\n");
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "MC_STATUS = 0x%08x (on entry = 0x%08x)\n",
+ INREG(RADEON_MC_STATUS), old_mc_status);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "You will probably crash now ... \n");
+ /* Nothing we can do except maybe try to kill the server,
+ * let's wait 2 seconds to leave the above message a chance
+ * to maybe hit the disk and continue trying to setup despite
+ * the MC being non-idle
+ */
+ usleep(2000000);
+ }
}
- tmp = INREG(RADEON_OV0_SCALE_CNTL);
- tmp &= ~RADEON_SCALER_ENABLE;
- OUTREG(RADEON_OV0_SCALE_CNTL, tmp);
- /* Make sure the chip settles down and set new map*/
- usleep(100000);
+ /* Update maps, first clearing out AGP to make sure we don't get
+ * a temporary overlap
+ */
+ OUTREG(RADEON_MC_AGP_LOCATION, 0xfffffffc);
OUTREG(RADEON_MC_FB_LOCATION, restore->mc_fb_location);
+ igp_no_mcfb:
OUTREG(RADEON_MC_AGP_LOCATION, restore->mc_agp_location);
/* Make sure map fully reached the chip */
(void)INREG(RADEON_MC_FB_LOCATION);
+ RADEONTRACE((" Map applied, resetting engine ...\n"));
+
/* Reset the engine and HDP */
RADEONEngineReset(pScrn);
+
+ RADEONTRACE((" All done.\n"));
}
-
+
+ RADEONTRACE(("Updating base addresses...\n"));
+
/* Restore base addresses */
OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr);
- OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr);
+ if (info->HasCRTC2)
+ OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr);
OUTREG(RADEON_OV0_BASE_ADDR, restore->ov0_base_addr);
-}
+
+ /* Flush PCI posting, make sure the above actually hit the card */
+ (void)INREG(RADEON_OV0_BASE_ADDR);
+
+ RADEONTRACE(("Done updating base addresses.\n"));
+ }
static void RADEONAdjustMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save)
{
@@ -6276,7 +6343,25 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
- OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl);
+ RADEONTRACE(("Programming CRTC1, offset: 0x%08x\n",
+ restore->crtc_offset));
+
+ /* Make sure we have sane offsets before enabling */
+ OUTREG(RADEON_CRTC_OFFSET, 0);
+ OUTREG(RADEON_CRTC_OFFSET_CNTL, 0);
+ OUTREG(RADEON_CUR_OFFSET, 0);
+
+ /* Magic delay ! This helps fixing a lockup on some setups, maybe
+ * the above need some time to properly hit the CRTC before we enable
+ * it, go figure ...
+ */
+ usleep(100000);
+
+ /* We prevent the CRTC from hitting the memory controller until
+ * fully programmed
+ */
+ OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl |
+ RADEON_CRTC_DISP_REQ_EN_B);
OUTREGP(RADEON_CRTC_EXT_CNTL,
restore->crtc_ext_cntl,
@@ -6305,6 +6390,8 @@ static void RADEONRestoreCrtcRegisters(ScrnInfoPtr pScrn,
OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
OUTREG(RADEON_CRTC2_GEN_CNTL, restore->crtc2_gen_cntl);
}
+
+ OUTREG(RADEON_CRTC_GEN_CNTL, restore->crtc_gen_cntl);
}
/* Write CRTC2 registers */
@@ -6313,12 +6400,33 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
{
RADEONInfoPtr info = RADEONPTR(pScrn);
unsigned char *RADEONMMIO = info->MMIO;
+ CARD32 crtc2_gen_cntl;
- OUTREGP(RADEON_CRTC2_GEN_CNTL,
- restore->crtc2_gen_cntl,
- RADEON_CRTC2_VSYNC_DIS |
- RADEON_CRTC2_HSYNC_DIS |
- RADEON_CRTC2_DISP_DIS);
+ RADEONTRACE(("Programming CRTC2, offset: 0x%08x\n",
+ restore->crtc2_offset));
+
+ /* Make sure we have sane offsets before enabling */
+ OUTREG(RADEON_CRTC2_OFFSET, 0);
+ OUTREG(RADEON_CRTC2_OFFSET_CNTL, 0);
+ OUTREG(RADEON_CUR2_OFFSET, 0);
+
+ /* Magic delay ! This helps fixing a lockup on some setups, maybe
+ * the above need some time to properly hit the CRTC before we enable
+ * it, go figure ...
+ */
+ usleep(100000);
+
+ crtc2_gen_cntl = INREG(RADEON_CRTC2_GEN_CNTL) &
+ (RADEON_CRTC2_VSYNC_DIS |
+ RADEON_CRTC2_HSYNC_DIS |
+ RADEON_CRTC2_DISP_DIS);
+ crtc2_gen_cntl |= restore->crtc2_gen_cntl;
+
+ /* We prevent the CRTC from hitting the memory controller until
+ * fully programmed
+ */
+ OUTREG(RADEON_CRTC2_GEN_CNTL,
+ crtc2_gen_cntl | RADEON_CRTC2_DISP_REQ_EN_B);
OUTREG(RADEON_DAC_CNTL2, restore->dac2_cntl);
@@ -6345,6 +6453,9 @@ static void RADEONRestoreCrtc2Registers(ScrnInfoPtr pScrn,
OUTREG(RADEON_FP_V2_SYNC_STRT_WID, restore->fp2_v_sync_strt_wid);
OUTREG(RADEON_FP2_GEN_CNTL, restore->fp2_gen_cntl);
}
+
+ OUTREG(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+
#if 0
/* Hack for restoring text mode -- fixed elsewhere */
usleep(100000);
@@ -8658,7 +8769,9 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone)
XF86DRISAREAPtr pSAREA;
#endif
+#if 0 /* Verbose */
RADEONTRACE(("RADEONDoAdjustFrame(%d,%d,%d)\n", x, y, clone));
+#endif
if (info->showCache && y) {
int lastline = info->FbMapSize /
@@ -8751,15 +8864,11 @@ void RADEONDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int clone)
}
#endif
- RADEONTRACE((" -> reg : 0x%04x = 0x%08x\n", reg, Base));
-
OUTREG(reg, Base);
if (IS_R300_VARIANT) {
- RADEONTRACE((" regcntl : 0x%04x = 0x%08x\n", xytilereg, crtcxytile));
OUTREG(xytilereg, crtcxytile);
} else {
- RADEONTRACE((" regcntl : 0x%04x = 0x%08x\n", regcntl, crtcoffsetcntl));
OUTREG(regcntl, crtcoffsetcntl);
}
@@ -8942,7 +9051,6 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen)
RADEONTRACE(("Disposing DGA\n"));
if (info->DGAModes) xfree(info->DGAModes);
info->DGAModes = NULL;
-
RADEONTRACE(("Unmapping memory\n"));
RADEONUnmapMem(pScrn);
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index c5dca461..71b10c02 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -307,9 +307,9 @@
# define RADEON_CRTC_DBL_SCAN_EN (1 << 0)
# define RADEON_CRTC_INTERLACE_EN (1 << 1)
# define RADEON_CRTC_CSYNC_EN (1 << 4)
+# define RADEON_CRTC_ICON_EN (1 << 15)
# define RADEON_CRTC_CUR_EN (1 << 16)
# define RADEON_CRTC_CUR_MODE_MASK (7 << 17)
-# define RADEON_CRTC_ICON_EN (1 << 20)
# define RADEON_CRTC_EXT_DISP_EN (1 << 24)
# define RADEON_CRTC_EN (1 << 25)
# define RADEON_CRTC_DISP_REQ_EN_B (1 << 26)
@@ -849,6 +849,9 @@
#define RADEON_MAX_LATENCY 0x0f3f /* PCI */
#define RADEON_MC_AGP_LOCATION 0x014c
#define RADEON_MC_FB_LOCATION 0x0148
+#define RADEON_MC_STATUS 0x0150
+# define RADEON_MC_IDLE (1 << 2)
+# define R300_MC_IDLE (1 << 4)
#define RADEON_DISPLAY_BASE_ADDR 0x23c
#define RADEON_DISPLAY2_BASE_ADDR 0x33c
#define RADEON_OV0_BASE_ADDR 0x43c