summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2012-02-16 17:19:57 -0500
committerDave Airlie <airlied@gmail.com>2012-08-08 08:58:03 +1000
commit66dc826d24e50e31047ae1772f2a8e94ed3e1f56 (patch)
treec2dff2a10f458d15cd31e7d802239d8e736d0458
parent94b009ede2375a3c25ce20d9528f9d0ed13e2d11 (diff)
WIP: RANDR 1.2 skeleton
-rw-r--r--src/Makefile.am3
-rw-r--r--src/mga.h4
-rw-r--r--src/mga_dacG.c51
-rw-r--r--src/mga_driver.c291
-rw-r--r--src/mga_g_crtc.c1157
-rw-r--r--src/mga_g_output.c268
-rw-r--r--src/mga_randr.h45
-rw-r--r--src/mga_shadow.c8
8 files changed, 1739 insertions, 88 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index fd02fc5..9bdb384 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,6 +41,8 @@ mga_drv_la_SOURCES = \
mga_driver.c \
mga_esc.c \
mga_g450pll.c \
+ mga_g_crtc.c \
+ mga_g_output.c \
mga.h \
mga_hwcurs.c \
mga_macros.h \
@@ -48,6 +50,7 @@ mga_drv_la_SOURCES = \
mga_merge.c \
mga_merge.h \
mgareg_flags.h \
+ mga_randr.h \
mga_reg.h \
mga_sarea.h \
mga_shadow.c \
diff --git a/src/mga.h b/src/mga.h
index c7178b6..e9d1801 100644
--- a/src/mga.h
+++ b/src/mga.h
@@ -89,7 +89,8 @@ typedef enum {
OPTION_OLDDMA,
OPTION_PCIDMA,
OPTION_ACCELMETHOD,
- OPTION_KVM
+ OPTION_KVM,
+ OPTION_RANDR12,
} MGAOpts;
@@ -653,6 +654,7 @@ typedef struct {
ScrnInfoPtr pScrn2; /*pointer to second CRTC screeninforec,
if in merged mode */
/* End of Merged Framebuffer Data */
+ Bool randr12;
} MGARec, *MGAPtr;
extern CARD32 MGAAtype[16];
diff --git a/src/mga_dacG.c b/src/mga_dacG.c
index a9ededb..5f0b50f 100644
--- a/src/mga_dacG.c
+++ b/src/mga_dacG.c
@@ -19,6 +19,7 @@
#include "mga.h"
#include "mga_macros.h"
#include "mga_maven.h"
+#include "mga_randr.h"
#include "xf86DDC.h"
@@ -48,11 +49,10 @@ static void MGAGRamdacInit(ScrnInfoPtr);
static void MGAGSave(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
static void MGAGRestore(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
static Bool MGAGInit(ScrnInfoPtr, DisplayModePtr);
-static void MGAGLoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr);
static Bool MGAG_i2cInit(ScrnInfoPtr pScrn);
-static void
-MGAG200SEComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
+void
+MGAG200SEComputePLLParam(long lFo, int *M, int *N, int *P)
{
unsigned int ulComputedFo;
unsigned int ulFDelta;
@@ -96,8 +96,8 @@ MGAG200SEComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
}
}
-static void
-MGAG200EVComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
+void
+MGAG200EVComputePLLParam(long lFo, int *M, int *N, int *P)
{
unsigned int ulComputedFo;
unsigned int ulFDelta;
@@ -140,15 +140,10 @@ MGAG200EVComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
}
}
}
-#if DEBUG
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "lFo=%ld n=0x%x m=0x%x p=0x%x \n",
- lFo, *N, *M, *P );
-#endif
}
-static void
-MGAG200WBComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
+void
+MGAG200WBComputePLLParam(long lFo, int *M, int *N, int *P)
{
unsigned int ulComputedFo;
unsigned int ulFDelta;
@@ -200,15 +195,10 @@ MGAG200WBComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
}
}
}
-#if DEBUG
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "lFo=%ld n=0x%x m=0x%x p=0x%x \n",
- lFo, *N, *M, *P );
-#endif
}
-static void
-MGAG200EHComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
+void
+MGAG200EHComputePLLParam(long lFo, int *M, int *N, int *P)
{
unsigned int ulComputedFo;
unsigned int ulFDelta;
@@ -445,7 +435,8 @@ MGAG200WBPIXPLLSET(ScrnInfoPtr pScrn, MGARegPtr mgaReg)
#define G200ER_VCOMIN 1056000
#define G200ER_VCOMAX 1488000
-static void MGAG200ERComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *piM, int *piN, int *piP)
+void
+MGAG200ERComputePLLParam(long lFo, int *piM, int *piN, int *piP)
{
int ulM;
@@ -853,31 +844,31 @@ MGAGSetPCLK( ScrnInfoPtr pScrn, long f_out )
}
if (pMga->is_G200SE) {
- MGAG200SEComputePLLParam(pScrn, f_out, &m, &n, &p);
+ MGAG200SEComputePLLParam(f_out, &m, &n, &p);
pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m;
pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n;
pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = p;
} else if (pMga->is_G200EV) {
- MGAG200EVComputePLLParam(pScrn, f_out, &m, &n, &p);
+ MGAG200EVComputePLLParam(f_out, &m, &n, &p);
pReg->PllM = m;
pReg->PllN = n;
pReg->PllP = p;
} else if (pMga->is_G200WB) {
- MGAG200WBComputePLLParam(pScrn, f_out, &m, &n, &p);
+ MGAG200WBComputePLLParam(f_out, &m, &n, &p);
pReg->PllM = m;
pReg->PllN = n;
pReg->PllP = p;
- } else if (pMga->is_G200EH) {
- MGAG200EHComputePLLParam(pScrn, f_out, &m, &n, &p);
+ } else if (pMga->is_G200EH) {
+ MGAG200EHComputePLLParam(f_out, &m, &n, &p);
pReg->PllM = m;
pReg->PllN = n;
pReg->PllP = p;
} else if (pMga->is_G200ER) {
- MGAG200ERComputePLLParam(pScrn, f_out, &m, &n, &p);
+ MGAG200ERComputePLLParam(f_out, &m, &n, &p);
pReg->PllM = m;
pReg->PllN = n;
pReg->PllP = p;
@@ -1330,7 +1321,7 @@ void MGAGLoadPalette(
* MGAGRestorePalette
*/
-static void
+void
MGAGRestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
{
MGAPtr pMga = MGAPTR(pScrn);
@@ -1344,7 +1335,7 @@ MGAGRestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
/*
* MGAGSavePalette
*/
-static void
+void
MGAGSavePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
{
MGAPtr pMga = MGAPTR(pScrn);
@@ -1861,12 +1852,12 @@ mgag_create_i2c_bus(const char *name, unsigned bus_index, unsigned scrn_index)
I2CBusPtr I2CPtr = xf86CreateI2CBusRec();
if (I2CPtr != NULL) {
- I2CPtr->BusName = name;
+ I2CPtr->BusName = (char *)name;
I2CPtr->scrnIndex = scrn_index;
I2CPtr->I2CPutBits = MGAG_I2CPutBits;
I2CPtr->I2CGetBits = MGAG_I2CGetBits;
I2CPtr->AcknTimeout = 5;
- I2CPtr->DriverPrivate.ptr = & i2c_priv[bus_index];
+ I2CPtr->DriverPrivate.ptr = (void *)&i2c_priv[bus_index];
if (!xf86I2CBusInit(I2CPtr)) {
xf86DestroyI2CBusRec(I2CPtr, TRUE, TRUE);
diff --git a/src/mga_driver.c b/src/mga_driver.c
index b90d5b8..7de5f5e 100644
--- a/src/mga_driver.c
+++ b/src/mga_driver.c
@@ -102,6 +102,8 @@
#include "dri.h"
#endif
+#include "mga_randr.h"
+
#include <unistd.h>
/*
@@ -558,6 +560,7 @@ static const OptionInfoRec MGAOptions[] = {
{ OPTION_PCIDMA, "ForcePciDma", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_ACCELMETHOD, "AccelMethod", OPTV_ANYSTR, {0}, FALSE },
{ OPTION_KVM, "KVM", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_RANDR12, "RANDR12", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
@@ -1368,6 +1371,29 @@ MGAMavenRead(ScrnInfoPtr pScrn, I2CByte reg, I2CByte *val)
return TRUE;
}
+static void
+setup_outputs(ScrnInfoPtr scrn)
+{
+ xf86OutputPtr output;
+
+ output = MGAG200EOutputInit(scrn);
+ output->possible_crtcs = 1;
+ output->possible_clones = 1;
+}
+
+static Bool
+crtc_config_resize(ScrnInfoPtr pScrn, int width, int height)
+{
+ pScrn->virtualX = width;
+ pScrn->virtualY = height;
+
+ return TRUE;
+}
+
+static const xf86CrtcConfigFuncsRec crtc_config_funcs = {
+ .resize = crtc_config_resize,
+};
+
/* Mandatory */
static Bool
MGAPreInit(ScrnInfoPtr pScrn, int flags)
@@ -1924,6 +1950,26 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags)
}
} /* ISMGAGx50() */
}
+
+ /*
+ * Note this means you can ask for RANDR 1.2 on a chipset where it's not
+ * implemented. That'll probably crash. Don't do that.
+ */
+ if (!xf86GetOptValBool(pMga->Options, OPTION_RANDR12, &pMga->randr12)) {
+ switch (pMga->Chipset) {
+ case PCI_CHIP_MGAG200_SE_A_PCI:
+ case PCI_CHIP_MGAG200_SE_B_PCI:
+ case PCI_CHIP_MGAG200_WINBOND_PCI:
+ case PCI_CHIP_MGAG200_EV_PCI:
+ case PCI_CHIP_MGAG200_EH_PCI:
+ case PCI_CHIP_MGAG200_ER_PCI:
+ pMga->randr12 = TRUE;
+ break;
+ default:
+ pMga->randr12 = FALSE;
+ }
+ }
+
if (pMga->FBDev) {
pScrn->SwitchMode = fbdevHWSwitchModeWeak();
pScrn->AdjustFrame = fbdevHWAdjustFrameWeak();
@@ -2100,32 +2146,60 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags)
pMga->BppShifts[2] = 0;
pMga->BppShifts[3] = 2;
+ if (pMga->randr12) {
+ xf86CrtcConfigInit(pScrn, &crtc_config_funcs);
+
+ /* who even knows if this is accurate */
+ xf86CrtcSetSizeRange(pScrn, 320, 200, 2560, 1024);
+
+ MGAGCrtc1Init(pScrn);
+ if (pMga->i2cInit)
+ pMga->i2cInit(pScrn);
+
+ setup_outputs(pScrn);
+ }
+
/*
* fill MGAdac struct
* Warning: currently, it should be after RAM counting
*/
(*pMga->PreInit)(pScrn);
+ if (!pMga->randr12) {
#if !defined(__powerpc__)
-
- /* Read and print the Monitor DDC info */
- pScrn->monitor->DDC = MGAdoDDC(pScrn);
+ /* Read and print the Monitor DDC info */
+ pScrn->monitor->DDC = MGAdoDDC(pScrn);
#endif /* !__powerpc__ */
- if (!pScrn->monitor->DDC && pMga->is_G200SE) {
- /* Jam in ranges big enough for 1024x768 */
- if (!pScrn->monitor->nHsync) {
- pScrn->monitor->nHsync = 1;
- pScrn->monitor->hsync[0].lo = 31.5;
- pScrn->monitor->hsync[0].hi = 48.0;
+ if (!pScrn->monitor->DDC && pMga->is_G200SE) {
+ /* Jam in ranges big enough for 1024x768 */
+ if (!pScrn->monitor->nHsync) {
+ pScrn->monitor->nHsync = 1;
+ pScrn->monitor->hsync[0].lo = 31.5;
+ pScrn->monitor->hsync[0].hi = 48.0;
+ }
+ if (!pScrn->monitor->nVrefresh) {
+ pScrn->monitor->nVrefresh = 1;
+ pScrn->monitor->vrefresh[0].lo = 56.0;
+ pScrn->monitor->vrefresh[0].hi = 75.0;
+ }
}
- if (!pScrn->monitor->nVrefresh) {
- pScrn->monitor->nVrefresh = 1;
- pScrn->monitor->vrefresh[0].lo = 56.0;
- pScrn->monitor->vrefresh[0].hi = 75.0;
+ }
+
+ if (pMga->randr12) {
+ if (!MGAMapMem(pScrn)) {
+ ErrorF("cannot map memory for probing\n");
+ return FALSE;
}
+
+ if (!xf86InitialConfiguration(pScrn, TRUE)) {
+ MGAUnmapMem(pScrn);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial config failed\n");
+ return FALSE;
+ }
+
+ MGAUnmapMem(pScrn);
}
-
/*
* If the driver can do gamma correction, it should call xf86SetGamma()
@@ -2225,7 +2299,7 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags)
* pScrn->maxVValue are set. Since our MGAValidMode() already takes
* care of this, we don't worry about setting them here.
*/
- {
+ if (!pMga->randr12) {
int Pitches1[] =
{640, 768, 800, 960, 1024, 1152, 1280, 1600, 1920, 2048, 0};
int Pitches2[] =
@@ -2285,26 +2359,31 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags)
LOOKUP_BEST_REFRESH);
free(linePitches);
- }
- if (i < 1 && pMga->FBDev) {
- fbdevHWUseBuildinMode(pScrn);
- pScrn->displayWidth = pScrn->virtualX; /* FIXME: might be wrong */
- i = 1;
- }
- if (i == -1) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Validate Modes Failed\n");
- MGAFreeRec(pScrn);
- return FALSE;
- }
+ if (i < 1 && pMga->FBDev) {
+ fbdevHWUseBuildinMode(pScrn);
+ pScrn->displayWidth = pScrn->virtualX; /* FIXME: might be wrong */
+ i = 1;
+ }
+ if (i == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Validate Modes Failed\n");
+ MGAFreeRec(pScrn);
+ return FALSE;
+ }
- /* Prune the modes marked as invalid */
- xf86PruneDriverModes(pScrn);
+ /* Prune the modes marked as invalid */
+ xf86PruneDriverModes(pScrn);
- if (i == 0 || pScrn->modes == NULL) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
- MGAFreeRec(pScrn);
- return FALSE;
+ if (i == 0 || pScrn->modes == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ MGAFreeRec(pScrn);
+ return FALSE;
+ }
+ } else { /* RANDR 1.2 */
+ if (!xf86RandR12PreInit(pScrn)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RANDR init failure\n");
+ return FALSE;
+ }
}
/* If the Device section explicitly set HasSDRAM, don't bother checking.
@@ -2395,7 +2474,7 @@ MGAPreInit(ScrnInfoPtr pScrn, int flags)
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "YDstOrg is set to %d\n",
pMga->YDstOrg);
- if(pMga->DualHeadEnabled) {
+ if(pMga->DualHeadEnabled && !pMga->randr12) {
if(pMga->SecondCrtc == FALSE) {
pMga->FbUsableSize = pMgaEnt->masterFbMapSize;
/* Allocate HW cursor buffer at the end of video ram */
@@ -2660,12 +2739,33 @@ MGASave(ScrnInfoPtr pScrn)
(*pMga->Save)(pScrn, vgaReg, mgaReg, pMga->Primary);
}
+static void
+MGARandR12Save(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int i;
+
+ /* Save CRTC states */
+ for (i = 0; i < config->num_crtc; i++) {
+ xf86CrtcPtr crtc = config->crtc[i];
+ crtc->funcs->save(crtc);
+ }
+
+ /* Save output states */
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ output->funcs->save(output);
+ }
+}
+
/*
* Initialise a new mode. This is currently still using the old
* "initialise struct, restore/write struct to HW" model. That could
* be changed.
*/
+/* JX this is MGASetMode in the branch; needed? */
+
static Bool
MGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
@@ -2715,7 +2815,7 @@ MGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
}
/* Reset tagfifo*/
- if (pMga->is_G200ER)
+ if (pMga->is_G200ER)
{
CARD32 ulMemCtl = INREG(MGAREG_MEMCTL);
CARD8 ucSeq1;
@@ -2741,7 +2841,7 @@ MGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
Higher HiPriLvl will reduce drawing performance
We need to give enough bandwith to crtc to avoid visual artifact
*/
- if (pMga->is_G200SE)
+ if (pMga->is_G200SE)
{
if (pMga->reg_1e24 >= 0x02)
{
@@ -2787,12 +2887,12 @@ MGAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Clock == %d\n", mode->Clock);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BitsPerPixel == %d\n", pScrn->bitsPerPixel);
OUTREG8(0x1FDE, 0x06);
- if (pMga->reg_1e24 >= 0x01)
+ if (pMga->reg_1e24 >= 0x01)
{
OUTREG8(0x1FDF, 0x03);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl == 03\n");
}
- else
+ else
{
OUTREG8(0x1FDF, 0x14);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "HiPriLvl == 14h\n");
@@ -2914,6 +3014,27 @@ MGARestore(ScrnInfoPtr pScrn)
}
}
+static void
+MGARandR12Restore(ScrnInfoPtr pScrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int i;
+
+ if (pScrn->pScreen != NULL)
+ MGAStormSync(pScrn);
+
+ /* Restore CRTC states */
+ for (i = 0; i < config->num_crtc; i++) {
+ xf86CrtcPtr crtc = config->crtc[i];
+ crtc->funcs->restore(crtc);
+ }
+
+ /* Restore output states */
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ output->funcs->restore(output);
+ }
+}
/* Workaround for a G400 CRTC2 display problem */
static void
@@ -3013,8 +3134,8 @@ MGAScreenInit(SCREEN_INIT_ARGS_DECL)
pPriv = xf86GetEntityPrivate(pScrn->entityList[0], MGAEntityIndex);
pMgaEnt = pPriv->ptr;
pMgaEnt->refCount++;
- } else {
}
+
if (pMga->is_G200SE) {
pScrn->videoRam = VRTemp;
pMga->FbMapSize = FBTemp;
@@ -3025,7 +3146,14 @@ MGAScreenInit(SCREEN_INIT_ARGS_DECL)
vgaHWGetIOBase(hwp);
/* Map the VGA memory when the primary video */
- if (!pMga->FBDev) {
+ if (pMga->randr12) {
+ pScrn->vtSema = TRUE;
+
+ MGARandR12Save(pScrn);
+ xf86SetDesiredModes(pScrn);
+ MGAStormSync(pScrn);
+ MGAStormEngineInit(pScrn);
+ } else if (!pMga->FBDev) {
if (pMga->Primary) {
hwp->MapSize = 0x10000;
if (!vgaHWMapMem(pScrn))
@@ -3037,8 +3165,7 @@ MGAScreenInit(SCREEN_INIT_ARGS_DECL)
/* Initialise the first mode */
if (!MGAModeInit(pScrn, pScrn->currentMode))
return FALSE;
- }
- else {
+ } else {
fbdevHWSave(pScrn);
/* Disable VGA core, and leave memory access on */
#ifdef XSERVER_LIBPCIACCESS
@@ -3061,8 +3188,10 @@ MGAScreenInit(SCREEN_INIT_ARGS_DECL)
/* Darken the screen for aesthetic reasons and set the viewport
*/
- (*pScreen->SaveScreen)(pScreen, SCREEN_SAVER_ON);
- pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
+ if (!pMga->randr12) {
+ (*pScreen->SaveScreen)(pScreen, SCREEN_SAVER_ON);
+ pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
+ }
/*
@@ -3109,15 +3238,28 @@ MGAScreenInit(SCREEN_INIT_ARGS_DECL)
* pScreen fields.
*/
- width = pScrn->virtualX;
+ if (pMga->randr12) {
+ width = displayWidth = pScrn->displayWidth = pScrn->virtualX;
+ } else {
+ width = pScrn->virtualX;
+ displayWidth = pScrn->displayWidth;
+ }
height = pScrn->virtualY;
- displayWidth = pScrn->displayWidth;
if(pMga->ShadowFB) {
- pMga->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
- pMga->ShadowPtr = malloc(pMga->ShadowPitch * height);
+ /*
+ * I don't really feel like faffing about with resizing the
+ * shadow buffer when the front buffer grows in RANDR, so I'm
+ * just going to allocate enough up front and let the upload hook
+ * correct for width.
+ */
+ if (pMga->randr12)
+ pMga->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * 2048);
+ else
+ pMga->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
+
displayWidth = pMga->ShadowPitch / (pScrn->bitsPerPixel >> 3);
- FBStart = pMga->ShadowPtr;
+ FBStart = pMga->ShadowPtr = malloc(pMga->ShadowPitch * height);
} else {
pMga->ShadowPtr = NULL;
FBStart = pMga->FbStart;
@@ -3198,7 +3340,8 @@ MGAScreenInit(SCREEN_INIT_ARGS_DECL)
pMga->BlockHandler = pScreen->BlockHandler;
pScreen->BlockHandler = MGABlockHandler;
- if(!pMga->ShadowFB) /* hardware cursor needs to wrap this layer */
+ /* hardware cursor needs to wrap this layer */
+ if (!pMga->ShadowFB && !pMga->randr12)
MGADGAInit(pScreen);
if (!pMga->NoAccel) {
@@ -3214,6 +3357,9 @@ MGAScreenInit(SCREEN_INIT_ARGS_DECL)
#endif
}
+ if (pMga->randr12 && !MGAEnterVT(VT_FUNC_ARGS))
+ return FALSE;
+
miInitializeBackingStore(pScreen);
xf86SetBackingStore(pScreen);
xf86SetSilkenMouse(pScreen);
@@ -3229,7 +3375,7 @@ MGAScreenInit(SCREEN_INIT_ARGS_DECL)
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Hardware cursor initialization failed\n");
}
- if(pMga->MergedFB) {
+ if (pMga->MergedFB && !pMga->randr12) {
/* Rotate and MergedFB are mutiualy exclusive, so we can use this
* variable.
*/
@@ -3260,11 +3406,22 @@ MGAScreenInit(SCREEN_INIT_ARGS_DECL)
ShadowFBInit(pScreen, refreshArea);
}
- xf86DPMSInit(pScreen, mga_dpms_set_proc, 0);
+ if (pMga->randr12)
+ xf86DPMSInit(pScreen, xf86DPMSSet, 0);
+ else
+ xf86DPMSInit(pScreen, mga_dpms_set_proc, 0);
pScrn->memPhysBase = pMga->FbAddress;
pScrn->fbOffset = pMga->YDstOrg * (pScrn->bitsPerPixel / 8);
+ if (pMga->randr12) {
+ pScreen->SaveScreen = xf86SaveScreen;
+ pMga->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = MGACloseScreen;
+
+ xf86CrtcScreenInit(pScreen);
+ }
+
MGAInitVideo(pScreen);
#ifdef MGADRI
@@ -3285,8 +3442,10 @@ MGAScreenInit(SCREEN_INIT_ARGS_DECL)
#endif
/* Wrap the current CloseScreen function */
- pMga->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = MGACloseScreen;
+ if (!pMga->randr12) {
+ pMga->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = MGACloseScreen;
+ }
/* Report any unused options (only for the first generation) */
if (serverGeneration == 1) {
@@ -3393,6 +3552,19 @@ MGAAdjustFrameCrtc2(ADJUST_FRAME_ARGS_DECL)
* We may wish to unmap video/MMIO memory too.
*/
+static Bool
+MGARandR12EnterVT(VT_FUNC_ARGS_DECL)
+{
+ SCRN_INFO_PTR(arg);
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ xf86SetDesiredModes(pScrn);
+ MGAStormSync(pScrn);
+ MGAStormEngineInit(pScrn);
+
+ return TRUE;
+}
+
/* Mandatory */
static Bool
MGAEnterVT(VT_FUNC_ARGS_DECL)
@@ -3402,6 +3574,9 @@ MGAEnterVT(VT_FUNC_ARGS_DECL)
pMga = MGAPTR(pScrn);
+ if (pMga->randr12)
+ return MGARandR12EnterVT(VT_FUNC_ARGS);
+
#ifdef MGADRI
if (pMga->directRenderingEnabled) {
if (pMga->irq) {
@@ -3472,7 +3647,10 @@ MGALeaveVT(VT_FUNC_ARGS_DECL)
ScreenPtr pScreen;
#endif
- MGARestore(pScrn);
+ if (pMga->randr12)
+ MGARandR12Restore(pScrn);
+ else
+ MGARestore(pScrn);
vgaHWLock(hwp);
#ifdef MGADRI
@@ -3524,7 +3702,10 @@ MGACloseScreen(CLOSE_SCREEN_ARGS_DECL)
fbdevHWRestore(pScrn);
MGAUnmapMem(pScrn);
} else {
- MGARestore(pScrn);
+ if (pMga->randr12)
+ MGARandR12Restore(pScrn);
+ else
+ MGARestore(pScrn);
vgaHWLock(hwp);
MGAUnmapMem(pScrn);
vgaHWUnmapMem(pScrn);
diff --git a/src/mga_g_crtc.c b/src/mga_g_crtc.c
new file mode 100644
index 0000000..ebeeaef
--- /dev/null
+++ b/src/mga_g_crtc.c
@@ -0,0 +1,1157 @@
+/*
+ * Copyright 2007 Tilman Sauerbeck
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software")
+ * to deal in the software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * them Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Tilman Sauerbeck <tilman@code-monkey.de>
+ * Adam Jackson <ajax@redhat.com>
+ *
+ * Sources:
+ * xf86-video-intel, mga_dacG.c
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* All drivers should typically include these */
+#include "xf86.h"
+#include "xf86_OSproc.h"
+
+/* Drivers for PCI hardware need this */
+#include "xf86PciInfo.h"
+
+/* Drivers that need to access the PCI config space directly need this */
+#include "xf86Pci.h"
+
+#include "mga_reg.h"
+#include "mga.h"
+#include "mga_macros.h"
+#include "mga_randr.h"
+
+#include <unistd.h>
+
+/*
+ * Only change bits shown in this mask. Ideally reserved bits should be
+ * zeroed here. Also, don't change the vgaioen bit here since it is
+ * controlled elsewhere.
+ *
+ * XXX These settings need to be checked.
+ */
+#define OPTION1_MASK 0xFFFFFEFF
+#define OPTION2_MASK 0xFFFFFFFF
+#define OPTION3_MASK 0xFFFFFFFF
+
+#define OPTION1_MASK_PRIMARY 0xFFFC0FF
+
+typedef struct {
+ unsigned char ExtVga[6];
+ unsigned char DacRegs[0x50];
+ unsigned char PllM;
+ unsigned char PllN;
+ unsigned char PllP;
+ unsigned char ExtVga_Index24;
+ unsigned char Dac_Index90;
+ CARD32 Option;
+ CARD32 Option2;
+ CARD32 Option3;
+ Bool PIXPLLCSaved;
+ long clock;
+} MgaCrtcStateRec, *MgaCrtcStatePtr;
+
+typedef struct {
+ MgaCrtcStateRec saved_state;
+} MgaCrtcDataRec, *MgaCrtcDataPtr;
+
+static void
+MGAG200WBPrepareForModeSwitch(ScrnInfoPtr pScrn)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ unsigned char ucTmpData = 0;
+ int ulIterationMax = 0;
+ // 1- The first step is to warn the BMC of an upcoming mode change.
+ // We are putting the misc<0> to output.
+ ucTmpData = inMGAdac(MGA1064_GEN_IO_CTL);
+ ucTmpData |= 0x10;
+ outMGAdac(MGA1064_GEN_IO_CTL, ucTmpData);
+
+ // We are putting a 1 on the misc<0> line.
+ ucTmpData = inMGAdac(MGA1064_GEN_IO_DATA);
+ ucTmpData |= 0x10;
+ outMGAdac(MGA1064_GEN_IO_DATA, ucTmpData);
+
+ // 2- The second step is to mask any further scan request
+ // This will be done by asserting the remfreqmsk bit (XSPAREREG<7>)
+ ucTmpData = inMGAdac(MGA1064_SPAREREG);
+ ucTmpData |= 0x80;
+ outMGAdac(MGA1064_SPAREREG, ucTmpData);
+
+ // 3a- The third step is to verify if there is an active scan
+ // We are searching for a 0 on remhsyncsts (XSPAREREG<0>)
+ ulIterationMax = 300;
+ while (!(ucTmpData & 0x01) && ulIterationMax)
+ {
+ ucTmpData = inMGAdac(MGA1064_SPAREREG);
+ usleep(1000);
+ ulIterationMax--;
+ }
+
+ // 3b- This step occurs only if the remote is actually scanning
+ // We are waiting for the end of the frame which is a 1 on
+ // remvsyncsts (XSPAREREG<1>)
+ if (ulIterationMax)
+ {
+ ulIterationMax = 300;
+ while ((ucTmpData & 0x02) && ulIterationMax)
+ {
+ ucTmpData = inMGAdac(MGA1064_SPAREREG);
+ usleep(1000);
+ ulIterationMax--;
+ }
+ }
+}
+
+static void
+MGAG200WBRestoreFromModeSwitch(ScrnInfoPtr pScrn)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ unsigned char ucTmpData = 0;
+
+ // 1- The first step is to ensure that the vrsten and hrsten are set
+ OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01);
+ ucTmpData = INREG8(MGAREG_CRTCEXT_DATA);
+ OUTREG8(MGAREG_CRTCEXT_DATA, ucTmpData | 0x88);
+
+ // 2- The second step is is to assert the rstlvl2
+ ucTmpData = inMGAdac(MGA1064_REMHEADCTL2);
+ ucTmpData |= 0x08;
+ outMGAdac(MGA1064_REMHEADCTL2, ucTmpData);
+
+ // - Wait for 10 us
+ usleep(10);
+
+ // 3- The next step is is to deassert the rstlvl2
+ ucTmpData &= ~0x08;
+ outMGAdac(MGA1064_REMHEADCTL2, ucTmpData);
+
+ // - Wait for 10 us
+ usleep(10);
+
+ // 4- The fourth step is to remove the mask of scan request
+ // This will be done by deasserting the remfreqmsk bit (XSPAREREG<7>)
+ ucTmpData = inMGAdac(MGA1064_SPAREREG);
+ ucTmpData &= ~0x80;
+ outMGAdac(MGA1064_SPAREREG, ucTmpData);
+
+ // 5- Finally, we are putting back a 0 on the misc<0> line.
+ ucTmpData = inMGAdac(MGA1064_GEN_IO_DATA);
+ ucTmpData &= ~0x10;
+ outMGAdac(MGA1064_GEN_IO_DATA, ucTmpData);
+}
+
+static void
+MGAG200EVPIXPLLSET(ScrnInfoPtr pScrn, MgaCrtcStatePtr mgaReg)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ unsigned char ucTempByte, ucPixCtrl;
+
+ // Set pixclkdis to 1
+ ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ // Select PLL Set C
+ ucTempByte = INREG8(MGAREG_MEM_MISC_READ);
+ ucTempByte |= 0x3<<2; //select MGA pixel clock
+ OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte);
+
+ // Set pixlock to 0
+ ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT);
+ outMGAdac(MGA1064_PIX_PLL_STAT, ucTempByte & ~0x40);
+
+ // Set pix_stby to 1
+ ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ // Program the Pixel PLL Register
+ outMGAdac(MGA1064_EV_PIX_PLLC_M, mgaReg->PllM);
+ outMGAdac(MGA1064_EV_PIX_PLLC_N, mgaReg->PllN);
+ outMGAdac(MGA1064_EV_PIX_PLLC_P, mgaReg->PllP);
+
+ // Wait 50 us
+ usleep(50);
+
+ // Set pix_stby to 0
+ ucPixCtrl &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ // Wait 500 us
+ usleep(500);
+
+ // Select the pixel PLL by setting pixclksel to 1
+ ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+ ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
+
+ // Set pixlock to 1
+ ucTempByte = inMGAdac(MGA1064_PIX_PLL_STAT);
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte | 0x40);
+
+ // Reset dotclock rate bit.
+ ucTempByte = INREG8(MGAREG_MEM_MISC_READ);
+ ucTempByte |= 0x3<<2; //select MGA pixel clock
+ OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte);
+
+ OUTREG8(MGAREG_SEQ_INDEX, 1);
+ ucTempByte = INREG8(MGAREG_SEQ_DATA);
+ OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8);
+
+ // Set pixclkdis to 0
+ ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
+}
+
+static void
+MGAG200WBPIXPLLSET(ScrnInfoPtr pScrn, MgaCrtcStatePtr mgaReg)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ unsigned long ulLoopCount, ulLockCheckIterations = 0, ulTempCount, ulVCount;
+ unsigned char ucTempByte, ucPixCtrl, ucPLLLocked = FALSE;
+
+ while(ulLockCheckIterations <= 32 && ucPLLLocked == FALSE)
+ {
+ if(ulLockCheckIterations > 0)
+ {
+ OUTREG8(MGAREG_CRTCEXT_INDEX, 0x1E);
+ ucTempByte = INREG8(MGAREG_CRTCEXT_DATA);
+ if(ucTempByte < 0xFF)
+ {
+ OUTREG8(MGAREG_CRTCEXT_DATA, ucTempByte+1);
+ }
+ }
+
+ // Set pixclkdis to 1
+ ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
+ ucTempByte |= MGA1064_REMHEADCTL_CLKDIS;
+ outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
+
+ // Select PLL Set C
+ ucTempByte = INREG8(MGAREG_MEM_MISC_READ);
+ ucTempByte |= 0x3<<2; //select MGA pixel clock
+ OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte);
+
+ ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ // Wait 500 us
+ usleep(500);
+
+ // Reset the PLL
+ // When we are varying the output frequency by more than
+ // 10%, we must reset the PLL. However to be prudent, we
+ // will reset it each time that we are changing it.
+ ucTempByte = inMGAdac(MGA1064_VREF_CTL);
+ ucTempByte &= ~0x04;
+ outMGAdac(MGA1064_VREF_CTL, ucTempByte );
+
+ // Wait 50 us
+ usleep(50);
+
+ // Program the Pixel PLL Register
+ outMGAdac(MGA1064_WB_PIX_PLLC_N, mgaReg->PllN);
+ outMGAdac(MGA1064_WB_PIX_PLLC_M, mgaReg->PllM);
+ outMGAdac(MGA1064_WB_PIX_PLLC_P, mgaReg->PllP);
+
+ // Wait 50 us
+ usleep(50);
+
+ // Turning the PLL on
+ ucTempByte = inMGAdac(MGA1064_VREF_CTL);
+ ucTempByte |= 0x04;
+ outMGAdac(MGA1064_VREF_CTL, ucTempByte );
+
+ // Wait 500 us
+ usleep(500);
+
+ // Select the pixel PLL by setting pixclksel to 1
+ ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+ ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
+
+ ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
+ ucTempByte &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
+ ucTempByte |= MGA1064_REMHEADCTL_CLKSL_PLL;
+ outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
+
+ // Reset dotclock rate bit.
+ OUTREG8(MGAREG_SEQ_INDEX, 1);
+ ucTempByte = INREG8(MGAREG_SEQ_DATA);
+ OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8);
+
+ // Set pixclkdis to 0
+ ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
+
+ // Poll VCount. If it increments twice inside 150us,
+ // we assume that the PLL has locked.
+ ulLoopCount = 0;
+ ulVCount = INREG(MGAREG_VCOUNT);
+
+ while(ulLoopCount < 30 && ucPLLLocked == FALSE)
+ {
+ ulTempCount = INREG(MGAREG_VCOUNT);
+
+ if(ulTempCount < ulVCount)
+ {
+ ulVCount = 0;
+ }
+ if ((ucTempByte - ulVCount) > 2)
+ {
+ ucPLLLocked = TRUE;
+ }
+ else
+ {
+ usleep(5);
+ }
+ ulLoopCount++;
+ }
+ ulLockCheckIterations++;
+ }
+
+ // Set remclkdis to 0
+ ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
+ ucTempByte &= ~MGA1064_REMHEADCTL_CLKDIS;
+ outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
+}
+
+static void
+MGAG200ERPIXPLLSET(ScrnInfoPtr pScrn, MgaCrtcStatePtr mgaReg)
+{
+ //TODO G200ER Validate sequence
+ CARD8 ucPixCtrl, ucTempByte;
+ MGAPtr pMga = MGAPTR(pScrn);
+
+
+ // Set pixclkdis to 1
+ ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ ucTempByte = inMGAdac(MGA1064_REMHEADCTL);
+ ucTempByte |= MGA1064_REMHEADCTL_CLKDIS;
+ outMGAdac(MGA1064_REMHEADCTL, ucTempByte);
+
+ // Select PLL Set C
+ ucTempByte = INREG8(MGAREG_MEM_MISC_READ);
+ ucTempByte |= (0x3<<2) | 0xc0; //select MGA pixel clock
+ OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte);
+
+ ucPixCtrl &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+ ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ // Wait 500 us
+ usleep(500);
+
+ // Program the Pixel PLL Register
+ outMGAdac(MGA1064_ER_PIX_PLLC_N, mgaReg->PllN);
+ outMGAdac(MGA1064_ER_PIX_PLLC_M, mgaReg->PllM);
+ outMGAdac(MGA1064_ER_PIX_PLLC_P, mgaReg->PllP);
+
+ // Wait 50 us
+ usleep(50);
+
+}
+
+static void
+MGAG200EHPIXPLLSET(ScrnInfoPtr pScrn, MgaCrtcStatePtr mgaReg)
+{
+ MGAPtr pMga = MGAPTR(pScrn);
+
+ unsigned long ulFallBackCounter, ulLoopCount, ulLockCheckIterations = 0, ulTempCount, ulVCount;
+ unsigned char ucTempByte, ucPixCtrl, ucPLLLocked = FALSE;
+ unsigned char ucM;
+ unsigned char ucN;
+ unsigned char ucP;
+ unsigned char ucS;
+
+ while(ulLockCheckIterations <= 32 && ucPLLLocked == FALSE)
+ {
+ // Set pixclkdis to 1
+ ucPixCtrl = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_DIS;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ // Select PLL Set C
+ ucTempByte = INREG8(MGAREG_MEM_MISC_READ);
+ ucTempByte |= 0x3<<2; //select MGA pixel clock
+ OUTREG8(MGAREG_MEM_MISC_WRITE, ucTempByte);
+
+ ucPixCtrl |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+ ucPixCtrl &= ~0x80;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucPixCtrl);
+
+ // Wait 500 us
+ usleep(500);
+
+ // Program the Pixel PLL Register
+ outMGAdac(MGA1064_EH_PIX_PLLC_N, mgaReg->PllN);
+ outMGAdac(MGA1064_EH_PIX_PLLC_M, mgaReg->PllM);
+ outMGAdac(MGA1064_EH_PIX_PLLC_P, mgaReg->PllP);
+
+ // Wait 500 us
+ usleep(500);
+
+ // Select the pixel PLL by setting pixclksel to 1
+ ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucTempByte &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
+ ucTempByte |= MGA1064_PIX_CLK_CTL_SEL_PLL;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
+
+ // Reset dotclock rate bit.
+ OUTREG8(MGAREG_SEQ_INDEX, 1);
+ ucTempByte = INREG8(MGAREG_SEQ_DATA);
+ OUTREG8(MGAREG_SEQ_DATA, ucTempByte & ~0x8);
+
+ // Set pixclkdis to 0 and pixplldn to 0
+ ucTempByte = inMGAdac(MGA1064_PIX_CLK_CTL);
+ ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
+ ucTempByte &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
+ outMGAdac(MGA1064_PIX_CLK_CTL, ucTempByte);
+
+ // Poll VCount. If it increments twice inside 150us,
+ // we assume that the PLL has locked.
+ ulLoopCount = 0;
+ ulVCount = INREG(MGAREG_VCOUNT);
+
+ while(ulLoopCount < 30 && ucPLLLocked == FALSE)
+ {
+ ulTempCount = INREG(MGAREG_VCOUNT);
+
+ if(ulTempCount < ulVCount)
+ {
+ ulVCount = 0;
+ }
+ if ((ucTempByte - ulVCount) > 2)
+ {
+ ucPLLLocked = TRUE;
+ }
+ else
+ {
+ usleep(5);
+ }
+ ulLoopCount++;
+ }
+ ulLockCheckIterations++;
+ }
+}
+
+
+static void crtc_dpms(xf86CrtcPtr crtc, int mode);
+static void crtc_save(xf86CrtcPtr crtc);
+static void crtc_restore(xf86CrtcPtr crtc);
+static Bool crtc_lock(xf86CrtcPtr crtc);
+static void crtc_unlock(xf86CrtcPtr crtc);
+static Bool crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode);
+static void crtc_prepare(xf86CrtcPtr crtc);
+static void crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode, int x, int y);
+static void crtc_commit(xf86CrtcPtr crtc);
+static void crtc_destroy(xf86CrtcPtr crtc);
+
+static const xf86CrtcFuncsRec crtc_funcs = {
+ .dpms = crtc_dpms,
+ .save = crtc_save,
+ .restore = crtc_restore,
+ .lock = crtc_lock,
+ .unlock = crtc_unlock,
+ .mode_fixup = crtc_mode_fixup,
+ .prepare = crtc_prepare,
+ .mode_set = crtc_mode_set,
+ .commit = crtc_commit,
+ .destroy = crtc_destroy
+};
+
+static void
+crtc_dpms(xf86CrtcPtr crtc, int mode)
+{
+}
+
+/*
+ * MGAGSetPCLK - Set the pixel (PCLK) clock.
+ */
+static void
+MGAGSetPCLK(xf86CrtcPtr crtc, MgaCrtcStatePtr state, long f_out)
+{
+ MGAPtr pMga = MGAPTR(crtc->scrn);
+
+ /* Pixel clock values */
+ int m, n, p;
+
+ if (MGAISGx50(pMga)) {
+ state->clock = f_out;
+ return;
+ }
+
+ if (pMga->is_G200SE) {
+ MGAG200SEComputePLLParam(f_out, &m, &n, &p);
+ /* the asymmetry here bugs me */
+ state->DacRegs[MGA1064_PIX_PLLC_M] = m;
+ state->DacRegs[MGA1064_PIX_PLLC_N] = n;
+ state->DacRegs[MGA1064_PIX_PLLC_P] = p;
+ } else {
+ if (pMga->is_G200EV) {
+ MGAG200EVComputePLLParam(f_out, &m, &n, &p);
+ } else if (pMga->is_G200WB) {
+ MGAG200WBComputePLLParam(f_out, &m, &n, &p);
+ } else if (pMga->is_G200EH) {
+ MGAG200EHComputePLLParam(f_out, &m, &n, &p);
+ } else if (pMga->is_G200ER) {
+ MGAG200ERComputePLLParam(f_out, &m, &n, &p);
+ }
+
+ state->PllM = m;
+ state->PllN = n;
+ state->PllP = p;
+ }
+}
+
+static void
+state_set(xf86CrtcPtr crtc, MgaCrtcStatePtr state,
+ DisplayModePtr mode, int x, int y)
+{
+ /*
+ * initial values of the DAC registers
+ */
+ const static unsigned char initDAC[] = {
+ /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0,
+ /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x18: */ 0x00, 0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
+ /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ /* 0x28: */ 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x40,
+ /* 0x30: */ 0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
+ /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
+ /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ int i;
+ int hd, hs, he, ht, vd, vs, ve, vt, wd;
+ int BppShift;
+ MGAPtr pMga = MGAPTR(crtc->scrn);
+ vgaRegPtr vga = &VGAHWPTR(crtc->scrn)->ModeReg;
+ unsigned int startadd = (y * crtc->scrn->virtualX) + x;
+
+ BppShift = pMga->BppShifts[(crtc->scrn->bitsPerPixel >> 3) - 1];
+
+ for (i = 0; i < sizeof(state->DacRegs); i++)
+ state->DacRegs[i] = initDAC[i];
+
+ switch (pMga->Chipset) {
+ case PCI_CHIP_MGAG200_SE_A_PCI:
+ case PCI_CHIP_MGAG200_SE_B_PCI:
+ state->DacRegs[MGA1064_VREF_CTL] = 0x03;
+ state->DacRegs[MGA1064_PIX_CLK_CTL] =
+ MGA1064_PIX_CLK_CTL_SEL_PLL;
+
+ state->DacRegs[MGA1064_MISC_CTL] =
+ MGA1064_MISC_CTL_DAC_EN |
+ MGA1064_MISC_CTL_VGA8 |
+ MGA1064_MISC_CTL_DAC_RAM_CS;
+
+ if (pMga->HasSDRAM)
+ state->Option = 0x40049120;
+
+ state->Option2 = 0x00008000;
+ break;
+
+ case PCI_CHIP_MGAG200_WINBOND_PCI:
+ state->DacRegs[MGA1064_VREF_CTL] = 0x07;
+ state->Option = 0x41049120;
+ state->Option2 = 0x0000b000;
+ break;
+
+ case PCI_CHIP_MGAG200_EV_PCI:
+ state->DacRegs[MGA1064_PIX_CLK_CTL] =
+ MGA1064_PIX_CLK_CTL_SEL_PLL;
+
+ state->DacRegs[MGA1064_MISC_CTL] =
+ MGA1064_MISC_CTL_VGA8 |
+ MGA1064_MISC_CTL_DAC_RAM_CS;
+
+ state->Option = 0x00000120;
+ state->Option2 = 0x0000b000;
+ break;
+
+ case PCI_CHIP_MGAG200_ER_PCI:
+ state->Dac_Index90 = 0;
+ break;
+
+ case PCI_CHIP_MGAG200_EH_PCI:
+ state->DacRegs[MGA1064_MISC_CTL] =
+ MGA1064_MISC_CTL_VGA8 |
+ MGA1064_MISC_CTL_DAC_RAM_CS;
+
+ state->Option = 0x00000120;
+ state->Option2 = 0x0000b000;
+ break;
+
+ default:
+ xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "Oh dear\n");
+ break;
+ }
+
+ /* must always have the pci retries on but rely on
+ polling to keep them from occuring */
+ state->Option &= ~0x20000000;
+
+ switch (crtc->scrn->bitsPerPixel) {
+ case 8:
+ state->DacRegs[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits;
+ startadd /= 8;
+ break;
+ case 16:
+ state->DacRegs[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits;
+
+ if ((crtc->scrn->weight.red == 5) && (crtc->scrn->weight.green == 5)
+ && (crtc->scrn->weight.blue == 5)) {
+ state->DacRegs[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits;
+ }
+
+ startadd /= 4;
+ break;
+ case 24:
+ state->DacRegs[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_24bits;
+ startadd /= 8;
+ break;
+ case 32:
+ state->DacRegs[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_32_24bits;
+
+ startadd /= 2;
+ break;
+ default:
+ FatalError("MGA: unsupported depth\n");
+ }
+
+ /* we only have 20 bits to store the start address */
+ startadd &= 0xfffff;
+
+ /*
+ * This will initialize all of the generic VGA registers.
+ */
+ if (!vgaHWInit(crtc->scrn, mode)) {
+ ErrorF("oh noes, vgahwinit failed\n");
+ return;
+ }
+
+ /*
+ * Here all of the MGA registers get filled in.
+ */
+ hd = (mode->CrtcHDisplay >> 3) - 1;
+ hs = (mode->CrtcHSyncStart >> 3) - 1;
+ he = (mode->CrtcHSyncEnd >> 3) - 1;
+ ht = (mode->CrtcHTotal >> 3) - 1;
+ vd = mode->CrtcVDisplay - 1;
+ vs = mode->CrtcVSyncStart - 1;
+ ve = mode->CrtcVSyncEnd - 1;
+ vt = mode->CrtcVTotal - 2;
+
+ /* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange
+ * vertical stripes
+ */
+ if ((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04)
+ ht++;
+
+ if (crtc->scrn->bitsPerPixel == 24)
+ wd = (mode->CrtcHDisplay * 3) >> (4 - BppShift);
+ else
+ wd = mode->CrtcHDisplay >> (4 - BppShift);
+
+ state->ExtVga[0] = 0;
+ state->ExtVga[5] = 0;
+
+ if (mode->Flags & V_INTERLACE) {
+ state->ExtVga[0] = 0x80;
+ state->ExtVga[5] = (hs + he - ht) >> 1;
+ wd <<= 1;
+ vt &= 0xFFFE;
+ }
+
+ state->ExtVga[0] |= (wd & 0x300) >> 4;
+ state->ExtVga[0] |= (startadd >> 16) & 0x0f;
+
+ state->ExtVga[1] = (((ht - 4) & 0x100) >> 8) |
+ ((hd & 0x100) >> 7) |
+ ((hs & 0x100) >> 6) |
+ (ht & 0x40);
+ state->ExtVga[2] = ((vt & 0xc00) >> 10) |
+ ((vd & 0x400) >> 8) |
+ ((vd & 0xc00) >> 7) |
+ ((vs & 0xc00) >> 5) |
+ ((vd & 0x400) >> 3); /* linecomp */
+
+ if (crtc->scrn->bitsPerPixel == 24)
+ state->ExtVga[3] = (((1 << BppShift) * 3) - 1) | 0x80;
+ else
+ state->ExtVga[3] = ((1 << BppShift) - 1) | 0x80;
+
+ state->ExtVga[4] = 0;
+
+ vga->CRTC[0] = ht - 4;
+ vga->CRTC[1] = hd;
+ vga->CRTC[2] = hd;
+ vga->CRTC[3] = (ht & 0x1F) | 0x80;
+ vga->CRTC[4] = hs;
+ vga->CRTC[5] = ((ht & 0x20) << 2) | (he & 0x1F);
+ vga->CRTC[6] = vt & 0xFF;
+ vga->CRTC[7] = ((vt & 0x100) >> 8 ) |
+ ((vd & 0x100) >> 7 ) |
+ ((vs & 0x100) >> 6 ) |
+ ((vd & 0x100) >> 5 ) |
+ ((vd & 0x100) >> 4 ) | /* linecomp */
+ ((vt & 0x200) >> 4 ) |
+ ((vd & 0x200) >> 3 ) |
+ ((vs & 0x200) >> 2 );
+ vga->CRTC[9] = ((vd & 0x200) >> 4) |
+ ((vd & 0x200) >> 3); /* linecomp */
+
+ vga->CRTC[12] = (startadd & 0xff00) >> 8;
+ vga->CRTC[13] = startadd & 0xff;
+
+ vga->CRTC[16] = vs & 0xFF;
+ vga->CRTC[17] = (ve & 0x0F) | 0x20;
+ vga->CRTC[18] = vd & 0xFF;
+ vga->CRTC[19] = wd & 0xFF;
+ vga->CRTC[21] = vd & 0xFF;
+ vga->CRTC[22] = (vt + 1) & 0xFF;
+ vga->CRTC[24] = vd & 0xFF; /* linecomp */
+
+ state->DacRegs[MGA1064_CURSOR_BASE_ADR_LOW] = pMga->FbCursorOffset >> 10;
+ state->DacRegs[MGA1064_CURSOR_BASE_ADR_HI] = pMga->FbCursorOffset >> 18;
+
+ if (pMga->SyncOnGreen) {
+ state->DacRegs[MGA1064_GEN_CTL] &=
+ ~MGA1064_GEN_CTL_SYNC_ON_GREEN_DIS;
+
+ state->ExtVga[3] |= 0x40;
+ }
+
+ /* select external clock */
+ vga->MiscOutReg |= 0x0C;
+
+ if (mode->Flags & V_DBLSCAN)
+ vga->CRTC[9] |= 0x80;
+
+ if (MGAISGx50(pMga)) {
+ OUTREG(MGAREG_ZORG, 0);
+ }
+
+ MGAGSetPCLK(crtc, state, mode->Clock);
+
+ /* This disables the VGA memory aperture */
+ vga->MiscOutReg &= ~0x02;
+
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ /* Disable byte-swapping for big-endian architectures - the XFree
+ driver seems to like a little-endian framebuffer -ReneR */
+ /* state->Option |= 0x80000000; */
+ state->Option &= ~0x80000000;
+#endif
+}
+
+/*
+ * This function restores a video mode. It basically writes out all of
+ * the registers that have previously been saved in the MgaCrtcStateRec
+ * data structure.
+ */
+static void
+state_restore(xf86CrtcPtr crtc, MgaCrtcStatePtr state,
+ vgaRegPtr vga, int vga_flags)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ MGAPtr pMga = MGAPTR(scrn);
+ CARD32 optionMask;
+ int i;
+
+ if (pMga->is_G200WB)
+ MGAG200WBPrepareForModeSwitch(scrn);
+
+ /*
+ * Pixel Clock needs to be restored regardless if we use
+ * HALLib or not. HALlib doesn't do a good job restoring
+ * VESA modes. MATROX: hint, hint.
+ *
+ * FIXME: This seems weird. Verify.
+ */
+ if (MGAISGx50(pMga) && state->clock) {
+ MGAG450SetPLLFreq(scrn, state->clock);
+ state->PIXPLLCSaved = FALSE;
+ }
+
+ /* Do not set the memory config for primary cards as it
+ should be correct already. Only on little endian architectures
+ since we need to modify the byteswap bit. -ReneR */
+#if X_BYTE_ORDER == X_BIG_ENDIAN
+ optionMask = OPTION1_MASK;
+#else
+ optionMask = (pMga->Primary) ? OPTION1_MASK_PRIMARY : OPTION1_MASK;
+#endif
+
+ /*
+ * Code is needed to get things back to bank zero.
+ */
+
+ /* restore DAC registers
+ * according to the docs we shouldn't write to reserved regs
+ */
+ for (i = 0; i < sizeof(state->DacRegs); i++) {
+ if ((i <= 0x03) ||
+ (i == 0x07) ||
+ (i == 0x0b) ||
+ (i == 0x0f) ||
+ ((i >= 0x13) && (i <= 0x17)) ||
+ (i == 0x1b) ||
+ (i == 0x1c) ||
+ ((i >= 0x1f) && (i <= 0x29)) ||
+ ((i >= 0x30) && (i <= 0x37)) ||
+ (MGAISGx50(pMga) && !state->PIXPLLCSaved &&
+ ((i == 0x2c) || (i == 0x2d) || (i == 0x2e) ||
+ (i == 0x4c) || (i == 0x4d) || (i == 0x4e))))
+ continue;
+ if (pMga->is_G200SE
+ && ((i == 0x2C) || (i == 0x2D) || (i == 0x2E)))
+ continue;
+ if ((pMga->is_G200EV || pMga->is_G200WB || pMga->is_G200EH) &&
+ (i >= 0x44) && (i <= 0x4E))
+ continue;
+
+ outMGAdac(i, state->DacRegs[i]);
+ }
+
+ if (pMga->is_G200ER)
+ outMGAdac(0x90, state->Dac_Index90);
+
+ if (!MGAISGx50(pMga)) {
+ /* restore pci_option register */
+#ifdef XSERVER_LIBPCIACCESS
+ pci_device_cfg_write_bits(pMga->PciInfo, optionMask,
+ state->Option, PCI_OPTION_REG);
+
+ if (pMga->Chipset != PCI_CHIP_MGA1064)
+ pci_device_cfg_write_bits(pMga->PciInfo, OPTION2_MASK,
+ state->Option2, PCI_MGA_OPTION2);
+
+ if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)
+ pci_device_cfg_write_bits(pMga->PciInfo, OPTION3_MASK,
+ state->Option3, PCI_MGA_OPTION3);
+#else
+ pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask,
+ state->Option);
+
+ if (pMga->Chipset != PCI_CHIP_MGA1064)
+ pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION2, OPTION2_MASK,
+ state->Option2);
+
+ if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)
+ pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION3, OPTION3_MASK,
+ state->Option3);
+#endif
+ }
+
+ if (pMga->is_G200ER) {
+ MGAG200ERPIXPLLSET(scrn, state);
+ } else if (pMga->is_G200EV) {
+ MGAG200EVPIXPLLSET(scrn, state);
+ } else if (pMga->is_G200WB) {
+ MGAG200WBPIXPLLSET(scrn, state);
+ } else if (pMga->is_G200EH) {
+ MGAG200EHPIXPLLSET(scrn, state);
+ }
+
+ /* restore CRTCEXT regs */
+ for (i = 0; i < 6; i++)
+ OUTREG16(MGAREG_CRTCEXT_INDEX, (state->ExtVga[i] << 8) | i);
+
+ if (pMga->is_G200ER) {
+ OUTREG8(MGAREG_CRTCEXT_INDEX, 0x24);
+ OUTREG8(MGAREG_CRTCEXT_DATA, state->ExtVga_Index24);
+ }
+
+ /* This handles restoring the generic VGA registers. */
+ if (pMga->is_G200SE) {
+ MGAG200SERestoreMode(scrn, vga);
+
+ if (vga_flags & VGA_SR_FONTS)
+ MGAG200SERestoreFonts(scrn, vga);
+ } else
+ vgaHWRestore(scrn, vga, vga_flags & ~VGA_SR_CMAP);
+
+ if (vga_flags & VGA_SR_CMAP)
+ MGAGRestorePalette(scrn, vga->DAC);
+
+ if (pMga->is_G200EV) {
+ OUTREG16(MGAREG_CRTCEXT_INDEX, 6);
+ OUTREG16(MGAREG_CRTCEXT_DATA, 0);
+ }
+
+ /*
+ * this is needed to properly restore start address
+ */
+ OUTREG16(MGAREG_CRTCEXT_INDEX, (state->ExtVga[0] << 8) | 0);
+
+ if (pMga->is_G200WB)
+ MGAG200WBRestoreFromModeSwitch(scrn);
+
+#if 1
+ ErrorF("Setting DAC:");
+ for (i = 0; i < sizeof(state->DacRegs); i++) {
+#if 1
+ if(!(i%16)) ErrorF("\n%02X: ",i);
+ ErrorF("%02X ", state->DacRegs[i]);
+#else
+ if(!(i%8)) ErrorF("\n%02X: ",i);
+ ErrorF("0x%02X, ", state->DacRegs[i]);
+#endif
+ }
+ ErrorF("\nOPTION = %08lX\n", state->Option);
+ ErrorF("OPTION2 = %08lX\n", state->Option2);
+ ErrorF("CRTCEXT:");
+ for (i=0; i<6; i++) ErrorF(" %02X", state->ExtVga[i]);
+ ErrorF("\n");
+#endif
+}
+
+static void
+state_save(xf86CrtcPtr crtc, MgaCrtcStatePtr state, int vga_flags)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ MGAPtr pMga = MGAPTR(scrn);
+ vgaRegPtr vga = &VGAHWPTR(scrn)->SavedReg;
+ int i;
+
+ if (MGAISGx50(pMga))
+ state->clock = MGAG450SavePLLFreq(scrn);
+
+ /*
+ * Code is needed to get back to bank zero.
+ */
+ OUTREG16(MGAREG_CRTCEXT_INDEX, 0x0004);
+
+ /*
+ * This function will handle creating the data structure and filling
+ * in the generic VGA portion.
+ */
+ if (pMga->is_G200SE) {
+ MGAG200SESaveMode(scrn, vga);
+
+ if (vga_flags & VGA_SR_FONTS)
+ MGAG200SESaveFonts(scrn, vga);
+ } else
+ vgaHWSave(scrn, vga, vga_flags);
+
+ MGAGSavePalette(scrn, vga->DAC);
+
+ /*
+ * The port I/O code necessary to read in the extended registers.
+ */
+ for (i = 0; i < sizeof(state->DacRegs); i++)
+ state->DacRegs[i] = inMGAdac(i);
+
+ if (pMga->is_G200WB) {
+ state->PllM = inMGAdac(MGA1064_WB_PIX_PLLC_M);
+ state->PllN = inMGAdac(MGA1064_WB_PIX_PLLC_N);
+ state->PllP = inMGAdac(MGA1064_WB_PIX_PLLC_P);
+ } else if (pMga->is_G200EV) {
+ state->PllM = inMGAdac(MGA1064_EV_PIX_PLLC_M);
+ state->PllN = inMGAdac(MGA1064_EV_PIX_PLLC_N);
+ state->PllP = inMGAdac(MGA1064_EV_PIX_PLLC_P);
+ } else if (pMga->is_G200EH) {
+ state->PllM = inMGAdac(MGA1064_EH_PIX_PLLC_M);
+ state->PllN = inMGAdac(MGA1064_EH_PIX_PLLC_N);
+ state->PllP = inMGAdac(MGA1064_EH_PIX_PLLC_P);
+ } else if (pMga->is_G200ER) {
+ state->PllM = inMGAdac(MGA1064_ER_PIX_PLLC_M);
+ state->PllN = inMGAdac(MGA1064_ER_PIX_PLLC_N);
+ state->PllP = inMGAdac(MGA1064_ER_PIX_PLLC_P);
+ state->Dac_Index90 = inMGAdac(0x90);
+ }
+
+ state->PIXPLLCSaved = TRUE;
+
+#ifdef XSERVER_LIBPCIACCESS
+ pci_device_cfg_read_u32(pMga->PciInfo, &state->Option,
+ PCI_OPTION_REG);
+ pci_device_cfg_read_u32(pMga->PciInfo, &state->Option2,
+ PCI_MGA_OPTION2);
+
+ if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)
+ pci_device_cfg_read_u32(pMga->PciInfo, &state->Option3,
+ PCI_MGA_OPTION3);
+#else
+ state->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
+ state->Option2 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION2);
+
+ if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)
+ state->Option3 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION3);
+#endif
+
+ for (i = 0; i < 6; i++) {
+ OUTREG8(MGAREG_CRTCEXT_INDEX, i);
+ state->ExtVga[i] = INREG8(MGAREG_CRTCEXT_DATA);
+ }
+ if (pMga->is_G200ER)
+ {
+ OUTREG8(MGAREG_CRTCEXT_INDEX, 0x24);
+ state->ExtVga_Index24 = INREG8(MGAREG_CRTCEXT_DATA);
+ }
+
+#ifdef DEBUG
+ ErrorF("Saved values:\nDAC:");
+ for (i = 0; i < sizeof(state->DacRegs); i++) {
+#if 1
+ if(!(i%16)) ErrorF("\n%02X: ",i);
+ ErrorF("%02X ", state->DacRegs[i]);
+#else
+ if(!(i%8)) ErrorF("\n%02X: ",i);
+ ErrorF("0x%02X, ", state->DacRegs[i]);
+#endif
+ }
+
+ ErrorF("\nOPTION = %08lX\n:", state->Option);
+ ErrorF("OPTION2 = %08lX\nCRTCEXT:", state->Option2);
+
+ for (i=0; i<6; i++) ErrorF(" %02X", state->ExtVga[i]);
+ ErrorF("\n");
+#endif
+}
+
+static void
+crtc_save(xf86CrtcPtr crtc)
+{
+ MgaCrtcDataPtr data = MGACRTCDATAPTR(crtc);
+ MGAPtr pMga = MGAPTR(crtc->scrn);
+ int vga_flags = VGA_SR_MODE;
+
+ if (pMga->Primary)
+ vga_flags |= VGA_SR_FONTS;
+
+ state_save(crtc, &data->saved_state, vga_flags);
+}
+
+static void
+crtc_restore(xf86CrtcPtr crtc)
+{
+ MgaCrtcDataPtr data = MGACRTCDATAPTR(crtc);
+ MGAPtr pMga = MGAPTR(crtc->scrn);
+ vgaHWPtr vga = VGAHWPTR(crtc->scrn);
+ int vga_flags = VGA_SR_MODE | VGA_SR_CMAP;
+
+ if (pMga->Primary)
+ vga_flags |= VGA_SR_FONTS;
+
+ state_restore(crtc, &data->saved_state, &vga->SavedReg, vga_flags);
+}
+
+static Bool
+crtc_lock(xf86CrtcPtr crtc)
+{
+ /* XXX this would need DRI support */
+ return FALSE;
+}
+
+static void
+crtc_unlock(xf86CrtcPtr crtc)
+{
+ /* XXX this would need DRI support */
+}
+
+static Bool
+crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ return TRUE;
+}
+
+static void
+crtc_prepare(xf86CrtcPtr crtc)
+{
+ crtc->funcs->dpms(crtc, DPMSModeOff);
+}
+
+static void
+crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
+ DisplayModePtr adjust_mode, int x, int y)
+{
+ MgaCrtcStateRec state;
+ vgaHWPtr vga = VGAHWPTR(crtc->scrn);
+
+ memset(&state, 0, sizeof (state));
+
+ state_set(crtc, &state, mode, x, y);
+ state_restore(crtc, &state, &vga->ModeReg, VGA_SR_MODE);
+}
+
+static void
+crtc_commit(xf86CrtcPtr crtc)
+{
+ crtc->funcs->dpms(crtc, DPMSModeOn);
+}
+
+static void
+crtc_destroy(xf86CrtcPtr crtc)
+{
+ free(crtc->driver_private);
+}
+
+Bool
+MGAGCrtc1Init(ScrnInfoPtr scrn)
+{
+ xf86CrtcPtr crtc;
+ MgaCrtcDataPtr data;
+
+ data = xnfcalloc (sizeof (MgaCrtcDataRec), 1);
+ if (!data)
+ return FALSE;
+
+ crtc = xf86CrtcCreate (scrn, &crtc_funcs);
+ if (!crtc) {
+ free(data);
+ return FALSE;
+ }
+
+ crtc->driver_private = data;
+
+ return TRUE;
+}
diff --git a/src/mga_g_output.c b/src/mga_g_output.c
new file mode 100644
index 0000000..147bac6
--- /dev/null
+++ b/src/mga_g_output.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2007 Tilman Sauerbeck
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software")
+ * to deal in the software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * them Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Tilman Sauerbeck <tilman@code-monkey.de>
+ *
+ * Sources:
+ * xf86-video-intel
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86PciInfo.h"
+
+#include "mga_reg.h"
+#include "mga.h"
+#include "mga_randr.h"
+#include "vbe.h"
+
+#define MGAOUTPUTDATAPTR(p) ((MgaOutputDataPtr) ((p)->driver_private))
+
+typedef struct {
+ I2CBusPtr ddc_bus;
+} MgaOutputDataRec, *MgaOutputDataPtr;
+
+static void output_dac1_dpms(xf86OutputPtr output, int mode);
+static void output_save(xf86OutputPtr output);
+static void output_restore(xf86OutputPtr output);
+static int output_mode_valid(xf86OutputPtr output, DisplayModePtr mode);
+static Bool output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode);
+static void output_prepare(xf86OutputPtr output);
+static void output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode);
+static void output_commit(xf86OutputPtr output);
+static xf86OutputStatus output_detect(xf86OutputPtr output);
+static DisplayModePtr output_get_modes(xf86OutputPtr output);
+static void output_destroy(xf86OutputPtr output);
+
+static const xf86OutputFuncsRec output_dac1_funcs = {
+ .dpms = output_dac1_dpms,
+ .save = output_save,
+ .restore = output_restore,
+ .mode_valid = output_mode_valid,
+ .mode_fixup = output_mode_fixup,
+ .prepare = output_prepare,
+ .mode_set = output_mode_set,
+ .commit = output_commit,
+ .detect = output_detect,
+ .get_modes = output_get_modes,
+ .destroy = output_destroy
+};
+
+/* enable/disable primary output. */
+static void
+output1_dpms(xf86OutputPtr output, int mode)
+{
+ MGAPtr pMga = MGAPTR(output->scrn);
+ CARD8 misc_ctl, disp_ctl, mask;
+
+ misc_ctl = inMGAdac(MGA1064_MISC_CTL);
+ mask = MGA1064_MISC_CTL_DAC_EN;
+
+ if (mode == DPMSModeOn)
+ outMGAdac(MGA1064_MISC_CTL, misc_ctl | mask);
+ else
+ outMGAdac(MGA1064_MISC_CTL, misc_ctl & ~mask);
+
+ disp_ctl = inMGAdac(MGA1064_DISP_CTL);
+ mask = MGA1064_DISP_CTL_DAC1OUTSEL_EN;
+
+ if (mode == DPMSModeOn)
+ outMGAdac(MGA1064_DISP_CTL, disp_ctl | mask);
+ else
+ outMGAdac(MGA1064_DISP_CTL, disp_ctl & ~mask);
+}
+
+static void
+output_dac1_dpms(xf86OutputPtr output, int mode)
+{
+ /* XXX
+ * . Prefer an implementation that doesn't depend on VGA specifics.
+ *
+ * . This will only work for the primary output or maybe only for
+ * CRTC1?
+ */
+
+ MGAPtr pMga = MGAPTR(output->scrn);
+
+#if 0
+ CARD8 val, seq1, crtcext1;
+
+ OUTREG8(MGAREG_SEQ_INDEX, 0x01); /* Select SEQ1 */
+ OUTREG8(MGAREG_CRTCEXT_INDEX, 0x01); /* Select CRTCEXT1 */
+
+ seq1 = INREG8(MGAREG_SEQ_DATA);
+ seq1 &= ~MGAREG_SEQ1_SCREEN_OFF;
+
+ crtcext1 = INREG8(MGAREG_CRTCEXT_DATA);
+ crtcext1 &= ~MGAREG_CRTCEXT1_HSYNC_OFF;
+ crtcext1 &= ~MGAREG_CRTCEXT1_VSYNC_OFF;
+
+ switch (mode) {
+ case DPMSModeOn:
+ /* nothing to do */
+ break;
+ case DPMSModeStandby:
+ seq1 |= MGAREG_SEQ1_SCREEN_OFF;
+ crtcext1 = MGAREG_CRTCEXT1_HSYNC_OFF;
+ break;
+ case DPMSModeSuspend:
+ seq1 |= MGAREG_SEQ1_SCREEN_OFF;
+ crtcext1 |= MGAREG_CRTCEXT1_VSYNC_OFF;
+ break;
+ case DPMSModeOff:
+ seq1 |= MGAREG_SEQ1_SCREEN_OFF;
+ crtcext1 |= MGAREG_CRTCEXT1_HSYNC_OFF;
+ crtcext1 |= MGAREG_CRTCEXT1_VSYNC_OFF;
+ break;
+ }
+
+ MGAWAITVSYNC();
+ MGAWAITBUSY();
+
+ OUTREG8(MGAREG_SEQ_DATA, seq1);
+
+ usleep(20000);
+
+ OUTREG8(MGAREG_CRTCEXT_DATA, crtcext1);
+#endif
+
+ output1_dpms(output, mode);
+}
+
+static void
+output_save(xf86OutputPtr output)
+{
+}
+
+static void
+output_restore(xf86OutputPtr output)
+{
+}
+
+static int
+output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
+{
+ return MODE_OK;
+}
+
+static Bool
+output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+ return TRUE;
+}
+
+static void
+output_prepare(xf86OutputPtr output)
+{
+ output->funcs->dpms(output, DPMSModeOff);
+}
+
+static void
+output_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+ DisplayModePtr adjusted_mode)
+{
+}
+
+static void
+output_commit(xf86OutputPtr output)
+{
+ output->funcs->dpms(output, DPMSModeOn);
+}
+
+static xf86OutputStatus
+output_detect(xf86OutputPtr output)
+{
+ MgaOutputDataPtr data = MGAOUTPUTDATAPTR(output);
+
+ /* lie lie lie */
+ return XF86OutputStatusConnected;
+
+ /* 0xa0 is DDC EEPROM address */
+ if (xf86I2CProbeAddress(data->ddc_bus, 0xa0))
+ return XF86OutputStatusConnected;
+ else
+ return XF86OutputStatusUnknown;
+}
+
+/* jesus christ i hate everything */
+static vbeInfoPtr vbe;
+
+static DisplayModePtr
+output_get_modes(xf86OutputPtr output)
+{
+ MgaOutputDataPtr data = MGAOUTPUTDATAPTR(output);
+ xf86MonPtr mon;
+
+#if 1
+ if (!vbe) {
+ xf86LoadSubModule(output->scrn, "vbe");
+ vbe = VBEInit(NULL, MGAPTR(output->scrn)->pEnt->index);
+ }
+
+ /* mon = xf86OutputGetEDID(output, data->ddc_bus); */
+ mon = vbeDoEDID(vbe, NULL);
+#else
+
+ extern xf86MonPtr MGAdoDDC(ScrnInfoPtr pScrn);
+ mon = MGAdoDDC(output->scrn);
+#endif
+
+ xf86OutputSetEDID(output, mon);
+
+ return xf86OutputGetEDIDModes(output);
+}
+
+static void
+output_destroy(xf86OutputPtr output)
+{
+ free(output->driver_private);
+}
+
+xf86OutputPtr
+MGAG200EOutputInit(ScrnInfoPtr scrn)
+{
+ MGAPtr pMga = MGAPTR(scrn);
+ xf86OutputPtr output;
+ MgaOutputDataPtr data;
+
+ data = xnfcalloc(sizeof(MgaOutputDataRec), 1);
+ if (!data)
+ return NULL;
+
+ output = xf86OutputCreate(scrn, &output_dac1_funcs, "VGA1");
+ if (!output) {
+ free(data);
+ return NULL;
+ }
+
+ output->driver_private = data;
+
+ data->ddc_bus = pMga->DDC_Bus1;
+
+ return output;
+}
diff --git a/src/mga_randr.h b/src/mga_randr.h
new file mode 100644
index 0000000..c3662c6
--- /dev/null
+++ b/src/mga_randr.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software")
+ * to deal in the software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * them Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef MGA_RANDR_H
+#define MGA_RANDR_H
+
+#include "config.h"
+#include "xf86.h"
+#include "xf86Crtc.h"
+#include "xf86RandR12.h"
+
+#define MGACRTCDATAPTR(p) ((MgaCrtcDataPtr) ((p)->driver_private))
+
+extern void MGAGRestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr);
+extern void MGAGLoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr);
+extern void MGAGSavePalette(ScrnInfoPtr pScrn, unsigned char* pntr);
+
+extern Bool MGAGCrtc1Init(ScrnInfoPtr scrn);
+extern xf86OutputPtr MGAG200EOutputInit(ScrnInfoPtr scrn);
+
+extern void MGAG200SEComputePLLParam(long lFo, int *M, int *N, int *P);
+extern void MGAG200EVComputePLLParam(long lFo, int *M, int *N, int *P);
+extern void MGAG200WBComputePLLParam(long lFo, int *M, int *N, int *P);
+extern void MGAG200EHComputePLLParam(long lFo, int *M, int *N, int *P);
+extern void MGAG200ERComputePLLParam(long lFo, int *M, int *N, int *P);
+#endif
diff --git a/src/mga_shadow.c b/src/mga_shadow.c
index d059852..18c7606 100644
--- a/src/mga_shadow.c
+++ b/src/mga_shadow.c
@@ -23,7 +23,10 @@ MGARefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
unsigned char *src, *dst;
Bpp = pScrn->bitsPerPixel >> 3;
- FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
+ if (pMga->randr12)
+ FBPitch = BitmapBytePad(pScrn->virtualX * pScrn->bitsPerPixel);
+ else
+ FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel);
while(num--) {
width = (pbox->x2 - pbox->x1) * Bpp;
@@ -32,7 +35,8 @@ MGARefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
(pbox->x1 * Bpp);
dst = pMga->FbStart + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
- while(height--) {
+ /* the && here is just fucking revolting */
+ while(height-- && (dst >= pMga->FbStart)) {
memcpy(dst, src, width);
dst += FBPitch;
src += pMga->ShadowPitch;