r128_cursor.c revision c582b7e3
1c582b7e3Smrg/*
2c582b7e3Smrg * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
3c582b7e3Smrg *                      Precision Insight, Inc., Cedar Park, Texas, and
4c582b7e3Smrg *                      VA Linux Systems Inc., Fremont, California.
5c582b7e3Smrg *
6c582b7e3Smrg * All Rights Reserved.
7c582b7e3Smrg *
8c582b7e3Smrg * Permission is hereby granted, free of charge, to any person obtaining
9c582b7e3Smrg * a copy of this software and associated documentation files (the
10c582b7e3Smrg * "Software"), to deal in the Software without restriction, including
11c582b7e3Smrg * without limitation on the rights to use, copy, modify, merge,
12c582b7e3Smrg * publish, distribute, sublicense, and/or sell copies of the Software,
13c582b7e3Smrg * and to permit persons to whom the Software is furnished to do so,
14c582b7e3Smrg * subject to the following conditions:
15c582b7e3Smrg *
16c582b7e3Smrg * The above copyright notice and this permission notice (including the
17c582b7e3Smrg * next paragraph) shall be included in all copies or substantial
18c582b7e3Smrg * portions of the Software.
19c582b7e3Smrg *
20c582b7e3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21c582b7e3Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22c582b7e3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23c582b7e3Smrg * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
24c582b7e3Smrg * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25c582b7e3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26c582b7e3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27c582b7e3Smrg * OTHER DEALINGS IN THE SOFTWARE.
28c582b7e3Smrg */
29c582b7e3Smrg
30c582b7e3Smrg/*
31c582b7e3Smrg * Authors:
32c582b7e3Smrg *   Rickard E. Faith <faith@valinux.com>
33c582b7e3Smrg *   Kevin E. Martin <martin@valinux.com>
34c582b7e3Smrg *
35c582b7e3Smrg * References:
36c582b7e3Smrg *
37c582b7e3Smrg *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
38c582b7e3Smrg *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
39c582b7e3Smrg *   1999.
40c582b7e3Smrg *
41c582b7e3Smrg *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
42c582b7e3Smrg *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
43c582b7e3Smrg *
44c582b7e3Smrg */
45c582b7e3Smrg
46c582b7e3Smrg#ifdef HAVE_CONFIG_H
47c582b7e3Smrg#include "config.h"
48c582b7e3Smrg#endif
49c582b7e3Smrg
50c582b7e3Smrg				/* Driver data structures */
51c582b7e3Smrg#include "r128.h"
52c582b7e3Smrg#include "r128_reg.h"
53c582b7e3Smrg
54c582b7e3Smrg				/* X and server generic header files */
55c582b7e3Smrg#include "xf86.h"
56c582b7e3Smrg
57c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
58c582b7e3Smrg#define P_SWAP32( a , b )                \
59c582b7e3Smrg       ((char *)a)[0] = ((char *)b)[3];  \
60c582b7e3Smrg       ((char *)a)[1] = ((char *)b)[2];  \
61c582b7e3Smrg       ((char *)a)[2] = ((char *)b)[1];  \
62c582b7e3Smrg       ((char *)a)[3] = ((char *)b)[0]
63c582b7e3Smrg
64c582b7e3Smrg#define P_SWAP16( a , b )                \
65c582b7e3Smrg       ((char *)a)[0] = ((char *)b)[1];  \
66c582b7e3Smrg       ((char *)a)[1] = ((char *)b)[0];  \
67c582b7e3Smrg       ((char *)a)[2] = ((char *)b)[3];  \
68c582b7e3Smrg       ((char *)a)[3] = ((char *)b)[2]
69c582b7e3Smrg#endif
70c582b7e3Smrg
71c582b7e3Smrg
72c582b7e3Smrg/* Set cursor foreground and background colors. */
73c582b7e3Smrgstatic void R128SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
74c582b7e3Smrg{
75c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
76c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
77c582b7e3Smrg
78c582b7e3Smrg    if(info->IsSecondary)
79c582b7e3Smrg    {
80c582b7e3Smrg        OUTREG(R128_CUR2_CLR0, bg);
81c582b7e3Smrg        OUTREG(R128_CUR2_CLR1, fg);
82c582b7e3Smrg    }
83c582b7e3Smrg    else
84c582b7e3Smrg    {
85c582b7e3Smrg    	OUTREG(R128_CUR_CLR0, bg);
86c582b7e3Smrg    	OUTREG(R128_CUR_CLR1, fg);
87c582b7e3Smrg    }
88c582b7e3Smrg}
89c582b7e3Smrg
90c582b7e3Smrg/* Set cursor position to (x,y) with offset into cursor bitmap at
91c582b7e3Smrg   (xorigin,yorigin). */
92c582b7e3Smrgstatic void R128SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
93c582b7e3Smrg{
94c582b7e3Smrg    R128InfoPtr           info      = R128PTR(pScrn);
95c582b7e3Smrg    unsigned char         *R128MMIO = info->MMIO;
96c582b7e3Smrg    xf86CursorInfoPtr     cursor    = info->cursor;
97c582b7e3Smrg    int                   xorigin   = 0;
98c582b7e3Smrg    int                   yorigin   = 0;
99c582b7e3Smrg    int                   total_y   = pScrn->frameY1 - pScrn->frameY0;
100c582b7e3Smrg
101c582b7e3Smrg    if (x < 0)                        xorigin = -x;
102c582b7e3Smrg    if (y < 0)                        yorigin = -y;
103c582b7e3Smrg    if (y > total_y)                  y       = total_y;
104c582b7e3Smrg    if (info->Flags & V_DBLSCAN)      y       *= 2;
105c582b7e3Smrg    if (xorigin >= cursor->MaxWidth)  xorigin = cursor->MaxWidth - 1;
106c582b7e3Smrg    if (yorigin >= cursor->MaxHeight) yorigin = cursor->MaxHeight - 1;
107c582b7e3Smrg
108c582b7e3Smrg    if(!info->IsSecondary)
109c582b7e3Smrg    {
110c582b7e3Smrg    	OUTREG(R128_CUR_HORZ_VERT_OFF,  R128_CUR_LOCK | (xorigin << 16) | yorigin);
111c582b7e3Smrg    	OUTREG(R128_CUR_HORZ_VERT_POSN, (R128_CUR_LOCK
112c582b7e3Smrg				     | ((xorigin ? 0 : x) << 16)
113c582b7e3Smrg				     | (yorigin ? 0 : y)));
114c582b7e3Smrg    	OUTREG(R128_CUR_OFFSET,         info->cursor_start + yorigin * 16);
115c582b7e3Smrg    }
116c582b7e3Smrg    else
117c582b7e3Smrg    {
118c582b7e3Smrg        OUTREG(R128_CUR2_HORZ_VERT_OFF,  (R128_CUR2_LOCK
119c582b7e3Smrg				       | (xorigin << 16)
120c582b7e3Smrg				       | yorigin));
121c582b7e3Smrg        OUTREG(R128_CUR2_HORZ_VERT_POSN, (R128_CUR2_LOCK
122c582b7e3Smrg				       | ((xorigin ? 0 : x) << 16)
123c582b7e3Smrg				       | (yorigin ? 0 : y)));
124c582b7e3Smrg        OUTREG(R128_CUR2_OFFSET,
125c582b7e3Smrg			info->cursor_start + pScrn->fbOffset + yorigin * 16);
126c582b7e3Smrg    }
127c582b7e3Smrg}
128c582b7e3Smrg
129c582b7e3Smrg/* Copy cursor image from `image' to video memory.  R128SetCursorPosition
130c582b7e3Smrg   will be called after this, so we can ignore xorigin and yorigin. */
131c582b7e3Smrgstatic void R128LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
132c582b7e3Smrg{
133c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
134c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
135c582b7e3Smrg    CARD32        *s        = (pointer)image;
136c582b7e3Smrg    CARD32        *d        = (pointer)((CARD8*)info->FB + info->cursor_start);
137c582b7e3Smrg    int           y;
138c582b7e3Smrg    CARD32        save;
139c582b7e3Smrg
140c582b7e3Smrg    if(!info->IsSecondary)
141c582b7e3Smrg    {
142c582b7e3Smrg    	save = INREG(R128_CRTC_GEN_CNTL);
143c582b7e3Smrg    	OUTREG(R128_CRTC_GEN_CNTL, save & (CARD32)~R128_CRTC_CUR_EN);
144c582b7e3Smrg    }
145c582b7e3Smrg    else
146c582b7e3Smrg    {
147c582b7e3Smrg        save = INREG(R128_CRTC2_GEN_CNTL);
148c582b7e3Smrg        OUTREG(R128_CRTC2_GEN_CNTL, save & (CARD32)~R128_CRTC2_CUR_EN);
149c582b7e3Smrg    }
150c582b7e3Smrg
151c582b7e3Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
152c582b7e3Smrg    switch(info->CurrentLayout.pixel_bytes) {
153c582b7e3Smrg    case 4:
154c582b7e3Smrg    case 3:
155c582b7e3Smrg	for (y = 0; y < 64; y++) {
156c582b7e3Smrg	    P_SWAP32(d,s);
157c582b7e3Smrg	    d++; s++;
158c582b7e3Smrg	    P_SWAP32(d,s);
159c582b7e3Smrg	    d++; s++;
160c582b7e3Smrg	    P_SWAP32(d,s);
161c582b7e3Smrg	    d++; s++;
162c582b7e3Smrg	    P_SWAP32(d,s);
163c582b7e3Smrg	    d++; s++;
164c582b7e3Smrg	}
165c582b7e3Smrg	break;
166c582b7e3Smrg    case 2:
167c582b7e3Smrg	for (y = 0; y < 64; y++) {
168c582b7e3Smrg	    P_SWAP16(d,s);
169c582b7e3Smrg	    d++; s++;
170c582b7e3Smrg	    P_SWAP16(d,s);
171c582b7e3Smrg	    d++; s++;
172c582b7e3Smrg	    P_SWAP16(d,s);
173c582b7e3Smrg	    d++; s++;
174c582b7e3Smrg	    P_SWAP16(d,s);
175c582b7e3Smrg	    d++; s++;
176c582b7e3Smrg	}
177c582b7e3Smrg	break;
178c582b7e3Smrg    default:
179c582b7e3Smrg	for (y = 0; y < 64; y++) {
180c582b7e3Smrg	    *d++ = *s++;
181c582b7e3Smrg	    *d++ = *s++;
182c582b7e3Smrg	    *d++ = *s++;
183c582b7e3Smrg	    *d++ = *s++;
184c582b7e3Smrg	}
185c582b7e3Smrg    }
186c582b7e3Smrg#else
187c582b7e3Smrg    for (y = 0; y < 64; y++) {
188c582b7e3Smrg	*d++ = *s++;
189c582b7e3Smrg	*d++ = *s++;
190c582b7e3Smrg	*d++ = *s++;
191c582b7e3Smrg	*d++ = *s++;
192c582b7e3Smrg    }
193c582b7e3Smrg#endif
194c582b7e3Smrg
195c582b7e3Smrg    /* Set the area after the cursor to be all transparent so that we
196c582b7e3Smrg       won't display corrupted cursors on the screen */
197c582b7e3Smrg    for (y = 0; y < 64; y++) {
198c582b7e3Smrg	*d++ = 0xffffffff; /* The AND bits */
199c582b7e3Smrg	*d++ = 0xffffffff;
200c582b7e3Smrg	*d++ = 0x00000000; /* The XOR bits */
201c582b7e3Smrg	*d++ = 0x00000000;
202c582b7e3Smrg    }
203c582b7e3Smrg
204c582b7e3Smrg
205c582b7e3Smrg    if(!info->IsSecondary)
206c582b7e3Smrg    	OUTREG(R128_CRTC_GEN_CNTL, save);
207c582b7e3Smrg    else
208c582b7e3Smrg        OUTREG(R128_CRTC2_GEN_CNTL, save);
209c582b7e3Smrg
210c582b7e3Smrg}
211c582b7e3Smrg
212c582b7e3Smrg/* Hide hardware cursor. */
213c582b7e3Smrgstatic void R128HideCursor(ScrnInfoPtr pScrn)
214c582b7e3Smrg{
215c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
216c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
217c582b7e3Smrg
218c582b7e3Smrg     if(info->IsSecondary)
219c582b7e3Smrg        OUTREGP(R128_CRTC2_GEN_CNTL, 0, ~R128_CRTC2_CUR_EN);
220c582b7e3Smrg     else
221c582b7e3Smrg    	OUTREGP(R128_CRTC_GEN_CNTL, 0, ~R128_CRTC_CUR_EN);
222c582b7e3Smrg}
223c582b7e3Smrg
224c582b7e3Smrg/* Show hardware cursor. */
225c582b7e3Smrgstatic void R128ShowCursor(ScrnInfoPtr pScrn)
226c582b7e3Smrg{
227c582b7e3Smrg    R128InfoPtr   info      = R128PTR(pScrn);
228c582b7e3Smrg    unsigned char *R128MMIO = info->MMIO;
229c582b7e3Smrg
230c582b7e3Smrg    if(info->IsSecondary)
231c582b7e3Smrg    {
232c582b7e3Smrg         OUTREGP(R128_CRTC2_GEN_CNTL, R128_CRTC2_CUR_EN,
233c582b7e3Smrg               ~R128_CRTC2_CUR_EN);
234c582b7e3Smrg    }
235c582b7e3Smrg    else
236c582b7e3Smrg    {
237c582b7e3Smrg    	OUTREGP(R128_CRTC_GEN_CNTL, R128_CRTC_CUR_EN, ~R128_CRTC_CUR_EN);
238c582b7e3Smrg    }
239c582b7e3Smrg}
240c582b7e3Smrg
241c582b7e3Smrg/* Determine if hardware cursor is in use. */
242c582b7e3Smrgstatic Bool R128UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
243c582b7e3Smrg{
244c582b7e3Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
245c582b7e3Smrg    R128InfoPtr info  = R128PTR(pScrn);
246c582b7e3Smrg
247c582b7e3Smrg    return info->cursor_start ? TRUE : FALSE;
248c582b7e3Smrg}
249c582b7e3Smrg
250c582b7e3Smrg/* Initialize hardware cursor support. */
251c582b7e3SmrgBool R128CursorInit(ScreenPtr pScreen)
252c582b7e3Smrg{
253c582b7e3Smrg    ScrnInfoPtr           pScrn   = xf86Screens[pScreen->myNum];
254c582b7e3Smrg    R128InfoPtr           info    = R128PTR(pScrn);
255c582b7e3Smrg    xf86CursorInfoPtr     cursor;
256c582b7e3Smrg    FBAreaPtr             fbarea;
257c582b7e3Smrg    int                   width;
258c582b7e3Smrg    int                   height;
259c582b7e3Smrg    int                   size;
260c582b7e3Smrg
261c582b7e3Smrg
262c582b7e3Smrg    if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE;
263c582b7e3Smrg
264c582b7e3Smrg    cursor->MaxWidth          = 64;
265c582b7e3Smrg    cursor->MaxHeight         = 64;
266c582b7e3Smrg    cursor->Flags             = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
267c582b7e3Smrg				 | HARDWARE_CURSOR_SHOW_TRANSPARENT
268c582b7e3Smrg				 | HARDWARE_CURSOR_UPDATE_UNHIDDEN
269c582b7e3Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
270c582b7e3Smrg				 | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
271c582b7e3Smrg#endif
272c582b7e3Smrg				 | HARDWARE_CURSOR_INVERT_MASK
273c582b7e3Smrg				 | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK
274c582b7e3Smrg				 | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64
275c582b7e3Smrg				 | HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK);
276c582b7e3Smrg
277c582b7e3Smrg    cursor->SetCursorColors   = R128SetCursorColors;
278c582b7e3Smrg    cursor->SetCursorPosition = R128SetCursorPosition;
279c582b7e3Smrg    cursor->LoadCursorImage   = R128LoadCursorImage;
280c582b7e3Smrg    cursor->HideCursor        = R128HideCursor;
281c582b7e3Smrg    cursor->ShowCursor        = R128ShowCursor;
282c582b7e3Smrg    cursor->UseHWCursor       = R128UseHWCursor;
283c582b7e3Smrg
284c582b7e3Smrg    size                      = (cursor->MaxWidth/4) * cursor->MaxHeight;
285c582b7e3Smrg    width                     = pScrn->displayWidth;
286c582b7e3Smrg    height                    = (size*2 + 1023) / pScrn->displayWidth;
287c582b7e3Smrg    fbarea                    = xf86AllocateOffscreenArea(pScreen,
288c582b7e3Smrg							  width,
289c582b7e3Smrg							  height,
290c582b7e3Smrg							  16,
291c582b7e3Smrg							  NULL,
292c582b7e3Smrg							  NULL,
293c582b7e3Smrg							  NULL);
294c582b7e3Smrg
295c582b7e3Smrg    if (!fbarea) {
296c582b7e3Smrg	info->cursor_start    = 0;
297c582b7e3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
298c582b7e3Smrg		   "Hardware cursor disabled"
299c582b7e3Smrg		   " due to insufficient offscreen memory\n");
300c582b7e3Smrg    } else {
301c582b7e3Smrg	info->cursor_start    = R128_ALIGN((fbarea->box.x1
302c582b7e3Smrg					    + width * fbarea->box.y1)
303c582b7e3Smrg					   * info->CurrentLayout.pixel_bytes, 16);
304c582b7e3Smrg	info->cursor_end      = info->cursor_start + size;
305c582b7e3Smrg    }
306c582b7e3Smrg
307c582b7e3Smrg    R128TRACE(("R128CursorInit (0x%08x-0x%08x)\n",
308c582b7e3Smrg	       info->cursor_start, info->cursor_end));
309c582b7e3Smrg
310c582b7e3Smrg    return xf86InitCursor(pScreen, cursor);
311c582b7e3Smrg}
312