115fb4814Smrg/*
215fb4814Smrg * Copyright (c) 2005 ASPEED Technology Inc.
315fb4814Smrg *
415fb4814Smrg * Permission to use, copy, modify, distribute, and sell this software and its
515fb4814Smrg * documentation for any purpose is hereby granted without fee, provided that
615fb4814Smrg * the above copyright notice appear in all copies and that both that
715fb4814Smrg * copyright notice and this permission notice appear in supporting
815fb4814Smrg * documentation, and that the name of the authors not be used in
915fb4814Smrg * advertising or publicity pertaining to distribution of the software without
1015fb4814Smrg * specific, written prior permission.  The authors makes no representations
1115fb4814Smrg * about the suitability of this software for any purpose.  It is provided
1215fb4814Smrg * "as is" without express or implied warranty.
1315fb4814Smrg *
1415fb4814Smrg * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1515fb4814Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1615fb4814Smrg * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1715fb4814Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1815fb4814Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1915fb4814Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2015fb4814Smrg * PERFORMANCE OF THIS SOFTWARE.
2115fb4814Smrg */
2215fb4814Smrg
2315fb4814Smrg#ifdef HAVE_CONFIG_H
2415fb4814Smrg#include <config.h>
2515fb4814Smrg#endif
2615fb4814Smrg#include "xf86.h"
2715fb4814Smrg#include "xf86_OSproc.h"
2815fb4814Smrg#include "xf86cmap.h"
2915fb4814Smrg#include "compiler.h"
3015fb4814Smrg#include "vgaHW.h"
3115fb4814Smrg#include "mipointer.h"
3215fb4814Smrg#include "micmap.h"
3315fb4814Smrg
3415fb4814Smrg#include "fb.h"
3515fb4814Smrg#include "regionstr.h"
3615fb4814Smrg#include "xf86xv.h"
3715fb4814Smrg#include <X11/extensions/Xv.h>
3815fb4814Smrg
3915fb4814Smrg#include "xf86Pci.h"
4015fb4814Smrg
4115fb4814Smrg/* framebuffer offscreen manager */
4215fb4814Smrg#include "xf86fbman.h"
4315fb4814Smrg
4415fb4814Smrg/* include xaa includes */
4515fb4814Smrg#include "xaarop.h"
4615fb4814Smrg
4715fb4814Smrg/* H/W cursor support */
4815fb4814Smrg#include "xf86Cursor.h"
4915fb4814Smrg#include "cursorstr.h"
5015fb4814Smrg
5115fb4814Smrg/* Driver specific headers */
5215fb4814Smrg#include "ast.h"
53cf503b78Smrg#include "ast_vgatool.h"
54cf503b78Smrg#include "ast_cursor.h"
5515fb4814Smrg
5615fb4814Smrg#ifdef	HWC
5715fb4814Smrg/* Prototype type declaration */
587fe5393cSmrgstatic void ASTShowCursor(ScrnInfoPtr pScrn);
59b534f209Smrgstatic void ASTHideCursor(ScrnInfoPtr pScrn);
6015fb4814Smrgstatic void ASTSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
6115fb4814Smrgstatic void ASTSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
6215fb4814Smrgstatic void ASTLoadCursorImage(ScrnInfoPtr pScrn, UCHAR *src);
6315fb4814Smrgstatic Bool ASTUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
6415fb4814Smrgstatic void ASTLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
6515fb4814Smrgstatic Bool ASTUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs);
667fe5393cSmrgstatic void ASTFireCursor(ScrnInfoPtr pScrn);
677fe5393cSmrgstatic void ASTShowCursor_AST1180(ScrnInfoPtr pScrn);
68b534f209Smrgstatic void ASTHideCursor_AST1180(ScrnInfoPtr pScrn);
69b534f209Smrgstatic void ASTSetCursorPosition_AST1180(ScrnInfoPtr pScrn, int x, int y);
7015fb4814Smrg
7115fb4814SmrgBool
7215fb4814SmrgASTCursorInit(ScreenPtr pScreen)
7315fb4814Smrg{
74b4d38c65Smrg    ScrnInfoPtr	pScrn = xf86ScreenToScrn(pScreen);
7515fb4814Smrg    ASTRecPtr 	pAST = ASTPTR(pScrn);
7615fb4814Smrg    xf86CursorInfoPtr infoPtr;
7715fb4814Smrg
7815fb4814Smrg    infoPtr = xf86CreateCursorInfoRec();
7915fb4814Smrg    if(!infoPtr) return FALSE;
8015fb4814Smrg
8115fb4814Smrg    pAST->HWCInfoPtr = infoPtr;
8215fb4814Smrg
8315fb4814Smrg    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
847fe5393cSmrg                     HARDWARE_CURSOR_INVERT_MASK |
8515fb4814Smrg                     HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
8615fb4814Smrg
8715fb4814Smrg    infoPtr->MaxWidth  = MAX_HWC_WIDTH;
8815fb4814Smrg    infoPtr->MaxHeight = MAX_HWC_HEIGHT;
89b534f209Smrg    if (pAST->jChipType == AST1180)
90b534f209Smrg    {
91b534f209Smrg        infoPtr->ShowCursor = ASTShowCursor_AST1180;
92b534f209Smrg        infoPtr->HideCursor = ASTHideCursor_AST1180;
93b534f209Smrg        infoPtr->SetCursorPosition = ASTSetCursorPosition_AST1180;
947fe5393cSmrg    }
95b534f209Smrg    else
96b534f209Smrg    {
97b534f209Smrg        infoPtr->ShowCursor = ASTShowCursor;
98b534f209Smrg        infoPtr->HideCursor = ASTHideCursor;
99b534f209Smrg        infoPtr->SetCursorPosition = ASTSetCursorPosition;
100b534f209Smrg    }
1017fe5393cSmrg    infoPtr->SetCursorColors = ASTSetCursorColors;
10215fb4814Smrg    infoPtr->LoadCursorImage = ASTLoadCursorImage;
10315fb4814Smrg    infoPtr->UseHWCursor = ASTUseHWCursor;
10415fb4814Smrg#ifdef ARGB_CURSOR
10515fb4814Smrg    infoPtr->UseHWCursorARGB = ASTUseHWCursorARGB;
10615fb4814Smrg    infoPtr->LoadCursorARGB = ASTLoadCursorARGB;
10715fb4814Smrg#endif
10815fb4814Smrg
10915fb4814Smrg    return(xf86InitCursor(pScreen, infoPtr));
1107fe5393cSmrg
11115fb4814Smrg}
11215fb4814Smrg
113cf503b78SmrgBool bASTInitHWC(ScrnInfoPtr pScrn, ASTRecPtr pAST)
11415fb4814Smrg{
11515fb4814Smrg    ScreenPtr	pScreen;
11615fb4814Smrg
11715fb4814Smrg    /* init cursor cache info */
1187fe5393cSmrg    /* Set HWC_NUM in Options instead */
11915fb4814Smrg    /* pAST->HWCInfo.HWC_NUM = DEFAULT_HWC_NUM; */
1207fe5393cSmrg    pAST->HWCInfo.HWC_NUM_Next = 0;
1217fe5393cSmrg
1227fe5393cSmrg    /* allocate HWC cache */
1237fe5393cSmrg    if (!pAST->pHWCPtr) {
124b4d38c65Smrg        pScreen = xf86ScrnToScreen(pScrn);
12515fb4814Smrg        pAST->pHWCPtr = xf86AllocateOffscreenLinear (pScreen, (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM, HWC_ALIGN, NULL, NULL, NULL);
12615fb4814Smrg
1277fe5393cSmrg        if (!pAST->pHWCPtr) {
12815fb4814Smrg           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Allocate HWC Cache failed \n");
12915fb4814Smrg           return (FALSE);
13015fb4814Smrg        }
1317fe5393cSmrg
13215fb4814Smrg        pAST->HWCInfo.ulHWCOffsetAddr  = pAST->pHWCPtr->offset*((pScrn->bitsPerPixel + 1) / 8);
1337fe5393cSmrg        pAST->HWCInfo.pjHWCVirtualAddr = pAST->FBVirtualAddr + pAST->HWCInfo.ulHWCOffsetAddr;
13415fb4814Smrg    }
13515fb4814Smrg
1367fe5393cSmrg    return (TRUE);
13715fb4814Smrg}
13815fb4814Smrg
139b534f209Smrgvoid ASTDisableHWC(ScrnInfoPtr pScrn)
140b534f209Smrg{
1417fe5393cSmrg    ASTRecPtr   pAST = ASTPTR(pScrn);
1427fe5393cSmrg
143b534f209Smrg    if (pAST->jChipType == AST1180)
1447fe5393cSmrg        ASTHideCursor_AST1180(pScrn);
1457fe5393cSmrg    else
146b534f209Smrg        ASTHideCursor(pScrn);
1477fe5393cSmrg}
14815fb4814Smrg
14915fb4814Smrgstatic void
15015fb4814SmrgASTShowCursor(ScrnInfoPtr pScrn)
15115fb4814Smrg{
1527fe5393cSmrg    ASTRecPtr   pAST = ASTPTR(pScrn);
15315fb4814Smrg    UCHAR 	jReg;
15415fb4814Smrg
15515fb4814Smrg    jReg= 0x02;
15615fb4814Smrg    if (pAST->HWCInfo.cursortype ==HWC_COLOR)
15715fb4814Smrg        jReg |= 0x01;
1587fe5393cSmrg
1597fe5393cSmrg    SetIndexRegMask(CRTC_PORT, 0xCB, 0xFC, jReg);	/* enable mono */
1607fe5393cSmrg
16115fb4814Smrg}
16215fb4814Smrg
163b534f209Smrgstatic void
16415fb4814SmrgASTHideCursor(ScrnInfoPtr pScrn)
16515fb4814Smrg{
16615fb4814Smrg    ASTRecPtr  pAST = ASTPTR(pScrn);
1677fe5393cSmrg
1687fe5393cSmrg    SetIndexRegMask(CRTC_PORT, 0xCB, 0xFC, 0x00);	/* disable HWC */
1697fe5393cSmrg
17015fb4814Smrg}
17115fb4814Smrg
17215fb4814Smrgstatic void
17315fb4814SmrgASTSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
17415fb4814Smrg{
17515fb4814Smrg    ASTRecPtr	pAST = ASTPTR(pScrn);
1767fe5393cSmrg    DisplayModePtr mode = pAST->ModePtr;
17715fb4814Smrg    int		x_offset, y_offset;
1787fe5393cSmrg    UCHAR 	*pjSignature;
1797fe5393cSmrg
1807fe5393cSmrg    /* Set cursor info to Offscreen */
1817fe5393cSmrg    pjSignature = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
18215fb4814Smrg    *((ULONG *) (pjSignature + HWC_SIGNATURE_X)) = x;
18315fb4814Smrg    *((ULONG *) (pjSignature + HWC_SIGNATURE_Y)) = y;
1847fe5393cSmrg
18515fb4814Smrg    x_offset = pAST->HWCInfo.offset_x;
18615fb4814Smrg    y_offset = pAST->HWCInfo.offset_y;
1877fe5393cSmrg
18815fb4814Smrg    if(x < 0) {
18915fb4814Smrg       x_offset = (-x) + pAST->HWCInfo.offset_x;
19015fb4814Smrg       x = 0;
19115fb4814Smrg    }
19215fb4814Smrg
19315fb4814Smrg    if(y < 0) {
19415fb4814Smrg       y_offset = (-y) + pAST->HWCInfo.offset_y;
19515fb4814Smrg       y = 0;
19615fb4814Smrg    }
19715fb4814Smrg
19815fb4814Smrg    if(mode->Flags & V_DBLSCAN)  y *= 2;
1997fe5393cSmrg
20015fb4814Smrg    /* Set to Reg. */
2017fe5393cSmrg    SetIndexReg(CRTC_PORT, 0xC2, (UCHAR) (x_offset));
2027fe5393cSmrg    SetIndexReg(CRTC_PORT, 0xC3, (UCHAR) (y_offset));
2037fe5393cSmrg    SetIndexReg(CRTC_PORT, 0xC4, (UCHAR) (x & 0xFF));
2047fe5393cSmrg    SetIndexReg(CRTC_PORT, 0xC5, (UCHAR) ((x >> 8) & 0x0F));
2057fe5393cSmrg    SetIndexReg(CRTC_PORT, 0xC6, (UCHAR) (y & 0xFF));
2067fe5393cSmrg    SetIndexReg(CRTC_PORT, 0xC7, (UCHAR) ((y >> 8) & 0x07));
2077fe5393cSmrg
20815fb4814Smrg    /* Fire HWC */
20915fb4814Smrg    ASTFireCursor(pScrn);
2107fe5393cSmrg
2117fe5393cSmrg}
21215fb4814Smrg
21315fb4814Smrgstatic void
21415fb4814SmrgASTSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
21515fb4814Smrg{
21615fb4814Smrg    ASTRecPtr 	pAST = ASTPTR(pScrn);
217de78e416Smrg    ULONG fg1, bg1;
2187fe5393cSmrg
219de78e416Smrg    fg1 = (fg & 0x0F) | (((fg>>8) & 0x0F) << 4) | (((fg>>16) & 0x0F) << 8);
2207fe5393cSmrg    bg1 = (bg & 0x0F) | (((bg>>8) & 0x0F) << 4) | (((bg>>16) & 0x0F) << 8);
221de78e416Smrg
222de78e416Smrg    /* Fixed xorg bugzilla #20609, ycchen@031209 */
2237fe5393cSmrg    if ( (fg1 != pAST->HWCInfo.fg) || (bg1 != pAST->HWCInfo.bg) )
224de78e416Smrg    {
225de78e416Smrg    	pAST->HWCInfo.fg = fg1;
226de78e416Smrg    	pAST->HWCInfo.bg = bg1;
227de78e416Smrg        ASTLoadCursorImage(pScrn, pAST->HWCInfo.cursorpattern);
2287fe5393cSmrg    }
229de78e416Smrg
23015fb4814Smrg}
23115fb4814Smrg
23215fb4814Smrgstatic void
23315fb4814SmrgASTLoadCursorImage(ScrnInfoPtr pScrn, UCHAR *src)
23415fb4814Smrg{
2357fe5393cSmrg    ASTRecPtr	pAST = ASTPTR(pScrn);
23615fb4814Smrg    int 	i, j, k;
23715fb4814Smrg    UCHAR 	*pjSrcAnd, *pjSrcXor, *pjDstData;
23815fb4814Smrg    ULONG   	ulTempDstAnd32[2], ulTempDstXor32[2], ulTempDstData32[2];
23915fb4814Smrg    UCHAR    	jTempSrcAnd32, jTempSrcXor32;
2407fe5393cSmrg    ULONG	ulCheckSum = 0;
2417fe5393cSmrg    ULONG 	ulPatternAddr;
2427fe5393cSmrg
24315fb4814Smrg    /* init cursor info. */
24415fb4814Smrg    pAST->HWCInfo.cursortype = HWC_MONO;
24515fb4814Smrg    pAST->HWCInfo.width  = (USHORT) MAX_HWC_WIDTH;
24615fb4814Smrg    pAST->HWCInfo.height = (USHORT) MAX_HWC_HEIGHT;
24715fb4814Smrg    pAST->HWCInfo.offset_x = MAX_HWC_WIDTH - pAST->HWCInfo.width;
24815fb4814Smrg    pAST->HWCInfo.offset_y = MAX_HWC_HEIGHT - pAST->HWCInfo.height;
24915fb4814Smrg
250de78e416Smrg    /* copy to hwc info */
251de78e416Smrg    for (i=0; i< MAX_HWC_WIDTH*MAX_HWC_HEIGHT/4; i+=4)
252de78e416Smrg       *(ULONG *) (pAST->HWCInfo.cursorpattern + i) = *(ULONG *) (src + i);
2537fe5393cSmrg
25415fb4814Smrg    /* copy cursor image to cache */
25515fb4814Smrg    pjSrcXor = src;
25615fb4814Smrg    pjSrcAnd = src + (MAX_HWC_WIDTH*MAX_HWC_HEIGHT/8);
25715fb4814Smrg    pjDstData =  pAST->HWCInfo.pjHWCVirtualAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next;
2587fe5393cSmrg
25915fb4814Smrg    for (j = 0; j < MAX_HWC_HEIGHT; j++)
26015fb4814Smrg    {
26115fb4814Smrg       for (i = 0; i < (MAX_HWC_WIDTH/8); i++ )
26215fb4814Smrg       {
26315fb4814Smrg       	    for (k=7; k>0; k-=2)
26415fb4814Smrg       	    {
26515fb4814Smrg                jTempSrcAnd32 = *((UCHAR *) pjSrcAnd);
266de78e416Smrg                jTempSrcXor32 = *((UCHAR *) pjSrcXor);
267de78e416Smrg                ulTempDstAnd32[0] = ((jTempSrcAnd32 >> k) & 0x01) ? 0x00008000L:0x00L;
2687fe5393cSmrg                ulTempDstXor32[0] = ((jTempSrcXor32 >> k) & 0x01) ? 0x00004000L:0x00L;
2697fe5393cSmrg                ulTempDstData32[0] = ((jTempSrcXor32 >> k) & 0x01) ? pAST->HWCInfo.fg:pAST->HWCInfo.bg;
2707fe5393cSmrg                ulTempDstAnd32[1] = ((jTempSrcAnd32 >> (k-1)) & 0x01) ? 0x80000000L:0x00L;
2717fe5393cSmrg                ulTempDstXor32[1] = ((jTempSrcXor32 >> (k-1)) & 0x01) ? 0x40000000L:0x00L;
27215fb4814Smrg                ulTempDstData32[1] = ((jTempSrcXor32 >> (k-1)) & 0x01) ? (pAST->HWCInfo.fg << 16):(pAST->HWCInfo.bg << 16);
273de78e416Smrg                /* No inverse for X Window cursor, ycchen@111808 */
274de78e416Smrg                if (ulTempDstAnd32[0])
275de78e416Smrg                    ulTempDstXor32[0] = 0;
276de78e416Smrg                if (ulTempDstAnd32[1])
2777fe5393cSmrg                    ulTempDstXor32[1] = 0;
27815fb4814Smrg                *((ULONG *) pjDstData) = ulTempDstAnd32[0] | ulTempDstXor32[0] | ulTempDstData32[0] | ulTempDstAnd32[1] | ulTempDstXor32[1] | ulTempDstData32[1];
2797fe5393cSmrg                ulCheckSum += *((ULONG *) pjDstData);
28015fb4814Smrg                pjDstData += 4;
28115fb4814Smrg
28215fb4814Smrg            }
28315fb4814Smrg            pjSrcAnd ++;
28415fb4814Smrg            pjSrcXor ++;
2857fe5393cSmrg
2867fe5393cSmrg       }
2877fe5393cSmrg
2887fe5393cSmrg    }
28915fb4814Smrg
290b534f209Smrg    if (pAST->jChipType == AST1180)
291b534f209Smrg    {
2927fe5393cSmrg        ulPatternAddr = pAST->ulVRAMBase + (pAST->HWCInfo.ulHWCOffsetAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next);
2937fe5393cSmrg        WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_PATTERNADDR, ulPatternAddr);
2947fe5393cSmrg    }
295b534f209Smrg    else
296b534f209Smrg    {
297b534f209Smrg        /* Write Checksum as signature */
2987fe5393cSmrg        pjDstData = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
299b534f209Smrg        *((ULONG *) pjDstData) = ulCheckSum;
300b534f209Smrg        *((ULONG *) (pjDstData + HWC_SIGNATURE_SizeX)) = pAST->HWCInfo.width;
301b534f209Smrg        *((ULONG *) (pjDstData + HWC_SIGNATURE_SizeY)) = pAST->HWCInfo.height;
302b534f209Smrg        *((ULONG *) (pjDstData + HWC_SIGNATURE_HOTSPOTX)) = 0;
303b534f209Smrg        *((ULONG *) (pjDstData + HWC_SIGNATURE_HOTSPOTY)) = 0;
3047fe5393cSmrg
305b534f209Smrg        /* set pattern offset */
306b534f209Smrg        ulPatternAddr = ((pAST->HWCInfo.ulHWCOffsetAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next) >> 3);
3077fe5393cSmrg        SetIndexReg(CRTC_PORT, 0xC8, (UCHAR) (ulPatternAddr & 0xFF));
3087fe5393cSmrg        SetIndexReg(CRTC_PORT, 0xC9, (UCHAR) ((ulPatternAddr >> 8) & 0xFF));
3097fe5393cSmrg        SetIndexReg(CRTC_PORT, 0xCA, (UCHAR) ((ulPatternAddr >> 16) & 0xFF));
310b534f209Smrg    }
3117fe5393cSmrg
31215fb4814Smrg    /* update HWC_NUM_Next */
31315fb4814Smrg    pAST->HWCInfo.HWC_NUM_Next = (pAST->HWCInfo.HWC_NUM_Next+1) % pAST->HWCInfo.HWC_NUM;
3147fe5393cSmrg
31515fb4814Smrg}
31615fb4814Smrg
3177fe5393cSmrgstatic Bool
31815fb4814SmrgASTUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
31915fb4814Smrg{
320de78e416Smrg    if ( (pCurs->bits->width > MAX_HWC_WIDTH) || (pCurs->bits->height > MAX_HWC_HEIGHT) )
321de78e416Smrg        return FALSE;
3227fe5393cSmrg
32315fb4814Smrg    return TRUE;
32415fb4814Smrg}
32515fb4814Smrg
32615fb4814Smrgstatic void
32715fb4814SmrgASTLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
32815fb4814Smrg{
3297fe5393cSmrg    ASTRecPtr 	pAST = ASTPTR(pScrn);
33015fb4814Smrg
33115fb4814Smrg    UCHAR	*pjDstXor, *pjSrcXor;
33215fb4814Smrg    ULONG       i, j, ulSrcWidth, ulSrcHeight;
3337fe5393cSmrg    ULONG	ulPerPixelCopy, ulTwoPixelCopy;
33415fb4814Smrg    LONG        lAlphaDstDelta, lLastAlphaDstDelta;
33515fb4814Smrg    union
33615fb4814Smrg    {
33715fb4814Smrg        ULONG   ul;
33815fb4814Smrg        UCHAR   b[4];
3397fe5393cSmrg    } ulSrcData32[2], ulData32;
34015fb4814Smrg    union
34115fb4814Smrg    {
34215fb4814Smrg        USHORT  us;
34315fb4814Smrg        UCHAR   b[2];
34415fb4814Smrg    } usData16;
3457fe5393cSmrg    ULONG	ulCheckSum = 0;
34615fb4814Smrg    ULONG 	ulPatternAddr;
3477fe5393cSmrg
34815fb4814Smrg    /* init cursor info. */
34915fb4814Smrg    pAST->HWCInfo.cursortype = HWC_COLOR;
35015fb4814Smrg    pAST->HWCInfo.width  = pCurs->bits->width;
35115fb4814Smrg    pAST->HWCInfo.height = pCurs->bits->height;
35215fb4814Smrg    pAST->HWCInfo.offset_x = MAX_HWC_WIDTH - pAST->HWCInfo.width;
35315fb4814Smrg    pAST->HWCInfo.offset_y = MAX_HWC_HEIGHT - pAST->HWCInfo.height;
3547fe5393cSmrg
35515fb4814Smrg    /* copy cursor image to cache */
3567fe5393cSmrg    ulSrcWidth  =  pAST->HWCInfo.width;
3577fe5393cSmrg    ulSrcHeight =  pAST->HWCInfo.height;
3587fe5393cSmrg
35915fb4814Smrg    lAlphaDstDelta = MAX_HWC_WIDTH << 1;
36015fb4814Smrg    lLastAlphaDstDelta = lAlphaDstDelta - (ulSrcWidth << 1);
36115fb4814Smrg
36215fb4814Smrg    pjSrcXor  = (UCHAR *) pCurs->bits->argb;;
36315fb4814Smrg    pjDstXor  = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next
36415fb4814Smrg                        + lLastAlphaDstDelta + (MAX_HWC_HEIGHT - ulSrcHeight) * lAlphaDstDelta;
3657fe5393cSmrg
36615fb4814Smrg    ulPerPixelCopy =  ulSrcWidth & 1;
36715fb4814Smrg    ulTwoPixelCopy =  ulSrcWidth >> 1;
3687fe5393cSmrg
36915fb4814Smrg    for (j = 0; j < ulSrcHeight; j++)
37015fb4814Smrg    {
37115fb4814Smrg
37215fb4814Smrg        for (i = 0; i < ulTwoPixelCopy; i++ )
37315fb4814Smrg        {
37415fb4814Smrg            ulSrcData32[0].ul = *((ULONG *) pjSrcXor) & 0xF0F0F0F0;
37515fb4814Smrg            ulSrcData32[1].ul = *((ULONG *) (pjSrcXor+4)) & 0xF0F0F0F0;
37615fb4814Smrg            ulData32.b[0] = ulSrcData32[0].b[1] | (ulSrcData32[0].b[0] >> 4);
37715fb4814Smrg            ulData32.b[1] = ulSrcData32[0].b[3] | (ulSrcData32[0].b[2] >> 4);
37815fb4814Smrg            ulData32.b[2] = ulSrcData32[1].b[1] | (ulSrcData32[1].b[0] >> 4);
3797fe5393cSmrg            ulData32.b[3] = ulSrcData32[1].b[3] | (ulSrcData32[1].b[2] >> 4);
38015fb4814Smrg            *((ULONG *) pjDstXor) = ulData32.ul;
3817fe5393cSmrg            ulCheckSum += (ULONG) ulData32.ul;
38215fb4814Smrg            pjDstXor += 4;
38315fb4814Smrg            pjSrcXor += 8;
3847fe5393cSmrg        }
3857fe5393cSmrg
38615fb4814Smrg        for (i = 0; i < ulPerPixelCopy; i++ )
38715fb4814Smrg        {
38815fb4814Smrg            ulSrcData32[0].ul = *((ULONG *) pjSrcXor) & 0xF0F0F0F0;
38915fb4814Smrg            usData16.b[0] = ulSrcData32[0].b[1] | (ulSrcData32[0].b[0] >> 4);
39015fb4814Smrg            usData16.b[1] = ulSrcData32[0].b[3] | (ulSrcData32[0].b[2] >> 4);
39115fb4814Smrg            *((USHORT *) pjDstXor) = usData16.us;
3927fe5393cSmrg            ulCheckSum += (ULONG) usData16.us;
39315fb4814Smrg            pjDstXor += 2;
39415fb4814Smrg            pjSrcXor += 4;
3957fe5393cSmrg        }
39615fb4814Smrg
39715fb4814Smrg        /* Point to next source and dest scans */
39815fb4814Smrg        pjDstXor += lLastAlphaDstDelta;
3997fe5393cSmrg
40015fb4814Smrg    } /* end of for-loop */
40115fb4814Smrg
402b534f209Smrg    if (pAST->jChipType == AST1180)
403b534f209Smrg    {
4047fe5393cSmrg        ulPatternAddr = pAST->ulVRAMBase + (pAST->HWCInfo.ulHWCOffsetAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next);
4057fe5393cSmrg        WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_PATTERNADDR, ulPatternAddr);
4067fe5393cSmrg    }
407b534f209Smrg    else
408b534f209Smrg    {
409b534f209Smrg        /* Write Checksum as signature */
4107fe5393cSmrg        pjDstXor = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
411b534f209Smrg        *((ULONG *) pjDstXor) = ulCheckSum;
412b534f209Smrg        *((ULONG *) (pjDstXor + HWC_SIGNATURE_SizeX)) = pAST->HWCInfo.width;
413b534f209Smrg        *((ULONG *) (pjDstXor + HWC_SIGNATURE_SizeY)) = pAST->HWCInfo.height;
414b534f209Smrg        *((ULONG *) (pjDstXor + HWC_SIGNATURE_HOTSPOTX)) = 0;
415b534f209Smrg        *((ULONG *) (pjDstXor + HWC_SIGNATURE_HOTSPOTY)) = 0;
4167fe5393cSmrg
417b534f209Smrg        /* set pattern offset */
418b534f209Smrg        ulPatternAddr = ((pAST->HWCInfo.ulHWCOffsetAddr +(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next) >> 3);
4197fe5393cSmrg        SetIndexReg(CRTC_PORT, 0xC8, (UCHAR) (ulPatternAddr & 0xFF));
4207fe5393cSmrg        SetIndexReg(CRTC_PORT, 0xC9, (UCHAR) ((ulPatternAddr >> 8) & 0xFF));
4217fe5393cSmrg        SetIndexReg(CRTC_PORT, 0xCA, (UCHAR) ((ulPatternAddr >> 16) & 0xFF));
422b534f209Smrg    }
4237fe5393cSmrg
42415fb4814Smrg    /* update HWC_NUM_Next */
42515fb4814Smrg    pAST->HWCInfo.HWC_NUM_Next = (pAST->HWCInfo.HWC_NUM_Next+1) % pAST->HWCInfo.HWC_NUM;
4267fe5393cSmrg
42715fb4814Smrg}
42815fb4814Smrg
4297fe5393cSmrgstatic Bool
43015fb4814SmrgASTUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
43115fb4814Smrg{
432de78e416Smrg    if ( (pCurs->bits->width > MAX_HWC_WIDTH) || (pCurs->bits->height > MAX_HWC_HEIGHT) )
433de78e416Smrg        return FALSE;
4347fe5393cSmrg
43515fb4814Smrg    return TRUE;
43615fb4814Smrg}
43715fb4814Smrg
43815fb4814Smrgstatic void
43915fb4814SmrgASTFireCursor(ScrnInfoPtr pScrn)
44015fb4814Smrg{
44115fb4814Smrg    ASTRecPtr  pAST = ASTPTR(pScrn);
4427fe5393cSmrg
443f010a93dSmrg    SetIndexRegMask(CRTC_PORT, 0xCB, 0xFF, 0x00);	/* dummy write to fire HWC */
4447fe5393cSmrg
44515fb4814Smrg}
44615fb4814Smrg
447b534f209Smrg/* AST1180 */
448b534f209Smrgstatic void
449b534f209SmrgASTShowCursor_AST1180(ScrnInfoPtr pScrn)
450b534f209Smrg{
4517fe5393cSmrg    ASTRecPtr   pAST = ASTPTR(pScrn);
452b534f209Smrg    ULONG 	ulData, ulTemp;
453b534f209Smrg
4547fe5393cSmrg    ReadAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_POSITION, ulTemp);
455b534f209Smrg
456b534f209Smrg    ReadAST1180SOC(AST1180_GFX_BASE+AST1180_VGA1_CTRL, ulData);
457b534f209Smrg    ulData &= ~AST1180_ALPHAHWC;
458b534f209Smrg    if (pAST->HWCInfo.cursortype ==HWC_COLOR)
4597fe5393cSmrg        ulData |= AST1180_ALPHAHWC;
460b534f209Smrg    ulData |= AST1180_ENABLEHWC;
4617fe5393cSmrg    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_VGA1_CTRL, ulData);
462b534f209Smrg
463b534f209Smrg    /* fire cursor */
4647fe5393cSmrg    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_POSITION, ulTemp);
4657fe5393cSmrg
466b534f209Smrg} /* ASTShowCursor_AST1180 */
467b534f209Smrg
468b534f209Smrgstatic void
469b534f209SmrgASTHideCursor_AST1180(ScrnInfoPtr pScrn)
470b534f209Smrg{
471b534f209Smrg    ASTRecPtr  pAST = ASTPTR(pScrn);
472b534f209Smrg    ULONG 	ulData;
473b534f209Smrg
474b534f209Smrg    ReadAST1180SOC(AST1180_GFX_BASE+AST1180_VGA1_CTRL, ulData);
475b534f209Smrg    ulData &= ~AST1180_ENABLEHWC;
4767fe5393cSmrg    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_VGA1_CTRL, ulData);
4777fe5393cSmrg
478b534f209Smrg    /* fire cursor */
4797fe5393cSmrg    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_POSITION, 0x07ff07ff);
4807fe5393cSmrg
481b534f209Smrg} /* ASTHideCursor_AST1180 */
482b534f209Smrg
483b534f209Smrgstatic void
484b534f209SmrgASTSetCursorPosition_AST1180(ScrnInfoPtr pScrn, int x, int y)
485b534f209Smrg{
486b534f209Smrg    ASTRecPtr	pAST = ASTPTR(pScrn);
4877fe5393cSmrg    DisplayModePtr mode = pAST->ModePtr;
488b534f209Smrg    int		x_offset, y_offset;
489b534f209Smrg    ULONG	ulData;
4907fe5393cSmrg
491b534f209Smrg    x_offset = pAST->HWCInfo.offset_x;
492b534f209Smrg    y_offset = pAST->HWCInfo.offset_y;
4937fe5393cSmrg
494b534f209Smrg    if(x < 0) {
495b534f209Smrg       x_offset = (-x) + pAST->HWCInfo.offset_x;
496b534f209Smrg       x = 0;
497b534f209Smrg    }
498b534f209Smrg
499b534f209Smrg    if(y < 0) {
500b534f209Smrg       y_offset = (-y) + pAST->HWCInfo.offset_y;
501b534f209Smrg       y = 0;
502b534f209Smrg    }
503b534f209Smrg
504b534f209Smrg    if(mode->Flags & V_DBLSCAN)  y *= 2;
5057fe5393cSmrg
506b534f209Smrg    /* Set to Reg. */
507b534f209Smrg    ulData = (x_offset) | (y_offset << 8);
5087fe5393cSmrg    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_OFFSET, ulData);
509b534f209Smrg    ulData = (x) | (y << 16);
5107fe5393cSmrg    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_POSITION, ulData);
5117fe5393cSmrg
5127fe5393cSmrg} /* ASTSetCursorPosition_AST1180 */
513b534f209Smrg
51415fb4814Smrg#endif	/* End of HWC */
515