1/*
2 * XGI hardware cursor handling
3 *
4 * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1) Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2) Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3) The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Author:   Thomas Winischhofer <thomas@winischhofer.net>
29 *
30 * Idea based on code by Can-Ru Yeou, XGI Inc.
31 *
32 */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#include "xf86.h"
39#include "xf86PciInfo.h"
40#include "cursorstr.h"
41#include "misc.h"
42#include "vgaHW.h"
43#include "xgi.h"
44#include "xgi_cursor.h"
45
46static int currX = 0 , currY = 0 ;
47
48static void XGIG1_SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) ;
49
50#if X_BYTE_ORDER == X_BIG_ENDIAN
51# define BE_SWAP32(v) (lswapl(v))
52#else
53# define BE_SWAP32(v) (v)
54#endif
55
56
57/* Helper function for Xabre to convert mono image to ARGB */
58/* The Xabre's cursor engine for CRT2 is buggy and can't
59 * handle mono cursors. We therefore convert the mono image
60 * to ARGB
61 */
62
63static void
64Volari_ShowCursor(ScrnInfoPtr pScrn)
65{
66    XGIPtr    pXGI = XGIPTR(pScrn);
67 /*   unsigned long cursor_addr = pXGI->CursorOffset ;  */
68    unsigned long cursor_base = pXGI->CursorOffset/1024 ;
69
70    /* Jong 09/19/2007; bug fixing for ??? */
71    if( pXGI->HWARGBCursor )
72    {
73        xgiG2CRT1_EnableARGBHWCursor(cursor_base, 0);
74        if (pXGI->VBFlags & CRT2_ENABLE)
75        {
76    		xgiG2CRT2_EnableARGBHWCursor(cursor_base, 0);
77        }
78    }
79    else
80    {
81        xgiG2CRT1_EnableHWCursor(cursor_base, 0);
82        if (pXGI->VBFlags & CRT2_ENABLE)
83        {
84    	    xgiG2CRT2_EnableHWCursor(cursor_base, 0);
85        }
86    }
87
88    XGIG1_SetCursorPosition(pScrn, currX, currY) ;
89
90	/* Jong 02/05/2009; improve performance of WinBench 99 */
91	/* XGI_WaitEndRetrace(pXGI->RelIO); */
92}
93
94static void
95Volari_HideCursor(ScrnInfoPtr pScrn)
96{
97    XGIPtr    pXGI = XGIPTR(pScrn);
98
99    PDEBUG4(ErrorF("Volari_HideCursor(pScrn)\n"));
100    xgiG1CRT1_DisableHWCursor() ;
101    if (pXGI->VBFlags & CRT2_ENABLE)  {
102        xgiG1CRT2_DisableHWCursor() ;
103    }
104
105    XGIG1_SetCursorPosition(pScrn, currX, currY) ;
106
107	/* Jong 02/05/2009; improve performance of WinBench 99 */
108    /* XGI_WaitEndRetrace(pXGI->RelIO); */
109}
110
111static void
112XGIG1_SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
113{
114    XGIPtr    pXGI = XGIPTR(pScrn);
115
116    unsigned char    x_preset = 0;
117    unsigned char    y_preset = 0;
118
119    currX = x ;
120    currY = y ;
121
122/* ErrorF("\nHWC Set pos x:%d y:%d",x,y);*/
123    if (x < 0) {
124        x_preset = (-x);
125        x = 0;
126    }
127    if (y < 0) {
128        y_preset = (-y);
129        y = 0;
130    }
131
132    xgiG1CRT1_SetCursorPositionX(x , x_preset) ;
133    xgiG1CRT1_SetCursorPositionY(y , y_preset) ;
134    if (pXGI->VBFlags & CRT2_ENABLE)  {
135        xgiG1CRT2_SetCursorPositionX(x+13, x_preset) ;
136        xgiG1CRT2_SetCursorPositionY(y, y_preset) ;
137    }
138}
139
140static void
141Volari_SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
142{
143    XGIPtr pXGI = XGIPTR(pScrn);
144
145    xgiG1CRT1_SetCursorBGColor(bg) ;
146    xgiG1CRT1_SetCursorFGColor(fg) ;
147    if (pXGI->VBFlags & CRT2_ENABLE)  {
148        xgiG1CRT2_SetCursorBGColor(bg) ;
149        xgiG1CRT2_SetCursorFGColor(fg) ;
150    }
151    XGIG1_SetCursorPosition(pScrn, currX, currY) ;
152}
153
154static void
155Volari_LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
156{
157    XGIPtr pXGI = XGIPTR(pScrn);
158    const unsigned long cursor_base = pXGI->CursorOffset / 1024;
159    unsigned char *const pCursorShape =
160        pXGI->FbBase + pXGI->CursorOffset;
161
162
163    memcpy(pCursorShape, src, 1024);
164
165    xgiG2CRT1_SetCursorAddressPattern(cursor_base,0) ;
166    if (pXGI->VBFlags & CRT2_ENABLE)  {
167        xgiG2CRT2_SetCursorAddressPattern(cursor_base,0) ;
168    }
169    XGIG1_SetCursorPosition(pScrn, currX, currY) ;
170}
171
172static Bool
173Volari_UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
174{
175    ScrnInfoPtr       pScrn = xf86Screens[pScreen->myNum];
176    DisplayModePtr     mode = pScrn->currentMode;
177
178    if (mode->Flags & V_INTERLACE)
179    {
180        return FALSE;
181    }
182    return TRUE;
183}
184
185/* Jong 09/19/2007; Is this required? */
186Bool
187Volari_UseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
188{
189    ScrnInfoPtr       pScrn = xf86Screens[pScreen->myNum];
190    DisplayModePtr     mode = pScrn->currentMode;
191    XGIPtr pXGI = XGIPTR(pScrn);
192
193    if (mode->Flags & V_INTERLACE)
194    {
195        return FALSE;
196    }
197
198	/* DumpDDIName("Volari_UserHWCursorARGB()\n") ; */
199
200	return TRUE ;
201}
202
203/* Jong 09/19/2007; Is this required? */
204static void
205Volari_LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCursor)
206{
207    XGIPtr pXGI = XGIPTR(pScrn);
208    unsigned long cursor_addr = pXGI->CursorOffset ;
209    unsigned long cursor_base = pXGI->CursorOffset/1024 ;
210    unsigned char *pCursorShape ;
211	int i , j ; CARD32 *pDest,*pSrc ;
212	CursorBitsPtr pCursorBits = pCursor->bits ;
213
214
215	/* DumpDDIName("Volari_LoadCursorARGB()\n") ; */
216	pXGI->HWARGBCursor = TRUE ;
217    pCursorShape = pXGI->FbBase + cursor_addr ;
218
219	pSrc = pCursorBits->argb ;
220
221	pXGI->CurXPreset = 64-pCursorBits->width ;
222	pXGI->CurYPreset = 64-pCursorBits->height ;
223
224	for( i = 64 - pCursorBits->height ; i< 64 ; i++ )
225	{
226		pDest = (CARD32 *)(pCursorShape + i*64*4 ) ;
227		for( j = 64-pCursorBits->width ; j < 64 ; j++, pSrc++ )
228		{
229			pDest[j] = *pSrc ;
230		}
231	}
232
233    xgiG2CRT1_SetCursorAddressPattern(cursor_base,0) ;
234
235    if (pXGI->VBFlags & CRT2_ENABLE)  {
236        xgiG2CRT2_SetCursorAddressPattern(cursor_base,0) ;
237        /* xgiG1CRT2_SetCursorAddress(cursor_base) ; */
238        /* xgiG1CRT2_SetCursorPatternSelect(0) ; */
239    }
240    XGIG1_SetCursorPosition(pScrn, currX, currY) ;
241	PDEBUG4(vWaitCRT1VerticalRetrace(pScrn)) ;
242	PDEBUG4(XGIDumpMMIO(pScrn));
243}
244
245Bool
246XGIHWCursorInit(ScreenPtr pScreen)
247{
248    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
249    XGIPtr pXGI = XGIPTR(pScrn);
250    xf86CursorInfoPtr infoPtr;
251
252    infoPtr = xf86CreateCursorInfoRec();
253    if(!infoPtr) return FALSE;
254
255    pXGI->CursorInfoPtr = infoPtr;
256
257    switch (pXGI->Chipset)  {
258
259      case PCI_CHIP_XGIXG40:
260      case PCI_CHIP_XGIXG20:
261      case PCI_CHIP_XGIXG21:
262    case PCI_CHIP_XGIXG27:
263        default:
264    PDEBUG(ErrorF("--- HWCursorInit() \n"));
265        infoPtr->MaxWidth  = 64;
266        infoPtr->MaxHeight = 64;
267/* infoPtr->ShowCursor = Volari_ShowCursorColor; // */
268        infoPtr->ShowCursor = Volari_ShowCursor;
269        infoPtr->HideCursor = Volari_HideCursor;
270        infoPtr->SetCursorPosition = XGIG1_SetCursorPosition;
271        infoPtr->SetCursorColors = Volari_SetCursorColors;
272/* infoPtr->LoadCursorImage = Volari_LoadCursorImageColors; // */
273        infoPtr->LoadCursorImage = Volari_LoadCursorImage;
274        infoPtr->UseHWCursor = Volari_UseHWCursor;
275/* infoPtr->RealizeCursor = XGIRealizeCursorColor ; // */
276
277        /* Jong 09/19/2007; Is this required */
278	#ifdef XGI_ARGB_CURSOR
279		infoPtr->UseHWCursorARGB = Volari_UseHWCursorARGB ;
280		infoPtr->LoadCursorARGB = Volari_LoadCursorARGB ;
281	#endif
282
283        infoPtr->Flags =
284            HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
285            HARDWARE_CURSOR_INVERT_MASK |
286            HARDWARE_CURSOR_BIT_ORDER_MSBFIRST  |
287            HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
288            HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
289            HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64  ;
290        break ;
291    }
292
293    return(xf86InitCursor(pScreen, infoPtr));
294}
295