#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "compiler.h"
#include "xf86PciInfo.h"
#include "xf86fbman.h"
#include "miline.h"
#include "neo.h"
#include "neo_reg.h"
#include "neo_macros.h"
static unsigned int neo2090Rop[16] = {
0x000000,
0x080000,
0x040000,
0x0c0000,
0x020000,
0x0a0000,
0x060000,
0x0e0000,
0x010000,
0x090000,
0x050000,
0x0d0000,
0x030000,
0x0b0000,
0x070000,
0x0f0000
};
static void Neo2090Sync(ScrnInfoPtr pScrn);
static void Neo2090SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
int ydir, int rop,
unsigned int planemask,
int trans_color);
static void Neo2090SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX,
int srcY, int dstX, int dstY,
int w, int h);
static void Neo2090SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
unsigned int planemask);
static void Neo2090SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
int w, int h);
static void Neo2093SetupForScanlineCPUToScreenColorExpandFill(
ScrnInfoPtr pScrn,
int fg, int bg,
int rop,
unsigned int planemask);
static void Neo2093SubsequentScanlineCPUToScreenColorExpandFill(
ScrnInfoPtr pScrn,
int x, int y,
int w, int h,
int skipleft);
static void Neo2093SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
Bool
Neo2090AccelInit(ScreenPtr pScreen)
{
XAAInfoRecPtr infoPtr;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
NEOPtr nPtr = NEOPTR(pScrn);
NEOACLPtr nAcl = NEOACLPTR(pScrn);
nPtr->AccelInfoRec = infoPtr = XAACreateInfoRec();
if(!infoPtr) return FALSE;
infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS;
if(nAcl->cacheEnd > nAcl->cacheStart) infoPtr->Flags |= PIXMAP_CACHE;
#if 0
infoPtr->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES;
#endif
infoPtr->Sync = Neo2090Sync;
infoPtr->ScreenToScreenCopyFlags = (NO_TRANSPARENCY | NO_PLANEMASK);
infoPtr->SetupForScreenToScreenCopy =
Neo2090SetupForScreenToScreenCopy;
infoPtr->SubsequentScreenToScreenCopy =
Neo2090SubsequentScreenToScreenCopy;
infoPtr->SolidFillFlags = NO_PLANEMASK;
infoPtr->SetupForSolidFill =
Neo2090SetupForSolidFillRect;
infoPtr->SubsequentSolidFillRect =
Neo2090SubsequentSolidFillRect;
if (nPtr->NeoChipset == PCI_CHIP_NM2093 && !nPtr->strangeLockups) {
infoPtr->ScanlineColorExpandBuffers =
(unsigned char **)xnfalloc(sizeof(char*));
infoPtr->ScanlineColorExpandBuffers[0] =
(unsigned char *)(nPtr->NeoMMIOBase + 0x100000);
infoPtr->NumScanlineColorExpandBuffers = 1;
infoPtr->ScanlineCPUToScreenColorExpandFillFlags = ( NO_PLANEMASK |
SCANLINE_PAD_DWORD |
CPU_TRANSFER_PAD_DWORD |
BIT_ORDER_IN_BYTE_MSBFIRST );
infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
Neo2093SetupForScanlineCPUToScreenColorExpandFill;
infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
Neo2093SubsequentScanlineCPUToScreenColorExpandFill;
infoPtr->SubsequentColorExpandScanline =
Neo2093SubsequentColorExpandScanline;
}
nAcl->ColorShiftAmt = 0;
switch (pScrn->bitsPerPixel) {
case 8:
nAcl->BltCntlFlags = NEO_BC1_DEPTH8;
nAcl->ColorShiftAmt = 8;
break;
case 15:
case 16:
nAcl->BltCntlFlags = NEO_BC1_DEPTH16;
nAcl->ColorShiftAmt = 0;
break;
case 24:
default:
return FALSE;
}
switch (pScrn->displayWidth) {
case 640:
nAcl->BltCntlFlags |= NEO_BC1_X_640;
break;
case 800:
nAcl->BltCntlFlags |= NEO_BC1_X_800;
break;
case 1024:
nAcl->BltCntlFlags |= NEO_BC1_X_1024;
break;
default:
return FALSE;
}
nAcl->BltCntlFlags |= NEO_BC3_FIFO_EN;
return(XAAInit(pScreen, infoPtr));
}
static void
Neo2090Sync(ScrnInfoPtr pScrn)
{
NEOPtr nPtr = NEOPTR(pScrn);
WAIT_ENGINE_IDLE();
}
static void
Neo2090SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
int rop,
unsigned int planemask,
int trans_color)
{
NEOPtr nPtr = NEOPTR(pScrn);
NEOACLPtr nAcl = NEOACLPTR(pScrn);
nAcl->tmpBltCntlFlags = (nAcl->BltCntlFlags |
NEO_BC3_SKIP_MAPPING |
NEO_BC3_DST_XY_ADDR |
NEO_BC3_SRC_XY_ADDR | neo2090Rop[rop]);
WAIT_FIFO(2);
OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
}
static void
Neo2090SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
int srcX, int srcY,
int dstX, int dstY,
int w, int h)
{
NEOPtr nPtr = NEOPTR(pScrn);
NEOACLPtr nAcl = NEOACLPTR(pScrn);
if ((dstY < srcY) || ((dstY == srcY) && (dstX < srcX))) {
WAIT_FIFO(4);
OUTREG(NEOREG_BLTCNTL, nAcl->tmpBltCntlFlags);
OUTREG(NEOREG_SRCSTARTOFF, (srcY<<16) | (srcX & 0xffff));
OUTREG(NEOREG_DSTSTARTOFF, (dstY<<16) | (dstX & 0xffff));
OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
}
else {
WAIT_FIFO(4);
OUTREG(NEOREG_BLTCNTL, (nAcl->tmpBltCntlFlags | NEO_BC0_X_DEC
| NEO_BC0_DST_Y_DEC
| NEO_BC0_SRC_Y_DEC));
OUTREG(NEOREG_SRCSTARTOFF, ((srcY+h-1)<<16) | ((srcX+w-1) & 0xffff));
OUTREG(NEOREG_DSTSTARTOFF, ((dstY+h-1)<<16) | ((dstX+w-1) & 0xffff));
OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
}
}
static void
Neo2090SetupForSolidFillRect(ScrnInfoPtr pScrn, int color, int rop,
unsigned int planemask)
{
NEOPtr nPtr = NEOPTR(pScrn);
NEOACLPtr nAcl = NEOACLPTR(pScrn);
WAIT_FIFO(2);
OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags |
NEO_BC0_SRC_IS_FG |
NEO_BC3_SKIP_MAPPING |
NEO_BC3_DST_XY_ADDR |
NEO_BC3_SRC_XY_ADDR | neo2090Rop[rop]);
OUTREG(NEOREG_FGCOLOR, color |= (color << nAcl->ColorShiftAmt));
}
static void
Neo2090SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
{
NEOPtr nPtr = NEOPTR(pScrn);
WAIT_FIFO(2);
OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
OUTREG(NEOREG_XYEXT, (h<<16) | (w & 0xffff));
}
static void
Neo2093SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
int fg, int bg,
int rop,
unsigned int planemask)
{
NEOPtr nPtr = NEOPTR(pScrn);
NEOACLPtr nAcl = NEOACLPTR(pScrn);
if (bg == -1) {
WAIT_FIFO(2);
OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags |
NEO_BC0_SYS_TO_VID |
NEO_BC0_SRC_MONO |
NEO_BC0_SRC_TRANS |
NEO_BC3_SKIP_MAPPING |
NEO_BC3_DST_XY_ADDR | neo2090Rop[rop]);
OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt));
}
else {
WAIT_FIFO(3);
OUTREG(NEOREG_BLTCNTL, nAcl->BltCntlFlags |
NEO_BC0_SYS_TO_VID |
NEO_BC0_SRC_MONO |
NEO_BC3_SKIP_MAPPING |
NEO_BC3_DST_XY_ADDR | neo2090Rop[rop]);
OUTREG(NEOREG_FGCOLOR, fg |= (fg << nAcl->ColorShiftAmt));
OUTREG(NEOREG_BGCOLOR, bg |= (bg << nAcl->ColorShiftAmt));
}
}
static void
Neo2093SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
int x, int y,
int w, int h,
int skipleft)
{
NEOPtr nPtr = NEOPTR(pScrn);
NEOACLPtr nAcl = NEOACLPTR(pScrn);
nAcl->CPUToScreenColorExpandFill_x = x;
nAcl->CPUToScreenColorExpandFill_y = y;
nAcl->CPUToScreenColorExpandFill_w = w;
nAcl->CPUToScreenColorExpandFill_h = h;
nAcl->CPUToScreenColorExpandFill_skipleft = skipleft;
WAIT_FIFO(4);
OUTREG(NEOREG_SRCBITOFF, skipleft);
OUTREG(NEOREG_SRCSTARTOFF, 0);
OUTREG(NEOREG_DSTSTARTOFF, (y<<16) | (x & 0xffff));
OUTREG(NEOREG_XYEXT, (1<<16) | (w & 0xffff));
}
static void
Neo2093SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
{
NEOPtr nPtr = NEOPTR(pScrn);
NEOACLPtr nAcl = NEOACLPTR(pScrn);
if (!(--nAcl->CPUToScreenColorExpandFill_h))
return;
WAIT_FIFO(4);
OUTREG(NEOREG_SRCBITOFF, nAcl->CPUToScreenColorExpandFill_skipleft);
OUTREG(NEOREG_SRCSTARTOFF, 0);
OUTREG(NEOREG_DSTSTARTOFF, ((++nAcl->CPUToScreenColorExpandFill_y)<<16)
| (nAcl->CPUToScreenColorExpandFill_x & 0xffff));
OUTREG(NEOREG_XYEXT, (1<<16)
| (nAcl->CPUToScreenColorExpandFill_w & 0xffff));
}