summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/atipreinit.c4
-rw-r--r--src/atiprobe.c13
-rw-r--r--src/ativga.c9
-rw-r--r--src/r128_accel.c8
-rw-r--r--src/r128_dri.c1
-rw-r--r--src/r128_driver.c6
-rw-r--r--src/r128_video.c6
-rw-r--r--src/radeon.h1
-rw-r--r--src/radeon_bios.c75
-rw-r--r--src/radeon_driver.c92
-rw-r--r--src/radeon_reg.h2
-rw-r--r--src/radeon_render.c103
12 files changed, 272 insertions, 48 deletions
diff --git a/src/atipreinit.c b/src/atipreinit.c
index ebe54ad..df11246 100644
--- a/src/atipreinit.c
+++ b/src/atipreinit.c
@@ -1918,11 +1918,11 @@ ATIPreInit
VBlankEnd += 0x0100U;
pATI->LCDHBlankWidth = HBlankEnd - HBlankStart;
- pATI->LCDHSyncStart = HSyncStart - HBlankStart - 1;
+ pATI->LCDHSyncStart = HSyncStart - HBlankStart;
pATI->LCDHSyncWidth = HSyncEnd - HSyncStart;
pATI->LCDVBlankWidth = VBlankEnd - VBlankStart;
- pATI->LCDVSyncStart = VSyncStart - VBlankStart - 1;
+ pATI->LCDVSyncStart = VSyncStart - VBlankStart;
pATI->LCDVSyncWidth = VSyncEnd - VSyncStart;
HDisplay = HTotal + 5 - pATI->LCDHBlankWidth;
diff --git a/src/atiprobe.c b/src/atiprobe.c
index 08cc56f..c7dff49 100644
--- a/src/atiprobe.c
+++ b/src/atiprobe.c
@@ -1243,6 +1243,10 @@ ATIProbe
xf86MsgVerb(X_INFO, 2, ATI_NAME ": Unshared VGA not probed.\n");
}
+ /*
+ * Mach8/32 probing doesn't work well on some legacy free ia64
+ * However if we use AVOID_CPIO we don't get here at all.
+ */
if (ATICheckSparseIOBases(NULL, ProbeFlags, 0x02E8U, 8,
fChipsets[ATI_CHIPSET_IBM8514] ||
fChipsets[ATI_CHIPSET_MACH8] ||
@@ -1275,6 +1279,10 @@ ATIProbe
ATI_NAME ": Unshared 8514/A not probed.\n");
}
+ /*
+ * Also NONPCI Mach64 probing is evil on legacy free platforms.
+ * However if we use AVOID_CPIO we don't get here at all.
+ */
for (i = 0; i < NumberOf(Mach64SparseIOBases); i++)
{
if (ATICheckSparseIOBases(NULL, ProbeFlags, Mach64SparseIOBases[i],
@@ -1309,7 +1317,6 @@ ATIProbe
ATIClaimSparseIOBases(ProbeFlags, Mach64SparseIOBases[i], 4,
DetectedMach64);
}
-
#endif /* AVOID_NON_PCI */
}
@@ -1539,7 +1546,6 @@ ATIProbe
ATIFindVGA(pVideo, &pVGA, &pATI, p8514,
ProbeFlags);
}
-
xf86SetPciVideo(NULL, NONE);
break;
}
@@ -1554,6 +1560,9 @@ ATIProbe
continue;
pPCI = pVideo->thisCard;
+ if (pPCI == NULL)
+ continue;
+
PciReg = pciReadLong(pPCI->tag, PCI_REG_USERCONFIG);
j = PciReg & 0x03U;
if (j == 0x03U)
diff --git a/src/ativga.c b/src/ativga.c
index 2ac97cd..7ecc700 100644
--- a/src/ativga.c
+++ b/src/ativga.c
@@ -185,7 +185,11 @@ ATIVGACalculate
(pATI->Chip >= ATI_CHIP_264CT))
pMode->CrtcHBlankStart--;
pMode->CrtcHSyncStart = pMode->HSyncStart >> 3;
+ if (pATI->LCDPanelID >= 0)
+ pMode->CrtcHSyncStart--;
pMode->CrtcHSyncEnd = pMode->HSyncEnd >> 3;
+ if (pATI->LCDPanelID >= 0)
+ pMode->CrtcHSyncEnd--;
pMode->CrtcHBlankEnd = (pMode->HTotal >> 3) - 1;
pMode->CrtcHTotal = (pMode->HTotal >> 3) - 5;
pMode->CrtcHSkew = pMode->HSkew;
@@ -327,6 +331,11 @@ ATIVGACalculate
pMode->CrtcVBlankStart++;
else
pMode->CrtcVBlankStart--;
+ if (pATI->LCDPanelID >= 0)
+ {
+ pMode->CrtcVSyncStart--;
+ pMode->CrtcVSyncEnd--;
+ }
pMode->CrtcVBlankEnd--;
if (pATI->Chip < ATI_CHIP_264CT)
pMode->CrtcVBlankEnd--;
diff --git a/src/r128_accel.c b/src/r128_accel.c
index 90c5cb5..ded73d5 100644
--- a/src/r128_accel.c
+++ b/src/r128_accel.c
@@ -237,17 +237,23 @@ void R128CCEWaitForIdle(ScrnInfoPtr pScrn)
i = 0;
do {
ret = drmCommandNone(info->drmFD, DRM_R128_CCE_IDLE);
- } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
+ } while ( ret && errno == EBUSY && i++ < (R128_IDLE_RETRY * R128_IDLE_RETRY) );
if (ret && ret != -EBUSY) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"%s: CCE idle %d\n", __FUNCTION__, ret);
}
+ if (i > R128_IDLE_RETRY) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "%s: (DEBUG) CCE idle took i = %d\n", __FUNCTION__, i);
+ }
+
if (ret == 0) return;
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Idle timed out, resetting engine...\n");
+ R128CCE_STOP(pScrn, info);
R128EngineReset(pScrn);
/* Always restart the engine when doing CCE 2D acceleration */
diff --git a/src/r128_dri.c b/src/r128_dri.c
index 2b35c33..65bb5b9 100644
--- a/src/r128_dri.c
+++ b/src/r128_dri.c
@@ -1297,6 +1297,7 @@ void R128DRICloseScreen(ScreenPtr pScreen)
if (info->irq) {
drmCtlUninstHandler(info->drmFD);
info->irq = 0;
+ info->gen_int_cntl = 0;
}
/* De-allocate vertex buffers */
diff --git a/src/r128_driver.c b/src/r128_driver.c
index 8167d00..c5dec60 100644
--- a/src/r128_driver.c
+++ b/src/r128_driver.c
@@ -1640,7 +1640,11 @@ static Bool R128PreInitModes(ScrnInfoPtr pScrn)
NULL, /* linePitches */
8 * 64, /* minPitch */
8 * 1024, /* maxPitch */
- 8 * 64, /* pitchInc */
+/*
+ * ATI docs say pitchInc must be 8 * 64, but this doesn't permit a pitch of
+ * 800 bytes, which is known to work on the Rage128 LF on clamshell iBooks
+ */
+ 8 * 32, /* pitchInc */
128, /* minHeight */
2048, /* maxHeight */
pScrn->display->virtualX,
diff --git a/src/r128_video.c b/src/r128_video.c
index 7ef31af..04d85e0 100644
--- a/src/r128_video.c
+++ b/src/r128_video.c
@@ -579,20 +579,20 @@ R128AllocateMemory(
pScreen = screenInfo.screens[pScrn->scrnIndex];
- new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8,
NULL, NULL, NULL);
if(!new_linear) {
int max_size;
- xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16,
+ xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8,
PRIORITY_EXTREME);
if(max_size < size)
return NULL;
xf86PurgeUnlockedOffscreenAreas(pScreen);
- new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16,
+ new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8,
NULL, NULL, NULL);
}
diff --git a/src/radeon.h b/src/radeon.h
index 523d2b7..636923a 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -555,6 +555,7 @@ typedef struct {
Bool RenderAccel;
Bool RenderInited3D;
FBLinearPtr RenderTex;
+ Bool RenderTexValidR100;
void (*RenderCallback)(ScrnInfoPtr);
Time RenderTimeout;
diff --git a/src/radeon_bios.c b/src/radeon_bios.c
index d54c9b9..37a3e26 100644
--- a/src/radeon_bios.c
+++ b/src/radeon_bios.c
@@ -198,13 +198,28 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
return FALSE;
}
} else {
+ /* Some laptops only have one connector (VGA) listed in the connector table,
+ * we need to add LVDS in as a non-DDC display.
+ * Note, we can't assume the listed VGA will be filled in PortInfo[0],
+ * when walking through connector table. connector_found has following meaning:
+ * 0 -- nothing found,
+ * 1 -- only PortInfo[0] filled,
+ * 2 -- only PortInfo[1] filled,
+ * 3 -- both are filled.
+ */
+ int connector_found = 0;
+
if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x50))) {
for (i = 1; i < 4; i++) {
if (!RADEON_BIOS8(tmp + i*2) && i > 1) break; /* end of table */
tmp0 = RADEON_BIOS16(tmp + i*2);
- if (((tmp0 >> 12) & 0x1f) == 0) continue; /* no connector */
+ if (((tmp0 >> 12) & 0x0f) == 0) continue; /* no connector */
+ if (connector_found > 0) {
+ if (pRADEONEnt->PortInfo[tmp1].DDCType == ((tmp0 >> 8) & 0x0f))
+ continue; /* same connector */
+ }
/* internal DDC_DVI port will get assigned to PortInfo[0], or if there is no DDC_DVI (like in some IGPs). */
tmp1 = ((((tmp0 >> 8) & 0xf) == DDC_DVI) || (tmp1 == 1)) ? 0 : 1; /* determine port info index */
@@ -222,9 +237,7 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
pRADEONEnt->PortInfo[tmp1].TMDSType == TMDS_INT)
pRADEONEnt->PortInfo[tmp1].TMDSType = TMDS_UNKNOWN;
- xf86DrvMsg(0, X_INFO, "Connector%d: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
- tmp1, pRADEONEnt->PortInfo[tmp1].DDCType, pRADEONEnt->PortInfo[tmp1].DACType,
- pRADEONEnt->PortInfo[tmp1].TMDSType, pRADEONEnt->PortInfo[tmp1].ConnectorType);
+ connector_found += (tmp1 + 1);
}
} else {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No Connector Info Table found!\n");
@@ -232,14 +245,54 @@ Bool RADEONGetConnectorInfoFromBIOS (ScrnInfoPtr pScrn)
}
if (info->IsMobility) {
- if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42))) {
- if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) {
- if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) {
- pRADEONEnt->PortInfo[0].DDCType = tmp1;
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n");
- }
+ /* For the cases where only one VGA connector is found,
+ we assume LVDS is not listed in the connector table,
+ add it in here as the first port.
+ */
+ if ((connector_found < 3) && (pRADEONEnt->PortInfo[tmp1].ConnectorType == CONNECTOR_CRT)) {
+ if (connector_found == 1) {
+ memcpy (&pRADEONEnt->PortInfo[1], &pRADEONEnt->PortInfo[0],
+ sizeof (pRADEONEnt->PortInfo[0]));
+ }
+ pRADEONEnt->PortInfo[0].DACType = DAC_TVDAC;
+ pRADEONEnt->PortInfo[0].TMDSType = TMDS_UNKNOWN;
+ pRADEONEnt->PortInfo[0].DDCType = DDC_NONE_DETECTED;
+ pRADEONEnt->PortInfo[0].ConnectorType = CONNECTOR_PROPRIETARY;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "LVDS port is not in connector table, added in.\n");
+ if (connector_found == 0) connector_found = 1;
+ else connector_found = 3;
}
- }
+
+ if ((tmp = RADEON_BIOS16(info->ROMHeaderStart + 0x42))) {
+ if ((tmp0 = RADEON_BIOS16(tmp + 0x15))) {
+ if ((tmp1 = RADEON_BIOS8(tmp0+2) & 0x07)) {
+ pRADEONEnt->PortInfo[0].DDCType = tmp1;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "LCD DDC Info Table found!\n");
+ }
+ }
+ }
+ } else if (connector_found == 2) {
+ memcpy (&pRADEONEnt->PortInfo[0], &pRADEONEnt->PortInfo[1],
+ sizeof (pRADEONEnt->PortInfo[0]));
+ pRADEONEnt->PortInfo[1].DACType = DAC_UNKNOWN;
+ pRADEONEnt->PortInfo[1].TMDSType = TMDS_UNKNOWN;
+ pRADEONEnt->PortInfo[1].DDCType = DDC_NONE_DETECTED;
+ pRADEONEnt->PortInfo[1].ConnectorType = CONNECTOR_NONE;
+ connector_found = 1;
+ }
+
+ if (connector_found == 0) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No connector found in Connector Info Table.\n");
+ } else {
+ xf86DrvMsg(0, X_INFO, "Connector0: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
+ pRADEONEnt->PortInfo[0].DDCType, pRADEONEnt->PortInfo[0].DACType,
+ pRADEONEnt->PortInfo[0].TMDSType, pRADEONEnt->PortInfo[0].ConnectorType);
+ }
+ if (connector_found == 3) {
+ xf86DrvMsg(0, X_INFO, "Connector1: DDCType-%d, DACType-%d, TMDSType-%d, ConnectorType-%d\n",
+ pRADEONEnt->PortInfo[1].DDCType, pRADEONEnt->PortInfo[1].DACType,
+ pRADEONEnt->PortInfo[1].TMDSType, pRADEONEnt->PortInfo[1].ConnectorType);
}
#if 0
diff --git a/src/radeon_driver.c b/src/radeon_driver.c
index cc90627..b9a6a3a 100644
--- a/src/radeon_driver.c
+++ b/src/radeon_driver.c
@@ -365,6 +365,7 @@ static const char *int10Symbols[] = {
"xf86InitInt10",
"xf86FreeInt10",
"xf86int10Addr",
+ "xf86ExecX86int10",
NULL
};
@@ -1311,7 +1312,7 @@ static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn)
info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1;
}
if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) {
- info->PanelXRes = ((fp_vert_stretch>>16) + 1) * 8;
+ info->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8;
} else {
info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8;
}
@@ -1712,6 +1713,13 @@ static BOOL RADEONQueryConnectedMonitors(ScrnInfoPtr pScrn)
break;
}
}
+ for (i = 0; i < max_mt; i++) {
+ if (strcmp(s2, MonTypeName[i]) == 0) {
+ pRADEONEnt->PortInfo[1].MonType = MonTypeID[i];
+ break;
+ }
+ }
+
if (i == max_mt)
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Invalid Monitor type specified for 2nd port \n");
@@ -1744,32 +1752,45 @@ static BOOL RADEONQueryConnectedMonitors(ScrnInfoPtr pScrn)
}
- if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) {
-
- if(((!info->HasCRTC2) || info->IsDellServer) &&
- (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN)) {
+ if(((!info->HasCRTC2) || info->IsDellServer)) {
+ if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) {
if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_DVI, &pRADEONEnt->PortInfo[0])));
else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_VGA, &pRADEONEnt->PortInfo[0])));
else if((pRADEONEnt->PortInfo[0].MonType = RADEONDisplayDDCConnected(pScrn, DDC_CRT2, &pRADEONEnt->PortInfo[0])));
else
pRADEONEnt->PortInfo[0].MonType = MT_CRT;
+ }
- if (!ignore_edid) {
- if (pRADEONEnt->PortInfo[0].MonInfo) {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n");
- xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo );
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n");
- }
+ if (!ignore_edid) {
+ if (pRADEONEnt->PortInfo[0].MonInfo) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Monitor1 EDID data ---------------------------\n");
+ xf86PrintEDID(pRADEONEnt->PortInfo[0].MonInfo );
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of Monitor1 EDID data --------------------\n");
}
-
- pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType;
- pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo;
- pRADEONEnt->MonType2 = MT_NONE;
- pRADEONEnt->MonInfo2 = NULL;
- info->MergeType = MT_NONE;
- return TRUE;
}
+ pRADEONEnt->MonType1 = pRADEONEnt->PortInfo[0].MonType;
+ pRADEONEnt->MonInfo1 = pRADEONEnt->PortInfo[0].MonInfo;
+ pRADEONEnt->MonType2 = MT_NONE;
+ pRADEONEnt->MonInfo2 = NULL;
+ info->MergeType = MT_NONE;
+ info->DisplayType = pRADEONEnt->MonType1;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "Primary:\n Monitor -- %s\n Connector -- %s\n DAC Type -- %s\n TMDS Type -- %s\n DDC Type -- %s\n",
+ MonTypeName[pRADEONEnt->PortInfo[0].MonType+1],
+ info->IsAtomBios ?
+ ConnectorTypeNameATOM[pRADEONEnt->PortInfo[0].ConnectorType]:
+ ConnectorTypeName[pRADEONEnt->PortInfo[0].ConnectorType],
+ DACTypeName[pRADEONEnt->PortInfo[0].DACType+1],
+ TMDSTypeName[pRADEONEnt->PortInfo[0].TMDSType+1],
+ DDCTypeName[pRADEONEnt->PortInfo[0].DDCType]);
+
+ return TRUE;
+ }
+
+ if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN || pRADEONEnt->PortInfo[1].MonType == MT_UNKNOWN) {
+
/* Primary Head (DVI or Laptop Int. panel)*/
/* A ddc capable display connected on DVI port */
if (pRADEONEnt->PortInfo[0].MonType == MT_UNKNOWN) {
@@ -2583,8 +2604,10 @@ static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn)
if (ddc->det_mon[j].type == 0) {
struct detailed_timings *d_timings =
&ddc->det_mon[j].section.d_timings;
- if (info->PanelXRes < d_timings->h_active &&
- info->PanelYRes < d_timings->v_active) {
+ if (info->PanelXRes <= d_timings->h_active &&
+ info->PanelYRes <= d_timings->v_active) {
+
+ if (info->DotClock) continue; /* Timings already inited */
info->PanelXRes = d_timings->h_active;
info->PanelYRes = d_timings->v_active;
@@ -3157,8 +3180,9 @@ static int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName)
new->next = NULL;
new->prev = last;
- last->next = new;
+ if (last) last->next = new;
last = new;
+ if (!first) first = new;
}
}
}
@@ -4471,10 +4495,12 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
RADEONSave(pScrn);
- if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
- RADEONSetDynamicClock(pScrn, 1);
- } else {
- RADEONSetDynamicClock(pScrn, 0);
+ if ((!info->IsSecondary) && info->IsMobility) {
+ if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) {
+ RADEONSetDynamicClock(pScrn, 1);
+ } else {
+ RADEONSetDynamicClock(pScrn, 0);
+ }
}
if (info->FBDev) {
@@ -7133,6 +7159,7 @@ void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags)
RADEONDoAdjustFrame(pScrn, x, y, FALSE);
}
+ RADEONSetFBLocation (pScrn);
#ifdef XF86DRI
if (info->CPStarted) DRIUnlock(pScrn->pScreen);
#endif
@@ -7145,9 +7172,22 @@ Bool RADEONEnterVT(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
RADEONInfoPtr info = RADEONPTR(pScrn);
+ unsigned char *RADEONMMIO = info->MMIO;
RADEONTRACE(("RADEONEnterVT\n"));
+ if (INREG(RADEON_CONFIG_MEMSIZE) == 0) { /* Softboot V_BIOS */
+ xf86Int10InfoPtr pInt;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "zero MEMSIZE, probably at D3cold. Re-POSTing via int10.\n");
+ pInt = xf86InitInt10 (info->pEnt->index);
+ if (pInt) {
+ pInt->num = 0xe6;
+ xf86ExecX86int10 (pInt);
+ xf86FreeInt10 (pInt);
+ }
+ }
+
if (info->FBDev) {
unsigned char *RADEONMMIO = info->MMIO;
if (!fbdevHWEnterVT(scrnIndex,flags)) return FALSE;
@@ -7158,6 +7198,8 @@ Bool RADEONEnterVT(int scrnIndex, int flags)
} else
if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE;
+ RADEONSetFBLocation (pScrn);
+
#ifdef XF86DRI
if (info->directRenderingEnabled) {
/* get the Radeon back into shape after resume */
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 8849cab..b56630c 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -803,7 +803,7 @@
# define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1<<12)
# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1<<13)
# define RADEON_MC_MCLK_DYN_ENABLE (1 << 14)
-# define RADEON_IO_MCLK_DYN_ENABLE (1 << 14)
+# define RADEON_IO_MCLK_DYN_ENABLE (1 << 15)
#define RADEON_MDGPIO_A_REG 0x01ac
#define RADEON_MDGPIO_EN_REG 0x01b0
#define RADEON_MDGPIO_MASK 0x0198
diff --git a/src/radeon_render.c b/src/radeon_render.c
index 145b653..9a218a3 100644
--- a/src/radeon_render.c
+++ b/src/radeon_render.c
@@ -7,6 +7,11 @@
#ifndef RENDER_GENERIC_HELPER
#define RENDER_GENERIC_HELPER
+/* R100 code path constants */
+/* Minimum working values for RV200: 65x8 - your mileage may vary */
+#define MAGIC_R100_MIN_TEX_WIDTH (65)
+#define MAGIC_R100_MIN_TEX_HEIGHT (8)
+
static void RadeonInit3DEngineMMIO(ScrnInfoPtr pScrn);
#ifdef XF86DRI
static void RadeonInit3DEngineCP(ScrnInfoPtr pScrn);
@@ -421,6 +426,8 @@ static Bool FUNC_NAME(R100SetupTexture)(
CARD8 *dst;
CARD32 tex_size = 0, txformat;
int dst_pitch, offset, size, i, tex_bytepp;
+ int offscreensize = (pScrn->bitsPerPixel >> 3) *
+ pScrn->displayWidth * MAGIC_R100_MIN_TEX_HEIGHT;
ACCEL_PREAMBLE();
if ((width > 2048) || (height > 2048))
@@ -440,7 +447,8 @@ static Bool FUNC_NAME(R100SetupTexture)(
dst_pitch = (width * tex_bytepp + 31) & ~31;
size = dst_pitch * height;
- if (!AllocateLinear(pScrn, size))
+ /* Allocate off-screen space for texture pre-rendering as well */
+ if (!AllocateLinear(pScrn, size + offscreensize))
return FALSE;
if (flags & XAA_RENDER_REPEAT) {
@@ -451,7 +459,7 @@ static Bool FUNC_NAME(R100SetupTexture)(
txformat |= RADEON_TXFORMAT_NON_POWER2;
}
- offset = info->RenderTex->offset * pScrn->bitsPerPixel / 8;
+ offset = info->RenderTex->offset * pScrn->bitsPerPixel / 8 + offscreensize;
/* Upload texture to card. Should use ImageWrite to avoid syncing. */
i = height;
@@ -481,6 +489,7 @@ static Bool FUNC_NAME(R100SetupTexture)(
RADEON_CLAMP_S_WRAP |
RADEON_CLAMP_T_WRAP);
FINISH_ACCEL();
+ info->RenderTexValidR100 = FALSE;
return TRUE;
}
@@ -608,6 +617,95 @@ FUNC_NAME(R100SubsequentCPUToScreenTexture) (
ACCEL_PREAMBLE();
+ /* R100 chips seem to have cache problems and do not reload small textures
+ * from memory for small render areas. Thus we have to render a
+ * 'sufficiently large' portion of the texture (may contain uninitialized
+ * data as well) to off-screen memory to invalidate the cache. */
+ if (!info->RenderTexValidR100 &&
+ width*height < MAGIC_R100_MIN_TEX_WIDTH*MAGIC_R100_MIN_TEX_HEIGHT)
+/* (width<MAGIC_R100_MIN_TEX_WIDTH || height<MAGIC_R100_MIN_TEX_HEIGHT))*/
+ {
+ fboffset = info->fbLocation + pScrn->fbOffset +
+ info->RenderTex->offset * (pScrn->bitsPerPixel >> 3);
+ l = 0.0;
+ t = 0.0;
+ r = MAGIC_R100_MIN_TEX_WIDTH;
+ b = MAGIC_R100_MIN_TEX_HEIGHT;
+
+#ifdef ACCEL_CP
+ BEGIN_RING(23);
+
+ OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset);
+
+ OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_3D_DRAW_IMMD, 17));
+ /* RADEON_SE_VTX_FMT */
+ OUT_RING(RADEON_CP_VC_FRMT_XY |
+ RADEON_CP_VC_FRMT_ST0);
+ /* SE_VF_CNTL */
+ OUT_RING(RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN |
+ RADEON_CP_VC_CNTL_PRIM_WALK_RING |
+ RADEON_CP_VC_CNTL_MAOS_ENABLE |
+ RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+ (4 << RADEON_CP_VC_CNTL_NUM_SHIFT));
+
+ OUT_RING(F_TO_DW(l));
+ OUT_RING(F_TO_DW(t));
+ OUT_RING(F_TO_DW(l));
+ OUT_RING(F_TO_DW(t));
+
+ OUT_RING(F_TO_DW(r));
+ OUT_RING(F_TO_DW(t));
+ OUT_RING(F_TO_DW(r));
+ OUT_RING(F_TO_DW(t));
+
+ OUT_RING(F_TO_DW(r));
+ OUT_RING(F_TO_DW(b));
+ OUT_RING(F_TO_DW(r));
+ OUT_RING(F_TO_DW(b));
+
+ OUT_RING(F_TO_DW(l));
+ OUT_RING(F_TO_DW(b));
+ OUT_RING(F_TO_DW(l));
+ OUT_RING(F_TO_DW(b));
+
+ OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+
+ ADVANCE_RING();
+#else
+ BEGIN_ACCEL(19);
+
+ OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, fboffset);
+
+ OUT_ACCEL_REG(RADEON_SE_VF_CNTL, RADEON_VF_PRIM_TYPE_TRIANGLE_FAN |
+ RADEON_VF_PRIM_WALK_DATA |
+ RADEON_VF_RADEON_MODE |
+ (4 << RADEON_VF_NUM_VERTICES_SHIFT));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(t));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(r));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b));
+
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(l));
+ OUT_ACCEL_REG(RADEON_SE_PORT_DATA0, F_TO_DW(b));
+
+ OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
+ FINISH_ACCEL();
+#endif
+ }
+
/* Note: we can't simply set up the 3D surface at the same location as the
* front buffer, because the 2048x2048 limit on coordinates may be smaller
* than the (MergedFB) screen.
@@ -696,6 +794,7 @@ FUNC_NAME(R100SubsequentCPUToScreenTexture) (
OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_3D_IDLECLEAN);
FINISH_ACCEL();
#endif
+ info->RenderTexValidR100 = TRUE;
}