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