Haiku ATI video driver adapted from the X.org ATI driver.
Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
Precision Insight, Inc., Cedar Park, Texas, and
VA Linux Systems Inc., Fremont, California.
Copyright 2009 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac 2009
*/
#include "accelerant.h"
#include "rage128.h"
void
Rage128_EngineFlush()
{
OUTREGM(R128_PC_NGUI_CTLSTAT, R128_PC_FLUSH_ALL, R128_PC_FLUSH_ALL);
for (int i = 0; i < R128_TIMEOUT; i++) {
if ( ! (INREG(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY))
break;
}
}
void
Rage128_EngineReset()
{
Rage128_EngineFlush();
uint32 clockCntlIndex = INREG(R128_CLOCK_CNTL_INDEX);
uint32 mclkCntl = GetPLLReg(R128_MCLK_CNTL);
SetPLLReg(R128_MCLK_CNTL, mclkCntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
uint32 genResetCntl = INREG(R128_GEN_RESET_CNTL);
OUTREG(R128_GEN_RESET_CNTL, genResetCntl | R128_SOFT_RESET_GUI);
INREG(R128_GEN_RESET_CNTL);
OUTREG(R128_GEN_RESET_CNTL, genResetCntl & ~R128_SOFT_RESET_GUI);
INREG(R128_GEN_RESET_CNTL);
SetPLLReg(R128_MCLK_CNTL, mclkCntl);
OUTREG(R128_CLOCK_CNTL_INDEX, clockCntlIndex);
OUTREG(R128_GEN_RESET_CNTL, genResetCntl);
}
void
Rage128_EngineInit(const DisplayModeEx& mode)
{
SharedInfo& si = *gInfo.sharedInfo;
TRACE("Rage128_EngineInit() bits/pixel: %d\n", mode.bitsPerPixel);
OUTREG(R128_SCALE_3D_CNTL, 0);
Rage128_EngineReset();
uint32 dataType = 0;
switch (mode.bitsPerPixel) {
case 8:
dataType = 2;
break;
case 15:
dataType = 3;
break;
case 16:
dataType = 4;
break;
case 32:
dataType = 6;
break;
default:
TRACE("Unsupported color depth: %d bits/pixel\n", mode.bitsPerPixel);
}
gInfo.WaitForFifo(2);
OUTREG(R128_DEFAULT_OFFSET, gInfo.sharedInfo->frameBufferOffset);
OUTREG(R128_DEFAULT_PITCH, mode.timing.h_display / 8);
gInfo.WaitForFifo(4);
OUTREG(R128_AUX_SC_CNTL, 0);
OUTREG(R128_DEFAULT_SC_BOTTOM_RIGHT, (R128_DEFAULT_SC_RIGHT_MAX
| R128_DEFAULT_SC_BOTTOM_MAX));
OUTREG(R128_SC_TOP_LEFT, 0);
OUTREG(R128_SC_BOTTOM_RIGHT, (R128_DEFAULT_SC_RIGHT_MAX
| R128_DEFAULT_SC_BOTTOM_MAX));
si.r128_dpGuiMasterCntl = ((dataType << R128_GMC_DST_DATATYPE_SHIFT)
| R128_GMC_CLR_CMP_CNTL_DIS
| R128_GMC_AUX_CLIP_DIS);
gInfo.WaitForFifo(1);
OUTREG(R128_DP_GUI_MASTER_CNTL, (si.r128_dpGuiMasterCntl
| R128_GMC_BRUSH_SOLID_COLOR
| R128_GMC_SRC_DATATYPE_COLOR));
gInfo.WaitForFifo(8);
OUTREG(R128_DST_BRES_ERR, 0);
OUTREG(R128_DST_BRES_INC, 0);
OUTREG(R128_DST_BRES_DEC, 0);
OUTREG(R128_DP_BRUSH_FRGD_CLR, 0xffffffff);
OUTREG(R128_DP_BRUSH_BKGD_CLR, 0x00000000);
OUTREG(R128_DP_SRC_FRGD_CLR, 0xffffffff);
OUTREG(R128_DP_SRC_BKGD_CLR, 0x00000000);
OUTREG(R128_DP_WRITE_MASK, 0xffffffff);
gInfo.WaitForFifo(1);
OUTREGM(R128_DP_DATATYPE, 0, R128_HOST_BIG_ENDIAN_EN);
gInfo.WaitForIdle();
}
void
Rage128_FillRectangle(engine_token *et, uint32 color, fill_rect_params *pList, uint32 count)
{
(void)et;
gInfo.WaitForFifo(3);
OUTREG(R128_DP_GUI_MASTER_CNTL, (gInfo.sharedInfo->r128_dpGuiMasterCntl
| R128_GMC_BRUSH_SOLID_COLOR
| R128_GMC_SRC_DATATYPE_COLOR
| R128_ROP3_P));
OUTREG(R128_DP_BRUSH_FRGD_CLR, color);
OUTREG(R128_DP_CNTL, R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
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(R128_DST_Y_X, (y << 16) | x);
OUTREG(R128_DST_WIDTH_HEIGHT, (w << 16) | h);
pList++;
}
}
void
Rage128_FillSpan(engine_token *et, uint32 color, uint16 *pList, uint32 count)
{
(void)et;
gInfo.WaitForFifo(2);
OUTREG(R128_DP_GUI_MASTER_CNTL, (gInfo.sharedInfo->r128_dpGuiMasterCntl
| R128_GMC_BRUSH_SOLID_COLOR
| R128_GMC_SRC_DATATYPE_COLOR
| R128_ROP3_P));
OUTREG(R128_DP_BRUSH_FRGD_CLR, color);
while (count--) {
int y = *pList++;
int x = *pList++;
int w = *pList++ - x + 1;
if (w <= 0)
continue;
gInfo.WaitForFifo(2);
OUTREG(R128_DST_Y_X, (y << 16) | x);
OUTREG(R128_DST_WIDTH_HEIGHT, (w << 16) | 1);
}
}
void
Rage128_InvertRectangle(engine_token *et, fill_rect_params *pList, uint32 count)
{
(void)et;
gInfo.WaitForFifo(2);
OUTREG(R128_DP_GUI_MASTER_CNTL, (gInfo.sharedInfo->r128_dpGuiMasterCntl
| R128_GMC_BRUSH_NONE
| R128_GMC_SRC_DATATYPE_COLOR
| R128_DP_SRC_SOURCE_MEMORY
| R128_ROP3_Dn));
OUTREG(R128_DP_CNTL, R128_DST_X_LEFT_TO_RIGHT | R128_DST_Y_TOP_TO_BOTTOM);
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(R128_DST_Y_X, (y << 16) | x);
OUTREG(R128_DST_WIDTH_HEIGHT, (w << 16) | h);
pList++;
}
}
void
Rage128_ScreenToScreenBlit(engine_token *et, blit_params *pList, uint32 count)
{
(void)et;
gInfo.WaitForFifo(1);
OUTREG(R128_DP_GUI_MASTER_CNTL, (gInfo.sharedInfo->r128_dpGuiMasterCntl
| R128_GMC_BRUSH_NONE
| R128_GMC_SRC_DATATYPE_COLOR
| R128_DP_SRC_SOURCE_MEMORY
| R128_ROP3_S));
while (count--) {
int cmd = 0;
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 |= R128_DST_X_LEFT_TO_RIGHT;
} else {
src_x += width;
dest_x += width;
}
if (dest_y <= src_y) {
cmd |= R128_DST_Y_TOP_TO_BOTTOM;
} else {
src_y += height;
dest_y += height;
}
gInfo.WaitForFifo(4);
OUTREG(R128_DP_CNTL, cmd);
OUTREG(R128_SRC_Y_X, (src_y << 16) | src_x);
OUTREG(R128_DST_Y_X, (dest_y << 16) | dest_x);
OUTREG(R128_DST_HEIGHT_WIDTH, ((height + 1) << 16) | (width + 1));
pList ++;
}
}