1340e3fbdSmrg/*
2340e3fbdSmrg *      Copyright 2001  Ani Joshi <ajoshi@unixbox.com>
3340e3fbdSmrg *
4340e3fbdSmrg *      XFree86 4.x driver for S3 chipsets
5340e3fbdSmrg *
6340e3fbdSmrg *
7340e3fbdSmrg * Permission to use, copy, modify, distribute, and sell this software and its
8340e3fbdSmrg * documentation for any purpose is hereby granted without fee, provided that
9340e3fbdSmrg * the above copyright notice appear in all copies and that both that copyright
10340e3fbdSmrg * notice and this permission notice appear in supporting documentation and
11340e3fbdSmrg * that the name of Ani Joshi not be used in advertising or
12340e3fbdSmrg * publicity pertaining to distribution of the software without specific,
13340e3fbdSmrg * written prior permission.  Ani Joshi makes no representations
14340e3fbdSmrg * about the suitability of this software for any purpose.  It is provided
15340e3fbdSmrg * "as-is" without express or implied warranty.
16340e3fbdSmrg *
17340e3fbdSmrg * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18340e3fbdSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19340e3fbdSmrg * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20340e3fbdSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21340e3fbdSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22340e3fbdSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23340e3fbdSmrg * PERFORMANCE OF THIS SOFTWARE.
24340e3fbdSmrg *
25340e3fbdSmrg *
26340e3fbdSmrg */
27340e3fbdSmrg
28340e3fbdSmrg#ifdef HAVE_CONFIG_H
29340e3fbdSmrg#include "config.h"
30340e3fbdSmrg#endif
31340e3fbdSmrg
32340e3fbdSmrg#include "xf86.h"
33340e3fbdSmrg#include "xf86_OSproc.h"
34340e3fbdSmrg
35340e3fbdSmrg#include "compiler.h"
36340e3fbdSmrg
37340e3fbdSmrg#include "s3.h"
38340e3fbdSmrg#include "s3_reg.h"
39340e3fbdSmrg
40340e3fbdSmrg
41340e3fbdSmrgstatic void S3SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
42340e3fbdSmrg{
43340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
44340e3fbdSmrg	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
45340e3fbdSmrg	unsigned short packfg, packbg;
46340e3fbdSmrg
47340e3fbdSmrg	switch (pS3->s3Bpp) {
48340e3fbdSmrg	case 1:
49340e3fbdSmrg		/* XXX Trio series only */
50340e3fbdSmrg		outb(vgaCRIndex, 0x45);
51340e3fbdSmrg		inb(vgaCRReg);
52340e3fbdSmrg		outb(vgaCRIndex, 0x4a);
53340e3fbdSmrg		outb(vgaCRReg, fg);
54340e3fbdSmrg		outb(vgaCRReg, fg);
55340e3fbdSmrg
56340e3fbdSmrg		outb(vgaCRIndex, 0x45);
57340e3fbdSmrg		inb(vgaCRReg);
58340e3fbdSmrg		outb(vgaCRIndex, 0x4b);
59340e3fbdSmrg		outb(vgaCRReg, bg);
60340e3fbdSmrg		outb(vgaCRReg, bg);
61340e3fbdSmrg
62340e3fbdSmrg		break;
63340e3fbdSmrg	case 2:
64340e3fbdSmrg		/* XXX depth 16 */
65340e3fbdSmrg		packfg = ((fg & 0x00f80000) >> 19) | ((fg & 0x0000fc00) >> 5) |
66340e3fbdSmrg			 ((fg & 0x000000f8) << 8);
67340e3fbdSmrg		packbg = ((bg & 0x00f80000) >> 19) | ((bg & 0x0000fc00) >> 5) |
68340e3fbdSmrg			 ((bg & 0x000000f8) << 8);
69340e3fbdSmrg
70340e3fbdSmrg		outb(vgaCRIndex, 0x45);
71340e3fbdSmrg		inb(vgaCRReg);
72340e3fbdSmrg		outb(vgaCRIndex, 0x4a);
73340e3fbdSmrg		outb(vgaCRReg, packfg);
74340e3fbdSmrg		outb(vgaCRReg, packfg >> 8);
75340e3fbdSmrg
76340e3fbdSmrg		outb(vgaCRIndex, 0x45);
77340e3fbdSmrg		inb(vgaCRReg);
78340e3fbdSmrg		outb(vgaCRIndex, 0x4b);
79340e3fbdSmrg		outb(vgaCRReg, packbg);
80340e3fbdSmrg		outb(vgaCRReg, packbg >> 8);
81340e3fbdSmrg
82340e3fbdSmrg		break;
83340e3fbdSmrg	default:
84340e3fbdSmrg		outb(vgaCRIndex, 0x45);
85340e3fbdSmrg		inb(vgaCRReg);
86340e3fbdSmrg		outb(vgaCRIndex, 0x4a);
87340e3fbdSmrg		outb(vgaCRReg, (fg & 0x00ff0000) >> 16);
88340e3fbdSmrg		outb(vgaCRReg, (fg & 0x0000ff00) >> 8);
89340e3fbdSmrg		outb(vgaCRReg, (fg & 0x000000ff));
90340e3fbdSmrg
91340e3fbdSmrg		outb(vgaCRIndex, 0x45);
92340e3fbdSmrg		inb(vgaCRReg);
93340e3fbdSmrg		outb(vgaCRIndex, 0x4b);
94340e3fbdSmrg		outb(vgaCRReg, (bg & 0x00ff0000) >> 16);
95340e3fbdSmrg		outb(vgaCRReg, (bg & 0x0000ff00) >> 8);
96340e3fbdSmrg		outb(vgaCRReg, (bg & 0x000000ff));
97340e3fbdSmrg
98340e3fbdSmrg		break;
99340e3fbdSmrg	}
100340e3fbdSmrg}
101340e3fbdSmrg
102340e3fbdSmrg
103340e3fbdSmrgstatic void S3SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
104340e3fbdSmrg{
105340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
106340e3fbdSmrg	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
107340e3fbdSmrg
108340e3fbdSmrg	outb(vgaCRIndex, 0x39);
109340e3fbdSmrg	outb(vgaCRReg, 0xa5);
110340e3fbdSmrg
111340e3fbdSmrg	outb(vgaCRIndex, 0x46);
112340e3fbdSmrg	outb(vgaCRReg, x >> 8);
113340e3fbdSmrg	outb(vgaCRIndex, 0x47);
114340e3fbdSmrg	outb(vgaCRReg, x);
115340e3fbdSmrg
116340e3fbdSmrg	outb(vgaCRIndex, 0x49);
117340e3fbdSmrg	outb(vgaCRReg, y);
118340e3fbdSmrg	outb(vgaCRIndex, 0x48);
119340e3fbdSmrg	outb(vgaCRReg, y >> 8);
120340e3fbdSmrg}
121340e3fbdSmrg
122340e3fbdSmrg
123340e3fbdSmrgstatic void S3HideCursor(ScrnInfoPtr pScrn)
124340e3fbdSmrg{
125340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
126340e3fbdSmrg	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
127340e3fbdSmrg	unsigned char tmp;
128340e3fbdSmrg
129340e3fbdSmrg	outb(vgaCRIndex, 0x45);
130340e3fbdSmrg	tmp = inb(vgaCRReg);
131340e3fbdSmrg	outb(vgaCRReg, tmp & ~0x01);
132340e3fbdSmrg}
133340e3fbdSmrg
134340e3fbdSmrg
135340e3fbdSmrgstatic void S3ShowCursor(ScrnInfoPtr pScrn)
136340e3fbdSmrg{
137340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
138340e3fbdSmrg	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
139340e3fbdSmrg	unsigned char tmp;
140340e3fbdSmrg
141340e3fbdSmrg	outb(vgaCRIndex, 0x39);
142340e3fbdSmrg	outb(vgaCRReg, 0xa5);
143340e3fbdSmrg
144340e3fbdSmrg	outb(vgaCRIndex, 0x55);
145340e3fbdSmrg	tmp = inb(vgaCRReg);
146340e3fbdSmrg	outb(vgaCRReg, tmp | 0x10);
147340e3fbdSmrg
148340e3fbdSmrg	outb(vgaCRIndex, 0x4c);
149340e3fbdSmrg	outb(vgaCRReg, pS3->FBCursorOffset >> 8);
150340e3fbdSmrg	outb(vgaCRIndex, 0x4d);
151340e3fbdSmrg	outb(vgaCRReg, pS3->FBCursorOffset);
152340e3fbdSmrg
153340e3fbdSmrg	outb(vgaCRIndex, 0x45);
154340e3fbdSmrg	tmp = inb(vgaCRReg);
155340e3fbdSmrg	outb(vgaCRReg, tmp | 0x01);
156340e3fbdSmrg}
157340e3fbdSmrg
158340e3fbdSmrg
159340e3fbdSmrgstatic void S3LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
160340e3fbdSmrg{
161340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
162340e3fbdSmrg	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
163340e3fbdSmrg	unsigned char cr45;
164340e3fbdSmrg
165340e3fbdSmrg	outb(vgaCRIndex, 0x39);
166340e3fbdSmrg	outb(vgaCRReg, 0xa5);
167340e3fbdSmrg
168340e3fbdSmrg	WaitIdle();
169340e3fbdSmrg
170340e3fbdSmrg	VerticalRetraceWait();
171340e3fbdSmrg
172340e3fbdSmrg	outb(vgaCRIndex, 0x45);
173340e3fbdSmrg	cr45 = inb(vgaCRReg);
174340e3fbdSmrg	outb(vgaCRReg, cr45 & 0xfe);
175340e3fbdSmrg
176340e3fbdSmrg	outb(vgaCRIndex, 0x46);
177340e3fbdSmrg	outb(vgaCRReg, 0xff);
178340e3fbdSmrg	outb(vgaCRIndex, 0x47);
179340e3fbdSmrg	outb(vgaCRReg, 0x7f);
180340e3fbdSmrg	outb(vgaCRIndex, 0x49);
181340e3fbdSmrg	outb(vgaCRReg, 0xff);
182340e3fbdSmrg	outb(vgaCRIndex, 0x4e);
183340e3fbdSmrg	outb(vgaCRReg, 0x3f);
184340e3fbdSmrg	outb(vgaCRIndex, 0x4f);
185340e3fbdSmrg	outb(vgaCRReg, 0x3f);
186340e3fbdSmrg	outb(vgaCRIndex, 0x48);
187340e3fbdSmrg	outb(vgaCRReg, 0x7f);
188340e3fbdSmrg
189340e3fbdSmrg	memcpy(pS3->FBBase + (pS3->FBCursorOffset * 1024), image, 1024);
190340e3fbdSmrg
191340e3fbdSmrg	VerticalRetraceWait();
192340e3fbdSmrg
193340e3fbdSmrg	outb(vgaCRIndex, 0x45);
194340e3fbdSmrg	outb(vgaCRReg, cr45);
195340e3fbdSmrg}
196340e3fbdSmrg
197340e3fbdSmrg
198340e3fbdSmrgstatic Bool S3UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
199340e3fbdSmrg{
200b27e1915Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
201340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
202340e3fbdSmrg	return (pS3->hwCursor);
203340e3fbdSmrg}
204340e3fbdSmrg
205340e3fbdSmrg
206340e3fbdSmrgBool S3_CursorInit(ScreenPtr pScreen)
207340e3fbdSmrg{
208b27e1915Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
209340e3fbdSmrg	S3Ptr pS3 = S3PTR(pScrn);
210340e3fbdSmrg	xf86CursorInfoPtr pCurs;
211340e3fbdSmrg
212340e3fbdSmrg	if (!(pCurs = pS3->pCurs = xf86CreateCursorInfoRec()))
213340e3fbdSmrg		return FALSE;
214340e3fbdSmrg
215340e3fbdSmrg	pCurs->MaxWidth = 64;
216340e3fbdSmrg	pCurs->MaxHeight = 64;
217340e3fbdSmrg	pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
218340e3fbdSmrg		       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
219340e3fbdSmrg		       HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
220340e3fbdSmrg
221340e3fbdSmrg	pCurs->SetCursorColors = S3SetCursorColors;
222340e3fbdSmrg	pCurs->SetCursorPosition = S3SetCursorPosition;
223340e3fbdSmrg	pCurs->LoadCursorImage = S3LoadCursorImage;
224340e3fbdSmrg	pCurs->HideCursor = S3HideCursor;
225340e3fbdSmrg	pCurs->ShowCursor = S3ShowCursor;
226340e3fbdSmrg	pCurs->UseHWCursor = S3UseHWCursor;
227340e3fbdSmrg
228340e3fbdSmrg	return xf86InitCursor(pScreen, pCurs);
229340e3fbdSmrg}
230340e3fbdSmrg
231