1/*
2 * Copyright (c) 2005 ASPEED Technology Inc.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the authors not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  The authors makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as is" without express or implied warranty.
13 *
14 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26#include "xf86.h"
27#include "xf86_OSproc.h"
28#include "xf86cmap.h"
29#include "compiler.h"
30#include "vgaHW.h"
31#include "mipointer.h"
32#include "micmap.h"
33
34#include "fb.h"
35#include "regionstr.h"
36#include "xf86xv.h"
37#include <X11/extensions/Xv.h>
38
39#include "xf86Pci.h"
40
41/* framebuffer offscreen manager */
42#include "xf86fbman.h"
43
44/* include xaa includes */
45#include "xaarop.h"
46
47/* H/W cursor support */
48#include "xf86Cursor.h"
49#include "cursorstr.h"
50
51/* Driver specific headers */
52#include "ast.h"
53#include "ast_vgatool.h"
54#include "ast_cursor.h"
55
56#ifdef	HWC
57/* Prototype type declaration */
58static void ASTShowCursor(ScrnInfoPtr pScrn);
59static void ASTHideCursor(ScrnInfoPtr pScrn);
60static void ASTSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
61static void ASTSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
62static void ASTLoadCursorImage(ScrnInfoPtr pScrn, UCHAR *src);
63static Bool ASTUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
64static void ASTLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
65static Bool ASTUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs);
66static void ASTFireCursor(ScrnInfoPtr pScrn);
67static void ASTShowCursor_AST1180(ScrnInfoPtr pScrn);
68static void ASTHideCursor_AST1180(ScrnInfoPtr pScrn);
69static void ASTSetCursorPosition_AST1180(ScrnInfoPtr pScrn, int x, int y);
70
71Bool
72ASTCursorInit(ScreenPtr pScreen)
73{
74    ScrnInfoPtr	pScrn = xf86ScreenToScrn(pScreen);
75    ASTRecPtr 	pAST = ASTPTR(pScrn);
76    xf86CursorInfoPtr infoPtr;
77
78    infoPtr = xf86CreateCursorInfoRec();
79    if(!infoPtr) return FALSE;
80
81    pAST->HWCInfoPtr = infoPtr;
82
83    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
84                     HARDWARE_CURSOR_INVERT_MASK |
85                     HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
86
87    infoPtr->MaxWidth  = MAX_HWC_WIDTH;
88    infoPtr->MaxHeight = MAX_HWC_HEIGHT;
89    if (pAST->jChipType == AST1180)
90    {
91        infoPtr->ShowCursor = ASTShowCursor_AST1180;
92        infoPtr->HideCursor = ASTHideCursor_AST1180;
93        infoPtr->SetCursorPosition = ASTSetCursorPosition_AST1180;
94    }
95    else
96    {
97        infoPtr->ShowCursor = ASTShowCursor;
98        infoPtr->HideCursor = ASTHideCursor;
99        infoPtr->SetCursorPosition = ASTSetCursorPosition;
100    }
101    infoPtr->SetCursorColors = ASTSetCursorColors;
102    infoPtr->LoadCursorImage = ASTLoadCursorImage;
103    infoPtr->UseHWCursor = ASTUseHWCursor;
104#ifdef ARGB_CURSOR
105    infoPtr->UseHWCursorARGB = ASTUseHWCursorARGB;
106    infoPtr->LoadCursorARGB = ASTLoadCursorARGB;
107#endif
108
109    return(xf86InitCursor(pScreen, infoPtr));
110
111}
112
113Bool bASTInitHWC(ScrnInfoPtr pScrn, ASTRecPtr pAST)
114{
115    ScreenPtr	pScreen;
116
117    /* init cursor cache info */
118    /* Set HWC_NUM in Options instead */
119    /* pAST->HWCInfo.HWC_NUM = DEFAULT_HWC_NUM; */
120    pAST->HWCInfo.HWC_NUM_Next = 0;
121
122    /* allocate HWC cache */
123    if (!pAST->pHWCPtr) {
124        pScreen = xf86ScrnToScreen(pScrn);
125        pAST->pHWCPtr = xf86AllocateOffscreenLinear (pScreen, (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM, HWC_ALIGN, NULL, NULL, NULL);
126
127        if (!pAST->pHWCPtr) {
128           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Allocate HWC Cache failed \n");
129           return (FALSE);
130        }
131
132        pAST->HWCInfo.ulHWCOffsetAddr  = pAST->pHWCPtr->offset*((pScrn->bitsPerPixel + 1) / 8);
133        pAST->HWCInfo.pjHWCVirtualAddr = pAST->FBVirtualAddr + pAST->HWCInfo.ulHWCOffsetAddr;
134    }
135
136    return (TRUE);
137}
138
139void ASTDisableHWC(ScrnInfoPtr pScrn)
140{
141    ASTRecPtr   pAST = ASTPTR(pScrn);
142
143    if (pAST->jChipType == AST1180)
144        ASTHideCursor_AST1180(pScrn);
145    else
146        ASTHideCursor(pScrn);
147}
148
149static void
150ASTShowCursor(ScrnInfoPtr pScrn)
151{
152    ASTRecPtr   pAST = ASTPTR(pScrn);
153    UCHAR 	jReg;
154
155    jReg= 0x02;
156    if (pAST->HWCInfo.cursortype ==HWC_COLOR)
157        jReg |= 0x01;
158
159    SetIndexRegMask(CRTC_PORT, 0xCB, 0xFC, jReg);	/* enable mono */
160
161}
162
163static void
164ASTHideCursor(ScrnInfoPtr pScrn)
165{
166    ASTRecPtr  pAST = ASTPTR(pScrn);
167
168    SetIndexRegMask(CRTC_PORT, 0xCB, 0xFC, 0x00);	/* disable HWC */
169
170}
171
172static void
173ASTSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
174{
175    ASTRecPtr	pAST = ASTPTR(pScrn);
176    DisplayModePtr mode = pAST->ModePtr;
177    int		x_offset, y_offset;
178    UCHAR 	*pjSignature;
179
180    /* Set cursor info to Offscreen */
181    pjSignature = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
182    *((ULONG *) (pjSignature + HWC_SIGNATURE_X)) = x;
183    *((ULONG *) (pjSignature + HWC_SIGNATURE_Y)) = y;
184
185    x_offset = pAST->HWCInfo.offset_x;
186    y_offset = pAST->HWCInfo.offset_y;
187
188    if(x < 0) {
189       x_offset = (-x) + pAST->HWCInfo.offset_x;
190       x = 0;
191    }
192
193    if(y < 0) {
194       y_offset = (-y) + pAST->HWCInfo.offset_y;
195       y = 0;
196    }
197
198    if(mode->Flags & V_DBLSCAN)  y *= 2;
199
200    /* Set to Reg. */
201    SetIndexReg(CRTC_PORT, 0xC2, (UCHAR) (x_offset));
202    SetIndexReg(CRTC_PORT, 0xC3, (UCHAR) (y_offset));
203    SetIndexReg(CRTC_PORT, 0xC4, (UCHAR) (x & 0xFF));
204    SetIndexReg(CRTC_PORT, 0xC5, (UCHAR) ((x >> 8) & 0x0F));
205    SetIndexReg(CRTC_PORT, 0xC6, (UCHAR) (y & 0xFF));
206    SetIndexReg(CRTC_PORT, 0xC7, (UCHAR) ((y >> 8) & 0x07));
207
208    /* Fire HWC */
209    ASTFireCursor(pScrn);
210
211}
212
213static void
214ASTSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
215{
216    ASTRecPtr 	pAST = ASTPTR(pScrn);
217    ULONG fg1, bg1;
218
219    fg1 = (fg & 0x0F) | (((fg>>8) & 0x0F) << 4) | (((fg>>16) & 0x0F) << 8);
220    bg1 = (bg & 0x0F) | (((bg>>8) & 0x0F) << 4) | (((bg>>16) & 0x0F) << 8);
221
222    /* Fixed xorg bugzilla #20609, ycchen@031209 */
223    if ( (fg1 != pAST->HWCInfo.fg) || (bg1 != pAST->HWCInfo.bg) )
224    {
225    	pAST->HWCInfo.fg = fg1;
226    	pAST->HWCInfo.bg = bg1;
227        ASTLoadCursorImage(pScrn, pAST->HWCInfo.cursorpattern);
228    }
229
230}
231
232static void
233ASTLoadCursorImage(ScrnInfoPtr pScrn, UCHAR *src)
234{
235    ASTRecPtr	pAST = ASTPTR(pScrn);
236    int 	i, j, k;
237    UCHAR 	*pjSrcAnd, *pjSrcXor, *pjDstData;
238    ULONG   	ulTempDstAnd32[2], ulTempDstXor32[2], ulTempDstData32[2];
239    UCHAR    	jTempSrcAnd32, jTempSrcXor32;
240    ULONG	ulCheckSum = 0;
241    ULONG 	ulPatternAddr;
242
243    /* init cursor info. */
244    pAST->HWCInfo.cursortype = HWC_MONO;
245    pAST->HWCInfo.width  = (USHORT) MAX_HWC_WIDTH;
246    pAST->HWCInfo.height = (USHORT) MAX_HWC_HEIGHT;
247    pAST->HWCInfo.offset_x = MAX_HWC_WIDTH - pAST->HWCInfo.width;
248    pAST->HWCInfo.offset_y = MAX_HWC_HEIGHT - pAST->HWCInfo.height;
249
250    /* copy to hwc info */
251    for (i=0; i< MAX_HWC_WIDTH*MAX_HWC_HEIGHT/4; i+=4)
252       *(ULONG *) (pAST->HWCInfo.cursorpattern + i) = *(ULONG *) (src + i);
253
254    /* copy cursor image to cache */
255    pjSrcXor = src;
256    pjSrcAnd = src + (MAX_HWC_WIDTH*MAX_HWC_HEIGHT/8);
257    pjDstData =  pAST->HWCInfo.pjHWCVirtualAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next;
258
259    for (j = 0; j < MAX_HWC_HEIGHT; j++)
260    {
261       for (i = 0; i < (MAX_HWC_WIDTH/8); i++ )
262       {
263       	    for (k=7; k>0; k-=2)
264       	    {
265                jTempSrcAnd32 = *((UCHAR *) pjSrcAnd);
266                jTempSrcXor32 = *((UCHAR *) pjSrcXor);
267                ulTempDstAnd32[0] = ((jTempSrcAnd32 >> k) & 0x01) ? 0x00008000L:0x00L;
268                ulTempDstXor32[0] = ((jTempSrcXor32 >> k) & 0x01) ? 0x00004000L:0x00L;
269                ulTempDstData32[0] = ((jTempSrcXor32 >> k) & 0x01) ? pAST->HWCInfo.fg:pAST->HWCInfo.bg;
270                ulTempDstAnd32[1] = ((jTempSrcAnd32 >> (k-1)) & 0x01) ? 0x80000000L:0x00L;
271                ulTempDstXor32[1] = ((jTempSrcXor32 >> (k-1)) & 0x01) ? 0x40000000L:0x00L;
272                ulTempDstData32[1] = ((jTempSrcXor32 >> (k-1)) & 0x01) ? (pAST->HWCInfo.fg << 16):(pAST->HWCInfo.bg << 16);
273                /* No inverse for X Window cursor, ycchen@111808 */
274                if (ulTempDstAnd32[0])
275                    ulTempDstXor32[0] = 0;
276                if (ulTempDstAnd32[1])
277                    ulTempDstXor32[1] = 0;
278                *((ULONG *) pjDstData) = ulTempDstAnd32[0] | ulTempDstXor32[0] | ulTempDstData32[0] | ulTempDstAnd32[1] | ulTempDstXor32[1] | ulTempDstData32[1];
279                ulCheckSum += *((ULONG *) pjDstData);
280                pjDstData += 4;
281
282            }
283            pjSrcAnd ++;
284            pjSrcXor ++;
285
286       }
287
288    }
289
290    if (pAST->jChipType == AST1180)
291    {
292        ulPatternAddr = pAST->ulVRAMBase + (pAST->HWCInfo.ulHWCOffsetAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next);
293        WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_PATTERNADDR, ulPatternAddr);
294    }
295    else
296    {
297        /* Write Checksum as signature */
298        pjDstData = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
299        *((ULONG *) pjDstData) = ulCheckSum;
300        *((ULONG *) (pjDstData + HWC_SIGNATURE_SizeX)) = pAST->HWCInfo.width;
301        *((ULONG *) (pjDstData + HWC_SIGNATURE_SizeY)) = pAST->HWCInfo.height;
302        *((ULONG *) (pjDstData + HWC_SIGNATURE_HOTSPOTX)) = 0;
303        *((ULONG *) (pjDstData + HWC_SIGNATURE_HOTSPOTY)) = 0;
304
305        /* set pattern offset */
306        ulPatternAddr = ((pAST->HWCInfo.ulHWCOffsetAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next) >> 3);
307        SetIndexReg(CRTC_PORT, 0xC8, (UCHAR) (ulPatternAddr & 0xFF));
308        SetIndexReg(CRTC_PORT, 0xC9, (UCHAR) ((ulPatternAddr >> 8) & 0xFF));
309        SetIndexReg(CRTC_PORT, 0xCA, (UCHAR) ((ulPatternAddr >> 16) & 0xFF));
310    }
311
312    /* update HWC_NUM_Next */
313    pAST->HWCInfo.HWC_NUM_Next = (pAST->HWCInfo.HWC_NUM_Next+1) % pAST->HWCInfo.HWC_NUM;
314
315}
316
317static Bool
318ASTUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
319{
320    if ( (pCurs->bits->width > MAX_HWC_WIDTH) || (pCurs->bits->height > MAX_HWC_HEIGHT) )
321        return FALSE;
322
323    return TRUE;
324}
325
326static void
327ASTLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
328{
329    ASTRecPtr 	pAST = ASTPTR(pScrn);
330
331    UCHAR	*pjDstXor, *pjSrcXor;
332    ULONG       i, j, ulSrcWidth, ulSrcHeight;
333    ULONG	ulPerPixelCopy, ulTwoPixelCopy;
334    LONG        lAlphaDstDelta, lLastAlphaDstDelta;
335    union
336    {
337        ULONG   ul;
338        UCHAR   b[4];
339    } ulSrcData32[2], ulData32;
340    union
341    {
342        USHORT  us;
343        UCHAR   b[2];
344    } usData16;
345    ULONG	ulCheckSum = 0;
346    ULONG 	ulPatternAddr;
347
348    /* init cursor info. */
349    pAST->HWCInfo.cursortype = HWC_COLOR;
350    pAST->HWCInfo.width  = pCurs->bits->width;
351    pAST->HWCInfo.height = pCurs->bits->height;
352    pAST->HWCInfo.offset_x = MAX_HWC_WIDTH - pAST->HWCInfo.width;
353    pAST->HWCInfo.offset_y = MAX_HWC_HEIGHT - pAST->HWCInfo.height;
354
355    /* copy cursor image to cache */
356    ulSrcWidth  =  pAST->HWCInfo.width;
357    ulSrcHeight =  pAST->HWCInfo.height;
358
359    lAlphaDstDelta = MAX_HWC_WIDTH << 1;
360    lLastAlphaDstDelta = lAlphaDstDelta - (ulSrcWidth << 1);
361
362    pjSrcXor  = (UCHAR *) pCurs->bits->argb;;
363    pjDstXor  = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next
364                        + lLastAlphaDstDelta + (MAX_HWC_HEIGHT - ulSrcHeight) * lAlphaDstDelta;
365
366    ulPerPixelCopy =  ulSrcWidth & 1;
367    ulTwoPixelCopy =  ulSrcWidth >> 1;
368
369    for (j = 0; j < ulSrcHeight; j++)
370    {
371
372        for (i = 0; i < ulTwoPixelCopy; i++ )
373        {
374            ulSrcData32[0].ul = *((ULONG *) pjSrcXor) & 0xF0F0F0F0;
375            ulSrcData32[1].ul = *((ULONG *) (pjSrcXor+4)) & 0xF0F0F0F0;
376            ulData32.b[0] = ulSrcData32[0].b[1] | (ulSrcData32[0].b[0] >> 4);
377            ulData32.b[1] = ulSrcData32[0].b[3] | (ulSrcData32[0].b[2] >> 4);
378            ulData32.b[2] = ulSrcData32[1].b[1] | (ulSrcData32[1].b[0] >> 4);
379            ulData32.b[3] = ulSrcData32[1].b[3] | (ulSrcData32[1].b[2] >> 4);
380            *((ULONG *) pjDstXor) = ulData32.ul;
381            ulCheckSum += (ULONG) ulData32.ul;
382            pjDstXor += 4;
383            pjSrcXor += 8;
384        }
385
386        for (i = 0; i < ulPerPixelCopy; i++ )
387        {
388            ulSrcData32[0].ul = *((ULONG *) pjSrcXor) & 0xF0F0F0F0;
389            usData16.b[0] = ulSrcData32[0].b[1] | (ulSrcData32[0].b[0] >> 4);
390            usData16.b[1] = ulSrcData32[0].b[3] | (ulSrcData32[0].b[2] >> 4);
391            *((USHORT *) pjDstXor) = usData16.us;
392            ulCheckSum += (ULONG) usData16.us;
393            pjDstXor += 2;
394            pjSrcXor += 4;
395        }
396
397        /* Point to next source and dest scans */
398        pjDstXor += lLastAlphaDstDelta;
399
400    } /* end of for-loop */
401
402    if (pAST->jChipType == AST1180)
403    {
404        ulPatternAddr = pAST->ulVRAMBase + (pAST->HWCInfo.ulHWCOffsetAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next);
405        WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_PATTERNADDR, ulPatternAddr);
406    }
407    else
408    {
409        /* Write Checksum as signature */
410        pjDstXor = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
411        *((ULONG *) pjDstXor) = ulCheckSum;
412        *((ULONG *) (pjDstXor + HWC_SIGNATURE_SizeX)) = pAST->HWCInfo.width;
413        *((ULONG *) (pjDstXor + HWC_SIGNATURE_SizeY)) = pAST->HWCInfo.height;
414        *((ULONG *) (pjDstXor + HWC_SIGNATURE_HOTSPOTX)) = 0;
415        *((ULONG *) (pjDstXor + HWC_SIGNATURE_HOTSPOTY)) = 0;
416
417        /* set pattern offset */
418        ulPatternAddr = ((pAST->HWCInfo.ulHWCOffsetAddr +(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next) >> 3);
419        SetIndexReg(CRTC_PORT, 0xC8, (UCHAR) (ulPatternAddr & 0xFF));
420        SetIndexReg(CRTC_PORT, 0xC9, (UCHAR) ((ulPatternAddr >> 8) & 0xFF));
421        SetIndexReg(CRTC_PORT, 0xCA, (UCHAR) ((ulPatternAddr >> 16) & 0xFF));
422    }
423
424    /* update HWC_NUM_Next */
425    pAST->HWCInfo.HWC_NUM_Next = (pAST->HWCInfo.HWC_NUM_Next+1) % pAST->HWCInfo.HWC_NUM;
426
427}
428
429static Bool
430ASTUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
431{
432    if ( (pCurs->bits->width > MAX_HWC_WIDTH) || (pCurs->bits->height > MAX_HWC_HEIGHT) )
433        return FALSE;
434
435    return TRUE;
436}
437
438static void
439ASTFireCursor(ScrnInfoPtr pScrn)
440{
441    ASTRecPtr  pAST = ASTPTR(pScrn);
442
443    SetIndexRegMask(CRTC_PORT, 0xCB, 0xFF, 0x00);	/* dummy write to fire HWC */
444
445}
446
447/* AST1180 */
448static void
449ASTShowCursor_AST1180(ScrnInfoPtr pScrn)
450{
451    ASTRecPtr   pAST = ASTPTR(pScrn);
452    ULONG 	ulData, ulTemp;
453
454    ReadAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_POSITION, ulTemp);
455
456    ReadAST1180SOC(AST1180_GFX_BASE+AST1180_VGA1_CTRL, ulData);
457    ulData &= ~AST1180_ALPHAHWC;
458    if (pAST->HWCInfo.cursortype ==HWC_COLOR)
459        ulData |= AST1180_ALPHAHWC;
460    ulData |= AST1180_ENABLEHWC;
461    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_VGA1_CTRL, ulData);
462
463    /* fire cursor */
464    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_POSITION, ulTemp);
465
466} /* ASTShowCursor_AST1180 */
467
468static void
469ASTHideCursor_AST1180(ScrnInfoPtr pScrn)
470{
471    ASTRecPtr  pAST = ASTPTR(pScrn);
472    ULONG 	ulData;
473
474    ReadAST1180SOC(AST1180_GFX_BASE+AST1180_VGA1_CTRL, ulData);
475    ulData &= ~AST1180_ENABLEHWC;
476    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_VGA1_CTRL, ulData);
477
478    /* fire cursor */
479    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_POSITION, 0x07ff07ff);
480
481} /* ASTHideCursor_AST1180 */
482
483static void
484ASTSetCursorPosition_AST1180(ScrnInfoPtr pScrn, int x, int y)
485{
486    ASTRecPtr	pAST = ASTPTR(pScrn);
487    DisplayModePtr mode = pAST->ModePtr;
488    int		x_offset, y_offset;
489    ULONG	ulData;
490
491    x_offset = pAST->HWCInfo.offset_x;
492    y_offset = pAST->HWCInfo.offset_y;
493
494    if(x < 0) {
495       x_offset = (-x) + pAST->HWCInfo.offset_x;
496       x = 0;
497    }
498
499    if(y < 0) {
500       y_offset = (-y) + pAST->HWCInfo.offset_y;
501       y = 0;
502    }
503
504    if(mode->Flags & V_DBLSCAN)  y *= 2;
505
506    /* Set to Reg. */
507    ulData = (x_offset) | (y_offset << 8);
508    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_OFFSET, ulData);
509    ulData = (x) | (y << 16);
510    WriteAST1180SOC(AST1180_GFX_BASE+AST1180_HWC1_POSITION, ulData);
511
512} /* ASTSetCursorPosition_AST1180 */
513
514#endif	/* End of HWC */
515