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