/* * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. * * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation on the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #if defined(ACCEL_MMIO) && defined(ACCEL_CP) #error Cannot define both MMIO and CP acceleration! #endif #if !defined(UNIXCPP) || defined(ANSICPP) #define FUNC_NAME_CAT(prefix,suffix) prefix##suffix #else #define FUNC_NAME_CAT(prefix,suffix) prefix/**/suffix #endif #ifdef ACCEL_MMIO #define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,MMIO) #else #ifdef ACCEL_CP #define FUNC_NAME(prefix) FUNC_NAME_CAT(prefix,CP) #else #error No accel type defined! #endif #endif static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); ACCEL_PREAMBLE(); info->texW[0] = info->texH[0] = info->texW[1] = info->texH[1] = 1; if (IS_R300_VARIANT) { BEGIN_ACCEL(3); OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, 0x3); OUT_ACCEL_REG(R300_WAIT_UNTIL, 0x30000); FINISH_ACCEL(); BEGIN_ACCEL(3); OUT_ACCEL_REG(R300_GB_TILE_CONFIG, 0x10011); OUT_ACCEL_REG(R300_GB_SELECT,0x0); OUT_ACCEL_REG(R300_GB_ENABLE, 0x0); FINISH_ACCEL(); BEGIN_ACCEL(3); OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, 0x3); OUT_ACCEL_REG(R300_WAIT_UNTIL, 0x30000); FINISH_ACCEL(); BEGIN_ACCEL(5); OUT_ACCEL_REG(R300_GB_AA_CONFIG, 0x0); OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, 0x3); OUT_ACCEL_REG(R300_GB_MSPOS0, 0x78888888); OUT_ACCEL_REG(R300_GB_MSPOS1, 0x08888888); FINISH_ACCEL(); BEGIN_ACCEL(4); OUT_ACCEL_REG(R300_GA_POLY_MODE, 0x120); OUT_ACCEL_REG(R300_GA_ROUND_MODE, 0x5); OUT_ACCEL_REG(R300_GA_COLOR_CONTROL, 0xAAAA); OUT_ACCEL_REG(R300_GA_OFFSET, 0x0); FINISH_ACCEL(); BEGIN_ACCEL(26); OUT_ACCEL_REG(R300_VAP_CNTL_STATUS, 0x0); OUT_ACCEL_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); OUT_ACCEL_REG(R300_VAP_CNTL, 0x300456); OUT_ACCEL_REG(R300_VAP_VTE_CNTL, 0x300); OUT_ACCEL_REG(R300_VAP_PSC_SGN_NORM_CNTL, 0x0); OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_0, 0x4a014001); OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_1, 0x6b01); OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_EXT_0, 0xf688f688); OUT_ACCEL_REG(R300_VAP_PROG_STREAM_CNTL_EXT_1, 0xf688); OUT_ACCEL_REG(R300_VAP_PVS_CODE_CNTL_0, 0x100400); OUT_ACCEL_REG(R300_VAP_PVS_CODE_CNTL_1, 0x1); OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0); OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00f00203); OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00d10001); OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248001); OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248001); OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00f02203); OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x00d10141); OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248141); OUT_ACCEL_REG(R300_VAP_PVS_VECTOR_DATA_REG,0x01248141); OUT_ACCEL_REG(R300_VAP_PVS_FLOW_CNTL_OPC, 0x0); OUT_ACCEL_REG(R300_VAP_OUT_VTX_FMT_0, 0x1); OUT_ACCEL_REG(R300_VAP_OUT_VTX_FMT_1, (0x2 << 3) | 0x2); OUT_ACCEL_REG(R300_VAP_GB_VERT_CLIP_ADJ, 0x3f800000); OUT_ACCEL_REG(R300_VAP_GB_VERT_DISC_ADJ, 0x3f800000); OUT_ACCEL_REG(R300_VAP_GB_HORZ_CLIP_ADJ, 0x3f800000); OUT_ACCEL_REG(R300_VAP_GB_HORZ_DISC_ADJ, 0x3f800000); OUT_ACCEL_REG(R300_VAP_CLIP_CNTL, 0x10000); FINISH_ACCEL(); BEGIN_ACCEL(7); OUT_ACCEL_REG(R300_SU_TEX_WRAP, 0x0); OUT_ACCEL_REG(R300_SU_POLY_OFFSET_ENABLE, 0x0); OUT_ACCEL_REG(R300_SU_CULL_MODE, 0x4); OUT_ACCEL_REG(R300_SU_DEPTH_SCALE, 0x4b7fffff); OUT_ACCEL_REG(R300_SU_DEPTH_OFFSET, 0x0); OUT_ACCEL_REG(R300_RS_COUNT, 0x40002); OUT_ACCEL_REG(R300_RS_IP_0, 0x1610000); FINISH_ACCEL(); BEGIN_ACCEL(5); OUT_ACCEL_REG(R300_US_W_FMT, 0x0); OUT_ACCEL_REG(R300_US_OUT_FMT_1, 0x1B0F); OUT_ACCEL_REG(R300_US_OUT_FMT_2, 0x1B0F); OUT_ACCEL_REG(R300_US_OUT_FMT_3, 0x1B0F); OUT_ACCEL_REG(R300_US_OUT_FMT_0, 0x1B01); FINISH_ACCEL(); BEGIN_ACCEL(2); OUT_ACCEL_REG(R300_RS_INST_COUNT, 0xC0); OUT_ACCEL_REG(R300_RS_INST_0, 0x8); FINISH_ACCEL(); BEGIN_ACCEL(3); OUT_ACCEL_REG(R300_FG_DEPTH_SRC, 0x0); OUT_ACCEL_REG(R300_FG_FOG_BLEND, 0x0); OUT_ACCEL_REG(R300_FG_ALPHA_FUNC, 0x0); FINISH_ACCEL(); BEGIN_ACCEL(12); OUT_ACCEL_REG(R300_RB3D_ZSTENCILCNTL, 0x0); OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, 0x3); OUT_ACCEL_REG(R300_RB3D_BW_CNTL, 0x0); OUT_ACCEL_REG(R300_RB3D_ZCNTL, 0x0); OUT_ACCEL_REG(R300_RB3D_ZTOP, 0x0); OUT_ACCEL_REG(R300_RB3D_ROPCNTL, 0x0); OUT_ACCEL_REG(R300_RB3D_AARESOLVE_CTL, 0x0); OUT_ACCEL_REG(R300_RB3D_COLOR_CHANNEL_MASK, 0xf); OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); OUT_ACCEL_REG(R300_RB3D_CCTL, 0x0); OUT_ACCEL_REG(R300_RB3D_DITHER_CTL, 0x0); OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); FINISH_ACCEL(); BEGIN_ACCEL(7); OUT_ACCEL_REG(R300_SC_EDGERULE, 0xA5294A5); OUT_ACCEL_REG(R300_SC_SCISSOR0, 0x0); OUT_ACCEL_REG(R300_SC_SCISSOR1, 0x3ffffff); OUT_ACCEL_REG(R300_SC_CLIP_0_A, 0x880440); OUT_ACCEL_REG(R300_SC_CLIP_0_B, 0xff0ff0); OUT_ACCEL_REG(R300_SC_CLIP_RULE, 0xAAAA); OUT_ACCEL_REG(R300_SC_SCREENDOOR, 0xffffff); FINISH_ACCEL(); } else if ((info->ChipFamily == CHIP_FAMILY_RV250) || (info->ChipFamily == CHIP_FAMILY_RV280) || (info->ChipFamily == CHIP_FAMILY_RS300) || (info->ChipFamily == CHIP_FAMILY_R200)) { BEGIN_ACCEL(7); if (info->ChipFamily == CHIP_FAMILY_RS300) { OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, RADEON_TCL_BYPASS); } else { OUT_ACCEL_REG(R200_SE_VAP_CNTL_STATUS, 0); } OUT_ACCEL_REG(R200_PP_CNTL_X, 0); OUT_ACCEL_REG(R200_PP_TXMULTI_CTL_0, 0); OUT_ACCEL_REG(R200_SE_VTX_STATE_CNTL, 0); OUT_ACCEL_REG(R200_RE_CNTL, 0x0); OUT_ACCEL_REG(R200_SE_VTE_CNTL, 0); OUT_ACCEL_REG(R200_SE_VAP_CNTL, R200_VAP_FORCE_W_TO_ONE | R200_VAP_VF_MAX_VTX_NUM); FINISH_ACCEL(); } else { BEGIN_ACCEL(2); if ((info->ChipFamily == CHIP_FAMILY_RADEON) || (info->ChipFamily == CHIP_FAMILY_RV200)) OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, 0); else OUT_ACCEL_REG(RADEON_SE_CNTL_STATUS, RADEON_TCL_BYPASS); OUT_ACCEL_REG(RADEON_SE_COORD_FMT, RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | RADEON_VTX_ST0_NONPARAMETRIC | RADEON_VTX_ST1_NONPARAMETRIC | RADEON_TEX1_W_ROUTING_USE_W0); FINISH_ACCEL(); } BEGIN_ACCEL(5); OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0); OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, 0x07ff07ff); OUT_ACCEL_REG(RADEON_AUX_SC_CNTL, 0); OUT_ACCEL_REG(RADEON_RB3D_PLANEMASK, 0xffffffff); OUT_ACCEL_REG(RADEON_SE_CNTL, RADEON_DIFFUSE_SHADE_GOURAUD | RADEON_BFACE_SOLID | RADEON_FFACE_SOLID | RADEON_VTX_PIX_CENTER_OGL | RADEON_ROUND_MODE_ROUND | RADEON_ROUND_PREC_4TH_PIX); FINISH_ACCEL(); } /* MMIO: * * Wait for the graphics engine to be completely idle: the FIFO has * drained, the Pixel Cache is flushed, and the engine is idle. This is * a standard "sync" function that will make the hardware "quiescent". * * CP: * * Wait until the CP is completely idle: the FIFO has drained and the CP * is idle. */ void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; int i = 0; #ifdef ACCEL_CP /* Make sure the CP is idle first */ if (info->CPStarted) { int ret; FLUSH_RING(); for (;;) { do { ret = drmCommandNone(info->drmFD, DRM_RADEON_CP_IDLE); if (ret && ret != -EBUSY) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%s: CP idle %d\n", __FUNCTION__, ret); } } while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT)); if (ret == 0) return; xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Idle timed out, resetting engine...\n"); RADEONEngineReset(pScrn); RADEONEngineRestore(pScrn); /* Always restart the engine when doing CP 2D acceleration */ RADEONCP_RESET(pScrn, info); RADEONCP_START(pScrn, info); } } #endif #if 0 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "WaitForIdle (entering): %d entries, stat=0x%08x\n", INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, INREG(RADEON_RBBM_STATUS)); #endif /* Wait for the engine to go idle */ RADEONWaitForFifoFunction(pScrn, 64); for (;;) { for (i = 0; i < RADEON_TIMEOUT; i++) { if (!(INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) { RADEONEngineFlush(pScrn); return; } } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Idle timed out: %u entries, stat=0x%08x\n", (unsigned int)INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, (unsigned int)INREG(RADEON_RBBM_STATUS)); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Idle timed out, resetting engine...\n"); RADEONEngineReset(pScrn); RADEONEngineRestore(pScrn); #ifdef XF86DRI if (info->directRenderingEnabled) { RADEONCP_RESET(pScrn, info); RADEONCP_START(pScrn, info); } #endif } }