s3v_hwcurs.c revision 1d54945d
11d54945dSmrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3virge/s3v_hwcurs.c,v 1.7 2003/02/04 02:20:50 dawes Exp $ */ 21d54945dSmrg 31d54945dSmrg/* 41d54945dSmrgCopyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved. 51d54945dSmrg 61d54945dSmrgPermission is hereby granted, free of charge, to any person obtaining a copy of 71d54945dSmrgthis software and associated documentation files (the "Software"), to deal in 81d54945dSmrgthe Software without restriction, including without limitation the rights to 91d54945dSmrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 101d54945dSmrgof the Software, and to permit persons to whom the Software is furnished to do 111d54945dSmrgso, subject to the following conditions: 121d54945dSmrg 131d54945dSmrgThe above copyright notice and this permission notice shall be included in all 141d54945dSmrgcopies or substantial portions of the Software. 151d54945dSmrg 161d54945dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 171d54945dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- 181d54945dSmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 191d54945dSmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 201d54945dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 211d54945dSmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 221d54945dSmrg 231d54945dSmrgExcept as contained in this notice, the name of the XFree86 Project shall not 241d54945dSmrgbe used in advertising or otherwise to promote the sale, use or other dealings 251d54945dSmrgin this Software without prior written authorization from the XFree86 Project. 261d54945dSmrg*/ 271d54945dSmrg 281d54945dSmrg#ifdef HAVE_CONFIG_H 291d54945dSmrg#include "config.h" 301d54945dSmrg#endif 311d54945dSmrg 321d54945dSmrg/* 331d54945dSmrg * s3v_hwcurs.c 341d54945dSmrg * HW Cursor support for 4.0 design level 351d54945dSmrg * 361d54945dSmrg * S3 ViRGE driver 371d54945dSmrg * 381d54945dSmrg * 391d54945dSmrg */ 401d54945dSmrg 411d54945dSmrg 421d54945dSmrg#include "s3v.h" 431d54945dSmrg 441d54945dSmrg/* protos */ 451d54945dSmrg 461d54945dSmrgstatic void S3VLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src); 471d54945dSmrgstatic void S3VShowCursor(ScrnInfoPtr pScrn); 481d54945dSmrgstatic void S3VHideCursor(ScrnInfoPtr pScrn); 491d54945dSmrgstatic void S3VSetCursorPosition(ScrnInfoPtr pScrn, int x, int y); 501d54945dSmrgstatic void S3VSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg); 511d54945dSmrg 521d54945dSmrg 531d54945dSmrg/* 541d54945dSmrg * Read/write to the DAC via MMIO 551d54945dSmrg */ 561d54945dSmrg 571d54945dSmrg#define inCRReg(reg) (VGAHWPTR(pScrn))->readCrtc( VGAHWPTR(pScrn), reg ) 581d54945dSmrg#define outCRReg(reg, val) (VGAHWPTR(pScrn))->writeCrtc( VGAHWPTR(pScrn), reg, val ) 591d54945dSmrg 601d54945dSmrg 611d54945dSmrg 621d54945dSmrg/**** 631d54945dSmrg *** HW Cursor 641d54945dSmrg */ 651d54945dSmrgstatic void 661d54945dSmrgS3VLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) 671d54945dSmrg{ 681d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 691d54945dSmrg 701d54945dSmrg /*PVERB5(" S3VLoadCursorImage\n");*/ 711d54945dSmrg 721d54945dSmrg /* Load storage location. */ 731d54945dSmrg outCRReg( HWCURSOR_ADDR_LOW_CR4D, 0xff & (ps3v->FBCursorOffset/1024)); 741d54945dSmrg outCRReg( HWCURSOR_ADDR_HIGH_CR4C, (0x0f00 & (ps3v->FBCursorOffset/1024)) >> 8); 751d54945dSmrg 761d54945dSmrg /* Copy cursor image to framebuffer storage */ 771d54945dSmrg memcpy( (ps3v->FBBase + ps3v->FBCursorOffset), src, 1024); 781d54945dSmrg 791d54945dSmrg} 801d54945dSmrg 811d54945dSmrg 821d54945dSmrgstatic void 831d54945dSmrgS3VShowCursor(ScrnInfoPtr pScrn) 841d54945dSmrg{ 851d54945dSmrg char tmp; 861d54945dSmrg 871d54945dSmrg tmp = inCRReg(HWCURSOR_MODE_CR45); 881d54945dSmrg /* Enable cursor */ 891d54945dSmrg outCRReg(HWCURSOR_MODE_CR45, tmp | 1 ); 901d54945dSmrg} 911d54945dSmrg 921d54945dSmrg 931d54945dSmrgstatic void 941d54945dSmrgS3VHideCursor(ScrnInfoPtr pScrn) 951d54945dSmrg{ 961d54945dSmrg char tmp; 971d54945dSmrg 981d54945dSmrg tmp = inCRReg(HWCURSOR_MODE_CR45); 991d54945dSmrg /* Disable cursor */ 1001d54945dSmrg outCRReg(HWCURSOR_MODE_CR45, tmp & ~1 ); 1011d54945dSmrg} 1021d54945dSmrg 1031d54945dSmrg 1041d54945dSmrgstatic void 1051d54945dSmrgS3VSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 1061d54945dSmrg{ 1071d54945dSmrg unsigned char xoff = 0, yoff = 0; 1081d54945dSmrg 1091d54945dSmrg /* 1101d54945dSmrg if (!xf86VTSema) 1111d54945dSmrg return; 1121d54945dSmrg */ 1131d54945dSmrg 1141d54945dSmrg /* 1151d54945dSmrg x -= s3vHotX; 1161d54945dSmrg y -= s3vHotY; 1171d54945dSmrg */ 1181d54945dSmrg 1191d54945dSmrg /* 1201d54945dSmrg * Make these even when used. There is a bug/feature on at least 1211d54945dSmrg * some chipsets that causes a "shadow" of the cursor in interlaced 1221d54945dSmrg * mode. Making this even seems to have no visible effect, so just 1231d54945dSmrg * do it for the generic case. 1241d54945dSmrg * note - xoff & yoff are used for displaying partial cursors on screen 1251d54945dSmrg * edges. 1261d54945dSmrg */ 1271d54945dSmrg 1281d54945dSmrg if (x < 0) { 1291d54945dSmrg xoff = ((-x) & 0xFE); 1301d54945dSmrg x = 0; 1311d54945dSmrg } 1321d54945dSmrg 1331d54945dSmrg if (y < 0) { 1341d54945dSmrg yoff = ((-y) & 0xFE); 1351d54945dSmrg y = 0; 1361d54945dSmrg } 1371d54945dSmrg 1381d54945dSmrg /* Double y position for a doublescan mode */ 1391d54945dSmrg if(pScrn->currentMode->Flags & V_DBLSCAN) y <<= 1; 1401d54945dSmrg 1411d54945dSmrg /* This is the recommended order to move the cursor */ 1421d54945dSmrg 1431d54945dSmrg outCRReg( 0x46, (x & 0xff00)>>8 ); 1441d54945dSmrg outCRReg( 0x47, (x & 0xff) ); 1451d54945dSmrg outCRReg( 0x49, (y & 0xff) ); 1461d54945dSmrg outCRReg( 0x4e, xoff ); 1471d54945dSmrg outCRReg( 0x4f, yoff ); 1481d54945dSmrg outCRReg( 0x48, (y & 0xff00)>>8 ); 1491d54945dSmrg} 1501d54945dSmrg 1511d54945dSmrg 1521d54945dSmrgstatic void 1531d54945dSmrgS3VSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 1541d54945dSmrg{ 1551d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 1561d54945dSmrg 1571d54945dSmrg /*PVERB5(" S3VSetCursorColors\n");*/ 1581d54945dSmrg 1591d54945dSmrg switch( pScrn->bitsPerPixel) { 1601d54945dSmrg case 8: 1611d54945dSmrg if (!(S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset))) { 1621d54945dSmrg /* Reset the cursor color stack pointer */ 1631d54945dSmrg inCRReg(0x45); 1641d54945dSmrg /* Write foreground */ 1651d54945dSmrg outCRReg(0x4a, fg); 1661d54945dSmrg outCRReg(0x4a, fg); 1671d54945dSmrg /* Reset the cursor color stack pointer */ 1681d54945dSmrg inCRReg(0x45); 1691d54945dSmrg /* Write background */ 1701d54945dSmrg outCRReg(0x4b, bg); 1711d54945dSmrg outCRReg(0x4b, bg); 1721d54945dSmrg break; 1731d54945dSmrg } /* else fall through for ViRGE/MX... */ 1741d54945dSmrg case 16: 1751d54945dSmrg if (!(S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset))) { 1761d54945dSmrg /* adjust colors to 16 bits */ 1771d54945dSmrg if (pScrn->weight.green == 5 && ps3v->Chipset != S3_ViRGE_VX) { 1781d54945dSmrg fg = ((fg & 0xf80000) >> 9) | 1791d54945dSmrg ((fg & 0xf800) >> 6) | 1801d54945dSmrg ((fg & 0xf8) >> 3); 1811d54945dSmrg bg = ((bg & 0xf80000) >> 9) | 1821d54945dSmrg ((bg & 0xf800) >> 6) | 1831d54945dSmrg ((bg & 0xf8) >> 3); 1841d54945dSmrg } else { 1851d54945dSmrg fg = ((fg & 0xf80000) >> 8) | 1861d54945dSmrg ((fg & 0xfc00) >> 5) | 1871d54945dSmrg ((fg & 0xf8) >> 3); 1881d54945dSmrg bg = ((bg & 0xf80000) >> 8) | 1891d54945dSmrg ((bg & 0xfc00) >> 5) | 1901d54945dSmrg ((bg & 0xf8) >> 3); 1911d54945dSmrg } 1921d54945dSmrg 1931d54945dSmrg inCRReg(0x45); 1941d54945dSmrg /* Write foreground */ 1951d54945dSmrg outCRReg(0x4a, fg); 1961d54945dSmrg outCRReg(0x4a, fg >> 8); 1971d54945dSmrg /* needed for 2nd pixel in double-clock modes */ 1981d54945dSmrg outCRReg(0x4a, fg); 1991d54945dSmrg outCRReg(0x4a, fg >> 8); 2001d54945dSmrg /* Reset the cursor color stack pointer */ 2011d54945dSmrg inCRReg(0x45); 2021d54945dSmrg /* Write background */ 2031d54945dSmrg outCRReg(0x4b, bg); 2041d54945dSmrg outCRReg(0x4b, bg >> 8); 2051d54945dSmrg /* needed for 2nd pixel in double-clock modes */ 2061d54945dSmrg outCRReg(0x4b, bg); 2071d54945dSmrg outCRReg(0x4b, bg >> 8); 2081d54945dSmrg break; 2091d54945dSmrg } /* else fall through for ViRGE/MX... */ 2101d54945dSmrg 2111d54945dSmrg case 24: 2121d54945dSmrg case 32: 2131d54945dSmrg /* Do it straight, full 24 bit color. */ 2141d54945dSmrg 2151d54945dSmrg /* Reset the cursor color stack pointer */ 2161d54945dSmrg inCRReg(0x45); 2171d54945dSmrg /* Write low, mid, high bytes - foreground */ 2181d54945dSmrg outCRReg(0x4a, fg); 2191d54945dSmrg outCRReg(0x4a, fg >> 8); 2201d54945dSmrg outCRReg(0x4a, fg >> 16); 2211d54945dSmrg /* Reset the cursor color stack pointer */ 2221d54945dSmrg inCRReg(0x45); 2231d54945dSmrg /* Write low, mid, high bytes - background */ 2241d54945dSmrg outCRReg(0x4b, bg); 2251d54945dSmrg outCRReg(0x4b, bg >> 8); 2261d54945dSmrg outCRReg(0x4b, bg >> 16); 2271d54945dSmrg break; 2281d54945dSmrg } 2291d54945dSmrg} 2301d54945dSmrg 2311d54945dSmrg 2321d54945dSmrgBool 2331d54945dSmrgS3VHWCursorInit(ScreenPtr pScreen) 2341d54945dSmrg{ 2351d54945dSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 2361d54945dSmrg S3VPtr ps3v = S3VPTR(pScrn); 2371d54945dSmrg xf86CursorInfoPtr infoPtr; 2381d54945dSmrg 2391d54945dSmrg PVERB5(" S3VHWCursorInit\n"); 2401d54945dSmrg 2411d54945dSmrg infoPtr = xf86CreateCursorInfoRec(); 2421d54945dSmrg if(!infoPtr) return FALSE; 2431d54945dSmrg 2441d54945dSmrg ps3v->CursorInfoRec = infoPtr; 2451d54945dSmrg 2461d54945dSmrg infoPtr->MaxWidth = 64; 2471d54945dSmrg infoPtr->MaxHeight = 64; 2481d54945dSmrg infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 | 2491d54945dSmrg HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | 2501d54945dSmrg HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 2511d54945dSmrg HARDWARE_CURSOR_BIT_ORDER_MSBFIRST; 2521d54945dSmrg if (S3_ViRGE_GX2_SERIES(ps3v->Chipset) || S3_ViRGE_MX_SERIES(ps3v->Chipset)) 2531d54945dSmrg infoPtr->Flags |= HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 2541d54945dSmrg HARDWARE_CURSOR_INVERT_MASK; 2551d54945dSmrg 2561d54945dSmrg infoPtr->SetCursorColors = S3VSetCursorColors; 2571d54945dSmrg infoPtr->SetCursorPosition = S3VSetCursorPosition; 2581d54945dSmrg infoPtr->LoadCursorImage = S3VLoadCursorImage; 2591d54945dSmrg infoPtr->HideCursor = S3VHideCursor; 2601d54945dSmrg infoPtr->ShowCursor = S3VShowCursor; 2611d54945dSmrg infoPtr->UseHWCursor = NULL; 2621d54945dSmrg 2631d54945dSmrg return(xf86InitCursor(pScreen, infoPtr)); 2641d54945dSmrg} 2651d54945dSmrg 2661d54945dSmrg/*EOF*/ 267