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