#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "glint_regs.h"
#include "glint.h"
static unsigned long
PM2VDAC_CalculateClock
(
unsigned long reqclock,
unsigned long refclock,
unsigned char *prescale,
unsigned char *feedback,
unsigned char *postscale
)
{
int f, pre, post;
unsigned long freq;
long freqerr = 1000;
unsigned long actualclock = 0;
unsigned char divide[5] = { 1, 2, 4, 8, 16 };
for (f=1;f<256;f++) {
for (pre=1;pre<256;pre++) {
for (post=0;post<2;post++) {
freq = ((refclock * f) / (pre * (1 << divide[post])));
if ((reqclock > freq - freqerr)&&(reqclock < freq + freqerr)){
freqerr = (reqclock > freq) ?
reqclock - freq : freq - reqclock;
*feedback = f;
*prescale = pre;
*postscale = post;
actualclock = freq;
}
}
}
}
return(actualclock);
}
static void
Permedia2VPreInitSecondary(ScrnInfoPtr pScrn)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
Permedia2vOutIndReg(pScrn, PM2VDACRDMClkControl, 0x00, 0);
Permedia2vOutIndReg(pScrn, PM2VDACRDMClkPreScale, 0x00, 0x09);
Permedia2vOutIndReg(pScrn, PM2VDACRDMClkFeedbackScale, 0x00, 0x58);
Permedia2vOutIndReg(pScrn, PM2VDACRDMClkPostScale, 0x00, 0x01);
Permedia2vOutIndReg(pScrn, PM2VDACRDMClkControl, 0x00, 1);
while ( (Permedia2vInIndReg(pScrn, PM2VDACRDMClkControl) & 0x2) == 0);
GLINT_SLOW_WRITE_REG(0xe6002021,PMMemConfig);
GLINT_SLOW_WRITE_REG(0x00000020,PMBootAddress);
}
void
Permedia2VPreInit(ScrnInfoPtr pScrn)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
if (IS_JPRO) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Appian Jeronimo Pro 4x8mb board detected and initialized.\n");
Permedia2VPreInitSecondary(pScrn);
}
#if defined(__alpha__)
if (!xf86IsPrimaryPci(pGlint->PciInfo)) {
if ( IS_QPM2V ) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"PM2V secondary: initializing\n");
Permedia2VPreInitSecondary(pScrn);
}
}
#endif
}
Bool
Permedia2VInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
GLINTRegPtr pReg = &pGlint->ModeReg[0];
CARD32 temp1, temp2, temp3, temp4;
temp1 = 0;
temp2 = 0;
#if X_BYTE_ORDER == X_BIG_ENDIAN
switch (pGlint->HwBpp) {
case 8:
case 24:
temp1 = 0x00;
temp2 = 0x00;
break;
case 15:
case 16:
temp1 = 0x02;
temp2 = 0x02;
break;
case 32:
temp1 = 0x01;
temp2 = 0x01;
break;
default:
break;
};
#endif
pReg->glintRegs[Aperture0 >> 3] = temp1;
pReg->glintRegs[Aperture1 >> 3] = temp2;
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;
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[PM2VDACRDDACControl] = 0x00;
{
unsigned char m,n,p;
(void) PM2VDAC_CalculateClock(mode->Clock/2,pGlint->RefClock,
&m,&n,&p);
pReg->DacRegs[PM2VDACRDDClk0PreScale] = m;
pReg->DacRegs[PM2VDACRDDClk0FeedbackScale] = n;
pReg->DacRegs[PM2VDACRDDClk0PostScale] = p;
}
pReg->glintRegs[PM2VDACRDIndexControl >> 3] = 0x00;
if (pScrn->rgbBits == 8)
pReg->DacRegs[PM2VDACRDMiscControl] = 0x01;
else
pReg->DacRegs[PM2VDACRDMiscControl] = 0x00;
pReg->DacRegs[PM2VDACRDSyncControl] = 0x00;
if (mode->Flags & V_PHSYNC)
pReg->DacRegs[PM2VDACRDSyncControl] |= 0x01;
if (mode->Flags & V_PVSYNC)
pReg->DacRegs[PM2VDACRDSyncControl] |= 0x08;
switch (pScrn->bitsPerPixel)
{
case 8:
pReg->DacRegs[PM2VDACRDPixelSize] = 0x00;
pReg->DacRegs[PM2VDACRDColorFormat] = 0x2E;
break;
case 16:
pReg->DacRegs[PM2VDACRDMiscControl] |= 0x08;
pReg->DacRegs[PM2VDACRDPixelSize] = 0x01;
if (pScrn->depth == 15)
pReg->DacRegs[PM2VDACRDColorFormat] = 0x61;
else
pReg->DacRegs[PM2VDACRDColorFormat] = 0x70;
break;
case 24:
pReg->DacRegs[PM2VDACRDMiscControl] |= 0x08;
pReg->DacRegs[PM2VDACRDPixelSize] = 0x04;
pReg->DacRegs[PM2VDACRDColorFormat] = 0x60;
break;
case 32:
pReg->DacRegs[PM2VDACRDMiscControl] |= 0x08;
pReg->DacRegs[PM2VDACRDPixelSize] = 0x02;
pReg->DacRegs[PM2VDACRDColorFormat] = 0x20;
if (pScrn->overlayFlags & OVERLAY_8_32_PLANAR) {
pReg->DacRegs[PM2VDACRDMiscControl] |= 0x18;
pReg->DacRegs[PM2VDACRDOverlayKey] = pScrn->colorKey;
}
break;
}
return(TRUE);
}
void
Permedia2VSave(ScrnInfoPtr pScrn, GLINTRegPtr glintReg)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
int i;
memcpy((CARD8*)pGlint->VGAdata,(CARD8*)pGlint->FbBase, 65536);
glintReg->glintRegs[ChipConfig >> 3] = GLINT_READ_REG(ChipConfig);
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);
for (i=0;i<768;i++) {
Permedia2ReadAddress(pScrn, i);
glintReg->cmap[i] = Permedia2ReadData(pScrn);
}
glintReg->glintRegs[PM2VDACRDIndexControl >> 3] =
GLINT_READ_REG(PM2VDACRDIndexControl);
glintReg->DacRegs[PM2VDACRDOverlayKey] =
Permedia2vInIndReg(pScrn, PM2VDACRDOverlayKey);
glintReg->DacRegs[PM2VDACRDSyncControl] =
Permedia2vInIndReg(pScrn, PM2VDACRDSyncControl);
glintReg->DacRegs[PM2VDACRDMiscControl] =
Permedia2vInIndReg(pScrn, PM2VDACRDMiscControl);
glintReg->DacRegs[PM2VDACRDDACControl] =
Permedia2vInIndReg(pScrn, PM2VDACRDDACControl);
glintReg->DacRegs[PM2VDACRDPixelSize] =
Permedia2vInIndReg(pScrn, PM2VDACRDPixelSize);
glintReg->DacRegs[PM2VDACRDColorFormat] =
Permedia2vInIndReg(pScrn, PM2VDACRDColorFormat);
glintReg->DacRegs[PM2VDACRDDClk0PreScale] = Permedia2vInIndReg(pScrn, PM2VDACRDDClk0PreScale);
glintReg->DacRegs[PM2VDACRDDClk0FeedbackScale] = Permedia2vInIndReg(pScrn, PM2VDACRDDClk0FeedbackScale);
glintReg->DacRegs[PM2VDACRDDClk0PostScale] = Permedia2vInIndReg(pScrn, PM2VDACRDDClk0PostScale);
}
void
Permedia2VRestore(ScrnInfoPtr pScrn, GLINTRegPtr glintReg)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
CARD32 temp;
int i;
if (pGlint->STATE)
memcpy((CARD8*)pGlint->FbBase,(CARD8*)pGlint->VGAdata, 65536);
GLINT_SLOW_WRITE_REG(glintReg->glintRegs[ChipConfig >> 3], ChipConfig);
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[PM2VDACRDIndexControl >> 3],
PM2VDACRDIndexControl);
Permedia2vOutIndReg(pScrn, PM2VDACRDOverlayKey, 0x00,
glintReg->DacRegs[PM2VDACRDOverlayKey]);
Permedia2vOutIndReg(pScrn, PM2VDACRDSyncControl, 0x00,
glintReg->DacRegs[PM2VDACRDSyncControl]);
Permedia2vOutIndReg(pScrn, PM2VDACRDMiscControl, 0x00,
glintReg->DacRegs[PM2VDACRDMiscControl]);
Permedia2vOutIndReg(pScrn, PM2VDACRDDACControl, 0x00,
glintReg->DacRegs[PM2VDACRDDACControl]);
Permedia2vOutIndReg(pScrn, PM2VDACRDPixelSize, 0x00,
glintReg->DacRegs[PM2VDACRDPixelSize]);
Permedia2vOutIndReg(pScrn, PM2VDACRDColorFormat, 0x00,
glintReg->DacRegs[PM2VDACRDColorFormat]);
for (i=0;i<768;i++) {
Permedia2WriteAddress(pScrn, i);
Permedia2WriteData(pScrn, glintReg->cmap[i]);
}
temp = Permedia2vInIndReg(pScrn, PM2VDACIndexClockControl) & 0xFC;
Permedia2vOutIndReg(pScrn, PM2VDACRDDClk0PreScale, 0x00,
glintReg->DacRegs[PM2VDACRDDClk0PreScale]);
Permedia2vOutIndReg(pScrn, PM2VDACRDDClk0FeedbackScale, 0x00,
glintReg->DacRegs[PM2VDACRDDClk0FeedbackScale]);
Permedia2vOutIndReg(pScrn, PM2VDACRDDClk0PostScale, 0x00,
glintReg->DacRegs[PM2VDACRDDClk0PostScale]);
Permedia2vOutIndReg(pScrn, PM2VDACIndexClockControl, 0x00, temp|0x03);
}
static void
Permedia2vShowCursor(ScrnInfoPtr pScrn)
{
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorMode, 0x00, 0x11);
}
static void Permedia2vLoadCursorCallback(ScrnInfoPtr pScrn);
static void
Permedia2vHideCursor(ScrnInfoPtr pScrn)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorMode, 0x00, 0x10);
if (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_PERMEDIA2V) {
memset(pGlint->HardwareCursorPattern, 0, 1024);
pGlint->LoadCursorCallback = Permedia2vLoadCursorCallback;
}
}
static void
Permedia2vLoadCursorCallback(
ScrnInfoPtr pScrn
)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
int i;
for (i=0; i<1024; i++)
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPattern+i, 0x00,
pGlint->HardwareCursorPattern[i]);
pGlint->LoadCursorCallback = NULL;
}
static void
Permedia2vLoadCursorImage(
ScrnInfoPtr pScrn,
unsigned char *src
)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
int i;
for (i=0; i<1024; i++)
pGlint->HardwareCursorPattern[i] = *(src++);
pGlint->LoadCursorCallback = Permedia2vLoadCursorCallback;
}
static void
Permedia2vSetCursorPosition(
ScrnInfoPtr pScrn,
int x, int y
)
{
x += 64;
y += 64;
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorHotSpotX, 0x00, 0x3f);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorHotSpotY, 0x00, 0x3f);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorXLow, 0x00, x & 0xFF);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorXHigh, 0x00, (x>>8) & 0x0F);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorYLow, 0x00, y & 0xFF);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorYHigh, 0x00, (y>>8) & 0x0F);
Permedia2vOutIndReg(pScrn, PM2DACCursorControl, 0x00, 0x00);
}
static void
Permedia2vCursorColorCallback(
ScrnInfoPtr pScrn
)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
int fg = pGlint->FGCursor;
int bg = pGlint->BGCursor;
if ((pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_PERMEDIA3) ||
((pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA) &&
(pGlint->MultiChip == PCI_CHIP_PERMEDIA3)) ) {
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+39, 0x00, (fg>>16)&0xff);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+40, 0x00, (fg>>8)&0xff);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+41, 0x00, fg & 0xff);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+42, 0x00, (bg>>16)&0xff);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+43, 0x00, (bg>>8)&0xff);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+44, 0x00, bg & 0xff);
} else {
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+0, 0x00, (bg>>16)&0xff);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+1, 0x00, (bg>>8)&0xff);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+2, 0x00, bg & 0xff);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+3, 0x00, (fg>>16)&0xff);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+4, 0x00, (fg>>8)&0xff);
Permedia2vOutIndReg(pScrn, PM2VDACRDCursorPalette+5, 0x00, fg & 0xff);
}
pGlint->CursorColorCallback = NULL;
}
static void
Permedia2vSetCursorColors(
ScrnInfoPtr pScrn,
int bg, int fg
)
{
GLINTPtr pGlint = GLINTPTR(pScrn);
pGlint->FGCursor = fg;
pGlint->BGCursor = bg;
pGlint->CursorColorCallback = Permedia2vCursorColorCallback;
}
static Bool
Permedia2vUseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
{
return TRUE;
}
Bool
Permedia2vHWCursorInit(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_BIG_ENDIAN
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
#endif
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
infoPtr->SetCursorColors = Permedia2vSetCursorColors;
infoPtr->SetCursorPosition = Permedia2vSetCursorPosition;
infoPtr->LoadCursorImage = Permedia2vLoadCursorImage;
infoPtr->HideCursor = Permedia2vHideCursor;
infoPtr->ShowCursor = Permedia2vShowCursor;
infoPtr->UseHWCursor = Permedia2vUseHWCursor;
return(xf86InitCursor(pScreen, infoPtr));
}