ast_cursor.c revision 15fb4814
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 "xf86Resources.h"
29#include "xf86RAC.h"
30#include "xf86cmap.h"
31#include "compiler.h"
32#include "mibstore.h"
33#include "vgaHW.h"
34#include "mipointer.h"
35#include "micmap.h"
36
37#include "fb.h"
38#include "regionstr.h"
39#include "xf86xv.h"
40#include <X11/extensions/Xv.h>
41#include "vbe.h"
42
43#include "xf86PciInfo.h"
44#include "xf86Pci.h"
45
46/* framebuffer offscreen manager */
47#include "xf86fbman.h"
48
49/* include xaa includes */
50#include "xaa.h"
51#include "xaarop.h"
52
53/* H/W cursor support */
54#include "xf86Cursor.h"
55#include "cursorstr.h"
56
57/* Driver specific headers */
58#include "ast.h"
59
60#ifdef	HWC
61/* Prototype type declaration */
62Bool ASTCursorInit(ScreenPtr pScreen);
63Bool bInitHWC(ScrnInfoPtr pScrn, ASTRecPtr pAST);
64static void ASTShowCursor(ScrnInfoPtr pScrn);
65static void ASTHideCursor(ScrnInfoPtr pScrn);
66static void ASTSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
67static void ASTSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
68static void ASTLoadCursorImage(ScrnInfoPtr pScrn, UCHAR *src);
69static Bool ASTUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
70static void ASTLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs);
71static Bool ASTUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs);
72
73static void ASTFireCursor(ScrnInfoPtr pScrn);
74
75Bool
76ASTCursorInit(ScreenPtr pScreen)
77{
78    ScrnInfoPtr	pScrn = xf86Screens[pScreen->myNum];
79    ASTRecPtr 	pAST = ASTPTR(pScrn);
80    xf86CursorInfoPtr infoPtr;
81
82    infoPtr = xf86CreateCursorInfoRec();
83    if(!infoPtr) return FALSE;
84
85    pAST->HWCInfoPtr = infoPtr;
86
87    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
88                     HARDWARE_CURSOR_INVERT_MASK |
89                     HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
90
91    infoPtr->MaxWidth  = MAX_HWC_WIDTH;
92    infoPtr->MaxHeight = MAX_HWC_HEIGHT;
93    infoPtr->ShowCursor = ASTShowCursor;
94    infoPtr->HideCursor = ASTHideCursor;
95    infoPtr->SetCursorPosition = ASTSetCursorPosition;
96    infoPtr->SetCursorColors = ASTSetCursorColors;
97    infoPtr->LoadCursorImage = ASTLoadCursorImage;
98    infoPtr->UseHWCursor = ASTUseHWCursor;
99#ifdef ARGB_CURSOR
100    infoPtr->UseHWCursorARGB = ASTUseHWCursorARGB;
101    infoPtr->LoadCursorARGB = ASTLoadCursorARGB;
102#endif
103
104    return(xf86InitCursor(pScreen, infoPtr));
105
106}
107
108Bool bInitHWC(ScrnInfoPtr pScrn, ASTRecPtr pAST)
109{
110    ScreenPtr	pScreen;
111
112    /* init cursor cache info */
113    /* Set HWC_NUM in Options instead */
114    /* pAST->HWCInfo.HWC_NUM = DEFAULT_HWC_NUM; */
115    pAST->HWCInfo.HWC_NUM_Next = 0;
116
117    /* allocate HWC cache */
118    if (!pAST->pHWCPtr) {
119        pScreen = screenInfo.screens[pScrn->scrnIndex];
120        pAST->pHWCPtr = xf86AllocateOffscreenLinear (pScreen, (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM, HWC_ALIGN, NULL, NULL, NULL);
121
122        if (!pAST->pHWCPtr) {
123           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Allocate HWC Cache failed \n");
124           return (FALSE);
125        }
126
127        pAST->HWCInfo.ulHWCOffsetAddr  = pAST->pHWCPtr->offset*((pScrn->bitsPerPixel + 1) / 8);
128        pAST->HWCInfo.pjHWCVirtualAddr = pAST->FBVirtualAddr + pAST->HWCInfo.ulHWCOffsetAddr;
129    }
130
131    return (TRUE);
132}
133
134
135static void
136ASTShowCursor(ScrnInfoPtr pScrn)
137{
138    ASTRecPtr   pAST = ASTPTR(pScrn);
139    UCHAR 	jReg;
140
141    jReg= 0x02;
142    if (pAST->HWCInfo.cursortype ==HWC_COLOR)
143        jReg |= 0x01;
144
145    SetIndexRegMask(CRTC_PORT, 0xCB, 0xFC, jReg);	/* enable mono */
146
147}
148
149static void
150ASTHideCursor(ScrnInfoPtr pScrn)
151{
152    ASTRecPtr  pAST = ASTPTR(pScrn);
153
154    SetIndexRegMask(CRTC_PORT, 0xCB, 0xFC, 0x00);	/* disable HWC */
155
156}
157
158static void
159ASTSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
160{
161    ASTRecPtr	pAST = ASTPTR(pScrn);
162    DisplayModePtr mode = pAST->ModePtr;
163    int		x_offset, y_offset;
164    UCHAR 	*pjSignature;
165
166    /* Set cursor info to Offscreen */
167    pjSignature = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
168    *((ULONG *) (pjSignature + HWC_SIGNATURE_X)) = x;
169    *((ULONG *) (pjSignature + HWC_SIGNATURE_Y)) = y;
170
171    x_offset = pAST->HWCInfo.offset_x;
172    y_offset = pAST->HWCInfo.offset_y;
173
174    if(x < 0) {
175       x_offset = (-x) + pAST->HWCInfo.offset_x;
176       x = 0;
177    }
178
179    if(y < 0) {
180       y_offset = (-y) + pAST->HWCInfo.offset_y;
181       y = 0;
182    }
183
184    if(mode->Flags & V_DBLSCAN)  y *= 2;
185
186    /* Set to Reg. */
187    SetIndexReg(CRTC_PORT, 0xC2, (UCHAR) (x_offset));
188    SetIndexReg(CRTC_PORT, 0xC3, (UCHAR) (y_offset));
189    SetIndexReg(CRTC_PORT, 0xC4, (UCHAR) (x & 0xFF));
190    SetIndexReg(CRTC_PORT, 0xC5, (UCHAR) ((x >> 8) & 0x0F));
191    SetIndexReg(CRTC_PORT, 0xC6, (UCHAR) (y & 0xFF));
192    SetIndexReg(CRTC_PORT, 0xC7, (UCHAR) ((y >> 8) & 0x07));
193
194    /* Fire HWC */
195    ASTFireCursor(pScrn);
196
197}
198
199static void
200ASTSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
201{
202    ASTRecPtr 	pAST = ASTPTR(pScrn);
203
204    pAST->HWCInfo.fg = (fg & 0x0F) | (((fg>>8) & 0x0F) << 4) | (((fg>>16) & 0x0F) << 8);
205    pAST->HWCInfo.bg = (bg & 0x0F) | (((bg>>8) & 0x0F) << 4) | (((bg>>16) & 0x0F) << 8);
206}
207
208static void
209ASTLoadCursorImage(ScrnInfoPtr pScrn, UCHAR *src)
210{
211    ASTRecPtr	pAST = ASTPTR(pScrn);
212    int 	i, j, k;
213    UCHAR 	*pjSrcAnd, *pjSrcXor, *pjDstData;
214    ULONG   	ulTempDstAnd32[2], ulTempDstXor32[2], ulTempDstData32[2];
215    UCHAR    	jTempSrcAnd32, jTempSrcXor32;
216    ULONG	ulCheckSum = 0;
217    ULONG 	ulPatternAddr;
218
219    /* init cursor info. */
220    pAST->HWCInfo.cursortype = HWC_MONO;
221    pAST->HWCInfo.width  = (USHORT) MAX_HWC_WIDTH;
222    pAST->HWCInfo.height = (USHORT) MAX_HWC_HEIGHT;
223    pAST->HWCInfo.offset_x = MAX_HWC_WIDTH - pAST->HWCInfo.width;
224    pAST->HWCInfo.offset_y = MAX_HWC_HEIGHT - pAST->HWCInfo.height;
225
226    /* copy cursor image to cache */
227    pjSrcXor = src;
228    pjSrcAnd = src + (MAX_HWC_WIDTH*MAX_HWC_HEIGHT/8);
229    pjDstData =  pAST->HWCInfo.pjHWCVirtualAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next;
230
231    for (j = 0; j < MAX_HWC_HEIGHT; j++)
232    {
233       for (i = 0; i < (MAX_HWC_WIDTH/8); i++ )
234       {
235       	    for (k=7; k>0; k-=2)
236       	    {
237                jTempSrcAnd32 = *((UCHAR *) pjSrcAnd);
238                jTempSrcXor32 = *((UCHAR *) pjSrcXor);
239                ulTempDstAnd32[0] = ((jTempSrcAnd32 >> k) & 0x01) ? 0x00008000L:0x00L;
240                ulTempDstXor32[0] = ((jTempSrcXor32 >> k) & 0x01) ? 0x00004000L:0x00L;
241                ulTempDstData32[0] = ((jTempSrcXor32 >> k) & 0x01) ? pAST->HWCInfo.fg:pAST->HWCInfo.bg;
242                ulTempDstAnd32[1] = ((jTempSrcAnd32 >> (k-1)) & 0x01) ? 0x80000000L:0x00L;
243                ulTempDstXor32[1] = ((jTempSrcXor32 >> (k-1)) & 0x01) ? 0x40000000L:0x00L;
244                ulTempDstData32[1] = ((jTempSrcXor32 >> (k-1)) & 0x01) ? (pAST->HWCInfo.fg << 16):(pAST->HWCInfo.bg << 16);
245                *((ULONG *) pjDstData) = ulTempDstAnd32[0] | ulTempDstXor32[0] | ulTempDstData32[0] | ulTempDstAnd32[1] | ulTempDstXor32[1] | ulTempDstData32[1];
246                ulCheckSum += *((ULONG *) pjDstData);
247                pjDstData += 4;
248
249            }
250            pjSrcAnd ++;
251            pjSrcXor ++;
252
253       }
254
255    }
256
257    /* Write Checksum as signature */
258    pjDstData = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
259    *((ULONG *) pjDstData) = ulCheckSum;
260    *((ULONG *) (pjDstData + HWC_SIGNATURE_SizeX)) = pAST->HWCInfo.width;
261    *((ULONG *) (pjDstData + HWC_SIGNATURE_SizeY)) = pAST->HWCInfo.height;
262    *((ULONG *) (pjDstData + HWC_SIGNATURE_HOTSPOTX)) = 0;
263    *((ULONG *) (pjDstData + HWC_SIGNATURE_HOTSPOTY)) = 0;
264
265    /* set pattern offset */
266    ulPatternAddr = ((pAST->HWCInfo.ulHWCOffsetAddr+(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next) >> 3);
267    SetIndexReg(CRTC_PORT, 0xC8, (UCHAR) (ulPatternAddr & 0xFF));
268    SetIndexReg(CRTC_PORT, 0xC9, (UCHAR) ((ulPatternAddr >> 8) & 0xFF));
269    SetIndexReg(CRTC_PORT, 0xCA, (UCHAR) ((ulPatternAddr >> 16) & 0xFF));
270
271    /* update HWC_NUM_Next */
272    pAST->HWCInfo.HWC_NUM_Next = (pAST->HWCInfo.HWC_NUM_Next+1) % pAST->HWCInfo.HWC_NUM;
273
274}
275
276static Bool
277ASTUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
278{
279    return TRUE;
280}
281
282static void
283ASTLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
284{
285    ASTRecPtr 	pAST = ASTPTR(pScrn);
286
287    UCHAR	*pjDstXor, *pjSrcXor;
288    ULONG       i, j, ulSrcWidth, ulSrcHeight;
289    ULONG	ulPerPixelCopy, ulTwoPixelCopy;
290    LONG        lAlphaDstDelta, lLastAlphaDstDelta;
291    union
292    {
293        ULONG   ul;
294        UCHAR   b[4];
295    } ulSrcData32[2], ulData32;
296    union
297    {
298        USHORT  us;
299        UCHAR   b[2];
300    } usData16;
301    ULONG	ulCheckSum = 0;
302    ULONG 	ulPatternAddr;
303
304    /* init cursor info. */
305    pAST->HWCInfo.cursortype = HWC_COLOR;
306    pAST->HWCInfo.width  = pCurs->bits->width;
307    pAST->HWCInfo.height = pCurs->bits->height;
308    pAST->HWCInfo.offset_x = MAX_HWC_WIDTH - pAST->HWCInfo.width;
309    pAST->HWCInfo.offset_y = MAX_HWC_HEIGHT - pAST->HWCInfo.height;
310
311    /* copy cursor image to cache */
312    ulSrcWidth  =  pAST->HWCInfo.width;
313    ulSrcHeight =  pAST->HWCInfo.height;
314
315    lAlphaDstDelta = MAX_HWC_WIDTH << 1;
316    lLastAlphaDstDelta = lAlphaDstDelta - (ulSrcWidth << 1);
317
318    pjSrcXor  = (UCHAR *) pCurs->bits->argb;;
319    pjDstXor  = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next
320                        + lLastAlphaDstDelta + (MAX_HWC_HEIGHT - ulSrcHeight) * lAlphaDstDelta;
321
322    ulPerPixelCopy =  ulSrcWidth & 1;
323    ulTwoPixelCopy =  ulSrcWidth >> 1;
324
325    for (j = 0; j < ulSrcHeight; j++)
326    {
327
328        for (i = 0; i < ulTwoPixelCopy; i++ )
329        {
330            ulSrcData32[0].ul = *((ULONG *) pjSrcXor) & 0xF0F0F0F0;
331            ulSrcData32[1].ul = *((ULONG *) (pjSrcXor+4)) & 0xF0F0F0F0;
332            ulData32.b[0] = ulSrcData32[0].b[1] | (ulSrcData32[0].b[0] >> 4);
333            ulData32.b[1] = ulSrcData32[0].b[3] | (ulSrcData32[0].b[2] >> 4);
334            ulData32.b[2] = ulSrcData32[1].b[1] | (ulSrcData32[1].b[0] >> 4);
335            ulData32.b[3] = ulSrcData32[1].b[3] | (ulSrcData32[1].b[2] >> 4);
336            *((ULONG *) pjDstXor) = ulData32.ul;
337            ulCheckSum += (ULONG) ulData32.ul;
338            pjDstXor += 4;
339            pjSrcXor += 8;
340        }
341
342        for (i = 0; i < ulPerPixelCopy; i++ )
343        {
344            ulSrcData32[0].ul = *((ULONG *) pjSrcXor) & 0xF0F0F0F0;
345            usData16.b[0] = ulSrcData32[0].b[1] | (ulSrcData32[0].b[0] >> 4);
346            usData16.b[1] = ulSrcData32[0].b[3] | (ulSrcData32[0].b[2] >> 4);
347            *((USHORT *) pjDstXor) = usData16.us;
348            ulCheckSum += (ULONG) usData16.us;
349            pjDstXor += 2;
350            pjSrcXor += 4;
351        }
352
353        /* Point to next source and dest scans */
354        pjDstXor += lLastAlphaDstDelta;
355
356    } /* end of for-loop */
357
358    /* Write Checksum as signature */
359    pjDstXor = (UCHAR *) pAST->HWCInfo.pjHWCVirtualAddr + (HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next + HWC_SIZE;
360    *((ULONG *) pjDstXor) = ulCheckSum;
361    *((ULONG *) (pjDstXor + HWC_SIGNATURE_SizeX)) = pAST->HWCInfo.width;
362    *((ULONG *) (pjDstXor + HWC_SIGNATURE_SizeY)) = pAST->HWCInfo.height;
363    *((ULONG *) (pjDstXor + HWC_SIGNATURE_HOTSPOTX)) = 0;
364    *((ULONG *) (pjDstXor + HWC_SIGNATURE_HOTSPOTY)) = 0;
365
366    /* set pattern offset */
367    ulPatternAddr = ((pAST->HWCInfo.ulHWCOffsetAddr +(HWC_SIZE+HWC_SIGNATURE_SIZE)*pAST->HWCInfo.HWC_NUM_Next) >> 3);
368    SetIndexReg(CRTC_PORT, 0xC8, (UCHAR) (ulPatternAddr & 0xFF));
369    SetIndexReg(CRTC_PORT, 0xC9, (UCHAR) ((ulPatternAddr >> 8) & 0xFF));
370    SetIndexReg(CRTC_PORT, 0xCA, (UCHAR) ((ulPatternAddr >> 16) & 0xFF));
371
372    /* update HWC_NUM_Next */
373    pAST->HWCInfo.HWC_NUM_Next = (pAST->HWCInfo.HWC_NUM_Next+1) % pAST->HWCInfo.HWC_NUM;
374
375}
376
377static Bool
378ASTUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
379{
380    return TRUE;
381}
382
383static void
384ASTFireCursor(ScrnInfoPtr pScrn)
385{
386    ASTRecPtr  pAST = ASTPTR(pScrn);
387
388    SetIndexRegMask(CRTC_PORT, 0xCB, 0xFF, 0x00);	/* dummp write to fire HWC */
389
390}
391
392#endif	/* End of HWC */
393