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