radeon_accel.c revision 209ff23f
1209ff23fSmrg/*
2209ff23fSmrg * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
3209ff23fSmrg *                VA Linux Systems Inc., Fremont, California.
4209ff23fSmrg *
5209ff23fSmrg * All Rights Reserved.
6209ff23fSmrg *
7209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining
8209ff23fSmrg * a copy of this software and associated documentation files (the
9209ff23fSmrg * "Software"), to deal in the Software without restriction, including
10209ff23fSmrg * without limitation on the rights to use, copy, modify, merge,
11209ff23fSmrg * publish, distribute, sublicense, and/or sell copies of the Software,
12209ff23fSmrg * and to permit persons to whom the Software is furnished to do so,
13209ff23fSmrg * subject to the following conditions:
14209ff23fSmrg *
15209ff23fSmrg * The above copyright notice and this permission notice (including the
16209ff23fSmrg * next paragraph) shall be included in all copies or substantial
17209ff23fSmrg * portions of the Software.
18209ff23fSmrg *
19209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20209ff23fSmrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21209ff23fSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22209ff23fSmrg * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
23209ff23fSmrg * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24209ff23fSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25209ff23fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26209ff23fSmrg * DEALINGS IN THE SOFTWARE.
27209ff23fSmrg */
28209ff23fSmrg
29209ff23fSmrg#ifdef HAVE_CONFIG_H
30209ff23fSmrg#include "config.h"
31209ff23fSmrg#endif
32209ff23fSmrg
33209ff23fSmrg/*
34209ff23fSmrg * Authors:
35209ff23fSmrg *   Kevin E. Martin <martin@xfree86.org>
36209ff23fSmrg *   Rickard E. Faith <faith@valinux.com>
37209ff23fSmrg *   Alan Hourihane <alanh@fairlite.demon.co.uk>
38209ff23fSmrg *
39209ff23fSmrg * Credits:
40209ff23fSmrg *
41209ff23fSmrg *   Thanks to Ani Joshi <ajoshi@shell.unixbox.com> for providing source
42209ff23fSmrg *   code to his Radeon driver.  Portions of this file are based on the
43209ff23fSmrg *   initialization code for that driver.
44209ff23fSmrg *
45209ff23fSmrg * References:
46209ff23fSmrg *
47209ff23fSmrg * !!!! FIXME !!!!
48209ff23fSmrg *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
49209ff23fSmrg *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
50209ff23fSmrg *   1999.
51209ff23fSmrg *
52209ff23fSmrg *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
53209ff23fSmrg *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
54209ff23fSmrg *
55209ff23fSmrg * Notes on unimplemented XAA optimizations:
56209ff23fSmrg *
57209ff23fSmrg *   SetClipping:   This has been removed as XAA expects 16bit registers
58209ff23fSmrg *                  for full clipping.
59209ff23fSmrg *   TwoPointLine:  The Radeon supports this. Not Bresenham.
60209ff23fSmrg *   DashedLine with non-power-of-two pattern length: Apparently, there is
61209ff23fSmrg *                  no way to set the length of the pattern -- it is always
62209ff23fSmrg *                  assumed to be 8 or 32 (or 1024?).
63209ff23fSmrg *   ScreenToScreenColorExpandFill: See p. 4-17 of the Technical Reference
64209ff23fSmrg *                  Manual where it states that monochrome expansion of frame
65209ff23fSmrg *                  buffer data is not supported.
66209ff23fSmrg *   CPUToScreenColorExpandFill, direct: The implementation here uses a hybrid
67209ff23fSmrg *                  direct/indirect method.  If we had more data registers,
68209ff23fSmrg *                  then we could do better.  If XAA supported a trigger write
69209ff23fSmrg *                  address, the code would be simpler.
70209ff23fSmrg *   Color8x8PatternFill: Apparently, an 8x8 color brush cannot take an 8x8
71209ff23fSmrg *                  pattern from frame buffer memory.
72209ff23fSmrg *   ImageWrites:   Same as CPUToScreenColorExpandFill
73209ff23fSmrg *
74209ff23fSmrg */
75209ff23fSmrg
76209ff23fSmrg#include <errno.h>
77209ff23fSmrg#include <string.h>
78209ff23fSmrg				/* Driver data structures */
79209ff23fSmrg#include "radeon.h"
80209ff23fSmrg#include "radeon_reg.h"
81209ff23fSmrg#include "radeon_macros.h"
82209ff23fSmrg#include "radeon_probe.h"
83209ff23fSmrg#include "radeon_version.h"
84209ff23fSmrg#ifdef XF86DRI
85209ff23fSmrg#define _XF86DRI_SERVER_
86209ff23fSmrg#include "radeon_dri.h"
87209ff23fSmrg#include "radeon_common.h"
88209ff23fSmrg#include "radeon_sarea.h"
89209ff23fSmrg#endif
90209ff23fSmrg
91209ff23fSmrg				/* Line support */
92209ff23fSmrg#include "miline.h"
93209ff23fSmrg
94209ff23fSmrg				/* X and server generic header files */
95209ff23fSmrg#include "xf86.h"
96209ff23fSmrg
97209ff23fSmrg
98209ff23fSmrg#ifdef USE_XAA
99209ff23fSmrgstatic struct {
100209ff23fSmrg    int rop;
101209ff23fSmrg    int pattern;
102209ff23fSmrg} RADEON_ROP[] = {
103209ff23fSmrg    { RADEON_ROP3_ZERO, RADEON_ROP3_ZERO }, /* GXclear        */
104209ff23fSmrg    { RADEON_ROP3_DSa,  RADEON_ROP3_DPa  }, /* Gxand          */
105209ff23fSmrg    { RADEON_ROP3_SDna, RADEON_ROP3_PDna }, /* GXandReverse   */
106209ff23fSmrg    { RADEON_ROP3_S,    RADEON_ROP3_P    }, /* GXcopy         */
107209ff23fSmrg    { RADEON_ROP3_DSna, RADEON_ROP3_DPna }, /* GXandInverted  */
108209ff23fSmrg    { RADEON_ROP3_D,    RADEON_ROP3_D    }, /* GXnoop         */
109209ff23fSmrg    { RADEON_ROP3_DSx,  RADEON_ROP3_DPx  }, /* GXxor          */
110209ff23fSmrg    { RADEON_ROP3_DSo,  RADEON_ROP3_DPo  }, /* GXor           */
111209ff23fSmrg    { RADEON_ROP3_DSon, RADEON_ROP3_DPon }, /* GXnor          */
112209ff23fSmrg    { RADEON_ROP3_DSxn, RADEON_ROP3_PDxn }, /* GXequiv        */
113209ff23fSmrg    { RADEON_ROP3_Dn,   RADEON_ROP3_Dn   }, /* GXinvert       */
114209ff23fSmrg    { RADEON_ROP3_SDno, RADEON_ROP3_PDno }, /* GXorReverse    */
115209ff23fSmrg    { RADEON_ROP3_Sn,   RADEON_ROP3_Pn   }, /* GXcopyInverted */
116209ff23fSmrg    { RADEON_ROP3_DSno, RADEON_ROP3_DPno }, /* GXorInverted   */
117209ff23fSmrg    { RADEON_ROP3_DSan, RADEON_ROP3_DPan }, /* GXnand         */
118209ff23fSmrg    { RADEON_ROP3_ONE,  RADEON_ROP3_ONE  }  /* GXset          */
119209ff23fSmrg};
120209ff23fSmrg#endif
121209ff23fSmrg
122209ff23fSmrg/* The FIFO has 64 slots.  This routines waits until at least `entries'
123209ff23fSmrg * of these slots are empty.
124209ff23fSmrg */
125209ff23fSmrgvoid RADEONWaitForFifoFunction(ScrnInfoPtr pScrn, int entries)
126209ff23fSmrg{
127209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
128209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
129209ff23fSmrg    int            i;
130209ff23fSmrg
131209ff23fSmrg    for (;;) {
132209ff23fSmrg	for (i = 0; i < RADEON_TIMEOUT; i++) {
133209ff23fSmrg	    info->fifo_slots =
134209ff23fSmrg		INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK;
135209ff23fSmrg	    if (info->fifo_slots >= entries) return;
136209ff23fSmrg	}
137209ff23fSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
138209ff23fSmrg		       "FIFO timed out: %u entries, stat=0x%08x\n",
139209ff23fSmrg		       (unsigned int)INREG(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK,
140209ff23fSmrg		       (unsigned int)INREG(RADEON_RBBM_STATUS));
141209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
142209ff23fSmrg		   "FIFO timed out, resetting engine...\n");
143209ff23fSmrg	RADEONEngineReset(pScrn);
144209ff23fSmrg	RADEONEngineRestore(pScrn);
145209ff23fSmrg#ifdef XF86DRI
146209ff23fSmrg	if (info->directRenderingEnabled) {
147209ff23fSmrg	    RADEONCP_RESET(pScrn, info);
148209ff23fSmrg	    RADEONCP_START(pScrn, info);
149209ff23fSmrg	}
150209ff23fSmrg#endif
151209ff23fSmrg    }
152209ff23fSmrg}
153209ff23fSmrg
154209ff23fSmrg/* Flush all dirty data in the Pixel Cache to memory */
155209ff23fSmrgvoid RADEONEngineFlush(ScrnInfoPtr pScrn)
156209ff23fSmrg{
157209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
158209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
159209ff23fSmrg    int            i;
160209ff23fSmrg
161209ff23fSmrg    if (info->ChipFamily <= CHIP_FAMILY_RV280) {
162209ff23fSmrg	OUTREGP(RADEON_RB3D_DSTCACHE_CTLSTAT,
163209ff23fSmrg		RADEON_RB3D_DC_FLUSH_ALL,
164209ff23fSmrg		~RADEON_RB3D_DC_FLUSH_ALL);
165209ff23fSmrg	for (i = 0; i < RADEON_TIMEOUT; i++) {
166209ff23fSmrg	    if (!(INREG(RADEON_RB3D_DSTCACHE_CTLSTAT) & RADEON_RB3D_DC_BUSY))
167209ff23fSmrg		break;
168209ff23fSmrg	}
169209ff23fSmrg	if (i == RADEON_TIMEOUT) {
170209ff23fSmrg	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
171209ff23fSmrg			   "DC flush timeout: %x\n",
172209ff23fSmrg			   (unsigned int)INREG(RADEON_RB3D_DSTCACHE_CTLSTAT));
173209ff23fSmrg	}
174209ff23fSmrg    } else {
175209ff23fSmrg	OUTREGP(R300_DSTCACHE_CTLSTAT,
176209ff23fSmrg		R300_RB2D_DC_FLUSH_ALL,
177209ff23fSmrg		~R300_RB2D_DC_FLUSH_ALL);
178209ff23fSmrg	for (i = 0; i < RADEON_TIMEOUT; i++) {
179209ff23fSmrg	    if (!(INREG(R300_DSTCACHE_CTLSTAT) & R300_RB2D_DC_BUSY))
180209ff23fSmrg		break;
181209ff23fSmrg	}
182209ff23fSmrg	if (i == RADEON_TIMEOUT) {
183209ff23fSmrg	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
184209ff23fSmrg			   "DC flush timeout: %x\n",
185209ff23fSmrg			   (unsigned int)INREG(R300_DSTCACHE_CTLSTAT));
186209ff23fSmrg	}
187209ff23fSmrg    }
188209ff23fSmrg}
189209ff23fSmrg
190209ff23fSmrg/* Reset graphics card to known state */
191209ff23fSmrgvoid RADEONEngineReset(ScrnInfoPtr pScrn)
192209ff23fSmrg{
193209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
194209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
195209ff23fSmrg    uint32_t       clock_cntl_index;
196209ff23fSmrg    uint32_t       mclk_cntl;
197209ff23fSmrg    uint32_t       rbbm_soft_reset;
198209ff23fSmrg    uint32_t       host_path_cntl;
199209ff23fSmrg
200209ff23fSmrg    /* The following RBBM_SOFT_RESET sequence can help un-wedge
201209ff23fSmrg     * an R300 after the command processor got stuck.
202209ff23fSmrg     */
203209ff23fSmrg    rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET);
204209ff23fSmrg    OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
205209ff23fSmrg                                   RADEON_SOFT_RESET_CP |
206209ff23fSmrg                                   RADEON_SOFT_RESET_HI |
207209ff23fSmrg                                   RADEON_SOFT_RESET_SE |
208209ff23fSmrg                                   RADEON_SOFT_RESET_RE |
209209ff23fSmrg                                   RADEON_SOFT_RESET_PP |
210209ff23fSmrg                                   RADEON_SOFT_RESET_E2 |
211209ff23fSmrg                                   RADEON_SOFT_RESET_RB));
212209ff23fSmrg    INREG(RADEON_RBBM_SOFT_RESET);
213209ff23fSmrg    OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & (uint32_t)
214209ff23fSmrg                                   ~(RADEON_SOFT_RESET_CP |
215209ff23fSmrg                                     RADEON_SOFT_RESET_HI |
216209ff23fSmrg                                     RADEON_SOFT_RESET_SE |
217209ff23fSmrg                                     RADEON_SOFT_RESET_RE |
218209ff23fSmrg                                     RADEON_SOFT_RESET_PP |
219209ff23fSmrg                                     RADEON_SOFT_RESET_E2 |
220209ff23fSmrg                                     RADEON_SOFT_RESET_RB)));
221209ff23fSmrg    INREG(RADEON_RBBM_SOFT_RESET);
222209ff23fSmrg    OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
223209ff23fSmrg    INREG(RADEON_RBBM_SOFT_RESET);
224209ff23fSmrg
225209ff23fSmrg    RADEONEngineFlush(pScrn);
226209ff23fSmrg
227209ff23fSmrg    clock_cntl_index = INREG(RADEON_CLOCK_CNTL_INDEX);
228209ff23fSmrg    RADEONPllErrataAfterIndex(info);
229209ff23fSmrg
230209ff23fSmrg#if 0 /* taken care of by new PM code */
231209ff23fSmrg    /* Some ASICs have bugs with dynamic-on feature, which are
232209ff23fSmrg     * ASIC-version dependent, so we force all blocks on for now
233209ff23fSmrg     */
234209ff23fSmrg    if (info->HasCRTC2) {
235209ff23fSmrg	uint32_t tmp;
236209ff23fSmrg
237209ff23fSmrg	tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
238209ff23fSmrg	OUTPLL(RADEON_SCLK_CNTL, ((tmp & ~RADEON_DYN_STOP_LAT_MASK) |
239209ff23fSmrg				  RADEON_CP_MAX_DYN_STOP_LAT |
240209ff23fSmrg				  RADEON_SCLK_FORCEON_MASK));
241209ff23fSmrg
242209ff23fSmrg	if (info->ChipFamily == CHIP_FAMILY_RV200) {
243209ff23fSmrg	    tmp = INPLL(pScrn, RADEON_SCLK_MORE_CNTL);
244209ff23fSmrg	    OUTPLL(RADEON_SCLK_MORE_CNTL, tmp | RADEON_SCLK_MORE_FORCEON);
245209ff23fSmrg	}
246209ff23fSmrg    }
247209ff23fSmrg#endif /* new PM code */
248209ff23fSmrg
249209ff23fSmrg    mclk_cntl = INPLL(pScrn, RADEON_MCLK_CNTL);
250209ff23fSmrg
251209ff23fSmrg#if 0 /* handled by new PM code */
252209ff23fSmrg    OUTPLL(RADEON_MCLK_CNTL, (mclk_cntl |
253209ff23fSmrg			      RADEON_FORCEON_MCLKA |
254209ff23fSmrg			      RADEON_FORCEON_MCLKB |
255209ff23fSmrg			      RADEON_FORCEON_YCLKA |
256209ff23fSmrg			      RADEON_FORCEON_YCLKB |
257209ff23fSmrg			      RADEON_FORCEON_MC |
258209ff23fSmrg			      RADEON_FORCEON_AIC));
259209ff23fSmrg#endif /* new PM code */
260209ff23fSmrg
261209ff23fSmrg    /* Soft resetting HDP thru RBBM_SOFT_RESET register can cause some
262209ff23fSmrg     * unexpected behaviour on some machines.  Here we use
263209ff23fSmrg     * RADEON_HOST_PATH_CNTL to reset it.
264209ff23fSmrg     */
265209ff23fSmrg    host_path_cntl = INREG(RADEON_HOST_PATH_CNTL);
266209ff23fSmrg    rbbm_soft_reset = INREG(RADEON_RBBM_SOFT_RESET);
267209ff23fSmrg
268209ff23fSmrg    if (IS_R300_VARIANT || IS_AVIVO_VARIANT) {
269209ff23fSmrg	uint32_t tmp;
270209ff23fSmrg
271209ff23fSmrg	OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
272209ff23fSmrg					RADEON_SOFT_RESET_CP |
273209ff23fSmrg					RADEON_SOFT_RESET_HI |
274209ff23fSmrg					RADEON_SOFT_RESET_E2));
275209ff23fSmrg	INREG(RADEON_RBBM_SOFT_RESET);
276209ff23fSmrg	OUTREG(RADEON_RBBM_SOFT_RESET, 0);
277209ff23fSmrg	tmp = INREG(RADEON_RB3D_DSTCACHE_MODE);
278209ff23fSmrg	OUTREG(RADEON_RB3D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */
279209ff23fSmrg    } else {
280209ff23fSmrg	OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset |
281209ff23fSmrg					RADEON_SOFT_RESET_CP |
282209ff23fSmrg					RADEON_SOFT_RESET_SE |
283209ff23fSmrg					RADEON_SOFT_RESET_RE |
284209ff23fSmrg					RADEON_SOFT_RESET_PP |
285209ff23fSmrg					RADEON_SOFT_RESET_E2 |
286209ff23fSmrg					RADEON_SOFT_RESET_RB));
287209ff23fSmrg	INREG(RADEON_RBBM_SOFT_RESET);
288209ff23fSmrg	OUTREG(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & (uint32_t)
289209ff23fSmrg					~(RADEON_SOFT_RESET_CP |
290209ff23fSmrg					  RADEON_SOFT_RESET_SE |
291209ff23fSmrg					  RADEON_SOFT_RESET_RE |
292209ff23fSmrg					  RADEON_SOFT_RESET_PP |
293209ff23fSmrg					  RADEON_SOFT_RESET_E2 |
294209ff23fSmrg					  RADEON_SOFT_RESET_RB)));
295209ff23fSmrg	INREG(RADEON_RBBM_SOFT_RESET);
296209ff23fSmrg    }
297209ff23fSmrg
298209ff23fSmrg    OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET);
299209ff23fSmrg    INREG(RADEON_HOST_PATH_CNTL);
300209ff23fSmrg    OUTREG(RADEON_HOST_PATH_CNTL, host_path_cntl);
301209ff23fSmrg
302209ff23fSmrg    if (!IS_R300_VARIANT && !IS_AVIVO_VARIANT)
303209ff23fSmrg	OUTREG(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);
304209ff23fSmrg
305209ff23fSmrg    OUTREG(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);
306209ff23fSmrg    RADEONPllErrataAfterIndex(info);
307209ff23fSmrg    OUTPLL(pScrn, RADEON_MCLK_CNTL, mclk_cntl);
308209ff23fSmrg}
309209ff23fSmrg
310209ff23fSmrg/* Restore the acceleration hardware to its previous state */
311209ff23fSmrgvoid RADEONEngineRestore(ScrnInfoPtr pScrn)
312209ff23fSmrg{
313209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
314209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
315209ff23fSmrg
316209ff23fSmrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
317209ff23fSmrg		   "EngineRestore (%d/%d)\n",
318209ff23fSmrg		   info->CurrentLayout.pixel_code,
319209ff23fSmrg		   info->CurrentLayout.bitsPerPixel);
320209ff23fSmrg
321209ff23fSmrg    /* Setup engine location. This shouldn't be necessary since we
322209ff23fSmrg     * set them appropriately before any accel ops, but let's avoid
323209ff23fSmrg     * random bogus DMA in case we inadvertently trigger the engine
324209ff23fSmrg     * in the wrong place (happened).
325209ff23fSmrg     */
326209ff23fSmrg    RADEONWaitForFifo(pScrn, 2);
327209ff23fSmrg    OUTREG(RADEON_DST_PITCH_OFFSET, info->dst_pitch_offset);
328209ff23fSmrg    OUTREG(RADEON_SRC_PITCH_OFFSET, info->dst_pitch_offset);
329209ff23fSmrg
330209ff23fSmrg    RADEONWaitForFifo(pScrn, 1);
331209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
332209ff23fSmrg    OUTREGP(RADEON_DP_DATATYPE,
333209ff23fSmrg	    RADEON_HOST_BIG_ENDIAN_EN,
334209ff23fSmrg	    ~RADEON_HOST_BIG_ENDIAN_EN);
335209ff23fSmrg#else
336209ff23fSmrg    OUTREGP(RADEON_DP_DATATYPE, 0, ~RADEON_HOST_BIG_ENDIAN_EN);
337209ff23fSmrg#endif
338209ff23fSmrg
339209ff23fSmrg    /* Restore SURFACE_CNTL */
340209ff23fSmrg    OUTREG(RADEON_SURFACE_CNTL, info->ModeReg->surface_cntl);
341209ff23fSmrg
342209ff23fSmrg    RADEONWaitForFifo(pScrn, 1);
343209ff23fSmrg    OUTREG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, (RADEON_DEFAULT_SC_RIGHT_MAX
344209ff23fSmrg					    | RADEON_DEFAULT_SC_BOTTOM_MAX));
345209ff23fSmrg    RADEONWaitForFifo(pScrn, 1);
346209ff23fSmrg    OUTREG(RADEON_DP_GUI_MASTER_CNTL, (info->dp_gui_master_cntl
347209ff23fSmrg				       | RADEON_GMC_BRUSH_SOLID_COLOR
348209ff23fSmrg				       | RADEON_GMC_SRC_DATATYPE_COLOR));
349209ff23fSmrg
350209ff23fSmrg    RADEONWaitForFifo(pScrn, 5);
351209ff23fSmrg    OUTREG(RADEON_DP_BRUSH_FRGD_CLR, 0xffffffff);
352209ff23fSmrg    OUTREG(RADEON_DP_BRUSH_BKGD_CLR, 0x00000000);
353209ff23fSmrg    OUTREG(RADEON_DP_SRC_FRGD_CLR,   0xffffffff);
354209ff23fSmrg    OUTREG(RADEON_DP_SRC_BKGD_CLR,   0x00000000);
355209ff23fSmrg    OUTREG(RADEON_DP_WRITE_MASK,     0xffffffff);
356209ff23fSmrg
357209ff23fSmrg    RADEONWaitForIdleMMIO(pScrn);
358209ff23fSmrg
359209ff23fSmrg    info->XInited3D = FALSE;
360209ff23fSmrg}
361209ff23fSmrg
362209ff23fSmrg/* Initialize the acceleration hardware */
363209ff23fSmrgvoid RADEONEngineInit(ScrnInfoPtr pScrn)
364209ff23fSmrg{
365209ff23fSmrg    RADEONInfoPtr  info       = RADEONPTR(pScrn);
366209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
367209ff23fSmrg
368209ff23fSmrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
369209ff23fSmrg		   "EngineInit (%d/%d)\n",
370209ff23fSmrg		   info->CurrentLayout.pixel_code,
371209ff23fSmrg		   info->CurrentLayout.bitsPerPixel);
372209ff23fSmrg
373209ff23fSmrg#ifdef XF86DRI
374209ff23fSmrg    if (info->directRenderingEnabled && (IS_R300_3D || IS_R500_3D)) {
375209ff23fSmrg	drmRadeonGetParam np;
376209ff23fSmrg	int num_pipes;
377209ff23fSmrg
378209ff23fSmrg	memset(&np, 0, sizeof(np));
379209ff23fSmrg	np.param = RADEON_PARAM_NUM_GB_PIPES;
380209ff23fSmrg	np.value = &num_pipes;
381209ff23fSmrg
382209ff23fSmrg	if (drmCommandWriteRead(info->drmFD, DRM_RADEON_GETPARAM, &np,
383209ff23fSmrg				sizeof(np)) < 0) {
384209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
385209ff23fSmrg		       "Failed to determine num pipes from DRM, falling back to "
386209ff23fSmrg		       "manual look-up!\n");
387209ff23fSmrg	    info->num_gb_pipes = 0;
388209ff23fSmrg	} else {
389209ff23fSmrg	    info->num_gb_pipes = num_pipes;
390209ff23fSmrg	}
391209ff23fSmrg    }
392209ff23fSmrg#endif
393209ff23fSmrg
394209ff23fSmrg    if ((info->ChipFamily == CHIP_FAMILY_RV410) ||
395209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_R420)  ||
396209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS600) ||
397209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS690) ||
398209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS740) ||
399209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS400) ||
400209ff23fSmrg	(info->ChipFamily == CHIP_FAMILY_RS480) ||
401209ff23fSmrg	IS_R500_3D) {
402209ff23fSmrg	if (info->num_gb_pipes == 0) {
403209ff23fSmrg	    uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT);
404209ff23fSmrg
405209ff23fSmrg	    info->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1;
406209ff23fSmrg	    if (IS_R500_3D)
407209ff23fSmrg		OUTPLL(pScrn, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
408209ff23fSmrg	}
409209ff23fSmrg    } else {
410209ff23fSmrg	if (info->num_gb_pipes == 0) {
411209ff23fSmrg	    if ((info->ChipFamily == CHIP_FAMILY_R300) ||
412209ff23fSmrg		(info->ChipFamily == CHIP_FAMILY_R350)) {
413209ff23fSmrg		/* R3xx chips */
414209ff23fSmrg		info->num_gb_pipes = 2;
415209ff23fSmrg	    } else {
416209ff23fSmrg		/* RV3xx chips */
417209ff23fSmrg		info->num_gb_pipes = 1;
418209ff23fSmrg	    }
419209ff23fSmrg	}
420209ff23fSmrg    }
421209ff23fSmrg
422209ff23fSmrg    if (IS_R300_3D || IS_R500_3D)
423209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
424209ff23fSmrg		   "num pipes is %d\n", info->num_gb_pipes);
425209ff23fSmrg
426209ff23fSmrg    if (IS_R300_3D || IS_R500_3D) {
427209ff23fSmrg	uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 | R300_SUBPIXEL_1_16);
428209ff23fSmrg
429209ff23fSmrg	switch(info->num_gb_pipes) {
430209ff23fSmrg	case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break;
431209ff23fSmrg	case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break;
432209ff23fSmrg	case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break;
433209ff23fSmrg	default:
434209ff23fSmrg	case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break;
435209ff23fSmrg	}
436209ff23fSmrg
437209ff23fSmrg	OUTREG(R300_GB_TILE_CONFIG, gb_tile_config);
438209ff23fSmrg	OUTREG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN);
439209ff23fSmrg	OUTREG(R300_DST_PIPE_CONFIG, INREG(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG);
440209ff23fSmrg	OUTREG(R300_RB2D_DSTCACHE_MODE, (INREG(R300_RB2D_DSTCACHE_MODE) |
441209ff23fSmrg					 R300_DC_AUTOFLUSH_ENABLE |
442209ff23fSmrg					 R300_DC_DC_DISABLE_IGNORE_PE));
443209ff23fSmrg    } else
444209ff23fSmrg	OUTREG(RADEON_RB3D_CNTL, 0);
445209ff23fSmrg
446209ff23fSmrg    RADEONEngineReset(pScrn);
447209ff23fSmrg
448209ff23fSmrg    switch (info->CurrentLayout.pixel_code) {
449209ff23fSmrg    case 8:  info->datatype = 2; break;
450209ff23fSmrg    case 15: info->datatype = 3; break;
451209ff23fSmrg    case 16: info->datatype = 4; break;
452209ff23fSmrg    case 24: info->datatype = 5; break;
453209ff23fSmrg    case 32: info->datatype = 6; break;
454209ff23fSmrg    default:
455209ff23fSmrg	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
456209ff23fSmrg		       "Unknown depth/bpp = %d/%d (code = %d)\n",
457209ff23fSmrg		       info->CurrentLayout.depth,
458209ff23fSmrg		       info->CurrentLayout.bitsPerPixel,
459209ff23fSmrg		       info->CurrentLayout.pixel_code);
460209ff23fSmrg    }
461209ff23fSmrg    info->pitch = ((info->CurrentLayout.displayWidth / 8) *
462209ff23fSmrg		   (info->CurrentLayout.pixel_bytes == 3 ? 3 : 1));
463209ff23fSmrg
464209ff23fSmrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
465209ff23fSmrg		   "Pitch for acceleration = %d\n", info->pitch);
466209ff23fSmrg
467209ff23fSmrg    info->dp_gui_master_cntl =
468209ff23fSmrg	((info->datatype << RADEON_GMC_DST_DATATYPE_SHIFT)
469209ff23fSmrg	 | RADEON_GMC_CLR_CMP_CNTL_DIS
470209ff23fSmrg	 | RADEON_GMC_DST_PITCH_OFFSET_CNTL);
471209ff23fSmrg
472209ff23fSmrg#ifdef XF86DRI
473209ff23fSmrg    info->sc_left         = 0x00000000;
474209ff23fSmrg    info->sc_right        = RADEON_DEFAULT_SC_RIGHT_MAX;
475209ff23fSmrg    info->sc_top          = 0x00000000;
476209ff23fSmrg    info->sc_bottom       = RADEON_DEFAULT_SC_BOTTOM_MAX;
477209ff23fSmrg
478209ff23fSmrg    info->re_top_left     = 0x00000000;
479209ff23fSmrg    if (info->ChipFamily <= CHIP_FAMILY_RV280)
480209ff23fSmrg	info->re_width_height = ((0x7ff << RADEON_RE_WIDTH_SHIFT) |
481209ff23fSmrg				 (0x7ff << RADEON_RE_HEIGHT_SHIFT));
482209ff23fSmrg    else
483209ff23fSmrg	info->re_width_height = ((8191 << R300_SCISSOR_X_SHIFT) |
484209ff23fSmrg				 (8191 << R300_SCISSOR_Y_SHIFT));
485209ff23fSmrg
486209ff23fSmrg    info->aux_sc_cntl     = 0x00000000;
487209ff23fSmrg#endif
488209ff23fSmrg
489209ff23fSmrg    RADEONEngineRestore(pScrn);
490209ff23fSmrg}
491209ff23fSmrg
492209ff23fSmrg
493209ff23fSmrg#define ACCEL_MMIO
494209ff23fSmrg#define ACCEL_PREAMBLE()        unsigned char *RADEONMMIO = info->MMIO
495209ff23fSmrg#define BEGIN_ACCEL(n)          RADEONWaitForFifo(pScrn, (n))
496209ff23fSmrg#define OUT_ACCEL_REG(reg, val) OUTREG(reg, val)
497209ff23fSmrg#define FINISH_ACCEL()
498209ff23fSmrg
499209ff23fSmrg#include "radeon_commonfuncs.c"
500209ff23fSmrg#if defined(RENDER) && defined(USE_XAA)
501209ff23fSmrg#include "radeon_render.c"
502209ff23fSmrg#endif
503209ff23fSmrg#include "radeon_accelfuncs.c"
504209ff23fSmrg
505209ff23fSmrg#undef ACCEL_MMIO
506209ff23fSmrg#undef ACCEL_PREAMBLE
507209ff23fSmrg#undef BEGIN_ACCEL
508209ff23fSmrg#undef OUT_ACCEL_REG
509209ff23fSmrg#undef FINISH_ACCEL
510209ff23fSmrg
511209ff23fSmrg#ifdef XF86DRI
512209ff23fSmrg
513209ff23fSmrg#define ACCEL_CP
514209ff23fSmrg#define ACCEL_PREAMBLE()						\
515209ff23fSmrg    RING_LOCALS;							\
516209ff23fSmrg    RADEONCP_REFRESH(pScrn, info)
517209ff23fSmrg#define BEGIN_ACCEL(n)          BEGIN_RING(2*(n))
518209ff23fSmrg#define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val)
519209ff23fSmrg#define FINISH_ACCEL()          ADVANCE_RING()
520209ff23fSmrg
521209ff23fSmrg
522209ff23fSmrg#include "radeon_commonfuncs.c"
523209ff23fSmrg#if defined(RENDER) && defined(USE_XAA)
524209ff23fSmrg#include "radeon_render.c"
525209ff23fSmrg#endif
526209ff23fSmrg#include "radeon_accelfuncs.c"
527209ff23fSmrg
528209ff23fSmrg#undef ACCEL_CP
529209ff23fSmrg#undef ACCEL_PREAMBLE
530209ff23fSmrg#undef BEGIN_ACCEL
531209ff23fSmrg#undef OUT_ACCEL_REG
532209ff23fSmrg#undef FINISH_ACCEL
533209ff23fSmrg
534209ff23fSmrg/* Stop the CP */
535209ff23fSmrgint RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info)
536209ff23fSmrg{
537209ff23fSmrg    drmRadeonCPStop  stop;
538209ff23fSmrg    int              ret, i;
539209ff23fSmrg
540209ff23fSmrg    stop.flush = 1;
541209ff23fSmrg    stop.idle  = 1;
542209ff23fSmrg
543209ff23fSmrg    ret = drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP, &stop,
544209ff23fSmrg			  sizeof(drmRadeonCPStop));
545209ff23fSmrg
546209ff23fSmrg    if (ret == 0) {
547209ff23fSmrg	return 0;
548209ff23fSmrg    } else if (errno != EBUSY) {
549209ff23fSmrg	return -errno;
550209ff23fSmrg    }
551209ff23fSmrg
552209ff23fSmrg    stop.flush = 0;
553209ff23fSmrg
554209ff23fSmrg    i = 0;
555209ff23fSmrg    do {
556209ff23fSmrg	ret = drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP, &stop,
557209ff23fSmrg			      sizeof(drmRadeonCPStop));
558209ff23fSmrg    } while (ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY);
559209ff23fSmrg
560209ff23fSmrg    if (ret == 0) {
561209ff23fSmrg	return 0;
562209ff23fSmrg    } else if (errno != EBUSY) {
563209ff23fSmrg	return -errno;
564209ff23fSmrg    }
565209ff23fSmrg
566209ff23fSmrg    stop.idle = 0;
567209ff23fSmrg
568209ff23fSmrg    if (drmCommandWrite(info->drmFD, DRM_RADEON_CP_STOP,
569209ff23fSmrg			&stop, sizeof(drmRadeonCPStop))) {
570209ff23fSmrg	return -errno;
571209ff23fSmrg    } else {
572209ff23fSmrg	return 0;
573209ff23fSmrg    }
574209ff23fSmrg}
575209ff23fSmrg
576209ff23fSmrg/* Get an indirect buffer for the CP 2D acceleration commands  */
577209ff23fSmrgdrmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn)
578209ff23fSmrg{
579209ff23fSmrg    RADEONInfoPtr  info = RADEONPTR(pScrn);
580209ff23fSmrg    drmDMAReq      dma;
581209ff23fSmrg    drmBufPtr      buf = NULL;
582209ff23fSmrg    int            indx = 0;
583209ff23fSmrg    int            size = 0;
584209ff23fSmrg    int            i = 0;
585209ff23fSmrg    int            ret;
586209ff23fSmrg
587209ff23fSmrg#if 0
588209ff23fSmrg    /* FIXME: pScrn->pScreen has not been initialized when this is first
589209ff23fSmrg     * called from RADEONSelectBuffer via RADEONDRICPInit.  We could use
590209ff23fSmrg     * the screen index from pScrn, which is initialized, and then get
591209ff23fSmrg     * the screen from screenInfo.screens[index], but that is a hack.
592209ff23fSmrg     */
593209ff23fSmrg    dma.context = DRIGetContext(pScrn->pScreen);
594209ff23fSmrg#else
595209ff23fSmrg    /* This is the X server's context */
596209ff23fSmrg    dma.context = 0x00000001;
597209ff23fSmrg#endif
598209ff23fSmrg
599209ff23fSmrg    dma.send_count    = 0;
600209ff23fSmrg    dma.send_list     = NULL;
601209ff23fSmrg    dma.send_sizes    = NULL;
602209ff23fSmrg    dma.flags         = 0;
603209ff23fSmrg    dma.request_count = 1;
604209ff23fSmrg    dma.request_size  = RADEON_BUFFER_SIZE;
605209ff23fSmrg    dma.request_list  = &indx;
606209ff23fSmrg    dma.request_sizes = &size;
607209ff23fSmrg    dma.granted_count = 0;
608209ff23fSmrg
609209ff23fSmrg    while (1) {
610209ff23fSmrg	do {
611209ff23fSmrg	    ret = drmDMA(info->drmFD, &dma);
612209ff23fSmrg	    if (ret && ret != -EBUSY) {
613209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
614209ff23fSmrg			   "%s: CP GetBuffer %d\n", __FUNCTION__, ret);
615209ff23fSmrg	    }
616209ff23fSmrg	} while ((ret == -EBUSY) && (i++ < RADEON_TIMEOUT));
617209ff23fSmrg
618209ff23fSmrg	if (ret == 0) {
619209ff23fSmrg	    buf = &info->buffers->list[indx];
620209ff23fSmrg	    buf->used = 0;
621209ff23fSmrg	    if (RADEON_VERBOSE) {
622209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
623209ff23fSmrg			   "   GetBuffer returning %d %p\n",
624209ff23fSmrg			   buf->idx, buf->address);
625209ff23fSmrg	    }
626209ff23fSmrg	    return buf;
627209ff23fSmrg	}
628209ff23fSmrg
629209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
630209ff23fSmrg		   "GetBuffer timed out, resetting engine...\n");
631209ff23fSmrg	RADEONEngineReset(pScrn);
632209ff23fSmrg	RADEONEngineRestore(pScrn);
633209ff23fSmrg
634209ff23fSmrg	/* Always restart the engine when doing CP 2D acceleration */
635209ff23fSmrg	RADEONCP_RESET(pScrn, info);
636209ff23fSmrg	RADEONCP_START(pScrn, info);
637209ff23fSmrg    }
638209ff23fSmrg}
639209ff23fSmrg
640209ff23fSmrg/* Flush the indirect buffer to the kernel for submission to the card */
641209ff23fSmrgvoid RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard)
642209ff23fSmrg{
643209ff23fSmrg    RADEONInfoPtr      info   = RADEONPTR(pScrn);
644209ff23fSmrg    drmBufPtr          buffer = info->indirectBuffer;
645209ff23fSmrg    int                start  = info->indirectStart;
646209ff23fSmrg    drmRadeonIndirect  indirect;
647209ff23fSmrg
648209ff23fSmrg    if (!buffer) return;
649209ff23fSmrg    if (start == buffer->used && !discard) return;
650209ff23fSmrg
651209ff23fSmrg    if (RADEON_VERBOSE) {
652209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Flushing buffer %d\n",
653209ff23fSmrg		   buffer->idx);
654209ff23fSmrg    }
655209ff23fSmrg
656209ff23fSmrg    indirect.idx     = buffer->idx;
657209ff23fSmrg    indirect.start   = start;
658209ff23fSmrg    indirect.end     = buffer->used;
659209ff23fSmrg    indirect.discard = discard;
660209ff23fSmrg
661209ff23fSmrg    drmCommandWriteRead(info->drmFD, DRM_RADEON_INDIRECT,
662209ff23fSmrg			&indirect, sizeof(drmRadeonIndirect));
663209ff23fSmrg
664209ff23fSmrg    if (discard) {
665209ff23fSmrg	info->indirectBuffer = RADEONCPGetBuffer(pScrn);
666209ff23fSmrg	info->indirectStart  = 0;
667209ff23fSmrg    } else {
668209ff23fSmrg	/* Start on a double word boundary */
669209ff23fSmrg	info->indirectStart  = buffer->used = (buffer->used + 7) & ~7;
670209ff23fSmrg	if (RADEON_VERBOSE) {
671209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "   Starting at %d\n",
672209ff23fSmrg		       info->indirectStart);
673209ff23fSmrg	}
674209ff23fSmrg    }
675209ff23fSmrg}
676209ff23fSmrg
677209ff23fSmrg/* Flush and release the indirect buffer */
678209ff23fSmrgvoid RADEONCPReleaseIndirect(ScrnInfoPtr pScrn)
679209ff23fSmrg{
680209ff23fSmrg    RADEONInfoPtr      info   = RADEONPTR(pScrn);
681209ff23fSmrg    drmBufPtr          buffer = info->indirectBuffer;
682209ff23fSmrg    int                start  = info->indirectStart;
683209ff23fSmrg    drmRadeonIndirect  indirect;
684209ff23fSmrg
685209ff23fSmrg    info->indirectBuffer = NULL;
686209ff23fSmrg    info->indirectStart  = 0;
687209ff23fSmrg
688209ff23fSmrg    if (!buffer) return;
689209ff23fSmrg
690209ff23fSmrg    if (RADEON_VERBOSE) {
691209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Releasing buffer %d\n",
692209ff23fSmrg		   buffer->idx);
693209ff23fSmrg    }
694209ff23fSmrg
695209ff23fSmrg    indirect.idx     = buffer->idx;
696209ff23fSmrg    indirect.start   = start;
697209ff23fSmrg    indirect.end     = buffer->used;
698209ff23fSmrg    indirect.discard = 1;
699209ff23fSmrg
700209ff23fSmrg    drmCommandWriteRead(info->drmFD, DRM_RADEON_INDIRECT,
701209ff23fSmrg			&indirect, sizeof(drmRadeonIndirect));
702209ff23fSmrg}
703209ff23fSmrg
704209ff23fSmrg/** \brief Calculate HostDataBlit parameters from pointer and pitch
705209ff23fSmrg *
706209ff23fSmrg * This is a helper for the trivial HostDataBlit users that don't need to worry
707209ff23fSmrg * about tiling etc.
708209ff23fSmrg */
709209ff23fSmrgvoid
710209ff23fSmrgRADEONHostDataParams(ScrnInfoPtr pScrn, uint8_t *dst, uint32_t pitch, int cpp,
711209ff23fSmrg		     uint32_t *dstPitchOff, int *x, int *y)
712209ff23fSmrg{
713209ff23fSmrg    RADEONInfoPtr info = RADEONPTR( pScrn );
714209ff23fSmrg    uint32_t dstOffs = dst - (uint8_t*)info->FB + info->fbLocation;
715209ff23fSmrg
716209ff23fSmrg    *dstPitchOff = pitch << 16 | (dstOffs & ~RADEON_BUFFER_ALIGN) >> 10;
717209ff23fSmrg    *y = ( dstOffs & RADEON_BUFFER_ALIGN ) / pitch;
718209ff23fSmrg    *x = ( ( dstOffs & RADEON_BUFFER_ALIGN ) - ( *y * pitch ) ) / cpp;
719209ff23fSmrg}
720209ff23fSmrg
721209ff23fSmrg/* Set up a hostdata blit to transfer data from system memory to the
722209ff23fSmrg * framebuffer. Returns the address where the data can be written to and sets
723209ff23fSmrg * the dstPitch and hpass variables as required.
724209ff23fSmrg */
725209ff23fSmrguint8_t*
726209ff23fSmrgRADEONHostDataBlit(
727209ff23fSmrg    ScrnInfoPtr pScrn,
728209ff23fSmrg    unsigned int cpp,
729209ff23fSmrg    unsigned int w,
730209ff23fSmrg    uint32_t dstPitchOff,
731209ff23fSmrg    uint32_t *bufPitch,
732209ff23fSmrg    int x,
733209ff23fSmrg    int *y,
734209ff23fSmrg    unsigned int *h,
735209ff23fSmrg    unsigned int *hpass
736209ff23fSmrg){
737209ff23fSmrg    RADEONInfoPtr info = RADEONPTR( pScrn );
738209ff23fSmrg    uint32_t format, dwords;
739209ff23fSmrg    uint8_t *ret;
740209ff23fSmrg    RING_LOCALS;
741209ff23fSmrg
742209ff23fSmrg    if ( *h == 0 )
743209ff23fSmrg    {
744209ff23fSmrg	return NULL;
745209ff23fSmrg    }
746209ff23fSmrg
747209ff23fSmrg    switch ( cpp )
748209ff23fSmrg    {
749209ff23fSmrg    case 4:
750209ff23fSmrg	format = RADEON_GMC_DST_32BPP;
751209ff23fSmrg	*bufPitch = 4 * w;
752209ff23fSmrg	break;
753209ff23fSmrg    case 2:
754209ff23fSmrg	format = RADEON_GMC_DST_16BPP;
755209ff23fSmrg	*bufPitch = 2 * ((w + 1) & ~1);
756209ff23fSmrg	break;
757209ff23fSmrg    case 1:
758209ff23fSmrg	format = RADEON_GMC_DST_8BPP_CI;
759209ff23fSmrg	*bufPitch = (w + 3) & ~3;
760209ff23fSmrg	break;
761209ff23fSmrg    default:
762209ff23fSmrg	xf86DrvMsg( pScrn->scrnIndex, X_ERROR,
763209ff23fSmrg		    "%s: Unsupported cpp %d!\n", __func__, cpp );
764209ff23fSmrg	return NULL;
765209ff23fSmrg    }
766209ff23fSmrg
767209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
768209ff23fSmrg    /* Swap doesn't work on R300 and later, it's handled during the
769209ff23fSmrg     * copy to ind. buffer pass
770209ff23fSmrg     */
771209ff23fSmrg    if (info->ChipFamily < CHIP_FAMILY_R300) {
772209ff23fSmrg        BEGIN_RING(2);
773209ff23fSmrg	if (cpp == 2)
774209ff23fSmrg	    OUT_RING_REG(RADEON_RBBM_GUICNTL,
775209ff23fSmrg			 RADEON_HOST_DATA_SWAP_HDW);
776209ff23fSmrg	else if (cpp == 1)
777209ff23fSmrg	    OUT_RING_REG(RADEON_RBBM_GUICNTL,
778209ff23fSmrg			 RADEON_HOST_DATA_SWAP_32BIT);
779209ff23fSmrg	else
780209ff23fSmrg	    OUT_RING_REG(RADEON_RBBM_GUICNTL,
781209ff23fSmrg			 RADEON_HOST_DATA_SWAP_NONE);
782209ff23fSmrg	ADVANCE_RING();
783209ff23fSmrg    }
784209ff23fSmrg#endif
785209ff23fSmrg
786209ff23fSmrg    /*RADEON_PURGE_CACHE();
787209ff23fSmrg      RADEON_WAIT_UNTIL_IDLE();*/
788209ff23fSmrg
789209ff23fSmrg    *hpass = min( *h, ( ( RADEON_BUFFER_SIZE - 10 * 4 ) / *bufPitch ) );
790209ff23fSmrg    dwords = *hpass * *bufPitch / 4;
791209ff23fSmrg
792209ff23fSmrg    BEGIN_RING( dwords + 10 );
793209ff23fSmrg    OUT_RING( CP_PACKET3( RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT, dwords + 10 - 2 ) );
794209ff23fSmrg    OUT_RING( RADEON_GMC_DST_PITCH_OFFSET_CNTL
795209ff23fSmrg	    | RADEON_GMC_DST_CLIPPING
796209ff23fSmrg	    | RADEON_GMC_BRUSH_NONE
797209ff23fSmrg	    | format
798209ff23fSmrg	    | RADEON_GMC_SRC_DATATYPE_COLOR
799209ff23fSmrg	    | RADEON_ROP3_S
800209ff23fSmrg	    | RADEON_DP_SRC_SOURCE_HOST_DATA
801209ff23fSmrg	    | RADEON_GMC_CLR_CMP_CNTL_DIS
802209ff23fSmrg	    | RADEON_GMC_WR_MSK_DIS );
803209ff23fSmrg    OUT_RING( dstPitchOff );
804209ff23fSmrg    OUT_RING( (*y << 16) | x );
805209ff23fSmrg    OUT_RING( ((*y + *hpass) << 16) | (x + w) );
806209ff23fSmrg    OUT_RING( 0xffffffff );
807209ff23fSmrg    OUT_RING( 0xffffffff );
808209ff23fSmrg    OUT_RING( *y << 16 | x );
809209ff23fSmrg    OUT_RING( *hpass << 16 | (*bufPitch / cpp) );
810209ff23fSmrg    OUT_RING( dwords );
811209ff23fSmrg
812209ff23fSmrg    ret = ( uint8_t* )&__head[__count];
813209ff23fSmrg
814209ff23fSmrg    __count += dwords;
815209ff23fSmrg    ADVANCE_RING();
816209ff23fSmrg
817209ff23fSmrg    *y += *hpass;
818209ff23fSmrg    *h -= *hpass;
819209ff23fSmrg
820209ff23fSmrg    return ret;
821209ff23fSmrg}
822209ff23fSmrg
823209ff23fSmrgvoid RADEONCopySwap(uint8_t *dst, uint8_t *src, unsigned int size, int swap)
824209ff23fSmrg{
825209ff23fSmrg    switch(swap) {
826209ff23fSmrg    case RADEON_HOST_DATA_SWAP_HDW:
827209ff23fSmrg        {
828209ff23fSmrg	    unsigned int *d = (unsigned int *)dst;
829209ff23fSmrg	    unsigned int *s = (unsigned int *)src;
830209ff23fSmrg	    unsigned int nwords = size >> 2;
831209ff23fSmrg
832209ff23fSmrg	    for (; nwords > 0; --nwords, ++d, ++s)
833209ff23fSmrg		*d = ((*s & 0xffff) << 16) | ((*s >> 16) & 0xffff);
834209ff23fSmrg	    return;
835209ff23fSmrg        }
836209ff23fSmrg    case RADEON_HOST_DATA_SWAP_32BIT:
837209ff23fSmrg        {
838209ff23fSmrg	    unsigned int *d = (unsigned int *)dst;
839209ff23fSmrg	    unsigned int *s = (unsigned int *)src;
840209ff23fSmrg	    unsigned int nwords = size >> 2;
841209ff23fSmrg
842209ff23fSmrg	    for (; nwords > 0; --nwords, ++d, ++s)
843209ff23fSmrg#ifdef __powerpc__
844209ff23fSmrg		asm volatile("stwbrx %0,0,%1" : : "r" (*s), "r" (d));
845209ff23fSmrg#else
846209ff23fSmrg		*d = ((*s >> 24) & 0xff) | ((*s >> 8) & 0xff00)
847209ff23fSmrg			| ((*s & 0xff00) << 8) | ((*s & 0xff) << 24);
848209ff23fSmrg#endif
849209ff23fSmrg	    return;
850209ff23fSmrg        }
851209ff23fSmrg    case RADEON_HOST_DATA_SWAP_16BIT:
852209ff23fSmrg        {
853209ff23fSmrg	    unsigned short *d = (unsigned short *)dst;
854209ff23fSmrg	    unsigned short *s = (unsigned short *)src;
855209ff23fSmrg	    unsigned int nwords = size >> 1;
856209ff23fSmrg
857209ff23fSmrg	    for (; nwords > 0; --nwords, ++d, ++s)
858209ff23fSmrg#ifdef __powerpc__
859209ff23fSmrg		asm volatile("stwbrx %0,0,%1" : : "r" (*s), "r" (d));
860209ff23fSmrg#else
861209ff23fSmrg	        *d = ((*s >> 24) & 0xff) | ((*s >> 8) & 0xff00)
862209ff23fSmrg			| ((*s & 0xff00) << 8) | ((*s & 0xff) << 24);
863209ff23fSmrg#endif
864209ff23fSmrg	    return;
865209ff23fSmrg	}
866209ff23fSmrg    }
867209ff23fSmrg    if (src != dst)
868209ff23fSmrg	    memmove(dst, src, size);
869209ff23fSmrg}
870209ff23fSmrg
871209ff23fSmrg/* Copies a single pass worth of data for a hostdata blit set up by
872209ff23fSmrg * RADEONHostDataBlit().
873209ff23fSmrg */
874209ff23fSmrgvoid
875209ff23fSmrgRADEONHostDataBlitCopyPass(
876209ff23fSmrg    ScrnInfoPtr pScrn,
877209ff23fSmrg    unsigned int cpp,
878209ff23fSmrg    uint8_t *dst,
879209ff23fSmrg    uint8_t *src,
880209ff23fSmrg    unsigned int hpass,
881209ff23fSmrg    unsigned int dstPitch,
882209ff23fSmrg    unsigned int srcPitch
883209ff23fSmrg){
884209ff23fSmrg
885209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
886209ff23fSmrg    RADEONInfoPtr info = RADEONPTR( pScrn );
887209ff23fSmrg#endif
888209ff23fSmrg
889209ff23fSmrg    /* RADEONHostDataBlitCopy can return NULL ! */
890209ff23fSmrg    if( (dst==NULL) || (src==NULL)) return;
891209ff23fSmrg
892209ff23fSmrg    if ( dstPitch == srcPitch )
893209ff23fSmrg    {
894209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
895209ff23fSmrg        if (info->ChipFamily >= CHIP_FAMILY_R300) {
896209ff23fSmrg	    switch(cpp) {
897209ff23fSmrg	    case 1:
898209ff23fSmrg		RADEONCopySwap(dst, src, hpass * dstPitch,
899209ff23fSmrg			       RADEON_HOST_DATA_SWAP_32BIT);
900209ff23fSmrg		return;
901209ff23fSmrg	    case 2:
902209ff23fSmrg	        RADEONCopySwap(dst, src, hpass * dstPitch,
903209ff23fSmrg			       RADEON_HOST_DATA_SWAP_HDW);
904209ff23fSmrg		return;
905209ff23fSmrg	    }
906209ff23fSmrg	}
907209ff23fSmrg#endif
908209ff23fSmrg	memcpy( dst, src, hpass * dstPitch );
909209ff23fSmrg    }
910209ff23fSmrg    else
911209ff23fSmrg    {
912209ff23fSmrg	unsigned int minPitch = min( dstPitch, srcPitch );
913209ff23fSmrg	while ( hpass-- )
914209ff23fSmrg	{
915209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
916209ff23fSmrg            if (info->ChipFamily >= CHIP_FAMILY_R300) {
917209ff23fSmrg		switch(cpp) {
918209ff23fSmrg		case 1:
919209ff23fSmrg		    RADEONCopySwap(dst, src, minPitch,
920209ff23fSmrg				   RADEON_HOST_DATA_SWAP_32BIT);
921209ff23fSmrg		    goto next;
922209ff23fSmrg		case 2:
923209ff23fSmrg	            RADEONCopySwap(dst, src, minPitch,
924209ff23fSmrg				   RADEON_HOST_DATA_SWAP_HDW);
925209ff23fSmrg		    goto next;
926209ff23fSmrg		}
927209ff23fSmrg	    }
928209ff23fSmrg#endif
929209ff23fSmrg	    memcpy( dst, src, minPitch );
930209ff23fSmrg#if X_BYTE_ORDER == X_BIG_ENDIAN
931209ff23fSmrg	next:
932209ff23fSmrg#endif
933209ff23fSmrg	    src += srcPitch;
934209ff23fSmrg	    dst += dstPitch;
935209ff23fSmrg	}
936209ff23fSmrg    }
937209ff23fSmrg}
938209ff23fSmrg
939209ff23fSmrg#endif
940209ff23fSmrg
941209ff23fSmrgBool RADEONAccelInit(ScreenPtr pScreen)
942209ff23fSmrg{
943209ff23fSmrg    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
944209ff23fSmrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
945209ff23fSmrg
946209ff23fSmrg    if (info->ChipFamily >= CHIP_FAMILY_R600)
947209ff23fSmrg	return FALSE;
948209ff23fSmrg
949209ff23fSmrg#ifdef USE_EXA
950209ff23fSmrg    if (info->useEXA) {
951209ff23fSmrg# ifdef XF86DRI
952209ff23fSmrg	if (info->directRenderingEnabled) {
953209ff23fSmrg	    if (!RADEONDrawInitCP(pScreen))
954209ff23fSmrg		return FALSE;
955209ff23fSmrg	} else
956209ff23fSmrg# endif /* XF86DRI */
957209ff23fSmrg	{
958209ff23fSmrg	    if (!RADEONDrawInitMMIO(pScreen))
959209ff23fSmrg		return FALSE;
960209ff23fSmrg	}
961209ff23fSmrg    }
962209ff23fSmrg#endif /* USE_EXA */
963209ff23fSmrg#ifdef USE_XAA
964209ff23fSmrg    if (!info->useEXA) {
965209ff23fSmrg	XAAInfoRecPtr  a;
966209ff23fSmrg
967209ff23fSmrg	if (!(a = info->accel = XAACreateInfoRec())) {
968209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAACreateInfoRec Error\n");
969209ff23fSmrg	    return FALSE;
970209ff23fSmrg	}
971209ff23fSmrg
972209ff23fSmrg#ifdef XF86DRI
973209ff23fSmrg	if (info->directRenderingEnabled)
974209ff23fSmrg	    RADEONAccelInitCP(pScreen, a);
975209ff23fSmrg	else
976209ff23fSmrg#endif /* XF86DRI */
977209ff23fSmrg	    RADEONAccelInitMMIO(pScreen, a);
978209ff23fSmrg
979209ff23fSmrg	RADEONEngineInit(pScrn);
980209ff23fSmrg
981209ff23fSmrg	if (!XAAInit(pScreen, a)) {
982209ff23fSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "XAAInit Error\n");
983209ff23fSmrg	    return FALSE;
984209ff23fSmrg	}
985209ff23fSmrg    }
986209ff23fSmrg#endif /* USE_XAA */
987209ff23fSmrg    return TRUE;
988209ff23fSmrg}
989209ff23fSmrg
990209ff23fSmrgvoid RADEONInit3DEngine(ScrnInfoPtr pScrn)
991209ff23fSmrg{
992209ff23fSmrg    RADEONInfoPtr info = RADEONPTR (pScrn);
993209ff23fSmrg
994209ff23fSmrg#ifdef XF86DRI
995209ff23fSmrg    if (info->directRenderingEnabled) {
996209ff23fSmrg	RADEONSAREAPrivPtr pSAREAPriv;
997209ff23fSmrg
998209ff23fSmrg	pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
999209ff23fSmrg	pSAREAPriv->ctxOwner = DRIGetContext(pScrn->pScreen);
1000209ff23fSmrg	RADEONInit3DEngineCP(pScrn);
1001209ff23fSmrg    } else
1002209ff23fSmrg#endif
1003209ff23fSmrg	RADEONInit3DEngineMMIO(pScrn);
1004209ff23fSmrg
1005209ff23fSmrg    info->XInited3D = TRUE;
1006209ff23fSmrg}
1007209ff23fSmrg
1008209ff23fSmrg#ifdef USE_XAA
1009209ff23fSmrg#ifdef XF86DRI
1010209ff23fSmrgBool
1011209ff23fSmrgRADEONSetupMemXAA_DRI(int scrnIndex, ScreenPtr pScreen)
1012209ff23fSmrg{
1013209ff23fSmrg    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
1014209ff23fSmrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
1015209ff23fSmrg    int            cpp = info->CurrentLayout.pixel_bytes;
1016209ff23fSmrg    int            depthCpp = (info->depthBits - 8) / 4;
1017209ff23fSmrg    int            width_bytes = pScrn->displayWidth * cpp;
1018209ff23fSmrg    int            bufferSize;
1019209ff23fSmrg    int            depthSize;
1020209ff23fSmrg    int            l;
1021209ff23fSmrg    int            scanlines;
1022209ff23fSmrg    int            texsizerequest;
1023209ff23fSmrg    BoxRec         MemBox;
1024209ff23fSmrg    FBAreaPtr      fbarea;
1025209ff23fSmrg
1026209ff23fSmrg    info->frontOffset = 0;
1027209ff23fSmrg    info->frontPitch = pScrn->displayWidth;
1028209ff23fSmrg    info->backPitch = pScrn->displayWidth;
1029209ff23fSmrg
1030209ff23fSmrg    /* make sure we use 16 line alignment for tiling (8 might be enough).
1031209ff23fSmrg     * Might need that for non-XF86DRI too?
1032209ff23fSmrg     */
1033209ff23fSmrg    if (info->allowColorTiling) {
1034209ff23fSmrg	bufferSize = (((pScrn->virtualY + 15) & ~15) * width_bytes
1035209ff23fSmrg		      + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN;
1036209ff23fSmrg    } else {
1037209ff23fSmrg        bufferSize = (pScrn->virtualY * width_bytes
1038209ff23fSmrg		      + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN;
1039209ff23fSmrg    }
1040209ff23fSmrg
1041209ff23fSmrg    /* Due to tiling, the Z buffer pitch must be a multiple of 32 pixels,
1042209ff23fSmrg     * which is always the case if color tiling is used due to color pitch
1043209ff23fSmrg     * but not necessarily otherwise, and its height a multiple of 16 lines.
1044209ff23fSmrg     */
1045209ff23fSmrg    info->depthPitch = (pScrn->displayWidth + 31) & ~31;
1046209ff23fSmrg    depthSize = ((((pScrn->virtualY + 15) & ~15) * info->depthPitch
1047209ff23fSmrg		  * depthCpp + RADEON_BUFFER_ALIGN) & ~RADEON_BUFFER_ALIGN);
1048209ff23fSmrg
1049209ff23fSmrg    switch (info->CPMode) {
1050209ff23fSmrg    case RADEON_DEFAULT_CP_PIO_MODE:
1051209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in PIO mode\n");
1052209ff23fSmrg	break;
1053209ff23fSmrg    case RADEON_DEFAULT_CP_BM_MODE:
1054209ff23fSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in BM mode\n");
1055209ff23fSmrg	break;
1056209ff23fSmrg    default:
1057209ff23fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CP in UNKNOWN mode\n");
1058209ff23fSmrg	break;
1059209ff23fSmrg    }
1060209ff23fSmrg
1061209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1062209ff23fSmrg	       "Using %d MB GART aperture\n", info->gartSize);
1063209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1064209ff23fSmrg	       "Using %d MB for the ring buffer\n", info->ringSize);
1065209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1066209ff23fSmrg	       "Using %d MB for vertex/indirect buffers\n", info->bufSize);
1067209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1068209ff23fSmrg	       "Using %d MB for GART textures\n", info->gartTexSize);
1069209ff23fSmrg
1070209ff23fSmrg    /* Try for front, back, depth, and three framebuffers worth of
1071209ff23fSmrg     * pixmap cache.  Should be enough for a fullscreen background
1072209ff23fSmrg     * image plus some leftovers.
1073209ff23fSmrg     * If the FBTexPercent option was used, try to achieve that percentage instead,
1074209ff23fSmrg     * but still have at least one pixmap buffer (get problems with xvideo/render
1075209ff23fSmrg     * otherwise probably), and never reserve more than 3 offscreen buffers as it's
1076209ff23fSmrg     * probably useless for XAA.
1077209ff23fSmrg     */
1078209ff23fSmrg    if (info->textureSize >= 0) {
1079209ff23fSmrg	texsizerequest = ((int)info->FbMapSize - 2 * bufferSize - depthSize
1080209ff23fSmrg			 - 2 * width_bytes - 16384 - info->FbSecureSize)
1081209ff23fSmrg	/* first divide, then multiply or we'll get an overflow (been there...) */
1082209ff23fSmrg			 / 100 * info->textureSize;
1083209ff23fSmrg    }
1084209ff23fSmrg    else {
1085209ff23fSmrg	texsizerequest = (int)info->FbMapSize / 2;
1086209ff23fSmrg    }
1087209ff23fSmrg    info->textureSize = info->FbMapSize - info->FbSecureSize - 5 * bufferSize - depthSize;
1088209ff23fSmrg
1089209ff23fSmrg    /* If that gives us less than the requested memory, let's
1090209ff23fSmrg     * be greedy and grab some more.  Sorry, I care more about 3D
1091209ff23fSmrg     * performance than playing nicely, and you'll get around a full
1092209ff23fSmrg     * framebuffer's worth of pixmap cache anyway.
1093209ff23fSmrg     */
1094209ff23fSmrg    if (info->textureSize < texsizerequest) {
1095209ff23fSmrg        info->textureSize = info->FbMapSize - 4 * bufferSize - depthSize;
1096209ff23fSmrg    }
1097209ff23fSmrg    if (info->textureSize < texsizerequest) {
1098209ff23fSmrg        info->textureSize = info->FbMapSize - 3 * bufferSize - depthSize;
1099209ff23fSmrg    }
1100209ff23fSmrg
1101209ff23fSmrg    /* If there's still no space for textures, try without pixmap cache, but
1102209ff23fSmrg     * never use the reserved space, the space hw cursor and PCIGART table might
1103209ff23fSmrg     * use.
1104209ff23fSmrg     */
1105209ff23fSmrg    if (info->textureSize < 0) {
1106209ff23fSmrg	info->textureSize = info->FbMapSize - 2 * bufferSize - depthSize
1107209ff23fSmrg	                    - 2 * width_bytes - 16384 - info->FbSecureSize;
1108209ff23fSmrg    }
1109209ff23fSmrg
1110209ff23fSmrg    /* Check to see if there is more room available after the 8192nd
1111209ff23fSmrg     * scanline for textures
1112209ff23fSmrg     */
1113209ff23fSmrg    /* FIXME: what's this good for? condition is pretty much impossible to meet */
1114209ff23fSmrg    if ((int)info->FbMapSize - 8192*width_bytes - bufferSize - depthSize
1115209ff23fSmrg	> info->textureSize) {
1116209ff23fSmrg	info->textureSize =
1117209ff23fSmrg		info->FbMapSize - 8192*width_bytes - bufferSize - depthSize;
1118209ff23fSmrg    }
1119209ff23fSmrg
1120209ff23fSmrg    /* If backbuffer is disabled, don't allocate memory for it */
1121209ff23fSmrg    if (info->noBackBuffer) {
1122209ff23fSmrg	info->textureSize += bufferSize;
1123209ff23fSmrg    }
1124209ff23fSmrg
1125209ff23fSmrg    /* RADEON_BUFFER_ALIGN is not sufficient for backbuffer!
1126209ff23fSmrg       At least for pageflip + color tiling, need to make sure it's 16 scanlines aligned,
1127209ff23fSmrg       otherwise the copy-from-front-to-back will fail (width_bytes * 16 will also guarantee
1128209ff23fSmrg       it's still 4kb aligned for tiled case). Need to round up offset (might get into cursor
1129209ff23fSmrg       area otherwise).
1130209ff23fSmrg       This might cause some space at the end of the video memory to be unused, since it
1131209ff23fSmrg       can't be used (?) due to that log_tex_granularity thing???
1132209ff23fSmrg       Could use different copyscreentoscreen function for the pageflip copies
1133209ff23fSmrg       (which would use different src and dst offsets) to avoid this. */
1134209ff23fSmrg    if (info->allowColorTiling && !info->noBackBuffer) {
1135209ff23fSmrg	info->textureSize = info->FbMapSize - ((info->FbMapSize - info->textureSize +
1136209ff23fSmrg			  width_bytes * 16 - 1) / (width_bytes * 16)) * (width_bytes * 16);
1137209ff23fSmrg    }
1138209ff23fSmrg    if (info->textureSize > 0) {
1139209ff23fSmrg	l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS);
1140209ff23fSmrg	if (l < RADEON_LOG_TEX_GRANULARITY)
1141209ff23fSmrg	    l = RADEON_LOG_TEX_GRANULARITY;
1142209ff23fSmrg	/* Round the texture size up to the nearest whole number of
1143209ff23fSmrg	 * texture regions.  Again, be greedy about this, don't
1144209ff23fSmrg	 * round down.
1145209ff23fSmrg	 */
1146209ff23fSmrg	info->log2TexGran = l;
1147209ff23fSmrg	info->textureSize = (info->textureSize >> l) << l;
1148209ff23fSmrg    } else {
1149209ff23fSmrg	info->textureSize = 0;
1150209ff23fSmrg    }
1151209ff23fSmrg
1152209ff23fSmrg    /* Set a minimum usable local texture heap size.  This will fit
1153209ff23fSmrg     * two 256x256x32bpp textures.
1154209ff23fSmrg     */
1155209ff23fSmrg    if (info->textureSize < 512 * 1024) {
1156209ff23fSmrg	info->textureOffset = 0;
1157209ff23fSmrg	info->textureSize = 0;
1158209ff23fSmrg    }
1159209ff23fSmrg
1160209ff23fSmrg    if (info->allowColorTiling && !info->noBackBuffer) {
1161209ff23fSmrg	info->textureOffset = ((info->FbMapSize - info->textureSize) /
1162209ff23fSmrg			       (width_bytes * 16)) * (width_bytes * 16);
1163209ff23fSmrg    }
1164209ff23fSmrg    else {
1165209ff23fSmrg	/* Reserve space for textures */
1166209ff23fSmrg	info->textureOffset = ((info->FbMapSize - info->textureSize +
1167209ff23fSmrg				RADEON_BUFFER_ALIGN) &
1168209ff23fSmrg			       ~(uint32_t)RADEON_BUFFER_ALIGN);
1169209ff23fSmrg    }
1170209ff23fSmrg
1171209ff23fSmrg    /* Reserve space for the shared depth
1172209ff23fSmrg     * buffer.
1173209ff23fSmrg     */
1174209ff23fSmrg    info->depthOffset = ((info->textureOffset - depthSize +
1175209ff23fSmrg			  RADEON_BUFFER_ALIGN) &
1176209ff23fSmrg			 ~(uint32_t)RADEON_BUFFER_ALIGN);
1177209ff23fSmrg
1178209ff23fSmrg    /* Reserve space for the shared back buffer */
1179209ff23fSmrg    if (info->noBackBuffer) {
1180209ff23fSmrg       info->backOffset = info->depthOffset;
1181209ff23fSmrg    } else {
1182209ff23fSmrg       info->backOffset = ((info->depthOffset - bufferSize +
1183209ff23fSmrg			    RADEON_BUFFER_ALIGN) &
1184209ff23fSmrg			   ~(uint32_t)RADEON_BUFFER_ALIGN);
1185209ff23fSmrg    }
1186209ff23fSmrg
1187209ff23fSmrg    info->backY = info->backOffset / width_bytes;
1188209ff23fSmrg    info->backX = (info->backOffset - (info->backY * width_bytes)) / cpp;
1189209ff23fSmrg
1190209ff23fSmrg    scanlines = (info->FbMapSize-info->FbSecureSize) / width_bytes;
1191209ff23fSmrg    if (scanlines > 8191)
1192209ff23fSmrg	scanlines = 8191;
1193209ff23fSmrg
1194209ff23fSmrg    MemBox.x1 = 0;
1195209ff23fSmrg    MemBox.y1 = 0;
1196209ff23fSmrg    MemBox.x2 = pScrn->displayWidth;
1197209ff23fSmrg    MemBox.y2 = scanlines;
1198209ff23fSmrg
1199209ff23fSmrg    if (!xf86InitFBManager(pScreen, &MemBox)) {
1200209ff23fSmrg        xf86DrvMsg(scrnIndex, X_ERROR,
1201209ff23fSmrg		   "Memory manager initialization to "
1202209ff23fSmrg		   "(%d,%d) (%d,%d) failed\n",
1203209ff23fSmrg		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
1204209ff23fSmrg	return FALSE;
1205209ff23fSmrg    } else {
1206209ff23fSmrg	int  width, height;
1207209ff23fSmrg
1208209ff23fSmrg	xf86DrvMsg(scrnIndex, X_INFO,
1209209ff23fSmrg		   "Memory manager initialized to (%d,%d) (%d,%d)\n",
1210209ff23fSmrg		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
1211209ff23fSmrg	/* why oh why can't we just request modes which are guaranteed to be 16 lines
1212209ff23fSmrg	   aligned... sigh */
1213209ff23fSmrg	if ((fbarea = xf86AllocateOffscreenArea(pScreen,
1214209ff23fSmrg						pScrn->displayWidth,
1215209ff23fSmrg						info->allowColorTiling ?
1216209ff23fSmrg						((pScrn->virtualY + 15) & ~15)
1217209ff23fSmrg						- pScrn->virtualY + 2 : 2,
1218209ff23fSmrg						0, NULL, NULL,
1219209ff23fSmrg						NULL))) {
1220209ff23fSmrg	    xf86DrvMsg(scrnIndex, X_INFO,
1221209ff23fSmrg		       "Reserved area from (%d,%d) to (%d,%d)\n",
1222209ff23fSmrg		       fbarea->box.x1, fbarea->box.y1,
1223209ff23fSmrg		       fbarea->box.x2, fbarea->box.y2);
1224209ff23fSmrg	} else {
1225209ff23fSmrg	    xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
1226209ff23fSmrg	}
1227209ff23fSmrg
1228209ff23fSmrg	RADEONDRIAllocatePCIGARTTable(pScreen);
1229209ff23fSmrg
1230209ff23fSmrg	if (xf86QueryLargestOffscreenArea(pScreen, &width,
1231209ff23fSmrg					  &height, 0, 0, 0)) {
1232209ff23fSmrg	    xf86DrvMsg(scrnIndex, X_INFO,
1233209ff23fSmrg		       "Largest offscreen area available: %d x %d\n",
1234209ff23fSmrg		       width, height);
1235209ff23fSmrg
1236209ff23fSmrg	    /* Lines in offscreen area needed for depth buffer and
1237209ff23fSmrg	     * textures
1238209ff23fSmrg	     */
1239209ff23fSmrg	    info->depthTexLines = (scanlines
1240209ff23fSmrg				   - info->depthOffset / width_bytes);
1241209ff23fSmrg	    info->backLines	    = (scanlines
1242209ff23fSmrg				       - info->backOffset / width_bytes
1243209ff23fSmrg				       - info->depthTexLines);
1244209ff23fSmrg	    info->backArea	    = NULL;
1245209ff23fSmrg	} else {
1246209ff23fSmrg	    xf86DrvMsg(scrnIndex, X_ERROR,
1247209ff23fSmrg		       "Unable to determine largest offscreen area "
1248209ff23fSmrg		       "available\n");
1249209ff23fSmrg	    return FALSE;
1250209ff23fSmrg	}
1251209ff23fSmrg    }
1252209ff23fSmrg
1253209ff23fSmrg    xf86DrvMsg(scrnIndex, X_INFO,
1254209ff23fSmrg	       "Will use front buffer at offset 0x%x\n",
1255209ff23fSmrg	       info->frontOffset);
1256209ff23fSmrg
1257209ff23fSmrg    xf86DrvMsg(scrnIndex, X_INFO,
1258209ff23fSmrg	       "Will use back buffer at offset 0x%x\n",
1259209ff23fSmrg	       info->backOffset);
1260209ff23fSmrg    xf86DrvMsg(scrnIndex, X_INFO,
1261209ff23fSmrg	       "Will use depth buffer at offset 0x%x\n",
1262209ff23fSmrg	       info->depthOffset);
1263209ff23fSmrg    if (info->cardType==CARD_PCIE)
1264209ff23fSmrg    	xf86DrvMsg(scrnIndex, X_INFO,
1265209ff23fSmrg	           "Will use %d kb for PCI GART table at offset 0x%x\n",
1266209ff23fSmrg		   info->pciGartSize/1024, (unsigned)info->pciGartOffset);
1267209ff23fSmrg    xf86DrvMsg(scrnIndex, X_INFO,
1268209ff23fSmrg	       "Will use %d kb for textures at offset 0x%x\n",
1269209ff23fSmrg	       info->textureSize/1024, info->textureOffset);
1270209ff23fSmrg
1271209ff23fSmrg    info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) |
1272209ff23fSmrg			      ((info->frontOffset + info->fbLocation) >> 10));
1273209ff23fSmrg
1274209ff23fSmrg    info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) |
1275209ff23fSmrg			     ((info->backOffset + info->fbLocation) >> 10));
1276209ff23fSmrg
1277209ff23fSmrg    info->depthPitchOffset = (((info->depthPitch * depthCpp / 64) << 22) |
1278209ff23fSmrg			      ((info->depthOffset + info->fbLocation) >> 10));
1279209ff23fSmrg    return TRUE;
1280209ff23fSmrg}
1281209ff23fSmrg#endif /* XF86DRI */
1282209ff23fSmrg
1283209ff23fSmrgBool
1284209ff23fSmrgRADEONSetupMemXAA(int scrnIndex, ScreenPtr pScreen)
1285209ff23fSmrg{
1286209ff23fSmrg    ScrnInfoPtr    pScrn = xf86Screens[pScreen->myNum];
1287209ff23fSmrg    RADEONInfoPtr  info  = RADEONPTR(pScrn);
1288209ff23fSmrg    BoxRec         MemBox;
1289209ff23fSmrg    int            y2;
1290209ff23fSmrg
1291209ff23fSmrg    int width_bytes = pScrn->displayWidth * info->CurrentLayout.pixel_bytes;
1292209ff23fSmrg
1293209ff23fSmrg    MemBox.x1 = 0;
1294209ff23fSmrg    MemBox.y1 = 0;
1295209ff23fSmrg    MemBox.x2 = pScrn->displayWidth;
1296209ff23fSmrg    y2 = info->FbMapSize / width_bytes;
1297209ff23fSmrg    if (y2 >= 32768)
1298209ff23fSmrg	y2 = 32767; /* because MemBox.y2 is signed short */
1299209ff23fSmrg    MemBox.y2 = y2;
1300209ff23fSmrg
1301209ff23fSmrg    /* The acceleration engine uses 14 bit
1302209ff23fSmrg     * signed coordinates, so we can't have any
1303209ff23fSmrg     * drawable caches beyond this region.
1304209ff23fSmrg     */
1305209ff23fSmrg    if (MemBox.y2 > 8191)
1306209ff23fSmrg	MemBox.y2 = 8191;
1307209ff23fSmrg
1308209ff23fSmrg    if (!xf86InitFBManager(pScreen, &MemBox)) {
1309209ff23fSmrg	xf86DrvMsg(scrnIndex, X_ERROR,
1310209ff23fSmrg		   "Memory manager initialization to "
1311209ff23fSmrg		   "(%d,%d) (%d,%d) failed\n",
1312209ff23fSmrg		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
1313209ff23fSmrg	return FALSE;
1314209ff23fSmrg    } else {
1315209ff23fSmrg	int       width, height;
1316209ff23fSmrg	FBAreaPtr fbarea;
1317209ff23fSmrg
1318209ff23fSmrg	xf86DrvMsg(scrnIndex, X_INFO,
1319209ff23fSmrg		   "Memory manager initialized to (%d,%d) (%d,%d)\n",
1320209ff23fSmrg		   MemBox.x1, MemBox.y1, MemBox.x2, MemBox.y2);
1321209ff23fSmrg	if ((fbarea = xf86AllocateOffscreenArea(pScreen,
1322209ff23fSmrg						pScrn->displayWidth,
1323209ff23fSmrg						info->allowColorTiling ?
1324209ff23fSmrg						((pScrn->virtualY + 15) & ~15)
1325209ff23fSmrg						- pScrn->virtualY + 2 : 2,
1326209ff23fSmrg						0, NULL, NULL,
1327209ff23fSmrg						NULL))) {
1328209ff23fSmrg	    xf86DrvMsg(scrnIndex, X_INFO,
1329209ff23fSmrg		       "Reserved area from (%d,%d) to (%d,%d)\n",
1330209ff23fSmrg		       fbarea->box.x1, fbarea->box.y1,
1331209ff23fSmrg		       fbarea->box.x2, fbarea->box.y2);
1332209ff23fSmrg	} else {
1333209ff23fSmrg	    xf86DrvMsg(scrnIndex, X_ERROR, "Unable to reserve area\n");
1334209ff23fSmrg	}
1335209ff23fSmrg	if (xf86QueryLargestOffscreenArea(pScreen, &width, &height,
1336209ff23fSmrg					      0, 0, 0)) {
1337209ff23fSmrg	    xf86DrvMsg(scrnIndex, X_INFO,
1338209ff23fSmrg		       "Largest offscreen area available: %d x %d\n",
1339209ff23fSmrg		       width, height);
1340209ff23fSmrg	}
1341209ff23fSmrg	return TRUE;
1342209ff23fSmrg    }
1343209ff23fSmrg}
1344209ff23fSmrg#endif /* USE_XAA */
1345