radeon_accel.c revision 921a55d8
1/* 2 * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and 3 * VA Linux Systems Inc., Fremont, California. 4 * 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining 8 * a copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation on the rights to use, copy, modify, merge, 11 * publish, distribute, sublicense, and/or sell copies of the Software, 12 * and to permit persons to whom the Software is furnished to do so, 13 * subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial 17 * portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR 23 * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 */ 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33/* 34 * Authors: 35 * Kevin E. Martin <martin@xfree86.org> 36 * Rickard E. Faith <faith@valinux.com> 37 * Alan Hourihane <alanh@fairlite.demon.co.uk> 38 * 39 * Credits: 40 * 41 * Thanks to Ani Joshi <ajoshi@shell.unixbox.com> for providing source 42 * code to his Radeon driver. Portions of this file are based on the 43 * initialization code for that driver. 44 * 45 * References: 46 * 47 * !!!! FIXME !!!! 48 * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical 49 * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April 50 * 1999. 51 * 52 * RAGE 128 Software Development Manual (Technical Reference Manual P/N 53 * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. 54 * 55 * Notes on unimplemented XAA optimizations: 56 * 57 * SetClipping: This has been removed as XAA expects 16bit registers 58 * for full clipping. 59 * TwoPointLine: The Radeon supports this. Not Bresenham. 60 * DashedLine with non-power-of-two pattern length: Apparently, there is 61 * no way to set the length of the pattern -- it is always 62 * assumed to be 8 or 32 (or 1024?). 63 * ScreenToScreenColorExpandFill: See p. 4-17 of the Technical Reference 64 * Manual where it states that monochrome expansion of frame 65 * buffer data is not supported. 66 * CPUToScreenColorExpandFill, direct: The implementation here uses a hybrid 67 * direct/indirect method. If we had more data registers, 68 * then we could do better. If XAA supported a trigger write 69 * address, the code would be simpler. 70 * Color8x8PatternFill: Apparently, an 8x8 color brush cannot take an 8x8 71 * pattern from frame buffer memory. 72 * ImageWrites: Same as CPUToScreenColorExpandFill 73 * 74 */ 75 76#include <errno.h> 77#include <string.h> 78#include <assert.h> 79 /* Driver data structures */ 80#include "radeon.h" 81#include "radeon_reg.h" 82#include "r600_reg.h" 83#include "radeon_macros.h" 84#include "radeon_probe.h" 85#include "radeon_version.h" 86#ifdef XF86DRI 87#define _XF86DRI_SERVER_ 88#include "radeon_drm.h" 89#endif 90 91#include "ati_pciids_gen.h" 92 93 /* Line support */ 94#include "miline.h" 95 96 /* X and server generic header files */ 97#include "xf86.h" 98 99static void R600EngineReset(ScrnInfoPtr pScrn); 100 101#ifdef USE_XAA 102static struct { 103 int rop; 104 int pattern; 105} RADEON_ROP[] = { 106 { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear */ 107 { RADEON_ROP3_DSa, RADEON_ROP3_DPa }, /* Gxand */ 108 { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse */ 109 { RADEON_ROP3_S, RADEON_ROP3_P }, /* GXcopy */ 110 { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted */ 111 { RADEON_ROP3_D, RADEON_ROP3_D }, /* GXnoop */ 112 { RADEON_ROP3_DSx, RADEON_ROP3_DPx }, /* GXxor */ 113 { RADEON_ROP3_DSo, RADEON_ROP3_DPo }, /* GXor */ 114 { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor */ 115 { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv */ 116 { RADEON_ROP3_Dn, RADEON_ROP3_Dn }, /* GXinvert */ 117 { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse */ 118 { RADEON_ROP3_Sn, RADEON_ROP3_Pn }, /* GXcopyInverted */ 119 { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted */ 120 { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand */ 121 { RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */ 122}; 123#endif 124 125/* The FIFO has 64 slots. This routines waits until at least `entries' 126 * of these slots are empty. 127 */ 128void RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries) 129{ 130 RADEONInfoPtr info = RADEONPTR(pScrn); 131 unsigned char *RADEONMMIO = info->MMIO; 132 int i; 133 134 for (;;) { 135 for (i = 0; i < RADEON_TIMEOUT; i++) { 136 info->accel_state->fifo_slots = 137 INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; 138 if (info->accel_state->fifo_slots >= entries) return; 139 } 140 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 141 "FIFO timed out: %u entries, stat=0x%08x\n", 142 (unsigned int)INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK, 143 (unsigned int)INREG(RADEON_RBBM_STATUS)); 144 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 145 "FIFO timed out, resetting engine...\n"); 146 RADEONEngineReset(pScrn); 147 RADEONEngineRestore(pScrn); 148#ifdef XF86DRI 149 if (info->directRenderingEnabled) { 150 RADEONCP_RESET(pScrn, info); 151 RADEONCP_START(pScrn, info); 152 } 153#endif 154 } 155} 156 157void R600WaitForFifoFunction(ScrnInfoPtr pScrn, int entries) 158{ 159 RADEONInfoPtr info = RADEONPTR(pScrn); 160 unsigned char *RADEONMMIO = info->MMIO; 161 int i; 162 163 for (;;) { 164 for (i = 0; i < RADEON_TIMEOUT; i++) { 165 if (info->ChipFamily >= CHIP_FAMILY_RV770) 166 info->accel_state->fifo_slots = 167 INREG(R600_GRBM_STATUS) & R700_CMDFIFO_AVAIL_MASK; 168 else 169 info->accel_state->fifo_slots = 170 INREG(R600_GRBM_STATUS) & R600_CMDFIFO_AVAIL_MASK; 171 if (info->accel_state->fifo_slots >= entries) return; 172 } 173 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 174 "FIFO timed out: stat=0x%08x\n", 175 (unsigned int)INREG(R600_GRBM_STATUS)); 176 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 177 "FIFO timed out, resetting engine...\n"); 178 R600EngineReset(pScrn); 179#ifdef XF86DRI 180 if (info->directRenderingEnabled) { 181 RADEONCP_RESET(pScrn, info); 182 RADEONCP_START(pScrn, info); 183 } 184#endif 185 } 186} 187 188/* Flush all dirty data in the Pixel Cache to memory */ 189void RADEONEngineFlush(ScrnInfoPtr pScrn) 190{ 191 RADEONInfoPtr info = RADEONPTR(pScrn); 192 unsigned char *RADEONMMIO = info->MMIO; 193 int i; 194 195 if (info->ChipFamily <= CHIP_FAMILY_RV280) { 196 OUTREGP(RADEON_RB3D_DSTCACHE_CTLSTAT, 197 RADEON_RB3D_DC_FLUSH_ALL, 198 ~RADEON_RB3D_DC_FLUSH_ALL); 199 for (i = 0; i < RADEON_TIMEOUT; i++) { 200 if (!(INREG(RADEON_RB3D_DSTCACHE_CTLSTAT) & RADEON_RB3D_DC_BUSY)) 201 break; 202 } 203 if (i == RADEON_TIMEOUT) { 204 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 205 "DC flush timeout: %x\n", 206 (unsigned int)INREG(RADEON_RB3D_DSTCACHE_CTLSTAT)); 207 } 208 } else { 209 OUTREGP(R300_DSTCACHE_CTLSTAT, 210 R300_RB2D_DC_FLUSH_ALL, 211 ~R300_RB2D_DC_FLUSH_ALL); 212 for (i = 0; i < RADEON_TIMEOUT; i++) { 213 if (!(INREG(R300_DSTCACHE_CTLSTAT) & R300_RB2D_DC_BUSY)) 214 break; 215 } 216 if (i == RADEON_TIMEOUT) { 217 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 218 "DC flush timeout: %x\n", 219 (unsigned int)INREG(R300_DSTCACHE_CTLSTAT)); 220 } 221 } 222} 223 224/* Reset graphics card to known state */ 225void RADEONEngineReset(ScrnInfoPtr pScrn) 226{ 227 RADEONInfoPtr info = RADEONPTR(pScrn); 228 unsigned char *RADEONMMIO = info->MMIO; 229 uint32_t clock_cntl_index; 230 uint32_t mclk_cntl; 231 uint32_t rbbm_soft_reset; 232 uint32_t host_path_cntl; 233 234 /* The following RBBM_SOFT_RESET sequence can help un-wedge 235 * an R300 after the command processor got stuck. 236 */ 237 rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); 238 OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | 239 RADEON_SOFT_RESET_CP | 240 RADEON_SOFT_RESET_HI | 241 RADEON_SOFT_RESET_SE | 242 RADEON_SOFT_RESET_RE | 243 RADEON_SOFT_RESET_PP | 244 RADEON_SOFT_RESET_E2 | 245 RADEON_SOFT_RESET_RB)); 246 INREG(RADEON_RBBM_SOFT_RESET); 247 OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & (uint32_t) 248 ~(RADEON_SOFT_RESET_CP | 249 RADEON_SOFT_RESET_HI | 250 RADEON_SOFT_RESET_SE | 251 RADEON_SOFT_RESET_RE | 252 RADEON_SOFT_RESET_PP | 253 RADEON_SOFT_RESET_E2 | 254 RADEON_SOFT_RESET_RB))); 255 INREG(RADEON_RBBM_SOFT_RESET); 256 OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); 257 INREG(RADEON_RBBM_SOFT_RESET); 258 259 RADEONEngineFlush(pScrn); 260 261 clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX); 262 RADEONPllErrataAfterIndex(info); 263 264#if 0 /* taken care of by new PM code */ 265 /* Some ASICs have bugs with dynamic-on feature, which are 266 * ASIC-version dependent, so we force all blocks on for now 267 */ 268 if (info->HasCRTC2) { 269 uint32_t tmp; 270 271 tmp = INPLL(pScrn, RADEON_SCLK_CNTL); 272 OUTPLL(RADEON_SCLK_CNTL, ((tmp & ~RADEON_DYN_STOP_LAT_MASK) | 273 RADEON_CP_MAX_DYN_STOP_LAT | 274 RADEON_SCLK_FORCEON_MASK)); 275 276 if (info->ChipFamily == CHIP_FAMILY_RV200) { 277 tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL); 278 OUTPLL(RADEON_SCLK_MORE_CNTL, tmp | RADEON_SCLK_MORE_FORCEON); 279 } 280 } 281#endif /* new PM code */ 282 283 mclk_cntl = INPLL(pScrn, RADEON_MCLK_CNTL); 284 285#if 0 /* handled by new PM code */ 286 OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl | 287 RADEON_FORCEON_MCLKA | 288 RADEON_FORCEON_MCLKB | 289 RADEON_FORCEON_YCLKA | 290 RADEON_FORCEON_YCLKB | 291 RADEON_FORCEON_MC | 292 RADEON_FORCEON_AIC)); 293#endif /* new PM code */ 294 295 /* Soft resetting HDP thru RBBM_SOFT_RESET register can cause some 296 * unexpected behaviour on some machines. Here we use 297 * RADEON_HOST_PATH_CNTL to reset it. 298 */ 299 host_path_cntl = INREG(RADEON_HOST_PATH_CNTL); 300 rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET); 301 302 if (IS_R300_VARIANT || IS_AVIVO_VARIANT) { 303 uint32_t tmp; 304 305 OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | 306 RADEON_SOFT_RESET_CP | 307 RADEON_SOFT_RESET_HI | 308 RADEON_SOFT_RESET_E2)); 309 INREG(RADEON_RBBM_SOFT_RESET); 310 OUTREG(RADEON_RBBM_SOFT_RESET, 0); 311 tmp = INREG(RADEON_RB3D_DSTCACHE_MODE); 312 OUTREG(RADEON_RB3D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */ 313 } else { 314 OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | 315 RADEON_SOFT_RESET_CP | 316 RADEON_SOFT_RESET_SE | 317 RADEON_SOFT_RESET_RE | 318 RADEON_SOFT_RESET_PP | 319 RADEON_SOFT_RESET_E2 | 320 RADEON_SOFT_RESET_RB)); 321 INREG(RADEON_RBBM_SOFT_RESET); 322 OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & (uint32_t) 323 ~(RADEON_SOFT_RESET_CP | 324 RADEON_SOFT_RESET_SE | 325 RADEON_SOFT_RESET_RE | 326 RADEON_SOFT_RESET_PP | 327 RADEON_SOFT_RESET_E2 | 328 RADEON_SOFT_RESET_RB))); 329 INREG(RADEON_RBBM_SOFT_RESET); 330 } 331 332 if (!IS_R300_VARIANT && !IS_AVIVO_VARIANT) 333 OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); 334 335 OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); 336 RADEONPllErrataAfterIndex(info); 337 OUTPLL(pScrn, RADEON_MCLK_CNTL, mclk_cntl); 338} 339 340/* Reset graphics card to known state */ 341static void R600EngineReset(ScrnInfoPtr pScrn) 342{ 343 RADEONInfoPtr info = RADEONPTR(pScrn); 344 unsigned char *RADEONMMIO = info->MMIO; 345 uint32_t cp_ptr, cp_me_cntl, cp_rb_cntl; 346 347 cp_ptr = INREG(R600_CP_RB_WPTR); 348 349 cp_me_cntl = INREG(R600_CP_ME_CNTL); 350 OUTREG(R600_CP_ME_CNTL, 0x10000000); 351 352 OUTREG(R600_GRBM_SOFT_RESET, 0x7fff); 353 INREG(R600_GRBM_SOFT_RESET); 354 usleep (50); 355 OUTREG(R600_GRBM_SOFT_RESET, 0); 356 INREG(R600_GRBM_SOFT_RESET); 357 358 OUTREG(R600_CP_RB_WPTR_DELAY, 0); 359 cp_rb_cntl = INREG(R600_CP_RB_CNTL); 360 OUTREG(R600_CP_RB_CNTL, 0x80000000); 361 362 OUTREG(R600_CP_RB_RPTR_WR, cp_ptr); 363 OUTREG(R600_CP_RB_WPTR, cp_ptr); 364 OUTREG(R600_CP_RB_CNTL, cp_rb_cntl); 365 OUTREG(R600_CP_ME_CNTL, cp_me_cntl); 366 367} 368 369/* Restore the acceleration hardware to its previous state */ 370void RADEONEngineRestore(ScrnInfoPtr pScrn) 371{ 372 RADEONInfoPtr info = RADEONPTR(pScrn); 373 unsigned char *RADEONMMIO = info->MMIO; 374 375 if (info->cs) 376 return; 377 378 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 379 "EngineRestore (%d/%d)\n", 380 info->CurrentLayout.pixel_code, 381 info->CurrentLayout.bitsPerPixel); 382 383 /* Setup engine location. This shouldn't be necessary since we 384 * set them appropriately before any accel ops, but let's avoid 385 * random bogus DMA in case we inadvertently trigger the engine 386 * in the wrong place (happened). 387 */ 388 RADEONWaitForFifo(pScrn, 2); 389 OUTREG(RADEON_DST_PITCH_OFFSET, info->accel_state->dst_pitch_offset); 390 OUTREG(RADEON_SRC_PITCH_OFFSET, info->accel_state->dst_pitch_offset); 391 392 RADEONWaitForFifo(pScrn, 1); 393#if X_BYTE_ORDER == X_BIG_ENDIAN 394 OUTREGP(RADEON_DP_DATATYPE, 395 RADEON_HOST_BIG_ENDIAN_EN, 396 ~RADEON_HOST_BIG_ENDIAN_EN); 397#else 398 OUTREGP(RADEON_DP_DATATYPE, 0, ~RADEON_HOST_BIG_ENDIAN_EN); 399#endif 400 401 /* Restore SURFACE_CNTL */ 402 OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl); 403 404 RADEONWaitForFifo(pScrn, 1); 405 OUTREG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX 406 | RADEON_DEFAULT_SC_BOTTOM_MAX)); 407 RADEONWaitForFifo(pScrn, 1); 408 OUTREG(RADEON_DP_GUI_MASTER_CNTL, (info->accel_state->dp_gui_master_cntl 409 | RADEON_GMC_BRUSH_SOLID_COLOR 410 | RADEON_GMC_SRC_DATATYPE_COLOR)); 411 412 RADEONWaitForFifo(pScrn, 5); 413 OUTREG(RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff); 414 OUTREG(RADEON_DP_BRUSH_BKGD_CLR, 0x00000000); 415 OUTREG(RADEON_DP_SRC_FRGD_CLR, 0xffffffff); 416 OUTREG(RADEON_DP_SRC_BKGD_CLR, 0x00000000); 417 OUTREG(RADEON_DP_WRITE_MASK, 0xffffffff); 418 419 RADEONWaitForIdleMMIO(pScrn); 420 421 info->accel_state->XInited3D = FALSE; 422} 423 424static int RADEONDRMGetNumPipes(ScrnInfoPtr pScrn, int *num_pipes) 425{ 426 RADEONInfoPtr info = RADEONPTR(pScrn); 427 if (info->dri->pKernelDRMVersion->version_major < 2) { 428 drm_radeon_getparam_t np; 429 430 memset(&np, 0, sizeof(np)); 431 np.param = RADEON_PARAM_NUM_GB_PIPES; 432 np.value = num_pipes; 433 return drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GETPARAM, &np, sizeof(np)); 434 } else { 435 struct drm_radeon_info np2; 436 np2.value = (unsigned long)num_pipes; 437 np2.request = RADEON_INFO_NUM_GB_PIPES; 438 return drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INFO, &np2, sizeof(np2)); 439 } 440} 441 442/* Initialize the acceleration hardware */ 443void RADEONEngineInit(ScrnInfoPtr pScrn) 444{ 445 RADEONInfoPtr info = RADEONPTR(pScrn); 446 unsigned char *RADEONMMIO = info->MMIO; 447 int datatype = 0; 448 info->accel_state->num_gb_pipes = 0; 449 450 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 451 "EngineInit (%d/%d)\n", 452 info->CurrentLayout.pixel_code, 453 info->CurrentLayout.bitsPerPixel); 454 455#ifdef XF86DRI 456 if (info->directRenderingEnabled && (IS_R300_3D || IS_R500_3D)) { 457 int num_pipes; 458 459 if(RADEONDRMGetNumPipes(pScrn, &num_pipes) < 0) { 460 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 461 "Failed to determine num pipes from DRM, falling back to " 462 "manual look-up!\n"); 463 info->accel_state->num_gb_pipes = 0; 464 } else { 465 info->accel_state->num_gb_pipes = num_pipes; 466 } 467 } 468#endif 469 470 if (!info->cs) { 471 if ((info->ChipFamily == CHIP_FAMILY_RV410) || 472 (info->ChipFamily == CHIP_FAMILY_R420) || 473 (info->ChipFamily == CHIP_FAMILY_RS600) || 474 (info->ChipFamily == CHIP_FAMILY_RS690) || 475 (info->ChipFamily == CHIP_FAMILY_RS740) || 476 (info->ChipFamily == CHIP_FAMILY_RS400) || 477 (info->ChipFamily == CHIP_FAMILY_RS480) || 478 IS_R500_3D) { 479 if (info->accel_state->num_gb_pipes == 0) { 480 uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT); 481 482 info->accel_state->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; 483 if (IS_R500_3D) 484 OUTPLL(pScrn, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4)); 485 } 486 } else { 487 if (info->accel_state->num_gb_pipes == 0) { 488 if ((info->ChipFamily == CHIP_FAMILY_R300) || 489 (info->ChipFamily == CHIP_FAMILY_R350)) { 490 /* R3xx chips */ 491 info->accel_state->num_gb_pipes = 2; 492 } else { 493 /* RV3xx chips */ 494 info->accel_state->num_gb_pipes = 1; 495 } 496 } 497 } 498 499 /* SE cards only have 1 quadpipe */ 500 if ((info->Chipset == PCI_CHIP_RV410_5E4C) || 501 (info->Chipset == PCI_CHIP_RV410_5E4F) || 502 (info->Chipset == PCI_CHIP_R300_AD) || 503 (info->Chipset == PCI_CHIP_R350_AH)) 504 info->accel_state->num_gb_pipes = 1; 505 506 if (IS_R300_3D || IS_R500_3D) 507 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 508 "num quad-pipes is %d\n", info->accel_state->num_gb_pipes); 509 510 if (IS_R300_3D || IS_R500_3D) { 511 uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); 512 513 switch(info->accel_state->num_gb_pipes) { 514 case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break; 515 case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break; 516 case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break; 517 default: 518 case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; 519 } 520 521 OUTREG(R300_GB_TILE_CONFIG, gb_tile_config); 522 OUTREG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); 523 if (info->ChipFamily >= CHIP_FAMILY_R420) 524 OUTREG(R300_DST_PIPE_CONFIG, INREG(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG); 525 OUTREG(R300_RB2D_DSTCACHE_MODE, (INREG(R300_RB2D_DSTCACHE_MODE) | 526 R300_DC_AUTOFLUSH_ENABLE | 527 R300_DC_DC_DISABLE_IGNORE_PE)); 528 } else 529 OUTREG(RADEON_RB3D_CNTL, 0); 530 531 RADEONEngineReset(pScrn); 532 } 533 534 switch (info->CurrentLayout.pixel_code) { 535 case 8: datatype = 2; break; 536 case 15: datatype = 3; break; 537 case 16: datatype = 4; break; 538 case 24: datatype = 5; break; 539 case 32: datatype = 6; break; 540 default: 541 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, 542 "Unknown depth/bpp = %d/%d (code = %d)\n", 543 info->CurrentLayout.depth, 544 info->CurrentLayout.bitsPerPixel, 545 info->CurrentLayout.pixel_code); 546 } 547 548 info->accel_state->dp_gui_master_cntl = 549 ((datatype << RADEON_GMC_DST_DATATYPE_SHIFT) 550 | RADEON_GMC_CLR_CMP_CNTL_DIS 551 | RADEON_GMC_DST_PITCH_OFFSET_CNTL); 552 553 RADEONEngineRestore(pScrn); 554} 555 556uint32_t radeonGetPixmapOffset(PixmapPtr pPix) 557{ 558 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; 559 RADEONInfoPtr info = RADEONPTR(pScrn); 560 uint32_t offset = 0; 561 if (info->cs) 562 return 0; 563#ifdef USE_EXA 564 if (info->useEXA) { 565 offset = exaGetPixmapOffset(pPix); 566 } else 567#endif 568 { 569 offset = pPix->devPrivate.ptr - info->FB; 570 } 571 offset += info->fbLocation + pScrn->fbOffset; 572 return offset; 573} 574 575int radeon_cs_space_remaining(ScrnInfoPtr pScrn) 576{ 577 RADEONInfoPtr info = RADEONPTR(pScrn); 578 579#ifdef XF86DRM_MODE 580 if (info->cs) 581 return (info->cs->ndw - info->cs->cdw); 582 else 583#endif 584 return (info->cp->indirectBuffer->total - info->cp->indirectBuffer->used) / (int)sizeof(uint32_t); 585} 586 587#define ACCEL_MMIO 588#define ACCEL_PREAMBLE() unsigned char *RADEONMMIO = info->MMIO 589#define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) 590#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) 591#define FINISH_ACCEL() 592 593#include "radeon_commonfuncs.c" 594#if defined(RENDER) && defined(USE_XAA) 595#include "radeon_render.c" 596#endif 597#include "radeon_accelfuncs.c" 598 599#undef ACCEL_MMIO 600#undef ACCEL_PREAMBLE 601#undef BEGIN_ACCEL 602#undef OUT_ACCEL_REG 603#undef FINISH_ACCEL 604 605#ifdef XF86DRI 606 607#define ACCEL_CP 608#define ACCEL_PREAMBLE() \ 609 RING_LOCALS; \ 610 RADEONCP_REFRESH(pScrn, info) 611#define BEGIN_ACCEL(n) BEGIN_RING(2*(n)) 612#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) 613#define FINISH_ACCEL() ADVANCE_RING() 614 615 616#include "radeon_commonfuncs.c" 617#if defined(RENDER) && defined(USE_XAA) 618#include "radeon_render.c" 619#endif 620#include "radeon_accelfuncs.c" 621 622#undef ACCEL_CP 623#undef ACCEL_PREAMBLE 624#undef BEGIN_ACCEL 625#undef OUT_ACCEL_REG 626#undef FINISH_ACCEL 627 628/* Stop the CP */ 629int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info) 630{ 631 drm_radeon_cp_stop_t stop; 632 int ret, i; 633 634 stop.flush = 1; 635 stop.idle = 1; 636 637 ret = drmCommandWrite(info->dri->drmFD, DRM_RADEON_CP_STOP, &stop, 638 sizeof(drm_radeon_cp_stop_t)); 639 640 if (ret == 0) { 641 return 0; 642 } else if (errno != EBUSY) { 643 return -errno; 644 } 645 646 stop.flush = 0; 647 648 i = 0; 649 do { 650 ret = drmCommandWrite(info->dri->drmFD, DRM_RADEON_CP_STOP, &stop, 651 sizeof(drm_radeon_cp_stop_t)); 652 } while (ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY); 653 654 if (ret == 0) { 655 return 0; 656 } else if (errno != EBUSY) { 657 return -errno; 658 } 659 660 stop.idle = 0; 661 662 if (drmCommandWrite(info->dri->drmFD, DRM_RADEON_CP_STOP, 663 &stop, sizeof(drm_radeon_cp_stop_t))) { 664 return -errno; 665 } else { 666 return 0; 667 } 668} 669 670#define RADEON_IB_RESERVE (16 * sizeof(uint32_t)) 671 672/* Get an indirect buffer for the CP 2D acceleration commands */ 673drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn) 674{ 675 RADEONInfoPtr info = RADEONPTR(pScrn); 676 drmDMAReq dma; 677 drmBufPtr buf = NULL; 678 int indx = 0; 679 int size = 0; 680 int i = 0; 681 int ret; 682 683#if 0 684 /* FIXME: pScrn->pScreen has not been initialized when this is first 685 * called from RADEONSelectBuffer via RADEONDRICPInit. We could use 686 * the screen index from pScrn, which is initialized, and then get 687 * the screen from screenInfo.screens[index], but that is a hack. 688 */ 689 dma.context = DRIGetContext(pScrn->pScreen); 690#else 691 /* This is the X server's context */ 692 dma.context = 0x00000001; 693#endif 694 695 dma.send_count = 0; 696 dma.send_list = NULL; 697 dma.send_sizes = NULL; 698 dma.flags = 0; 699 dma.request_count = 1; 700 dma.request_size = RADEON_BUFFER_SIZE; 701 dma.request_list = &indx; 702 dma.request_sizes = &size; 703 dma.granted_count = 0; 704 705 while (1) { 706 do { 707 ret = drmDMA(info->dri->drmFD, &dma); 708 if (ret && ret != -EBUSY) { 709 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 710 "%s: CP GetBuffer %d\n", __FUNCTION__, ret); 711 } 712 } while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT)); 713 714 if (ret == 0) { 715 buf = &info->dri->buffers->list[indx]; 716 buf->used = 0; 717 if (RADEON_VERBOSE) { 718 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 719 " GetBuffer returning %d %p\n", 720 buf->idx, buf->address); 721 } 722 return buf; 723 } 724 725 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 726 "GetBuffer timed out, resetting engine...\n"); 727 728 if (info->ChipFamily < CHIP_FAMILY_R600) { 729 RADEONEngineReset(pScrn); 730 RADEONEngineRestore(pScrn); 731 } else 732 R600EngineReset(pScrn); 733 734 /* Always restart the engine when doing CP 2D acceleration */ 735 RADEONCP_RESET(pScrn, info); 736 RADEONCP_START(pScrn, info); 737 } 738} 739 740/* Flush the indirect buffer to the kernel for submission to the card */ 741void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard) 742{ 743 RADEONInfoPtr info = RADEONPTR(pScrn); 744 drmBufPtr buffer = info->cp->indirectBuffer; 745 int start = info->cp->indirectStart; 746 drm_radeon_indirect_t indirect; 747 748 assert(!info->cs); 749 if (!buffer) return; 750 if (start == buffer->used && !discard) return; 751 752 if (RADEON_VERBOSE) { 753 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Flushing buffer %d\n", 754 buffer->idx); 755 } 756 757 if (info->ChipFamily >= CHIP_FAMILY_R600) { 758 if (buffer->used & 0x3c) { 759 RING_LOCALS; 760 761 while (buffer->used & 0x3c) { 762 BEGIN_RING(1); 763 OUT_RING(CP_PACKET2()); /* fill up to multiple of 16 dwords */ 764 ADVANCE_RING(); 765 } 766 } 767 } 768 769 indirect.idx = buffer->idx; 770 indirect.start = start; 771 indirect.end = buffer->used; 772 indirect.discard = discard; 773 774 drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INDIRECT, 775 &indirect, sizeof(drm_radeon_indirect_t)); 776 777 if (discard) { 778 info->cp->indirectBuffer = RADEONCPGetBuffer(pScrn); 779 info->cp->indirectStart = 0; 780 } else { 781 /* Start on a double word boundary */ 782 info->cp->indirectStart = buffer->used = RADEON_ALIGN(buffer->used, 8); 783 if (RADEON_VERBOSE) { 784 xf86DrvMsg(pScrn->scrnIndex, X_INFO, " Starting at %d\n", 785 info->cp->indirectStart); 786 } 787 } 788} 789 790/* Flush and release the indirect buffer */ 791void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn) 792{ 793 RADEONInfoPtr info = RADEONPTR(pScrn); 794 drmBufPtr buffer = info->cp->indirectBuffer; 795 int start = info->cp->indirectStart; 796 drm_radeon_indirect_t indirect; 797 798 assert(!info->cs); 799 if (info->ChipFamily >= CHIP_FAMILY_R600) { 800 if (buffer && (buffer->used & 0x3c)) { 801 RING_LOCALS; 802 803 while (buffer->used & 0x3c) { 804 BEGIN_RING(1); 805 OUT_RING(CP_PACKET2()); /* fill up to multiple of 16 dwords */ 806 ADVANCE_RING(); 807 } 808 } 809 } 810 811 info->cp->indirectBuffer = NULL; 812 info->cp->indirectStart = 0; 813 814 if (!buffer) return; 815 816 if (RADEON_VERBOSE) { 817 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Releasing buffer %d\n", 818 buffer->idx); 819 } 820 821 indirect.idx = buffer->idx; 822 indirect.start = start; 823 indirect.end = buffer->used; 824 indirect.discard = 1; 825 826 drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_INDIRECT, 827 &indirect, sizeof(drm_radeon_indirect_t)); 828} 829 830/** \brief Calculate HostDataBlit parameters from pointer and pitch 831 * 832 * This is a helper for the trivial HostDataBlit users that don't need to worry 833 * about tiling etc. 834 */ 835void 836RADEONHostDataParams(ScrnInfoPtr pScrn, uint8_t *dst, uint32_t pitch, int cpp, 837 uint32_t *dstPitchOff, int *x, int *y) 838{ 839 RADEONInfoPtr info = RADEONPTR( pScrn ); 840 uint32_t dstOffs = dst - (uint8_t*)info->FB + info->fbLocation; 841 842 *dstPitchOff = pitch << 16 | (dstOffs & ~RADEON_BUFFER_ALIGN) >> 10; 843 *y = ( dstOffs & RADEON_BUFFER_ALIGN ) / pitch; 844 *x = ( ( dstOffs & RADEON_BUFFER_ALIGN ) - ( *y * pitch ) ) / cpp; 845} 846 847/* Set up a hostdata blit to transfer data from system memory to the 848 * framebuffer. Returns the address where the data can be written to and sets 849 * the dstPitch and hpass variables as required. 850 */ 851uint8_t* 852RADEONHostDataBlit( 853 ScrnInfoPtr pScrn, 854 unsigned int cpp, 855 unsigned int w, 856 uint32_t dstPitchOff, 857 uint32_t *bufPitch, 858 int x, 859 int *y, 860 unsigned int *h, 861 unsigned int *hpass 862){ 863 RADEONInfoPtr info = RADEONPTR( pScrn ); 864 uint32_t format, dwords; 865 uint8_t *ret; 866 RING_LOCALS; 867 868 if ( *h == 0 ) 869 { 870 return NULL; 871 } 872 873 switch ( cpp ) 874 { 875 case 4: 876 format = RADEON_GMC_DST_32BPP; 877 *bufPitch = 4 * w; 878 break; 879 case 2: 880 format = RADEON_GMC_DST_16BPP; 881 *bufPitch = 2 * RADEON_ALIGN(w, 2); 882 break; 883 case 1: 884 format = RADEON_GMC_DST_8BPP_CI; 885 *bufPitch = RADEON_ALIGN(w, 4); 886 break; 887 default: 888 xf86DrvMsg( pScrn->scrnIndex, X_ERROR, 889 "%s: Unsupported cpp %d!\n", __func__, cpp ); 890 return NULL; 891 } 892 893#if X_BYTE_ORDER == X_BIG_ENDIAN 894 /* Swap doesn't work on R300 and later, it's handled during the 895 * copy to ind. buffer pass 896 */ 897 if (info->ChipFamily < CHIP_FAMILY_R300) { 898 BEGIN_RING(2); 899 if (cpp == 2) 900 OUT_RING_REG(RADEON_RBBM_GUICNTL, 901 RADEON_HOST_DATA_SWAP_HDW); 902 else if (cpp == 1) 903 OUT_RING_REG(RADEON_RBBM_GUICNTL, 904 RADEON_HOST_DATA_SWAP_32BIT); 905 else 906 OUT_RING_REG(RADEON_RBBM_GUICNTL, 907 RADEON_HOST_DATA_SWAP_NONE); 908 ADVANCE_RING(); 909 } 910#endif 911 912 /*RADEON_PURGE_CACHE(); 913 RADEON_WAIT_UNTIL_IDLE();*/ 914 915 *hpass = min( *h, ( ( RADEON_BUFFER_SIZE - 10 * 4 ) / *bufPitch ) ); 916 dwords = *hpass * *bufPitch / 4; 917 918 BEGIN_RING( dwords + 10 ); 919 OUT_RING( CP_PACKET3( RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT, dwords + 10 - 2 ) ); 920 OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL 921 | RADEON_GMC_DST_CLIPPING 922 | RADEON_GMC_BRUSH_NONE 923 | format 924 | RADEON_GMC_SRC_DATATYPE_COLOR 925 | RADEON_ROP3_S 926 | RADEON_DP_SRC_SOURCE_HOST_DATA 927 | RADEON_GMC_CLR_CMP_CNTL_DIS 928 | RADEON_GMC_WR_MSK_DIS ); 929 OUT_RING( dstPitchOff ); 930 OUT_RING( (*y << 16) | x ); 931 OUT_RING( ((*y + *hpass) << 16) | (x + w) ); 932 OUT_RING( 0xffffffff ); 933 OUT_RING( 0xffffffff ); 934 OUT_RING( *y << 16 | x ); 935 OUT_RING( *hpass << 16 | (*bufPitch / cpp) ); 936 OUT_RING( dwords ); 937 938 ret = ( uint8_t* )&__head[__count]; 939 940 __count += dwords; 941 ADVANCE_RING(); 942 943 *y += *hpass; 944 *h -= *hpass; 945 946 return ret; 947} 948 949void RADEONCopySwap(uint8_t *dst, uint8_t *src, unsigned int size, int swap) 950{ 951 switch(swap) { 952 case RADEON_HOST_DATA_SWAP_HDW: 953 { 954 unsigned int *d = (unsigned int *)dst; 955 unsigned int *s = (unsigned int *)src; 956 unsigned int nwords = size >> 2; 957 958 for (; nwords > 0; --nwords, ++d, ++s) 959 *d = ((*s & 0xffff) << 16) | ((*s >> 16) & 0xffff); 960 return; 961 } 962 case RADEON_HOST_DATA_SWAP_32BIT: 963 { 964 unsigned int *d = (unsigned int *)dst; 965 unsigned int *s = (unsigned int *)src; 966 unsigned int nwords = size >> 2; 967 968 for (; nwords > 0; --nwords, ++d, ++s) 969#ifdef __powerpc__ 970 asm volatile("stwbrx %0,0,%1" : : "r" (*s), "r" (d)); 971#else 972 *d = ((*s >> 24) & 0xff) | ((*s >> 8) & 0xff00) 973 | ((*s & 0xff00) << 8) | ((*s & 0xff) << 24); 974#endif 975 return; 976 } 977 case RADEON_HOST_DATA_SWAP_16BIT: 978 { 979 unsigned short *d = (unsigned short *)dst; 980 unsigned short *s = (unsigned short *)src; 981 unsigned int nwords = size >> 1; 982 983 for (; nwords > 0; --nwords, ++d, ++s) 984#ifdef __powerpc__ 985 asm volatile("stwbrx %0,0,%1" : : "r" (*s), "r" (d)); 986#else 987 *d = ((*s >> 24) & 0xff) | ((*s >> 8) & 0xff00) 988 | ((*s & 0xff00) << 8) | ((*s & 0xff) << 24); 989#endif 990 return; 991 } 992 } 993 if (src != dst) 994 memcpy(dst, src, size); 995} 996 997/* Copies a single pass worth of data for a hostdata blit set up by 998 * RADEONHostDataBlit(). 999 */ 1000void 1001RADEONHostDataBlitCopyPass( 1002 ScrnInfoPtr pScrn, 1003 unsigned int cpp, 1004 uint8_t *dst, 1005 uint8_t *src, 1006 unsigned int hpass, 1007 unsigned int dstPitch, 1008 unsigned int srcPitch 1009){ 1010 1011#if X_BYTE_ORDER == X_BIG_ENDIAN 1012 RADEONInfoPtr info = RADEONPTR( pScrn ); 1013#endif 1014 1015 /* RADEONHostDataBlitCopy can return NULL ! */ 1016 if( (dst==NULL) || (src==NULL)) return; 1017 1018 if ( dstPitch == srcPitch ) 1019 { 1020#if X_BYTE_ORDER == X_BIG_ENDIAN 1021 if (info->ChipFamily >= CHIP_FAMILY_R300) { 1022 switch(cpp) { 1023 case 1: 1024 RADEONCopySwap(dst, src, hpass * dstPitch, 1025 RADEON_HOST_DATA_SWAP_32BIT); 1026 return; 1027 case 2: 1028 RADEONCopySwap(dst, src, hpass * dstPitch, 1029 RADEON_HOST_DATA_SWAP_HDW); 1030 return; 1031 } 1032 } 1033#endif 1034 memcpy( dst, src, hpass * dstPitch ); 1035 } 1036 else 1037 { 1038 unsigned int minPitch = min( dstPitch, srcPitch ); 1039 while ( hpass-- ) 1040 { 1041#if X_BYTE_ORDER == X_BIG_ENDIAN 1042 if (info->ChipFamily >= CHIP_FAMILY_R300) { 1043 switch(cpp) { 1044 case 1: 1045 RADEONCopySwap(dst, src, minPitch, 1046 RADEON_HOST_DATA_SWAP_32BIT); 1047 goto next; 1048 case 2: 1049 RADEONCopySwap(dst, src, minPitch, 1050 RADEON_HOST_DATA_SWAP_HDW); 1051 goto next; 1052 } 1053 } 1054#endif 1055 memcpy( dst, src, minPitch ); 1056#if X_BYTE_ORDER == X_BIG_ENDIAN 1057 next: 1058#endif 1059 src += srcPitch; 1060 dst += dstPitch; 1061 } 1062 } 1063} 1064 1065#endif 1066 1067Bool RADEONAccelInit(ScreenPtr pScreen) 1068{ 1069 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1070 RADEONInfoPtr info = RADEONPTR(pScrn); 1071 1072#ifdef USE_EXA 1073 if (info->useEXA) { 1074# ifdef XF86DRI 1075 if (info->directRenderingEnabled) { 1076#ifdef XF86DRM_MODE 1077 if (info->ChipFamily >= CHIP_FAMILY_CEDAR) { 1078 if (!EVERGREENDrawInit(pScreen)) 1079 return FALSE; 1080 } else 1081#endif 1082 if (info->ChipFamily >= CHIP_FAMILY_R600) { 1083 if (!R600DrawInit(pScreen)) 1084 return FALSE; 1085 } else { 1086 if (!RADEONDrawInitCP(pScreen)) 1087 return FALSE; 1088 } 1089 } else 1090# endif /* XF86DRI */ 1091 { 1092 if (info->ChipFamily >= CHIP_FAMILY_R600) 1093 return FALSE; 1094 else { 1095 if (!RADEONDrawInitMMIO(pScreen)) 1096 return FALSE; 1097 } 1098 } 1099 } 1100#endif /* USE_EXA */ 1101#ifdef USE_XAA 1102 if (!info->useEXA) { 1103 XAAInfoRecPtr a; 1104 1105 if (info->ChipFamily >= CHIP_FAMILY_R600) 1106 return FALSE; 1107 1108 if (!(a = info->accel_state->accel = XAACreateInfoRec())) { 1109 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAACreateInfoRec Error\n"); 1110 return FALSE; 1111 } 1112 1113#ifdef XF86DRI 1114 if (info->directRenderingEnabled) 1115 RADEONAccelInitCP(pScreen, a); 1116 else 1117#endif /* XF86DRI */ 1118 RADEONAccelInitMMIO(pScreen, a); 1119 1120 RADEONEngineInit(pScrn); 1121 1122 if (!XAAInit(pScreen, a)) { 1123 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAAInit Error\n"); 1124 return FALSE; 1125 } 1126 } 1127#endif /* USE_XAA */ 1128 return TRUE; 1129} 1130 1131void RADEONInit3DEngine(ScrnInfoPtr pScrn) 1132{ 1133 RADEONInfoPtr info = RADEONPTR (pScrn); 1134 1135#ifdef XF86DRI 1136 if (info->directRenderingEnabled) { 1137 drm_radeon_sarea_t *pSAREAPriv; 1138 1139 if (!info->kms_enabled) { 1140 pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); 1141 pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen); 1142 } 1143 RADEONInit3DEngineCP(pScrn); 1144 } else 1145#endif 1146 RADEONInit3DEngineMMIO(pScrn); 1147 1148 info->accel_state->XInited3D = TRUE; 1149} 1150 1151#ifdef USE_XAA 1152#ifdef XF86DRI 1153Bool 1154RADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen) 1155{ 1156 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1157 RADEONInfoPtr info = RADEONPTR(pScrn); 1158 int cpp = info->CurrentLayout.pixel_bytes; 1159 int depthCpp = (info->dri->depthBits - 8) / 4; 1160 int width_bytes = pScrn->displayWidth * cpp; 1161 int bufferSize; 1162 int depthSize; 1163 int l; 1164 int scanlines; 1165 int texsizerequest; 1166 BoxRec MemBox; 1167 FBAreaPtr fbarea; 1168 1169 info->dri->frontOffset = 0; 1170 info->dri->frontPitch = pScrn->displayWidth; 1171 info->dri->backPitch = pScrn->displayWidth; 1172 1173 /* make sure we use 16 line alignment for tiling (8 might be enough). 1174 * Might need that for non-XF86DRI too? 1175 */ 1176 if (info->allowColorTiling) { 1177 bufferSize = RADEON_ALIGN((RADEON_ALIGN(pScrn->virtualY, 16)) * width_bytes, 1178 RADEON_GPU_PAGE_SIZE); 1179 } else { 1180 bufferSize = RADEON_ALIGN(pScrn->virtualY * width_bytes, 1181 RADEON_GPU_PAGE_SIZE); 1182 } 1183 1184 /* Due to tiling, the Z buffer pitch must be a multiple of 32 pixels, 1185 * which is always the case if color tiling is used due to color pitch 1186 * but not necessarily otherwise, and its height a multiple of 16 lines. 1187 */ 1188 info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); 1189 depthSize = RADEON_ALIGN((RADEON_ALIGN(pScrn->virtualY, 16)) * info->dri->depthPitch 1190 * depthCpp, RADEON_GPU_PAGE_SIZE); 1191 1192 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1193 "Using %d MB GART aperture\n", info->dri->gartSize); 1194 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1195 "Using %d MB for the ring buffer\n", info->dri->ringSize); 1196 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1197 "Using %d MB for vertex/indirect buffers\n", info->dri->bufSize); 1198 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1199 "Using %d MB for GART textures\n", info->dri->gartTexSize); 1200 1201 /* Try for front, back, depth, and three framebuffers worth of 1202 * pixmap cache. Should be enough for a fullscreen background 1203 * image plus some leftovers. 1204 * If the FBTexPercent option was used, try to achieve that percentage instead, 1205 * but still have at least one pixmap buffer (get problems with xvideo/render 1206 * otherwise probably), and never reserve more than 3 offscreen buffers as it's 1207 * probably useless for XAA. 1208 */ 1209 if (info->dri->textureSize >= 0) { 1210 texsizerequest = ((int)info->FbMapSize - 2 * bufferSize - depthSize 1211 - 2 * width_bytes - 16384 - info->FbSecureSize) 1212 /* first divide, then multiply or we'll get an overflow (been there...) */ 1213 / 100 * info->dri->textureSize; 1214 } 1215 else { 1216 texsizerequest = (int)info->FbMapSize / 2; 1217 } 1218 info->dri->textureSize = info->FbMapSize - info->FbSecureSize - 5 * bufferSize - depthSize; 1219 1220 /* If that gives us less than the requested memory, let's 1221 * be greedy and grab some more. Sorry, I care more about 3D 1222 * performance than playing nicely, and you'll get around a full 1223 * framebuffer's worth of pixmap cache anyway. 1224 */ 1225 if (info->dri->textureSize < texsizerequest) { 1226 info->dri->textureSize = info->FbMapSize - 4 * bufferSize - depthSize; 1227 } 1228 if (info->dri->textureSize < texsizerequest) { 1229 info->dri->textureSize = info->FbMapSize - 3 * bufferSize - depthSize; 1230 } 1231 1232 /* If there's still no space for textures, try without pixmap cache, but 1233 * never use the reserved space, the space hw cursor and PCIGART table might 1234 * use. 1235 */ 1236 if (info->dri->textureSize < 0) { 1237 info->dri->textureSize = info->FbMapSize - 2 * bufferSize - depthSize 1238 - 2 * width_bytes - 16384 - info->FbSecureSize; 1239 } 1240 1241 /* Check to see if there is more room available after the 8192nd 1242 * scanline for textures 1243 */ 1244 /* FIXME: what's this good for? condition is pretty much impossible to meet */ 1245 if ((int)info->FbMapSize - 8192*width_bytes - bufferSize - depthSize 1246 > info->dri->textureSize) { 1247 info->dri->textureSize = 1248 info->FbMapSize - 8192*width_bytes - bufferSize - depthSize; 1249 } 1250 1251 /* If backbuffer is disabled, don't allocate memory for it */ 1252 if (info->dri->noBackBuffer) { 1253 info->dri->textureSize += bufferSize; 1254 } 1255 1256 /* RADEON_BUFFER_ALIGN is not sufficient for backbuffer! 1257 At least for pageflip + color tiling, need to make sure it's 16 scanlines aligned, 1258 otherwise the copy-from-front-to-back will fail (width_bytes * 16 will also guarantee 1259 it's still 4kb aligned for tiled case). Need to round up offset (might get into cursor 1260 area otherwise). 1261 This might cause some space at the end of the video memory to be unused, since it 1262 can't be used (?) due to that log_tex_granularity thing??? 1263 Could use different copyscreentoscreen function for the pageflip copies 1264 (which would use different src and dst offsets) to avoid this. */ 1265 if (info->allowColorTiling && !info->dri->noBackBuffer) { 1266 info->dri->textureSize = info->FbMapSize - ((info->FbMapSize - info->dri->textureSize + 1267 width_bytes * 16 - 1) / (width_bytes * 16)) * (width_bytes * 16); 1268 } 1269 if (info->dri->textureSize > 0) { 1270 l = RADEONMinBits((info->dri->textureSize-1) / RADEON_NR_TEX_REGIONS); 1271 if (l < RADEON_LOG_TEX_GRANULARITY) 1272 l = RADEON_LOG_TEX_GRANULARITY; 1273 /* Round the texture size up to the nearest whole number of 1274 * texture regions. Again, be greedy about this, don't 1275 * round down. 1276 */ 1277 info->dri->log2TexGran = l; 1278 info->dri->textureSize = (info->dri->textureSize >> l) << l; 1279 } else { 1280 info->dri->textureSize = 0; 1281 } 1282 1283 /* Set a minimum usable local texture heap size. This will fit 1284 * two 256x256x32bpp textures. 1285 */ 1286 if (info->dri->textureSize < 512 * 1024) { 1287 info->dri->textureOffset = 0; 1288 info->dri->textureSize = 0; 1289 } 1290 1291 if (info->allowColorTiling && !info->dri->noBackBuffer) { 1292 info->dri->textureOffset = ((info->FbMapSize - info->dri->textureSize) / 1293 (width_bytes * 16)) * (width_bytes * 16); 1294 } 1295 else { 1296 /* Reserve space for textures */ 1297 info->dri->textureOffset = RADEON_ALIGN(info->FbMapSize - info->dri->textureSize, 1298 RADEON_GPU_PAGE_SIZE); 1299 } 1300 1301 /* Reserve space for the shared depth 1302 * buffer. 1303 */ 1304 info->dri->depthOffset = RADEON_ALIGN(info->dri->textureOffset - depthSize, 1305 RADEON_GPU_PAGE_SIZE); 1306 1307 /* Reserve space for the shared back buffer */ 1308 if (info->dri->noBackBuffer) { 1309 info->dri->backOffset = info->dri->depthOffset; 1310 } else { 1311 info->dri->backOffset = RADEON_ALIGN(info->dri->depthOffset - bufferSize, 1312 RADEON_GPU_PAGE_SIZE); 1313 } 1314 1315 info->dri->backY = info->dri->backOffset / width_bytes; 1316 info->dri->backX = (info->dri->backOffset - (info->dri->backY * width_bytes)) / cpp; 1317 1318 scanlines = (info->FbMapSize-info->FbSecureSize) / width_bytes; 1319 if (scanlines > 8191) 1320 scanlines = 8191; 1321 1322 MemBox.x1 = 0; 1323 MemBox.y1 = 0; 1324 MemBox.x2 = pScrn->displayWidth; 1325 MemBox.y2 = scanlines; 1326 1327 if (!xf86InitFBManager(pScreen, &MemBox)) { 1328 xf86DrvMsg(scrnIndex, X_ERROR, 1329 "Memory manager initialization to " 1330 "(%d,%d) (%d,%d) failed\n", 1331 MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 1332 return FALSE; 1333 } else { 1334 int width, height; 1335 1336 xf86DrvMsg(scrnIndex, X_INFO, 1337 "Memory manager initialized to (%d,%d) (%d,%d)\n", 1338 MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 1339 /* why oh why can't we just request modes which are guaranteed to be 16 lines 1340 aligned... sigh */ 1341 if ((fbarea = xf86AllocateOffscreenArea(pScreen, 1342 pScrn->displayWidth, 1343 info->allowColorTiling ? 1344 (RADEON_ALIGN(pScrn->virtualY, 16)) 1345 - pScrn->virtualY + 2 : 2, 1346 0, NULL, NULL, 1347 NULL))) { 1348 xf86DrvMsg(scrnIndex, X_INFO, 1349 "Reserved area from (%d,%d) to (%d,%d)\n", 1350 fbarea->box.x1, fbarea->box.y1, 1351 fbarea->box.x2, fbarea->box.y2); 1352 } else { 1353 xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); 1354 } 1355 1356 RADEONDRIAllocatePCIGARTTable(pScreen); 1357 1358 if (xf86QueryLargestOffscreenArea(pScreen, &width, 1359 &height, 0, 0, 0)) { 1360 xf86DrvMsg(scrnIndex, X_INFO, 1361 "Largest offscreen area available: %d x %d\n", 1362 width, height); 1363 1364 /* Lines in offscreen area needed for depth buffer and 1365 * textures 1366 */ 1367 info->dri->depthTexLines = (scanlines 1368 - info->dri->depthOffset / width_bytes); 1369 info->dri->backLines = (scanlines 1370 - info->dri->backOffset / width_bytes 1371 - info->dri->depthTexLines); 1372 info->dri->backArea = NULL; 1373 } else { 1374 xf86DrvMsg(scrnIndex, X_ERROR, 1375 "Unable to determine largest offscreen area " 1376 "available\n"); 1377 return FALSE; 1378 } 1379 } 1380 1381 xf86DrvMsg(scrnIndex, X_INFO, 1382 "Will use front buffer at offset 0x%x\n", 1383 info->dri->frontOffset); 1384 1385 xf86DrvMsg(scrnIndex, X_INFO, 1386 "Will use back buffer at offset 0x%x\n", 1387 info->dri->backOffset); 1388 xf86DrvMsg(scrnIndex, X_INFO, 1389 "Will use depth buffer at offset 0x%x\n", 1390 info->dri->depthOffset); 1391 if (info->cardType==CARD_PCIE) 1392 xf86DrvMsg(scrnIndex, X_INFO, 1393 "Will use %d kb for PCI GART table at offset 0x%x\n", 1394 info->dri->pciGartSize/1024, (unsigned)info->dri->pciGartOffset); 1395 xf86DrvMsg(scrnIndex, X_INFO, 1396 "Will use %d kb for textures at offset 0x%x\n", 1397 info->dri->textureSize/1024, info->dri->textureOffset); 1398 1399 info->dri->frontPitchOffset = (((info->dri->frontPitch * cpp / 64) << 22) | 1400 ((info->dri->frontOffset + info->fbLocation) >> 10)); 1401 1402 info->dri->backPitchOffset = (((info->dri->backPitch * cpp / 64) << 22) | 1403 ((info->dri->backOffset + info->fbLocation) >> 10)); 1404 1405 info->dri->depthPitchOffset = (((info->dri->depthPitch * depthCpp / 64) << 22) | 1406 ((info->dri->depthOffset + info->fbLocation) >> 10)); 1407 return TRUE; 1408} 1409#endif /* XF86DRI */ 1410 1411Bool 1412RADEONSetupMemXAA(int scrnIndex, ScreenPtr pScreen) 1413{ 1414 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1415 RADEONInfoPtr info = RADEONPTR(pScrn); 1416 BoxRec MemBox; 1417 int y2; 1418 1419 int width_bytes = pScrn->displayWidth * info->CurrentLayout.pixel_bytes; 1420 1421 MemBox.x1 = 0; 1422 MemBox.y1 = 0; 1423 MemBox.x2 = pScrn->displayWidth; 1424 y2 = info->FbMapSize / width_bytes; 1425 if (y2 >= 32768) 1426 y2 = 32767; /* because MemBox.y2 is signed short */ 1427 MemBox.y2 = y2; 1428 1429 /* The acceleration engine uses 14 bit 1430 * signed coordinates, so we can't have any 1431 * drawable caches beyond this region. 1432 */ 1433 if (MemBox.y2 > 8191) 1434 MemBox.y2 = 8191; 1435 1436 if (!xf86InitFBManager(pScreen, &MemBox)) { 1437 xf86DrvMsg(scrnIndex, X_ERROR, 1438 "Memory manager initialization to " 1439 "(%d,%d) (%d,%d) failed\n", 1440 MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 1441 return FALSE; 1442 } else { 1443 int width, height; 1444 FBAreaPtr fbarea; 1445 1446 xf86DrvMsg(scrnIndex, X_INFO, 1447 "Memory manager initialized to (%d,%d) (%d,%d)\n", 1448 MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2); 1449 if ((fbarea = xf86AllocateOffscreenArea(pScreen, 1450 pScrn->displayWidth, 1451 info->allowColorTiling ? 1452 (RADEON_ALIGN(pScrn->virtualY, 16)) 1453 - pScrn->virtualY + 2 : 2, 1454 0, NULL, NULL, 1455 NULL))) { 1456 xf86DrvMsg(scrnIndex, X_INFO, 1457 "Reserved area from (%d,%d) to (%d,%d)\n", 1458 fbarea->box.x1, fbarea->box.y1, 1459 fbarea->box.x2, fbarea->box.y2); 1460 } else { 1461 xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n"); 1462 } 1463 if (xf86QueryLargestOffscreenArea(pScreen, &width, &height, 1464 0, 0, 0)) { 1465 xf86DrvMsg(scrnIndex, X_INFO, 1466 "Largest offscreen area available: %d x %d\n", 1467 width, height); 1468 } 1469 return TRUE; 1470 } 1471} 1472#endif /* USE_XAA */ 1473