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