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