tseng_cursor.c revision d983712d
1d983712dSmrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tseng/tseng_cursor.c,v 1.16 2000/09/19 12:46:19 eich Exp $ */ 2d983712dSmrg 3d983712dSmrg#ifdef HAVE_CONFIG_H 4d983712dSmrg#include "config.h" 5d983712dSmrg#endif 6d983712dSmrg 7d983712dSmrg#include "tseng.h" 8d983712dSmrg 9d983712dSmrg/* 10d983712dSmrg * 11d983712dSmrg * ET4000 HWCursor is disabled currently: we need to find a way to set the 12d983712dSmrg * sprite colours. 13d983712dSmrg * 14d983712dSmrg */ 15d983712dSmrg 16d983712dSmrg/* 17d983712dSmrg * ET4000W32 sprite engine. 18d983712dSmrg */ 19d983712dSmrgstatic CARD8 20d983712dSmrgET4000CursorRead(CARD8 Index) 21d983712dSmrg{ 22d983712dSmrg outb(0x217A, Index); 23d983712dSmrg return inb(0x217B); 24d983712dSmrg} 25d983712dSmrg 26d983712dSmrgstatic void 27d983712dSmrgET4000CursorWrite(CARD8 Index, CARD8 Value) 28d983712dSmrg{ 29d983712dSmrg outb(0x217A, Index); 30d983712dSmrg outb(0x217B, Value); 31d983712dSmrg} 32d983712dSmrg 33d983712dSmrg/* 34d983712dSmrg * 35d983712dSmrg */ 36d983712dSmrgstatic Bool 37d983712dSmrgTsengUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) 38d983712dSmrg{ 39d983712dSmrg /* have this return false for DoubleScan and Interlaced ? */ 40d983712dSmrg return TRUE; 41d983712dSmrg} 42d983712dSmrg 43d983712dSmrgstatic void 44d983712dSmrgTsengShowCursor(ScrnInfoPtr pScrn) 45d983712dSmrg{ 46d983712dSmrg unsigned char tmp; 47d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 48d983712dSmrg 49d983712dSmrg /* Enable the hardware cursor. */ 50d983712dSmrg if (pTseng->ChipType == ET6000) { 51d983712dSmrg tmp = ET6000IORead(pTseng, 0x46); 52d983712dSmrg ET6000IOWrite(pTseng, 0x46, (tmp | 0x01)); 53d983712dSmrg } else { 54d983712dSmrg tmp = ET4000CursorRead(0xF7); 55d983712dSmrg ET4000CursorWrite(0xF7, tmp | 0x80); 56d983712dSmrg } 57d983712dSmrg} 58d983712dSmrg 59d983712dSmrgstatic void 60d983712dSmrgTsengHideCursor(ScrnInfoPtr pScrn) 61d983712dSmrg{ 62d983712dSmrg unsigned char tmp; 63d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 64d983712dSmrg 65d983712dSmrg /* Disable the hardware cursor. */ 66d983712dSmrg if (pTseng->ChipType == ET6000) { 67d983712dSmrg tmp = ET6000IORead(pTseng, 0x46); 68d983712dSmrg ET6000IOWrite(pTseng, 0x46, (tmp & 0xfe)); 69d983712dSmrg } else { 70d983712dSmrg tmp = ET4000CursorRead(0xF7); 71d983712dSmrg ET4000CursorWrite(0xF7, tmp & ~0x80); 72d983712dSmrg } 73d983712dSmrg} 74d983712dSmrg 75d983712dSmrgstatic void 76d983712dSmrgTsengSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 77d983712dSmrg{ 78d983712dSmrg int xorigin, yorigin; 79d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 80d983712dSmrg 81d983712dSmrg /* 82d983712dSmrg * If the cursor is partly out of screen at the left or top, 83d983712dSmrg * we need to modify the origin. 84d983712dSmrg */ 85d983712dSmrg xorigin = 0; 86d983712dSmrg yorigin = 0; 87d983712dSmrg if (x < 0) { 88d983712dSmrg xorigin = -x; 89d983712dSmrg x = 0; 90d983712dSmrg } 91d983712dSmrg if (y < 0) { 92d983712dSmrg yorigin = -y; 93d983712dSmrg y = 0; 94d983712dSmrg } 95d983712dSmrg#ifdef TODO 96d983712dSmrg /* Correct cursor position in DoubleScan modes */ 97d983712dSmrg if (XF86SCRNINFO(pScr)->modes->Flags & V_DBLSCAN) 98d983712dSmrg y *= 2; 99d983712dSmrg#endif 100d983712dSmrg 101d983712dSmrg if (pTseng->ChipType == ET6000) { 102d983712dSmrg ET6000IOWrite(pTseng, 0x82, xorigin); 103d983712dSmrg ET6000IOWrite(pTseng, 0x83, yorigin); 104d983712dSmrg 105d983712dSmrg ET6000IOWrite(pTseng, 0x84, (x & 0xff)); 106d983712dSmrg ET6000IOWrite(pTseng, 0x85, ((x >> 8) & 0x0f)); 107d983712dSmrg 108d983712dSmrg ET6000IOWrite(pTseng, 0x86, (y & 0xff)); 109d983712dSmrg ET6000IOWrite(pTseng, 0x87, ((y >> 8) & 0x0f)); 110d983712dSmrg } else { 111d983712dSmrg ET4000CursorWrite(0xE2, xorigin); 112d983712dSmrg ET4000CursorWrite(0xE6, yorigin); 113d983712dSmrg 114d983712dSmrg ET4000CursorWrite(0xE0, x & 0xFF); 115d983712dSmrg ET4000CursorWrite(0xE1, (x >> 8) & 0x0F); 116d983712dSmrg 117d983712dSmrg ET4000CursorWrite(0xE4, y & 0xFF); 118d983712dSmrg ET4000CursorWrite(0xE5, (y >> 8) & 0x0F); 119d983712dSmrg } 120d983712dSmrg} 121d983712dSmrg 122d983712dSmrg/* 123d983712dSmrg * The ET6000 cursor color is only 6 bits, with 2 bits per color. This 124d983712dSmrg * is of course very inaccurate, but high-bit-depth color differences 125d983712dSmrg * are only visible on _large_ planes of equal color. i.e. small areas 126d983712dSmrg * of a certain color (like a cursor) don't need many bits per pixel at 127d983712dSmrg * all, because the difference will not be seen. 128d983712dSmrg * 129d983712dSmrg * So it won't be as bad, but should still be documented nonetheless. 130d983712dSmrg */ 131d983712dSmrgstatic void 132d983712dSmrgTsengSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 133d983712dSmrg{ 134d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 135d983712dSmrg unsigned char et6k_fg, et6k_bg; 136d983712dSmrg 137d983712dSmrg if (pTseng->ChipType == ET6000) { 138d983712dSmrg et6k_fg = (fg & 0x00000003) 139d983712dSmrg | ((fg & 0x00000300) >> 6) 140d983712dSmrg | ((fg & 0x00030000) >> 12); 141d983712dSmrg et6k_bg = (bg & 0x00000003) 142d983712dSmrg | ((bg & 0x00000300) >> 6) 143d983712dSmrg | ((bg & 0x00030000) >> 12); 144d983712dSmrg 145d983712dSmrg ET6000IOWrite(pTseng, 0x67, 0x09); /* prepare for colour data */ 146d983712dSmrg ET6000IOWrite(pTseng, 0x69, et6k_bg); 147d983712dSmrg ET6000IOWrite(pTseng, 0x69, et6k_fg); 148d983712dSmrg } else { 149d983712dSmrg /* 150d983712dSmrg * The ET4000 uses color 0 as sprite color "0", and color 0xFF as 151d983712dSmrg * sprite color "1". Changing colors implies changing colors 0 and 152d983712dSmrg * 255. This is currently not implemented. 153d983712dSmrg * 154d983712dSmrg * In non-8bpp modes, this would result in always black and white 155d983712dSmrg * colors (since the colormap isn't there to translate 0 and 255 to 156d983712dSmrg * other colors). And besides, in non-8bpp, there seem to be TWO 157d983712dSmrg * cursor images on the screen... 158d983712dSmrg */ 159d983712dSmrg xf86Msg(X_ERROR, "Internal error: ET4000 hardware cursor color changes not implemented\n"); 160d983712dSmrg } 161d983712dSmrg} 162d983712dSmrg 163d983712dSmrgvoid 164d983712dSmrgTsengLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits) 165d983712dSmrg{ 166d983712dSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 167d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 168d983712dSmrg CARD8 tmp; 169d983712dSmrg 170d983712dSmrg#ifdef DEBUG_HWC 171d983712dSmrg int i; 172d983712dSmrg int d; 173d983712dSmrg 174d983712dSmrg for (i = 0; i < 1024; i++) { 175d983712dSmrg d = *(bits + i); 176d983712dSmrg ErrorF("%d%d%d%d", d & 0x03, (d >> 2) & 0x03, (d >> 4) & 0x03, (d >> 6) & 0x03); 177d983712dSmrg if ((i & 15) == 15) 178d983712dSmrg ErrorF("\n"); 179d983712dSmrg } 180d983712dSmrg#endif 181d983712dSmrg 182d983712dSmrg /* 183d983712dSmrg * Program the cursor image address in video memory. 184d983712dSmrg * We need to set it here or we might loose it on mode/vt switches. 185d983712dSmrg */ 186d983712dSmrg 187d983712dSmrg if (pTseng->ChipType == ET6000) { 188d983712dSmrg /* bits 19:16 */ 189d983712dSmrg tmp = hwp->readCrtc(hwp, 0x0E) & 0xF0; 190d983712dSmrg tmp |= ((pTseng->HWCursorBufferOffset / 4) >> 16) & 0x0F; 191d983712dSmrg hwp->writeCrtc(hwp, 0x0E, tmp); 192d983712dSmrg 193d983712dSmrg /* bits 15:8 */ 194d983712dSmrg hwp->writeCrtc(hwp, 0x0F, ((pTseng->HWCursorBufferOffset / 4) >> 8) & 0xFF); 195d983712dSmrg /* on the ET6000, bits (7:0) are always 0 */ 196d983712dSmrg } else { 197d983712dSmrg /* bits 19:16 */ 198d983712dSmrg tmp = ET4000CursorRead(0xEA) & 0xF0; 199d983712dSmrg ET4000CursorWrite(0xEA, tmp | (((pTseng->HWCursorBufferOffset / 4) >> 16) & 0x0F)); 200d983712dSmrg /* bits 15:8 */ 201d983712dSmrg ET4000CursorWrite(0xE9, ((pTseng->HWCursorBufferOffset / 4) >> 8) & 0xFF); 202d983712dSmrg /* bits 7:0 */ 203d983712dSmrg ET4000CursorWrite(0xE8, (pTseng->HWCursorBufferOffset / 4) & 0xFF); 204d983712dSmrg 205d983712dSmrg /* this needs to be set for the sprite */ 206d983712dSmrg ET4000CursorWrite(0xEB, 0x02); 207d983712dSmrg 208d983712dSmrg tmp = ET4000CursorRead(0xEC); 209d983712dSmrg ET4000CursorWrite(0xEC, tmp & 0xFE); 210d983712dSmrg 211d983712dSmrg tmp = ET4000CursorRead(0xEF) & 0xF8; 212d983712dSmrg ET4000CursorWrite(0xEF, tmp | 0x02); 213d983712dSmrg 214d983712dSmrg ET4000CursorWrite(0xEE, 0x01); 215d983712dSmrg } 216d983712dSmrg /* this assumes the apertures have been set up correctly for banked mode */ 217d983712dSmrg memcpy(pTseng->HWCursorBuffer, bits, 1024); 218d983712dSmrg} 219d983712dSmrg 220d983712dSmrg/* 221d983712dSmrg * 222d983712dSmrg * 223d983712dSmrg */ 224d983712dSmrgBool 225d983712dSmrgTsengHWCursorInit(ScreenPtr pScreen) 226d983712dSmrg{ 227d983712dSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 228d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 229d983712dSmrg xf86CursorInfoPtr infoPtr; 230d983712dSmrg 231d983712dSmrg PDEBUG(" TsengHWCursorInit\n"); 232d983712dSmrg 233d983712dSmrg if (!pTseng->HWCursor) 234d983712dSmrg return FALSE; 235d983712dSmrg 236d983712dSmrg infoPtr = xf86CreateCursorInfoRec(); 237d983712dSmrg if (!infoPtr) 238d983712dSmrg return FALSE; 239d983712dSmrg 240d983712dSmrg pTseng->CursorInfoRec = infoPtr; 241d983712dSmrg 242d983712dSmrg /* calculate memory addres from video memory offsets */ 243d983712dSmrg pTseng->HWCursorBuffer = 244d983712dSmrg pTseng->FbBase + pTseng->HWCursorBufferOffset; 245d983712dSmrg 246d983712dSmrg /* set up the XAA HW cursor structure */ 247d983712dSmrg infoPtr->MaxWidth = 64; 248d983712dSmrg infoPtr->MaxHeight = 64; 249d983712dSmrg infoPtr->Flags = 250d983712dSmrg HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 251d983712dSmrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 252d983712dSmrg HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 253d983712dSmrg HARDWARE_CURSOR_INVERT_MASK; 254d983712dSmrg infoPtr->SetCursorColors = TsengSetCursorColors; 255d983712dSmrg infoPtr->SetCursorPosition = TsengSetCursorPosition; 256d983712dSmrg infoPtr->LoadCursorImage = TsengLoadCursorImage; 257d983712dSmrg infoPtr->HideCursor = TsengHideCursor; 258d983712dSmrg infoPtr->ShowCursor = TsengShowCursor; 259d983712dSmrg infoPtr->UseHWCursor = TsengUseHWCursor; 260d983712dSmrg 261d983712dSmrg return (xf86InitCursor(pScreen, infoPtr)); 262d983712dSmrg} 263d983712dSmrg 264d983712dSmrg/* 265d983712dSmrg * 266d983712dSmrg */ 267d983712dSmrgvoid 268d983712dSmrgTsengCursorStore(ScrnInfoPtr pScrn, TsengRegPtr Reg) 269d983712dSmrg{ 270d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 271d983712dSmrg 272d983712dSmrg if (pTseng->ChipType == ET4000) 273d983712dSmrg Reg->CursorCtrl = ET4000CursorRead(0xF7); 274d983712dSmrg} 275d983712dSmrg 276d983712dSmrg/* 277d983712dSmrg * 278d983712dSmrg */ 279d983712dSmrgvoid 280d983712dSmrgTsengCursorRestore(ScrnInfoPtr pScrn, TsengRegPtr Reg) 281d983712dSmrg{ 282d983712dSmrg TsengPtr pTseng = TsengPTR(pScrn); 283d983712dSmrg 284d983712dSmrg if (pTseng->ChipType == ET4000) 285d983712dSmrg ET4000CursorWrite(0xF7, Reg->CursorCtrl); 286d983712dSmrg} 287