#include "savage_driver.h"
static void SavageLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
static void SavageSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
static void SavageSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
#define inCRReg(reg) (VGAHWPTR(pScrn))->readCrtc( VGAHWPTR(pScrn), reg )
#define outCRReg(reg, val) (VGAHWPTR(pScrn))->writeCrtc( VGAHWPTR(pScrn), reg, val )
#define inSRReg(reg) (VGAHWPTR(pScrn))->readSeq( VGAHWPTR(pScrn), reg )
#define outSRReg(reg, val) (VGAHWPTR(pScrn))->writeSeq( VGAHWPTR(pScrn), reg, val )
#define inStatus1() (VGAHWPTR(pScrn))->readST01( VGAHWPTR(pScrn) )
#define waitHSync(n) { \
int num = n; \
while (num--) { \
while ((inStatus1()) & 0x01){};\
while (!(inStatus1()) & 0x01){};\
} \
}
#define MAX_CURS 64
static Bool
SavageUseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
{
ScrnInfoPtr pScrn = xf86Screens[pScr->myNum];
SavagePtr psav = SAVPTR(pScrn);
if (psav->PanelX != pScrn->currentMode->HDisplay
|| psav->PanelY != pScrn->currentMode->VDisplay) {
unsigned char cr6d = inCRReg( 0x6d );
if (cr6d & 0x02)
return FALSE;
}
return TRUE;
}
Bool
SavageHWCursorInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
SavagePtr psav = SAVPTR(pScrn);
xf86CursorInfoPtr infoPtr;
infoPtr = xf86CreateCursorInfoRec();
if(!infoPtr)
return FALSE;
psav->CursorInfoRec = infoPtr;
infoPtr->MaxWidth = MAX_CURS;
infoPtr->MaxHeight = MAX_CURS;
infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 |
HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
HARDWARE_CURSOR_INVERT_MASK;
if(
((psav->Chipset != S3_SAVAGE4)
&& (inSRReg(0x18) & 0x80) && (inSRReg(0x15) & 0x50) )
||
S3_SAVAGE_MOBILE_SERIES(psav->Chipset)
)
infoPtr->Flags |= HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
infoPtr->SetCursorColors = SavageSetCursorColors;
infoPtr->SetCursorPosition = SavageSetCursorPosition;
infoPtr->LoadCursorImage = SavageLoadCursorImage;
infoPtr->HideCursor = SavageHideCursor;
infoPtr->ShowCursor = SavageShowCursor;
if ((S3_SAVAGE_MOBILE_SERIES(psav->Chipset)
|| (psav->Chipset == S3_PROSAVAGE)) && !psav->CrtOnly)
infoPtr->UseHWCursor = SavageUseHWCursor;
else
infoPtr->UseHWCursor = NULL;
if( !psav->CursorKByte )
psav->CursorKByte = pScrn->videoRam - 4;
return xf86InitCursor(pScreen, infoPtr);
}
void
SavageShowCursor(ScrnInfoPtr pScrn)
{
outCRReg( 0x45, inCRReg(0x45) | 0x01 );
SAVPTR(pScrn)->hwc_on = TRUE;
}
void
SavageHideCursor(ScrnInfoPtr pScrn)
{
if( S3_SAVAGE4_SERIES( SAVPTR(pScrn)->Chipset ) )
{
waitHSync(5);
}
outCRReg( 0x45, inCRReg(0x45) & 0xfe );
SAVPTR(pScrn)->hwc_on = FALSE;
}
static void
SavageLoadCursorImage(
ScrnInfoPtr pScrn,
unsigned char* src)
{
SavagePtr psav = SAVPTR(pScrn);
outCRReg( 0x4d, (0xff & psav->CursorKByte));
outCRReg( 0x4c, (0xff00 & psav->CursorKByte) >> 8);
memcpy(psav->FBBase + psav->CursorKByte * 1024, src, 1024);
if( S3_SAVAGE4_SERIES( psav->Chipset ) ) {
volatile unsigned int i = ALT_STATUS_WORD0;
(void)i;
}
}
static void
SavageSetCursorPosition(
ScrnInfoPtr pScrn,
int x,
int y)
{
unsigned char xoff, yoff;
if( S3_SAVAGE4_SERIES( SAVPTR(pScrn)->Chipset ) )
{
waitHSync(5);
}
if (pScrn->bitsPerPixel == 8)
x += ((pScrn->frameX0) & 3);
else if (pScrn->bitsPerPixel == 16)
x += ((pScrn->frameX0) & 1);
else if (pScrn->bitsPerPixel == 32)
x += ((pScrn->frameX0+2) & 3) - 2;
if (x < 0) {
xoff = ((-x) & 0xFE);
x = 0;
} else {
xoff = 0;
}
if (y < 0) {
yoff = ((-y) & 0xFE);
y = 0;
} else {
yoff = 0;
}
outCRReg( 0x46, (x & 0xff00)>>8 );
outCRReg( 0x47, (x & 0xff) );
outCRReg( 0x49, (y & 0xff) );
outCRReg( 0x4e, xoff );
outCRReg( 0x4f, yoff );
outCRReg( 0x48, (y & 0xff00)>>8 );
}
static void
SavageSetCursorColors(
ScrnInfoPtr pScrn,
int bg,
int fg)
{
SavagePtr psav = SAVPTR(pScrn);
Bool bNeedExtra = FALSE;
bNeedExtra =
(psav->CursorInfoRec->Flags & HARDWARE_CURSOR_TRUECOLOR_AT_8BPP);
if(
S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
(pScrn->depth == 24) ||
((pScrn->depth == 8) && bNeedExtra)
)
{
inCRReg(0x45);
outCRReg(0x4a, fg);
outCRReg(0x4a, fg >> 8);
outCRReg(0x4a, fg >> 16);
inCRReg(0x45);
outCRReg(0x4b, bg);
outCRReg(0x4b, bg >> 8);
outCRReg(0x4b, bg >> 16);
return;
}
else if( (pScrn->depth == 15) || (pScrn->depth == 16) )
{
if (pScrn->depth == 15) {
fg = ((fg & 0xf80000) >> 9) |
((fg & 0xf800) >> 6) |
((fg & 0xf8) >> 3);
bg = ((bg & 0xf80000) >> 9) |
((bg & 0xf800) >> 6) |
((bg & 0xf8) >> 3);
} else {
fg = ((fg & 0xf80000) >> 8) |
((fg & 0xfc00) >> 5) |
((fg & 0xf8) >> 3);
bg = ((bg & 0xf80000) >> 8) |
((bg & 0xfc00) >> 5) |
((bg & 0xf8) >> 3);
}
inCRReg( 0x45 );
outCRReg( 0x4a, fg );
outCRReg( 0x4a, fg>>8 );
if( bNeedExtra )
{
outCRReg( 0x4a, fg );
outCRReg( 0x4a, fg>>8 );
}
inCRReg( 0x45 );
outCRReg( 0x4b, bg );
outCRReg( 0x4b, bg>>8 );
if( bNeedExtra )
{
outCRReg( 0x4b, bg );
outCRReg( 0x4b, bg>>8 );
}
}
else if( pScrn->depth == 8 )
{
inCRReg(0x45);
outCRReg(0x4a, fg);
outCRReg(0x4a, fg);
inCRReg(0x45);
outCRReg(0x4b, bg);
outCRReg(0x4b, bg);
}
}