diff options
author | Adam Jackson <ajax@redhat.com> | 2012-02-16 17:19:57 -0500 |
---|---|---|
committer | Dave Airlie <airlied@gmail.com> | 2012-08-08 08:58:03 +1000 |
commit | 66dc826d24e50e31047ae1772f2a8e94ed3e1f56 (patch) | |
tree | c2dff2a10f458d15cd31e7d802239d8e736d0458 | |
parent | 94b009ede2375a3c25ce20d9528f9d0ed13e2d11 (diff) |
WIP: RANDR 1.2 skeleton
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/mga.h | 4 | ||||
-rw-r--r-- | src/mga_dacG.c | 51 | ||||
-rw-r--r-- | src/mga_driver.c | 291 | ||||
-rw-r--r-- | src/mga_g_crtc.c | 1157 | ||||
-rw-r--r-- | src/mga_g_output.c | 268 | ||||
-rw-r--r-- | src/mga_randr.h | 45 | ||||
-rw-r--r-- | src/mga_shadow.c | 8 |
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 \ @@ -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; |