s3v_hwcurs.c revision ba85709e
1
2/*
3Copyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of
6this software and associated documentation files (the "Software"), to deal in
7the Software without restriction, including without limitation the rights to
8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9of the Software, and to permit persons to whom the Software is furnished to do
10so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
17NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of the XFree86 Project shall not
23be used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from the XFree86 Project.
25*/
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31/*
32 * s3v_hwcurs.c
33 * HW Cursor support for 4.0 design level
34 *
35 * S3 ViRGE driver
36 *
37 *
38 */
39
40
41#include "s3v.h"
42
43/* protos */
44
45static void S3VLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
46static void S3VShowCursor(ScrnInfoPtr pScrn);
47static void S3VHideCursor(ScrnInfoPtr pScrn);
48static void S3VSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
49static void S3VSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
50
51
52/*
53 * Read/write to the DAC via MMIO
54 */
55
56#define inCRReg(reg) (VGAHWPTR(pScrn))->readCrtc( VGAHWPTR(pScrn), reg )
57#define outCRReg(reg, val) (VGAHWPTR(pScrn))->writeCrtc( VGAHWPTR(pScrn), reg, val )
58
59
60
61/****
62 ***  HW Cursor
63 */
64static void
65S3VLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
66{
67  S3VPtr ps3v = S3VPTR(pScrn);
68
69    /*PVERB5("	S3VLoadCursorImage\n");*/
70
71    /* Load storage location.  */
72    outCRReg( HWCURSOR_ADDR_LOW_CR4D, 0xff & (ps3v->FBCursorOffset/1024));
73    outCRReg( HWCURSOR_ADDR_HIGH_CR4C, (0x0f00 & (ps3v->FBCursorOffset/1024)) >> 8);
74
75	/* Copy cursor image to framebuffer storage */
76	memcpy( (ps3v->FBBase + ps3v->FBCursorOffset), src, 1024);
77
78}
79
80
81static void
82S3VShowCursor(ScrnInfoPtr pScrn)
83{
84  char tmp;
85
86  tmp = inCRReg(HWCURSOR_MODE_CR45);
87    /* Enable cursor */
88  outCRReg(HWCURSOR_MODE_CR45, tmp | 1 );
89}
90
91
92static void
93S3VHideCursor(ScrnInfoPtr pScrn)
94{
95  char tmp;
96
97  tmp = inCRReg(HWCURSOR_MODE_CR45);
98   /* Disable cursor */
99  outCRReg(HWCURSOR_MODE_CR45, tmp & ~1 );
100}
101
102
103static void
104S3VSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
105{
106   unsigned char xoff = 0, yoff = 0;
107
108   /*
109   if (!xf86VTSema)
110      return;
111    */
112
113   /*
114   x -= s3vHotX;
115   y -= s3vHotY;
116    */
117
118   /*
119    * Make these even when used.  There is a bug/feature on at least
120    * some chipsets that causes a "shadow" of the cursor in interlaced
121    * mode.  Making this even seems to have no visible effect, so just
122    * do it for the generic case.
123    * note - xoff & yoff are used for displaying partial cursors on screen
124    * edges.
125    */
126
127   if (x < 0) {
128     xoff = ((-x) & 0xFE);
129     x = 0;
130   }
131
132   if (y < 0) {
133      yoff = ((-y) & 0xFE);
134      y = 0;
135   }
136
137   /* Double y position for a doublescan mode */
138   if(pScrn->currentMode->Flags & V_DBLSCAN) y <<= 1;
139
140   /* This is the recommended order to move the cursor */
141
142   outCRReg( 0x46, (x & 0xff00)>>8 );
143   outCRReg( 0x47, (x & 0xff) );
144   outCRReg( 0x49, (y & 0xff) );
145   outCRReg( 0x4e, xoff );
146   outCRReg( 0x4f, yoff );
147   outCRReg( 0x48, (y & 0xff00)>>8 );
148}
149
150
151static void
152S3VSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
153{
154    S3VPtr ps3v = S3VPTR(pScrn);
155
156    /*PVERB5("	S3VSetCursorColors\n");*/
157
158	switch( pScrn->bitsPerPixel) {
159	case 8:
160	  if (!(S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset))) {
161	    /* Reset the cursor color stack pointer */
162	    inCRReg(0x45);
163	    /* Write foreground */
164	    outCRReg(0x4a, fg);
165	    outCRReg(0x4a, fg);
166	    /* Reset the cursor color stack pointer */
167	    inCRReg(0x45);
168	    /* Write background */
169	    outCRReg(0x4b, bg);
170	    outCRReg(0x4b, bg);
171	    break;
172	  }  /* else fall through for ViRGE/MX... */
173	case 16:
174	  if (!(S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset))) {
175	    /* adjust colors to 16 bits */
176	    if (pScrn->weight.green == 5 && ps3v->Chipset != S3_ViRGE_VX) {
177	      fg = ((fg & 0xf80000) >> 9) |
178		((fg & 0xf800) >> 6) |
179		((fg & 0xf8) >> 3);
180	      bg = ((bg & 0xf80000) >> 9) |
181		((bg & 0xf800) >> 6) |
182		((bg & 0xf8) >> 3);
183	    } else {
184	      fg = ((fg & 0xf80000) >> 8) |
185		((fg & 0xfc00) >> 5) |
186		((fg & 0xf8) >> 3);
187	      bg = ((bg & 0xf80000) >> 8) |
188		((bg & 0xfc00) >> 5) |
189		((bg & 0xf8) >> 3);
190	    }
191
192	    inCRReg(0x45);
193	    /* Write foreground */
194	    outCRReg(0x4a, fg);
195	    outCRReg(0x4a, fg >> 8);
196	    /* needed for 2nd pixel in double-clock modes */
197	    outCRReg(0x4a, fg);
198	    outCRReg(0x4a, fg >> 8);
199	    /* Reset the cursor color stack pointer */
200	    inCRReg(0x45);
201	    /* Write background */
202	    outCRReg(0x4b, bg);
203	    outCRReg(0x4b, bg >> 8);
204	    /* needed for 2nd pixel in double-clock modes */
205	    outCRReg(0x4b, bg);
206	    outCRReg(0x4b, bg >> 8);
207	    break;
208	  }  /* else fall through for ViRGE/MX... */
209
210	case 24:
211	case 32:
212	  /* Do it straight, full 24 bit color. */
213
214	  /* Reset the cursor color stack pointer */
215	  inCRReg(0x45);
216	  /* Write low, mid, high bytes - foreground */
217	  outCRReg(0x4a, fg);
218	  outCRReg(0x4a, fg >> 8);
219	  outCRReg(0x4a, fg >> 16);
220	  /* Reset the cursor color stack pointer */
221	  inCRReg(0x45);
222	  /* Write low, mid, high bytes - background */
223	  outCRReg(0x4b, bg);
224	  outCRReg(0x4b, bg >> 8);
225	  outCRReg(0x4b, bg >> 16);
226	  break;
227	}
228}
229
230
231Bool
232S3VHWCursorInit(ScreenPtr pScreen)
233{
234    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
235    S3VPtr ps3v = S3VPTR(pScrn);
236    xf86CursorInfoPtr infoPtr;
237
238    PVERB5("	S3VHWCursorInit\n");
239
240    infoPtr = xf86CreateCursorInfoRec();
241    if(!infoPtr) return FALSE;
242
243    ps3v->CursorInfoRec = infoPtr;
244
245    infoPtr->MaxWidth = 64;
246    infoPtr->MaxHeight = 64;
247    infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 |
248    				 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
249				 HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
250        			 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
251    if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset))
252       infoPtr->Flags |= HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
253	                 HARDWARE_CURSOR_INVERT_MASK;
254
255    infoPtr->SetCursorColors = S3VSetCursorColors;
256    infoPtr->SetCursorPosition = S3VSetCursorPosition;
257    infoPtr->LoadCursorImage = S3VLoadCursorImage;
258    infoPtr->HideCursor = S3VHideCursor;
259    infoPtr->ShowCursor = S3VShowCursor;
260    infoPtr->UseHWCursor = NULL;
261
262    return(xf86InitCursor(pScreen, infoPtr));
263}
264
265/*EOF*/
266