132b578d3Smrg/*
232b578d3Smrg * Copyright 2003 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
332b578d3Smrg *
432b578d3Smrg * Permission to use, copy, modify, distribute, and sell this software and its
532b578d3Smrg * documentation for any purpose is hereby granted without fee, provided that
632b578d3Smrg * the above copyright notice appear in all copies and that both that copyright
732b578d3Smrg * notice and this permission notice appear in supporting documentation, and
832b578d3Smrg * that the name of Marc Aurele La France not be used in advertising or
932b578d3Smrg * publicity pertaining to distribution of the software without specific,
1032b578d3Smrg * written prior permission.  Marc Aurele La France makes no representations
1132b578d3Smrg * about the suitability of this software for any purpose.  It is provided
1232b578d3Smrg * "as-is" without express or implied warranty.
1332b578d3Smrg *
1432b578d3Smrg * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1532b578d3Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
1632b578d3Smrg * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1732b578d3Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1832b578d3Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1932b578d3Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2032b578d3Smrg * PERFORMANCE OF THIS SOFTWARE.
2132b578d3Smrg */
2232b578d3Smrg/*
2332b578d3Smrg * Copyright 1999-2000 Precision Insight, Inc., Cedar Park, Texas.
2432b578d3Smrg * All Rights Reserved.
2532b578d3Smrg *
2632b578d3Smrg * Permission is hereby granted, free of charge, to any person obtaining a copy
2732b578d3Smrg * of this software and associated documentation files (the "Software"), to
2832b578d3Smrg * deal in the Software without restriction, including without limitation the
2932b578d3Smrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
3032b578d3Smrg * sell copies of the Software, and to permit persons to whom the Software is
3132b578d3Smrg * furnished to do so, subject to the following conditions:
3232b578d3Smrg *
3332b578d3Smrg * The above copyright notice and this permission notice (including the next
3432b578d3Smrg * paragraph) shall be included in all copies or substantial portions of the
3532b578d3Smrg * Software.
3632b578d3Smrg *
3732b578d3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3832b578d3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3932b578d3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
4032b578d3Smrg * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
4132b578d3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
4232b578d3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
4332b578d3Smrg * DEALINGS IN THE SOFTWARE.
4432b578d3Smrg */
4532b578d3Smrg/*
4632b578d3Smrg * DRI support by:
4732b578d3Smrg *    Manuel Teira
4832b578d3Smrg *    Leif Delgass <ldelgass@retinalburn.net>
4932b578d3Smrg */
5032b578d3Smrg
5132b578d3Smrg#ifdef HAVE_CONFIG_H
5232b578d3Smrg#include "config.h"
5332b578d3Smrg#endif
5432b578d3Smrg
5532b578d3Smrg#include "ati.h"
5632b578d3Smrg#include "atichip.h"
5732b578d3Smrg#include "atimach64accel.h"
5832b578d3Smrg#include "atimach64io.h"
5932b578d3Smrg#include "atipriv.h"
6032b578d3Smrg#include "atiregs.h"
6132b578d3Smrg
6232b578d3Smrg#ifdef XF86DRI_DEVEL
6332b578d3Smrg#include "mach64_common.h"
6432b578d3Smrg#endif
6532b578d3Smrg
6632b578d3Smrg#include "miline.h"
6732b578d3Smrg
6832b578d3Smrg/* Used to test MMIO cache integrity in ATIMach64Sync() */
6932b578d3Smrg#define TestRegisterCaching(_Register)                   \
7032b578d3Smrg    if (RegisterIsCached(_Register) &&                   \
7132b578d3Smrg        (CacheSlot(_Register) != inm(_Register)))        \
7232b578d3Smrg    {                                                    \
7332b578d3Smrg        UncacheRegister(_Register);                      \
7432b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,    \
7532b578d3Smrg            #_Register " MMIO write cache disabled!\n"); \
7632b578d3Smrg    }
7732b578d3Smrg
7832b578d3Smrg/*
7932b578d3Smrg * X-to-Mach64 mix translation table.
8032b578d3Smrg */
8132b578d3SmrgCARD8 ATIMach64ALU[16] =
8232b578d3Smrg{
8332b578d3Smrg    MIX_0,                       /* GXclear */
8432b578d3Smrg    MIX_AND,                     /* GXand */
8532b578d3Smrg    MIX_SRC_AND_NOT_DST,         /* GXandReverse */
8632b578d3Smrg    MIX_SRC,                     /* GXcopy */
8732b578d3Smrg    MIX_NOT_SRC_AND_DST,         /* GXandInverted */
8832b578d3Smrg    MIX_DST,                     /* GXnoop */
8932b578d3Smrg    MIX_XOR,                     /* GXxor */
9032b578d3Smrg    MIX_OR,                      /* GXor */
9132b578d3Smrg    MIX_NOR,                     /* GXnor */
9232b578d3Smrg    MIX_XNOR,                    /* GXequiv */
9332b578d3Smrg    MIX_NOT_DST,                 /* GXinvert */
9432b578d3Smrg    MIX_SRC_OR_NOT_DST,          /* GXorReverse */
9532b578d3Smrg    MIX_NOT_SRC,                 /* GXcopyInverted */
9632b578d3Smrg    MIX_NOT_SRC_OR_DST,          /* GXorInverted */
9732b578d3Smrg    MIX_NAND,                    /* GXnand */
9832b578d3Smrg    MIX_1                        /* GXset */
9932b578d3Smrg};
10032b578d3Smrg
10132b578d3Smrg/*
10232b578d3Smrg * ATIMach64ValidateClip --
10332b578d3Smrg *
10432b578d3Smrg * This function ensures the current scissor settings do not interfere with
10532b578d3Smrg * the current draw request.
10632b578d3Smrg */
10732b578d3Smrgvoid
10832b578d3SmrgATIMach64ValidateClip
10932b578d3Smrg(
11032b578d3Smrg    ATIPtr pATI,
11132b578d3Smrg    int    sc_left,
11232b578d3Smrg    int    sc_right,
11332b578d3Smrg    int    sc_top,
11432b578d3Smrg    int    sc_bottom
11532b578d3Smrg)
11632b578d3Smrg{
11732b578d3Smrg    if ((sc_left < (int)pATI->sc_left) || (sc_right > (int)pATI->sc_right))
11832b578d3Smrg    {
11932b578d3Smrg        outf(SC_LEFT_RIGHT, pATI->sc_left_right);
12032b578d3Smrg        pATI->sc_left = pATI->NewHW.sc_left;
12132b578d3Smrg        pATI->sc_right = pATI->NewHW.sc_right;
12232b578d3Smrg    }
12332b578d3Smrg
12432b578d3Smrg    if ((sc_top < (int)pATI->sc_top) || (sc_bottom > (int)pATI->sc_bottom))
12532b578d3Smrg    {
12632b578d3Smrg        outf(SC_TOP_BOTTOM, pATI->sc_top_bottom);
12732b578d3Smrg        pATI->sc_top = pATI->NewHW.sc_top;
12832b578d3Smrg        pATI->sc_bottom = pATI->NewHW.sc_bottom;
12932b578d3Smrg    }
13032b578d3Smrg}
13132b578d3Smrg
13232b578d3Smrgstatic __inline__ void TestRegisterCachingDP(ScrnInfoPtr pScreenInfo);
13332b578d3Smrgstatic __inline__ void TestRegisterCachingXV(ScrnInfoPtr pScreenInfo);
13432b578d3Smrg
13532b578d3Smrg/*
13632b578d3Smrg * ATIMach64Sync --
13732b578d3Smrg *
13832b578d3Smrg * This is called to wait for the draw engine to become idle.
13932b578d3Smrg */
14032b578d3Smrgvoid
14132b578d3SmrgATIMach64Sync
14232b578d3Smrg(
14332b578d3Smrg    ScrnInfoPtr pScreenInfo
14432b578d3Smrg)
14532b578d3Smrg{
14632b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
14732b578d3Smrg
14832b578d3Smrg#ifdef XF86DRI_DEVEL
14932b578d3Smrg
15032b578d3Smrg    if ( pATI->directRenderingEnabled && pATI->NeedDRISync )
15132b578d3Smrg    {
15232b578d3Smrg	ATIHWPtr pATIHW = &pATI->NewHW;
15332b578d3Smrg	CARD32 offset;
15432b578d3Smrg
15532b578d3Smrg	if (pATI->OptionMMIOCache) {
15632b578d3Smrg	    /* "Invalidate" the MMIO cache so the cache slots get updated */
15732b578d3Smrg	    UncacheRegister(SRC_CNTL);
15832b578d3Smrg	    UncacheRegister(SCALE_3D_CNTL);
15932b578d3Smrg	    UncacheRegister(HOST_CNTL);
16032b578d3Smrg	    UncacheRegister(PAT_CNTL);
16132b578d3Smrg	    UncacheRegister(SC_LEFT_RIGHT);
16232b578d3Smrg	    UncacheRegister(SC_TOP_BOTTOM);
16332b578d3Smrg	    UncacheRegister(DP_BKGD_CLR);
16432b578d3Smrg	    UncacheRegister(DP_FRGD_CLR);
16532b578d3Smrg	    UncacheRegister(DP_PIX_WIDTH);
16632b578d3Smrg	    UncacheRegister(DP_MIX);
16732b578d3Smrg	    UncacheRegister(CLR_CMP_CNTL);
16832b578d3Smrg	    UncacheRegister(TEX_SIZE_PITCH);
16932b578d3Smrg	}
17032b578d3Smrg
17132b578d3Smrg	ATIDRIWaitForIdle(pATI);
17232b578d3Smrg
17332b578d3Smrg	outr( BUS_CNTL, pATIHW->bus_cntl );
17432b578d3Smrg
17532b578d3Smrg	/* DRI uses GUI_TRAJ_CNTL, which is a composite of
17632b578d3Smrg	 * src_cntl, dst_cntl, pat_cntl, and host_cntl
17732b578d3Smrg	 */
17832b578d3Smrg	outf( SRC_CNTL, pATIHW->src_cntl );
17932b578d3Smrg	outf( DST_CNTL, pATIHW->dst_cntl );
18032b578d3Smrg	outf( PAT_CNTL, pATIHW->pat_cntl );
18132b578d3Smrg	outf( HOST_CNTL, pATIHW->host_cntl );
18232b578d3Smrg
18332b578d3Smrg	outf( DST_OFF_PITCH, pATIHW->dst_off_pitch );
18432b578d3Smrg	outf( SRC_OFF_PITCH, pATIHW->src_off_pitch );
18532b578d3Smrg	outf( DP_SRC, pATIHW->dp_src );
18632b578d3Smrg	outf( DP_MIX, pATIHW->dp_mix );
18732b578d3Smrg	outf( DP_FRGD_CLR,  pATIHW->dp_frgd_clr );
18832b578d3Smrg	outf( DP_WRITE_MASK, pATIHW->dp_write_mask );
18932b578d3Smrg	outf( DP_PIX_WIDTH, pATIHW->dp_pix_width );
19032b578d3Smrg
19132b578d3Smrg	outf( CLR_CMP_CNTL, pATIHW->clr_cmp_cntl );
19232b578d3Smrg
19332b578d3Smrg	offset = TEX_LEVEL(pATIHW->tex_size_pitch);
19432b578d3Smrg
19532b578d3Smrg	ATIMach64WaitForFIFO(pATI, 6);
19632b578d3Smrg	outf( ALPHA_TST_CNTL, 0 );
19732b578d3Smrg	outf( Z_CNTL, 0 );
19832b578d3Smrg	outf( SCALE_3D_CNTL, pATIHW->scale_3d_cntl );
19932b578d3Smrg	outf( TEX_0_OFF + offset, pATIHW->tex_offset );
20032b578d3Smrg	outf( TEX_SIZE_PITCH, pATIHW->tex_size_pitch );
20132b578d3Smrg	outf( TEX_CNTL, pATIHW->tex_cntl );
20232b578d3Smrg
20332b578d3Smrg	ATIMach64WaitForFIFO(pATI, 2);
20432b578d3Smrg	outf( SC_LEFT_RIGHT,
20532b578d3Smrg	      SetWord(pATIHW->sc_right, 1) | SetWord(pATIHW->sc_left, 0) );
20632b578d3Smrg	outf( SC_TOP_BOTTOM,
20732b578d3Smrg	      SetWord(pATIHW->sc_bottom, 1) | SetWord(pATIHW->sc_top, 0) );
20832b578d3Smrg
20932b578d3Smrg	if (pATI->OptionMMIOCache) {
21032b578d3Smrg	    /* Now that the cache slots reflect the register state, re-enable MMIO cache */
21132b578d3Smrg	    CacheRegister(SRC_CNTL);
21232b578d3Smrg	    CacheRegister(SCALE_3D_CNTL);
21332b578d3Smrg	    CacheRegister(HOST_CNTL);
21432b578d3Smrg	    CacheRegister(PAT_CNTL);
21532b578d3Smrg	    CacheRegister(SC_LEFT_RIGHT);
21632b578d3Smrg	    CacheRegister(SC_TOP_BOTTOM);
21732b578d3Smrg	    CacheRegister(DP_BKGD_CLR);
21832b578d3Smrg	    CacheRegister(DP_FRGD_CLR);
21932b578d3Smrg	    CacheRegister(DP_PIX_WIDTH);
22032b578d3Smrg	    CacheRegister(DP_MIX);
22132b578d3Smrg	    CacheRegister(CLR_CMP_CNTL);
22232b578d3Smrg	    CacheRegister(TEX_SIZE_PITCH);
22332b578d3Smrg	}
22432b578d3Smrg
22532b578d3Smrg	ATIMach64WaitForIdle(pATI);
22632b578d3Smrg
22732b578d3Smrg	if (pATI->OptionMMIOCache && pATI->OptionTestMMIOCache) {
22832b578d3Smrg
22932b578d3Smrg	    /* Only check registers we didn't restore */
23032b578d3Smrg	    TestRegisterCaching(PAT_REG0);
23132b578d3Smrg            TestRegisterCaching(PAT_REG1);
23232b578d3Smrg
23332b578d3Smrg            TestRegisterCaching(CLR_CMP_CLR);
23432b578d3Smrg            TestRegisterCaching(CLR_CMP_MSK);
23532b578d3Smrg
23632b578d3Smrg	    TestRegisterCachingXV(pScreenInfo);
23732b578d3Smrg         }
23832b578d3Smrg	pATI->NeedDRISync = FALSE;
23932b578d3Smrg
24032b578d3Smrg    }
24132b578d3Smrg    else
24232b578d3Smrg
24332b578d3Smrg#endif /* XF86DRI_DEVEL */
24432b578d3Smrg    {
24532b578d3Smrg      ATIMach64WaitForIdle(pATI);
24632b578d3Smrg
24732b578d3Smrg      if (pATI->OptionMMIOCache && pATI->OptionTestMMIOCache)
24832b578d3Smrg      {
24932b578d3Smrg        /*
25032b578d3Smrg         * For debugging purposes, attempt to verify that each cached register
25132b578d3Smrg         * should actually be cached.
25232b578d3Smrg         */
25332b578d3Smrg        TestRegisterCachingDP(pScreenInfo);
25432b578d3Smrg
25532b578d3Smrg        TestRegisterCachingXV(pScreenInfo);
25632b578d3Smrg      }
25732b578d3Smrg    }
25832b578d3Smrg
25932b578d3Smrg#ifdef USE_EXA
26032b578d3Smrg    /* EXA sets pEXA->needsSync to FALSE on its own */
26132b578d3Smrg#endif
26232b578d3Smrg
26332b578d3Smrg#ifdef USE_XAA
26432b578d3Smrg    if (pATI->pXAAInfo)
26532b578d3Smrg        pATI->pXAAInfo->NeedToSync = FALSE;
26632b578d3Smrg#endif
26732b578d3Smrg
26832b578d3Smrg    if (pATI->Chip >= ATI_CHIP_264VTB)
26932b578d3Smrg    {
27032b578d3Smrg        /*
27132b578d3Smrg         * Flush the read-back cache (by turning on INVALIDATE_RB_CACHE),
27232b578d3Smrg         * otherwise the host might get stale data when reading through the
27332b578d3Smrg         * aperture.
27432b578d3Smrg         */
27532b578d3Smrg        outr(MEM_BUF_CNTL, pATI->NewHW.mem_buf_cntl);
27632b578d3Smrg    }
27732b578d3Smrg
27832b578d3Smrg    /*
27932b578d3Smrg     * Note:
28032b578d3Smrg     * Before actually invalidating the read-back cache, the mach64 driver
28132b578d3Smrg     * was using the trick below which is buggy. The code is left here for
28232b578d3Smrg     * reference, DRI uses this trick and needs updating.
28332b578d3Smrg     *
28432b578d3Smrg     * For VTB's and later, the first CPU read of the framebuffer will return
28532b578d3Smrg     * zeroes, so do it here.  This appears to be due to some kind of engine
28632b578d3Smrg     * caching of framebuffer data I haven't found any way of disabling, or
28732b578d3Smrg     * otherwise circumventing.  Thanks to Mark Vojkovich for the suggestion.
28832b578d3Smrg     *
28932b578d3Smrg     * pATI = *(volatile ATIPtr *)pATI->pMemory;
29032b578d3Smrg     */
29132b578d3Smrg}
29232b578d3Smrg
29332b578d3Smrgstatic __inline__ void
29432b578d3SmrgTestRegisterCachingDP(ScrnInfoPtr pScreenInfo)
29532b578d3Smrg{
29632b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
29732b578d3Smrg
29832b578d3Smrg    TestRegisterCaching(SRC_CNTL);
29932b578d3Smrg
30032b578d3Smrg    if (pATI->Chip >= ATI_CHIP_264GTPRO)
30132b578d3Smrg    {
30232b578d3Smrg        TestRegisterCaching(SCALE_3D_CNTL);
30332b578d3Smrg    }
30432b578d3Smrg
30532b578d3Smrg    TestRegisterCaching(HOST_CNTL);
30632b578d3Smrg
30732b578d3Smrg    TestRegisterCaching(PAT_REG0);
30832b578d3Smrg    TestRegisterCaching(PAT_REG1);
30932b578d3Smrg    TestRegisterCaching(PAT_CNTL);
31032b578d3Smrg
31132b578d3Smrg    if (RegisterIsCached(SC_LEFT_RIGHT) &&      /* Special case */
31232b578d3Smrg        (CacheSlot(SC_LEFT_RIGHT) !=
31332b578d3Smrg         (SetWord(inm(SC_RIGHT), 1) | SetWord(inm(SC_LEFT), 0))))
31432b578d3Smrg    {
31532b578d3Smrg        UncacheRegister(SC_LEFT_RIGHT);
31632b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
31732b578d3Smrg            "SC_LEFT_RIGHT write cache disabled!\n");
31832b578d3Smrg    }
31932b578d3Smrg
32032b578d3Smrg    if (RegisterIsCached(SC_TOP_BOTTOM) &&      /* Special case */
32132b578d3Smrg        (CacheSlot(SC_TOP_BOTTOM) !=
32232b578d3Smrg         (SetWord(inm(SC_BOTTOM), 1) | SetWord(inm(SC_TOP), 0))))
32332b578d3Smrg    {
32432b578d3Smrg        UncacheRegister(SC_TOP_BOTTOM);
32532b578d3Smrg        xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
32632b578d3Smrg            "SC_TOP_BOTTOM write cache disabled!\n");
32732b578d3Smrg    }
32832b578d3Smrg
32932b578d3Smrg    TestRegisterCaching(DP_BKGD_CLR);
33032b578d3Smrg    TestRegisterCaching(DP_FRGD_CLR);
33132b578d3Smrg    TestRegisterCaching(DP_PIX_WIDTH);
33232b578d3Smrg    TestRegisterCaching(DP_MIX);
33332b578d3Smrg
33432b578d3Smrg    TestRegisterCaching(CLR_CMP_CLR);
33532b578d3Smrg    TestRegisterCaching(CLR_CMP_MSK);
33632b578d3Smrg    TestRegisterCaching(CLR_CMP_CNTL);
33732b578d3Smrg
33832b578d3Smrg    if (pATI->Chip >= ATI_CHIP_264GTPRO)
33932b578d3Smrg    {
34032b578d3Smrg        TestRegisterCaching(TEX_SIZE_PITCH);
34132b578d3Smrg    }
34232b578d3Smrg}
34332b578d3Smrg
34432b578d3Smrgstatic __inline__ void
34532b578d3SmrgTestRegisterCachingXV(ScrnInfoPtr pScreenInfo)
34632b578d3Smrg{
34732b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
34832b578d3Smrg
34932b578d3Smrg    if (!pATI->Block1Base)
35032b578d3Smrg        return;
35132b578d3Smrg
35232b578d3Smrg    TestRegisterCaching(OVERLAY_Y_X_START);
35332b578d3Smrg    TestRegisterCaching(OVERLAY_Y_X_END);
35432b578d3Smrg
35532b578d3Smrg    TestRegisterCaching(OVERLAY_GRAPHICS_KEY_CLR);
35632b578d3Smrg    TestRegisterCaching(OVERLAY_GRAPHICS_KEY_MSK);
35732b578d3Smrg
35832b578d3Smrg    TestRegisterCaching(OVERLAY_KEY_CNTL);
35932b578d3Smrg
36032b578d3Smrg    TestRegisterCaching(OVERLAY_SCALE_INC);
36132b578d3Smrg    TestRegisterCaching(OVERLAY_SCALE_CNTL);
36232b578d3Smrg
36332b578d3Smrg    TestRegisterCaching(SCALER_HEIGHT_WIDTH);
36432b578d3Smrg
36532b578d3Smrg    TestRegisterCaching(SCALER_TEST);
36632b578d3Smrg
36732b578d3Smrg    TestRegisterCaching(VIDEO_FORMAT);
36832b578d3Smrg
36932b578d3Smrg    if (pATI->Chip < ATI_CHIP_264VTB)
37032b578d3Smrg    {
37132b578d3Smrg        TestRegisterCaching(BUF0_OFFSET);
37232b578d3Smrg        TestRegisterCaching(BUF0_PITCH);
37332b578d3Smrg        TestRegisterCaching(BUF1_OFFSET);
37432b578d3Smrg        TestRegisterCaching(BUF1_PITCH);
37532b578d3Smrg
37632b578d3Smrg        return;
37732b578d3Smrg    }
37832b578d3Smrg
37932b578d3Smrg    TestRegisterCaching(SCALER_BUF0_OFFSET);
38032b578d3Smrg    TestRegisterCaching(SCALER_BUF1_OFFSET);
38132b578d3Smrg    TestRegisterCaching(SCALER_BUF_PITCH);
38232b578d3Smrg
38332b578d3Smrg    TestRegisterCaching(OVERLAY_EXCLUSIVE_HORZ);
38432b578d3Smrg    TestRegisterCaching(OVERLAY_EXCLUSIVE_VERT);
38532b578d3Smrg
38632b578d3Smrg    if (pATI->Chip < ATI_CHIP_264GTPRO)
38732b578d3Smrg        return;
38832b578d3Smrg
38932b578d3Smrg    TestRegisterCaching(SCALER_COLOUR_CNTL);
39032b578d3Smrg
39132b578d3Smrg    TestRegisterCaching(SCALER_H_COEFF0);
39232b578d3Smrg    TestRegisterCaching(SCALER_H_COEFF1);
39332b578d3Smrg    TestRegisterCaching(SCALER_H_COEFF2);
39432b578d3Smrg    TestRegisterCaching(SCALER_H_COEFF3);
39532b578d3Smrg    TestRegisterCaching(SCALER_H_COEFF4);
39632b578d3Smrg
39732b578d3Smrg    TestRegisterCaching(SCALER_BUF0_OFFSET_U);
39832b578d3Smrg    TestRegisterCaching(SCALER_BUF0_OFFSET_V);
39932b578d3Smrg    TestRegisterCaching(SCALER_BUF1_OFFSET_U);
40032b578d3Smrg    TestRegisterCaching(SCALER_BUF1_OFFSET_V);
40132b578d3Smrg}
40232b578d3Smrg
40332b578d3Smrg#ifdef USE_XAA
40432b578d3Smrg/*
40532b578d3Smrg * ATIMach64SetupForScreenToScreenCopy --
40632b578d3Smrg *
40732b578d3Smrg * This function sets up the draw engine for a series of screen-to-screen copy
40832b578d3Smrg * operations.
40932b578d3Smrg */
41032b578d3Smrgstatic void
41132b578d3SmrgATIMach64SetupForScreenToScreenCopy
41232b578d3Smrg(
41332b578d3Smrg    ScrnInfoPtr  pScreenInfo,
41432b578d3Smrg    int          xdir,
41532b578d3Smrg    int          ydir,
41632b578d3Smrg    int          rop,
41732b578d3Smrg    unsigned int planemask,
41832b578d3Smrg    int          TransparencyColour
41932b578d3Smrg)
42032b578d3Smrg{
42132b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
42232b578d3Smrg
42332b578d3Smrg    ATIDRISync(pScreenInfo);
42432b578d3Smrg
42532b578d3Smrg    ATIMach64WaitForFIFO(pATI, 3);
42632b578d3Smrg    outf(DP_WRITE_MASK, planemask);
42732b578d3Smrg    outf(DP_SRC, DP_MONO_SRC_ALLONES |
42832b578d3Smrg        SetBits(SRC_BLIT, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
42932b578d3Smrg    outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
43032b578d3Smrg
43132b578d3Smrg#ifdef AVOID_DGA
43232b578d3Smrg
43332b578d3Smrg    if (TransparencyColour == -1)
43432b578d3Smrg
43532b578d3Smrg#else /* AVOID_DGA */
43632b578d3Smrg
43732b578d3Smrg    if (!pATI->XAAForceTransBlit && (TransparencyColour == -1))
43832b578d3Smrg
43932b578d3Smrg#endif /* AVOID_DGA */
44032b578d3Smrg
44132b578d3Smrg    {
44232b578d3Smrg        outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
44332b578d3Smrg    }
44432b578d3Smrg    else
44532b578d3Smrg    {
44632b578d3Smrg        ATIMach64WaitForFIFO(pATI, 2);
44732b578d3Smrg        outf(CLR_CMP_CLR, TransparencyColour);
44832b578d3Smrg        outf(CLR_CMP_CNTL, CLR_CMP_FN_EQUAL | CLR_CMP_SRC_2D);
44932b578d3Smrg    }
45032b578d3Smrg
45132b578d3Smrg    pATI->dst_cntl = 0;
45232b578d3Smrg
45332b578d3Smrg    if (ydir > 0)
45432b578d3Smrg        pATI->dst_cntl |= DST_Y_DIR;
45532b578d3Smrg    if (xdir > 0)
45632b578d3Smrg        pATI->dst_cntl |= DST_X_DIR;
45732b578d3Smrg
45832b578d3Smrg    if (pATI->XModifier == 1)
45932b578d3Smrg        outf(DST_CNTL, pATI->dst_cntl);
46032b578d3Smrg    else
46132b578d3Smrg        pATI->dst_cntl |= DST_24_ROT_EN;
46232b578d3Smrg}
46332b578d3Smrg
46432b578d3Smrg/*
46532b578d3Smrg * ATIMach64SubsequentScreenToScreenCopy --
46632b578d3Smrg *
46732b578d3Smrg * This function performs a screen-to-screen copy operation.
46832b578d3Smrg */
46932b578d3Smrgstatic void
47032b578d3SmrgATIMach64SubsequentScreenToScreenCopy
47132b578d3Smrg(
47232b578d3Smrg    ScrnInfoPtr pScreenInfo,
47332b578d3Smrg    int         xSrc,
47432b578d3Smrg    int         ySrc,
47532b578d3Smrg    int         xDst,
47632b578d3Smrg    int         yDst,
47732b578d3Smrg    int         w,
47832b578d3Smrg    int         h
47932b578d3Smrg)
48032b578d3Smrg{
48132b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
48232b578d3Smrg
48332b578d3Smrg    xSrc *= pATI->XModifier;
48432b578d3Smrg    xDst *= pATI->XModifier;
48532b578d3Smrg    w    *= pATI->XModifier;
48632b578d3Smrg
48732b578d3Smrg    ATIDRISync(pScreenInfo);
48832b578d3Smrg
48932b578d3Smrg    /* Disable clipping if it gets in the way */
49032b578d3Smrg    ATIMach64ValidateClip(pATI, xDst, xDst + w - 1, yDst, yDst + h - 1);
49132b578d3Smrg
49232b578d3Smrg    if (!(pATI->dst_cntl & DST_X_DIR))
49332b578d3Smrg    {
49432b578d3Smrg        xSrc += w - 1;
49532b578d3Smrg        xDst += w - 1;
49632b578d3Smrg    }
49732b578d3Smrg
49832b578d3Smrg    if (!(pATI->dst_cntl & DST_Y_DIR))
49932b578d3Smrg    {
50032b578d3Smrg        ySrc += h - 1;
50132b578d3Smrg        yDst += h - 1;
50232b578d3Smrg    }
50332b578d3Smrg
50432b578d3Smrg    if (pATI->XModifier != 1)
50532b578d3Smrg        outf(DST_CNTL, pATI->dst_cntl | SetBits((xDst / 4) % 6, DST_24_ROT));
50632b578d3Smrg
50732b578d3Smrg    ATIMach64WaitForFIFO(pATI, 4);
50832b578d3Smrg    outf(SRC_Y_X, SetWord(xSrc, 1) | SetWord(ySrc, 0));
50932b578d3Smrg    outf(SRC_WIDTH1, w);
51032b578d3Smrg    outf(DST_Y_X, SetWord(xDst, 1) | SetWord(yDst, 0));
51132b578d3Smrg    outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
51232b578d3Smrg
51332b578d3Smrg    /*
51432b578d3Smrg     * On VTB's and later, the engine will randomly not wait for a copy
51532b578d3Smrg     * operation to commit its results to video memory before starting the next
51632b578d3Smrg     * one.  The probability of such occurrences increases with GUI_WB_FLUSH
51732b578d3Smrg     * (or GUI_WB_FLUSH_P) setting, bitsPerPixel and/or CRTC clock.  This
51832b578d3Smrg     * would point to some kind of video memory bandwidth problem were it noti
51932b578d3Smrg     * for the fact that the problem occurs less often (but still occurs) when
52032b578d3Smrg     * copying larger rectangles.
52132b578d3Smrg     */
52232b578d3Smrg    if ((pATI->Chip >= ATI_CHIP_264VTB) && !pATI->OptionDevel)
52332b578d3Smrg        ATIMach64Sync(pScreenInfo);
52432b578d3Smrg}
52532b578d3Smrg
52632b578d3Smrg/*
52732b578d3Smrg * ATIMach64SetupForSolidFill --
52832b578d3Smrg *
52932b578d3Smrg * This function sets up the draw engine for a series of solid fills.
53032b578d3Smrg */
53132b578d3Smrgstatic void
53232b578d3SmrgATIMach64SetupForSolidFill
53332b578d3Smrg(
53432b578d3Smrg    ScrnInfoPtr  pScreenInfo,
53532b578d3Smrg    int          colour,
53632b578d3Smrg    int          rop,
53732b578d3Smrg    unsigned int planemask
53832b578d3Smrg)
53932b578d3Smrg{
54032b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
54132b578d3Smrg
54232b578d3Smrg    ATIDRISync(pScreenInfo);
54332b578d3Smrg
54432b578d3Smrg    ATIMach64WaitForFIFO(pATI, 5);
54532b578d3Smrg    outf(DP_WRITE_MASK, planemask);
54632b578d3Smrg    outf(DP_SRC, DP_MONO_SRC_ALLONES |
54732b578d3Smrg        SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
54832b578d3Smrg    outf(DP_FRGD_CLR, colour);
54932b578d3Smrg    outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
55032b578d3Smrg
55132b578d3Smrg    outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
55232b578d3Smrg
55332b578d3Smrg    if (pATI->XModifier == 1)
55432b578d3Smrg        outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
55532b578d3Smrg}
55632b578d3Smrg
55732b578d3Smrg/*
55832b578d3Smrg * ATIMach64SubsequentSolidFillRect --
55932b578d3Smrg *
56032b578d3Smrg * This function performs a solid rectangle fill.
56132b578d3Smrg */
56232b578d3Smrgstatic void
56332b578d3SmrgATIMach64SubsequentSolidFillRect
56432b578d3Smrg(
56532b578d3Smrg    ScrnInfoPtr pScreenInfo,
56632b578d3Smrg    int         x,
56732b578d3Smrg    int         y,
56832b578d3Smrg    int         w,
56932b578d3Smrg    int         h
57032b578d3Smrg)
57132b578d3Smrg{
57232b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
57332b578d3Smrg
57432b578d3Smrg    ATIDRISync(pScreenInfo);
57532b578d3Smrg
57632b578d3Smrg    if (pATI->XModifier != 1)
57732b578d3Smrg    {
57832b578d3Smrg        x *= pATI->XModifier;
57932b578d3Smrg        w *= pATI->XModifier;
58032b578d3Smrg
58132b578d3Smrg        outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
58232b578d3Smrg            (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
58332b578d3Smrg    }
58432b578d3Smrg
58532b578d3Smrg    /* Disable clipping if it gets in the way */
58632b578d3Smrg    ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1);
58732b578d3Smrg
58832b578d3Smrg    ATIMach64WaitForFIFO(pATI, 2);
58932b578d3Smrg    outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
59032b578d3Smrg    outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
59132b578d3Smrg}
59232b578d3Smrg
59332b578d3Smrg/*
59432b578d3Smrg * ATIMach64SetupForSolidLine --
59532b578d3Smrg *
59632b578d3Smrg * This function sets up the draw engine for a series of solid lines.  It is
59732b578d3Smrg * not used for 24bpp because the engine doesn't support it.
59832b578d3Smrg */
59932b578d3Smrgstatic void
60032b578d3SmrgATIMach64SetupForSolidLine
60132b578d3Smrg(
60232b578d3Smrg    ScrnInfoPtr  pScreenInfo,
60332b578d3Smrg    int          colour,
60432b578d3Smrg    int          rop,
60532b578d3Smrg    unsigned int planemask
60632b578d3Smrg)
60732b578d3Smrg{
60832b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
60932b578d3Smrg
61032b578d3Smrg    ATIDRISync(pScreenInfo);
61132b578d3Smrg
61232b578d3Smrg    ATIMach64WaitForFIFO(pATI, 5);
61332b578d3Smrg    outf(DP_WRITE_MASK, planemask);
61432b578d3Smrg    outf(DP_SRC, DP_MONO_SRC_ALLONES |
61532b578d3Smrg        SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
61632b578d3Smrg    outf(DP_FRGD_CLR, colour);
61732b578d3Smrg    outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX));
61832b578d3Smrg
61932b578d3Smrg    outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
62032b578d3Smrg
62132b578d3Smrg    ATIMach64ValidateClip(pATI, pATI->NewHW.sc_left, pATI->NewHW.sc_right,
62232b578d3Smrg        pATI->NewHW.sc_top, pATI->NewHW.sc_bottom);
62332b578d3Smrg}
62432b578d3Smrg
62532b578d3Smrg/*
62632b578d3Smrg * ATIMach64SubsequentSolidHorVertLine --
62732b578d3Smrg *
62832b578d3Smrg * This is called to draw a solid horizontal or vertical line.  This does a
62932b578d3Smrg * one-pixel wide solid fill.
63032b578d3Smrg */
63132b578d3Smrgstatic void
63232b578d3SmrgATIMach64SubsequentSolidHorVertLine
63332b578d3Smrg(
63432b578d3Smrg    ScrnInfoPtr pScreenInfo,
63532b578d3Smrg    int         x,
63632b578d3Smrg    int         y,
63732b578d3Smrg    int         len,
63832b578d3Smrg    int         dir
63932b578d3Smrg)
64032b578d3Smrg{
64132b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
64232b578d3Smrg
64332b578d3Smrg    ATIDRISync(pScreenInfo);
64432b578d3Smrg
64532b578d3Smrg    ATIMach64WaitForFIFO(pATI, 3);
64632b578d3Smrg    outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
64732b578d3Smrg    outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
64832b578d3Smrg
64932b578d3Smrg    if (dir == DEGREES_0)
65032b578d3Smrg        outf(DST_HEIGHT_WIDTH, SetWord(len, 1) | SetWord(1, 0));
65132b578d3Smrg    else /* if (dir == DEGREES_270) */
65232b578d3Smrg        outf(DST_HEIGHT_WIDTH, SetWord(1, 1) | SetWord(len, 0));
65332b578d3Smrg}
65432b578d3Smrg
65532b578d3Smrg/*
65632b578d3Smrg * ATIMach64SubsequentSolidBresenhamLine --
65732b578d3Smrg *
65832b578d3Smrg * This function draws a line using the Bresenham line engine.
65932b578d3Smrg */
66032b578d3Smrgstatic void
66132b578d3SmrgATIMach64SubsequentSolidBresenhamLine
66232b578d3Smrg(
66332b578d3Smrg    ScrnInfoPtr pScreenInfo,
66432b578d3Smrg    int         x,
66532b578d3Smrg    int         y,
66632b578d3Smrg    int         major,
66732b578d3Smrg    int         minor,
66832b578d3Smrg    int         err,
66932b578d3Smrg    int         len,
67032b578d3Smrg    int         octant
67132b578d3Smrg)
67232b578d3Smrg{
67332b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
67432b578d3Smrg    CARD32 dst_cntl = DST_LAST_PEL;
67532b578d3Smrg
67632b578d3Smrg    if (octant & YMAJOR)
67732b578d3Smrg        dst_cntl |= DST_Y_MAJOR;
67832b578d3Smrg
67932b578d3Smrg    if (!(octant & XDECREASING))
68032b578d3Smrg        dst_cntl |= DST_X_DIR;
68132b578d3Smrg
68232b578d3Smrg    if (!(octant & YDECREASING))
68332b578d3Smrg        dst_cntl |= DST_Y_DIR;
68432b578d3Smrg
68532b578d3Smrg    ATIDRISync(pScreenInfo);
68632b578d3Smrg
68732b578d3Smrg    ATIMach64WaitForFIFO(pATI, 6);
68832b578d3Smrg    outf(DST_CNTL, dst_cntl);
68932b578d3Smrg    outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
69032b578d3Smrg    outf(DST_BRES_ERR, minor + err);
69132b578d3Smrg    outf(DST_BRES_INC, minor);
69232b578d3Smrg    outf(DST_BRES_DEC, minor - major);
69332b578d3Smrg    outf(DST_BRES_LNTH, len);
69432b578d3Smrg}
69532b578d3Smrg
69632b578d3Smrg/*
69732b578d3Smrg * ATIMach64SetupForMono8x8PatternFill --
69832b578d3Smrg *
69932b578d3Smrg * This function sets up the draw engine for a series of 8x8 1bpp pattern
70032b578d3Smrg * fills.
70132b578d3Smrg */
70232b578d3Smrgstatic void
70332b578d3SmrgATIMach64SetupForMono8x8PatternFill
70432b578d3Smrg(
70532b578d3Smrg    ScrnInfoPtr  pScreenInfo,
70632b578d3Smrg    int          patx,
70732b578d3Smrg    int          paty,
70832b578d3Smrg    int          fg,
70932b578d3Smrg    int          bg,
71032b578d3Smrg    int          rop,
71132b578d3Smrg    unsigned int planemask
71232b578d3Smrg)
71332b578d3Smrg{
71432b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
71532b578d3Smrg
71632b578d3Smrg    ATIDRISync(pScreenInfo);
71732b578d3Smrg
71832b578d3Smrg    ATIMach64WaitForFIFO(pATI, 3);
71932b578d3Smrg    outf(DP_WRITE_MASK, planemask);
72032b578d3Smrg    outf(DP_SRC, DP_MONO_SRC_PATTERN |
72132b578d3Smrg        SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
72232b578d3Smrg    outf(DP_FRGD_CLR, fg);
72332b578d3Smrg
72432b578d3Smrg    if (bg == -1)
72532b578d3Smrg    {
72632b578d3Smrg        outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
72732b578d3Smrg            SetBits(MIX_DST, DP_BKGD_MIX));
72832b578d3Smrg    }
72932b578d3Smrg    else
73032b578d3Smrg    {
73132b578d3Smrg        ATIMach64WaitForFIFO(pATI, 2);
73232b578d3Smrg        outf(DP_BKGD_CLR, bg);
73332b578d3Smrg        outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
73432b578d3Smrg            SetBits(ATIMach64ALU[rop], DP_BKGD_MIX));
73532b578d3Smrg    }
73632b578d3Smrg
73732b578d3Smrg    ATIMach64WaitForFIFO(pATI, 4);
73832b578d3Smrg    outf(PAT_REG0, patx);
73932b578d3Smrg    outf(PAT_REG1, paty);
74032b578d3Smrg    outf(PAT_CNTL, PAT_MONO_EN);
74132b578d3Smrg
74232b578d3Smrg    outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
74332b578d3Smrg
74432b578d3Smrg    if (pATI->XModifier == 1)
74532b578d3Smrg        outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
74632b578d3Smrg}
74732b578d3Smrg
74832b578d3Smrg/*
74932b578d3Smrg * ATIMach64SubsequentMono8x8PatternFillRect --
75032b578d3Smrg *
75132b578d3Smrg * This function performs an 8x8 1bpp pattern fill.
75232b578d3Smrg */
75332b578d3Smrgstatic void
75432b578d3SmrgATIMach64SubsequentMono8x8PatternFillRect
75532b578d3Smrg(
75632b578d3Smrg    ScrnInfoPtr pScreenInfo,
75732b578d3Smrg    int         patx,
75832b578d3Smrg    int         paty,
75932b578d3Smrg    int         x,
76032b578d3Smrg    int         y,
76132b578d3Smrg    int         w,
76232b578d3Smrg    int         h
76332b578d3Smrg)
76432b578d3Smrg{
76532b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
76632b578d3Smrg
76732b578d3Smrg    ATIDRISync(pScreenInfo);
76832b578d3Smrg
76932b578d3Smrg    if (pATI->XModifier != 1)
77032b578d3Smrg    {
77132b578d3Smrg        x *= pATI->XModifier;
77232b578d3Smrg        w *= pATI->XModifier;
77332b578d3Smrg
77432b578d3Smrg        outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
77532b578d3Smrg            (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
77632b578d3Smrg    }
77732b578d3Smrg
77832b578d3Smrg    /* Disable clipping if it gets in the way */
77932b578d3Smrg    ATIMach64ValidateClip(pATI, x, x + w - 1, y, y + h - 1);
78032b578d3Smrg
78132b578d3Smrg    ATIMach64WaitForFIFO(pATI, 2);
78232b578d3Smrg    outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
78332b578d3Smrg    outf(DST_HEIGHT_WIDTH, SetWord(w, 1) | SetWord(h, 0));
78432b578d3Smrg}
78532b578d3Smrg
78632b578d3Smrg/*
78732b578d3Smrg * ATIMach64SetupForScanlineCPUToScreenColorExpandFill --
78832b578d3Smrg *
78932b578d3Smrg * This function sets up the engine for a series of colour expansion fills.
79032b578d3Smrg */
79132b578d3Smrgstatic void
79232b578d3SmrgATIMach64SetupForScanlineCPUToScreenColorExpandFill
79332b578d3Smrg(
79432b578d3Smrg    ScrnInfoPtr  pScreenInfo,
79532b578d3Smrg    int          fg,
79632b578d3Smrg    int          bg,
79732b578d3Smrg    int          rop,
79832b578d3Smrg    unsigned int planemask
79932b578d3Smrg)
80032b578d3Smrg{
80132b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
80232b578d3Smrg
80332b578d3Smrg    ATIDRISync(pScreenInfo);
80432b578d3Smrg
80532b578d3Smrg    ATIMach64WaitForFIFO(pATI, 3);
80632b578d3Smrg    outf(DP_WRITE_MASK, planemask);
80732b578d3Smrg    outf(DP_SRC, DP_MONO_SRC_HOST |
80832b578d3Smrg        SetBits(SRC_FRGD, DP_FRGD_SRC) | SetBits(SRC_BKGD, DP_BKGD_SRC));
80932b578d3Smrg    outf(DP_FRGD_CLR, fg);
81032b578d3Smrg
81132b578d3Smrg    if (bg == -1)
81232b578d3Smrg    {
81332b578d3Smrg        outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
81432b578d3Smrg            SetBits(MIX_DST, DP_BKGD_MIX));
81532b578d3Smrg    }
81632b578d3Smrg    else
81732b578d3Smrg    {
81832b578d3Smrg        ATIMach64WaitForFIFO(pATI, 2);
81932b578d3Smrg        outf(DP_BKGD_CLR, bg);
82032b578d3Smrg        outf(DP_MIX, SetBits(ATIMach64ALU[rop], DP_FRGD_MIX) |
82132b578d3Smrg            SetBits(ATIMach64ALU[rop], DP_BKGD_MIX));
82232b578d3Smrg    }
82332b578d3Smrg
82432b578d3Smrg    outf(CLR_CMP_CNTL, CLR_CMP_FN_FALSE);
82532b578d3Smrg
82632b578d3Smrg    if (pATI->XModifier == 1)
82732b578d3Smrg        outf(DST_CNTL, DST_X_DIR | DST_Y_DIR);
82832b578d3Smrg}
82932b578d3Smrg
83032b578d3Smrg/*
83132b578d3Smrg * ATIMach64SubsequentScanlineCPUToScreenColorExpandFill --
83232b578d3Smrg *
83332b578d3Smrg * This function sets up the engine for a single colour expansion fill.
83432b578d3Smrg */
83532b578d3Smrgstatic void
83632b578d3SmrgATIMach64SubsequentScanlineCPUToScreenColorExpandFill
83732b578d3Smrg(
83832b578d3Smrg    ScrnInfoPtr pScreenInfo,
83932b578d3Smrg    int         x,
84032b578d3Smrg    int         y,
84132b578d3Smrg    int         w,
84232b578d3Smrg    int         h,
84332b578d3Smrg    int         skipleft
84432b578d3Smrg)
84532b578d3Smrg{
84632b578d3Smrg    ATIPtr pATI = ATIPTR(pScreenInfo);
84732b578d3Smrg
84832b578d3Smrg    ATIDRISync(pScreenInfo);
84932b578d3Smrg
85032b578d3Smrg    if (pATI->XModifier != 1)
85132b578d3Smrg    {
85232b578d3Smrg        x *= pATI->XModifier;
85332b578d3Smrg        w *= pATI->XModifier;
85432b578d3Smrg        skipleft *= pATI->XModifier;
85532b578d3Smrg
85632b578d3Smrg        outf(DST_CNTL, SetBits((x / 4) % 6, DST_24_ROT) |
85732b578d3Smrg            (DST_X_DIR | DST_Y_DIR | DST_24_ROT_EN));
85832b578d3Smrg    }
85932b578d3Smrg
86032b578d3Smrg    pATI->ExpansionBitmapWidth = (w + 31) / 32;
86132b578d3Smrg
86232b578d3Smrg    ATIMach64WaitForFIFO(pATI, 3);
86332b578d3Smrg    pATI->sc_left = x + skipleft;
86432b578d3Smrg    pATI->sc_right = x + w - 1;
86532b578d3Smrg    outf(SC_LEFT_RIGHT,
86632b578d3Smrg        SetWord(pATI->sc_right, 1) | SetWord(pATI->sc_left, 0));
86732b578d3Smrg    outf(DST_Y_X, SetWord(x, 1) | SetWord(y, 0));
86832b578d3Smrg    outf(DST_HEIGHT_WIDTH,
86932b578d3Smrg        SetWord(pATI->ExpansionBitmapWidth * 32, 1) | SetWord(h, 0));
87032b578d3Smrg}
87132b578d3Smrg
87232b578d3Smrg/*
87332b578d3Smrg * ATIMach64SubsequentColorExpandScanline --
87432b578d3Smrg *
87532b578d3Smrg * This function feeds a bitmap scanline to the engine for a colour expansion
87632b578d3Smrg * fill.  This is written to do burst transfers for those platforms that can do
87732b578d3Smrg * them, and to improve CPU/engine concurrency.
87832b578d3Smrg */
87932b578d3Smrgstatic void
88032b578d3SmrgATIMach64SubsequentColorExpandScanline
88132b578d3Smrg(
88232b578d3Smrg    ScrnInfoPtr pScreenInfo,
88332b578d3Smrg    int         iBuffer
88432b578d3Smrg)
88532b578d3Smrg{
88632b578d3Smrg    ATIPtr          pATI         = ATIPTR(pScreenInfo);
88732b578d3Smrg    CARD32          *pBitmapData = pATI->ExpansionBitmapScanlinePtr[iBuffer];
88832b578d3Smrg    int             w            = pATI->ExpansionBitmapWidth;
88932b578d3Smrg    int             nDWord;
89032b578d3Smrg
89132b578d3Smrg    ATIDRISync(pScreenInfo);
89232b578d3Smrg
89332b578d3Smrg    while (w > 0)
89432b578d3Smrg    {
89532b578d3Smrg        /*
89632b578d3Smrg         * Transfers are done in chunks of up to 64 bytes in length (32 on
89732b578d3Smrg         * earlier controllers).
89832b578d3Smrg         */
89932b578d3Smrg        nDWord = w;
90032b578d3Smrg        if (nDWord > pATI->nHostFIFOEntries)
90132b578d3Smrg            nDWord = pATI->nHostFIFOEntries;
90232b578d3Smrg
90332b578d3Smrg        /* Make enough FIFO slots available */
90432b578d3Smrg        ATIMach64WaitForFIFO(pATI, nDWord);
90532b578d3Smrg
90632b578d3Smrg        /*
90732b578d3Smrg         * Always start transfers on a chuck-sized boundary.  Note that
90832b578d3Smrg         * HOST_DATA_0 is actually on a 512-byte boundary, but *pBitmapData can
90932b578d3Smrg         * only be guaranteed to be on a chunk-sized boundary.
91032b578d3Smrg         *
91132b578d3Smrg         * Transfer current chunk.  With any luck, the compiler won't mangle
91232b578d3Smrg         * this too badly...
91332b578d3Smrg         */
91432b578d3Smrg
91532b578d3Smrg#       if defined(ATIMove32)
91632b578d3Smrg
91732b578d3Smrg        {
91832b578d3Smrg            ATIMove32(pATI->pHOST_DATA, pBitmapData, nDWord);
91932b578d3Smrg        }
92032b578d3Smrg
92132b578d3Smrg#       else
92232b578d3Smrg
92332b578d3Smrg        {
92432b578d3Smrg            volatile CARD32 *pDst;
92532b578d3Smrg            CARD32          *pSrc;
92632b578d3Smrg            unsigned int    iDWord;
92732b578d3Smrg
92832b578d3Smrg            iDWord = 16 - nDWord;
92932b578d3Smrg            pDst = (volatile CARD32 *)pATI->pHOST_DATA - iDWord;
93032b578d3Smrg            pSrc = pBitmapData - iDWord;
93132b578d3Smrg
93232b578d3Smrg            switch (iDWord)
93332b578d3Smrg            {
93432b578d3Smrg                case  0:  MMIO_MOVE32(pDst +  0, 0, *(pSrc +  0));
93532b578d3Smrg                case  1:  MMIO_MOVE32(pDst +  1, 0, *(pSrc +  1));
93632b578d3Smrg                case  2:  MMIO_MOVE32(pDst +  2, 0, *(pSrc +  2));
93732b578d3Smrg                case  3:  MMIO_MOVE32(pDst +  3, 0, *(pSrc +  3));
93832b578d3Smrg                case  4:  MMIO_MOVE32(pDst +  4, 0, *(pSrc +  4));
93932b578d3Smrg                case  5:  MMIO_MOVE32(pDst +  5, 0, *(pSrc +  5));
94032b578d3Smrg                case  6:  MMIO_MOVE32(pDst +  6, 0, *(pSrc +  6));
94132b578d3Smrg                case  7:  MMIO_MOVE32(pDst +  7, 0, *(pSrc +  7));
94232b578d3Smrg                case  8:  MMIO_MOVE32(pDst +  8, 0, *(pSrc +  8));
94332b578d3Smrg                case  9:  MMIO_MOVE32(pDst +  9, 0, *(pSrc +  9));
94432b578d3Smrg                case 10:  MMIO_MOVE32(pDst + 10, 0, *(pSrc + 10));
94532b578d3Smrg                case 11:  MMIO_MOVE32(pDst + 11, 0, *(pSrc + 11));
94632b578d3Smrg                case 12:  MMIO_MOVE32(pDst + 12, 0, *(pSrc + 12));
94732b578d3Smrg                case 13:  MMIO_MOVE32(pDst + 13, 0, *(pSrc + 13));
94832b578d3Smrg                case 14:  MMIO_MOVE32(pDst + 14, 0, *(pSrc + 14));
94932b578d3Smrg                case 15:  MMIO_MOVE32(pDst + 15, 0, *(pSrc + 15));
95032b578d3Smrg
95132b578d3Smrg                default:    /* Muffle compiler */
95232b578d3Smrg                    break;
95332b578d3Smrg            }
95432b578d3Smrg        }
95532b578d3Smrg
95632b578d3Smrg#       endif
95732b578d3Smrg
95832b578d3Smrg        /* Step to next chunk */
95932b578d3Smrg        pBitmapData += nDWord;
96032b578d3Smrg        w -= nDWord;
96132b578d3Smrg        pATI->nAvailableFIFOEntries -= nDWord;
96232b578d3Smrg    }
96332b578d3Smrg
96432b578d3Smrg    pATI->EngineIsBusy = TRUE;
96532b578d3Smrg}
96632b578d3Smrg
96732b578d3Smrg/*
96832b578d3Smrg * ATIMach64AccelInit --
96932b578d3Smrg *
97032b578d3Smrg * This function fills in structure fields needed for acceleration on Mach64
97132b578d3Smrg * variants.
97232b578d3Smrg */
97332b578d3SmrgBool
97432b578d3SmrgATIMach64AccelInit
97532b578d3Smrg(
97632b578d3Smrg    ScreenPtr pScreen
97732b578d3Smrg)
97832b578d3Smrg{
979e35d4d8eSmrg    ScrnInfoPtr   pScreenInfo = xf86ScreenToScrn(pScreen);
98032b578d3Smrg    ATIPtr        pATI        = ATIPTR(pScreenInfo);
98132b578d3Smrg    XAAInfoRecPtr pXAAInfo;
98232b578d3Smrg
98332b578d3Smrg    if (!(pATI->pXAAInfo = XAACreateInfoRec()))
98432b578d3Smrg        return FALSE;
98532b578d3Smrg
98632b578d3Smrg    pXAAInfo = pATI->pXAAInfo;
98732b578d3Smrg
98832b578d3Smrg    /* This doesn't seem quite right... */
98932b578d3Smrg    if (pATI->XModifier == 1)
99032b578d3Smrg    {
99132b578d3Smrg        pXAAInfo->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
99232b578d3Smrg        pXAAInfo->Flags |= LINEAR_FRAMEBUFFER;
99332b578d3Smrg    }
99432b578d3Smrg
99532b578d3Smrg    /* Sync */
99632b578d3Smrg    pXAAInfo->Sync = ATIMach64Sync;
99732b578d3Smrg
99832b578d3Smrg    /* Screen-to-screen copy */
99932b578d3Smrg    pXAAInfo->SetupForScreenToScreenCopy = ATIMach64SetupForScreenToScreenCopy;
100032b578d3Smrg    pXAAInfo->SubsequentScreenToScreenCopy =
100132b578d3Smrg        ATIMach64SubsequentScreenToScreenCopy;
100232b578d3Smrg
100332b578d3Smrg    /* Solid fills */
100432b578d3Smrg    pXAAInfo->SetupForSolidFill = ATIMach64SetupForSolidFill;
100532b578d3Smrg    pXAAInfo->SubsequentSolidFillRect = ATIMach64SubsequentSolidFillRect;
100632b578d3Smrg
100732b578d3Smrg    /* 8x8 mono pattern fills */
100832b578d3Smrg    pXAAInfo->Mono8x8PatternFillFlags =
100932b578d3Smrg
101032b578d3Smrg#if X_BYTE_ORDER != X_LITTLE_ENDIAN
101132b578d3Smrg
101232b578d3Smrg        BIT_ORDER_IN_BYTE_MSBFIRST |
101332b578d3Smrg
101432b578d3Smrg#endif /* X_BYTE_ORDER */
101532b578d3Smrg
101632b578d3Smrg        HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_SCREEN_ORIGIN;
101732b578d3Smrg    pXAAInfo->SetupForMono8x8PatternFill = ATIMach64SetupForMono8x8PatternFill;
101832b578d3Smrg    pXAAInfo->SubsequentMono8x8PatternFillRect =
101932b578d3Smrg        ATIMach64SubsequentMono8x8PatternFillRect;
102032b578d3Smrg
102132b578d3Smrg    /*
102232b578d3Smrg     * Use scanline version of colour expansion, not only for the non-ix86
102332b578d3Smrg     * case, but also to avoid PCI retries.
102432b578d3Smrg     */
102532b578d3Smrg    pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags =
102632b578d3Smrg        LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X |
102732b578d3Smrg        CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD;
102832b578d3Smrg    if (pATI->XModifier != 1)
102932b578d3Smrg        pXAAInfo->ScanlineCPUToScreenColorExpandFillFlags |= TRIPLE_BITS_24BPP;
103032b578d3Smrg    pXAAInfo->NumScanlineColorExpandBuffers = 1;
103132b578d3Smrg
103232b578d3Smrg    /* Align bitmap data on a 64-byte boundary */
103332b578d3Smrg    pATI->ExpansionBitmapWidth =        /* DWord size in bits */
103432b578d3Smrg        ((pATI->displayWidth * pATI->XModifier) + 31) & ~31U;
103532b578d3Smrg    pATI->ExpansionBitmapScanlinePtr[1] =
103632b578d3Smrg        (CARD32 *)xnfalloc((pATI->ExpansionBitmapWidth >> 3) + 63);
103732b578d3Smrg    pATI->ExpansionBitmapScanlinePtr[0] =
103832b578d3Smrg        (pointer)(((unsigned long)pATI->ExpansionBitmapScanlinePtr[1] + 63) &
103932b578d3Smrg                  ~63UL);
104032b578d3Smrg    pXAAInfo->ScanlineColorExpandBuffers =
104132b578d3Smrg        (CARD8 **)pATI->ExpansionBitmapScanlinePtr;
104232b578d3Smrg    pXAAInfo->SetupForScanlineCPUToScreenColorExpandFill =
104332b578d3Smrg        ATIMach64SetupForScanlineCPUToScreenColorExpandFill;
104432b578d3Smrg    pXAAInfo->SubsequentScanlineCPUToScreenColorExpandFill =
104532b578d3Smrg        ATIMach64SubsequentScanlineCPUToScreenColorExpandFill;
104632b578d3Smrg    pXAAInfo->SubsequentColorExpandScanline =
104732b578d3Smrg        ATIMach64SubsequentColorExpandScanline;
104832b578d3Smrg
104932b578d3Smrg    /* The engine does not support the following primitives for 24bpp */
105032b578d3Smrg    if (pATI->XModifier != 1)
105132b578d3Smrg        goto XAAInit;
105232b578d3Smrg
105332b578d3Smrg    /* Solid lines */
105432b578d3Smrg    pXAAInfo->SetupForSolidLine = ATIMach64SetupForSolidLine;
105532b578d3Smrg    pXAAInfo->SubsequentSolidHorVertLine = ATIMach64SubsequentSolidHorVertLine;
105632b578d3Smrg    pXAAInfo->SubsequentSolidBresenhamLine =
105732b578d3Smrg        ATIMach64SubsequentSolidBresenhamLine;
105832b578d3Smrg
105932b578d3SmrgXAAInit:
106032b578d3Smrg    if (!XAAInit(pScreen, pATI->pXAAInfo)) {
106132b578d3Smrg        XAADestroyInfoRec(pATI->pXAAInfo);
106232b578d3Smrg        pATI->pXAAInfo = NULL;
106332b578d3Smrg        return FALSE;
106432b578d3Smrg    }
106532b578d3Smrg
106632b578d3Smrg    return TRUE;
106732b578d3Smrg}
106832b578d3Smrg#endif /* USE_XAA */
1069