#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "xf86_ansic.h"
#include "compiler.h"
#include "xf86PciInfo.h"
#include "mga.h"
#include "mga_macros.h"
#include "mga_reg.h"
#include "mga_merge.h"
#include "fbdevhw.h"
static int
StrToRanges(range* r, char* s) {
float num=0.0;
int rangenum=0;
Bool gotdash = FALSE;
Bool nextdash = FALSE;
char* strnum=NULL;
do {
switch(*s) {
case '0': case '1': case '2': case '3': case '4': case '5':
case '6': case '7': case '8': case '9': case '.':
if(strnum == NULL) {
strnum = s;
gotdash = nextdash;
nextdash = FALSE;
}
break;
case '-':
case ' ': case 0:
if(strnum == NULL) break;
if(strnum != NULL) sscanf(strnum,"%f",&num);
if(gotdash)
r[rangenum-1].hi = num;
else {
r[rangenum].lo = num;
r[rangenum].hi = num;
rangenum++;
}
strnum = NULL;
if(*s == '-')
nextdash = (rangenum != 0);
break;
default :
return 0;
}
} while(*(s++) != 0);
return rangenum;
}
static DisplayModePtr
CopyModeNLink(ScrnInfoPtr pScrn, DisplayModePtr dest, DisplayModePtr i, DisplayModePtr j, MgaScrn2Rel srel) {
DisplayModePtr mode;
int dx = 0,dy = 0;
mode = xalloc(sizeof(DisplayModeRec));
memcpy(mode,i, sizeof(DisplayModeRec));
mode->Private = xalloc(sizeof(MergedDisplayModeRec));
((MergedDisplayModePtr)mode->Private)->Monitor1 = i;
((MergedDisplayModePtr)mode->Private)->Monitor2 = j;
((MergedDisplayModePtr)mode->Private)->Monitor2Pos = srel;
mode->PrivSize = 0;
switch(srel) {
case mgaLeftOf:
case mgaRightOf:
dx = min(pScrn->virtualX,i->HDisplay + j->HDisplay) - mode->HDisplay;
dy = min(pScrn->virtualY, max(i->VDisplay,j->VDisplay)) - mode->VDisplay;
break;
case mgaAbove:
case mgaBelow:
dy = min(pScrn->virtualY,i->VDisplay + j->VDisplay) - mode->VDisplay;
dx = min(pScrn->virtualX, max(i->HDisplay,j->HDisplay)) - mode->HDisplay;
break;
case mgaClone:
dx = min(pScrn->virtualX, max(i->HDisplay,j->HDisplay)) - mode->HDisplay;
dy = min(pScrn->virtualY, max(i->VDisplay,j->VDisplay)) - mode->VDisplay;
break;
}
mode->HDisplay += dx;
mode->HSyncStart += dx;
mode->HSyncEnd += dx;
mode->HTotal += dx;
mode->VDisplay += dy;
mode->VSyncStart += dy;
mode->VSyncEnd += dy;
mode->VTotal += dy;
mode->Clock = 0;
mode->next = mode;
mode->prev = mode;
if(dest) {
mode->next = dest->next;
dest->next->prev = mode;
mode->prev = dest;
dest->next = mode;
}
return mode;
}
static DisplayModePtr
GetModeFromName(char* str, DisplayModePtr i)
{
DisplayModePtr c = i;
if(!i) return NULL;
do {
if(strcmp(str,c->name) == 0) return c;
c = c->next;
} while(c != i);
return NULL;
}
static DisplayModePtr
GenerateModeList(ScrnInfoPtr pScrn, char* str,
DisplayModePtr i, DisplayModePtr j, MgaScrn2Rel srel) {
char* strmode = str;
char modename[256];
Bool gotdash = FALSE;
MgaScrn2Rel sr;
DisplayModePtr mode1 = NULL;
DisplayModePtr mode2 = NULL;
DisplayModePtr result = NULL;
do {
switch(*str) {
case 0:
case '-':
case ' ':
if((strmode != str)) {
strncpy(modename,strmode,str - strmode);
modename[str - strmode] = 0;
if(gotdash) {
if(mode1 == NULL) return NULL;
mode2 = GetModeFromName(modename,j);
if(!mode2) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Mode: \"%s\" is not a supported mode for monitor 2\n",modename);
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Skipping metamode \"%s-%s\".\n",mode1->name,modename);
mode1 = NULL;
}
} else {
mode1 = GetModeFromName(modename,i);
if(!mode1) {
char* tmps = str;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Mode: \"%s\" is not a supported mode for monitor 1\n",modename);
gotdash = FALSE;
while(*tmps == ' ') tmps++;
if(*tmps == '-') {
tmps++;
while((*tmps == ' ') && (*tmps != 0)) tmps++;
while((*tmps != ' ') && (*tmps != '-') && (*tmps != 0)) tmps++;
strncpy(modename,strmode,tmps - strmode);
modename[tmps - strmode] = 0;
str = tmps-1;
}
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Skipping metamode \"%s\".\n",modename);
mode1 = NULL;
}
}
gotdash = FALSE;
}
strmode = str+1;
gotdash |= (*str == '-');
if(*str != 0) break;
default:
if(!gotdash && mode1) {
sr = srel;
if(!mode2) {
mode2 = GetModeFromName(mode1->name,j);
sr = mgaClone;
}
if(!mode2) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Mode: \"%s\" is not a supported mode for monitor 2\n",mode1->name);
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
"Skipping clone mode \"%s\".\n", mode1->name);
mode1 = NULL;
} else {
result = CopyModeNLink(pScrn,result,mode1,mode2,sr);
mode1 = NULL;
mode2 = NULL;
}
}
break;
}
} while(*(str++) != 0);
return result;
}
Bool
MGAPreInitMergedFB(ScrnInfoPtr pScrn1, int flags)
{
ScrnInfoPtr pScrn;
MGAPtr pMga;
MGAPtr pMga1;
MessageType from;
int i;
char* s;
ClockRangePtr clockRanges;
#ifdef USEMGAHAL
ULONG status;
#endif
MgaScrn2Rel Monitor2Pos;
xf86DrvMsg(pScrn1->scrnIndex, X_INFO, "==== Start of second screen initialization ====\n");
pScrn = xalloc(sizeof(ScrnInfoRec));
memcpy(pScrn,pScrn1,sizeof(ScrnInfoRec));
pScrn->driverPrivate = NULL;
if (!MGAGetRec(pScrn)) {
return FALSE;
}
pMga = MGAPTR(pScrn);
#ifdef USEMGAHAL
pMga->pMgaModeInfo = NULL;
#endif
pMga1 = MGAPTR(pScrn1);
pMga1->pScrn2 = pScrn;
pMga->pEnt = pMga1->pEnt;
pMga->device = pMga1->device;
if (flags & PROBE_DETECT) {
MGAProbeDDC(pScrn, pMga->pEnt->index);
return TRUE;
}
pMga->PciTag = pMga1->PciTag;
pMga->Primary = pMga1->Primary;
{
pScrn->monitor = xalloc(sizeof(MonRec));
memcpy(pScrn->monitor,pScrn1->monitor,sizeof(MonRec));
pScrn->monitor->DDC = NULL;
if ((s = xf86GetOptValString(pMga1->Options, OPTION_HSYNC2))) {
pScrn->monitor->nHsync = StrToRanges(pScrn->monitor->hsync,s);
}
if ((s = xf86GetOptValString(pMga1->Options, OPTION_VREFRESH2))) {
pScrn->monitor->nVrefresh = StrToRanges(pScrn->monitor->vrefresh,s);
}
}
pMga->SecondCrtc = TRUE;
pMga->HWCursor = FALSE;
pScrn->AdjustFrame = MGAAdjustMergeFrames;
pScrn1->AdjustFrame = MGAAdjustMergeFrames;
pScrn->progClock = TRUE;
pScrn->options = pScrn1->options;
pMga->Options = pMga1->Options;
if (pScrn->depth == 8)
pScrn->rgbBits = 8;
pScrn->chipset = pScrn1->chipset;
pMga->Chipset = pMga1->Chipset;
pMga->ChipRev = pMga1->ChipRev;
#ifdef XF86DRI
pMga->agpMode = pMga1->agpMode;
#endif
pMga->NoAccel = pMga1->NoAccel;
pMga->UsePCIRetry = pMga1->UsePCIRetry;
pMga->SyncOnGreen = pMga1->SyncOnGreen;
pMga->ShowCache = pMga1->ShowCache;
pMga->HasSDRAM = pMga1->HasSDRAM;
pMga->MemClk = pMga1->MemClk;
pMga->Overlay8Plus24 = pMga1->Overlay8Plus24;
pMga->colorKey = pMga1->colorKey;
pScrn->colorKey = pScrn1->colorKey;
pScrn->overlayFlags = pScrn1->overlayFlags;
pMga->videoKey = pMga1->videoKey;
pMga->HWCursor = FALSE;
pMga->ShadowFB = FALSE;
pMga->FBDev = FALSE;
pMga->OverclockMem = pMga1->OverclockMem;
pMga->TexturedVideo = pMga1->TexturedVideo;
pMga->MergedFB = TRUE;
pMga->Rotate = 0;
switch (pMga->Chipset) {
case PCI_CHIP_MGA2064:
case PCI_CHIP_MGA2164:
case PCI_CHIP_MGA2164_AGP:
MGA2064SetupFuncs(pScrn);
break;
case PCI_CHIP_MGA1064:
case PCI_CHIP_MGAG100:
case PCI_CHIP_MGAG100_PCI:
case PCI_CHIP_MGAG200:
case PCI_CHIP_MGAG200_PCI:
case PCI_CHIP_MGAG400:
case PCI_CHIP_MGAG550:
MGAGSetupFuncs(pScrn);
break;
}
pMga->FbAddress = pMga1->FbAddress;
pMga->FbBaseReg = pMga1->FbBaseReg;
pMga->PciInfo = pMga1->PciInfo;
pMga->IOAddress = pMga1->IOAddress;
pMga->ILOADAddress = pMga1->ILOADAddress;
pMga->BiosFrom = pMga1->BiosFrom;
pMga->BiosAddress = pMga1->BiosAddress;
MGAReadBios(pScrn);
pMga->HwBpp = pMga1->HwBpp;
if ( (!pMga->Primary && !pMga->FBDev) || xf86IsPc98() )
MGASoftReset(pScrn);
pScrn->videoRam = pScrn1->videoRam;
pMga->FbMapSize = pMga1->FbMapSize;
pMga->SrcOrg = pMga1->SrcOrg;
pMga->DstOrg = pMga1->DstOrg;
pMga->BppShifts[0] = 0;
pMga->BppShifts[1] = 1;
pMga->BppShifts[2] = 0;
pMga->BppShifts[3] = 2;
(*pMga->PreInit)(pScrn);
#if !defined(__powerpc__)
#endif
{
Gamma zeros = {0.0, 0.0, 0.0};
if (!xf86SetGamma(pScrn, zeros)) {
return FALSE;
}
}
pMga->MinClock = pMga1->MinClock;
xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "CRTC2: Min pixel clock is %d MHz\n",
pMga->MinClock / 1000);
if (pMga->ChipRev >= 0x80 || (pMga->Chipset == PCI_CHIP_MGAG550)) {
pMga->MaxClock = 234000;
} else {
pMga->MaxClock = 135000;
}
xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "CRTC2: Max pixel clock is %d MHz\n",
pMga->MaxClock / 1000);
clockRanges = xnfcalloc(sizeof(ClockRange), 1);
clockRanges->next = NULL;
clockRanges->minClock = pMga->MinClock;
clockRanges->maxClock = pMga->MaxClock;
clockRanges->clockIndex = -1;
clockRanges->interlaceAllowed = TRUE;
clockRanges->doubleScanAllowed = TRUE;
#ifdef USEMGAHAL
MGA_HAL(clockRanges->interlaceAllowed = FALSE);
MGA_HAL(clockRanges->doubleScanAllowed = FALSE);
#endif
clockRanges->interlaceAllowed = FALSE;
clockRanges->ClockMulFactor = 1;
clockRanges->ClockDivFactor = 1;
if (pMga->Dac.SetMemClk) {
if (pMga->MemClk == 0) {
pMga->MemClk = pMga->Dac.MemoryClock;
from = pMga->Dac.MemClkFrom;
} else
from = X_CONFIG;
xf86DrvMsg(pScrn->scrnIndex, from, "CRTC2: MCLK used is %.1f MHz\n",
pMga->MemClk / 1000.0);
}
{
int Pitches1[] =
{640, 768, 800, 960, 1024, 1152, 1280, 1600, 1920, 2048, 0};
int Pitches2[] =
{512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664,
1920, 2048, 0};
int *linePitches = NULL;
int minPitch = 256;
int maxPitch = 2048;
switch(pMga->Chipset) {
case PCI_CHIP_MGA2064:
if (!pMga->NoAccel) {
linePitches = xalloc(sizeof(Pitches1));
memcpy(linePitches, Pitches1, sizeof(Pitches1));
minPitch = maxPitch = 0;
}
break;
case PCI_CHIP_MGA2164:
case PCI_CHIP_MGA2164_AGP:
case PCI_CHIP_MGA1064:
if (!pMga->NoAccel) {
linePitches = xalloc(sizeof(Pitches2));
memcpy(linePitches, Pitches2, sizeof(Pitches2));
minPitch = maxPitch = 0;
}
break;
case PCI_CHIP_MGAG100:
case PCI_CHIP_MGAG100_PCI:
maxPitch = 2048;
break;
case PCI_CHIP_MGAG200:
case PCI_CHIP_MGAG200_PCI:
case PCI_CHIP_MGAG400:
case PCI_CHIP_MGAG550:
maxPitch = 4096;
break;
}
pScrn->modePool=NULL;
pScrn->modes = NULL;
i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
pScrn->display->modes, clockRanges,
linePitches, minPitch, maxPitch,
pMga->Roundings[(pScrn->bitsPerPixel >> 3) - 1] *
pScrn->bitsPerPixel, 128, 2048,
pScrn->display->virtualX,
pScrn->display->virtualY,
pMga->FbMapSize,
LOOKUP_BEST_REFRESH);
if (linePitches)
xfree(linePitches);
}
if (i < 1 && pMga->FBDev) {
fbdevHWUseBuildinMode(pScrn);
pScrn->displayWidth = pScrn->virtualX;
i = 1;
}
if (i == -1) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "CRTC2: Validate Modes Failed\n");
MGAFreeRec(pScrn);
return FALSE;
}
xf86PruneDriverModes(pScrn);
if (i == 0 || pScrn->modes == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "CRTC2: No valid modes found\n");
MGAFreeRec(pScrn);
return FALSE;
}
#ifdef USEMGAHAL
MGA_HAL(
pMga->pBoard = pMga1->pBoard;
pMga->pClientStruct = pMga1->pClientStruct;
pMga->pMgaHwInfo = pMga1->pMgaHwInfo;
MGAFillModeInfoStruct(pScrn,NULL);
pMga->pMgaModeInfo->ulDispWidth = pScrn->virtualX;
pMga->pMgaModeInfo->ulDispHeight = pScrn->virtualY;
if((status = MGAValidateMode(pMga->pBoard,pMga->pMgaModeInfo)) != 0) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"MGAValidateMode from HALlib found the mode to be invalid.\n"
"\tError: 0x%lx\n", status);
return FALSE;
}
pScrn->displayWidth = pMga->pMgaModeInfo->ulFBPitch;
);
#endif
#ifdef USEMGAHAL
MGA_HAL(xf86SetCrtcForModes(pScrn, 0));
#endif
MGA_NOT_HAL(xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V));
pScrn->currentMode = pScrn->modes;
xf86PrintModes(pScrn);
xf86SetDpi(pScrn, 0, 0);
pMga->YDstOrg = pMga1->YDstOrg;
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "CRTC2: YDstOrg is set to %d\n",
pMga->YDstOrg);
pMga->FbUsableSize = pMga1->FbUsableSize;
pMga->FbCursorOffset = pMga1->FbCursorOffset;
pMga->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel;
pMga->CurrentLayout.depth = pScrn->depth;
pMga->CurrentLayout.displayWidth = pScrn->displayWidth;
pMga->CurrentLayout.weight.red = pScrn->weight.red;
pMga->CurrentLayout.weight.green = pScrn->weight.green;
pMga->CurrentLayout.weight.blue = pScrn->weight.blue;
pMga->CurrentLayout.Overlay8Plus24 = pMga->Overlay8Plus24;
pMga->CurrentLayout.mode = pScrn->currentMode;
Monitor2Pos = mgaRightOf;
if ((s = xf86GetOptValString(pMga1->Options, OPTION_MONITOR2POS))) {
switch(s[0]) {
case 'L': case 'l': case 'G': case 'g':
Monitor2Pos = mgaLeftOf;
break;
case 'R': case 'r': case 'D': case 'd':
Monitor2Pos = mgaRightOf;
break;
case 'A': case 'a': case 'H': case 'h':
Monitor2Pos = mgaAbove;
break;
case 'B': case 'b':
Monitor2Pos = mgaBelow;
break;
case 'C': case 'c':
Monitor2Pos = mgaClone;
break;
default:
Monitor2Pos = mgaRightOf;
break;
}
}
pMga1->M1modes = pScrn1->modes;
pMga1->M1currentMode = pScrn1->currentMode;
if ((s = xf86GetOptValString(pMga1->Options, OPTION_METAMODES))) {
pScrn1->modes = GenerateModeList(pScrn,s,pMga1->M1modes,pScrn->modes,Monitor2Pos);
if(!pScrn1->modes) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Parse Error reading MetaModes, or No modes left.\n");
return FALSE;
}
pScrn1->modes = pScrn1->modes->next;
pScrn1->currentMode = pScrn1->modes;
} else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "MetaModes option missing.\n");
return FALSE;
}
xf86DrvMsg(pScrn1->scrnIndex, X_INFO, "==== End of second screen initialization ====\n");
return TRUE;
}
void
MGADisplayPowerManagementSetMerged(ScrnInfoPtr pScrn, int PowerManagementMode,
int flags)
{
MGADisplayPowerManagementSet(pScrn,PowerManagementMode,flags);
MGADisplayPowerManagementSetCrtc2(pScrn,PowerManagementMode,flags);
}
typedef struct _region {
int x0,x1,y0,y1;
} region;
static Bool
InRegion(int x, int y, region r) {
return (r.x0 <= x) && (x < r.x1) && (r.y0 <= y) && (y < r.y1);
}
#define BOUND(test,low,hi) { \
if(test < low) test = low; \
if(test > hi) test = hi; }
#define REBOUND(low,hi,test) { \
if(test < low) { \
hi += test-low; \
low = test; } \
if(test > hi) { \
low += test-hi; \
hi = test; } }
void
MGAMergePointerMoved(int scrnIndex, int x, int y)
{
ScrnInfoPtr pScr = xf86Screens[scrnIndex];
MGAPtr pMga = MGAPTR(pScr);
ScrnInfoPtr pScr2 = pMga->pScrn2;
region out,in1,in2,f2,f1;
int deltax,deltay;
f1.x0 = pMga->M1frameX0;
f1.x1 = pMga->M1frameX1+1;
f1.y0 = pMga->M1frameY0;
f1.y1 = pMga->M1frameY1+1;
f2.x0 = pScr2->frameX0;
f2.x1 = pScr2->frameX1+1;
f2.y0 = pScr2->frameY0;
f2.y1 = pScr2->frameY1+1;
out.x0 = pScr->frameX0;
out.x1 = pScr->frameX1+1;
out.y0 = pScr->frameY0;
out.y1 = pScr->frameY1+1;
in1 = out;
in2 = out;
switch(((MergedDisplayModePtr)pScr->currentMode->Private)->Monitor2Pos) {
case mgaLeftOf :
in1.x0 = f1.x0;
in2.x1 = f2.x1;
break;
case mgaRightOf :
in1.x1 = f1.x1;
in2.x0 = f2.x0;
break;
case mgaBelow :
in1.y1 = f1.y1;
in2.y0 = f2.y0;
break;
case mgaAbove :
in1.y0 = f1.y0;
in2.y1 = f2.y1;
break;
case mgaClone :
break;
}
deltay = 0;
deltax = 0;
if(InRegion(x,y,out)) {
if( InRegion(x,y, in1) && !InRegion(x,y, f1) ) {
REBOUND(f1.x0,f1.x1,x);
REBOUND(f1.y0,f1.y1,y);
deltax = 1;
}
if( InRegion(x,y, in2) && !InRegion(x,y, f2) ) {
REBOUND(f2.x0,f2.x1,x);
REBOUND(f2.y0,f2.y1,y);
deltax = 1;
}
}
else {
if ( out.x0 > x) {
deltax = x - out.x0;
}
if ( out.x1 < x) {
deltax = x - out.x1;
}
f1.x0 += deltax;
f1.x1 += deltax;
f2.x0 += deltax;
f2.x1 += deltax;
pScr->frameX0 += deltax;
pScr->frameX1 += deltax;
if ( out.y0 > y) {
deltay = y - out.y0;
}
if ( out.y1 < y) {
deltay = y - out.y1;
}
f1.y0 += deltay;
f1.y1 += deltay;
f2.y0 += deltay;
f2.y1 += deltay;
pScr->frameY0 += deltay;
pScr->frameY1 += deltay;
}
if (deltax != 0 || deltay != 0) {
pMga->M1frameX0 = f1.x0;
pMga->M1frameY0 = f1.y0;
pScr2->frameX0 = f2.x0;
pScr2->frameY0 = f2.y0;
MGAAdjustGranularity(pScr,&pMga->M1frameX0,&pMga->M1frameY0);
MGAAdjustGranularity(pScr,&pScr2->frameX0,&pScr2->frameY0);
MGAAdjustGranularity(pScr,&pScr->frameX0,&pScr->frameY0);
pMga->M1frameX1 = pMga->M1frameX0 + MDMPTR(pScr)->Monitor1->HDisplay -1;
pMga->M1frameY1 = pMga->M1frameY0 + MDMPTR(pScr)->Monitor1->VDisplay -1;
pScr2->frameX1 = pScr2->frameX0 + MDMPTR(pScr)->Monitor2->HDisplay -1;
pScr2->frameY1 = pScr2->frameY0 + MDMPTR(pScr)->Monitor2->VDisplay -1;
pScr->frameX1 = pScr->frameX0 + pScr->currentMode->HDisplay -1;
pScr->frameY1 = pScr->frameY0 + pScr->currentMode->VDisplay -1;
MGAAdjustFrame(pScr->scrnIndex, pMga->M1frameX0, pMga->M1frameY0, 0);
MGAAdjustFrameCrtc2(pScr->scrnIndex, pScr2->frameX0, pScr2->frameY0, 0);
}
}
void
MGAAdjustMergeFrames(int scrnIndex, int x, int y, int flags) {
ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex];
MGAPtr pMga = MGAPTR(pScrn1);
ScrnInfoPtr pScrn2 = pMga->pScrn2;
int VTotal = pScrn1->currentMode->VDisplay;
int HTotal = pScrn1->currentMode->HDisplay;
int VMax = VTotal;
int HMax = HTotal;
BOUND(x,0,pScrn1->virtualX-HTotal);
BOUND(y,0,pScrn1->virtualY-VTotal);
switch(MDMPTR(pScrn1)->Monitor2Pos) {
case mgaLeftOf:
pScrn2->frameX0 = x;
BOUND(pScrn2->frameY0,y,y + VMax - MDMPTR(pScrn1)->Monitor2->VDisplay);
pMga->M1frameX0 = x+MDMPTR(pScrn1)->Monitor2->HDisplay;
BOUND(pMga->M1frameY0,y,y + VMax - MDMPTR(pScrn1)->Monitor1->VDisplay);
break;
case mgaRightOf:
pMga->M1frameX0 = x;
BOUND(pMga->M1frameY0,y,y + VMax - MDMPTR(pScrn1)->Monitor1->VDisplay);
pScrn2->frameX0 = x+MDMPTR(pScrn1)->Monitor1->HDisplay;
BOUND(pScrn2->frameY0,y,y + VMax - MDMPTR(pScrn1)->Monitor2->VDisplay);
break;
case mgaAbove:
BOUND(pScrn2->frameX0,x,x + HMax - MDMPTR(pScrn1)->Monitor2->HDisplay);
pScrn2->frameY0 = y;
BOUND(pMga->M1frameX0,x,x + HMax - MDMPTR(pScrn1)->Monitor1->HDisplay);
pMga->M1frameY0 = y+MDMPTR(pScrn1)->Monitor2->VDisplay;
break;
case mgaBelow:
BOUND(pMga->M1frameX0,x,x + HMax - MDMPTR(pScrn1)->Monitor1->HDisplay);
pMga->M1frameY0 = y;
BOUND(pScrn2->frameX0,x,x + HMax - MDMPTR(pScrn1)->Monitor2->HDisplay);
pScrn2->frameY0 = y+MDMPTR(pScrn1)->Monitor1->VDisplay;
break;
case mgaClone:
BOUND(pMga->M1frameX0,x,x + HMax - MDMPTR(pScrn1)->Monitor1->HDisplay);
BOUND(pMga->M1frameY0,y,y + VMax - MDMPTR(pScrn1)->Monitor1->VDisplay);
BOUND(pScrn2->frameX0,x,x + HMax - MDMPTR(pScrn1)->Monitor2->HDisplay);
BOUND(pScrn2->frameY0,y,y + VMax - MDMPTR(pScrn1)->Monitor2->VDisplay);
break;
}
BOUND(pMga->M1frameX0,0,pScrn1->virtualX -MDMPTR(pScrn1)->Monitor1->HDisplay);
BOUND(pMga->M1frameY0,0,pScrn1->virtualY -MDMPTR(pScrn1)->Monitor1->VDisplay);
BOUND(pScrn2->frameX0,0,pScrn2->virtualX -MDMPTR(pScrn1)->Monitor2->HDisplay);
BOUND(pScrn2->frameY0,0,pScrn2->virtualY -MDMPTR(pScrn1)->Monitor2->VDisplay);
pScrn1->frameX0 = x;
pScrn1->frameY0 = y;
MGAAdjustGranularity(pScrn1,&pMga->M1frameX0,&pMga->M1frameY0);
MGAAdjustGranularity(pScrn1,&pScrn2->frameX0,&pScrn2->frameY0);
MGAAdjustGranularity(pScrn1,&pScrn1->frameX0,&pScrn1->frameY0);
pMga->M1frameX1 = pMga->M1frameX0 + MDMPTR(pScrn1)->Monitor1->HDisplay -1;
pMga->M1frameY1 = pMga->M1frameY0 + MDMPTR(pScrn1)->Monitor1->VDisplay -1;
pScrn2->frameX1 = pScrn2->frameX0 + MDMPTR(pScrn1)->Monitor2->HDisplay -1;
pScrn2->frameY1 = pScrn2->frameY0 + MDMPTR(pScrn1)->Monitor2->VDisplay -1;
pScrn1->frameX1 = pScrn1->frameX0 + pScrn1->currentMode->HDisplay -1;
pScrn1->frameY1 = pScrn1->frameY0 + pScrn1->currentMode->VDisplay -1;
MGAAdjustFrame(scrnIndex, pMga->M1frameX0, pMga->M1frameY0, flags);
MGAAdjustFrameCrtc2(scrnIndex, pScrn2->frameX0, pScrn2->frameY0, flags);
return;
}
Bool
MGACloseScreenMerged(int scrnIndex, ScreenPtr pScreen) {
ScrnInfoPtr pScrn1 = xf86Screens[scrnIndex];
MGAPtr pMga = MGAPTR(pScrn1);
ScrnInfoPtr pScrn2 = pMga->pScrn2;
if(pScrn2) {
xfree(pScrn2->monitor);
pScrn2->monitor = NULL;
xfree(pScrn2);
pMga->pScrn2 = NULL;
}
if(pScrn1->modes) {
pScrn1->currentMode = pScrn1->modes;
do {
DisplayModePtr p = pScrn1->currentMode->next;
if(pScrn1->currentMode->Private)
xfree(pScrn1->currentMode->Private);
xfree(pScrn1->currentMode);
pScrn1->currentMode = p;
}while( pScrn1->currentMode != pScrn1->modes);
}
pScrn1->currentMode = pMga->M1currentMode;
pScrn1->modes = pMga->M1modes;
return TRUE;
}
Bool
MGASaveScreenMerged(ScreenPtr pScreen, int mode)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
MGAPtr pMga = MGAPTR(pScrn);
BOOL on = xf86IsUnblank(mode);
CARD8 reg;
if (on) {
reg = inMGAdac(0x1E);
outMGAdac(0x1E, reg | 1);
reg = inMGAdac(0xA0);
outMGAdac(0xA0, reg | 1);
} else {
reg = inMGAdac(0x1E);
outMGAdac(0x1E, reg & ~1);
reg = inMGAdac(0xA0);
outMGAdac(0xA0, reg & ~1);
}
return TRUE;
}