109885543Smrg/*
209885543SmrgCopyright (C) 2006 Dennis De Winter  All Rights Reserved.
309885543SmrgCopyright (C) 2007 Alex Deucher  All Rights Reserved.
409885543Smrg
509885543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy of
609885543Smrgthis software and associated documentation files (the "Software"), to deal in
709885543Smrgthe Software without restriction, including without limitation the rights to
809885543Smrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
909885543Smrgof the Software, and to permit persons to whom the Software is furnished to do
1009885543Smrgso, subject to the following conditions:
1109885543Smrg
1209885543SmrgThe above copyright notice and this permission notice shall be included in all
1309885543Smrgcopies or substantial portions of the Software.
1409885543Smrg
1509885543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1609885543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
1709885543SmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1809885543SmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1909885543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2009885543SmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2109885543Smrg
2209885543Smrg*/
2309885543Smrg
2409885543Smrg#ifdef HAVE_CONFIG_H
2509885543Smrg#include "config.h"
2609885543Smrg#endif
2709885543Smrg
2809885543Smrg#include "smi.h"
2909885543Smrg
307104f784Smrg#if SMI501_CLI_DEBUG
317104f784Smrg# include "smi_501.h"
327104f784Smrg# undef WRITE_DPR
337104f784Smrg# define WRITE_DPR(pSmi, dpr, data)					\
347104f784Smrg    do {								\
357104f784Smrg	if (pSmi->batch_active)						\
367104f784Smrg	    BATCH_LOAD_REG((pSmi->DPRBase - pSmi->MapBase) +		\
377104f784Smrg			   dpr, data);					\
387104f784Smrg	else								\
397104f784Smrg	    MMIO_OUT32(pSmi->DPRBase, dpr, data);			\
407104f784Smrg	DEBUG("DPR%02X = %08X\n", dpr, data);				\
417104f784Smrg    } while (0)
427104f784Smrg#endif
4309885543Smrg
4409885543Smrgstatic void
4509885543SmrgSMI_EXASync(ScreenPtr pScreen, int marker);
4609885543Smrg
4709885543Smrgstatic Bool
4809885543SmrgSMI_PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
4909885543Smrg		int xdir, int ydir, int alu, Pixel planemask);
5009885543Smrg
5109885543Smrgstatic void
5209885543SmrgSMI_Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height);
5309885543Smrg
5409885543Smrgstatic void
5509885543SmrgSMI_DoneCopy(PixmapPtr pDstPixmap);
5609885543Smrg
5709885543Smrgstatic Bool
5809885543SmrgSMI_PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg);
5909885543Smrg
6009885543Smrgstatic void
6109885543SmrgSMI_Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2);
6209885543Smrg
6309885543Smrgstatic void
6409885543SmrgSMI_DoneSolid(PixmapPtr pPixmap);
6509885543Smrg
6609885543SmrgBool
6709885543SmrgSMI_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch);
6809885543Smrg
6909885543SmrgBool
7009885543SmrgSMI_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch);
7109885543Smrg
727104f784Smrgstatic Bool
737104f784SmrgSMI_CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture);
747104f784Smrgstatic Bool
757104f784SmrgSMI_PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture,
767104f784Smrg                     PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
777104f784Smrgstatic void
787104f784SmrgSMI_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
797104f784Smrg              int dstX, int dstY, int width, int height);
807104f784Smrgstatic void
817104f784SmrgSMI730_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
827104f784Smrg              int dstX, int dstY, int width, int height);
837104f784Smrgstatic void
847104f784SmrgSMI_DoneComposite(PixmapPtr pDst);
857104f784Smrg
867104f784Smrg
877104f784Smrg#define PIXMAP_FORMAT(pixmap) SMI_DEDataFormat(pixmap->drawable.bitsPerPixel)
887104f784Smrg#define PIXMAP_OFFSET(pixmap)	IS_MSOC(pSmi) ?				\
897104f784Smrg    exaGetPixmapOffset(pixmap) : exaGetPixmapOffset(pixmap) >> 3
907104f784Smrg
9109885543SmrgBool
9209885543SmrgSMI_EXAInit(ScreenPtr pScreen)
9309885543Smrg{
94b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
9509885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
9609885543Smrg
977104f784Smrg    ENTER();
9809885543Smrg
9909885543Smrg    if (!(pSmi->EXADriverPtr = exaDriverAlloc())) {
10009885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate EXADriverRec.\n");
1017104f784Smrg	LEAVE(FALSE);
10209885543Smrg    }
10309885543Smrg
1047104f784Smrg    /* Require 2.1 semantics:
1057104f784Smrg       Don't uninitialize the memory manager when swapping out */
10609885543Smrg    pSmi->EXADriverPtr->exa_major = 2;
1077104f784Smrg    pSmi->EXADriverPtr->exa_minor = 1;
10809885543Smrg
10909885543Smrg    SMI_EngineReset(pScrn);
11009885543Smrg
11109885543Smrg    /* Memory Manager */
1127104f784Smrg    pSmi->EXADriverPtr->memoryBase = pSmi->FBBase;
1137104f784Smrg    pSmi->EXADriverPtr->memorySize = pSmi->FBReserved;
1147104f784Smrg
1157104f784Smrg    /* The framebuffer is allocated as an offscreen area with the
1167104f784Smrg       memory manager (It makes easier further resizing) */
1177104f784Smrg    pSmi->EXADriverPtr->offScreenBase = 0;
11809885543Smrg
11909885543Smrg    /* Flags */
12009885543Smrg    pSmi->EXADriverPtr->flags = EXA_TWO_BITBLT_DIRECTIONS;
12109885543Smrg    if (pSmi->EXADriverPtr->memorySize > pSmi->EXADriverPtr->offScreenBase) {
12209885543Smrg	/* Offscreen Pixmaps */
12309885543Smrg	pSmi->EXADriverPtr->flags |= EXA_OFFSCREEN_PIXMAPS;
12409885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1257104f784Smrg		   "EXA offscreen memory manager enabled.\n");
1267104f784Smrg    }
1277104f784Smrg    else
12809885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
12909885543Smrg		   "Not enough video RAM for EXA offscreen memory manager.\n");
13009885543Smrg
13109885543Smrg    /* 12 bit coordinates */
13209885543Smrg    pSmi->EXADriverPtr->maxX = 4096;
13309885543Smrg    pSmi->EXADriverPtr->maxY = 4096;
13409885543Smrg
1357104f784Smrg    if (pScrn->bitsPerPixel == 24) {
1367104f784Smrg	pSmi->EXADriverPtr->maxX = 4096 / 3;
1377104f784Smrg
1387104f784Smrg	if (pSmi->Chipset == SMI_LYNX) {
1397104f784Smrg	    pSmi->EXADriverPtr->maxY = 4096 / 3;
1407104f784Smrg	}
1417104f784Smrg    }
1427104f784Smrg
14309885543Smrg    pSmi->EXADriverPtr->pixmapPitchAlign  = 16;
14409885543Smrg    pSmi->EXADriverPtr->pixmapOffsetAlign = 8;
14509885543Smrg
14609885543Smrg    /* Sync */
14709885543Smrg    pSmi->EXADriverPtr->WaitMarker = SMI_EXASync;
14809885543Smrg
14909885543Smrg    /* Copy */
15009885543Smrg    pSmi->EXADriverPtr->PrepareCopy = SMI_PrepareCopy;
15109885543Smrg    pSmi->EXADriverPtr->Copy = SMI_Copy;
15209885543Smrg    pSmi->EXADriverPtr->DoneCopy = SMI_DoneCopy;
15309885543Smrg
15409885543Smrg    /* Solid */
15509885543Smrg    pSmi->EXADriverPtr->PrepareSolid = SMI_PrepareSolid;
15609885543Smrg    pSmi->EXADriverPtr->Solid = SMI_Solid;
15709885543Smrg    pSmi->EXADriverPtr->DoneSolid = SMI_DoneSolid;
15809885543Smrg
15909885543Smrg#if 0
1607104f784Smrg    /* DFS & UTS */
16109885543Smrg    pSmi->EXADriverPtr->UploadToScreen = SMI_UploadToScreen;
16209885543Smrg    pSmi->EXADriverPtr->DownloadFromScreen = SMI_DownloadFromScreen;
16309885543Smrg#endif
16409885543Smrg
1657104f784Smrg    /* Composite */
1667104f784Smrg    pSmi->EXADriverPtr->CheckComposite = SMI_CheckComposite;
1677104f784Smrg    pSmi->EXADriverPtr->PrepareComposite = SMI_PrepareComposite;
1687104f784Smrg
1692ec8c4b4Smrg    if (IS_MSOC(pSmi) || pSmi->Chipset == SMI_COUGAR3DR)
1707104f784Smrg	pSmi->EXADriverPtr->Composite = SMI730_Composite;
1717104f784Smrg    else
1727104f784Smrg	pSmi->EXADriverPtr->Composite = SMI_Composite;
1732ec8c4b4Smrg
1747104f784Smrg    pSmi->EXADriverPtr->DoneComposite = SMI_DoneComposite;
1757104f784Smrg
17609885543Smrg    if(!exaDriverInit(pScreen, pSmi->EXADriverPtr)) {
17709885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "exaDriverInit failed.\n");
1787104f784Smrg	LEAVE(FALSE);
17909885543Smrg    }
1807104f784Smrg
1817104f784Smrg
1827104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EXA Acceleration enabled.\n");
1837104f784Smrg
1847104f784Smrg    LEAVE(TRUE);
18509885543Smrg}
18609885543Smrg
18709885543Smrgstatic void
18809885543SmrgSMI_EXASync(ScreenPtr pScreen, int marker)
18909885543Smrg{
190b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
19109885543Smrg
1927104f784Smrg    ENTER();
19309885543Smrg
1947104f784Smrg    SMI_AccelSync(pScrn);
19509885543Smrg
1967104f784Smrg    LEAVE();
19709885543Smrg}
19809885543Smrg
19909885543Smrg/* ----------------------------------------------------- EXA Copy ---------------------------------------------- */
20009885543Smrg
20109885543SmrgCARD8 SMI_BltRop[16] =	/* table stolen from KAA */
20209885543Smrg{
20309885543Smrg    /* GXclear      */      0x00,         /* 0 */
20409885543Smrg    /* GXand        */      0x88,         /* src AND dst */
20509885543Smrg    /* GXandReverse */      0x44,         /* src AND NOT dst */
20609885543Smrg    /* GXcopy       */      0xCC,         /* src */
20709885543Smrg    /* GXandInverted*/      0x22,         /* NOT src AND dst */
20809885543Smrg    /* GXnoop       */      0xAA,         /* dst */
20909885543Smrg    /* GXxor        */      0x66,         /* src XOR dst */
21009885543Smrg    /* GXor         */      0xEE,         /* src OR dst */
21109885543Smrg    /* GXnor        */      0x11,         /* NOT src AND NOT dst */
21209885543Smrg    /* GXequiv      */      0x99,         /* NOT src XOR dst */
21309885543Smrg    /* GXinvert     */      0x55,         /* NOT dst */
21409885543Smrg    /* GXorReverse  */      0xDD,         /* src OR NOT dst */
21509885543Smrg    /* GXcopyInverted*/     0x33,         /* NOT src */
21609885543Smrg    /* GXorInverted */      0xBB,         /* NOT src OR dst */
21709885543Smrg    /* GXnand       */      0x77,         /* NOT src OR NOT dst */
21809885543Smrg    /* GXset        */      0xFF,         /* 1 */
21909885543Smrg};
22009885543Smrg
22109885543Smrgstatic Bool
22209885543SmrgSMI_PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir,
22309885543Smrg		int alu, Pixel planemask)
22409885543Smrg{
225b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
22609885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
22709885543Smrg    int src_pitch, dst_pitch;
22809885543Smrg    unsigned long src_offset, dst_offset;
22909885543Smrg
2307104f784Smrg    ENTER();
2317104f784Smrg    DEBUG("xdir=%d ydir=%d alu=%02X", xdir, ydir, alu);
23209885543Smrg
23309885543Smrg    /* Bit Mask not supported > 16 bpp */
23409885543Smrg    if ((pSrcPixmap->drawable.bitsPerPixel > 16) &&
2357104f784Smrg	(!EXA_PM_IS_SOLID(&pSrcPixmap->drawable, planemask)))
2367104f784Smrg	LEAVE(FALSE);
23709885543Smrg
23809885543Smrg    /* calculate pitch in pixel unit */
23909885543Smrg    src_pitch  = exaGetPixmapPitch(pSrcPixmap) / (pSrcPixmap->drawable.bitsPerPixel >> 3);
24009885543Smrg    dst_pitch  = exaGetPixmapPitch(pDstPixmap) / (pDstPixmap->drawable.bitsPerPixel >> 3);
24109885543Smrg    /* calculate offset in 8 byte (64 bit) unit */
2427104f784Smrg    src_offset = PIXMAP_OFFSET(pSrcPixmap);
2437104f784Smrg    dst_offset = PIXMAP_OFFSET(pDstPixmap);
24409885543Smrg
24509885543Smrg    pSmi->AccelCmd = SMI_BltRop[alu]
24609885543Smrg		   | SMI_BITBLT
24709885543Smrg		   | SMI_QUICK_START;
24809885543Smrg
24909885543Smrg    if (xdir < 0 || (ydir < 0)) {
25009885543Smrg	pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT;
25109885543Smrg    }
25209885543Smrg
25309885543Smrg    if (pDstPixmap->drawable.bitsPerPixel == 24) {
25409885543Smrg	src_pitch *= 3;
25509885543Smrg	dst_pitch *= 3;
25609885543Smrg    }
25709885543Smrg
2587104f784Smrg#if SMI501_CLI_DEBUG
2597104f784Smrg    BATCH_BEGIN(7);
2607104f784Smrg#else
2617104f784Smrg    WaitQueue();
2627104f784Smrg#endif
2637104f784Smrg    /* Destination and Source Window Widths */
2647104f784Smrg    WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (src_pitch & 0xFFFF));
2657104f784Smrg    /* Destination and Source Row Pitch */
2667104f784Smrg    WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (src_pitch & 0xFFFF));
2677104f784Smrg
26809885543Smrg    /* Bit Mask (planemask) - 16 bit only */
26909885543Smrg    if (pSrcPixmap->drawable.bitsPerPixel == 16) {
27009885543Smrg	WRITE_DPR(pSmi, 0x28, planemask | 0xFFFF0000);
27109885543Smrg    } else {
27209885543Smrg	WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF);
27309885543Smrg    }
27409885543Smrg    /* Drawing engine data format */
2757104f784Smrg    WRITE_DPR(pSmi, 0x1C, PIXMAP_FORMAT(pDstPixmap));
27609885543Smrg    /* Destination and Source Base Address (offset) */
27709885543Smrg    WRITE_DPR(pSmi, 0x40, src_offset);
27809885543Smrg    WRITE_DPR(pSmi, 0x44, dst_offset);
27909885543Smrg
28009885543Smrg    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
2817104f784Smrg#if SMI501_CLI_DEBUG
2827104f784Smrg    BATCH_END();
2837104f784Smrg#endif
28409885543Smrg
2857104f784Smrg    LEAVE(TRUE);
28609885543Smrg}
28709885543Smrg
28809885543Smrgstatic void
28909885543SmrgSMI_Copy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX,
29009885543Smrg	 int dstY, int width, int height)
29109885543Smrg{
292b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
29309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
29409885543Smrg
2957104f784Smrg    ENTER();
2967104f784Smrg    DEBUG("srcX=%d srcY=%d dstX=%d dstY=%d width=%d height=%d\n",
2977104f784Smrg	  srcX, srcY, dstX, dstY, width, height);
29809885543Smrg
29909885543Smrg    if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) {
30009885543Smrg	srcX += width  - 1;
30109885543Smrg	srcY += height - 1;
30209885543Smrg	dstX += width  - 1;
30309885543Smrg	dstY += height - 1;
30409885543Smrg    }
30509885543Smrg
30609885543Smrg    if (pDstPixmap->drawable.bitsPerPixel == 24) {
30709885543Smrg	srcX  *= 3;
30809885543Smrg	dstX  *= 3;
30909885543Smrg	width *= 3;
31009885543Smrg
31109885543Smrg    	if (pSmi->Chipset == SMI_LYNX) {
31209885543Smrg	    srcY *= 3;
31309885543Smrg	    dstY *= 3;
31409885543Smrg        }
31509885543Smrg
31609885543Smrg	if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) {
31709885543Smrg	    srcX += 2;
31809885543Smrg	    dstX += 2;
31909885543Smrg	}
32009885543Smrg    }
32109885543Smrg
3227104f784Smrg#if SMI501_CLI_DEBUG
3237104f784Smrg    BATCH_BEGIN(3);
3247104f784Smrg#else
3257104f784Smrg    WaitQueue();
3267104f784Smrg#endif
32709885543Smrg    WRITE_DPR(pSmi, 0x00, (srcX  << 16) + (srcY & 0xFFFF));
32809885543Smrg    WRITE_DPR(pSmi, 0x04, (dstX  << 16) + (dstY & 0xFFFF));
32909885543Smrg    WRITE_DPR(pSmi, 0x08, (width << 16) + (height & 0xFFFF));
3307104f784Smrg#if SMI501_CLI_DEBUG
3317104f784Smrg    BATCH_END();
3327104f784Smrg#endif
33309885543Smrg
3347104f784Smrg    LEAVE();
33509885543Smrg}
33609885543Smrg
33709885543Smrgstatic void
33809885543SmrgSMI_DoneCopy(PixmapPtr pDstPixmap)
33909885543Smrg{
3407104f784Smrg    ENTER();
34109885543Smrg
3427104f784Smrg    LEAVE();
34309885543Smrg}
34409885543Smrg
34509885543Smrg/* ----------------------------------------------------- EXA Solid --------------------------------------------- */
34609885543Smrg
34709885543SmrgCARD8 SMI_SolidRop[16] =	/* table stolen from KAA */
34809885543Smrg{
34909885543Smrg    /* GXclear      */      0x00,         /* 0 */
35009885543Smrg    /* GXand        */      0xA0,         /* src AND dst */
35109885543Smrg    /* GXandReverse */      0x50,         /* src AND NOT dst */
35209885543Smrg    /* GXcopy       */      0xF0,         /* src */
35309885543Smrg    /* GXandInverted*/      0x0A,         /* NOT src AND dst */
35409885543Smrg    /* GXnoop       */      0xAA,         /* dst */
35509885543Smrg    /* GXxor        */      0x5A,         /* src XOR dst */
35609885543Smrg    /* GXor         */      0xFA,         /* src OR dst */
35709885543Smrg    /* GXnor        */      0x05,         /* NOT src AND NOT dst */
35809885543Smrg    /* GXequiv      */      0xA5,         /* NOT src XOR dst */
35909885543Smrg    /* GXinvert     */      0x55,         /* NOT dst */
36009885543Smrg    /* GXorReverse  */      0xF5,         /* src OR NOT dst */
36109885543Smrg    /* GXcopyInverted*/     0x0F,         /* NOT src */
36209885543Smrg    /* GXorInverted */      0xAF,         /* NOT src OR dst */
36309885543Smrg    /* GXnand       */      0x5F,         /* NOT src OR NOT dst */
36409885543Smrg    /* GXset        */      0xFF,         /* 1 */
36509885543Smrg};
36609885543Smrg
36709885543Smrgstatic Bool
36809885543SmrgSMI_PrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
36909885543Smrg{
370b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
37109885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
37209885543Smrg    int dst_pitch;
37309885543Smrg    unsigned long dst_offset;
37409885543Smrg
3757104f784Smrg    ENTER();
3767104f784Smrg    DEBUG("alu=%02X\n", alu);
37709885543Smrg
37809885543Smrg    /* HW ignores alpha */
37909885543Smrg    if (pPixmap->drawable.bitsPerPixel == 32)
3807104f784Smrg	LEAVE(FALSE);
38109885543Smrg
38209885543Smrg    /* Bit Mask not supported > 16 bpp */
38309885543Smrg    if ((pPixmap->drawable.bitsPerPixel > 16) &&
3847104f784Smrg	(!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask)))
3857104f784Smrg	LEAVE(FALSE);
38609885543Smrg
38709885543Smrg    /* calculate pitch in pixel unit */
38809885543Smrg    dst_pitch  = exaGetPixmapPitch(pPixmap) / (pPixmap->drawable.bitsPerPixel >> 3);
38909885543Smrg    /* calculate offset in 8 byte (64 bit) unit */
3907104f784Smrg    dst_offset = PIXMAP_OFFSET(pPixmap);
39109885543Smrg
39209885543Smrg    pSmi->AccelCmd = SMI_SolidRop[alu]
39309885543Smrg		   | SMI_BITBLT
39409885543Smrg		   | SMI_QUICK_START;
39509885543Smrg
39609885543Smrg    if (pPixmap->drawable.bitsPerPixel == 24) {
39709885543Smrg	dst_pitch *= 3;
39809885543Smrg    }
39909885543Smrg
4007104f784Smrg#if SMI501_CLI_DEBUG
4017104f784Smrg    BATCH_BEGIN(10);
4027104f784Smrg#else
4037104f784Smrg    WaitQueue();
4047104f784Smrg#endif
4057104f784Smrg
4067104f784Smrg    /* Destination Window Width */
4077104f784Smrg    WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (dst_pitch & 0xFFFF));
4087104f784Smrg    /* Destination Row Pitch */
4097104f784Smrg    WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (dst_pitch & 0xFFFF));
4107104f784Smrg
41109885543Smrg    /* Bit Mask (planemask) - 16 bit only */
41209885543Smrg    if (pPixmap->drawable.bitsPerPixel == 16) {
41309885543Smrg	WRITE_DPR(pSmi, 0x28, planemask | 0xFFFF0000);
41409885543Smrg    } else {
41509885543Smrg	WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF);
41609885543Smrg    }
41709885543Smrg
41809885543Smrg    /* Drawing engine data format */
4197104f784Smrg    WRITE_DPR(pSmi, 0x1C, PIXMAP_FORMAT(pPixmap));
42009885543Smrg    /* Source and Destination Base Address (offset) */
42109885543Smrg    WRITE_DPR(pSmi, 0x40, dst_offset);
42209885543Smrg    WRITE_DPR(pSmi, 0x44, dst_offset);
42309885543Smrg    /* Foreground Color */
42409885543Smrg    WRITE_DPR(pSmi, 0x14, fg);
42509885543Smrg    /* Mono Pattern High and Low */
42609885543Smrg    WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF);
42709885543Smrg    WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF);
42809885543Smrg
42909885543Smrg    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
4307104f784Smrg#if SMI501_CLI_DEBUG
4317104f784Smrg    BATCH_END();
4327104f784Smrg#endif
43309885543Smrg
4347104f784Smrg    LEAVE(TRUE);
43509885543Smrg}
43609885543Smrg
43709885543Smrgstatic void
43809885543SmrgSMI_Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
43909885543Smrg{
440b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
44109885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
44209885543Smrg    int w, h;
44309885543Smrg
4447104f784Smrg    ENTER();
4457104f784Smrg    DEBUG("x1=%d y1=%d x2=%d y2=%d\n", x1, y1, x2, y2);
44609885543Smrg
44709885543Smrg    w = (x2 - x1);
44809885543Smrg    h = (y2 - y1);
44909885543Smrg
45009885543Smrg    if (pPixmap->drawable.bitsPerPixel == 24) {
45109885543Smrg	x1 *= 3;
45209885543Smrg	w  *= 3;
45309885543Smrg
45409885543Smrg	if (pSmi->Chipset == SMI_LYNX) {
45509885543Smrg	    y1 *= 3;
45609885543Smrg	}
45709885543Smrg    }
45809885543Smrg
4597104f784Smrg#if SMI501_CLI_DEBUG
4607104f784Smrg    BATCH_BEGIN(2);
4617104f784Smrg#else
4627104f784Smrg    WaitQueue();
4637104f784Smrg#endif
46409885543Smrg    WRITE_DPR(pSmi, 0x04, (x1 << 16) | (y1 & 0xFFFF));
46509885543Smrg    WRITE_DPR(pSmi, 0x08, (w  << 16) | (h  & 0xFFFF));
4667104f784Smrg#if SMI501_CLI_DEBUG
4677104f784Smrg    BATCH_END();
4687104f784Smrg#endif
46909885543Smrg
4707104f784Smrg    LEAVE();
47109885543Smrg}
47209885543Smrg
47309885543Smrgstatic void
47409885543SmrgSMI_DoneSolid(PixmapPtr pPixmap)
47509885543Smrg{
4767104f784Smrg    ENTER();
47709885543Smrg
4787104f784Smrg    LEAVE();
47909885543Smrg}
48009885543Smrg
48109885543Smrg/* --------------------------------------- EXA DFS & UTS ---------------------------------------- */
48209885543Smrg
48309885543SmrgBool
48409885543SmrgSMI_DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
48509885543Smrg		       char *dst, int dst_pitch)
48609885543Smrg{
48709885543Smrg    unsigned char *src = pSrc->devPrivate.ptr;
48809885543Smrg    int src_pitch = exaGetPixmapPitch(pSrc);
48909885543Smrg
4907104f784Smrg    ENTER();
4917104f784Smrg    DEBUG("x=%d y=%d w=%d h=%d dst=%d dst_pitch=%d\n",
4927104f784Smrg	  x, y, w, h, dst, dst_pitch);
4937104f784Smrg
49409885543Smrg    exaWaitSync(pSrc->drawable.pScreen);
49509885543Smrg
4967104f784Smrg    src += (y * src_pitch) + (x * pSrc->drawable.bitsPerPixel/8);
4977104f784Smrg    w   *= pSrc->drawable.bitsPerPixel/8;
49809885543Smrg
49909885543Smrg    while (h--) {
50009885543Smrg	memcpy(dst, src, w);
50109885543Smrg	src += src_pitch;
50209885543Smrg	dst += dst_pitch;
50309885543Smrg    }
50409885543Smrg
5057104f784Smrg    LEAVE(TRUE);
50609885543Smrg}
50709885543Smrg
50809885543SmrgBool
50909885543SmrgSMI_UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
51009885543Smrg		   char *src, int src_pitch)
51109885543Smrg{
512b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
51309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
5147104f784Smrg    int dst_pixelpitch, src_pixelpitch, align, aligned_pitch;
51509885543Smrg    unsigned long dst_offset;
51609885543Smrg
5177104f784Smrg    ENTER();
5187104f784Smrg    DEBUG("x=%d y=%d w=%d h=%d src=%d src_pitch=%d\n",
5197104f784Smrg	  x, y, w, h, src, src_pitch);
5207104f784Smrg
5217104f784Smrg    if (pDst->drawable.bitsPerPixel == 24) {
5227104f784Smrg	align = 16;
5237104f784Smrg    } else {
5247104f784Smrg	align = 128 / pDst->drawable.bitsPerPixel;
5257104f784Smrg    }
5267104f784Smrg
5277104f784Smrg    aligned_pitch = ((w*pDst->drawable.bitsPerPixel >> 3) + align - 1) & ~(align - 1);
52809885543Smrg
52909885543Smrg    /* calculate pitch in pixel unit */
5307104f784Smrg    dst_pixelpitch  = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel >> 3);
5317104f784Smrg    src_pixelpitch = src_pitch / (pDst->drawable.bitsPerPixel >> 3);
53209885543Smrg    /* calculate offset in 8 byte (64 bit) unit */
5337104f784Smrg    dst_offset = PIXMAP_OFFSET(pDst);
53409885543Smrg
53509885543Smrg    pSmi->AccelCmd = 0xCC /* GXcopy */
53609885543Smrg		   | SMI_HOSTBLT_WRITE
53709885543Smrg		   | SMI_QUICK_START;
53809885543Smrg
5397104f784Smrg    /* set clipping */
5407104f784Smrg    SMI_SetClippingRectangle(pScrn, x, y, x+w, y+h);
54109885543Smrg
5427104f784Smrg#if SMI501_CLI_DEBUG
5437104f784Smrg    BATCH_BEGIN(9);
5447104f784Smrg#else
5457104f784Smrg    WaitQueue();
5467104f784Smrg#endif
5477104f784Smrg    /* Destination and Source Window Widths */
5487104f784Smrg    WRITE_DPR(pSmi, 0x3C, (dst_pixelpitch << 16) | (src_pixelpitch & 0xFFFF));
54909885543Smrg
55009885543Smrg    if (pDst->drawable.bitsPerPixel == 24) {
55109885543Smrg	x *= 3;
55209885543Smrg	w *= 3;
5537104f784Smrg	dst_pixelpitch *= 3;
55409885543Smrg	if (pSmi->Chipset == SMI_LYNX) {
55509885543Smrg	    y *= 3;
55609885543Smrg	}
55709885543Smrg    }
55809885543Smrg
5597104f784Smrg    /* Source and Destination Row Pitch */
5607104f784Smrg    WRITE_DPR(pSmi, 0x10, (dst_pixelpitch << 16) | (src_pixelpitch & 0xFFFF));
56109885543Smrg    /* Drawing engine data format */
5627104f784Smrg    WRITE_DPR(pSmi, 0x1C,PIXMAP_FORMAT(pDst));
5637104f784Smrg    /* Source and Destination Base Address (offset) */
5647104f784Smrg    WRITE_DPR(pSmi, 0x40, 0);
56509885543Smrg    WRITE_DPR(pSmi, 0x44, dst_offset);
56609885543Smrg
56709885543Smrg    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
56809885543Smrg    WRITE_DPR(pSmi, 0x00, 0);
5697104f784Smrg    WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
57009885543Smrg    WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
5717104f784Smrg#if SMI501_CLI_DEBUG
5727104f784Smrg    BATCH_END();
5737104f784Smrg#endif
57409885543Smrg
5757104f784Smrg    while (h--) {
5767104f784Smrg	memcpy(pSmi->DataPortBase, src, aligned_pitch);
5777104f784Smrg	src += src_pitch;
57809885543Smrg    }
57909885543Smrg
58009885543Smrg    /* disable clipping */
5817104f784Smrg    SMI_DisableClipping(pScrn);
58209885543Smrg
58309885543Smrg    exaWaitSync(pDst->drawable.pScreen);
58409885543Smrg
5857104f784Smrg    LEAVE(TRUE);
5867104f784Smrg}
5877104f784Smrg
5887104f784Smrg/* --------------------------------------- EXA Composite ---------------------------------------- */
5897104f784Smrg/* This is a very incomplete Composite implementation that only
5907104f784Smrg   accelerates PictOpSrc with source coordinates transformation by
5917104f784Smrg   using 2D Engine rotate-BITBLTs */
59209885543Smrg
5937104f784Smrg#define SMI_ISROTATION_90(t)                                    \
5947104f784Smrg    (t->matrix[0][0] == 0 && t->matrix[0][1] == xFixed1 &&      \
5957104f784Smrg     t->matrix[1][0] == -xFixed1 && t->matrix[1][1] == 0)
5967104f784Smrg
5977104f784Smrg#define SMI_ISROTATION_270(t)                                   \
5987104f784Smrg    (t->matrix[0][0] == 0 && t->matrix[0][1] == -xFixed1 &&     \
5997104f784Smrg     t->matrix[1][0] == xFixed1 && t->matrix[1][1] == 0)
6007104f784Smrg
6017104f784Smrgstatic Bool
6027104f784SmrgSMI_CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture)
6037104f784Smrg{
6047104f784Smrg    ENTER();
6057104f784Smrg
6067104f784Smrg    if(op!=PictOpSrc || pMaskPicture ||
6077104f784Smrg       pSrcPicture->repeatType || !pSrcPicture->transform)
6087104f784Smrg	LEAVE(FALSE);
6097104f784Smrg
6107104f784Smrg    if(!SMI_ISROTATION_90(pSrcPicture->transform) &&
6117104f784Smrg       !SMI_ISROTATION_270(pSrcPicture->transform))
6127104f784Smrg        LEAVE(FALSE);
6137104f784Smrg
6147104f784Smrg    if(PICT_FORMAT_BPP(pSrcPicture->format) == 24)
6157104f784Smrg	LEAVE(FALSE);
6167104f784Smrg
6177104f784Smrg    LEAVE(TRUE);
61809885543Smrg}
61909885543Smrg
6207104f784Smrgstatic Bool
6217104f784SmrgSMI_PrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture,
6227104f784Smrg		       PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
6237104f784Smrg{
624b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
6257104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
626f395c03eSmrg
627f395c03eSmrg    if (!pSrc) return FALSE;
628f395c03eSmrg    if (!pSrcPicture->pDrawable) return FALSE;
629f395c03eSmrg
6307104f784Smrg    int src_pitch = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel >> 3);
6317104f784Smrg    int dst_pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel >> 3);
6327104f784Smrg
6337104f784Smrg    ENTER();
6347104f784Smrg
6357104f784Smrg#if SMI501_CLI_DEBUG
6367104f784Smrg    BATCH_BEGIN(7);
6377104f784Smrg#else
6387104f784Smrg    WaitQueue();
6397104f784Smrg#endif
6407104f784Smrg
6417104f784Smrg    /* Destination and Source Window Widths */
6427104f784Smrg    WRITE_DPR(pSmi, 0x3C, (dst_pitch << 16) | (src_pitch & 0xFFFF));
6437104f784Smrg
6447104f784Smrg    /* Destination and Source Row Pitch */
6457104f784Smrg    WRITE_DPR(pSmi, 0x10, (dst_pitch << 16) | (src_pitch & 0xFFFF));
6467104f784Smrg
6477104f784Smrg    /* Drawing engine data format */
6487104f784Smrg    WRITE_DPR(pSmi, 0x1C, PIXMAP_FORMAT(pDst));
6497104f784Smrg
6507104f784Smrg    /* DE Bit Mask */
6517104f784Smrg    WRITE_DPR(pSmi, 0x28, 0xFFFFFFFF);
6527104f784Smrg
6537104f784Smrg    /* Destination and Source Base Address (offset) */
6547104f784Smrg    WRITE_DPR(pSmi, 0x40, PIXMAP_OFFSET(pSrc));
6557104f784Smrg    WRITE_DPR(pSmi, 0x44, PIXMAP_OFFSET(pDst));
6567104f784Smrg
6577104f784Smrg    /* DE command*/
6587104f784Smrg    if(SMI_ISROTATION_90(pSrcPicture->transform))
6597104f784Smrg        WRITE_DPR(pSmi, 0x0C, 0xCC /*GXCopy*/ | SMI_ROTATE_BLT |
6607104f784Smrg		    SMI_ROTATE_CW | SMI_QUICK_START);
6617104f784Smrg    else
6627104f784Smrg        WRITE_DPR(pSmi, 0x0C, 0xCC /*GXCopy*/ | SMI_ROTATE_BLT |
6637104f784Smrg		    SMI_ROTATE_CCW | SMI_QUICK_START);
6647104f784Smrg
6657104f784Smrg#if SMI501_CLI_DEBUG
6667104f784Smrg    BATCH_END();
6677104f784Smrg#endif
6687104f784Smrg
6697104f784Smrg    pSmi->renderTransform = pSrcPicture->transform;
6707104f784Smrg
6717104f784Smrg    LEAVE(TRUE);
6727104f784Smrg}
6737104f784Smrg
6747104f784Smrgstatic void
6757104f784SmrgSMI_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
6767104f784Smrg		int dstX, int dstY, int width, int height)
6777104f784Smrg{
678b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
6797104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
6807104f784Smrg    PictTransformPtr t = pSmi->renderTransform;
6817104f784Smrg    PictVector v;
6827104f784Smrg
6837104f784Smrg    ENTER();
6847104f784Smrg
6857104f784Smrg    if(SMI_ISROTATION_90(t)){
6867104f784Smrg        srcX=srcX+width;
6877104f784Smrg        dstX=dstX+width-1;
6887104f784Smrg    }else{
6897104f784Smrg        srcY=srcY+height;
6907104f784Smrg        dstY=dstY+height-1;
6917104f784Smrg    }
6927104f784Smrg
6937104f784Smrg    v.vector[0] = IntToxFixed(srcX);
6947104f784Smrg    v.vector[1] = IntToxFixed(srcY);
6957104f784Smrg    v.vector[2] = xFixed1;
6967104f784Smrg    PictureTransformPoint(t, &v);
6977104f784Smrg
6987104f784Smrg#if SMI501_CLI_DEBUG
6997104f784Smrg    BATCH_BEGIN(3);
7007104f784Smrg#else
7017104f784Smrg    WaitQueue();
7027104f784Smrg#endif
7037104f784Smrg
7047104f784Smrg    WRITE_DPR(pSmi, 0x00, (xFixedToInt(v.vector[0]) << 16) + (xFixedToInt(v.vector[1]) & 0xFFFF));
7057104f784Smrg    WRITE_DPR(pSmi, 0x04, (dstX << 16) + (dstY & 0xFFFF));
7067104f784Smrg    WRITE_DPR(pSmi, 0x08, (height << 16) + (width & 0xFFFF));
7077104f784Smrg#if SMI501_CLI_DEBUG
7087104f784Smrg    BATCH_END();
7097104f784Smrg#endif
7107104f784Smrg
7117104f784Smrg    LEAVE();
7127104f784Smrg}
7137104f784Smrg
7147104f784Smrgstatic void
7157104f784SmrgSMI730_Composite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
7167104f784Smrg		int dstX, int dstY, int width, int height)
7177104f784Smrg{
718b12e5c03Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
7192ec8c4b4Smrg    SMIPtr pSmi = SMIPTR(pScrn);
7207104f784Smrg    int maxPixels;
7217104f784Smrg
7227104f784Smrg    ENTER();
7237104f784Smrg
7242ec8c4b4Smrg    /* Both SM501 and SM731 cannot rotate-blt more than a certain
7252ec8c4b4Smrg       number of pixels. */
7262ec8c4b4Smrg    if(IS_MSOC(pSmi))
7272ec8c4b4Smrg        maxPixels = 128 / pDst->drawable.bitsPerPixel;
7282ec8c4b4Smrg    else
7292ec8c4b4Smrg        maxPixels = 1280 / pDst->drawable.bitsPerPixel;
7307104f784Smrg
7317104f784Smrg    while(height>0){
7327104f784Smrg	SMI_Composite(pDst, srcX, srcY, maskX, maskY, dstX, dstY, width, min(height, maxPixels));
7337104f784Smrg
7347104f784Smrg	srcY += maxPixels;
7357104f784Smrg	dstY += maxPixels;
7367104f784Smrg	height -= maxPixels;
7377104f784Smrg    }
7387104f784Smrg
7397104f784Smrg    LEAVE();
7407104f784Smrg}
7417104f784Smrg
7427104f784Smrgstatic void
7437104f784SmrgSMI_DoneComposite(PixmapPtr pDst)
7447104f784Smrg{
7457104f784Smrg    ENTER();
7467104f784Smrg    LEAVE();
7477104f784Smrg}
748