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