Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
169 | giacomo | 1 | /* |
2 | * VGAlib version 1.2 - (c) 1993 Tommy Frandsen |
||
3 | * |
||
4 | * This library is free software; you can redistribute it and/or |
||
5 | * modify it without any restrictions. This library is distributed |
||
6 | * in the hope that it will be useful, but without any warranty. |
||
7 | * |
||
8 | * Multi-chipset support Copyright (C) 1993 Harm Hanemaayer |
||
9 | * S3 805,868 support Copyright (C) 1995 Stephen Lee |
||
10 | */ |
||
11 | |||
12 | /* |
||
13 | * Mar 1999 (Eduardo ...) |
||
14 | * Recognizes Trio3D as Trio64 |
||
15 | * |
||
16 | * Sep 1997 (Greg Alexander): |
||
17 | * Recognizes S3Trio64V2/DX cards as Trio64's. |
||
18 | * |
||
19 | * Feb 1996 (Stephen Lee): |
||
20 | * 968/IBMRGB support. Only 256 colors for now. |
||
21 | * can now save more than 10 DAC registers (IBMRGB has 256!) |
||
22 | * Trio64 patch from Moto Kawamura <kawamura@mmp.cl.nec.co.jp>. |
||
23 | * Changed handling of CR34 for VGA modes at Andreas' suggestion. |
||
24 | * Changes to s3_saveregs() and s3_setregs() to make them more safe against |
||
25 | * lockups. |
||
26 | * 16 color mode should work on the 868/SDAC. |
||
27 | * SDAC 4/8bpp doesn't seem to do pixel multiplexing. |
||
28 | * |
||
29 | * Dec 1995 (Stephen Lee): |
||
30 | * Fixed color problem with 868 (CR43 again!). Could somebody find the |
||
31 | * value that works with Trio64? |
||
32 | * |
||
33 | * Nov 1995 (Stephen Lee): |
||
34 | * Linear addressing mode partially works (but is very alpha). |
||
35 | * Merged in Andreas Arens' <ari@av.rwth-aachen.de> patch for the 928. |
||
36 | * |
||
37 | * Sep 1995 (Stephen Lee): |
||
38 | * 16 Colors works on my 805, should work on other cards too. |
||
39 | * |
||
40 | * Alternate banking scheme for 864+. If you have problems, try undefining |
||
41 | * S3_LINEAR_MODE_BANKING_864. |
||
42 | * |
||
43 | * 8 bit color *really* works. Took me 3 months to bag this sucker. |
||
44 | * |
||
45 | * SVGA 8 bit color modes works. 320x200x256 is not really 'packed-pixel', |
||
46 | * it occupies 256K per page. There is no SVGA 320x200x256 mode; I cannot |
||
47 | * get the display (timing?) right. |
||
48 | * |
||
49 | * Aug 1995 (Stephen Lee): |
||
50 | * Added "Dacspeed" parsing. |
||
51 | * Added support for CLUT8_8 on ATT20C490/498. |
||
52 | * Improved support for S3-801/805. |
||
53 | * 15/16/24 bit colors works on the 805 + ATT20C490 I tested. |
||
54 | * Newer chipsets are recognized (but no support coded in yet). |
||
55 | * Should recognize memory size correctly on S3-924. |
||
56 | * |
||
57 | * Dec 1994 (Harm Hanemaayer): |
||
58 | * Partially rewritten using new SVGA-abstracted interface. |
||
59 | * Based on XFree86 code (accel/s3/s3.c and s3init.c). |
||
60 | * Goal is to have support for the S3-864 + S3-SDAC (which I can test). |
||
61 | * 80x with GENDAC might also be supported. |
||
62 | * Also, 640x480x256 should work on cards that have standard 25 and 28 MHz |
||
63 | * clocks. |
||
64 | * |
||
65 | * XFree86-equivalent clock select is now supported plus some |
||
66 | * industry-standard RAMDACs. |
||
67 | * |
||
68 | * Remaining problems: |
||
69 | * * Okay, okay, so 256 color still isn't fully working on the 805. I'm |
||
70 | * trying to get a fix for it. |
||
71 | * |
||
72 | * * The DCLK limit for 864/868 is a bit too relaxed. If you see noise at |
||
73 | * the highest resolutions when the screen is drawing it is possibly due |
||
74 | * to this. (How about changing MCLK?) |
||
75 | * |
||
76 | * * Horizontal Total is limited to 4088 which makes some modes unavailable |
||
77 | * (e.g. 800x600x16M with HTotal > 1022). Should experiment with |
||
78 | * CR43.7? |
||
79 | * |
||
80 | * * Some 864 problems are now fixed -- XF86_S3 seems to program the |
||
81 | * linewidth in bytes doubled for the S3-864 with > 1024K, which |
||
82 | * caused problems for this driver. There's still interference |
||
83 | * though when writing to video memory in the higher resolutions. |
||
84 | * |
||
85 | * * XXXX results of malloc() are not checked: should fix sometime. |
||
86 | */ |
||
87 | |||
88 | #include <stdlib.h> |
||
89 | #include <stdarg.h> |
||
90 | #include <stdio.h> |
||
91 | #include <string.h> |
||
92 | #include <unistd.h> |
||
93 | #include "vga.h" |
||
94 | #include "libvga.h" |
||
95 | #include "driver.h" |
||
96 | #include "timing.h" |
||
97 | #include "ramdac.h" |
||
98 | #include "clockchip.h" |
||
99 | #include "vgaregs.h" |
||
100 | #include "interface.h" |
||
101 | #include "8514a.h" |
||
102 | #include "vgapci.h" |
||
103 | |||
104 | /* no acceleration as of now. */ |
||
105 | #undef S3_USE_GRAPHIC_ENGINE |
||
106 | |||
107 | /* kludge packed pixel for 320x200x256 */ |
||
108 | /* XXXX doesn't really work */ |
||
109 | #undef S3_KLUDGE_PAGE_MODE |
||
110 | |||
111 | /* use alternate 'linear' banking method for 864+ */ |
||
112 | #undef S3_LINEAR_MODE_BANKING_864 |
||
113 | |||
114 | #ifdef __alpha__ /* no good for alpha's */ |
||
115 | #undef S3_LINEAR_MODE_BANKING_864 |
||
116 | #endif |
||
117 | |||
118 | /* |
||
119 | * supports linear buffer. |
||
120 | * |
||
121 | * XXXX does not work with console switching and might be incompatible with |
||
122 | * S3_LINEAR_MODE_BANKING_864. |
||
123 | */ |
||
124 | #define S3_LINEAR_SUPPORT |
||
125 | |||
126 | /* supports 16 colors */ |
||
127 | #define S3_16_COLORS |
||
128 | |||
129 | /* |
||
130 | * zero wait state + (ramdac?) FIFO for 864 & 805, |
||
131 | * twice as fast but might not work on some cards. |
||
132 | */ |
||
133 | #undef S3_0_WAIT_805_864 |
||
134 | |||
135 | enum { |
||
136 | S3_911, S3_924, S3_801, S3_805, S3_928, S3_864, S3_964, S3_TRIO32, |
||
137 | S3_TRIO64, S3_866, S3_868, S3_968, S3_765 |
||
138 | }; |
||
139 | |||
140 | static const char *s3_chipname[] = |
||
141 | {"911", "924", "801", "805", "928", |
||
142 | "864", "964", "Trio32", "Trio64", "866", "868", "968", "Trio64V+"}; |
||
143 | |||
144 | #define S3_CR(n) (EXT + (0x##n) - 0x30) |
||
145 | |||
146 | #define S3_CR30 S3_CR(30) |
||
147 | #define S3_CR31 S3_CR(31) |
||
148 | #define S3_CR32 S3_CR(32) |
||
149 | #define S3_CR33 S3_CR(33) |
||
150 | #define S3_CR34 S3_CR(34) |
||
151 | #define S3_CR35 S3_CR(35) |
||
152 | #define S3_CR3A S3_CR(3A) |
||
153 | #define S3_CR3B S3_CR(3B) |
||
154 | #define S3_CR3C S3_CR(3C) |
||
155 | #define S3_CR40 S3_CR(40) |
||
156 | #define S3_CR42 S3_CR(42) |
||
157 | #define S3_CR43 S3_CR(43) |
||
158 | #define S3_CR44 S3_CR(44) |
||
159 | #define S3_CR50 S3_CR(50) /* 801+ */ |
||
160 | #define S3_CR51 S3_CR(51) |
||
161 | #define S3_CR53 S3_CR(53) |
||
162 | #define S3_CR54 S3_CR(54) |
||
163 | #define S3_CR55 S3_CR(55) |
||
164 | #define S3_CR58 S3_CR(58) |
||
165 | #define S3_CR59 S3_CR(59) |
||
166 | #define S3_CR5A S3_CR(5A) |
||
167 | #define S3_CR5D S3_CR(5D) |
||
168 | #define S3_CR5E S3_CR(5E) |
||
169 | #define S3_CR60 S3_CR(60) |
||
170 | #define S3_CR61 S3_CR(61) |
||
171 | #define S3_CR62 S3_CR(62) |
||
172 | #define S3_CR67 S3_CR(67) |
||
173 | #define S3_CR6A S3_CR(6A) |
||
174 | #define S3_CR6D S3_CR(6D) |
||
175 | |||
176 | /* For debugging, these (non-)registers are read also (but never written). */ |
||
177 | |||
178 | #define S3_CR36 S3_CR(36) |
||
179 | #define S3_CR37 S3_CR(37) |
||
180 | #define S3_CR38 S3_CR(38) |
||
181 | #define S3_CR39 S3_CR(39) |
||
182 | #define S3_CR3D S3_CR(3D) |
||
183 | #define S3_CR3E S3_CR(3E) |
||
184 | #define S3_CR3F S3_CR(3F) |
||
185 | #define S3_CR45 S3_CR(45) |
||
186 | #define S3_CR46 S3_CR(46) |
||
187 | #define S3_CR47 S3_CR(47) |
||
188 | #define S3_CR48 S3_CR(48) |
||
189 | #define S3_CR49 S3_CR(49) |
||
190 | #define S3_CR4A S3_CR(4A) |
||
191 | #define S3_CR4B S3_CR(4B) |
||
192 | #define S3_CR4C S3_CR(4C) |
||
193 | #define S3_CR4D S3_CR(4D) |
||
194 | #define S3_CR4E S3_CR(4E) |
||
195 | #define S3_CR4F S3_CR(4F) |
||
196 | #define S3_CR52 S3_CR(52) |
||
197 | #define S3_CR56 S3_CR(56) |
||
198 | #define S3_CR57 S3_CR(57) |
||
199 | #define S3_CR5B S3_CR(5B) |
||
200 | #define S3_CR5C S3_CR(5C) |
||
201 | #define S3_CR5F S3_CR(5F) |
||
202 | #define S3_CR63 S3_CR(63) |
||
203 | #define S3_CR64 S3_CR(64) |
||
204 | #define S3_CR65 S3_CR(65) |
||
205 | #define S3_CR66 S3_CR(66) |
||
206 | #define S3_CR6E S3_CR(6E) |
||
207 | #define S3_CR6F S3_CR(6F) |
||
208 | |||
209 | /* Trio extended SR registers */ |
||
210 | |||
211 | #define S3_SR(n) (S3_CR6F + 1 + (0x##n) - 0x08) |
||
212 | |||
213 | #define S3_SR08 S3_SR(08) |
||
214 | #define S3_SR09 S3_SR(09) |
||
215 | #define S3_SR0A S3_SR(0A) |
||
216 | #define S3_SR0D S3_SR(0D) |
||
217 | #define S3_SR10 S3_SR(10) |
||
218 | #define S3_SR11 S3_SR(11) |
||
219 | #define S3_SR12 S3_SR(12) |
||
220 | #define S3_SR13 S3_SR(13) |
||
221 | #define S3_SR15 S3_SR(15) |
||
222 | #define S3_SR18 S3_SR(18) |
||
223 | #define S3_SR1D S3_SR(1D) |
||
224 | |||
225 | #define S3_8514_OFFSET (S3_SR1D + 1) |
||
226 | |||
227 | #define S3_8514_COUNT (1) /* number of 2-byte words */ |
||
228 | |||
229 | #define S3_DAC_OFFSET (S3_8514_OFFSET + (S3_8514_COUNT * 2)) |
||
230 | |||
231 | #define S3_TOTAL_REGS (S3_DAC_OFFSET + MAX_DAC_STATE) |
||
232 | |||
233 | /* 8514 regs */ |
||
234 | #define S3_ADVFUNC_CNTL 0 |
||
235 | |||
236 | static unsigned short s3_8514regs[S3_8514_COUNT] = |
||
237 | { |
||
238 | /* default assuming text mode */ |
||
239 | 0x0000U |
||
240 | }; |
||
241 | |||
242 | /* flags used by this driver */ |
||
243 | #define S3_LOCALBUS 0x01 |
||
244 | #define S3_CLUT8_8 0x02 |
||
245 | #define S3_OLD_STEPPING 0x04 |
||
246 | |||
247 | static int s3_flags = 0; |
||
248 | |||
249 | static int s3_chiptype; |
||
250 | static int s3_memory; |
||
251 | static CardSpecs *cardspecs; |
||
252 | static DacMethods *dac_used; |
||
253 | static ClockChipMethods *clk_used; |
||
254 | static int dac_speed = 0; |
||
255 | |||
256 | int __svgalib_s3_s3Mclk = 0; |
||
257 | |||
258 | /* forward declaration. */ |
||
259 | extern DriverSpecs __svgalib_s3_driverspecs; |
||
260 | |||
261 | static int s3_init(int, int, int); |
||
262 | static void s3_setpage(int page); |
||
263 | #ifdef S3_LINEAR_MODE_BANKING_864 |
||
264 | static void s3_setpage864(int page); |
||
265 | #endif |
||
266 | |||
267 | #ifdef S3_LINEAR_SUPPORT |
||
268 | static int s3_cr40; |
||
269 | static int s3_cr54; |
||
270 | static int s3_cr58; |
||
271 | static int s3_cr59; |
||
272 | static int s3_cr5A; |
||
273 | static int s3_linear_opt = 0; |
||
274 | static int s3_linear_addr = 0; |
||
275 | static int s3_linear_base = 0; |
||
276 | static void s3_linear_enable(void); |
||
277 | static void s3_linear_disable(void); |
||
278 | #endif |
||
279 | |||
280 | static void nothing(void) |
||
281 | { |
||
282 | } |
||
283 | |||
284 | /* |
||
285 | * Lock S3's registers. |
||
286 | * There are more locks, but this should suffice. |
||
287 | * |
||
288 | * ARI: More complete Extended VGA Register Lock Documentation, as of Ferraro: |
||
289 | * |
||
290 | * Register Bit Controls Access To: Function |
||
291 | * CR33 1 CR7 bits 1 and 6 1=disable write protect |
||
292 | * setting of CR11 bit 7 |
||
293 | * CR33 4 Ramdac Register 1=disable writes |
||
294 | * CR33 6 Palette/Overscan Registers 1=lock |
||
295 | * CR34 5 Memory Configuration bit 5 1=lock |
||
296 | * CR34 7 Misc Register bit 3-2 (Clock) 1=lock |
||
297 | * CR35 4 Vertical Timing Registers 1=lock |
||
298 | * CR35 5 Horizontal Timing Registers 1=lock |
||
299 | * |
||
300 | * XXXX mostly, need to lock the enhanced command regs on the 805 (and |
||
301 | * probably below) to avoid display corruption. |
||
302 | */ |
||
303 | static void s3_lock(void) |
||
304 | { |
||
305 | __svgalib_outCR(0x39, 0x00); /* Lock system control regs. */ |
||
306 | __svgalib_outCR(0x38, 0x00); /* Lock special regs. */ |
||
307 | } |
||
308 | |||
309 | static void s3_lock_enh(void) |
||
310 | { |
||
311 | if (s3_chiptype > S3_911) |
||
312 | __svgalib_outCR(0x40, __svgalib_inCR(0x40) & ~0x01); /* Lock enhanced command regs. */ |
||
313 | s3_lock(); |
||
314 | } |
||
315 | |||
316 | /* |
||
317 | * Unlock S3's registers. |
||
318 | * There are more locks, but this should suffice. |
||
319 | */ |
||
320 | static void s3_unlock(void) |
||
321 | { |
||
322 | __svgalib_outCR(0x38, 0x48); /* Unlock special regs. */ |
||
323 | __svgalib_outCR(0x39, 0xA5); /* Unlock system control regs. */ |
||
324 | } |
||
325 | |||
326 | static void s3_unlock_enh(void) |
||
327 | { |
||
328 | s3_unlock(); |
||
329 | if (s3_chiptype > S3_911) |
||
330 | __svgalib_outCR(0x40, __svgalib_inCR(0x40) | 0x01); /* Unlock enhanced command regs. */ |
||
331 | } |
||
332 | |||
333 | /* |
||
334 | * Adjust the display width. This is necessary for the graphics |
||
335 | * engine if acceleration is used. However it will require more |
||
336 | * memory making some modes unavailable. |
||
337 | */ |
||
338 | static int s3_adjlinewidth(int oldwidth) |
||
339 | { |
||
340 | if (s3_chiptype < S3_801) |
||
341 | return 1024; |
||
342 | #ifdef S3_USE_GRAPHIC_ENGINE |
||
343 | if (oldwidth <= 640) |
||
344 | return 640; |
||
345 | if (oldwidth <= 800) |
||
346 | return 800; |
||
347 | if (oldwidth <= 1024) |
||
348 | return 1024; |
||
349 | if (!(s3_flags & S3_OLD_STEPPING)) |
||
350 | if (oldwidth <= 1152) |
||
351 | return 1152; |
||
352 | if (oldwidth <= 1280) |
||
353 | return 1280; |
||
354 | if (oldwidth <= 1600 && s3_chiptype >= S3_864) |
||
355 | return 1600; |
||
356 | |||
357 | return 2048; |
||
358 | #else |
||
359 | return oldwidth; |
||
360 | #endif |
||
361 | } |
||
362 | |||
363 | /* Fill in chipset specific mode information */ |
||
364 | |||
365 | static void s3_getmodeinfo(int mode, vga_modeinfo * modeinfo) |
||
366 | { |
||
367 | switch (modeinfo->colors) { |
||
368 | case 16: /* 4-plane 16 color mode */ |
||
369 | modeinfo->maxpixels = s3_memory * 1024 * 2; |
||
370 | break; |
||
371 | default: |
||
372 | modeinfo->maxpixels = s3_memory * 1024 / |
||
373 | modeinfo->bytesperpixel; |
||
374 | } |
||
375 | |||
376 | /* Adjust line width (only for SVGA modes) */ |
||
377 | if (!IS_IN_STANDARD_VGA_DRIVER(mode)) |
||
378 | modeinfo->linewidth = s3_adjlinewidth(modeinfo->linewidth); |
||
379 | |||
380 | modeinfo->maxlogicalwidth = 8184; |
||
381 | if (s3_chiptype >= S3_801) |
||
382 | modeinfo->startaddressrange = 0x3fffff; |
||
383 | else |
||
384 | modeinfo->startaddressrange = 0xfffff; |
||
385 | |||
386 | #ifdef S3_KLUDGE_PAGE_MODE |
||
387 | if (mode == G320x200x256) { |
||
388 | /* set page size to 256k. */ |
||
389 | modeinfo->startaddressrange /= 4; |
||
390 | modeinfo->maxpixels /= 4; |
||
391 | } |
||
392 | #else |
||
393 | if (mode == G320x200x256) { |
||
394 | /* disable page flipping. */ |
||
395 | /* modeinfo->startaddressrange = 0xffff; */ |
||
396 | modeinfo->startaddressrange = 0; |
||
397 | modeinfo->maxpixels = 65536; |
||
398 | } |
||
399 | #endif |
||
400 | |||
401 | modeinfo->haveblit = 0; |
||
402 | modeinfo->flags &= ~HAVE_RWPAGE; |
||
403 | modeinfo->flags |= HAVE_EXT_SET; |
||
404 | #ifdef S3_LINEAR_SUPPORT |
||
405 | if (modeinfo->bytesperpixel >= 1) { |
||
406 | modeinfo->flags |= CAPABLE_LINEAR; |
||
407 | if (s3_linear_addr) |
||
408 | modeinfo->flags |= IS_LINEAR | LINEAR_MODE; |
||
409 | } |
||
410 | #endif |
||
411 | |||
412 | modeinfo->memory = s3_memory; |
||
413 | modeinfo->chiptype = s3_chiptype; |
||
414 | } |
||
415 | |||
416 | /* |
||
417 | * XXX Part of this function should be implemented in ramdac.c, |
||
418 | * but we just kludge it here for now. |
||
419 | */ |
||
420 | static int s3_ext_set(unsigned what, va_list params) |
||
421 | { |
||
422 | int param2, old_values; |
||
423 | unsigned char regs[10]; |
||
424 | |||
425 | /* only know this, for now */ |
||
426 | if (dac_used->id != ATT20C490 && dac_used->id != ATT20C498 && |
||
427 | dac_used->id != SIERRA_15025) |
||
428 | return 0; |
||
429 | |||
430 | param2 = va_arg(params, int); |
||
431 | old_values = (s3_flags & S3_CLUT8_8) ? VGA_CLUT8 : 0; |
||
432 | |||
433 | switch (what) { |
||
434 | case VGA_EXT_AVAILABLE: |
||
435 | switch (param2) { |
||
436 | case VGA_AVAIL_SET: |
||
437 | return VGA_EXT_AVAILABLE | VGA_EXT_SET | VGA_EXT_CLEAR | VGA_EXT_RESET; |
||
438 | case VGA_AVAIL_ACCEL: |
||
439 | return 0; |
||
440 | case VGA_AVAIL_FLAGS: |
||
441 | return VGA_CLUT8; |
||
442 | } |
||
443 | break; |
||
444 | |||
445 | case VGA_EXT_SET: |
||
446 | if (param2 & VGA_CLUT8) |
||
447 | goto setclut8; |
||
448 | |||
449 | case VGA_EXT_CLEAR: |
||
450 | if (param2 & VGA_CLUT8) |
||
451 | goto clearclut8; |
||
452 | |||
453 | case VGA_EXT_RESET: |
||
454 | if (param2 & VGA_CLUT8) { |
||
455 | setclut8: |
||
456 | dac_used->saveState(regs); |
||
457 | if (regs[0] == 0x00) { /* 8bpp, 6 bits/color */ |
||
458 | s3_flags |= S3_CLUT8_8; |
||
459 | if (dac_used->id == SIERRA_15025) |
||
460 | regs[1] = 1; |
||
461 | regs[0] = 0x02; |
||
462 | } |
||
463 | dac_used->restoreState(regs); |
||
464 | return old_values; |
||
465 | } else { |
||
466 | clearclut8: |
||
467 | dac_used->saveState(regs); |
||
468 | if (regs[0] == 0x02) { /* 8bpp, 8 bits/color */ |
||
469 | s3_flags &= ~S3_CLUT8_8; |
||
470 | if (dac_used->id == SIERRA_15025) |
||
471 | regs[1] = 0; |
||
472 | regs[0] = 0x00; |
||
473 | } |
||
474 | dac_used->restoreState(regs); |
||
475 | return old_values; |
||
476 | } |
||
477 | default: |
||
478 | break; |
||
479 | } |
||
480 | return 0; |
||
481 | } |
||
482 | |||
483 | /* Return non-zero if mode is available */ |
||
484 | |||
485 | static int s3_modeavailable(int mode) |
||
486 | { |
||
487 | struct info *info; |
||
488 | ModeInfo *modeinfo; |
||
489 | ModeTiming *modetiming; |
||
490 | |||
491 | if (IS_IN_STANDARD_VGA_DRIVER(mode)) |
||
492 | return __svgalib_vga_driverspecs.modeavailable(mode); |
||
493 | |||
494 | /* Enough memory? */ |
||
495 | info = &__svgalib_infotable[mode]; |
||
496 | if (s3_memory * 1024 < info->ydim * s3_adjlinewidth(info->xbytes)) |
||
497 | return 0; |
||
498 | |||
499 | modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); |
||
500 | |||
501 | modetiming = malloc(sizeof(ModeTiming)); |
||
502 | if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { |
||
503 | free(modetiming); |
||
504 | free(modeinfo); |
||
505 | return 0; |
||
506 | } |
||
507 | free(modetiming); |
||
508 | free(modeinfo); |
||
509 | |||
510 | return SVGADRV; |
||
511 | } |
||
512 | |||
513 | /* |
||
514 | * save S3 registers. Lock registers receive special treatment |
||
515 | * so dumpreg will work under X. |
||
516 | */ |
||
517 | static int s3_saveregs(unsigned char regs[]) |
||
518 | { |
||
519 | unsigned char b, bmax; |
||
520 | unsigned char cr38, cr39, cr40; |
||
521 | |||
522 | cr38 = __svgalib_inCR(0x38); |
||
523 | __svgalib_outCR(0x38, 0x48); /* unlock S3 VGA regs (CR30-CR3B) */ |
||
524 | |||
525 | cr39 = __svgalib_inCR(0x39); |
||
526 | __svgalib_outCR(0x39, 0xA5); /* unlock S3 system control (CR40-CR4F) */ |
||
527 | /* and extended regs (CR50-CR6D) */ |
||
528 | |||
529 | cr40 = __svgalib_inCR(0x40); /* unlock enhanced regs */ |
||
530 | __svgalib_outCR(0x40, cr40 | 0x01); |
||
531 | |||
532 | /* retrieve values from private copy */ |
||
533 | memcpy(regs + S3_8514_OFFSET, s3_8514regs, S3_8514_COUNT * 2); |
||
534 | |||
535 | /* get S3 VGA/Ext registers */ |
||
536 | bmax = 0x4F; |
||
537 | if (s3_chiptype >= S3_801) |
||
538 | bmax = 0x66; |
||
539 | if (s3_chiptype >= S3_864) |
||
540 | bmax = 0x6D; |
||
541 | for (b = 0x30; b <= bmax; b++) |
||
542 | regs[EXT + b - 0x30] = __svgalib_inCR(b); |
||
543 | |||
544 | /* get S3 ext. SR registers */ |
||
545 | /* if (s3_chiptype >= S3_864) { */ |
||
546 | if (s3_chiptype == S3_TRIO32 || s3_chiptype == S3_TRIO64 |
||
547 | || s3_chiptype == S3_765) {/* SL: actually Trio32/64/V+ */ |
||
548 | regs[S3_SR08] = __svgalib_inSR(0x08); |
||
549 | __svgalib_outSR(0x08, 0x06); /* unlock extended seq regs */ |
||
550 | regs[S3_SR09] = __svgalib_inSR(0x09); |
||
551 | regs[S3_SR0A] = __svgalib_inSR(0x0A); |
||
552 | regs[S3_SR0D] = __svgalib_inSR(0x0D); |
||
553 | regs[S3_SR10] = __svgalib_inSR(0x10); |
||
554 | regs[S3_SR11] = __svgalib_inSR(0x11); |
||
555 | regs[S3_SR12] = __svgalib_inSR(0x12); |
||
556 | regs[S3_SR13] = __svgalib_inSR(0x13); |
||
557 | regs[S3_SR15] = __svgalib_inSR(0x15); |
||
558 | regs[S3_SR18] = __svgalib_inSR(0x18); |
||
559 | __svgalib_outSR(0x08, regs[S3_SR08]); |
||
560 | } |
||
561 | |||
562 | dac_used->saveState(regs + S3_DAC_OFFSET); |
||
563 | |||
564 | /* leave the locks the way we found it */ |
||
565 | __svgalib_outCR(0x40, regs[EXT + 0x40 - 0x30] = cr40); |
||
566 | __svgalib_outCR(0x39, regs[EXT + 0x39 - 0x30] = cr39); |
||
567 | __svgalib_outCR(0x38, regs[EXT + 0x38 - 0x30] = cr38); |
||
568 | #if 0 |
||
569 | #include "ramdac/IBMRGB52x.h" |
||
570 | |||
571 | do { |
||
572 | unsigned char m, n, df; |
||
573 | |||
574 | fprintf(stderr,"pix_fmt = 0x%02X, 8bpp = 0x%02X, 16bpp = 0x%02X, 24bpp = 0x%02X, 32bpp = 0x%02X,\n" |
||
575 | "CR58 = 0x%02X, CR66 = 0x%02X, CR67 = 0x%02X, CR6D = 0x%02X\n", |
||
576 | regs[S3_DAC_OFFSET + IBMRGB_pix_fmt], |
||
577 | regs[S3_DAC_OFFSET + IBMRGB_8bpp], |
||
578 | regs[S3_DAC_OFFSET + IBMRGB_16bpp], |
||
579 | regs[S3_DAC_OFFSET + IBMRGB_24bpp], |
||
580 | regs[S3_DAC_OFFSET + IBMRGB_32bpp], |
||
581 | regs[S3_CR58], |
||
582 | regs[S3_CR66], |
||
583 | regs[S3_CR67], |
||
584 | regs[S3_CR6D]); |
||
585 | |||
586 | m = regs[S3_DAC_OFFSET + IBMRGB_m0 + 4]; |
||
587 | n = regs[S3_DAC_OFFSET + IBMRGB_n0 + 4]; |
||
588 | df = m >> 6; |
||
589 | m &= ~0xC0; |
||
590 | |||
591 | fprintf(stderr,"m = 0x%02X %d, n = 0x%02X %d, df = 0x%02X %d, freq = %.3f\n", |
||
592 | m, m, n, n, df, df, ((m + 65.0) / n) / (8 >> df) * 16.0); |
||
593 | } while (0); |
||
594 | #endif |
||
595 | return S3_DAC_OFFSET - VGA_TOTAL_REGS + dac_used->stateSize; |
||
596 | } |
||
597 | |||
598 | /* Set chipset-specific registers */ |
||
599 | static void s3_setregs(const unsigned char regs[], int mode) |
||
600 | { |
||
601 | unsigned char b, bmax; |
||
602 | /* |
||
603 | * Right now, anything != 0x00 gets written in s3_setregs. |
||
604 | * May change this into a bitmask later. |
||
605 | */ |
||
606 | static unsigned char s3_regmask[] = |
||
607 | { |
||
608 | 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x00, 0x00, /* CR30-CR37 */ |
||
609 | 0x00, 0x00, 0x3A, 0x3B, 0x3C, 0x00, 0x00, 0x00, /* CR38-CR3F */ |
||
610 | 0x00, 0x00, 0x42, 0x43, 0x44, 0x00, 0x00, 0x00, /* CR40-CR47 */ |
||
611 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CR48-CR4F */ |
||
612 | 0x50, 0x51, 0x00, 0x00, 0x54, 0x55, 0x00, 0x00, /* CR50-CR57 */ |
||
613 | 0x58, 0x59, 0x5A, 0x00, 0x00, 0x5D, 0x5E, 0x00, /* CR58-CR5F */ |
||
614 | 0x60, 0x61, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, /* CR60-CR67 */ |
||
615 | 0x00, 0x00, 0x6A, 0x00, 0x00, 0x00 /* CR68-CR6D */ |
||
616 | }; |
||
617 | |||
618 | s3_unlock_enh(); |
||
619 | |||
620 | /* save a private copy */ |
||
621 | memcpy(s3_8514regs, regs + S3_8514_OFFSET, S3_8514_COUNT * 2); |
||
622 | /* |
||
623 | * set this first, so if we segfault on this |
||
624 | * we don't get a screwed up display |
||
625 | */ |
||
626 | outw(ADVFUNC_CNTL, s3_8514regs[S3_ADVFUNC_CNTL]); |
||
627 | |||
628 | /* get S3 VGA/Ext registers */ |
||
629 | bmax = 0x4F; |
||
630 | if (s3_chiptype >= S3_801) |
||
631 | bmax = 0x66; |
||
632 | if (s3_chiptype >= S3_864) |
||
633 | bmax = 0x6D; |
||
634 | for (b = 0x30; b <= bmax; b++) { |
||
635 | if (s3_regmask[b - 0x30]) |
||
636 | __svgalib_outCR(b, regs[EXT + b - 0x30]); |
||
637 | } |
||
638 | |||
639 | if (dac_used->id != NORMAL_DAC) { |
||
640 | unsigned char CR1; |
||
641 | /* Blank the screen. */ |
||
642 | CR1 = __svgalib_inCR(0x01); |
||
643 | __svgalib_outCR(0x01, CR1 | 0x20); |
||
644 | |||
645 | __svgalib_outcrtc(0x55, __svgalib_inCR(0x55) | 1); |
||
646 | __svgalib_outcrtc(0x66, regs[S3_CR66]); |
||
647 | __svgalib_outcrtc(0x67, regs[S3_CR67]); /* S3 pixmux. */ |
||
648 | |||
649 | dac_used->restoreState(regs + S3_DAC_OFFSET); |
||
650 | |||
651 | __svgalib_outcrtc(0x6D, regs[S3_CR6D]); |
||
652 | __svgalib_outcrtc(0x55, __svgalib_inCR(0x55) & ~1); |
||
653 | |||
654 | __svgalib_outcrtc(0x01, CR1); /* Unblank screen. */ |
||
655 | } |
||
656 | #ifdef S3_LINEAR_SUPPORT |
||
657 | if (mode == TEXT && s3_linear_addr) |
||
658 | s3_linear_disable(); /* make sure linear is off */ |
||
659 | #endif |
||
660 | |||
661 | /* restore CR38/39 (may lock other regs) */ |
||
662 | if (mode == TEXT) { |
||
663 | /* restore lock registers as well */ |
||
664 | __svgalib_outCR(0x40, regs[S3_CR40]); |
||
665 | __svgalib_outCR(0x39, regs[S3_CR39]); |
||
666 | __svgalib_outCR(0x38, regs[S3_CR38]); |
||
667 | } else |
||
668 | s3_lock_enh(); |
||
669 | } |
||
670 | |||
671 | /* |
||
672 | * Initialize register state for a mode. |
||
673 | */ |
||
674 | |||
675 | static void s3_initializemode(unsigned char *moderegs, |
||
676 | ModeTiming * modetiming, ModeInfo * modeinfo) |
||
677 | { |
||
678 | /* Get current values. */ |
||
679 | s3_saveregs(moderegs); |
||
680 | |||
681 | /* Set up the standard VGA registers for a generic SVGA. */ |
||
682 | __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); |
||
683 | |||
684 | /* Set up the extended register values, including modifications */ |
||
685 | /* of standard VGA registers. */ |
||
686 | |||
687 | moderegs[VGA_SR0] = 0x03; |
||
688 | moderegs[VGA_CR13] = modeinfo->lineWidth >> 3; |
||
689 | moderegs[VGA_CR17] = 0xE3; |
||
690 | |||
691 | if (modeinfo->lineWidth / modeinfo->bytesPerPixel == 2048) |
||
692 | moderegs[S3_CR31] = 0x8F; |
||
693 | else |
||
694 | moderegs[S3_CR31] = 0x8D; |
||
695 | #ifdef S3_LINEAR_MODE_BANKING_864 |
||
696 | if (s3_chiptype >= S3_864) { |
||
697 | /* moderegs[S3_ENHANCEDMODE] |= 0x01; */ |
||
698 | /* Enable enhanced memory mode. */ |
||
699 | moderegs[S3_CR31] |= 0x04; |
||
700 | /* Enable banking via CR6A in linear mode. */ |
||
701 | moderegs[S3_CR31] |= 0x01; |
||
702 | } |
||
703 | #endif |
||
704 | moderegs[S3_CR32] = 0; |
||
705 | moderegs[S3_CR33] = 0x20; |
||
706 | moderegs[S3_CR34] = 0x10; /* 1024 */ |
||
707 | moderegs[S3_CR35] = 0; |
||
708 | /* Call cebank() here when setting registers. */ |
||
709 | if (modeinfo->bitsPerPixel >= 8) { |
||
710 | moderegs[S3_CR3A] = 0xB5; |
||
711 | if (s3_chiptype == S3_928) |
||
712 | /* ARI: Turn on CHAIN4 for 928, since __svgalib_setup_VGA_registers |
||
713 | initializes ModeX */ |
||
714 | moderegs[VGA_CR14] = 0x60; |
||
715 | } else { |
||
716 | /* 16 color mode */ |
||
717 | moderegs[VGA_CR13] = modeinfo->lineWidth >> 1; |
||
718 | moderegs[VGA_GR0] = 0x0F; |
||
719 | moderegs[VGA_GR1] = 0x0F; |
||
720 | moderegs[VGA_GR5] = 0x00; /* write mode 0 */ |
||
721 | moderegs[VGA_AR11] = 0x00; |
||
722 | moderegs[S3_CR3A] = 0x85; |
||
723 | } |
||
724 | |||
725 | moderegs[S3_CR3B] = (moderegs[VGA_CR0] + moderegs[VGA_CR4] + 1) / 2; |
||
726 | moderegs[S3_CR3C] = moderegs[VGA_CR0] / 2; |
||
727 | if (s3_chiptype == S3_911) { |
||
728 | moderegs[S3_CR40] &= 0xF2; |
||
729 | moderegs[S3_CR40] |= 0x09; |
||
730 | } else if (s3_flags & S3_LOCALBUS) { |
||
731 | moderegs[S3_CR40] &= 0xF2; |
||
732 | /* Pegasus wants 0x01 for zero wait states. */ |
||
733 | #ifdef S3_0_WAIT_805_864 |
||
734 | moderegs[S3_CR40] |= 0x09; /* use fifo + 0 wait state */ |
||
735 | #else |
||
736 | moderegs[S3_CR40] |= 0x05; |
||
737 | #endif |
||
738 | } else { |
||
739 | moderegs[S3_CR40] &= 0xF6; |
||
740 | moderegs[S3_CR40] |= 0x01; |
||
741 | } |
||
742 | |||
743 | if (modeinfo->bitsPerPixel >= 24) { |
||
744 | /* 24/32 bit color */ |
||
745 | if (s3_chiptype == S3_864 || s3_chiptype == S3_964) |
||
746 | moderegs[S3_CR43] = 0x08; |
||
747 | else if (s3_chiptype == S3_928 && dac_used->id == SIERRA_15025) |
||
748 | moderegs[S3_CR43] = 0x01; /* ELSA Winner 1000 */ |
||
749 | } else if (modeinfo->bitsPerPixel >= 15) { |
||
750 | /* 15/16 bit color */ |
||
751 | if (s3_chiptype <= S3_864 || s3_chiptype >= S3_866) { /* XXXX Trio? */ |
||
752 | moderegs[S3_CR43] = 0x08; |
||
753 | if (dac_used->id == IBMRGB52x) |
||
754 | moderegs[S3_CR43] = 0x10; |
||
755 | else if (s3_chiptype == S3_928 && dac_used->id == SIERRA_15025) |
||
756 | moderegs[S3_CR43] = 0x01; |
||
757 | if (s3_chiptype <= S3_924 && dac_used->id != NORMAL_DAC) |
||
758 | moderegs[S3_CR43] = 0x01; |
||
759 | |||
760 | } else |
||
761 | /* XXXX some DAC might need this; XF86 source says... */ |
||
762 | moderegs[S3_CR43] = 0x09; |
||
763 | } else { |
||
764 | /* 4/8 bit color */ |
||
765 | moderegs[S3_CR43] = 0x00; |
||
766 | } |
||
767 | |||
768 | if (s3_chiptype >= S3_924 && s3_chiptype <= S3_928) { /* different for 864+ */ |
||
769 | s3_8514regs[S3_ADVFUNC_CNTL] = 0x0002; |
||
770 | if ((s3_chiptype == S3_928 && modeinfo->bitsPerPixel != 4) || !(s3_flags & S3_OLD_STEPPING)) |
||
771 | s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0001; |
||
772 | if (modeinfo->bitsPerPixel == 4) |
||
773 | s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004; |
||
774 | #if 0 |
||
775 | /* 864 databook says it is for enhanced 4bpp */ |
||
776 | if (modeinfo->lineWidth > 640) |
||
777 | s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004; |
||
778 | #endif |
||
779 | } else if (s3_chiptype == S3_968) { |
||
780 | s3_8514regs[S3_ADVFUNC_CNTL] = 0x0002; |
||
781 | if (modeinfo->bitsPerPixel == 4) |
||
782 | s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0004; |
||
783 | #ifdef PIXEL_MULTIPLEXING |
||
784 | else |
||
785 | s3_8514regs[S3_ADVFUNC_CNTL] |= 0x0001; |
||
786 | #endif |
||
787 | } else if (modeinfo->lineWidth / modeinfo->bytesPerPixel == 1024) |
||
788 | s3_8514regs[S3_ADVFUNC_CNTL] = 0x0007; |
||
789 | else |
||
790 | s3_8514regs[S3_ADVFUNC_CNTL] = 0x0003; |
||
791 | |||
792 | moderegs[S3_CR44] = 0; |
||
793 | /* Skip CR45, 'hi/truecolor cursor color enable'. */ |
||
794 | |||
795 | if (s3_chiptype >= S3_801) { |
||
796 | int m, n; /* for FIFO balancing */ |
||
797 | |||
798 | /* XXXX Not all chips support all widths. */ |
||
799 | moderegs[S3_CR50] &= ~0xF1; |
||
800 | switch (modeinfo->bitsPerPixel) { |
||
801 | case 16: |
||
802 | moderegs[S3_CR50] |= 0x10; |
||
803 | break; |
||
804 | case 24: /* XXXX 868/968 only */ |
||
805 | if (s3_chiptype >= S3_868) |
||
806 | moderegs[S3_CR50] |= 0x20; |
||
807 | break; |
||
808 | case 32: |
||
809 | moderegs[S3_CR50] |= 0x30; |
||
810 | break; |
||
811 | } |
||
812 | |||
813 | switch (modeinfo->lineWidth / modeinfo->bytesPerPixel) { |
||
814 | case 640: |
||
815 | moderegs[S3_CR50] |= 0x40; |
||
816 | break; |
||
817 | case 800: |
||
818 | moderegs[S3_CR50] |= 0x80; |
||
819 | break; |
||
820 | case 1152: |
||
821 | if (!(s3_flags & S3_OLD_STEPPING)) { |
||
822 | moderegs[S3_CR50] |= 0x01; |
||
823 | break; |
||
824 | } /* else fall through */ |
||
825 | case 1280: |
||
826 | moderegs[S3_CR50] |= 0xC0; |
||
827 | break; |
||
828 | case 1600: |
||
829 | moderegs[S3_CR50] |= 0x81; |
||
830 | break; |
||
831 | /* 1024/2048 no change. */ |
||
832 | } |
||
833 | |||
834 | moderegs[S3_CR51] &= 0xC0; |
||
835 | moderegs[S3_CR51] |= (modeinfo->lineWidth >> 7) & 0x30; |
||
836 | |||
837 | /* moderegs[S3_CR53] |= 0x10; *//* Enable MMIO. */ |
||
838 | /* moderegs[S3_CR53] |= 0x20; *//* DRAM interleaving for S3_805i with 2MB */ |
||
839 | |||
840 | n = 0xFF; |
||
841 | if (s3_chiptype >= S3_864 || |
||
842 | s3_chiptype == S3_801 || s3_chiptype == S3_805) { |
||
843 | /* |
||
844 | * CRT FIFO balancing for DRAM cards and 964/968 |
||
845 | * in VGA mode. |
||
846 | */ |
||
847 | int clock, mclk; |
||
848 | if (modeinfo->bitsPerPixel < 8) { |
||
849 | clock = modetiming->pixelClock; |
||
850 | } else { |
||
851 | clock = modetiming->pixelClock * |
||
852 | modeinfo->bytesPerPixel; |
||
853 | } |
||
854 | if (s3_memory < 2048 || s3_chiptype == S3_TRIO32) |
||
855 | clock *= 2; |
||
856 | if (__svgalib_s3_s3Mclk > 0) |
||
857 | mclk = __svgalib_s3_s3Mclk; |
||
858 | else if (s3_chiptype == S3_801 || s3_chiptype == S3_805) |
||
859 | mclk = 50000; /* Assumption. */ |
||
860 | else |
||
861 | mclk = 60000; /* Assumption. */ |
||
862 | m = (int) ((mclk / 1000.0 * .72 + 16.867) * 89.736 / (clock / 1000.0 + 39) - 21.1543); |
||
863 | if (s3_memory < 2048 || s3_chiptype == S3_TRIO32) |
||
864 | m /= 2; |
||
865 | if (m > 31) |
||
866 | m = 31; |
||
867 | else if (m < 0) { |
||
868 | m = 0; |
||
869 | n = 16; |
||
870 | } |
||
871 | } else if (s3_memory == 512 || modetiming->HDisplay > 1200) |
||
872 | m = 0; |
||
873 | else if (s3_memory == 1024) |
||
874 | m = 2; |
||
875 | else |
||
876 | m = 20; |
||
877 | |||
878 | moderegs[S3_CR54] = m << 3; |
||
879 | moderegs[S3_CR60] = n; |
||
880 | |||
881 | moderegs[S3_CR55] &= 0x08; |
||
882 | moderegs[S3_CR55] |= 0x40; |
||
883 | |||
884 | #ifdef S3_LINEAR_MODE_BANKING_864 |
||
885 | if (s3_chiptype >= S3_864) { |
||
886 | if (modeinfo->bitsPerPixel >= 8) { |
||
887 | /* Enable linear addressing. */ |
||
888 | moderegs[S3_CR58] |= 0x10; |
||
889 | /* Set window size to 64K. */ |
||
890 | moderegs[S3_CR58] &= ~0x03; |
||
891 | /* Assume CR59/5A are correctly set up for 0xA0000. */ |
||
892 | /* Set CR6A linear bank to zero. */ |
||
893 | moderegs[S3_CR6A] &= ~0x3F; |
||
894 | /* use alternate __svgalib_setpage() function */ |
||
895 | __svgalib_s3_driverspecs.__svgalib_setpage = s3_setpage864; |
||
896 | } else { |
||
897 | /* doesn't work for 4bpp. */ |
||
898 | __svgalib_s3_driverspecs.__svgalib_setpage = s3_setpage; |
||
899 | } |
||
900 | } |
||
901 | #endif |
||
902 | #ifdef S3_LINEAR_SUPPORT |
||
903 | moderegs[S3_CR59] = s3_cr59; |
||
904 | moderegs[S3_CR5A] = s3_cr5A; |
||
905 | #endif |
||
906 | |||
907 | /* Extended CRTC timing. */ |
||
908 | moderegs[S3_CR5E] = |
||
909 | (((modetiming->CrtcVTotal - 2) & 0x400) >> 10) | |
||
910 | (((modetiming->CrtcVDisplay - 1) & 0x400) >> 9) | |
||
911 | (((modetiming->CrtcVSyncStart) & 0x400) >> 8) | |
||
912 | (((modetiming->CrtcVSyncStart) & 0x400) >> 6) | 0x40; |
||
913 | |||
914 | { |
||
915 | int i, j; |
||
916 | i = ((((modetiming->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | |
||
917 | ((((modetiming->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | |
||
918 | ((((modetiming->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | |
||
919 | ((modetiming->CrtcHSyncStart & 0x800) >> 7); |
||
920 | if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 64) |
||
921 | i |= 0x08; |
||
922 | if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 32) |
||
923 | i |= 0x20; |
||
924 | j = ((moderegs[VGA_CR0] + ((i & 0x01) << 8) + |
||
925 | moderegs[VGA_CR4] + ((i & 0x10) << 4) + 1) / 2); |
||
926 | if (j - (moderegs[VGA_CR4] + ((i & 0x10) << 4)) < 4) { |
||
927 | if (moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4 <= moderegs[VGA_CR0] + ((i & 0x01) << 8)) |
||
928 | j = moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4; |
||
929 | else |
||
930 | j = moderegs[VGA_CR0] + ((i & 0x01) << 8) + 1; |
||
931 | } |
||
932 | |||
933 | moderegs[S3_CR3B] = j & 0xFF; |
||
934 | i |= (j & 0x100) >> 2; |
||
935 | /* Interlace mode frame offset. */ |
||
936 | moderegs[S3_CR3C] = (moderegs[VGA_CR0] + ((i & 0x01) << 8)) / 2; |
||
937 | moderegs[S3_CR5D] = (moderegs[S3_CR5D] & 0x80) | i; |
||
938 | } |
||
939 | |||
940 | { |
||
941 | int i; |
||
942 | |||
943 | if (modeinfo->bitsPerPixel < 8) |
||
944 | i = modetiming->HDisplay / 4 + 1; |
||
945 | else |
||
946 | i = modetiming->HDisplay * |
||
947 | modeinfo->bytesPerPixel / 4 + 1; |
||
948 | |||
949 | moderegs[S3_CR61] = (i >> 8) | 0x80; |
||
950 | moderegs[S3_CR62] = i & 0xFF; |
||
951 | } |
||
952 | } /* 801+ */ |
||
953 | if (modetiming->flags & INTERLACED) |
||
954 | moderegs[S3_CR42] |= 0x20; |
||
955 | |||
956 | /* |
||
957 | * Clock select works as follows: |
||
958 | * Clocks 0 and 1 (VGA 25 and 28 MHz) can be selected via the |
||
959 | * two VGA MiscOutput clock select bits. |
||
960 | * If 0x3 is written to these bits, the selected clock index |
||
961 | * is taken from the S3 clock select register at CR42. Clock |
||
962 | * indices 0 and 1 should correspond to the VGA ones above, |
||
963 | * and 3 is often 0 MHz, followed by extended clocks for a |
||
964 | * total of mostly 16. |
||
965 | */ |
||
966 | |||
967 | if (modetiming->flags & USEPROGRCLOCK) |
||
968 | moderegs[VGA_MISCOUTPUT] |= 0x0C; /* External clock select. */ |
||
969 | else if (modetiming->selectedClockNo < 2) { |
||
970 | /* Program clock select bits 0 and 1. */ |
||
971 | moderegs[VGA_MISCOUTPUT] &= ~0x0C; |
||
972 | moderegs[VGA_MISCOUTPUT] |= |
||
973 | (modetiming->selectedClockNo & 3) << 2; |
||
974 | } else if (modetiming->selectedClockNo >= 2) { |
||
975 | moderegs[VGA_MISCOUTPUT] |= 0x0C; |
||
976 | /* Program S3 clock select bits. */ |
||
977 | moderegs[S3_CR42] &= ~0x1F; |
||
978 | moderegs[S3_CR42] |= |
||
979 | modetiming->selectedClockNo; |
||
980 | } |
||
981 | if (s3_chiptype == S3_TRIO64 || s3_chiptype == S3_765) { |
||
982 | moderegs[S3_CR33] &= ~0x08; |
||
983 | if (modeinfo->bitsPerPixel == 16) |
||
984 | moderegs[S3_CR33] |= 0x08; |
||
985 | /* |
||
986 | * The rest of the DAC/clocking is setup by the |
||
987 | * Trio64 code in the RAMDAC interface (ramdac.c). |
||
988 | */ |
||
989 | } |
||
990 | if (dac_used->id != NORMAL_DAC) { |
||
991 | int colormode; |
||
992 | colormode = __svgalib_colorbits_to_colormode(modeinfo->bitsPerPixel, |
||
993 | modeinfo->colorBits); |
||
994 | dac_used->initializeState(&moderegs[S3_DAC_OFFSET], |
||
995 | modeinfo->bitsPerPixel, colormode, |
||
996 | modetiming->pixelClock); |
||
997 | |||
998 | if (dac_used->id == ATT20C490) { |
||
999 | int pixmux, invert_vclk, blank_delay; |
||
1000 | pixmux = 0; |
||
1001 | invert_vclk = 0; |
||
1002 | blank_delay = 2; |
||
1003 | if (colormode == CLUT8_6 |
||
1004 | && modetiming->pixelClock >= 67500) { |
||
1005 | pixmux = 0x00; |
||
1006 | invert_vclk = 1; |
||
1007 | } else if (colormode == CLUT8_8) |
||
1008 | pixmux = 0x02; |
||
1009 | else if (colormode == RGB16_555) |
||
1010 | pixmux = 0xa0; |
||
1011 | else if (colormode == RGB16_565) |
||
1012 | pixmux = 0xc0; |
||
1013 | else if (colormode == RGB24_888_B) |
||
1014 | pixmux = 0xe0; |
||
1015 | moderegs[S3_CR67] = pixmux | invert_vclk; |
||
1016 | moderegs[S3_CR6D] = blank_delay; |
||
1017 | } |
||
1018 | if (dac_used->id == S3_SDAC) { |
||
1019 | int pixmux, invert_vclk, blank_delay; |
||
1020 | pixmux = 0; |
||
1021 | invert_vclk = 0; |
||
1022 | blank_delay = 0; |
||
1023 | if (colormode == CLUT8_6 |
||
1024 | && modetiming->pixelClock >= 67500) { |
||
1025 | #ifdef SDAC_8BPP_PIXMUX |
||
1026 | /* x64 8bpp pixel multiplexing? */ |
||
1027 | pixmux = 0x10; |
||
1028 | if (s3_chiptype != S3_866 && s3_chiptype != S3_868) |
||
1029 | invert_vclk = 1; |
||
1030 | blank_delay = 2; |
||
1031 | #endif |
||
1032 | } else if (colormode == RGB16_555) { |
||
1033 | pixmux = 0x30; |
||
1034 | blank_delay = 2; |
||
1035 | } else if (colormode == RGB16_565) { |
||
1036 | pixmux = 0x50; |
||
1037 | blank_delay = 2; |
||
1038 | } else if (colormode == RGB24_888_B) { /* XXXX 868/968 only */ |
||
1039 | pixmux = 0x90; |
||
1040 | blank_delay = 2; |
||
1041 | } else if (colormode == RGB32_888_B) { |
||
1042 | pixmux = 0x70; |
||
1043 | blank_delay = 2; |
||
1044 | } |
||
1045 | moderegs[S3_CR67] = pixmux | invert_vclk; |
||
1046 | moderegs[S3_CR6D] = blank_delay; |
||
1047 | /* Clock select. */ |
||
1048 | moderegs[S3_CR42] &= ~0x0F; |
||
1049 | moderegs[S3_CR42] |= 0x02; |
||
1050 | } |
||
1051 | if (dac_used->id == IBMRGB52x) { |
||
1052 | unsigned char pixmux, blank_delay, tmp; |
||
1053 | tmp = 0; |
||
1054 | pixmux = 0x11; |
||
1055 | blank_delay = 0; |
||
1056 | if (modeinfo->bitsPerPixel < 8 || colormode == RGB32_888_B) |
||
1057 | pixmux = 0x00; |
||
1058 | moderegs[S3_CR58] |= 0x40; |
||
1059 | moderegs[S3_CR65] = 0; |
||
1060 | moderegs[S3_CR66] &= 0xf8; |
||
1061 | moderegs[S3_CR66] |= tmp; |
||
1062 | #ifdef PIXEL_MULTIPLEXING |
||
1063 | moderegs[S3_CR67] = pixmux; |
||
1064 | #endif |
||
1065 | moderegs[S3_CR6D] = blank_delay; |
||
1066 | /* Clock select. */ |
||
1067 | moderegs[S3_CR42] &= ~0x0F; |
||
1068 | moderegs[S3_CR42] |= 0x02; |
||
1069 | } |
||
1070 | } |
||
1071 | #ifdef S3_LINEAR_SUPPORT |
||
1072 | s3_cr58 = moderegs[S3_CR58]; |
||
1073 | s3_cr40 = moderegs[S3_CR40]; |
||
1074 | s3_cr54 = moderegs[S3_CR54]; |
||
1075 | #endif |
||
1076 | if (clk_used == &__svgalib_I2061A_clockchip_methods && |
||
1077 | (modetiming->flags & USEPROGRCLOCK)) { |
||
1078 | /* Clock select. */ |
||
1079 | moderegs[S3_CR42] &= ~0x0F; |
||
1080 | moderegs[S3_CR42] |= 0x02; |
||
1081 | } |
||
1082 | /* update the 8514 regs */ |
||
1083 | memcpy(moderegs + S3_8514_OFFSET, s3_8514regs, S3_8514_COUNT * 2); |
||
1084 | } |
||
1085 | |||
1086 | |||
1087 | /* Set a mode */ |
||
1088 | |||
1089 | static int s3_setmode(int mode, int prv_mode) |
||
1090 | { |
||
1091 | ModeInfo *modeinfo; |
||
1092 | ModeTiming *modetiming; |
||
1093 | unsigned char moderegs[S3_TOTAL_REGS]; |
||
1094 | int res; |
||
1095 | |||
1096 | if (IS_IN_STANDARD_VGA_DRIVER(mode)) { |
||
1097 | /* Let the standard VGA driver set standard VGA modes. */ |
||
1098 | res = __svgalib_vga_driverspecs.setmode(mode, prv_mode); |
||
1099 | if (res == 0) { |
||
1100 | /* |
||
1101 | * ARI: Turn off virtual size of 1024 - this fixes all problems |
||
1102 | * with standard modes, including 320x200x256. |
||
1103 | * |
||
1104 | * SL: Is this for 928 only? Doesn't matter for 805. |
||
1105 | * |
||
1106 | * MZ: Affects 765 as well, so I assume it is good for all chipsets. |
||
1107 | */ |
||
1108 | s3_unlock(); |
||
1109 | __svgalib_outCR(0x34, __svgalib_inCR(0x34) & ~0x10); |
||
1110 | s3_lock(); |
||
1111 | } |
||
1112 | return res; |
||
1113 | } |
||
1114 | if (!s3_modeavailable(mode)) |
||
1115 | return 1; |
||
1116 | |||
1117 | modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); |
||
1118 | |||
1119 | modetiming = malloc(sizeof(ModeTiming)); |
||
1120 | if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { |
||
1121 | free(modetiming); |
||
1122 | free(modeinfo); |
||
1123 | return 1; |
||
1124 | } |
||
1125 | /* Adjust the display width. */ |
||
1126 | modeinfo->lineWidth = s3_adjlinewidth(modeinfo->lineWidth); |
||
1127 | CI.xbytes = modeinfo->lineWidth; |
||
1128 | |||
1129 | s3_initializemode(moderegs, modetiming, modeinfo); |
||
1130 | free(modeinfo); |
||
1131 | free(modetiming); |
||
1132 | |||
1133 | __svgalib_setregs(moderegs); /* Set standard regs. */ |
||
1134 | s3_setregs(moderegs, mode); /* Set extended regs. */ |
||
1135 | return 0; |
||
1136 | } |
||
1137 | |||
1138 | |||
1139 | /* Indentify chipset; return non-zero if detected */ |
||
1140 | |||
1141 | /* Some port I/O functions: */ |
||
1142 | static unsigned char rdinx(int port, unsigned char index) |
||
1143 | { |
||
1144 | outb(port, index); |
||
1145 | return port_in(port + 1); |
||
1146 | } |
||
1147 | |||
1148 | static void wrinx(int port, unsigned char index, unsigned char val) |
||
1149 | { |
||
1150 | outb(port, index); |
||
1151 | outb(port + 1, val); |
||
1152 | } |
||
1153 | |||
1154 | /* |
||
1155 | * Returns true iff the bits in 'mask' of register 'port', index 'index' |
||
1156 | * are read/write. |
||
1157 | */ |
||
1158 | static int testinx2(int port, unsigned char index, unsigned char mask) |
||
1159 | { |
||
1160 | unsigned char old, new1, new2; |
||
1161 | |||
1162 | old = rdinx(port, index); |
||
1163 | wrinx(port, index, (old & ~mask)); |
||
1164 | new1 = rdinx(port, index) & mask; |
||
1165 | wrinx(port, index, (old | mask)); |
||
1166 | new2 = rdinx(port, index) & mask; |
||
1167 | wrinx(port, index, old); |
||
1168 | return (new1 == 0) && (new2 == mask); |
||
1169 | } |
||
1170 | |||
1171 | int s3_test(void) |
||
1172 | { |
||
1173 | int vgaIOBase, vgaCRIndex, vgaCRReg; |
||
1174 | |||
1175 | vgaIOBase = (port_in(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; |
||
1176 | vgaCRIndex = vgaIOBase + 4; |
||
1177 | vgaCRReg = vgaIOBase + 5; |
||
1178 | |||
1179 | outb(vgaCRIndex, 0x11); /* for register CR11, (Vertical Retrace End) */ |
||
1180 | outb(vgaCRReg, 0x00); /* set to 0 */ |
||
1181 | |||
1182 | outb(vgaCRIndex, 0x38); /* check if we have an S3 */ |
||
1183 | outb(vgaCRReg, 0x00); |
||
1184 | |||
1185 | /* Make sure we can't write when locked */ |
||
1186 | |||
1187 | if (testinx2(vgaCRIndex, 0x35, 0x0f)) |
||
1188 | return 0; |
||
1189 | |||
1190 | outb(vgaCRIndex, 0x38); /* for register CR38, (REG_LOCK1) */ |
||
1191 | outb(vgaCRReg, 0x48); /* unlock S3 register set for read/write */ |
||
1192 | |||
1193 | /* Make sure we can write when unlocked */ |
||
1194 | |||
1195 | if (!testinx2(vgaCRIndex, 0x35, 0x0f)) |
||
1196 | return 0; |
||
1197 | |||
1198 | if (s3_init(0, 0, 0)) /* type not OK */ |
||
1199 | return 0; |
||
1200 | return 1; |
||
1201 | } |
||
1202 | |||
1203 | /* |
||
1204 | * Bank switching function - set 64K bank number |
||
1205 | * |
||
1206 | * XXXX locking and unlocking might hurt performance but is safer. |
||
1207 | */ |
||
1208 | static void s3_setpage(int page) |
||
1209 | { |
||
1210 | #ifdef S3_16_COLORS |
||
1211 | /* |
||
1212 | * XXXX adjust the parameter for 4bpp (1bpp is ignored). Shouldn't |
||
1213 | * need this, but either me or the drawing functions are making bad |
||
1214 | * assumptions about 4bpp. |
||
1215 | */ |
||
1216 | if (infotable[CM].bytesperpixel == 0) |
||
1217 | page *= 4; |
||
1218 | #endif |
||
1219 | #ifdef S3_KLUDGE_PAGE_MODE |
||
1220 | /* adjust to use 256K pages */ |
||
1221 | if (CM == G320x200x256) |
||
1222 | page *= 4; |
||
1223 | #endif |
||
1224 | s3_unlock(); |
||
1225 | outb(CRT_IC, 0x35); |
||
1226 | outb(CRT_DC, (port_in(CRT_DC) & 0xF0) | (page & 0x0F)); |
||
1227 | if (s3_chiptype >= S3_801) { |
||
1228 | outb(CRT_IC, 0x51); |
||
1229 | outb(CRT_DC, (port_in(CRT_DC) & ~0x0C) | ((page & 0x30) >> 2)); |
||
1230 | } |
||
1231 | port_in(CRT_DC); /* ARI: Ferraro says: required for first generation 911 only */ |
||
1232 | s3_lock(); |
||
1233 | } |
||
1234 | |||
1235 | /* |
||
1236 | * Bank switching function - set 64K bank number for 864+ |
||
1237 | * (not for 4bpp) |
||
1238 | * |
||
1239 | * XXXX locking and unlocking might hurt performance |
||
1240 | * (864 shouldn't need it). |
||
1241 | */ |
||
1242 | #ifdef S3_LINEAR_MODE_BANKING_864 |
||
1243 | static void s3_setpage864(int page) |
||
1244 | { |
||
1245 | s3_unlock(); |
||
1246 | /* "Linear" mode banking. */ |
||
1247 | outb(CRT_IC, 0x6A); |
||
1248 | outb(CRT_DC, (port_in(CRT_DC) & ~0x3F) | page); |
||
1249 | s3_lock(); |
||
1250 | } |
||
1251 | |||
1252 | #endif |
||
1253 | |||
1254 | /* |
||
1255 | * Set display start address (not for 16 color modes). |
||
1256 | * |
||
1257 | * This works up to 4Mb (should be able to go higher). |
||
1258 | * |
||
1259 | * XXXX locking and unlocking might hurt performance but is safer. |
||
1260 | */ |
||
1261 | static void s3_setdisplaystart(int address) |
||
1262 | { |
||
1263 | #ifdef S3_KLUDGE_PAGE_MODE |
||
1264 | /* adjust to use 256K pages */ |
||
1265 | if (CM == G320x200x256) |
||
1266 | address *= 4; |
||
1267 | #endif |
||
1268 | s3_unlock(); |
||
1269 | outw(CRT_IC, 0x0d | ((address << 6) & 0xff00)); /* sa2-sa9 */ |
||
1270 | outw(CRT_IC, 0x0c | ((address >> 2) & 0xff00)); /* sa10-sa17 */ |
||
1271 | port_in(0x3da); /* set ATC to addressing mode */ |
||
1272 | outb(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ |
||
1273 | outb(ATT_IW, (port_in(ATT_R) & 0xf0) | ((address & 3) << 1)); |
||
1274 | /* write sa0-1 to bits 1-2 */ |
||
1275 | |||
1276 | outb(CRT_IC, 0x31); |
||
1277 | outb(CRT_DC, (port_in(CRT_DC) & ~0x30) | ((address & 0xc0000) >> 14)); |
||
1278 | if (s3_chiptype >= S3_801) { |
||
1279 | outb(CRT_IC, 0x51); |
||
1280 | outb(CRT_DC, (port_in(CRT_DC) & ~0x03) | ((address & 0x300000) >> 20)); |
||
1281 | } |
||
1282 | s3_lock(); |
||
1283 | } |
||
1284 | |||
1285 | /* |
||
1286 | * Set logical scanline length (Multiples of 8 to 8184). |
||
1287 | * CR43.2 should be 0 for this. |
||
1288 | */ |
||
1289 | static void s3_setlogicalwidth(int width) |
||
1290 | { |
||
1291 | __svgalib_outCR(0x13, (width >> 3)); /* lw3-lw11 */ |
||
1292 | __svgalib_outCR(0x51, (width & 0x300) >> 4); /* lw12-lw13 */ |
||
1293 | } |
||
1294 | |||
1295 | #ifdef S3_LINEAR_SUPPORT |
||
1296 | static void s3_linear_enable(void) |
||
1297 | { |
||
1298 | s3_unlock(); |
||
1299 | |||
1300 | if (s3_chiptype > S3_924) { |
||
1301 | int i; |
||
1302 | outb (CRT_IC, 0x40); |
||
1303 | i = (s3_cr40 & 0xf6) | 0x0a; |
||
1304 | outb (CRT_DC, (unsigned char) i); |
||
1305 | outb (CRT_IC, 0x58); |
||
1306 | outb (CRT_DC, s3_linear_opt | s3_cr58); |
||
1307 | if (s3_chiptype > S3_928) { |
||
1308 | outb (CRT_IC, 0x54); |
||
1309 | outb (CRT_DC, (s3_cr54 + 0x07)); |
||
1310 | } |
||
1311 | } |
||
1312 | |||
1313 | s3_lock(); |
||
1314 | } |
||
1315 | |||
1316 | static void s3_linear_disable(void) |
||
1317 | { |
||
1318 | s3_unlock(); |
||
1319 | |||
1320 | if (s3_chiptype > S3_924) { |
||
1321 | if (s3_chiptype > S3_928) { |
||
1322 | outb (CRT_IC, 0x54); |
||
1323 | outb (CRT_DC, s3_cr54); |
||
1324 | } |
||
1325 | outb (CRT_IC, 0x58); |
||
1326 | outb (CRT_DC, s3_cr58); |
||
1327 | outb (CRT_IC, 0x40); |
||
1328 | outb (CRT_DC, s3_cr40); |
||
1329 | } |
||
1330 | |||
1331 | s3_lock(); |
||
1332 | } |
||
1333 | |||
1334 | /* Set linear addressing mode */ |
||
1335 | |||
1336 | static int s3_linear(int op, int param) |
||
1337 | { |
||
1338 | if (op == LINEAR_QUERY_BASE) |
||
1339 | return s3_linear_base; |
||
1340 | if (op == LINEAR_QUERY_GRANULARITY) { |
||
1341 | switch (s3_memory) { |
||
1342 | case 4096: |
||
1343 | case 2048: |
||
1344 | case 1024: |
||
1345 | return s3_memory * 1024; |
||
1346 | default: |
||
1347 | return 1024 * 1024; |
||
1348 | } |
||
1349 | } else if (op == LINEAR_QUERY_RANGE) |
||
1350 | return 256; |
||
1351 | else if (op == LINEAR_ENABLE) { |
||
1352 | s3_setpage(0); |
||
1353 | s3_linear_enable(); |
||
1354 | s3_linear_addr = param; |
||
1355 | return 0; |
||
1356 | } else if (op == LINEAR_DISABLE) { |
||
1357 | s3_setpage(0); |
||
1358 | s3_linear_disable(); |
||
1359 | s3_linear_addr = 0; |
||
1360 | return 0; |
||
1361 | } else |
||
1362 | return -1; |
||
1363 | } |
||
1364 | |||
1365 | #define S3_LINEAR_FUNC s3_linear |
||
1366 | #else |
||
1367 | #define S3_LINEAR_FUNC 0 |
||
1368 | #endif /* S3_LINEAR_SUPPORT */ |
||
1369 | |||
1370 | /* Function table (exported) */ |
||
1371 | |||
1372 | DriverSpecs __svgalib_s3_driverspecs = |
||
1373 | { |
||
1374 | s3_saveregs, /* saveregs */ |
||
1375 | s3_setregs, /* setregs */ |
||
1376 | (void (*)(void)) nothing, /* unlock */ |
||
1377 | (void (*)(void)) nothing, /* lock */ |
||
1378 | s3_test, |
||
1379 | s3_init, |
||
1380 | s3_setpage, |
||
1381 | (void (*)(int)) nothing, |
||
1382 | (void (*)(int)) nothing, |
||
1383 | s3_setmode, |
||
1384 | s3_modeavailable, |
||
1385 | s3_setdisplaystart, |
||
1386 | s3_setlogicalwidth, |
||
1387 | s3_getmodeinfo, |
||
1388 | 0, /* bitblt */ |
||
1389 | 0, /* imageblt */ |
||
1390 | 0, /* fillblt */ |
||
1391 | 0, /* hlinelistblt */ |
||
1392 | 0, /* bltwait */ |
||
1393 | s3_ext_set, /* extset */ |
||
1394 | 0, /* accel */ |
||
1395 | S3_LINEAR_FUNC, /* linear */ |
||
1396 | NULL, /* Accelspecs */ |
||
1397 | NULL, /* Emulation */ |
||
1398 | }; |
||
1399 | |||
1400 | /* Initialize driver (called after detection) */ |
||
1401 | /* Derived from XFree86 SuperProbe and s3 driver. */ |
||
1402 | |||
1403 | static DacMethods *dacs_to_probe[] = |
||
1404 | { |
||
1405 | #ifdef INCLUDE_S3_SDAC_DAC_TEST |
||
1406 | &__svgalib_S3_SDAC_methods, |
||
1407 | #endif |
||
1408 | #ifdef INCLUDE_S3_GENDAC_DAC_TEST |
||
1409 | &__svgalib_S3_GENDAC_methods, |
||
1410 | #endif |
||
1411 | #ifdef INCLUDE_ATT20C490_DAC_TEST |
||
1412 | &__svgalib_ATT20C490_methods, |
||
1413 | #endif |
||
1414 | #ifdef INCLUDE_SC15025_DAC_TEST |
||
1415 | &__svgalib_SC15025_methods, |
||
1416 | #endif |
||
1417 | #ifdef INCLUDE_SC1148X_DAC_TEST |
||
1418 | &__svgalib_SC1148X_methods, |
||
1419 | #endif |
||
1420 | #ifdef INCLUDE_IBMRGB52x_DAC_TEST |
||
1421 | &__svgalib_IBMRGB52x_methods, |
||
1422 | #endif |
||
1423 | NULL}; |
||
1424 | |||
1425 | static int s3_init(int force, int par1, int par2) |
||
1426 | { |
||
1427 | int id, rev, config; |
||
1428 | |||
1429 | s3_unlock(); |
||
1430 | |||
1431 | s3_flags = 0; /* initialize */ |
||
1432 | id = __svgalib_inCR(0x30); /* Get chip id. */ |
||
1433 | rev = id & 0x0F; |
||
1434 | if (id >= 0xE0) { |
||
1435 | id |= __svgalib_inCR(0x2E) << 8; |
||
1436 | rev |= __svgalib_inCR(0x2F) << 4; |
||
1437 | } |
||
1438 | if (force) { |
||
1439 | s3_chiptype = par1; /* we already know the type */ |
||
1440 | s3_memory = par2; |
||
1441 | /* ARI: can we really trust the user's specification, or should we ignore |
||
1442 | it and probe ourselves ? */ |
||
1443 | if (s3_chiptype == S3_801 || s3_chiptype == S3_805) { |
||
1444 | if ((rev & 0x0F) < 2) |
||
1445 | s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */ |
||
1446 | } else if (s3_chiptype == S3_928) { |
||
1447 | if ((rev & 0x0F) < 4) /* ARI: Stepping D or below */ |
||
1448 | s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */ |
||
1449 | } |
||
1450 | } else { |
||
1451 | s3_chiptype = -1; |
||
1452 | config = __svgalib_inCR(0x36); /* get configuration info */ |
||
1453 | switch (id & 0xf0) { |
||
1454 | case 0x80: |
||
1455 | if (rev == 1) { |
||
1456 | s3_chiptype = S3_911; |
||
1457 | break; |
||
1458 | } |
||
1459 | if (rev == 2) { |
||
1460 | s3_chiptype = S3_924; |
||
1461 | break; |
||
1462 | } |
||
1463 | break; |
||
1464 | case 0xa0: |
||
1465 | switch (config & 0x03) { |
||
1466 | case 0x00: |
||
1467 | case 0x01: |
||
1468 | /* EISA or VLB - 805 */ |
||
1469 | s3_chiptype = S3_805; |
||
1470 | /* ARI: Test stepping: 0:B, 1:unknown, 2,3,4:C, 8:I, >=5:D */ |
||
1471 | if ((rev & 0x0F) < 2) |
||
1472 | s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */ |
||
1473 | break; |
||
1474 | case 0x03: |
||
1475 | /* ISA - 801 */ |
||
1476 | s3_chiptype = S3_801; |
||
1477 | /* Stepping same as 805, just ISA */ |
||
1478 | if ((rev & 0x0F) < 2) |
||
1479 | s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */ |
||
1480 | break; |
||
1481 | } |
||
1482 | break; |
||
1483 | case 0x90: |
||
1484 | s3_chiptype = S3_928; |
||
1485 | if ((rev & 0x0F) < 4) /* ARI: Stepping D or below */ |
||
1486 | s3_flags |= S3_OLD_STEPPING; /* can't handle 1152 width */ |
||
1487 | break; |
||
1488 | case 0xB0: |
||
1489 | /* 928P */ |
||
1490 | s3_chiptype = S3_928; |
||
1491 | break; |
||
1492 | case 0xC0: |
||
1493 | s3_chiptype = S3_864; |
||
1494 | break; |
||
1495 | case 0xD0: |
||
1496 | s3_chiptype = S3_964; |
||
1497 | break; |
||
1498 | case 0xE0: |
||
1499 | switch (id & 0xFFF0) { |
||
1500 | case 0x10E0: |
||
1501 | s3_chiptype = S3_TRIO32; |
||
1502 | break; |
||
1503 | case 0x3DE0: /* ViRGE/VX ID */ |
||
1504 | case 0x31E0: /* ViRGE ID */ |
||
1505 | case 0x01E0: /* S3Trio64V2/DX ... any others? */ |
||
1506 | case 0x04E0: |
||
1507 | case 0x11E0: |
||
1508 | if (rev & 0x0400) |
||
1509 | s3_chiptype = S3_765; |
||
1510 | else |
||
1511 | s3_chiptype = S3_TRIO64; |
||
1512 | break; |
||
1513 | case 0x80E0: |
||
1514 | s3_chiptype = S3_866; |
||
1515 | break; |
||
1516 | case 0x90E0: |
||
1517 | s3_chiptype = S3_868; |
||
1518 | break; |
||
1519 | case 0xF0E0: /* XXXX From data book; XF86 says 0xB0E0? */ |
||
1520 | s3_chiptype = S3_968; |
||
1521 | break; |
||
1522 | } |
||
1523 | } |
||
1524 | if (s3_chiptype == -1) { |
||
1525 | printk(KERN_ERR "svgalib: S3: Unknown chip id %02x\n", |
||
1526 | id); |
||
1527 | return -1; |
||
1528 | } |
||
1529 | if (s3_chiptype <= S3_924) { |
||
1530 | if ((config & 0x20) != 0) |
||
1531 | s3_memory = 512; |
||
1532 | else |
||
1533 | s3_memory = 1024; |
||
1534 | } else { |
||
1535 | /* look at bits 5, 6 and 7 */ |
||
1536 | switch ((config & 0xE0) >> 5) { |
||
1537 | case 0: |
||
1538 | s3_memory = 4096; |
||
1539 | break; |
||
1540 | case 2: |
||
1541 | s3_memory = 3072; |
||
1542 | break; |
||
1543 | case 3: |
||
1544 | s3_memory = 8192; |
||
1545 | break; |
||
1546 | case 4: |
||
1547 | s3_memory = 2048; |
||
1548 | break; |
||
1549 | case 5: |
||
1550 | s3_memory = 6144; |
||
1551 | break; |
||
1552 | case 6: |
||
1553 | s3_memory = 1024; |
||
1554 | break; |
||
1555 | case 7: |
||
1556 | s3_memory = 512; |
||
1557 | break; /* Trio32 */ |
||
1558 | } |
||
1559 | } |
||
1560 | |||
1561 | if ((config & 0x03) < 3) /* XXXX 928P is ignored */ |
||
1562 | s3_flags |= S3_LOCALBUS; |
||
1563 | } |
||
1564 | |||
1565 | if (__svgalib_driver_report) { |
||
1566 | printk(KERN_INFO "svgalib: Using S3 driver (%s, %dK).\n", s3_chipname[s3_chiptype], |
||
1567 | s3_memory); |
||
1568 | if (s3_flags & S3_OLD_STEPPING) |
||
1569 | printk(KERN_INFO "svgalib: Chip revision cannot handle modes with width 1152.\n"); |
||
1570 | if (s3_chiptype > S3_TRIO64) { |
||
1571 | printk(KERN_INFO "svgalib: s3: chipsets newer than S3 Trio64 is not supported well yet.\n"); |
||
1572 | } |
||
1573 | |||
1574 | } |
||
1575 | /* begin: Initialize cardspecs. */ |
||
1576 | #ifdef S3_LINEAR_SUPPORT |
||
1577 | if (s3_chiptype > S3_805) { |
||
1578 | int found_pciconfig; |
||
1579 | unsigned long pci_conf[64]; |
||
1580 | |||
1581 | found_pciconfig = __svgalib_pci_find_vendor_vga(0x5333, pci_conf, 0); |
||
1582 | if (!found_pciconfig) |
||
1583 | s3_linear_base = pci_conf[4] & 0xFF800000; |
||
1584 | } |
||
1585 | |||
1586 | s3_cr59 = s3_linear_base >> 24; |
||
1587 | s3_cr5A = (s3_linear_base >> 16); |
||
1588 | if (! (s3_cr59 | s3_cr5A)) { |
||
1589 | s3_cr59 = __svgalib_inCR(0x59); |
||
1590 | s3_cr5A = __svgalib_inCR(0x5A); |
||
1591 | if (!s3_cr59) { |
||
1592 | s3_cr59 = 0xF3000000 >> 24; |
||
1593 | s3_cr5A = (0xF3000000 >> 16); |
||
1594 | } |
||
1595 | s3_linear_base = (s3_cr59 << 24) | (s3_cr5A << 16); |
||
1596 | } |
||
1597 | s3_linear_opt |= 0x10; |
||
1598 | switch (s3_memory) { |
||
1599 | case 512 : |
||
1600 | case 1024 : |
||
1601 | s3_linear_opt |= 0x01; |
||
1602 | break; |
||
1603 | case 2048 : |
||
1604 | s3_linear_opt |= 0x02; |
||
1605 | break; |
||
1606 | case 3072 : |
||
1607 | case 4096 : |
||
1608 | case 6144 : |
||
1609 | case 8192 : |
||
1610 | s3_linear_opt |= 0x03; |
||
1611 | break; |
||
1612 | default : |
||
1613 | s3_linear_opt = 0x14; /* like XFree */ |
||
1614 | } |
||
1615 | #endif |
||
1616 | |||
1617 | cardspecs = malloc(sizeof(CardSpecs)); |
||
1618 | cardspecs->videoMemory = s3_memory; |
||
1619 | cardspecs->nClocks = 0; |
||
1620 | /* cardspecs->maxHorizontalCrtc = 2040; SL: kills 800x600x32k and above */ |
||
1621 | cardspecs->maxHorizontalCrtc = 4088; |
||
1622 | cardspecs->flags = INTERLACE_DIVIDE_VERT; |
||
1623 | |||
1624 | dac_used = NULL; |
||
1625 | clk_used = NULL; |
||
1626 | |||
1627 | #ifdef INCLUDE_S3_TRIO64_DAC |
||
1628 | if ((s3_chiptype == S3_TRIO64 || s3_chiptype == S3_765) && dac_used == NULL) |
||
1629 | dac_used = &__svgalib_Trio64_methods; |
||
1630 | #endif |
||
1631 | |||
1632 | if (dac_used == NULL) { |
||
1633 | /* Not supported. */ |
||
1634 | printk(KERN_ERR "svgalib: s3: Assuming S3_SDAC.\n"); |
||
1635 | dac_used = &__svgalib_S3_SDAC_methods; |
||
1636 | dac_used->initialize(); |
||
1637 | } |
||
1638 | if (clk_used) |
||
1639 | clk_used->initialize(cardspecs, dac_used); |
||
1640 | |||
1641 | dac_used->qualifyCardSpecs(cardspecs, dac_speed); |
||
1642 | |||
1643 | /* Initialize standard clocks for unknown DAC. */ |
||
1644 | if ((!(cardspecs->flags & CLOCK_PROGRAMMABLE)) |
||
1645 | && cardspecs->nClocks == 0) { |
||
1646 | /* |
||
1647 | * Almost all cards have 25 and 28 MHz on VGA clocks 0 and 1, |
||
1648 | * so use these for an unknown DAC, yielding 640x480x256. |
||
1649 | */ |
||
1650 | cardspecs->nClocks = 2; |
||
1651 | cardspecs->clocks = malloc(sizeof(int) * 2); |
||
1652 | cardspecs->clocks[0] = 25175; |
||
1653 | cardspecs->clocks[1] = 28322; |
||
1654 | } |
||
1655 | /* Limit pixel clocks according to chip specifications. */ |
||
1656 | if (s3_chiptype == S3_864 || s3_chiptype == S3_868) { |
||
1657 | /* Limit max clocks according to 95 MHz DCLK spec. */ |
||
1658 | /* SL: might just be 95000 for 4/8bpp since no pixmux'ing */ |
||
1659 | LIMIT(cardspecs->maxPixelClock4bpp, 95000 * 2); |
||
1660 | LIMIT(cardspecs->maxPixelClock8bpp, 95000 * 2); |
||
1661 | LIMIT(cardspecs->maxPixelClock16bpp, 95000); |
||
1662 | /* see explanation below */ |
||
1663 | LIMIT(cardspecs->maxPixelClock24bpp, 36000); |
||
1664 | /* |
||
1665 | * The official 32bpp limit is 47500, but we allow |
||
1666 | * 50 MHz for VESA 800x600 timing (actually the |
||
1667 | * S3-864 doesn't have the horizontal timing range |
||
1668 | * to run unmodified VESA 800x600 72 Hz timings). |
||
1669 | */ |
||
1670 | LIMIT(cardspecs->maxPixelClock32bpp, 50000); |
||
1671 | } |
||
1672 | #ifndef S3_16_COLORS |
||
1673 | cardspecs->maxPixelClock4bpp = 0; /* 16-color doesn't work. */ |
||
1674 | #endif |
||
1675 | |||
1676 | /* end: Initialize cardspecs. */ |
||
1677 | |||
1678 | __svgalib_driverspecs = &__svgalib_s3_driverspecs; |
||
1679 | |||
1680 | __svgalib_banked_mem_base=0xa0000; |
||
1681 | __svgalib_banked_mem_size=0x10000; |
||
1682 | #ifdef S3_LINEAR_SUPPORT |
||
1683 | __svgalib_linear_mem_base=s3_linear_base; |
||
1684 | __svgalib_linear_mem_size=s3_memory*0x400; |
||
1685 | #endif |
||
1686 | |||
1687 | sleep(4); |
||
1688 | |||
1689 | return 0; |
||
1690 | |||
1691 | } |