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