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