#include "ati.h"
#include "atichip.h"
#include "atimach64accel.h"
#include "atimach64io.h"
#include "atipriv.h"
#include "atiregs.h"
#include "miline.h"
#define TestRegisterCaching(_Register) \
if (RegisterIsCached(_Register) && \
(CacheSlot(_Register) != inm(_Register))) \
{ \
UncacheRegister(_Register); \
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, \
#_Register " MMIO write cache disabled!\n"); \
}
static CARD8 ATIMach64ALU[16] =
{
MIX_0,
MIX_AND,
MIX_SRC_AND_NOT_DST,
MIX_SRC,
MIX_NOT_SRC_AND_DST,
MIX_DST,
MIX_XOR,
MIX_OR,
MIX_NOR,
MIX_XNOR,
MIX_NOT_DST,
MIX_SRC_OR_NOT_DST,
MIX_NOT_SRC,
MIX_NOT_SRC_OR_DST,
MIX_NAND,
MIX_1
};
static void
ATIMach64ValidateClip
(
ATIPtr pATI,
int sc_left,
int sc_right,
int sc_top,
int sc_bottom
)
{
if ((sc_left < (int)pATI->sc_left) || (sc_right > (int)pATI->sc_right))
{
outf(SC_LEFT_RIGHT, pATI->sc_left_right);
pATI->sc_left = pATI->NewHW.sc_left;
pATI->sc_right = pATI->NewHW.sc_right;
}
if ((sc_top < (int)pATI->sc_top) || (sc_bottom > (int)pATI->sc_bottom))
{
outf(SC_TOP_BOTTOM, pATI->sc_top_bottom);
pATI->sc_top = pATI->NewHW.sc_top;
pATI->sc_bottom = pATI->NewHW.sc_bottom;
}
}
void
ATIMach64Sync
(
ScrnInfoPtr pScreenInfo
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
ATIMach64WaitForIdle(pATI);
if (pATI->pXAAInfo)
pATI->pXAAInfo->NeedToSync = FALSE;
if (pATI->OptionMMIOCache && pATI->OptionTestMMIOCache)
{
TestRegisterCaching(SRC_CNTL);
TestRegisterCaching(HOST_CNTL);
TestRegisterCaching(PAT_REG0);
TestRegisterCaching(PAT_REG1);
TestRegisterCaching(PAT_CNTL);
if (RegisterIsCached(SC_LEFT_RIGHT) &&
(CacheSlot(SC_LEFT_RIGHT) !=
(SetWord(inm(SC_RIGHT), 1) | SetWord(inm(SC_LEFT), 0))))
{
UncacheRegister(SC_LEFT_RIGHT);
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"SC_LEFT_RIGHT write cache disabled!\n");
}
if (RegisterIsCached(SC_TOP_BOTTOM) &&
(CacheSlot(SC_TOP_BOTTOM) !=
(SetWord(inm(SC_BOTTOM), 1) | SetWord(inm(SC_TOP), 0))))
{
UncacheRegister(SC_TOP_BOTTOM);
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"SC_TOP_BOTTOM write cache disabled!\n");
}
TestRegisterCaching(DP_BKGD_CLR);
TestRegisterCaching(DP_FRGD_CLR);
TestRegisterCaching(DP_WRITE_MASK);
TestRegisterCaching(DP_MIX);
TestRegisterCaching(CLR_CMP_CLR);
TestRegisterCaching(CLR_CMP_MSK);
TestRegisterCaching(CLR_CMP_CNTL);
if (pATI->Block1Base)
{
TestRegisterCaching(OVERLAY_Y_X_START);
TestRegisterCaching(OVERLAY_Y_X_END);
TestRegisterCaching(OVERLAY_GRAPHICS_KEY_CLR);
TestRegisterCaching(OVERLAY_GRAPHICS_KEY_MSK);
TestRegisterCaching(OVERLAY_KEY_CNTL);
TestRegisterCaching(OVERLAY_SCALE_INC);
TestRegisterCaching(OVERLAY_SCALE_CNTL);
TestRegisterCaching(SCALER_HEIGHT_WIDTH);
TestRegisterCaching(SCALER_TEST);
TestRegisterCaching(VIDEO_FORMAT);
if (pATI->Chip < ATI_CHIP_264VTB)
{
TestRegisterCaching(BUF0_OFFSET);
TestRegisterCaching(BUF0_PITCH);
TestRegisterCaching(BUF1_OFFSET);
TestRegisterCaching(BUF1_PITCH);
}
else
{
TestRegisterCaching(SCALER_BUF0_OFFSET);
TestRegisterCaching(SCALER_BUF1_OFFSET);
TestRegisterCaching(SCALER_BUF_PITCH);
TestRegisterCaching(OVERLAY_EXCLUSIVE_HORZ);
TestRegisterCaching(OVERLAY_EXCLUSIVE_VERT);
if (pATI->Chip >= ATI_CHIP_264GTPRO)
{
TestRegisterCaching(SCALER_COLOUR_CNTL);
TestRegisterCaching(SCALER_H_COEFF0);
TestRegisterCaching(SCALER_H_COEFF1);
TestRegisterCaching(SCALER_H_COEFF2);
TestRegisterCaching(SCALER_H_COEFF3);
TestRegisterCaching(SCALER_H_COEFF4);
TestRegisterCaching(SCALER_BUF0_OFFSET_U);
TestRegisterCaching(SCALER_BUF0_OFFSET_V);
TestRegisterCaching(SCALER_BUF1_OFFSET_U);
TestRegisterCaching(SCALER_BUF1_OFFSET_V);
}
}
}
}
pATI = *(volatile ATIPtr *)pATI->pMemory;
}
static void
ATIMach64SetupForScreenToScreenCopy
(
ScrnInfoPtr pScreenInfo,
int xdir,
int ydir,
int rop,
unsigned int planemask,
int TransparencyColour
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
ATIMach64WaitForFIFO(pATI, 3);
outf(DP_WRITE_MASK, planemask);
outf(DP_SRC, DP_MONO_SRC_ALLONES |
SetBits(SRC_BLIT, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
#ifdef AVOID_DGA
if (TransparencyColour == -1)
#else
if (!pATI->XAAForceTransBlit && (TransparencyColour == -1))
#endif
{
outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
}
else
{
ATIMach64WaitForFIFO(pATI, 2);
outf(CLR_CMP_CLR, TransparencyColour);
outf(CLR_CMP_CNTL, CLR_CMP_FN_EQUAL | CLR_CMP_SRC_2D);
}
pATI->dst_cntl = 0;
if (ydir > 0)
pATI->dst_cntl |= DST_Y_DIR;
if (xdir > 0)
pATI->dst_cntl |= DST_X_DIR;
if (pATI->XModifier == 1)
outf(DST_CNTL, pATI->dst_cntl);
else
pATI->dst_cntl |= DST_24_ROT_EN;
}
static void
ATIMach64SubsequentScreenToScreenCopy
(
ScrnInfoPtr pScreenInfo,
int xSrc,
int ySrc,
int xDst,
int yDst,
int w,
int h
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
xSrc *= pATI->XModifier;
xDst *= pATI->XModifier;
w *= pATI->XModifier;
ATIMach64ValidateClip(pATI, xDst, xDst + w - 1, yDst, yDst + h - 1);
if (!(pATI->dst_cntl & DST_X_DIR))
{
xSrc += w - 1;
xDst += w - 1;
}
if (!(pATI->dst_cntl & DST_Y_DIR))
{
ySrc += h - 1;
yDst += h - 1;
}
if (pATI->XModifier != 1)
outf(DST_CNTL, pATI->dst_cntl | SetBits((xDst / 4) % 6, DST_24_ROT));
ATIMach64WaitForFIFO(pATI, 4);
outf(SRC_Y_X, SetWord(xSrc, 1) | SetWord(ySrc, 0));
outf(SRC_WIDTH1, w);
outf(DST_Y_X, SetWord(xDst, 1) | SetWord(yDst, 0));
outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
}
static void
ATIMach64SetupForSolidFill
(
ScrnInfoPtr pScreenInfo,
int colour,
int rop,
unsigned int planemask
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
ATIMach64WaitForFIFO(pATI, 5);
outf(DP_WRITE_MASK, planemask);
outf(DP_SRC, DP_MONO_SRC_ALLONES |
SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
outf(DP_FRGD_CLR, colour);
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
if (pATI->XModifier == 1)
outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
}
static void
ATIMach64SubsequentSolidFillRect
(
ScrnInfoPtr pScreenInfo,
int x,
int y,
int w,
int h
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
if (pATI->XModifier != 1)
{
x *= pATI->XModifier;
w *= pATI->XModifier;
outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
(DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
}
ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1);
ATIMach64WaitForFIFO(pATI, 2);
outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
}
static void
ATIMach64SetupForSolidLine
(
ScrnInfoPtr pScreenInfo,
int colour,
int rop,
unsigned int planemask
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
ATIMach64WaitForFIFO(pATI, 5);
outf(DP_WRITE_MASK, planemask);
outf(DP_SRC, DP_MONO_SRC_ALLONES |
SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
outf(DP_FRGD_CLR, colour);
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
ATIMach64ValidateClip(pATI, pATI->NewHW.sc_left, pATI->NewHW.sc_right,
pATI->NewHW.sc_top, pATI->NewHW.sc_bottom);
}
static void
ATIMach64SubsequentSolidHorVertLine
(
ScrnInfoPtr pScreenInfo,
int x,
int y,
int len,
int dir
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
ATIMach64WaitForFIFO(pATI, 3);
outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
if (dir == DEGREES_0)
outf(DST_HEIGHT_WIDTH, SetWord(len, 1) | SetWord(1, 0));
else
outf(DST_HEIGHT_WIDTH, SetWord(1, 1) | SetWord(len, 0));
}
static void
ATIMach64SubsequentSolidBresenhamLine
(
ScrnInfoPtr pScreenInfo,
int x,
int y,
int major,
int minor,
int err,
int len,
int octant
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
CARD32 dst_cntl = DST_LAST_PEL;
if (octant & YMAJOR)
dst_cntl |= DST_Y_MAJOR;
if (!(octant & XDECREASING))
dst_cntl |= DST_X_DIR;
if (!(octant & YDECREASING))
dst_cntl |= DST_Y_DIR;
ATIMach64WaitForFIFO(pATI, 6);
outf(DST_CNTL, dst_cntl);
outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
outf(DST_BRES_ERR, minor + err);
outf(DST_BRES_INC, minor);
outf(DST_BRES_DEC, minor - major);
outf(DST_BRES_LNTH, len);
}
static void
ATIMach64SetupForMono8x8PatternFill
(
ScrnInfoPtr pScreenInfo,
int patx,
int paty,
int fg,
int bg,
int rop,
unsigned int planemask
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
ATIMach64WaitForFIFO(pATI, 3);
outf(DP_WRITE_MASK, planemask);
outf(DP_SRC, DP_MONO_SRC_PATTERN |
SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
outf(DP_FRGD_CLR, fg);
if (bg == -1)
{
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
SetBits(MIX_DST, DP_BKGD_MIX));
}
else
{
ATIMach64WaitForFIFO(pATI, 2);
outf(DP_BKGD_CLR, bg);
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
SetBits(ATIMach64ALU[rop], DP_BKGD_MIX));
}
ATIMach64WaitForFIFO(pATI, 4);
outf(PAT_REG0, patx);
outf(PAT_REG1, paty);
outf(PAT_CNTL, PAT_MONO_EN);
outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
if (pATI->XModifier == 1)
outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
}
static void
ATIMach64SubsequentMono8x8PatternFillRect
(
ScrnInfoPtr pScreenInfo,
int patx,
int paty,
int x,
int y,
int w,
int h
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
if (pATI->XModifier != 1)
{
x *= pATI->XModifier;
w *= pATI->XModifier;
outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
(DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
}
ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1);
ATIMach64WaitForFIFO(pATI, 2);
outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
}
static void
ATIMach64SetupForScanlineCPUToScreenColorExpandFill
(
ScrnInfoPtr pScreenInfo,
int fg,
int bg,
int rop,
unsigned int planemask
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
ATIMach64WaitForFIFO(pATI, 3);
outf(DP_WRITE_MASK, planemask);
outf(DP_SRC, DP_MONO_SRC_HOST |
SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
outf(DP_FRGD_CLR, fg);
if (bg == -1)
{
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
SetBits(MIX_DST, DP_BKGD_MIX));
}
else
{
ATIMach64WaitForFIFO(pATI, 2);
outf(DP_BKGD_CLR, bg);
outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
SetBits(ATIMach64ALU[rop], DP_BKGD_MIX));
}
outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
if (pATI->XModifier == 1)
outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
}
static void
ATIMach64SubsequentScanlineCPUToScreenColorExpandFill
(
ScrnInfoPtr pScreenInfo,
int x,
int y,
int w,
int h,
int skipleft
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
if (pATI->XModifier != 1)
{
x *= pATI->XModifier;
w *= pATI->XModifier;
skipleft *= pATI->XModifier;
outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
(DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
}
pATI->ExpansionBitmapWidth = (w + 31) / 32;
ATIMach64WaitForFIFO(pATI, 3);
pATI->sc_left = x + skipleft;
pATI->sc_right = x + w - 1;
outf(SC_LEFT_RIGHT,
SetWord(pATI->sc_right, 1) | SetWord(pATI->sc_left, 0));
outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
outf(DST_HEIGHT_WIDTH,
SetWord(pATI->ExpansionBitmapWidth * 32, 1) | SetWord(h, 0));
}
static void
ATIMach64SubsequentColorExpandScanline
(
ScrnInfoPtr pScreenInfo,
int iBuffer
)
{
ATIPtr pATI = ATIPTR(pScreenInfo);
CARD32 *pBitmapData = pATI->ExpansionBitmapScanlinePtr[iBuffer];
int w = pATI->ExpansionBitmapWidth;
int nDWord;
while (w > 0)
{
nDWord = w;
if (nDWord > pATI->nHostFIFOEntries)
nDWord = pATI->nHostFIFOEntries;
ATIMach64WaitForFIFO(pATI, nDWord);
# if defined(ATIMove32)
{
ATIMove32(pATI->pHOST_DATA, pBitmapData, nDWord);
}
# else
{
volatile CARD32 *pDst;
CARD32 *pSrc;
unsigned int iDWord;
iDWord = 16 - nDWord;
pDst = (volatile CARD32 *)pATI->pHOST_DATA - iDWord;
pSrc = pBitmapData - iDWord;
switch (iDWord)
{
case 0: MMIO_MOVE32(pDst + 0, 0, *(pSrc + 0));
case 1: MMIO_MOVE32(pDst + 1, 0, *(pSrc + 1));
case 2: MMIO_MOVE32(pDst + 2, 0, *(pSrc + 2));
case 3: MMIO_MOVE32(pDst + 3, 0, *(pSrc + 3));
case 4: MMIO_MOVE32(pDst + 4, 0, *(pSrc + 4));
case 5: MMIO_MOVE32(pDst + 5, 0, *(pSrc + 5));
case 6: MMIO_MOVE32(pDst + 6, 0, *(pSrc + 6));
case 7: MMIO_MOVE32(pDst + 7, 0, *(pSrc + 7));
case 8: MMIO_MOVE32(pDst + 8, 0, *(pSrc + 8));
case 9: MMIO_MOVE32(pDst + 9, 0, *(pSrc + 9));
case 10: MMIO_MOVE32(pDst + 10, 0, *(pSrc + 10));
case 11: MMIO_MOVE32(pDst + 11, 0, *(pSrc + 11));
case 12: MMIO_MOVE32(pDst + 12, 0, *(pSrc + 12));
case 13: MMIO_MOVE32(pDst + 13, 0, *(pSrc + 13));
case 14: MMIO_MOVE32(pDst + 14, 0, *(pSrc + 14));
case 15: MMIO_MOVE32(pDst + 15, 0, *(pSrc + 15));
default:
break;
}
}
# endif
pBitmapData += nDWord;
w -= nDWord;
pATI->nAvailableFIFOEntries -= nDWord;
}
pATI->EngineIsBusy = TRUE;
}
int
ATIMach64AccelInit
(
ATIPtr pATI,
XAAInfoRecPtr pXAAInfo
)
{
if (pATI->XModifier == 1)
{
pXAAInfo->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
#ifndef AVOID_CPIO
if (!pATI->BankInfo.BankSize)
#endif
{
pXAAInfo->Flags |= LINEAR_FRAMEBUFFER;
}
}
pXAAInfo->Sync = ATIMach64Sync;
pXAAInfo->SetupForScreenToScreenCopy = ATIMach64SetupForScreenToScreenCopy;
pXAAInfo->SubsequentScreenToScreenCopy =
ATIMach64SubsequentScreenToScreenCopy;
pXAAInfo->SetupForSolidFill = ATIMach64SetupForSolidFill;
pXAAInfo->SubsequentSolidFillRect = ATIMach64SubsequentSolidFillRect;
pXAAInfo->Mono8x8PatternFillFlags =
#if X_BYTE_ORDER != X_LITTLE_ENDIAN
BIT_ORDER_IN_BYTE_MSBFIRST |
#endif
HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_SCREEN_ORIGIN;
pXAAInfo->SetupForMono8x8PatternFill = ATIMach64SetupForMono8x8PatternFill;
pXAAInfo->SubsequentMono8x8PatternFillRect =
ATIMach64SubsequentMono8x8PatternFillRect;
pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags =
LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X |
CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD;
if (pATI->XModifier != 1)
pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags |= TRIPLE_BITS_24BPP;
pXAAInfo->NumScanlineColorExpandBuffers = 1;
pATI->ExpansionBitmapWidth =
((pATI->displayWidth * pATI->XModifier) + 31) & ~31U;
pATI->ExpansionBitmapScanlinePtr[1] =
(CARD32 *)xnfalloc((pATI->ExpansionBitmapWidth >> 3) + 63);
pATI->ExpansionBitmapScanlinePtr[0] =
(pointer)(((unsigned long)pATI->ExpansionBitmapScanlinePtr[1] + 63) &
~63UL);
pXAAInfo->ScanlineColorExpandBuffers =
(CARD8 **)pATI->ExpansionBitmapScanlinePtr;
pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill =
ATIMach64SetupForScanlineCPUToScreenColorExpandFill;
pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill =
ATIMach64SubsequentScanlineCPUToScreenColorExpandFill;
pXAAInfo->SubsequentColorExpandScanline =
ATIMach64SubsequentColorExpandScanline;
if (pATI->XModifier != 1)
return ATIMach64MaxY;
pXAAInfo->SetupForSolidLine = ATIMach64SetupForSolidLine;
pXAAInfo->SubsequentSolidHorVertLine = ATIMach64SubsequentSolidHorVertLine;
pXAAInfo->SubsequentSolidBresenhamLine =
ATIMach64SubsequentSolidBresenhamLine;
return ATIMach64MaxY;
}