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