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