#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "compiler.h"
#include "xf86Pci.h"
#include "xf86PciInfo.h"
#include "vgaHW.h"
#include "cir.h"
#define _LG_PRIVATE_
#include "lg.h"
#include "lg_xaa.h"
#define CURSORWIDTH 64
#define CURSORHEIGHT 64
#define CURSORSIZE (CURSORWIDTH*CURSORHEIGHT/8)
enum {
PALETTE_READ_ADDR = 0x00A4,
PALETTE_WRITE_ADDR = 0x00A8,
PALETTE_DATA = 0x00AC,
PALETTE_STATE = 0x00B0,
CURSOR_X_POS = 0x00E0,
CURSOR_Y_POS = 0x00E2,
CURSOR_PRESET = 0x00E4,
CURSOR_CONTROL = 0x00E6,
CURSOR_ADDR = 0x00E8
};
static void
LgFindCursorTile(ScrnInfoPtr pScrn, int *x, int *y, int *width, int *height,
CARD32 *curAddr);
static void LgSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
const CirPtr pCir = CIRPTR(pScrn);
#ifdef LG_CURSOR_DEBUG
ErrorF("LgSetCursorColors\n");
#endif
memwb(PALETTE_STATE, (memrb(PALETTE_STATE) | (1<<3)));
memwb(PALETTE_WRITE_ADDR, 0x00);
memwb(PALETTE_DATA, (bg >> 16));
memwb(PALETTE_DATA, (bg >> 8));
memwb(PALETTE_DATA, (bg >> 0));
memwb(PALETTE_WRITE_ADDR, 0x0F);
memwb(PALETTE_DATA, (fg >> 16));
memwb(PALETTE_DATA, (fg >> 8));
memwb(PALETTE_DATA, (fg >> 0));
memwb(PALETTE_STATE, (memrb(PALETTE_STATE) & ~(1<<3)));
}
static void LgSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
const CirPtr pCir = CIRPTR(pScrn);
#if 0
#ifdef LG_CURSOR_DEBUG
ErrorF("LgSetCursorPosition %d %d\n", x, y);
#endif
#endif
if (x < 0 || y < 0) {
CARD16 oldPreset = memrw(CURSOR_PRESET);
CARD16 newPreset = 0x8080 & oldPreset;
if (x < 0) {
newPreset |= ((-x & 0x7F) << 8);
x = 0;
}
if (y < 0) {
newPreset |= ((-y & 0x7F) << 0);
y = 0;
}
memww(CURSOR_PRESET, newPreset);
pCir->CursorIsSkewed = TRUE;
} else if (pCir->CursorIsSkewed) {
memww(CURSOR_PRESET, memrw(CURSOR_PRESET & 0x8080));
pCir->CursorIsSkewed = FALSE;
}
memww(CURSOR_X_POS, x);
memww(CURSOR_Y_POS, y);
}
static void LgLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits)
{
const CirPtr pCir = CIRPTR(pScrn);
const LgPtr pLg = LGPTR(pCir);
volatile CARD32 *pXCursorBits = (CARD32 *)bits;
int l, w;
#ifdef LG_CURSOR_DEBUG
ErrorF("LgLoadCursorImage\n");
#endif
while (!LgREADY()) {}
;
while (memrb(QFREE) < 10) {}
;
LgSETMODE(HOST2SCR);
LgSETROP(0x00CC);
LgSETMDSTXY(pLg->HWCursorImageX+pLg->HWCursorTileWidth, pLg->HWCursorImageY);
LgSETMPHASE1(0);
LgSETMEXTENTSNOMONOQW(pLg->HWCursorTileWidth, pLg->HWCursorTileHeight);
for (l = 0; l < CURSORHEIGHT; l++) {
for (w = 0; w < CURSORWIDTH >> 5; w++)
memwl(HOSTDATA, 0x00000000);
for (w = 0; w < CURSORWIDTH >> 5; w++)
memwl(HOSTDATA, 0x00000000);
}
LgSETMDSTXY(pLg->HWCursorImageX, pLg->HWCursorImageY);
LgSETMPHASE1(0);
LgSETMEXTENTSNOMONOQW(pLg->HWCursorTileWidth, pLg->HWCursorTileHeight);
for (l = 0; l < CURSORHEIGHT; l++) {
for (w = 0; w < CURSORWIDTH >> 5; w++)
memwl(HOSTDATA, *pXCursorBits++);
for (w = 0; w < CURSORWIDTH >> 5; w++)
memwl(HOSTDATA, *pXCursorBits++);
}
while (!LgREADY())
;
}
static void
LgFindCursorTile(ScrnInfoPtr pScrn, int *x, int *y, int *width, int *height,
CARD32 *curAddr)
{
CirPtr pCir = CIRPTR(pScrn);
LgPtr pLg = LGPTR(pCir);
int videoRam = pScrn->videoRam;
int tileHeight = LgLineData[pLg->lineDataIndex].width?8:16;
int tileWidth = LgLineData[pLg->lineDataIndex].width?256:128;
int tilesPerLine = LgLineData[pLg->lineDataIndex].tilesPerLine;
int filledOutTileLines, leftoverMem;
int yTile, xTile;
int tileNumber;
filledOutTileLines = videoRam / (tilesPerLine * 2);
leftoverMem = videoRam - filledOutTileLines*tilesPerLine*2;
if (leftoverMem > 0) {
yTile = filledOutTileLines;
} else {
yTile = filledOutTileLines - 1;
}
xTile = 0;
if (x)
*x = xTile * tileWidth;
if (y)
*y = yTile * tileHeight;
if (width)
*width = tileWidth;
if (height)
*height = tileHeight / 2;
if (curAddr) {
unsigned int nIL;
nIL = pLg->memInterleave==0x00? 1 : (pLg->memInterleave==0x40 ? 2 : 4);
if (PCI_CHIP_GD5465 == pCir->Chipset) {
unsigned long page, bank;
unsigned int nX, nY;
nX = xTile * tileWidth;
nY = yTile * tileHeight;
page = (nY / (tileHeight * nIL)) * tilesPerLine + nX / tileWidth;
bank = (nX/tileWidth + nY/tileHeight) % nIL + page/(512*nIL);
page = page & 0x1FF;
*curAddr = bank*1024*1024L + page*2048 + (nY%tileHeight)*tileWidth;
} else {
tileNumber = (tilesPerLine*nIL) * (yTile/nIL) + yTile % nIL;
*curAddr = tileNumber * 2048;
}
}
}
void LgHideCursor(ScrnInfoPtr pScrn)
{
const CirPtr pCir = CIRPTR(pScrn);
#ifdef LG_CURSOR_DEBUG
ErrorF("LgHideCursor\n");
#endif
memww(CURSOR_CONTROL, (memrw(CURSOR_CONTROL) & 0xFFFE));
}
void LgShowCursor(ScrnInfoPtr pScrn)
{
const CirPtr pCir = CIRPTR(pScrn);
const LgPtr pLg = LGPTR(pCir);
#ifdef LG_CURSOR_DEBUG
ErrorF("LgShowCursor\n");
#endif
memww(CURSOR_CONTROL,(memrw(CURSOR_CONTROL) | (1<<0)));
memww(CURSOR_ADDR,(pLg->HWCursorAddr & 0x7FFC));
}
static Bool LgUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
#ifdef LG_CURSOR_DEBUG
ErrorF("LgUseHWCursor\n");
#endif
if(pScrn->bitsPerPixel < 8)
return FALSE;
return TRUE;
}
Bool LgHWCursorInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
CirPtr pCir = CIRPTR(pScrn);
xf86CursorInfoPtr infoPtr;
#ifdef LG_CURSOR_DEBUG
ErrorF("LgHWCursorInit\n");
#endif
infoPtr = xf86CreateCursorInfoRec();
if(!infoPtr) return FALSE;
pCir->CursorInfoRec = infoPtr;
LgFindCursorTile(pScrn, &pCir->chip.lg->HWCursorImageX, &pCir->chip.lg->HWCursorImageY,
&pCir->chip.lg->HWCursorTileWidth, &pCir->chip.lg->HWCursorTileHeight,
&pCir->chip.lg->HWCursorAddr);
pCir->chip.lg->HWCursorAddr = (pCir->chip.lg->HWCursorAddr >> 8) & 0x7FFC;
pCir->CursorIsSkewed = FALSE;
infoPtr->MaxWidth = CURSORWIDTH;
infoPtr->MaxHeight = CURSORHEIGHT;
infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
| HARDWARE_CURSOR_AND_SOURCE_WITH_MASK
| HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64;
infoPtr->SetCursorColors = LgSetCursorColors;
infoPtr->SetCursorPosition = LgSetCursorPosition;
infoPtr->LoadCursorImage = LgLoadCursorImage;
infoPtr->HideCursor = LgHideCursor;
infoPtr->ShowCursor = LgShowCursor;
infoPtr->UseHWCursor = LgUseHWCursor;
#ifdef LG_CURSOR_DEBUG
ErrorF("LgHWCursorInit before xf86InitCursor\n");
#endif
return(xf86InitCursor(pScreen, infoPtr));
}