Haiku ATI video driver adapted from the X.org ATI driver.
Copyright 1992,1993,1994,1995,1996,1997 by Kevin E. Martin, Chapel Hill, North Carolina.
Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
Copyright 2009 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac 2009
*/
#include "accelerant.h"
#include "mach64.h"
void
Mach64_EngineReset()
{
uint32 genTestCntl = INREG(GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE;
OUTREG(GEN_TEST_CNTL, genTestCntl);
OUTREG(GEN_TEST_CNTL, genTestCntl | GUI_ENGINE_ENABLE);
OUTREG(BUS_CNTL, INREG(BUS_CNTL) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK);
}
void
Mach64_EngineInit(const DisplayModeEx& mode)
{
Mach64_EngineReset();
gInfo.WaitForIdle();
OUTREG(MEM_VGA_WP_SEL, 0x00010000);
OUTREG(MEM_VGA_RP_SEL, 0x00010000);
uint32 dpPixWidth = 0;
uint32 dpChainMask = 0;
switch (mode.bitsPerPixel) {
case 8:
dpPixWidth = HOST_8BPP | SRC_8BPP | DST_8BPP;
dpChainMask = DP_CHAIN_8BPP;
break;
case 15:
dpPixWidth = HOST_15BPP | SRC_15BPP | DST_15BPP;
dpChainMask = DP_CHAIN_15BPP;
break;
case 16:
dpPixWidth = HOST_16BPP | SRC_16BPP | DST_16BPP;
dpChainMask = DP_CHAIN_16BPP;
break;
case 32:
dpPixWidth = HOST_32BPP | SRC_32BPP | DST_32BPP;
dpChainMask = DP_CHAIN_32BPP;
break;
}
dpPixWidth |= BYTE_ORDER_LSB_TO_MSB;
gInfo.WaitForFifo(3);
OUTREG(DP_PIX_WIDTH, dpPixWidth);
OUTREG(DP_CHAIN_MASK, dpChainMask);
OUTREG(CONTEXT_MASK, 0xffffffff);
gInfo.WaitForFifo(7);
OUTREG(DST_OFF_PITCH, (mode.timing.h_display / 8) << 22);
OUTREG(DST_Y_X, 0);
OUTREG(DST_HEIGHT, 0);
OUTREG(DST_BRES_ERR, 0);
OUTREG(DST_BRES_INC, 0);
OUTREG(DST_BRES_DEC, 0);
OUTREG(DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM | DST_LAST_PEL);
gInfo.WaitForFifo(6);
OUTREG(SRC_OFF_PITCH, (mode.timing.h_display / 8) << 22);
OUTREG(SRC_Y_X, 0);
OUTREG(SRC_HEIGHT1_WIDTH1, 0x10001);
OUTREG(SRC_Y_X_START, 0);
OUTREG(SRC_HEIGHT2_WIDTH2, 0x10001);
OUTREG(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT);
gInfo.WaitForFifo(7);
OUTREGM(HOST_CNTL, 0, HOST_BYTE_ALIGN);
OUTREG(PAT_REG0, 0);
OUTREG(PAT_REG1, 0);
OUTREG(PAT_CNTL, 0);
OUTREG(SC_LEFT_RIGHT, ((mode.timing.h_display << 16) | 0 ));
OUTREG(SC_TOP_BOTTOM, ((mode.timing.v_display << 16) | 0 ));
gInfo.WaitForFifo(9);
OUTREG(DP_BKGD_CLR, 0);
OUTREG(DP_FRGD_CLR, 0xffffffff);
OUTREG(DP_WRITE_MASK, 0xffffffff);
OUTREG(DP_MIX, (MIX_SRC << 16) | MIX_DST);
OUTREG(DP_SRC, FRGD_SRC_FRGD_CLR);
OUTREG(CLR_CMP_CLR, 0);
OUTREG(CLR_CMP_MASK, 0xffffffff);
OUTREG(CLR_CMP_CNTL, 0);
gInfo.WaitForIdle();
}
void
Mach64_FillRectangle(engine_token *et, uint32 color, fill_rect_params *pList, uint32 count)
{
(void)et;
gInfo.WaitForFifo(4);
OUTREG(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE);
OUTREG(DP_FRGD_CLR, color);
OUTREG(DP_MIX, (MIX_SRC << 16) | MIX_DST);
OUTREG(DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM | DST_LAST_PEL);
while (count--) {
int x = pList->left;
int y = pList->top;
int w = pList->right - x + 1;
int h = pList->bottom - y + 1;
gInfo.WaitForFifo(2);
OUTREG(DST_Y_X, (x << 16) | y);
OUTREG(DST_HEIGHT_WIDTH, (w << 16) | h);
pList++;
}
}
void
Mach64_FillSpan(engine_token *et, uint32 color, uint16 *pList, uint32 count)
{
(void)et;
gInfo.WaitForFifo(4);
OUTREG(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE);
OUTREG(DP_FRGD_CLR, color);
OUTREG(DP_MIX, (MIX_SRC << 16) | MIX_DST);
OUTREG(DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM | DST_LAST_PEL);
while (count--) {
int y = *pList++;
int x = *pList++;
int w = *pList++ - x + 1;
if (w <= 0)
continue;
gInfo.WaitForFifo(2);
OUTREG(DST_Y_X, (x << 16) | y);
OUTREG(DST_HEIGHT_WIDTH, (w << 16) | 1);
}
}
void
Mach64_InvertRectangle(engine_token *et, fill_rect_params *pList, uint32 count)
{
(void)et;
gInfo.WaitForFifo(3);
OUTREG(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE);
OUTREG(DP_MIX, MIX_NOT_DST << 16);
OUTREG(DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM | DST_LAST_PEL);
while (count--) {
int x = pList->left;
int y = pList->top;
int w = pList->right - x + 1;
int h = pList->bottom - y + 1;
gInfo.WaitForFifo(2);
OUTREG(DST_Y_X, (x << 16) | y);
OUTREG(DST_HEIGHT_WIDTH, (w << 16) | h);
pList++;
}
}
void
Mach64_ScreenToScreenBlit(engine_token *et, blit_params *pList, uint32 count)
{
(void)et;
gInfo.WaitForFifo(2);
OUTREG(DP_SRC, FRGD_SRC_BLIT);
OUTREG(DP_MIX, MIX_SRC << 16);
while (count--) {
int cmd = DST_LAST_PEL;
int src_x = pList->src_left;
int src_y = pList->src_top;
int dest_x = pList->dest_left;
int dest_y = pList->dest_top;
int width = pList->width;
int height = pList->height;
if (dest_x <= src_x) {
cmd |= DST_X_LEFT_TO_RIGHT;
} else {
src_x += width;
dest_x += width;
}
if (dest_y <= src_y) {
cmd |= DST_Y_TOP_TO_BOTTOM;
} else {
src_y += height;
dest_y += height;
}
gInfo.WaitForFifo(5);
OUTREG(DST_CNTL, cmd);
OUTREG(SRC_Y_X, (src_x << 16) | src_y);
OUTREG(SRC_HEIGHT1_WIDTH1, ((width + 1) << 16) | (height + 1));
OUTREG(DST_Y_X, (dest_x << 16) | dest_y);
OUTREG(DST_HEIGHT_WIDTH, ((width + 1) << 16) | (height + 1));
pList ++;
}
}