[PATCH] radeon: Fix errata
Benjamin Herrenschmidt
benh at kernel.crashing.org
Sun Mar 13 20:56:42 PST 2005
Hi !
This is my latest patch for the PLL access errata fixes. It also
fixes a couple of bogosity in the reading of the current PPLL index
in the clock probe code and LVDS panel probe code (used on PPC).
If Hui is ok with that version, it should be applied asap.
Ben.
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c 2005-03-04 13:58:17.000000000 +1100
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_driver.c 2005-03-14 15:53:20.000000000 +1100
@@ -64,9 +64,9 @@
/* Driver data structures */
#include "radeon.h"
+#include "radeon_reg.h"
#include "radeon_macros.h"
#include "radeon_probe.h"
-#include "radeon_reg.h"
#include "radeon_version.h"
#include "radeon_mergedfb.h"
@@ -712,24 +712,7 @@
return TRUE;
}
-/* This function is required to workaround a hardware bug in some (all?)
- * revisions of the R300. This workaround should be called after every
- * CLOCK_CNTL_INDEX register access. If not, register reads afterward
- * may not be correct.
- */
-void R300CGWorkaround(ScrnInfoPtr pScrn) {
- RADEONInfoPtr info = RADEONPTR(pScrn);
- unsigned char *RADEONMMIO = info->MMIO;
- CARD32 save, tmp;
-
- save = INREG(RADEON_CLOCK_CNTL_INDEX);
- tmp = save & ~(0x3f | RADEON_PLL_WR_EN);
- OUTREG(RADEON_CLOCK_CNTL_INDEX, tmp);
- tmp = INREG(RADEON_CLOCK_CNTL_DATA);
- OUTREG(RADEON_CLOCK_CNTL_INDEX, save);
-}
-
-/* Read PLL information */
+/* Read PLL register */
unsigned RADEONINPLL(ScrnInfoPtr pScrn, int addr)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
@@ -737,12 +720,27 @@
CARD32 data;
OUTREG8(RADEON_CLOCK_CNTL_INDEX, addr & 0x3f);
+ RADEONPllErrataAfterIndex(info);
data = INREG(RADEON_CLOCK_CNTL_DATA);
- if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+ RADEONPllErrataAfterData(info);
return data;
}
+/* Write PLL information */
+unsigned RADEONOUTPLL(ScrnInfoPtr pScrn, int addr, CARD32 data)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ OUTREG8(RADEON_CLOCK_CNTL_INDEX, (((addr) & 0x3f) |
+ RADEON_PLL_WR_EN));
+ RADEONPllErrataAfterIndex(info);
+ OUTREG(RADEON_CLOCK_CNTL_DATA, data);
+ RADEONPllErrataAfterData(info);
+}
+
+
#if 0
/* Read PAL information (only used for debugging) */
static int RADEONINPAL(int idx)
@@ -1287,8 +1285,8 @@
break;
}
- OUTREG(RADEON_CLOCK_CNTL_INDEX, 1);
- ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_DATA + 1) & 0x3;
+ ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3;
+ RADEONPllErrataAfterIndex(info);
n = (INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
m = (INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x3ff);
@@ -1441,15 +1439,15 @@
if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) {
CARD32 ppll_div_sel, ppll_val;
- OUTREG(RADEON_CLOCK_CNTL_INDEX, 1);
- ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_DATA + 1) & 0x3;
- ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel);
+ ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3;
+ RADEONPllErrataAfterIndex(info);
+ ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel);
if ((ppll_val & 0x000707ff) == 0x1bb)
- goto noprobe;
- info->FeedbackDivider = ppll_val & 0x7ff;
- info->PostDivider = (ppll_val >> 16) & 0x7;
- info->RefDivider = info->pll.reference_div;
- info->UseBiosDividers = TRUE;
+ goto noprobe;
+ info->FeedbackDivider = ppll_val & 0x7ff;
+ info->PostDivider = (ppll_val >> 16) & 0x7;
+ info->RefDivider = info->pll.reference_div;
+ info->UseBiosDividers = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Existing panel PLL dividers will be used.\n");
@@ -2548,10 +2546,22 @@
/* Some production boards of m6 will return 0 if it's 8 MB */
if (pScrn->videoRam == 0) pScrn->videoRam = 8192;
- info->R300CGWorkaround =
- (info->ChipFamily == CHIP_FAMILY_R300 &&
- (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK)
- == RADEON_CFG_ATI_REV_A11);
+ /* Check chip errata */
+ info->ChipErrata = 0;
+
+ if (info->ChipFamily == CHIP_FAMILY_R300 &&
+ (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK)
+ == RADEON_CFG_ATI_REV_A11)
+ info->ChipErrata |= CHIP_ERRATA_R300_CG;
+
+ if (info->ChipFamily == CHIP_FAMILY_RV200 ||
+ info->ChipFamily == CHIP_FAMILY_RS200)
+ info->ChipErrata |= CHIP_ERRATA_PLL_DUMMYREADS;
+
+ if (info->ChipFamily == CHIP_FAMILY_RV100 ||
+ info->ChipFamily == CHIP_FAMILY_RS100 ||
+ info->ChipFamily == CHIP_FAMILY_RS200)
+ info->ChipErrata |= CHIP_ERRATA_PLL_DELAY;
info->MemCntl = INREG(RADEON_SDRAM_MODE_REG);
info->BusCntl = INREG(RADEON_BUS_CNTL);
@@ -5693,7 +5703,7 @@
if (info->IsMobility || info->IsIGP) {
if (!(restore->lvds_gen_cntl & RADEON_LVDS_ON)) {
- OUTPLL(RADEON_PIXCLKS_CNTL, tmpPixclksCntl);
+ OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl);
}
}
}
@@ -5766,8 +5776,14 @@
By doing this we can avoid the blanking problem with some panels.
*/
if ((restore->ppll_ref_div == (INPLL(pScrn, RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) &&
- (restore->ppll_div_3 == (INPLL(pScrn, RADEON_PPLL_DIV_3) & (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK))))
- return;
+ (restore->ppll_div_3 == (INPLL(pScrn, RADEON_PPLL_DIV_3) &
+ (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) {
+ OUTREGP(RADEON_CLOCK_CNTL_INDEX,
+ RADEON_PLL_DIV_SEL,
+ ~(RADEON_PLL_DIV_SEL));
+ RADEONPllErrataAfterIndex(info);
+ return;
+ }
}
OUTPLLP(pScrn, RADEON_VCLK_ECP_CNTL,
@@ -5786,6 +5802,7 @@
OUTREGP(RADEON_CLOCK_CNTL_INDEX,
RADEON_PLL_DIV_SEL,
~(RADEON_PLL_DIV_SEL));
+ RADEONPllErrataAfterIndex(info);
if (IS_R300_VARIANT ||
(info->ChipFamily == CHIP_FAMILY_RS300)) {
@@ -5819,7 +5836,7 @@
RADEONPLLWriteUpdate(pScrn);
RADEONPLLWaitForReadUpdateComplete(pScrn);
- OUTPLL(RADEON_HTOTAL_CNTL, restore->htotal_cntl);
+ OUTPLL(pScrn, RADEON_HTOTAL_CNTL, restore->htotal_cntl);
OUTPLLP(pScrn, RADEON_PPLL_CNTL,
0,
@@ -5881,7 +5898,7 @@
RADEONPLL2WriteUpdate(pScrn);
RADEONPLL2WaitForReadUpdateComplete(pScrn);
- OUTPLL(RADEON_HTOTAL2_CNTL, restore->htotal_cntl2);
+ OUTPLL(pScrn, RADEON_HTOTAL2_CNTL, restore->htotal_cntl2);
OUTPLLP(pScrn, RADEON_P2PLL_CNTL,
0,
@@ -6394,7 +6411,7 @@
save->dp_datatype = INREG(RADEON_DP_DATATYPE);
save->rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET);
save->clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX);
- if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+ RADEONPllErrataAfterIndex(info);
}
RADEONSaveMode(pScrn, save);
@@ -6423,7 +6440,7 @@
RADEONBlank(pScrn);
OUTREG(RADEON_CLOCK_CNTL_INDEX, restore->clock_cntl_index);
- if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+ RADEONPllErrataAfterIndex(info);
OUTREG(RADEON_RBBM_SOFT_RESET, restore->rbbm_soft_reset);
OUTREG(RADEON_DP_DATATYPE, restore->dp_datatype);
OUTREG(RADEON_GRPH_BUFFER_CNTL, restore->grph_buffer_cntl);
@@ -8373,7 +8390,7 @@
~(RADEON_LVDS_BLON | RADEON_LVDS_ON));
if (info->IsMobility || info->IsIGP) {
- OUTPLL(RADEON_PIXCLKS_CNTL, tmpPixclksCntl);
+ OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmpPixclksCntl);
}
} else if (info->DisplayType == MT_CRT) {
if ((pRADEONEnt->HasSecondary) || info->MergedFB) {
@@ -8594,14 +8611,14 @@
RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB |
RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM |
RADEON_SCLK_FORCE_RB);
- OUTPLL(RADEON_SCLK_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
} else if (info->ChipFamily == CHIP_FAMILY_RV350) {
/* for RV350/M10, no delays are required. */
tmp = INPLL(pScrn, R300_SCLK_CNTL2);
tmp |= (R300_SCLK_FORCE_TCL |
R300_SCLK_FORCE_GA |
R300_SCLK_FORCE_CBA);
- OUTPLL(R300_SCLK_CNTL2, tmp);
+ OUTPLL(pScrn, R300_SCLK_CNTL2, tmp);
tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP |
@@ -8612,11 +8629,11 @@
R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX |
R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK |
R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0);
- OUTPLL(RADEON_SCLK_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
tmp |= RADEON_SCLK_MORE_FORCEON;
- OUTPLL(RADEON_SCLK_MORE_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp);
tmp = INPLL(pScrn, RADEON_MCLK_CNTL);
tmp |= (RADEON_FORCEON_MCLKA |
@@ -8624,13 +8641,13 @@
RADEON_FORCEON_YCLKA |
RADEON_FORCEON_YCLKB |
RADEON_FORCEON_MC);
- OUTPLL(RADEON_MCLK_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp);
tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
RADEON_PIXCLK_DAC_ALWAYS_ONb |
R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF);
- OUTPLL(RADEON_VCLK_ECP_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb |
@@ -8647,7 +8664,7 @@
R300_P2G2CLK_ALWAYS_ONb |
R300_P2G2CLK_ALWAYS_ONb |
R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF);
- OUTPLL(RADEON_PIXCLKS_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
} else {
tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2);
@@ -8684,7 +8701,7 @@
tmp |= ( R300_SCLK_FORCE_TCL |
R300_SCLK_FORCE_GA |
R300_SCLK_FORCE_CBA);
- OUTPLL(R300_SCLK_CNTL2, tmp);
+ OUTPLL(pScrn, R300_SCLK_CNTL2, tmp);
usleep(16000);
}
@@ -8701,7 +8718,7 @@
(info->ChipFamily == CHIP_FAMILY_RV280)) {
tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
tmp |= RADEON_SCLK_MORE_FORCEON;
- OUTPLL(RADEON_SCLK_MORE_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp);
usleep(16000);
}
@@ -8720,7 +8737,7 @@
tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
RADEON_PIXCLK_DAC_ALWAYS_ONb);
- OUTPLL(RADEON_VCLK_ECP_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Clock Scaling Disabled\n");
break;
@@ -8736,7 +8753,7 @@
RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE |
RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM |
RADEON_SCLK_FORCE_TDM);
- OUTPLL (RADEON_SCLK_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
} else if ((info->ChipFamily == CHIP_FAMILY_R300) ||
(info->ChipFamily == CHIP_FAMILY_R350) ||
(info->ChipFamily == CHIP_FAMILY_RV350)) {
@@ -8748,7 +8765,7 @@
tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT |
R300_SCLK_GA_MAX_DYN_STOP_LAT |
R300_SCLK_CBA_MAX_DYN_STOP_LAT);
- OUTPLL(R300_SCLK_CNTL2, tmp);
+ OUTPLL(pScrn, R300_SCLK_CNTL2, tmp);
tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
tmp &= ~(RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP |
@@ -8760,17 +8777,17 @@
R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK |
R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0);
tmp |= RADEON_DYN_STOP_LAT_MASK;
- OUTPLL(RADEON_SCLK_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
tmp &= ~RADEON_SCLK_MORE_FORCEON;
tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT;
- OUTPLL(RADEON_SCLK_MORE_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp);
tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
RADEON_PIXCLK_DAC_ALWAYS_ONb);
- OUTPLL(RADEON_VCLK_ECP_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
tmp = INPLL(pScrn, RADEON_PIXCLKS_CNTL);
tmp |= (RADEON_PIX2CLK_ALWAYS_ONb |
@@ -8786,12 +8803,12 @@
R300_PIXCLK_TVO_ALWAYS_ONb |
R300_P2G2CLK_ALWAYS_ONb |
R300_P2G2CLK_ALWAYS_ONb);
- OUTPLL(RADEON_PIXCLKS_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
tmp = INPLL(pScrn, RADEON_MCLK_MISC);
tmp |= (RADEON_MC_MCLK_DYN_ENABLE |
RADEON_IO_MCLK_DYN_ENABLE);
- OUTPLL(RADEON_MCLK_MISC, tmp);
+ OUTPLL(pScrn, RADEON_MCLK_MISC, tmp);
tmp = INPLL(pScrn, RADEON_MCLK_CNTL);
tmp |= (RADEON_FORCEON_MCLKA |
@@ -8820,19 +8837,19 @@
}
}
- OUTPLL(RADEON_MCLK_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_MCLK_CNTL, tmp);
} else {
tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
tmp &= ~(R300_SCLK_FORCE_VAP);
tmp |= RADEON_SCLK_FORCE_CP;
- OUTPLL(RADEON_SCLK_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
usleep(15000);
tmp = INPLL(pScrn, R300_SCLK_CNTL2);
tmp &= ~(R300_SCLK_FORCE_TCL |
R300_SCLK_FORCE_GA |
R300_SCLK_FORCE_CBA);
- OUTPLL(R300_SCLK_CNTL2, tmp);
+ OUTPLL(pScrn, R300_SCLK_CNTL2, tmp);
}
} else {
tmp = INPLL(pScrn, RADEON_CLK_PWRMGT_CNTL);
@@ -8843,12 +8860,12 @@
tmp |= (RADEON_ENGIN_DYNCLK_MODE |
(0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT));
- OUTPLL(RADEON_CLK_PWRMGT_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_CLK_PWRMGT_CNTL, tmp);
usleep(15000);
tmp = INPLL(pScrn, RADEON_CLK_PIN_CNTL);
tmp |= RADEON_SCLK_DYN_START_CNTL;
- OUTPLL(RADEON_CLK_PIN_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_CLK_PIN_CNTL, tmp);
usleep(15000);
/* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
@@ -8869,7 +8886,7 @@
tmp |= RADEON_SCLK_FORCE_VIP;
}
- OUTPLL(RADEON_SCLK_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
if ((info->ChipFamily == CHIP_FAMILY_RV200) ||
(info->ChipFamily == CHIP_FAMILY_RV250) ||
@@ -8884,7 +8901,7 @@
RADEON_CFG_ATI_REV_A13)) {
tmp |= RADEON_SCLK_MORE_FORCEON;
}
- OUTPLL(RADEON_SCLK_MORE_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_SCLK_MORE_CNTL, tmp);
usleep(15000);
}
@@ -8909,14 +8926,14 @@
RADEON_PIXCLK_LVDS_ALWAYS_ONb |
RADEON_PIXCLK_TMDS_ALWAYS_ONb);
- OUTPLL(RADEON_PIXCLKS_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_PIXCLKS_CNTL, tmp);
usleep(15000);
tmp = INPLL(pScrn, RADEON_VCLK_ECP_CNTL);
tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
RADEON_PIXCLK_DAC_ALWAYS_ONb);
- OUTPLL(RADEON_VCLK_ECP_CNTL, tmp);
+ OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, tmp);
usleep(15000);
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dynamic Clock Scaling Enabled\n");
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h 2004-07-31 08:20:21.000000000 +1000
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_macros.h 2005-03-14 15:47:43.000000000 +1100
@@ -84,19 +84,14 @@
#define INPLL(pScrn, addr) RADEONINPLL(pScrn, addr)
-#define OUTPLL(addr, val) \
-do { \
- OUTREG8(RADEON_CLOCK_CNTL_INDEX, (((addr) & 0x3f) | \
- RADEON_PLL_WR_EN)); \
- OUTREG(RADEON_CLOCK_CNTL_DATA, val); \
-} while (0)
+#define OUTPLL(pScrn, addr, val) RADEONOUTPLL(pScrn, addr, val)
#define OUTPLLP(pScrn, addr, val, mask) \
do { \
CARD32 tmp_ = INPLL(pScrn, addr); \
tmp_ &= (mask); \
tmp_ |= (val); \
- OUTPLL(addr, tmp_); \
+ OUTPLL(pScrn, addr, tmp_); \
} while (0)
#define OUTPAL_START(idx) \
@@ -138,5 +133,46 @@
} \
} while (0)
+static inline RADEONPllErrataAfterIndex(RADEONInfoPtr info)
+{
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ if (!(info->ChipErrata & CHIP_ERRATA_PLL_DUMMYREADS))
+ return;
+
+ /* This workaround is necessary on rv200 and RS200 or PLL
+ * reads may return garbage (among others...)
+ */
+ (void)INREG(RADEON_CLOCK_CNTL_DATA);
+ (void)INREG(RADEON_CRTC_GEN_CNTL);
+}
+
+static inline RADEONPllErrataAfterData(RADEONInfoPtr info)
+{
+ unsigned char *RADEONMMIO = info->MMIO;
+
+ /* This workarounds is necessary on RV100, RS100 and RS200 chips
+ * or the chip could hang on a subsequent access
+ */
+ if (info->ChipErrata & CHIP_ERRATA_PLL_DELAY) {
+ /* we can't deal with posted writes here ... */
+ usleep(5000);
+ }
+
+ /* This function is required to workaround a hardware bug in some (all?)
+ * revisions of the R300. This workaround should be called after every
+ * CLOCK_CNTL_INDEX register access. If not, register reads afterward
+ * may not be correct.
+ */
+ if (info->ChipErrata & CHIP_ERRATA_R300_CG) {
+ CARD32 save, tmp;
+
+ save = INREG(RADEON_CLOCK_CNTL_INDEX);
+ tmp = save & ~(0x3f | RADEON_PLL_WR_EN);
+ OUTREG(RADEON_CLOCK_CNTL_INDEX, tmp);
+ tmp = INREG(RADEON_CLOCK_CNTL_DATA);
+ OUTREG(RADEON_CLOCK_CNTL_INDEX, save);
+ }
+}
#endif
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon.h 2005-03-04 13:58:17.000000000 +1100
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon.h 2005-03-14 15:38:33.000000000 +1100
@@ -277,6 +277,16 @@
(info->ChipFamily == CHIP_FAMILY_RV380) || \
(info->ChipFamily == CHIP_FAMILY_R420))
+/*
+ * Errata workarounds
+ */
+typedef enum {
+ CHIP_ERRATA_R300_CG = 0x00000001,
+ CHIP_ERRATA_PLL_DUMMYREADS = 0x00000002,
+ CHIP_ERRATA_PLL_DELAY = 0x00000004,
+} RADEONErrata;
+
+
typedef struct {
CARD32 freq;
@@ -289,6 +299,7 @@
PCITAG PciTag;
int Chipset;
RADEONChipFamily ChipFamily;
+ RADEONErrata ChipErrata;
Bool FBDev;
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c 2005-01-27 14:31:22.000000000 +1100
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_accel.c 2005-03-14 15:42:51.000000000 +1100
@@ -72,9 +72,9 @@
/* Driver data structures */
#include "radeon.h"
+#include "radeon_reg.h"
#include "radeon_macros.h"
#include "radeon_probe.h"
-#include "radeon_reg.h"
#include "radeon_version.h"
#ifdef XF86DRI
#define _XF86DRI_SERVER_
@@ -196,7 +196,7 @@
RADEONEngineFlush(pScrn);
clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX);
- if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+ RADEONPllErrataAfterIndex(info);
#if 0 /* taken care of by new PM code */
/* Some ASICs have bugs with dynamic-on feature, which are
@@ -274,8 +274,8 @@
OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
- OUTPLL(RADEON_MCLK_CNTL, mclk_cntl);
- if (info->R300CGWorkaround) R300CGWorkaround(pScrn);
+ RADEONPllErrataAfterIndex(info);
+ OUTPLL(pScrn, RADEON_MCLK_CNTL, mclk_cntl);
}
/* Restore the acceleration hardware to its previous state */
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c 2005-03-08 11:26:26.000000000 +1100
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c 2005-03-14 15:39:50.000000000 +1100
@@ -38,9 +38,9 @@
/* Driver data structures */
#include "radeon.h"
+#include "radeon_reg.h"
#include "radeon_macros.h"
#include "radeon_dri.h"
-#include "radeon_reg.h"
#include "radeon_version.h"
/* X and server generic header files */
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.c
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.c 2005-03-04 13:58:17.000000000 +1100
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_mergedfb.c 2005-03-14 15:44:52.000000000 +1100
@@ -43,8 +43,8 @@
#include "radeon.h"
-#include "radeon_macros.h"
#include "radeon_reg.h"
+#include "radeon_macros.h"
#include "radeon_mergedfb.h"
/* psuedo xinerama support */
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c 2005-03-04 13:58:17.000000000 +1100
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c 2005-03-14 15:42:42.000000000 +1100
@@ -1,9 +1,9 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_video.c,v 1.30 2003/11/10 18:22:18 tsi Exp $ */
#include "radeon.h"
+#include "radeon_reg.h"
#include "radeon_macros.h"
#include "radeon_probe.h"
-#include "radeon_reg.h"
#include "radeon_mergedfb.h"
#include "radeon_video.h"
@@ -1323,8 +1323,8 @@
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Dotclock is %g Mhz, setting ecp_div to %d\n", info->ModeReg.dot_clock_freq/100.0, pPriv->ecp_div);
#endif
- OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) &
- 0xfffffCff) | (pPriv->ecp_div << 8));
+ OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) &
+ 0xfffffCff) | (pPriv->ecp_div << 8));
/* I suspect we may need a usleep after writing to the PLL. if you play a video too soon
after switching crtcs in mergedfb clone mode you get a temporary one pixel line of colorkey
@@ -1336,7 +1336,8 @@
(info->ChipFamily == CHIP_FAMILY_RS300)) {
/* Force the overlay clock on for integrated chips
*/
- OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) | (1<<18)));
+ OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL,
+ (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) | (1<<18)));
}
/* overlay scaler line length differs for different revisions
@@ -2301,7 +2302,8 @@
else
ecp_div = 1;
- OUTPLL(RADEON_VCLK_ECP_CNTL, (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (ecp_div << 8));
+ OUTPLL(pScrn, RADEON_VCLK_ECP_CNTL,
+ (INPLL(pScrn, RADEON_VCLK_ECP_CNTL) & 0xfffffCff) | (ecp_div << 8));
/* I suspect we may need a usleep after writing to the PLL. if you play a video too soon
after switching crtcs in mergedfb clone mode you get a temporary one pixel line of colorkey
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c 2004-11-23 14:58:47.000000000 +1100
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_cursor.c 2005-03-14 15:45:15.000000000 +1100
@@ -46,8 +46,8 @@
/* Driver data structures */
#include "radeon.h"
-#include "radeon_macros.h"
#include "radeon_reg.h"
+#include "radeon_macros.h"
#include "radeon_mergedfb.h"
/* X and server generic header files */
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_mm_i2c.c
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_mm_i2c.c 2004-10-04 09:54:40.000000000 +1000
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_mm_i2c.c 2005-03-14 15:48:23.000000000 +1100
@@ -1,7 +1,7 @@
#include "radeon.h"
+#include "radeon_reg.h"
#include "radeon_macros.h"
#include "radeon_probe.h"
-#include "radeon_reg.h"
#include "Xv.h"
#include "radeon_video.h"
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_bios.c
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_bios.c 2005-01-27 14:31:22.000000000 +1100
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_bios.c 2005-03-14 15:48:07.000000000 +1100
@@ -30,9 +30,9 @@
#include "xf86_OSproc.h"
#include "radeon.h"
+#include "radeon_reg.h"
#include "radeon_macros.h"
#include "radeon_probe.h"
-#include "radeon_reg.h"
#include "vbe.h"
/* Read the Video BIOS block and the FP registers (if applicable). */
Index: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_vip.c
===================================================================
--- xc.orig/programs/Xserver/hw/xfree86/drivers/ati/radeon_vip.c 2004-10-03 06:55:42.000000000 +1000
+++ xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_vip.c 2005-03-14 15:48:41.000000000 +1100
@@ -1,7 +1,7 @@
#include "radeon.h"
+#include "radeon_reg.h"
#include "radeon_macros.h"
#include "radeon_probe.h"
-#include "radeon_reg.h"
#include "Xv.h"
#include "radeon_video.h"
More information about the xorg
mailing list