s3v_hwcurs.c revision 22663e35
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#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