2
* Copyright 2001 Ani Joshi <ajoshi@unixbox.com>
4
* XFree86 4.x driver for S3 chipsets
7
* Permission to use, copy, modify, distribute, and sell this software and its
8
* documentation for any purpose is hereby granted without fee, provided that
9
* the above copyright notice appear in all copies and that both that copyright
10
* notice and this permission notice appear in supporting documentation and
11
* that the name of Ani Joshi not be used in advertising or
12
* publicity pertaining to distribution of the software without specific,
13
* written prior permission. Ani Joshi makes no representations
14
* about the suitability of this software for any purpose. It is provided
15
* "as-is" without express or implied warranty.
17
* ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19
* EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23
* PERFORMANCE OF THIS SOFTWARE.
27
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Ti.c,v 1.5 2003/02/17 16:45:24 dawes Exp $ */
30
#include "xf86_OSproc.h"
31
#include "xf86_ansic.h"
40
#define TI_WRITE_ADDR 0x3C8 /* CR55 low bit == 0 */
41
#define TI_RAMDAC_DATA 0x3C9 /* CR55 low bit == 0 */
42
#define TI_PIXEL_MASK 0x3C6 /* CR55 low bit == 0 */
43
#define TI_READ_ADDR 0x3C7 /* CR55 low bit == 0 */
44
#define TI_INDEX_REG 0x3C6 /* CR55 low bit == 1 */
45
#define TI_DATA_REG 0x3C7 /* CR55 low bit == 1 */
47
#define TIDAC_output_clock_select 0x1b
48
#define TIDAC_auxiliary_ctrl 0x29
49
#define TIDAC_general_io_ctrl 0x2a
50
#define TIDAC_general_io_data 0x2b
51
#define TIDAC_cursor_color_0_red 0x23
52
#define TIDAC_cursor_color_0_green 0x24
53
#define TIDAC_cursor_color_0_blue 0x25
54
#define TIDAC_cursor_color_1_red 0x26
55
#define TIDAC_cursor_color_1_green 0x27
56
#define TIDAC_cursor_color_1_blue 0x28
57
#define TIDAC_cursor_x_low 0x00
58
#define TIDAC_cursor_x_high 0x01
59
#define TIDAC_cursor_y_low 0x02
60
#define TIDAC_cursor_y_high 0x03
61
#define TIDAC_cursor_ram_addr_low 0x08
62
#define TIDAC_cursor_ram_addr_high 0x09
63
#define TIDAC_cursor_ram_data 0x0a
66
#define TI_REF_FREQ 14.31818 /* 3025 only */
69
#define FREQ_MIN 12000
70
#define FREQ_MAX 220000
74
void S3OutTiIndReg(ScrnInfoPtr pScrn, CARD32 reg, unsigned char mask,
77
S3Ptr pS3 = S3PTR(pScrn);
78
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
79
unsigned char tmp, tmp1, tmp2 = 0x00;
81
outb(vgaCRIndex, 0x55);
82
tmp = inb(vgaCRReg) & 0xfc;
83
outb(vgaCRReg, tmp | 0x01);
84
tmp1 = inb(TI_INDEX_REG);
85
outb(TI_INDEX_REG, reg);
88
tmp2 = inb(TI_DATA_REG) & mask;
89
outb(TI_DATA_REG, tmp2 | data);
91
outb(TI_INDEX_REG, tmp1);
96
static unsigned char S3InTiIndReg(ScrnInfoPtr pScrn, CARD32 reg)
98
S3Ptr pS3 = S3PTR(pScrn);
99
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
100
unsigned char tmp, tmp1, ret;
102
outb(vgaCRIndex, 0x55);
103
tmp = inb(vgaCRReg) & 0xfc;
104
outb(vgaCRReg, tmp | 0x01);
105
tmp1 = inb(TI_INDEX_REG);
106
outb(TI_INDEX_REG, reg);
108
ret = inb(TI_DATA_REG);
110
outb(TI_INDEX_REG, tmp1);
117
Bool S3TiDACProbe(ScrnInfoPtr pScrn)
119
S3Ptr pS3 = S3PTR(pScrn);
121
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
122
unsigned char cr55, cr45, cr43, cr5c;
123
unsigned char TIndx, TIndx2, TIdata;
125
if (!S3_964_SERIES())
128
outb(vgaCRIndex, 0x43);
129
cr43 = inb(vgaCRReg);
130
outb(vgaCRReg, cr43 & ~0x02);
132
outb(vgaCRIndex, 0x45);
133
cr45 = inb(vgaCRReg);
135
outb(vgaCRIndex, 0x55);
136
cr55 = inb(vgaCRReg);
137
outb(vgaCRReg, (cr55 & 0xfc) | 0x01);
139
TIndx = inb(TI_INDEX_REG);
140
outb(TI_INDEX_REG, TIDAC_id);
141
if(inb(TI_DATA_REG) == 0x20) {
142
found = TI3020_RAMDAC;
146
outb(vgaCRIndex, 0x5c);
147
cr5c = inb(vgaCRReg);
148
outb(vgaCRReg, cr5c & 0xdf);
149
TIndx2 = inb(TI_INDEX_REG);
150
outb(TI_INDEX_REG, TIDAC_ind_curs_ctrl);
151
TIdata = inb(TI_DATA_REG);
152
outb(TI_DATA_REG, TIdata & 0x7f);
154
outb(TI_INDEX_REG, TIDAC_id);
155
if (inb(TI_DATA_REG) == 0x25) {
156
found = TI3025_RAMDAC;
161
outb(TI_INDEX_REG, TIDAC_ind_curs_ctrl);
162
outb(TI_DATA_REG, TIdata);
163
outb(TI_INDEX_REG, TIndx2);
164
outb(vgaCRIndex, 0x5c);
165
outb(vgaCRReg, cr5c);
168
outb(TI_INDEX_REG, TIndx);
169
outb(vgaCRIndex, 0x55);
170
outb(vgaCRReg, cr55);
172
outb(vgaCRIndex, 0x45);
173
outb(vgaCRReg, cr45);
175
outb(vgaCRIndex, 0x43);
176
outb(vgaCRReg, cr43);
179
RamDacInit(pScrn, pS3->RamDacRec);
180
pS3->RamDac = RamDacHelperCreateInfoRec();
181
pS3->RamDac->RamDacType = found;
189
void S3TiDAC_Save(ScrnInfoPtr pScrn)
191
S3Ptr pS3 = S3PTR(pScrn);
192
S3RegPtr save = &pS3->SavedRegs;
193
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
195
if (pS3->RamDac->RamDacType == TI3025_RAMDAC) {
198
outb(vgaCRIndex, 0x5c);
199
cr5c = inb(vgaCRReg);
200
outb(vgaCRReg, cr5c & 0xdf);
202
save->dacregs[TIDAC_ind_curs_ctrl] =
203
S3InTiIndReg(pScrn, TIDAC_ind_curs_ctrl);
204
S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, 0x7f, 0x00);
207
save->dacregs[TIDAC_true_color_ctrl] =
208
S3InTiIndReg(pScrn, TIDAC_true_color_ctrl);
209
save->dacregs[TIDAC_multiplex_ctrl] =
210
S3InTiIndReg(pScrn, TIDAC_multiplex_ctrl);
211
save->dacregs[TIDAC_clock_select] =
212
S3InTiIndReg(pScrn, TIDAC_clock_select);
213
save->dacregs[TIDAC_output_clock_select] =
214
S3InTiIndReg(pScrn, TIDAC_output_clock_select);
215
save->dacregs[TIDAC_general_ctrl] =
216
S3InTiIndReg(pScrn, TIDAC_general_ctrl);
217
save->dacregs[TIDAC_auxiliary_ctrl] =
218
S3InTiIndReg(pScrn, TIDAC_auxiliary_ctrl);
219
S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x1f);
220
save->dacregs[TIDAC_general_io_data] =
221
S3InTiIndReg(pScrn, TIDAC_general_io_data);
223
if (pS3->RamDac->RamDacType == TI3025_RAMDAC) {
224
save->dacregs[0x0e] = S3InTiIndReg(pScrn, 0x0e);
225
save->dacregs[TIDAC_misc_ctrl] =
226
S3InTiIndReg(pScrn, TIDAC_misc_ctrl);
227
S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x00);
228
save->dacregs[0x40] = S3InTiIndReg(pScrn, TIDAC_pll_pixel_data);
229
S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
230
save->dacregs[0x40]);
231
save->dacregs[0x41] = S3InTiIndReg(pScrn, TIDAC_pll_pixel_data);
232
S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
233
save->dacregs[0x41]);
234
save->dacregs[0x42] = S3InTiIndReg(pScrn, TIDAC_pll_pixel_data);
235
S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
236
save->dacregs[0x42]);
237
save->dacregs[0x43] = S3InTiIndReg(pScrn, TIDAC_pll_memory_data);
238
S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
239
save->dacregs[0x43]);
240
save->dacregs[0x44] = S3InTiIndReg(pScrn, TIDAC_pll_memory_data);
241
S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
242
save->dacregs[0x44]);
243
save->dacregs[0x45] = S3InTiIndReg(pScrn, TIDAC_pll_memory_data);
244
S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
245
save->dacregs[0x45]);
246
save->dacregs[0x46] = S3InTiIndReg(pScrn, TIDAC_pll_loop_data);
247
S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
248
save->dacregs[0x46]);
249
save->dacregs[0x47] = S3InTiIndReg(pScrn, TIDAC_pll_loop_data);
250
S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
251
save->dacregs[0x47]);
252
save->dacregs[0x48] = S3InTiIndReg(pScrn, TIDAC_pll_loop_data);
253
S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
254
save->dacregs[0x48]);
259
void S3TiDAC_Restore(ScrnInfoPtr pScrn)
261
S3Ptr pS3 = S3PTR(pScrn);
262
S3RegPtr restore = &pS3->SavedRegs;
264
S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00,
265
restore->dacregs[TIDAC_true_color_ctrl]);
266
S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00,
267
restore->dacregs[TIDAC_multiplex_ctrl]);
268
S3OutTiIndReg(pScrn, TIDAC_clock_select, 0x00,
269
restore->dacregs[TIDAC_clock_select]);
270
S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00,
271
restore->dacregs[TIDAC_output_clock_select]);
272
S3OutTiIndReg(pScrn, TIDAC_general_ctrl, 0x00,
273
restore->dacregs[TIDAC_general_ctrl]);
274
S3OutTiIndReg(pScrn, TIDAC_auxiliary_ctrl, 0x00,
275
restore->dacregs[TIDAC_auxiliary_ctrl]);
276
S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x1f);
277
S3OutTiIndReg(pScrn, TIDAC_general_io_data, 0x00,
278
restore->dacregs[TIDAC_general_io_data]);
279
if (pS3->RamDac->RamDacType == TI3025_RAMDAC) {
280
S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00,
281
restore->dacregs[TIDAC_pll_addr]);
282
S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
283
restore->dacregs[0x40]);
284
S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
285
restore->dacregs[0x41]);
286
S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
287
restore->dacregs[0x42]);
289
S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
290
restore->dacregs[0x43]);
291
S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
292
restore->dacregs[0x44]);
293
S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
294
restore->dacregs[0x45] | 0x80);
296
S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
297
restore->dacregs[0x46]);
298
S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
299
restore->dacregs[0x47]);
300
S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
301
restore->dacregs[0x48]);
303
S3OutTiIndReg(pScrn, 0x0e, 0x00, restore->dacregs[0x0e]);
304
S3OutTiIndReg(pScrn, TIDAC_misc_ctrl, 0x00,
305
restore->dacregs[TIDAC_misc_ctrl]);
308
S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, 0x00,
309
restore->dacregs[TIDAC_ind_curs_ctrl]);
313
void S3TiDAC_PreInit(ScrnInfoPtr pScrn)
315
S3Ptr pS3 = S3PTR(pScrn);
316
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
317
int mclk, m, n, p, mcc, cr5c;
319
outb(vgaCRIndex, 0x5c);
320
cr5c = inb(vgaCRReg);
321
outb(vgaCRReg, cr5c & 0xdf);
323
S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x00);
324
n = S3InTiIndReg(pScrn, TIDAC_pll_memory_data) & 0x7f;
325
S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x01);
326
m = S3InTiIndReg(pScrn, TIDAC_pll_memory_data) & 0x7f;
327
S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x02);
328
p = S3InTiIndReg(pScrn, TIDAC_pll_memory_data) & 0x03;
329
mcc = S3InTiIndReg(pScrn, TIDAC_clock_ctrl);
331
mcc = (mcc & 0x07) * 2 + 2;
335
mclk = ((1431818 * ((m+2) * 8)) / (n+2) / (1 << p) / mcc + 50) / 100;
337
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MCLK %1.3f MHz\n",
340
outb(vgaCRIndex, 0x5c);
341
outb(vgaCRReg, cr5c);
345
static void S3TiDACCalcNMP(long freq, int *calc_n, int *calc_m, int *calc_p)
349
int best_n=32, best_m=32;
350
double diff, mindiff;
353
ffreq = FREQ_MIN / 1000.0;
354
else if (freq > FREQ_MAX)
355
ffreq = FREQ_MAX / 1000.0;
357
ffreq = freq / 1000.0;
359
for (p=0; p<4 && ffreq<110.0; p++)
361
#if FREQ_MIN < 110000/8
368
ffreq /= TI_REF_FREQ;
372
for (n=1; n<=(int)(TI_REF_FREQ/0.5 - 2); n++) {
373
m = (int)(ffreq * (n+2) / 8.0 + 0.5) - 2;
379
diff = ((m+2) * 8) / (n+2.0) - ffreq;
383
if (diff < mindiff) {
396
static void S3TiDACProgramClock(ScrnInfoPtr pScrn, int clk,
397
unsigned char n, unsigned char m,
400
S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x00);
402
if (clk != TIDAC_pll_memory_data) {
403
S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, n);
404
S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, m);
405
S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, p | 0x08);
407
S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, 0x01);
408
S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, 0x01);
409
S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, p > 0 ? p : 1);
410
S3OutTiIndReg(pScrn, TIDAC_misc_ctrl, 0x00, 0x80 | 0x40 | 0x04);
412
S3OutTiIndReg(pScrn, TIDAC_clock_select, 0x00, 0x05);
414
S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, n);
415
S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, m);
416
S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, p | 0x80);
421
static void S3TiDACSetClock(ScrnInfoPtr pScrn, long freq, int clk)
425
S3TiDACCalcNMP(freq, &n, &m, &p);
427
S3TiDACProgramClock(pScrn, clk, n, m, p);
432
void S3TiDAC_Init(ScrnInfoPtr pScrn, DisplayModePtr mode)
434
S3Ptr pS3 = S3PTR(pScrn);
435
vgaHWPtr hwp = VGAHWPTR(pScrn);
436
vgaRegPtr pVga = &hwp->ModeReg;
437
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
438
unsigned char tmp, tmp1, tmp2;
440
S3TiDACSetClock(pScrn, mode->Clock, 2);
441
outb(vgaCRIndex, 0x42);
442
tmp = inb(vgaCRReg) & 0xf0;
443
outb(vgaCRReg, tmp | 0x02);
448
outb(0x3c5, tmp2 | 0x20); /* blank */
450
tmp = pVga->MiscOutReg;
451
pVga->MiscOutReg |= 0xc0;
458
S3OutTiIndReg(pScrn, TIDAC_general_ctrl, 0x00, tmp1);
459
S3OutTiIndReg(pScrn, 0x0e, 0x00, 0x00);
461
/* XXX do 3020 input_clock_sel */
463
outb(vgaCRIndex, 0x65);
465
outb(vgaCRReg, 0x00);
468
outb(vgaCRIndex, 0x40);
469
outb(vgaCRReg, 0x11);
470
outb(vgaCRIndex, 0x55);
471
outb(vgaCRReg, 0x00);
473
if (pScrn->bitsPerPixel > 8)
474
S3OutTiIndReg(pScrn, TIDAC_auxiliary_ctrl, 0x00, 0x00);
476
S3OutTiIndReg(pScrn, TIDAC_auxiliary_ctrl, 0x00, 0x01);
478
switch (pScrn->depth) {
480
S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00,
482
outb(vgaCRIndex, 0x66);
484
if (mode->Clock > 80000)
485
outb(vgaCRReg, (tmp & 0xf8) | 0x02);
487
outb(vgaCRReg, (tmp & 0xf8) | 0x03);
490
S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00,
492
outb(vgaCRIndex, 0x66);
494
if (mode->Clock > 80000)
495
outb(vgaCRReg, (tmp & 0xf8) | 0x01);
497
outb(vgaCRReg, (tmp & 0xf8) | 0x02);
500
S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00,
501
(0x40 | 0x08 | 0x01));
502
outb(vgaCRIndex, 0x66);
504
if (mode->Clock > 80000)
505
outb(vgaCRReg, (tmp & 0xf8) | 0x00);
507
outb(vgaCRReg, (tmp & 0xf8) | 0x01);
511
outb(vgaCRIndex, 0x58);
513
outb(vgaCRReg, (tmp & 0xbf) | 0x40);
515
switch(pScrn->depth) {
517
S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x80);
518
S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x1c);
521
S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x4c);
522
S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x04);
523
S3OutTiIndReg(pScrn, TIDAC_key_ctrl, 0x00, 0x01);
526
S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x4d);
527
S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x04);
528
S3OutTiIndReg(pScrn, TIDAC_key_ctrl, 0x00, 0x01);
531
S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x4e);
532
S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x04);
533
S3OutTiIndReg(pScrn, TIDAC_key_ctrl, 0x00, 0x01);
537
S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x1f);
538
S3OutTiIndReg(pScrn, TIDAC_general_io_data, 0x00, 0x01);
539
S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x00);
540
S3OutTiIndReg(pScrn, TIDAC_misc_ctrl, 0xf0, (0x04 | 0x08));
542
outb(vgaCRIndex, 0x6d);
544
if (mode->Clock > 80000)
545
outb(vgaCRReg, 0x02);
547
outb(vgaCRReg, 0x03);
548
else if (pS3->s3Bpp == 2)
549
if (mode->Clock > 80000)
550
outb(vgaCRReg, 0x00);
552
outb(vgaCRReg, 0x01);
554
outb(vgaCRReg, 0x00);
556
S3OutTiIndReg(pScrn, TIDAC_sense_test, 0x00, 0x00);
564
for(j=0; j<768; j++) {
572
outb(0x3c5, tmp2); /* unblank */
576
void S3TiLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, LOCO *colors,
584
for (i=0; i<768; i++) {
596
/* hardware cursor */
598
static void S3TiSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
600
S3Ptr pS3 = S3PTR(pScrn);
601
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
603
/* unlock sys regs */
604
outb(vgaCRIndex, 0x39);
605
outb(vgaCRReg, 0xa5);
607
S3OutTiIndReg(pScrn, TIDAC_cursor_color_0_red, 0x00,
608
(bg & 0x00FF0000) >> 16);
609
S3OutTiIndReg(pScrn, TIDAC_cursor_color_0_green, 0x00,
610
(bg & 0x0000FF00) >> 8);
611
S3OutTiIndReg(pScrn, TIDAC_cursor_color_0_blue, 0x00,
614
S3OutTiIndReg(pScrn, TIDAC_cursor_color_1_red, 0x00,
615
(fg & 0x00FF0000) >> 16);
616
S3OutTiIndReg(pScrn, TIDAC_cursor_color_1_green, 0x00,
617
(fg & 0x0000FF00) >> 8);
618
S3OutTiIndReg(pScrn, TIDAC_cursor_color_1_blue, 0x00,
624
static void S3TiSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
626
S3Ptr pS3 = S3PTR(pScrn);
627
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
629
/* unlock sys regs */
630
outb(vgaCRIndex, 0x39);
631
outb(vgaCRReg, 0xa5);
633
S3OutTiIndReg(pScrn, TIDAC_cursor_x_low, 0x00, x & 0xff);
634
S3OutTiIndReg(pScrn, TIDAC_cursor_x_high, 0x00, (x >> 8) & 0x0f);
635
S3OutTiIndReg(pScrn, TIDAC_cursor_y_low, 0x00, y & 0xff);
636
S3OutTiIndReg(pScrn, TIDAC_cursor_y_high, 0x00, (y >> 8) & 0x0f);
640
static void S3TiHideCursor(ScrnInfoPtr pScrn)
642
S3Ptr pS3 = S3PTR(pScrn);
643
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
645
/* unlock sys regs */
646
outb(vgaCRIndex, 0x39);
647
outb(vgaCRReg, 0xa5);
649
S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, (unsigned char)
650
~(0x40 | 0x10), 0x00);
654
static void S3TiShowCursor(ScrnInfoPtr pScrn)
656
S3Ptr pS3 = S3PTR(pScrn);
657
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
660
/* unlock sys regs */
661
outb(vgaCRIndex, 0x39);
662
outb(vgaCRReg, 0xa5);
664
outb(vgaCRIndex, 0x55);
665
tmp = inb(vgaCRReg) & 0xdf;
666
outb(vgaCRReg, tmp | 0x20);
668
outb(vgaCRIndex, 0x45);
669
tmp = inb(vgaCRReg) & 0xdf;
670
outb(vgaCRReg, tmp | 0x20);
672
S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, (unsigned char)
673
~(0x40 | 0x10), (0x40 | 0x10));
677
static void S3TiLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
679
S3Ptr pS3 = S3PTR(pScrn);
680
int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
681
unsigned char tmp, tmp1;
684
register unsigned char *mask = image + 1;
687
/* unlock sys regs */
688
outb(vgaCRIndex, 0x39);
689
outb(vgaCRReg, 0xa5);
691
outb(vgaCRIndex, 0x55);
692
tmp = inb(vgaCRReg) & 0xfc;
693
outb(vgaCRReg, tmp | 0x01);
694
tmp1 = inb(TI_INDEX_REG);
696
outb(TI_INDEX_REG, TIDAC_cursor_ram_addr_low);
697
outb(TI_DATA_REG, 0x00);
698
outb(TI_INDEX_REG, TIDAC_cursor_ram_addr_high);
699
outb(TI_DATA_REG, 0x00);
700
outb(TI_INDEX_REG, TIDAC_cursor_ram_data);
703
for (i=0; i<512; i++, mask+=2)
704
outb(TI_DATA_REG, *mask);
705
for (i=0; i<512; i++, image+=2)
706
outb(TI_DATA_REG, *image);
708
for (i=0; i<1024; i++) {
709
outb(TI_DATA_REG, *image);
714
outb(TI_INDEX_REG, tmp1);
716
outb(vgaCRIndex, 0x55);
722
static Bool S3TiUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
729
Bool S3Ti_CursorInit(ScreenPtr pScreen)
731
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
732
S3Ptr pS3 = S3PTR(pScrn);
733
xf86CursorInfoPtr pCurs;
735
if (!(pCurs = pS3->pCurs = xf86CreateCursorInfoRec()))
738
pCurs->MaxWidth = 64;
739
pCurs->MaxHeight = 64;
740
pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
741
HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
742
HARDWARE_CURSOR_NIBBLE_SWAPPED |
743
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
745
pCurs->SetCursorColors = S3TiSetCursorColors;
746
pCurs->SetCursorPosition = S3TiSetCursorPosition;
747
pCurs->LoadCursorImage = S3TiLoadCursorImage;
748
pCurs->HideCursor = S3TiHideCursor;
749
pCurs->ShowCursor = S3TiShowCursor;
750
pCurs->UseHWCursor = S3TiUseHWCursor;
752
return xf86InitCursor(pScreen, pCurs);