#include "Xarch.h"
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "glint_regs.h"
#include "glint.h"
#define INITIALFREQERR 100000
#define MINCLK 110000
#define MAXCLK 250000
static unsigned long
PM2DAC_CalculateMNPCForClock
(
unsigned long reqclock,
unsigned long refclock,
unsigned char *rm,
unsigned char *rn,
unsigned char *rp
)
{
unsigned char m, n, p;
unsigned long f;
long freqerr, lowestfreqerr = INITIALFREQERR;
unsigned long clock,actualclock = 0;
for (n = 2; n <= 14; n++) {
for (m = 2; m != 0; m++) {
f = refclock * m / n;
if ( (f < MINCLK) || (f > MAXCLK) )
continue;
for (p = 0; p <= 4; p++) {
clock = f >> p;
freqerr = reqclock - clock;
if (freqerr < 0)
freqerr = -freqerr;
if (freqerr < lowestfreqerr) {
*rn = n;
*rm = m;
*rp = p;
lowestfreqerr = freqerr;
actualclock = clock;
#ifdef DEBUG
ErrorF("Best %ld diff %ld\n",actualclock,freqerr);
#endif
}
}
}
}
return(actualclock);
}
Bool
Permedia2Init(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
GLINTRegPtr pReg = &pGlint->ModeReg[0];
CARD32 temp1, temp2, temp3, temp4;
pReg->glintRegs[Aperture0 >> 3] = 0;
pReg->glintRegs[Aperture1 >> 3] = 0;
pReg->glintRegs[PMFramebufferWriteMask >> 3] = 0xFFFFFFFF;
pReg->glintRegs[PMBypassWriteMask >> 3] = 0xFFFFFFFF;
pReg->glintRegs[DFIFODis >> 3] = 0;
pReg->glintRegs[FIFODis >> 3] = 1;
if (pGlint->UseBlockWrite)
pReg->glintRegs[PMMemConfig >> 3] = GLINT_READ_REG(PMMemConfig) | 1<<21;
temp1 = mode->CrtcHSyncStart - mode->CrtcHDisplay;
temp2 = mode->CrtcVSyncStart - mode->CrtcVDisplay;
temp3 = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
temp4 = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
pReg->glintRegs[PMHTotal >> 3] = Shiftbpp(pScrn,mode->CrtcHTotal);
pReg->glintRegs[PMHsEnd >> 3] = Shiftbpp(pScrn, temp1 + temp3);
pReg->glintRegs[PMHsStart >> 3] = Shiftbpp(pScrn, temp1);
pReg->glintRegs[PMHbEnd >> 3] =
Shiftbpp(pScrn,mode->CrtcHTotal-mode->CrtcHDisplay);
pReg->glintRegs[PMScreenStride >> 3] =
Shiftbpp(pScrn,pScrn->displayWidth>>1);
pReg->glintRegs[PMVTotal >> 3] = mode->CrtcVTotal;
pReg->glintRegs[PMVsEnd >> 3] = temp2 + temp4;
pReg->glintRegs[PMVsStart >> 3] = temp2;
pReg->glintRegs[PMVbEnd >> 3] = mode->CrtcVTotal - mode->CrtcVDisplay;
pReg->glintRegs[PMVideoControl >> 3] =
(1 << 5) | (1 << 3) | 1;
if (pScrn->bitsPerPixel > 8) {
pReg->glintRegs[PMVideoControl >> 3] |= 1<<16;
pReg->glintRegs[PMHTotal >> 3] >>= 1;
pReg->glintRegs[PMHsEnd >> 3] >>= 1;
pReg->glintRegs[PMHsStart >> 3] >>= 1;
pReg->glintRegs[PMHbEnd >> 3] >>= 1;
}
pReg->glintRegs[VClkCtl >> 3] = (GLINT_READ_REG(VClkCtl) & 0xFFFFFFFC);
pReg->glintRegs[PMScreenBase >> 3] = 0;
pReg->glintRegs[PMHTotal >> 3] -= 1;
pReg->glintRegs[PMHsStart >> 3] -= 1;
pReg->glintRegs[PMVTotal >> 3] -= 1;
pReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig) & 0xFFFFFFDD;
pReg->DacRegs[PM2DACIndexMDCR] = 0x00;
{
unsigned char m,n,p;
(void) PM2DAC_CalculateMNPCForClock(mode->Clock,pGlint->RefClock,
&m,&n,&p);
pReg->DacRegs[PM2DACIndexClockAM] = m;
pReg->DacRegs[PM2DACIndexClockAN] = n;
pReg->DacRegs[PM2DACIndexClockAP] = p|0x08;
}
if (pScrn->rgbBits == 8)
pReg->DacRegs[PM2DACIndexMCR] = 0x02;
else
pReg->DacRegs[PM2DACIndexMCR] = 0x00;
if (!(mode->Flags & V_PHSYNC))
pReg->DacRegs[PM2DACIndexMCR] |= 0x04;
if (!(mode->Flags & V_PVSYNC))
pReg->DacRegs[PM2DACIndexMCR] |= 0x08;
switch (pScrn->bitsPerPixel)
{
case 8:
pReg->DacRegs[PM2DACIndexCMR] = PM2DAC_RGB | PM2DAC_GRAPHICS |
PM2DAC_CI8;
break;
case 16:
if (pScrn->depth == 15) {
pReg->DacRegs[PM2DACIndexCMR] = PM2DAC_RGB | PM2DAC_TRUECOLOR|
PM2DAC_GRAPHICS | PM2DAC_5551;
} else {
pReg->DacRegs[PM2DACIndexCMR] = PM2DAC_RGB | PM2DAC_TRUECOLOR|
PM2DAC_GRAPHICS | PM2DAC_565;
}
break;
case 24:
pReg->DacRegs[PM2DACIndexCMR] = PM2DAC_RGB | PM2DAC_TRUECOLOR|
PM2DAC_GRAPHICS | PM2DAC_PACKED;
break;
case 32:
pReg->DacRegs[PM2DACIndexCMR] = PM2DAC_RGB |
PM2DAC_GRAPHICS | PM2DAC_8888;
if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
pReg->DacRegs[PM2DACIndexColorKeyControl] = 0x11;
pReg->DacRegs[PM2DACIndexColorKeyOverlay] = pScrn->colorKey;
} else
pReg->DacRegs[PM2DACIndexCMR] |= PM2DAC_TRUECOLOR;
break;
}
return(TRUE);
}
void
Permedia2Save(ScrnInfoPtr pScrn, GLINTRegPtr glintReg)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
int i;
xf86SlowBcopy((CARD8*)pGlint->FbBase, (CARD8*)pGlint->VGAdata, 65536);
glintReg->glintRegs[Aperture0 >> 3] = GLINT_READ_REG(Aperture0);
glintReg->glintRegs[Aperture1 >> 3] = GLINT_READ_REG(Aperture1);
glintReg->glintRegs[PMFramebufferWriteMask >> 3] =
GLINT_READ_REG(PMFramebufferWriteMask);
glintReg->glintRegs[PMBypassWriteMask >> 3] = GLINT_READ_REG(PMBypassWriteMask);
glintReg->glintRegs[DFIFODis >> 3] = GLINT_READ_REG(DFIFODis);
glintReg->glintRegs[FIFODis >> 3] = GLINT_READ_REG(FIFODis);
if (pGlint->UseBlockWrite)
glintReg->glintRegs[PMMemConfig >> 3] = GLINT_READ_REG(PMMemConfig);
glintReg->glintRegs[PMHTotal >> 3] = GLINT_READ_REG(PMHTotal);
glintReg->glintRegs[PMHbEnd >> 3] = GLINT_READ_REG(PMHbEnd);
glintReg->glintRegs[PMHbEnd >> 3] = GLINT_READ_REG(PMHgEnd);
glintReg->glintRegs[PMScreenStride >> 3] = GLINT_READ_REG(PMScreenStride);
glintReg->glintRegs[PMHsStart >> 3] = GLINT_READ_REG(PMHsStart);
glintReg->glintRegs[PMHsEnd >> 3] = GLINT_READ_REG(PMHsEnd);
glintReg->glintRegs[PMVTotal >> 3] = GLINT_READ_REG(PMVTotal);
glintReg->glintRegs[PMVbEnd >> 3] = GLINT_READ_REG(PMVbEnd);
glintReg->glintRegs[PMVsStart >> 3] = GLINT_READ_REG(PMVsStart);
glintReg->glintRegs[PMVsEnd >> 3] = GLINT_READ_REG(PMVsEnd);
glintReg->glintRegs[PMScreenBase >> 3] = GLINT_READ_REG(PMScreenBase);
glintReg->glintRegs[PMVideoControl >> 3] = GLINT_READ_REG(PMVideoControl);
glintReg->glintRegs[VClkCtl >> 3] = GLINT_READ_REG(VClkCtl);
glintReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig);
for (i=0;i<768;i++) {
Permedia2ReadAddress(pScrn, i);
glintReg->cmap[i] = Permedia2ReadData(pScrn);
}
glintReg->DacRegs[PM2DACIndexColorKeyOverlay] =
Permedia2InIndReg(pScrn, PM2DACIndexColorKeyOverlay);
glintReg->DacRegs[PM2DACIndexColorKeyControl] =
Permedia2InIndReg(pScrn, PM2DACIndexColorKeyControl);
glintReg->DacRegs[PM2DACIndexMCR] =
Permedia2InIndReg(pScrn, PM2DACIndexMCR);
glintReg->DacRegs[PM2DACIndexMDCR] =
Permedia2InIndReg(pScrn, PM2DACIndexMDCR);
glintReg->DacRegs[PM2DACIndexCMR] =
Permedia2InIndReg(pScrn, PM2DACIndexCMR);
glintReg->DacRegs[PM2DACIndexClockAM] =
Permedia2InIndReg(pScrn, PM2DACIndexClockAM);
glintReg->DacRegs[PM2DACIndexClockAN] =
Permedia2InIndReg(pScrn, PM2DACIndexClockAN);
glintReg->DacRegs[PM2DACIndexClockAP] =
Permedia2InIndReg(pScrn, PM2DACIndexClockAP);
}
void
Permedia2Restore(ScrnInfoPtr pScrn, GLINTRegPtr glintReg)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
int i;
if (pGlint->STATE)
xf86SlowBcopy((CARD8*)pGlint->VGAdata, (CARD8*)pGlint->FbBase, 65536);
#if 0
GLINT_SLOW_WRITE_REG(0, ResetStatus);
while(GLINT_READ_REG(ResetStatus) != 0) {
xf86MsgVerb(X_INFO, 2, "Resetting Engine - Please Wait.\n");
};
#endif
GLINT_SLOW_WRITE_REG(0xFF, PM2DACReadMask);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[Aperture0 >> 3], Aperture0);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[Aperture1 >> 3], Aperture1);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMFramebufferWriteMask >> 3],
PMFramebufferWriteMask);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMBypassWriteMask >> 3],
PMBypassWriteMask);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[DFIFODis >> 3], DFIFODis);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[FIFODis >> 3], FIFODis);
if (pGlint->UseBlockWrite)
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMMemConfig >> 3],PMMemConfig);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVideoControl >> 3],
PMVideoControl);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHbEnd >> 3], PMHgEnd);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMScreenBase >> 3], PMScreenBase);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[VClkCtl >> 3], VClkCtl);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMScreenStride >> 3],
PMScreenStride);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHTotal >> 3], PMHTotal);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHbEnd >> 3], PMHbEnd);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHsStart >> 3], PMHsStart);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMHsEnd >> 3], PMHsEnd);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVTotal >> 3], PMVTotal);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVbEnd >> 3], PMVbEnd);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVsStart >> 3], PMVsStart);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[PMVsEnd >> 3], PMVsEnd);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[ChipConfig >> 3], ChipConfig);
Permedia2OutIndReg(pScrn, PM2DACIndexColorKeyOverlay, 0x00,
glintReg->DacRegs[PM2DACIndexColorKeyOverlay]);
Permedia2OutIndReg(pScrn, PM2DACIndexColorKeyControl, 0x00,
glintReg->DacRegs[PM2DACIndexColorKeyControl]);
Permedia2OutIndReg(pScrn, PM2DACIndexMCR, 0x00,
glintReg->DacRegs[PM2DACIndexMCR]);
Permedia2OutIndReg(pScrn, PM2DACIndexMDCR, 0x00,
glintReg->DacRegs[PM2DACIndexMDCR]);
Permedia2OutIndReg(pScrn, PM2DACIndexCMR, 0x00,
glintReg->DacRegs[PM2DACIndexCMR]);
Permedia2OutIndReg(pScrn, PM2DACIndexClockAM, 0x00,
glintReg->DacRegs[PM2DACIndexClockAM]);
Permedia2OutIndReg(pScrn, PM2DACIndexClockAN, 0x00,
glintReg->DacRegs[PM2DACIndexClockAN]);
Permedia2OutIndReg(pScrn, PM2DACIndexClockAP, 0x00,
glintReg->DacRegs[PM2DACIndexClockAP]);
for (i=0;i<768;i++) {
Permedia2WriteAddress(pScrn, i);
Permedia2WriteData(pScrn, glintReg->cmap[i]);
}
}
static void
Permedia2ShowCursor(ScrnInfoPtr pScrn)
{
Permedia2OutIndReg(pScrn, PM2DACCursorControl, 0x00, 0x43);
}
static void
Permedia2HideCursor(ScrnInfoPtr pScrn)
{
Permedia2OutIndReg(pScrn, PM2DACCursorControl, 0x00, 0x00);
}
static void
Permedia2LoadCursorImage(
ScrnInfoPtr pScrn,
unsigned char *src
)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
int i;
GLINT_SLOW_WRITE_REG(0x00, PM2DACWriteAddress);
for (i=0; i<1024; i++) {
GLINT_SLOW_WRITE_REG(*(src++), PM2DACCursorData);
}
}
static void
Permedia2SetCursorPosition(
ScrnInfoPtr pScrn,
int x, int y
)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
x += 64;
y += 64;
GLINT_WRITE_REG(x & 0xFF, PM2DACCursorXLsb);
GLINT_WRITE_REG((x>>8) & 0x07, PM2DACCursorXMsb);
GLINT_WRITE_REG(y & 0xFF, PM2DACCursorYLsb);
GLINT_WRITE_REG((y>>8) & 0x07, PM2DACCursorYMsb);
}
static void
Permedia2SetCursorColors(
ScrnInfoPtr pScrn,
int bg, int fg
)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
GLINT_SLOW_WRITE_REG(1, PM2DACCursorColorAddress);
GLINT_SLOW_WRITE_REG(bg >> 0, PM2DACCursorColorData);
GLINT_SLOW_WRITE_REG(bg >> 8, PM2DACCursorColorData);
GLINT_SLOW_WRITE_REG(bg >> 16, PM2DACCursorColorData);
GLINT_SLOW_WRITE_REG(fg >> 0, PM2DACCursorColorData);
GLINT_SLOW_WRITE_REG(fg >> 8, PM2DACCursorColorData);
GLINT_SLOW_WRITE_REG(fg >> 16, PM2DACCursorColorData);
}
static Bool
Permedia2UseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
{
return TRUE;
}
Bool
Permedia2HWCursorInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
GLINTPtr pGlint = GLINTPTR(pScrn);
xf86CursorInfoPtr infoPtr;
infoPtr = xf86CreateCursorInfoRec();
if(!infoPtr) return FALSE;
pGlint->CursorInfoRec = infoPtr;
infoPtr->MaxWidth = 64;
infoPtr->MaxHeight = 64;
infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
#endif
HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
infoPtr->SetCursorColors = Permedia2SetCursorColors;
infoPtr->SetCursorPosition = Permedia2SetCursorPosition;
infoPtr->LoadCursorImage = Permedia2LoadCursorImage;
infoPtr->HideCursor = Permedia2HideCursor;
infoPtr->ShowCursor = Permedia2ShowCursor;
infoPtr->UseHWCursor = Permedia2UseHWCursor;
return(xf86InitCursor(pScreen, infoPtr));
}
void
Permedia2I2CUDelay(I2CBusPtr b, int usec)
{
GLINTPtr pGlint = (GLINTPtr) b->DriverPrivate.ptr;
CARD32 ct1 = GLINT_READ_REG(PMCount);
CARD32 ct2 = usec * 100;
if (GLINT_READ_REG(PMCount) != ct1)
while ((GLINT_READ_REG(PMCount) - ct1) < ct2);
}
void
Permedia2I2CPutBits(I2CBusPtr b, int scl, int sda)
{
GLINTPtr pGlint = (GLINTPtr) b->DriverPrivate.ptr;
int r = (pGlint->DDCBus == b) ? PMDDCData : VSSerialBusControl;
CARD32 v = GLINT_READ_REG(r) & ~(ClkOut | DataOut);
if (scl > 0) v |= ClkOut;
if (sda > 0) v |= DataOut;
GLINT_WRITE_REG(v, r);
}
void
Permedia2I2CGetBits(I2CBusPtr b, int *scl, int *sda)
{
GLINTPtr pGlint = (GLINTPtr) b->DriverPrivate.ptr;
CARD32 v = GLINT_READ_REG((pGlint->DDCBus == b) ?
PMDDCData : VSSerialBusControl);
*scl = (v & ClkIn) > 0;
*sda = (v & DataIn) > 0;
}
void
Permedia2PreInit(ScrnInfoPtr pScrn)
{
#if defined(__alpha__)
GLINTPtr pGlint = GLINTPTR(pScrn);
if (!xf86IsPrimaryPci(pGlint->PciInfo)) {
if ( IS_GLORIASYNERGY ) {
Permedia2OutIndReg(pScrn, PM2DACIndexMemClockM, 0x00, 0x7b);
Permedia2OutIndReg(pScrn, PM2DACIndexMemClockN, 0x00, 0x0b);
Permedia2OutIndReg(pScrn, PM2DACIndexMemClockP, 0x00, 0x09);
GLINT_SLOW_WRITE_REG( 0x20, PMBootAddress);
GLINT_SLOW_WRITE_REG( 0xe6002021, PMMemConfig);
}
}
#endif
}