Pull bugzilla-5452 into release branch
[linux-2.6] / drivers / video / savage / savagefb_driver.c
1 /*
2  * linux/drivers/video/savagefb.c -- S3 Savage Framebuffer Driver
3  *
4  * Copyright (c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>
5  *                          Sven Neumann <neo@directfb.org>
6  *
7  *
8  * Card specific code is based on XFree86's savage driver.
9  * Framebuffer framework code is based on code of cyber2000fb and tdfxfb.
10  *
11  * This file is subject to the terms and conditions of the GNU General
12  * Public License.  See the file COPYING in the main directory of this
13  * archive for more details.
14  *
15  * 0.4.0 (neo)
16  *  - hardware accelerated clear and move
17  *
18  * 0.3.2 (dok)
19  *  - wait for vertical retrace before writing to cr67
20  *    at the beginning of savagefb_set_par
21  *  - use synchronization registers cr23 and cr26
22  *
23  * 0.3.1 (dok)
24  *  - reset 3D engine
25  *  - don't return alpha bits for 32bit format
26  *
27  * 0.3.0 (dok)
28  *  - added WaitIdle functions for all Savage types
29  *  - do WaitIdle before mode switching
30  *  - code cleanup
31  *
32  * 0.2.0 (dok)
33  *  - first working version
34  *
35  *
36  * TODO
37  * - clock validations in decode_var
38  *
39  * BUGS
40  * - white margin on bootup
41  *
42  */
43
44 #include <linux/config.h>
45 #include <linux/module.h>
46 #include <linux/kernel.h>
47 #include <linux/errno.h>
48 #include <linux/string.h>
49 #include <linux/mm.h>
50 #include <linux/tty.h>
51 #include <linux/slab.h>
52 #include <linux/delay.h>
53 #include <linux/fb.h>
54 #include <linux/pci.h>
55 #include <linux/init.h>
56 #include <linux/console.h>
57
58 #include <asm/io.h>
59 #include <asm/irq.h>
60 #include <asm/pgtable.h>
61 #include <asm/system.h>
62 #include <asm/uaccess.h>
63
64 #ifdef CONFIG_MTRR
65 #include <asm/mtrr.h>
66 #endif
67
68 #include "savagefb.h"
69
70
71 #define SAVAGEFB_VERSION "0.4.0_2.6"
72
73 /* --------------------------------------------------------------------- */
74
75
76 static char *mode_option __devinitdata = NULL;
77
78 #ifdef MODULE
79
80 MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>");
81 MODULE_LICENSE("GPL");
82 MODULE_DESCRIPTION("FBDev driver for S3 Savage PCI/AGP Chips");
83
84 #endif
85
86
87 /* --------------------------------------------------------------------- */
88
89 static void vgaHWSeqReset (struct savagefb_par *par, int start)
90 {
91         if (start)
92                 VGAwSEQ (0x00, 0x01, par);      /* Synchronous Reset */
93         else
94                 VGAwSEQ (0x00, 0x03, par);      /* End Reset */
95 }
96
97 static void vgaHWProtect (struct savagefb_par *par, int on)
98 {
99         unsigned char tmp;
100
101         if (on) {
102                 /*
103                  * Turn off screen and disable sequencer.
104                  */
105                 tmp = VGArSEQ (0x01, par);
106
107                 vgaHWSeqReset (par, 1);         /* start synchronous reset */
108                 VGAwSEQ (0x01, tmp | 0x20, par);/* disable the display */
109
110                 VGAenablePalette(par);
111         } else {
112                 /*
113                  * Reenable sequencer, then turn on screen.
114                  */
115
116                 tmp = VGArSEQ (0x01, par);
117
118                 VGAwSEQ (0x01, tmp & ~0x20, par);/* reenable display */
119                 vgaHWSeqReset (par, 0);         /* clear synchronous reset */
120
121                 VGAdisablePalette(par);
122         }
123 }
124
125 static void vgaHWRestore (struct savagefb_par  *par)
126 {
127         int i;
128
129         VGAwMISC (par->MiscOutReg, par);
130
131         for (i = 1; i < 5; i++)
132                 VGAwSEQ (i, par->Sequencer[i], par);
133
134         /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or
135            CRTC[17] */
136         VGAwCR (17, par->CRTC[17] & ~0x80, par);
137
138         for (i = 0; i < 25; i++)
139                 VGAwCR (i, par->CRTC[i], par);
140
141         for (i = 0; i < 9; i++)
142                 VGAwGR (i, par->Graphics[i], par);
143
144         VGAenablePalette(par);
145
146         for (i = 0; i < 21; i++)
147                 VGAwATTR (i, par->Attribute[i], par);
148
149         VGAdisablePalette(par);
150 }
151
152 static void vgaHWInit (struct fb_var_screeninfo *var,
153                        struct savagefb_par            *par,
154                        struct xtimings                *timings)
155 {
156         par->MiscOutReg = 0x23;
157
158         if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
159                 par->MiscOutReg |= 0x40;
160
161         if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
162                 par->MiscOutReg |= 0x80;
163
164         /*
165          * Time Sequencer
166          */
167         par->Sequencer[0x00] = 0x00;
168         par->Sequencer[0x01] = 0x01;
169         par->Sequencer[0x02] = 0x0F;
170         par->Sequencer[0x03] = 0x00;          /* Font select */
171         par->Sequencer[0x04] = 0x0E;          /* Misc */
172
173         /*
174          * CRTC Controller
175          */
176         par->CRTC[0x00] = (timings->HTotal >> 3) - 5;
177         par->CRTC[0x01] = (timings->HDisplay >> 3) - 1;
178         par->CRTC[0x02] = (timings->HSyncStart >> 3) - 1;
179         par->CRTC[0x03] = (((timings->HSyncEnd >> 3)  - 1) & 0x1f) | 0x80;
180         par->CRTC[0x04] = (timings->HSyncStart >> 3);
181         par->CRTC[0x05] = ((((timings->HSyncEnd >> 3) - 1) & 0x20) << 2) |
182                 (((timings->HSyncEnd >> 3)) & 0x1f);
183         par->CRTC[0x06] = (timings->VTotal - 2) & 0xFF;
184         par->CRTC[0x07] = (((timings->VTotal - 2) & 0x100) >> 8) |
185                 (((timings->VDisplay - 1) & 0x100) >> 7) |
186                 ((timings->VSyncStart & 0x100) >> 6) |
187                 (((timings->VSyncStart - 1) & 0x100) >> 5) |
188                 0x10 |
189                 (((timings->VTotal - 2) & 0x200) >> 4) |
190                 (((timings->VDisplay - 1) & 0x200) >> 3) |
191                 ((timings->VSyncStart & 0x200) >> 2);
192         par->CRTC[0x08] = 0x00;
193         par->CRTC[0x09] = (((timings->VSyncStart - 1) & 0x200) >> 4) | 0x40;
194
195         if (timings->dblscan)
196                 par->CRTC[0x09] |= 0x80;
197
198         par->CRTC[0x0a] = 0x00;
199         par->CRTC[0x0b] = 0x00;
200         par->CRTC[0x0c] = 0x00;
201         par->CRTC[0x0d] = 0x00;
202         par->CRTC[0x0e] = 0x00;
203         par->CRTC[0x0f] = 0x00;
204         par->CRTC[0x10] = timings->VSyncStart & 0xff;
205         par->CRTC[0x11] = (timings->VSyncEnd & 0x0f) | 0x20;
206         par->CRTC[0x12] = (timings->VDisplay - 1) & 0xff;
207         par->CRTC[0x13] = var->xres_virtual >> 4;
208         par->CRTC[0x14] = 0x00;
209         par->CRTC[0x15] = (timings->VSyncStart - 1) & 0xff;
210         par->CRTC[0x16] = (timings->VSyncEnd - 1) & 0xff;
211         par->CRTC[0x17] = 0xc3;
212         par->CRTC[0x18] = 0xff;
213
214         /*
215          * are these unnecessary?
216          * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
217          * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
218          */
219
220         /*
221          * Graphics Display Controller
222          */
223         par->Graphics[0x00] = 0x00;
224         par->Graphics[0x01] = 0x00;
225         par->Graphics[0x02] = 0x00;
226         par->Graphics[0x03] = 0x00;
227         par->Graphics[0x04] = 0x00;
228         par->Graphics[0x05] = 0x40;
229         par->Graphics[0x06] = 0x05;   /* only map 64k VGA memory !!!! */
230         par->Graphics[0x07] = 0x0F;
231         par->Graphics[0x08] = 0xFF;
232
233
234         par->Attribute[0x00]  = 0x00; /* standard colormap translation */
235         par->Attribute[0x01]  = 0x01;
236         par->Attribute[0x02]  = 0x02;
237         par->Attribute[0x03]  = 0x03;
238         par->Attribute[0x04]  = 0x04;
239         par->Attribute[0x05]  = 0x05;
240         par->Attribute[0x06]  = 0x06;
241         par->Attribute[0x07]  = 0x07;
242         par->Attribute[0x08]  = 0x08;
243         par->Attribute[0x09]  = 0x09;
244         par->Attribute[0x0a] = 0x0A;
245         par->Attribute[0x0b] = 0x0B;
246         par->Attribute[0x0c] = 0x0C;
247         par->Attribute[0x0d] = 0x0D;
248         par->Attribute[0x0e] = 0x0E;
249         par->Attribute[0x0f] = 0x0F;
250         par->Attribute[0x10] = 0x41;
251         par->Attribute[0x11] = 0xFF;
252         par->Attribute[0x12] = 0x0F;
253         par->Attribute[0x13] = 0x00;
254         par->Attribute[0x14] = 0x00;
255 }
256
257 /* -------------------- Hardware specific routines ------------------------- */
258
259 /*
260  * Hardware Acceleration for SavageFB
261  */
262
263 /* Wait for fifo space */
264 static void
265 savage3D_waitfifo(struct savagefb_par *par, int space)
266 {
267         int slots = MAXFIFO - space;
268
269         while ((savage_in32(0x48C00, par) & 0x0000ffff) > slots);
270 }
271
272 static void
273 savage4_waitfifo(struct savagefb_par *par, int space)
274 {
275         int slots = MAXFIFO - space;
276
277         while ((savage_in32(0x48C60, par) & 0x001fffff) > slots);
278 }
279
280 static void
281 savage2000_waitfifo(struct savagefb_par *par, int space)
282 {
283         int slots = MAXFIFO - space;
284
285         while ((savage_in32(0x48C60, par) & 0x0000ffff) > slots);
286 }
287
288 /* Wait for idle accelerator */
289 static void
290 savage3D_waitidle(struct savagefb_par *par)
291 {
292         while ((savage_in32(0x48C00, par) & 0x0008ffff) != 0x80000);
293 }
294
295 static void
296 savage4_waitidle(struct savagefb_par *par)
297 {
298         while ((savage_in32(0x48C60, par) & 0x00a00000) != 0x00a00000);
299 }
300
301 static void
302 savage2000_waitidle(struct savagefb_par *par)
303 {
304         while ((savage_in32(0x48C60, par) & 0x009fffff));
305 }
306
307
308 static void
309 SavageSetup2DEngine (struct savagefb_par  *par)
310 {
311         unsigned long GlobalBitmapDescriptor;
312
313         GlobalBitmapDescriptor = 1 | 8 | BCI_BD_BW_DISABLE;
314         BCI_BD_SET_BPP (GlobalBitmapDescriptor, par->depth);
315         BCI_BD_SET_STRIDE (GlobalBitmapDescriptor, par->vwidth);
316
317         switch(par->chip) {
318         case S3_SAVAGE3D:
319         case S3_SAVAGE_MX:
320                 /* Disable BCI */
321                 savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);
322                 /* Setup BCI command overflow buffer */
323                 savage_out32(0x48C14,
324                              (par->cob_offset >> 11) | (par->cob_index << 29),
325                              par);
326                 /* Program shadow status update. */
327                 savage_out32(0x48C10, 0x78207220, par);
328                 savage_out32(0x48C0C, 0, par);
329                 /* Enable BCI and command overflow buffer */
330                 savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par);
331                 break;
332         case S3_SAVAGE4:
333         case S3_PROSAVAGE:
334         case S3_SUPERSAVAGE:
335                 /* Disable BCI */
336                 savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);
337                 /* Program shadow status update */
338                 savage_out32(0x48C10, 0x00700040, par);
339                 savage_out32(0x48C0C, 0, par);
340                 /* Enable BCI without the COB */
341                 savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x08, par);
342                 break;
343         case S3_SAVAGE2000:
344                 /* Disable BCI */
345                 savage_out32(0x48C18, 0, par);
346                 /* Setup BCI command overflow buffer */
347                 savage_out32(0x48C18,
348                              (par->cob_offset >> 7) | (par->cob_index),
349                              par);
350                 /* Disable shadow status update */
351                 savage_out32(0x48A30, 0, par);
352                 /* Enable BCI and command overflow buffer */
353                 savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x00280000,
354                              par);
355                 break;
356             default:
357                 break;
358         }
359         /* Turn on 16-bit register access. */
360         vga_out8(0x3d4, 0x31, par);
361         vga_out8(0x3d5, 0x0c, par);
362
363         /* Set stride to use GBD. */
364         vga_out8 (0x3d4, 0x50, par);
365         vga_out8 (0x3d5, vga_in8(0x3d5, par) | 0xC1, par);
366
367         /* Enable 2D engine. */
368         vga_out8 (0x3d4, 0x40, par);
369         vga_out8 (0x3d5, 0x01, par);
370
371         savage_out32 (MONO_PAT_0, ~0, par);
372         savage_out32 (MONO_PAT_1, ~0, par);
373
374         /* Setup plane masks */
375         savage_out32 (0x8128, ~0, par); /* enable all write planes */
376         savage_out32 (0x812C, ~0, par); /* enable all read planes */
377         savage_out16 (0x8134, 0x27, par);
378         savage_out16 (0x8136, 0x07, par);
379
380         /* Now set the GBD */
381         par->bci_ptr = 0;
382         par->SavageWaitFifo (par, 4);
383
384         BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD1 );
385         BCI_SEND( 0 );
386         BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD2 );
387         BCI_SEND( GlobalBitmapDescriptor );
388 }
389
390
391 static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1,
392                             int min_n2, int max_n2, long freq_min,
393                             long freq_max, unsigned int *mdiv,
394                             unsigned int *ndiv, unsigned int *r)
395 {
396         long diff, best_diff;
397         unsigned int m;
398         unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2;
399
400         if (freq < freq_min / (1 << max_n2)) {
401                 printk (KERN_ERR "invalid frequency %ld Khz\n", freq);
402                 freq = freq_min / (1 << max_n2);
403         }
404         if (freq > freq_max / (1 << min_n2)) {
405                 printk (KERN_ERR "invalid frequency %ld Khz\n", freq);
406                 freq = freq_max / (1 << min_n2);
407         }
408
409         /* work out suitable timings */
410         best_diff = freq;
411
412         for (n2=min_n2; n2<=max_n2; n2++) {
413                 for (n1=min_n1+2; n1<=max_n1+2; n1++) {
414                         m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
415                                 BASE_FREQ;
416                         if (m < min_m+2 || m > 127+2)
417                                 continue;
418                         if ((m * BASE_FREQ >= freq_min * n1) &&
419                             (m * BASE_FREQ <= freq_max * n1)) {
420                                 diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
421                                 if (diff < 0)
422                                         diff = -diff;
423                                 if (diff < best_diff) {
424                                         best_diff = diff;
425                                         best_m = m;
426                                         best_n1 = n1;
427                                         best_n2 = n2;
428                                 }
429                         }
430                 }
431         }
432
433         *ndiv = best_n1 - 2;
434         *r = best_n2;
435         *mdiv = best_m - 2;
436 }
437
438 static int common_calc_clock(long freq, int min_m, int min_n1, int max_n1,
439                              int min_n2, int max_n2, long freq_min,
440                              long freq_max, unsigned char *mdiv,
441                              unsigned char *ndiv)
442 {
443         long diff, best_diff;
444         unsigned int m;
445         unsigned char n1, n2;
446         unsigned char best_n1 = 16+2, best_n2 = 2, best_m = 125+2;
447
448         best_diff = freq;
449
450         for (n2 = min_n2; n2 <= max_n2; n2++) {
451                 for (n1 = min_n1+2; n1 <= max_n1+2; n1++) {
452                         m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
453                                 BASE_FREQ;
454                         if (m < min_m + 2 || m > 127+2)
455                                 continue;
456                         if((m * BASE_FREQ >= freq_min * n1) &&
457                            (m * BASE_FREQ <= freq_max * n1)) {
458                                 diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
459                                 if(diff < 0)
460                                         diff = -diff;
461                                 if(diff < best_diff) {
462                                         best_diff = diff;
463                                         best_m = m;
464                                         best_n1 = n1;
465                                         best_n2 = n2;
466                                 }
467                         }
468                 }
469         }
470
471         if(max_n1 == 63)
472                 *ndiv = (best_n1 - 2) | (best_n2 << 6);
473         else
474                 *ndiv = (best_n1 - 2) | (best_n2 << 5);
475
476         *mdiv = best_m - 2;
477
478         return 0;
479 }
480
481 #ifdef SAVAGEFB_DEBUG
482 /* This function is used to debug, it prints out the contents of s3 regs */
483
484 static void SavagePrintRegs(void)
485 {
486         unsigned char i;
487         int vgaCRIndex = 0x3d4;
488         int vgaCRReg = 0x3d5;
489
490         printk(KERN_DEBUG "SR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE "
491                "xF" );
492
493         for( i = 0; i < 0x70; i++ ) {
494                 if( !(i % 16) )
495                         printk(KERN_DEBUG "\nSR%xx ", i >> 4 );
496                 vga_out8( 0x3c4, i, par);
497                 printk(KERN_DEBUG " %02x", vga_in8(0x3c5, par) );
498         }
499
500         printk(KERN_DEBUG "\n\nCR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC "
501                "xD xE xF" );
502
503         for( i = 0; i < 0xB7; i++ ) {
504                 if( !(i % 16) )
505                         printk(KERN_DEBUG "\nCR%xx ", i >> 4 );
506                 vga_out8( vgaCRIndex, i, par);
507                 printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg, par) );
508         }
509
510         printk(KERN_DEBUG "\n\n");
511 }
512 #endif
513
514 /* --------------------------------------------------------------------- */
515
516 static void savage_get_default_par(struct savagefb_par *par)
517 {
518         unsigned char cr3a, cr53, cr66;
519
520         vga_out16 (0x3d4, 0x4838, par);
521         vga_out16 (0x3d4, 0xa039, par);
522         vga_out16 (0x3c4, 0x0608, par);
523
524         vga_out8 (0x3d4, 0x66, par);
525         cr66 = vga_in8 (0x3d5, par);
526         vga_out8 (0x3d5, cr66 | 0x80, par);
527         vga_out8 (0x3d4, 0x3a, par);
528         cr3a = vga_in8 (0x3d5, par);
529         vga_out8 (0x3d5, cr3a | 0x80, par);
530         vga_out8 (0x3d4, 0x53, par);
531         cr53 = vga_in8 (0x3d5, par);
532         vga_out8 (0x3d5, cr53 & 0x7f, par);
533
534         vga_out8 (0x3d4, 0x66, par);
535         vga_out8 (0x3d5, cr66, par);
536         vga_out8 (0x3d4, 0x3a, par);
537         vga_out8 (0x3d5, cr3a, par);
538
539         vga_out8 (0x3d4, 0x66, par);
540         vga_out8 (0x3d5, cr66, par);
541         vga_out8 (0x3d4, 0x3a, par);
542         vga_out8 (0x3d5, cr3a, par);
543
544         /* unlock extended seq regs */
545         vga_out8 (0x3c4, 0x08, par);
546         par->SR08 = vga_in8 (0x3c5, par);
547         vga_out8 (0x3c5, 0x06, par);
548
549         /* now save all the extended regs we need */
550         vga_out8 (0x3d4, 0x31, par);
551         par->CR31 = vga_in8 (0x3d5, par);
552         vga_out8 (0x3d4, 0x32, par);
553         par->CR32 = vga_in8 (0x3d5, par);
554         vga_out8 (0x3d4, 0x34, par);
555         par->CR34 = vga_in8 (0x3d5, par);
556         vga_out8 (0x3d4, 0x36, par);
557         par->CR36 = vga_in8 (0x3d5, par);
558         vga_out8 (0x3d4, 0x3a, par);
559         par->CR3A = vga_in8 (0x3d5, par);
560         vga_out8 (0x3d4, 0x40, par);
561         par->CR40 = vga_in8 (0x3d5, par);
562         vga_out8 (0x3d4, 0x42, par);
563         par->CR42 = vga_in8 (0x3d5, par);
564         vga_out8 (0x3d4, 0x45, par);
565         par->CR45 = vga_in8 (0x3d5, par);
566         vga_out8 (0x3d4, 0x50, par);
567         par->CR50 = vga_in8 (0x3d5, par);
568         vga_out8 (0x3d4, 0x51, par);
569         par->CR51 = vga_in8 (0x3d5, par);
570         vga_out8 (0x3d4, 0x53, par);
571         par->CR53 = vga_in8 (0x3d5, par);
572         vga_out8 (0x3d4, 0x58, par);
573         par->CR58 = vga_in8 (0x3d5, par);
574         vga_out8 (0x3d4, 0x60, par);
575         par->CR60 = vga_in8 (0x3d5, par);
576         vga_out8 (0x3d4, 0x66, par);
577         par->CR66 = vga_in8 (0x3d5, par);
578         vga_out8 (0x3d4, 0x67, par);
579         par->CR67 = vga_in8 (0x3d5, par);
580         vga_out8 (0x3d4, 0x68, par);
581         par->CR68 = vga_in8 (0x3d5, par);
582         vga_out8 (0x3d4, 0x69, par);
583         par->CR69 = vga_in8 (0x3d5, par);
584         vga_out8 (0x3d4, 0x6f, par);
585         par->CR6F = vga_in8 (0x3d5, par);
586
587         vga_out8 (0x3d4, 0x33, par);
588         par->CR33 = vga_in8 (0x3d5, par);
589         vga_out8 (0x3d4, 0x86, par);
590         par->CR86 = vga_in8 (0x3d5, par);
591         vga_out8 (0x3d4, 0x88, par);
592         par->CR88 = vga_in8 (0x3d5, par);
593         vga_out8 (0x3d4, 0x90, par);
594         par->CR90 = vga_in8 (0x3d5, par);
595         vga_out8 (0x3d4, 0x91, par);
596         par->CR91 = vga_in8 (0x3d5, par);
597         vga_out8 (0x3d4, 0xb0, par);
598         par->CRB0 = vga_in8 (0x3d5, par) | 0x80;
599
600         /* extended mode timing regs */
601         vga_out8 (0x3d4, 0x3b, par);
602         par->CR3B = vga_in8 (0x3d5, par);
603         vga_out8 (0x3d4, 0x3c, par);
604         par->CR3C = vga_in8 (0x3d5, par);
605         vga_out8 (0x3d4, 0x43, par);
606         par->CR43 = vga_in8 (0x3d5, par);
607         vga_out8 (0x3d4, 0x5d, par);
608         par->CR5D = vga_in8 (0x3d5, par);
609         vga_out8 (0x3d4, 0x5e, par);
610         par->CR5E = vga_in8 (0x3d5, par);
611         vga_out8 (0x3d4, 0x65, par);
612         par->CR65 = vga_in8 (0x3d5, par);
613
614         /* save seq extended regs for DCLK PLL programming */
615         vga_out8 (0x3c4, 0x0e, par);
616         par->SR0E = vga_in8 (0x3c5, par);
617         vga_out8 (0x3c4, 0x0f, par);
618         par->SR0F = vga_in8 (0x3c5, par);
619         vga_out8 (0x3c4, 0x10, par);
620         par->SR10 = vga_in8 (0x3c5, par);
621         vga_out8 (0x3c4, 0x11, par);
622         par->SR11 = vga_in8 (0x3c5, par);
623         vga_out8 (0x3c4, 0x12, par);
624         par->SR12 = vga_in8 (0x3c5, par);
625         vga_out8 (0x3c4, 0x13, par);
626         par->SR13 = vga_in8 (0x3c5, par);
627         vga_out8 (0x3c4, 0x29, par);
628         par->SR29 = vga_in8 (0x3c5, par);
629
630         vga_out8 (0x3c4, 0x15, par);
631         par->SR15 = vga_in8 (0x3c5, par);
632         vga_out8 (0x3c4, 0x30, par);
633         par->SR30 = vga_in8 (0x3c5, par);
634         vga_out8 (0x3c4, 0x18, par);
635         par->SR18 = vga_in8 (0x3c5, par);
636
637         /* Save flat panel expansion regsters. */
638         if (par->chip == S3_SAVAGE_MX) {
639                 int i;
640
641                 for (i = 0; i < 8; i++) {
642                         vga_out8 (0x3c4, 0x54+i, par);
643                         par->SR54[i] = vga_in8 (0x3c5, par);
644                 }
645         }
646
647         vga_out8 (0x3d4, 0x66, par);
648         cr66 = vga_in8 (0x3d5, par);
649         vga_out8 (0x3d5, cr66 | 0x80, par);
650         vga_out8 (0x3d4, 0x3a, par);
651         cr3a = vga_in8 (0x3d5, par);
652         vga_out8 (0x3d5, cr3a | 0x80, par);
653
654         /* now save MIU regs */
655         if (par->chip != S3_SAVAGE_MX) {
656                 par->MMPR0 = savage_in32(FIFO_CONTROL_REG, par);
657                 par->MMPR1 = savage_in32(MIU_CONTROL_REG, par);
658                 par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG, par);
659                 par->MMPR3 = savage_in32(MISC_TIMEOUT_REG, par);
660         }
661
662         vga_out8 (0x3d4, 0x3a, par);
663         vga_out8 (0x3d5, cr3a, par);
664         vga_out8 (0x3d4, 0x66, par);
665         vga_out8 (0x3d5, cr66, par);
666 }
667
668 static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
669 {
670         var->xres = var->xres_virtual = modedb->xres;
671         var->yres = modedb->yres;
672         if (var->yres_virtual < var->yres)
673             var->yres_virtual = var->yres;
674         var->xoffset = var->yoffset = 0;
675         var->pixclock = modedb->pixclock;
676         var->left_margin = modedb->left_margin;
677         var->right_margin = modedb->right_margin;
678         var->upper_margin = modedb->upper_margin;
679         var->lower_margin = modedb->lower_margin;
680         var->hsync_len = modedb->hsync_len;
681         var->vsync_len = modedb->vsync_len;
682         var->sync = modedb->sync;
683         var->vmode = modedb->vmode;
684 }
685
686 static int savagefb_check_var (struct fb_var_screeninfo   *var,
687                                struct fb_info *info)
688 {
689         struct savagefb_par *par = info->par;
690         int memlen, vramlen, mode_valid = 0;
691
692         DBG("savagefb_check_var");
693
694         var->transp.offset = 0;
695         var->transp.length = 0;
696         switch (var->bits_per_pixel) {
697         case 8:
698                 var->red.offset = var->green.offset =
699                         var->blue.offset = 0;
700                 var->red.length = var->green.length =
701                         var->blue.length = var->bits_per_pixel;
702                 break;
703         case 16:
704                 var->red.offset = 11;
705                 var->red.length = 5;
706                 var->green.offset = 5;
707                 var->green.length = 6;
708                 var->blue.offset = 0;
709                 var->blue.length = 5;
710                 break;
711         case 32:
712                 var->transp.offset = 24;
713                 var->transp.length = 8;
714                 var->red.offset = 16;
715                 var->red.length = 8;
716                 var->green.offset = 8;
717                 var->green.length = 8;
718                 var->blue.offset = 0;
719                 var->blue.length = 8;
720                 break;
721
722         default:
723                 return -EINVAL;
724         }
725
726         if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
727             !info->monspecs.dclkmax || !fb_validate_mode(var, info))
728                 mode_valid = 1;
729
730         /* calculate modeline if supported by monitor */
731         if (!mode_valid && info->monspecs.gtf) {
732                 if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
733                         mode_valid = 1;
734         }
735
736         if (!mode_valid) {
737                 struct fb_videomode *mode;
738
739                 mode = fb_find_best_mode(var, &info->modelist);
740                 if (mode) {
741                         savage_update_var(var, mode);
742                         mode_valid = 1;
743                 }
744         }
745
746         if (!mode_valid && info->monspecs.modedb_len)
747                 return -EINVAL;
748
749         /* Is the mode larger than the LCD panel? */
750         if (par->SavagePanelWidth &&
751             (var->xres > par->SavagePanelWidth ||
752              var->yres > par->SavagePanelHeight)) {
753                 printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel "
754                         "(%dx%d)\n", var->xres,  var->yres,
755                         par->SavagePanelWidth,
756                         par->SavagePanelHeight);
757                 return -1;
758         }
759
760         if (var->yres_virtual < var->yres)
761                 var->yres_virtual = var->yres;
762         if (var->xres_virtual < var->xres)
763                 var->xres_virtual = var->xres;
764
765         vramlen = info->fix.smem_len;
766
767         memlen = var->xres_virtual * var->bits_per_pixel *
768                 var->yres_virtual / 8;
769         if (memlen > vramlen) {
770                 var->yres_virtual = vramlen * 8 /
771                         (var->xres_virtual * var->bits_per_pixel);
772                 memlen = var->xres_virtual * var->bits_per_pixel *
773                         var->yres_virtual / 8;
774         }
775
776         /* we must round yres/xres down, we already rounded y/xres_virtual up
777            if it was possible. We should return -EINVAL, but I disagree */
778         if (var->yres_virtual < var->yres)
779                 var->yres = var->yres_virtual;
780         if (var->xres_virtual < var->xres)
781                 var->xres = var->xres_virtual;
782         if (var->xoffset + var->xres > var->xres_virtual)
783                 var->xoffset = var->xres_virtual - var->xres;
784         if (var->yoffset + var->yres > var->yres_virtual)
785                 var->yoffset = var->yres_virtual - var->yres;
786
787         return 0;
788 }
789
790
791 static int savagefb_decode_var (struct fb_var_screeninfo   *var,
792                                 struct savagefb_par        *par)
793 {
794         struct xtimings timings;
795         int width, dclk, i, j; /*, refresh; */
796         unsigned int m, n, r;
797         unsigned char tmp = 0;
798         unsigned int pixclock = var->pixclock;
799
800         DBG("savagefb_decode_var");
801
802         memset (&timings, 0, sizeof(timings));
803
804         if (!pixclock) pixclock = 10000;        /* 10ns = 100MHz */
805         timings.Clock = 1000000000 / pixclock;
806         if (timings.Clock < 1) timings.Clock = 1;
807         timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
808         timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
809         timings.HDisplay = var->xres;
810         timings.HSyncStart = timings.HDisplay + var->right_margin;
811         timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
812         timings.HTotal = timings.HSyncEnd + var->left_margin;
813         timings.VDisplay = var->yres;
814         timings.VSyncStart = timings.VDisplay + var->lower_margin;
815         timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
816         timings.VTotal = timings.VSyncEnd + var->upper_margin;
817         timings.sync = var->sync;
818
819
820         par->depth  = var->bits_per_pixel;
821         par->vwidth = var->xres_virtual;
822
823         if (var->bits_per_pixel == 16  &&  par->chip == S3_SAVAGE3D) {
824                 timings.HDisplay *= 2;
825                 timings.HSyncStart *= 2;
826                 timings.HSyncEnd *= 2;
827                 timings.HTotal *= 2;
828         }
829
830         /*
831          * This will allocate the datastructure and initialize all of the
832          * generic VGA registers.
833          */
834         vgaHWInit (var, par, &timings);
835
836         /* We need to set CR67 whether or not we use the BIOS. */
837
838         dclk = timings.Clock;
839         par->CR67 = 0x00;
840
841         switch( var->bits_per_pixel ) {
842         case 8:
843                 if( (par->chip == S3_SAVAGE2000) && (dclk >= 230000) )
844                         par->CR67 = 0x10;       /* 8bpp, 2 pixels/clock */
845                 else
846                         par->CR67 = 0x00;       /* 8bpp, 1 pixel/clock */
847                 break;
848         case 15:
849                 if ( S3_SAVAGE_MOBILE_SERIES(par->chip) ||
850                      ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) )
851                         par->CR67 = 0x30;       /* 15bpp, 2 pixel/clock */
852                 else
853                         par->CR67 = 0x20;       /* 15bpp, 1 pixels/clock */
854                 break;
855         case 16:
856                 if( S3_SAVAGE_MOBILE_SERIES(par->chip) ||
857                     ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) )
858                         par->CR67 = 0x50;       /* 16bpp, 2 pixel/clock */
859                 else
860                         par->CR67 = 0x40;       /* 16bpp, 1 pixels/clock */
861                 break;
862         case 24:
863                 par->CR67 = 0x70;
864                 break;
865         case 32:
866                 par->CR67 = 0xd0;
867                 break;
868         }
869
870         /*
871          * Either BIOS use is disabled, or we failed to find a suitable
872          * match.  Fall back to traditional register-crunching.
873          */
874
875         vga_out8 (0x3d4, 0x3a, par);
876         tmp = vga_in8 (0x3d5, par);
877         if (1 /*FIXME:psav->pci_burst*/)
878                 par->CR3A = (tmp & 0x7f) | 0x15;
879         else
880                 par->CR3A = tmp | 0x95;
881
882         par->CR53 = 0x00;
883         par->CR31 = 0x8c;
884         par->CR66 = 0x89;
885
886         vga_out8 (0x3d4, 0x58, par);
887         par->CR58 = vga_in8 (0x3d5, par) & 0x80;
888         par->CR58 |= 0x13;
889
890         par->SR15 = 0x03 | 0x80;
891         par->SR18 = 0x00;
892         par->CR43 = par->CR45 = par->CR65 = 0x00;
893
894         vga_out8 (0x3d4, 0x40, par);
895         par->CR40 = vga_in8 (0x3d5, par) & ~0x01;
896
897         par->MMPR0 = 0x010400;
898         par->MMPR1 = 0x00;
899         par->MMPR2 = 0x0808;
900         par->MMPR3 = 0x08080810;
901
902         SavageCalcClock (dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r);
903         /* m = 107; n = 4; r = 2; */
904
905         if (par->MCLK <= 0) {
906                 par->SR10 = 255;
907                 par->SR11 = 255;
908         } else {
909                 common_calc_clock (par->MCLK, 1, 1, 31, 0, 3, 135000, 270000,
910                                    &par->SR11, &par->SR10);
911                 /*      par->SR10 = 80; // MCLK == 286000 */
912                 /*      par->SR11 = 125; */
913         }
914
915         par->SR12 = (r << 6) | (n & 0x3f);
916         par->SR13 = m & 0xff;
917         par->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2;
918
919         if (var->bits_per_pixel < 24)
920                 par->MMPR0 -= 0x8000;
921         else
922                 par->MMPR0 -= 0x4000;
923
924         if (timings.interlaced)
925                 par->CR42 = 0x20;
926         else
927                 par->CR42 = 0x00;
928
929         par->CR34 = 0x10; /* display fifo */
930
931         i = ((((timings.HTotal >> 3) - 5) & 0x100) >> 8) |
932                 ((((timings.HDisplay >> 3) - 1) & 0x100) >> 7) |
933                 ((((timings.HSyncStart >> 3) - 1) & 0x100) >> 6) |
934                 ((timings.HSyncStart & 0x800) >> 7);
935
936         if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 64)
937                 i |= 0x08;
938         if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 32)
939                 i |= 0x20;
940
941         j = (par->CRTC[0] + ((i & 0x01) << 8) +
942              par->CRTC[4] + ((i & 0x10) << 4) + 1) / 2;
943
944         if (j - (par->CRTC[4] + ((i & 0x10) << 4)) < 4) {
945                 if (par->CRTC[4] + ((i & 0x10) << 4) + 4 <=
946                     par->CRTC[0] + ((i & 0x01) << 8))
947                         j = par->CRTC[4] + ((i & 0x10) << 4) + 4;
948                 else
949                         j = par->CRTC[0] + ((i & 0x01) << 8) + 1;
950         }
951
952         par->CR3B = j & 0xff;
953         i |= (j & 0x100) >> 2;
954         par->CR3C = (par->CRTC[0] + ((i & 0x01) << 8)) / 2;
955         par->CR5D = i;
956         par->CR5E = (((timings.VTotal - 2) & 0x400) >> 10) |
957                 (((timings.VDisplay - 1) & 0x400) >> 9) |
958                 (((timings.VSyncStart) & 0x400) >> 8) |
959                 (((timings.VSyncStart) & 0x400) >> 6) | 0x40;
960         width = (var->xres_virtual * ((var->bits_per_pixel+7) / 8)) >> 3;
961         par->CR91 = par->CRTC[19] = 0xff & width;
962         par->CR51 = (0x300 & width) >> 4;
963         par->CR90 = 0x80 | (width >> 8);
964         par->MiscOutReg |= 0x0c;
965
966         /* Set frame buffer description. */
967
968         if (var->bits_per_pixel <= 8)
969                 par->CR50 = 0;
970         else if (var->bits_per_pixel <= 16)
971                 par->CR50 = 0x10;
972         else
973                 par->CR50 = 0x30;
974
975         if (var->xres_virtual <= 640)
976                 par->CR50 |= 0x40;
977         else if (var->xres_virtual == 800)
978                 par->CR50 |= 0x80;
979         else if (var->xres_virtual == 1024)
980                 par->CR50 |= 0x00;
981         else if (var->xres_virtual == 1152)
982                 par->CR50 |= 0x01;
983         else if (var->xres_virtual == 1280)
984                 par->CR50 |= 0xc0;
985         else if (var->xres_virtual == 1600)
986                 par->CR50 |= 0x81;
987         else
988                 par->CR50 |= 0xc1;      /* Use GBD */
989
990         if( par->chip == S3_SAVAGE2000 )
991                 par->CR33 = 0x08;
992         else
993                 par->CR33 = 0x20;
994
995         par->CRTC[0x17] = 0xeb;
996
997         par->CR67 |= 1;
998
999         vga_out8(0x3d4, 0x36, par);
1000         par->CR36 = vga_in8 (0x3d5, par);
1001         vga_out8 (0x3d4, 0x68, par);
1002         par->CR68 = vga_in8 (0x3d5, par);
1003         par->CR69 = 0;
1004         vga_out8 (0x3d4, 0x6f, par);
1005         par->CR6F = vga_in8 (0x3d5, par);
1006         vga_out8 (0x3d4, 0x86, par);
1007         par->CR86 = vga_in8 (0x3d5, par);
1008         vga_out8 (0x3d4, 0x88, par);
1009         par->CR88 = vga_in8 (0x3d5, par) | 0x08;
1010         vga_out8 (0x3d4, 0xb0, par);
1011         par->CRB0 = vga_in8 (0x3d5, par) | 0x80;
1012
1013         return 0;
1014 }
1015
1016 /* --------------------------------------------------------------------- */
1017
1018 /*
1019  *    Set a single color register. Return != 0 for invalid regno.
1020  */
1021 static int savagefb_setcolreg(unsigned        regno,
1022                               unsigned        red,
1023                               unsigned        green,
1024                               unsigned        blue,
1025                               unsigned        transp,
1026                               struct fb_info *info)
1027 {
1028         struct savagefb_par *par = info->par;
1029
1030         if (regno >= NR_PALETTE)
1031                 return -EINVAL;
1032
1033         par->palette[regno].red    = red;
1034         par->palette[regno].green  = green;
1035         par->palette[regno].blue   = blue;
1036         par->palette[regno].transp = transp;
1037
1038         switch (info->var.bits_per_pixel) {
1039         case 8:
1040                 vga_out8 (0x3c8, regno, par);
1041
1042                 vga_out8 (0x3c9, red   >> 10, par);
1043                 vga_out8 (0x3c9, green >> 10, par);
1044                 vga_out8 (0x3c9, blue  >> 10, par);
1045                 break;
1046
1047         case 16:
1048                 if (regno < 16)
1049                         ((u32 *)info->pseudo_palette)[regno] =
1050                                 ((red   & 0xf800)      ) |
1051                                 ((green & 0xfc00) >>  5) |
1052                                 ((blue  & 0xf800) >> 11);
1053                 break;
1054
1055         case 24:
1056                 if (regno < 16)
1057                         ((u32 *)info->pseudo_palette)[regno] =
1058                                 ((red    & 0xff00) <<  8) |
1059                                 ((green  & 0xff00)      ) |
1060                                 ((blue   & 0xff00) >>  8);
1061                 break;
1062         case 32:
1063                 if (regno < 16)
1064                         ((u32 *)info->pseudo_palette)[regno] =
1065                                 ((transp & 0xff00) << 16) |
1066                                 ((red    & 0xff00) <<  8) |
1067                                 ((green  & 0xff00)      ) |
1068                                 ((blue   & 0xff00) >>  8);
1069                 break;
1070
1071         default:
1072                 return 1;
1073         }
1074
1075         return 0;
1076 }
1077
1078 static void savagefb_set_par_int (struct savagefb_par  *par)
1079 {
1080         unsigned char tmp, cr3a, cr66, cr67;
1081
1082         DBG ("savagefb_set_par_int");
1083
1084         par->SavageWaitIdle (par);
1085
1086         vga_out8 (0x3c2, 0x23, par);
1087
1088         vga_out16 (0x3d4, 0x4838, par);
1089         vga_out16 (0x3d4, 0xa539, par);
1090         vga_out16 (0x3c4, 0x0608, par);
1091
1092         vgaHWProtect (par, 1);
1093
1094         /*
1095          * Some Savage/MX and /IX systems go nuts when trying to exit the
1096          * server after WindowMaker has displayed a gradient background.  I
1097          * haven't been able to find what causes it, but a non-destructive
1098          * switch to mode 3 here seems to eliminate the issue.
1099          */
1100
1101         VerticalRetraceWait(par);
1102         vga_out8 (0x3d4, 0x67, par);
1103         cr67 = vga_in8 (0x3d5, par);
1104         vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c, par); /* no STREAMS yet */
1105
1106         vga_out8 (0x3d4, 0x23, par);
1107         vga_out8 (0x3d5, 0x00, par);
1108         vga_out8 (0x3d4, 0x26, par);
1109         vga_out8 (0x3d5, 0x00, par);
1110
1111         /* restore extended regs */
1112         vga_out8 (0x3d4, 0x66, par);
1113         vga_out8 (0x3d5, par->CR66, par);
1114         vga_out8 (0x3d4, 0x3a, par);
1115         vga_out8 (0x3d5, par->CR3A, par);
1116         vga_out8 (0x3d4, 0x31, par);
1117         vga_out8 (0x3d5, par->CR31, par);
1118         vga_out8 (0x3d4, 0x32, par);
1119         vga_out8 (0x3d5, par->CR32, par);
1120         vga_out8 (0x3d4, 0x58, par);
1121         vga_out8 (0x3d5, par->CR58, par);
1122         vga_out8 (0x3d4, 0x53, par);
1123         vga_out8 (0x3d5, par->CR53 & 0x7f, par);
1124
1125         vga_out16 (0x3c4, 0x0608, par);
1126
1127         /* Restore DCLK registers. */
1128
1129         vga_out8 (0x3c4, 0x0e, par);
1130         vga_out8 (0x3c5, par->SR0E, par);
1131         vga_out8 (0x3c4, 0x0f, par);
1132         vga_out8 (0x3c5, par->SR0F, par);
1133         vga_out8 (0x3c4, 0x29, par);
1134         vga_out8 (0x3c5, par->SR29, par);
1135         vga_out8 (0x3c4, 0x15, par);
1136         vga_out8 (0x3c5, par->SR15, par);
1137
1138         /* Restore flat panel expansion regsters. */
1139         if( par->chip == S3_SAVAGE_MX ) {
1140                 int i;
1141
1142                 for( i = 0; i < 8; i++ ) {
1143                         vga_out8 (0x3c4, 0x54+i, par);
1144                         vga_out8 (0x3c5, par->SR54[i], par);
1145                 }
1146         }
1147
1148         vgaHWRestore (par);
1149
1150         /* extended mode timing registers */
1151         vga_out8 (0x3d4, 0x53, par);
1152         vga_out8 (0x3d5, par->CR53, par);
1153         vga_out8 (0x3d4, 0x5d, par);
1154         vga_out8 (0x3d5, par->CR5D, par);
1155         vga_out8 (0x3d4, 0x5e, par);
1156         vga_out8 (0x3d5, par->CR5E, par);
1157         vga_out8 (0x3d4, 0x3b, par);
1158         vga_out8 (0x3d5, par->CR3B, par);
1159         vga_out8 (0x3d4, 0x3c, par);
1160         vga_out8 (0x3d5, par->CR3C, par);
1161         vga_out8 (0x3d4, 0x43, par);
1162         vga_out8 (0x3d5, par->CR43, par);
1163         vga_out8 (0x3d4, 0x65, par);
1164         vga_out8 (0x3d5, par->CR65, par);
1165
1166         /* restore the desired video mode with cr67 */
1167         vga_out8 (0x3d4, 0x67, par);
1168         /* following part not present in X11 driver */
1169         cr67 = vga_in8 (0x3d5, par) & 0xf;
1170         vga_out8 (0x3d5, 0x50 | cr67, par);
1171         udelay (10000);
1172         vga_out8 (0x3d4, 0x67, par);
1173         /* end of part */
1174         vga_out8 (0x3d5, par->CR67 & ~0x0c, par);
1175
1176         /* other mode timing and extended regs */
1177         vga_out8 (0x3d4, 0x34, par);
1178         vga_out8 (0x3d5, par->CR34, par);
1179         vga_out8 (0x3d4, 0x40, par);
1180         vga_out8 (0x3d5, par->CR40, par);
1181         vga_out8 (0x3d4, 0x42, par);
1182         vga_out8 (0x3d5, par->CR42, par);
1183         vga_out8 (0x3d4, 0x45, par);
1184         vga_out8 (0x3d5, par->CR45, par);
1185         vga_out8 (0x3d4, 0x50, par);
1186         vga_out8 (0x3d5, par->CR50, par);
1187         vga_out8 (0x3d4, 0x51, par);
1188         vga_out8 (0x3d5, par->CR51, par);
1189
1190         /* memory timings */
1191         vga_out8 (0x3d4, 0x36, par);
1192         vga_out8 (0x3d5, par->CR36, par);
1193         vga_out8 (0x3d4, 0x60, par);
1194         vga_out8 (0x3d5, par->CR60, par);
1195         vga_out8 (0x3d4, 0x68, par);
1196         vga_out8 (0x3d5, par->CR68, par);
1197         vga_out8 (0x3d4, 0x69, par);
1198         vga_out8 (0x3d5, par->CR69, par);
1199         vga_out8 (0x3d4, 0x6f, par);
1200         vga_out8 (0x3d5, par->CR6F, par);
1201
1202         vga_out8 (0x3d4, 0x33, par);
1203         vga_out8 (0x3d5, par->CR33, par);
1204         vga_out8 (0x3d4, 0x86, par);
1205         vga_out8 (0x3d5, par->CR86, par);
1206         vga_out8 (0x3d4, 0x88, par);
1207         vga_out8 (0x3d5, par->CR88, par);
1208         vga_out8 (0x3d4, 0x90, par);
1209         vga_out8 (0x3d5, par->CR90, par);
1210         vga_out8 (0x3d4, 0x91, par);
1211         vga_out8 (0x3d5, par->CR91, par);
1212
1213         if (par->chip == S3_SAVAGE4) {
1214                 vga_out8 (0x3d4, 0xb0, par);
1215                 vga_out8 (0x3d5, par->CRB0, par);
1216         }
1217
1218         vga_out8 (0x3d4, 0x32, par);
1219         vga_out8 (0x3d5, par->CR32, par);
1220
1221         /* unlock extended seq regs */
1222         vga_out8 (0x3c4, 0x08, par);
1223         vga_out8 (0x3c5, 0x06, par);
1224
1225         /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates
1226          * that we should leave the default SR10 and SR11 values there.
1227          */
1228         if (par->SR10 != 255) {
1229                 vga_out8 (0x3c4, 0x10, par);
1230                 vga_out8 (0x3c5, par->SR10, par);
1231                 vga_out8 (0x3c4, 0x11, par);
1232                 vga_out8 (0x3c5, par->SR11, par);
1233         }
1234
1235         /* restore extended seq regs for dclk */
1236         vga_out8 (0x3c4, 0x0e, par);
1237         vga_out8 (0x3c5, par->SR0E, par);
1238         vga_out8 (0x3c4, 0x0f, par);
1239         vga_out8 (0x3c5, par->SR0F, par);
1240         vga_out8 (0x3c4, 0x12, par);
1241         vga_out8 (0x3c5, par->SR12, par);
1242         vga_out8 (0x3c4, 0x13, par);
1243         vga_out8 (0x3c5, par->SR13, par);
1244         vga_out8 (0x3c4, 0x29, par);
1245         vga_out8 (0x3c5, par->SR29, par);
1246
1247         vga_out8 (0x3c4, 0x18, par);
1248         vga_out8 (0x3c5, par->SR18, par);
1249
1250         /* load new m, n pll values for dclk & mclk */
1251         vga_out8 (0x3c4, 0x15, par);
1252         tmp = vga_in8 (0x3c5, par) & ~0x21;
1253
1254         vga_out8 (0x3c5, tmp | 0x03, par);
1255         vga_out8 (0x3c5, tmp | 0x23, par);
1256         vga_out8 (0x3c5, tmp | 0x03, par);
1257         vga_out8 (0x3c5, par->SR15, par);
1258         udelay (100);
1259
1260         vga_out8 (0x3c4, 0x30, par);
1261         vga_out8 (0x3c5, par->SR30, par);
1262         vga_out8 (0x3c4, 0x08, par);
1263         vga_out8 (0x3c5, par->SR08, par);
1264
1265         /* now write out cr67 in full, possibly starting STREAMS */
1266         VerticalRetraceWait(par);
1267         vga_out8 (0x3d4, 0x67, par);
1268         vga_out8 (0x3d5, par->CR67, par);
1269
1270         vga_out8 (0x3d4, 0x66, par);
1271         cr66 = vga_in8 (0x3d5, par);
1272         vga_out8 (0x3d5, cr66 | 0x80, par);
1273         vga_out8 (0x3d4, 0x3a, par);
1274         cr3a = vga_in8 (0x3d5, par);
1275         vga_out8 (0x3d5, cr3a | 0x80, par);
1276
1277         if (par->chip != S3_SAVAGE_MX) {
1278                 VerticalRetraceWait(par);
1279                 savage_out32 (FIFO_CONTROL_REG, par->MMPR0, par);
1280                 par->SavageWaitIdle (par);
1281                 savage_out32 (MIU_CONTROL_REG, par->MMPR1, par);
1282                 par->SavageWaitIdle (par);
1283                 savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2, par);
1284                 par->SavageWaitIdle (par);
1285                 savage_out32 (MISC_TIMEOUT_REG, par->MMPR3, par);
1286         }
1287
1288         vga_out8 (0x3d4, 0x66, par);
1289         vga_out8 (0x3d5, cr66, par);
1290         vga_out8 (0x3d4, 0x3a, par);
1291         vga_out8 (0x3d5, cr3a, par);
1292
1293         SavageSetup2DEngine (par);
1294         vgaHWProtect (par, 0);
1295 }
1296
1297 static void savagefb_update_start (struct savagefb_par      *par,
1298                                    struct fb_var_screeninfo *var)
1299 {
1300         int base;
1301
1302         base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1))
1303                 * ((var->bits_per_pixel+7) / 8)) >> 2;
1304
1305         /* now program the start address registers */
1306         vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);
1307         vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);
1308         vga_out8 (0x3d4, 0x69, par);
1309         vga_out8 (0x3d5, (base & 0x7f0000) >> 16, par);
1310 }
1311
1312
1313 static void savagefb_set_fix(struct fb_info *info)
1314 {
1315         info->fix.line_length = info->var.xres_virtual *
1316                 info->var.bits_per_pixel / 8;
1317
1318         if (info->var.bits_per_pixel == 8) {
1319                 info->fix.visual      = FB_VISUAL_PSEUDOCOLOR;
1320                 info->fix.xpanstep    = 4;
1321         } else {
1322                 info->fix.visual      = FB_VISUAL_TRUECOLOR;
1323                 info->fix.xpanstep    = 2;
1324         }
1325
1326 }
1327
1328 #if defined(CONFIG_FB_SAVAGE_ACCEL)
1329 static void savagefb_set_clip(struct fb_info *info)
1330 {
1331     struct savagefb_par *par = info->par;
1332     int cmd;
1333
1334     cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
1335     par->bci_ptr = 0;
1336     par->SavageWaitFifo(par,3);
1337     BCI_SEND(cmd);
1338     BCI_SEND(BCI_CLIP_TL(0, 0));
1339     BCI_SEND(BCI_CLIP_BR(0xfff, 0xfff));
1340 }
1341 #endif
1342
1343 static int savagefb_set_par (struct fb_info *info)
1344 {
1345         struct savagefb_par *par = info->par;
1346         struct fb_var_screeninfo *var = &info->var;
1347         int err;
1348
1349         DBG("savagefb_set_par");
1350         err = savagefb_decode_var (var, par);
1351         if (err)
1352                 return err;
1353
1354         if (par->dacSpeedBpp <= 0) {
1355                 if (var->bits_per_pixel > 24)
1356                         par->dacSpeedBpp = par->clock[3];
1357                 else if (var->bits_per_pixel >= 24)
1358                         par->dacSpeedBpp = par->clock[2];
1359                 else if ((var->bits_per_pixel > 8) && (var->bits_per_pixel < 24))
1360                         par->dacSpeedBpp = par->clock[1];
1361                 else if (var->bits_per_pixel <= 8)
1362                         par->dacSpeedBpp = par->clock[0];
1363         }
1364
1365         /* Set ramdac limits */
1366         par->maxClock = par->dacSpeedBpp;
1367         par->minClock = 10000;
1368
1369         savagefb_set_par_int (par);
1370         fb_set_cmap (&info->cmap, info);
1371         savagefb_set_fix(info);
1372         savagefb_set_clip(info);
1373
1374         SavagePrintRegs();
1375         return 0;
1376 }
1377
1378 /*
1379  *    Pan or Wrap the Display
1380  */
1381 static int savagefb_pan_display (struct fb_var_screeninfo *var,
1382                                  struct fb_info           *info)
1383 {
1384         struct savagefb_par *par = info->par;
1385
1386         savagefb_update_start (par, var);
1387         return 0;
1388 }
1389
1390 static int savagefb_blank(int blank, struct fb_info *info)
1391 {
1392         struct savagefb_par *par = info->par;
1393         u8 sr8 = 0, srd = 0;
1394
1395         if (par->display_type == DISP_CRT) {
1396                 vga_out8(0x3c4, 0x08, par);
1397                 sr8 = vga_in8(0x3c5, par);
1398                 sr8 |= 0x06;
1399                 vga_out8(0x3c5, sr8, par);
1400                 vga_out8(0x3c4, 0x0d, par);
1401                 srd = vga_in8(0x3c5, par);
1402                 srd &= 0x03;
1403
1404                 switch (blank) {
1405                 case FB_BLANK_UNBLANK:
1406                 case FB_BLANK_NORMAL:
1407                         break;
1408                 case FB_BLANK_VSYNC_SUSPEND:
1409                         srd |= 0x10;
1410                         break;
1411                 case FB_BLANK_HSYNC_SUSPEND:
1412                         srd |= 0x40;
1413                         break;
1414                 case FB_BLANK_POWERDOWN:
1415                         srd |= 0x50;
1416                         break;
1417                 }
1418
1419                 vga_out8(0x3c4, 0x0d, par);
1420                 vga_out8(0x3c5, srd, par);
1421         }
1422
1423         if (par->display_type == DISP_LCD ||
1424             par->display_type == DISP_DFP) {
1425                 switch(blank) {
1426                 case FB_BLANK_UNBLANK:
1427                 case FB_BLANK_NORMAL:
1428                         vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */
1429                         vga_out8(0x3c5, vga_in8(0x3c5, par) | 0x10, par);
1430                         break;
1431                 case FB_BLANK_VSYNC_SUSPEND:
1432                 case FB_BLANK_HSYNC_SUSPEND:
1433                 case FB_BLANK_POWERDOWN:
1434                         vga_out8(0x3c4, 0x31, par); /* SR31 bit 4 - FP enable */
1435                         vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x10, par);
1436                         break;
1437                 }
1438         }
1439
1440         return (blank == FB_BLANK_NORMAL) ? 1 : 0;
1441 }
1442
1443 static struct fb_ops savagefb_ops = {
1444         .owner          = THIS_MODULE,
1445         .fb_check_var   = savagefb_check_var,
1446         .fb_set_par     = savagefb_set_par,
1447         .fb_setcolreg   = savagefb_setcolreg,
1448         .fb_pan_display = savagefb_pan_display,
1449         .fb_blank       = savagefb_blank,
1450 #if defined(CONFIG_FB_SAVAGE_ACCEL)
1451         .fb_fillrect    = savagefb_fillrect,
1452         .fb_copyarea    = savagefb_copyarea,
1453         .fb_imageblit   = savagefb_imageblit,
1454         .fb_sync        = savagefb_sync,
1455 #else
1456         .fb_fillrect    = cfb_fillrect,
1457         .fb_copyarea    = cfb_copyarea,
1458         .fb_imageblit   = cfb_imageblit,
1459 #endif
1460 };
1461
1462 /* --------------------------------------------------------------------- */
1463
1464 static struct fb_var_screeninfo __devinitdata savagefb_var800x600x8 = {
1465         .accel_flags =  FB_ACCELF_TEXT,
1466         .xres =         800,
1467         .yres =         600,
1468         .xres_virtual =  800,
1469         .yres_virtual =  600,
1470         .bits_per_pixel = 8,
1471         .pixclock =     25000,
1472         .left_margin =  88,
1473         .right_margin = 40,
1474         .upper_margin = 23,
1475         .lower_margin = 1,
1476         .hsync_len =    128,
1477         .vsync_len =    4,
1478         .sync =         FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
1479         .vmode =        FB_VMODE_NONINTERLACED
1480 };
1481
1482 static void savage_enable_mmio (struct savagefb_par *par)
1483 {
1484         unsigned char val;
1485
1486         DBG ("savage_enable_mmio\n");
1487
1488         val = vga_in8 (0x3c3, par);
1489         vga_out8 (0x3c3, val | 0x01, par);
1490         val = vga_in8 (0x3cc, par);
1491         vga_out8 (0x3c2, val | 0x01, par);
1492
1493         if (par->chip >= S3_SAVAGE4) {
1494                 vga_out8 (0x3d4, 0x40, par);
1495                 val = vga_in8 (0x3d5, par);
1496                 vga_out8 (0x3d5, val | 1, par);
1497         }
1498 }
1499
1500
1501 static void savage_disable_mmio (struct savagefb_par *par)
1502 {
1503         unsigned char val;
1504
1505         DBG ("savage_disable_mmio\n");
1506
1507         if(par->chip >= S3_SAVAGE4 ) {
1508                 vga_out8 (0x3d4, 0x40, par);
1509                 val = vga_in8 (0x3d5, par);
1510                 vga_out8 (0x3d5, val | 1, par);
1511         }
1512 }
1513
1514
1515 static int __devinit savage_map_mmio (struct fb_info *info)
1516 {
1517         struct savagefb_par *par = info->par;
1518         DBG ("savage_map_mmio");
1519
1520         if (S3_SAVAGE3D_SERIES (par->chip))
1521                 par->mmio.pbase = pci_resource_start (par->pcidev, 0) +
1522                         SAVAGE_NEWMMIO_REGBASE_S3;
1523         else
1524                 par->mmio.pbase = pci_resource_start (par->pcidev, 0) +
1525                         SAVAGE_NEWMMIO_REGBASE_S4;
1526
1527         par->mmio.len = SAVAGE_NEWMMIO_REGSIZE;
1528
1529         par->mmio.vbase = ioremap (par->mmio.pbase, par->mmio.len);
1530         if (!par->mmio.vbase) {
1531                 printk ("savagefb: unable to map memory mapped IO\n");
1532                 return -ENOMEM;
1533         } else
1534                 printk (KERN_INFO "savagefb: mapped io at %p\n",
1535                         par->mmio.vbase);
1536
1537         info->fix.mmio_start = par->mmio.pbase;
1538         info->fix.mmio_len   = par->mmio.len;
1539
1540         par->bci_base = (u32 __iomem *)(par->mmio.vbase + BCI_BUFFER_OFFSET);
1541         par->bci_ptr  = 0;
1542
1543         savage_enable_mmio (par);
1544
1545         return 0;
1546 }
1547
1548 static void savage_unmap_mmio (struct fb_info *info)
1549 {
1550         struct savagefb_par *par = info->par;
1551         DBG ("savage_unmap_mmio");
1552
1553         savage_disable_mmio(par);
1554
1555         if (par->mmio.vbase) {
1556                 iounmap(par->mmio.vbase);
1557                 par->mmio.vbase = NULL;
1558         }
1559 }
1560
1561 static int __devinit savage_map_video (struct fb_info *info,
1562                                        int video_len)
1563 {
1564         struct savagefb_par *par = info->par;
1565         int resource;
1566
1567         DBG("savage_map_video");
1568
1569         if (S3_SAVAGE3D_SERIES (par->chip))
1570                 resource = 0;
1571         else
1572                 resource = 1;
1573
1574         par->video.pbase = pci_resource_start (par->pcidev, resource);
1575         par->video.len   = video_len;
1576         par->video.vbase = ioremap (par->video.pbase, par->video.len);
1577
1578         if (!par->video.vbase) {
1579                 printk ("savagefb: unable to map screen memory\n");
1580                 return -ENOMEM;
1581         } else
1582                 printk (KERN_INFO "savagefb: mapped framebuffer at %p, "
1583                         "pbase == %x\n", par->video.vbase, par->video.pbase);
1584
1585         info->fix.smem_start = par->video.pbase;
1586         info->fix.smem_len   = par->video.len - par->cob_size;
1587         info->screen_base    = par->video.vbase;
1588
1589 #ifdef CONFIG_MTRR
1590         par->video.mtrr = mtrr_add (par->video.pbase, video_len,
1591                                      MTRR_TYPE_WRCOMB, 1);
1592 #endif
1593
1594         /* Clear framebuffer, it's all white in memory after boot */
1595         memset_io (par->video.vbase, 0, par->video.len);
1596
1597         return 0;
1598 }
1599
1600 static void savage_unmap_video (struct fb_info *info)
1601 {
1602         struct savagefb_par *par = info->par;
1603
1604         DBG("savage_unmap_video");
1605
1606         if (par->video.vbase) {
1607 #ifdef CONFIG_MTRR
1608                 mtrr_del (par->video.mtrr, par->video.pbase, par->video.len);
1609 #endif
1610
1611                 iounmap (par->video.vbase);
1612                 par->video.vbase = NULL;
1613                 info->screen_base = NULL;
1614         }
1615 }
1616
1617 static int savage_init_hw (struct savagefb_par *par)
1618 {
1619         unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
1620
1621         static unsigned char RamSavage3D[] = { 8, 4, 4, 2 };
1622         static unsigned char RamSavage4[] =  { 2, 4, 8, 12, 16, 32, 64, 32 };
1623         static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
1624         static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
1625         int videoRam, videoRambytes, dvi;
1626
1627         DBG("savage_init_hw");
1628
1629         /* unprotect CRTC[0-7] */
1630         vga_out8(0x3d4, 0x11, par);
1631         tmp = vga_in8(0x3d5, par);
1632         vga_out8(0x3d5, tmp & 0x7f, par);
1633
1634         /* unlock extended regs */
1635         vga_out16(0x3d4, 0x4838, par);
1636         vga_out16(0x3d4, 0xa039, par);
1637         vga_out16(0x3c4, 0x0608, par);
1638
1639         vga_out8(0x3d4, 0x40, par);
1640         tmp = vga_in8(0x3d5, par);
1641         vga_out8(0x3d5, tmp & ~0x01, par);
1642
1643         /* unlock sys regs */
1644         vga_out8(0x3d4, 0x38, par);
1645         vga_out8(0x3d5, 0x48, par);
1646
1647         /* Unlock system registers. */
1648         vga_out16(0x3d4, 0x4838, par);
1649
1650         /* Next go on to detect amount of installed ram */
1651
1652         vga_out8(0x3d4, 0x36, par);            /* for register CR36 (CONFG_REG1), */
1653         config1 = vga_in8(0x3d5, par);    /* get amount of vram installed */
1654
1655         /* Compute the amount of video memory and offscreen memory. */
1656
1657         switch  (par->chip) {
1658         case S3_SAVAGE3D:
1659                 videoRam = RamSavage3D[ (config1 & 0xC0) >> 6 ] * 1024;
1660                 break;
1661
1662         case S3_SAVAGE4:
1663                 /*
1664                  * The Savage4 has one ugly special case to consider.  On
1665                  * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB
1666                  * when it really means 8MB.  Why do it the same when you
1667                  * can do it different...
1668                  */
1669                 vga_out8(0x3d4, 0x68, par);     /* memory control 1 */
1670                 if( (vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6) )
1671                         RamSavage4[1] = 8;
1672
1673                 /*FALLTHROUGH*/
1674
1675         case S3_SAVAGE2000:
1676                 videoRam = RamSavage4[ (config1 & 0xE0) >> 5 ] * 1024;
1677                 break;
1678
1679         case S3_SAVAGE_MX:
1680         case S3_SUPERSAVAGE:
1681                 videoRam = RamSavageMX[ (config1 & 0x0E) >> 1 ] * 1024;
1682                 break;
1683
1684         case S3_PROSAVAGE:
1685                 videoRam = RamSavageNB[ (config1 & 0xE0) >> 5 ] * 1024;
1686                 break;
1687
1688         default:
1689                 /* How did we get here? */
1690                 videoRam = 0;
1691                 break;
1692         }
1693
1694         videoRambytes = videoRam * 1024;
1695
1696         printk (KERN_INFO "savagefb: probed videoram:  %dk\n", videoRam);
1697
1698         /* reset graphics engine to avoid memory corruption */
1699         vga_out8 (0x3d4, 0x66, par);
1700         cr66 = vga_in8 (0x3d5, par);
1701         vga_out8 (0x3d5, cr66 | 0x02, par);
1702         udelay (10000);
1703
1704         vga_out8 (0x3d4, 0x66, par);
1705         vga_out8 (0x3d5, cr66 & ~0x02, par);    /* clear reset flag */
1706         udelay (10000);
1707
1708
1709         /*
1710          * reset memory interface, 3D engine, AGP master, PCI master,
1711          * master engine unit, motion compensation/LPB
1712          */
1713         vga_out8 (0x3d4, 0x3f, par);
1714         cr3f = vga_in8 (0x3d5, par);
1715         vga_out8 (0x3d5, cr3f | 0x08, par);
1716         udelay (10000);
1717
1718         vga_out8 (0x3d4, 0x3f, par);
1719         vga_out8 (0x3d5, cr3f & ~0x08, par);    /* clear reset flags */
1720         udelay (10000);
1721
1722         /* Savage ramdac speeds */
1723         par->numClocks = 4;
1724         par->clock[0] = 250000;
1725         par->clock[1] = 250000;
1726         par->clock[2] = 220000;
1727         par->clock[3] = 220000;
1728
1729         /* detect current mclk */
1730         vga_out8(0x3c4, 0x08, par);
1731         sr8 = vga_in8(0x3c5, par);
1732         vga_out8(0x3c5, 0x06, par);
1733         vga_out8(0x3c4, 0x10, par);
1734         n = vga_in8(0x3c5, par);
1735         vga_out8(0x3c4, 0x11, par);
1736         m = vga_in8(0x3c5, par);
1737         vga_out8(0x3c4, 0x08, par);
1738         vga_out8(0x3c5, sr8, par);
1739         m &= 0x7f;
1740         n1 = n & 0x1f;
1741         n2 = (n >> 5) & 0x03;
1742         par->MCLK = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100;
1743         printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
1744                 par->MCLK);
1745
1746         /* check for DVI/flat panel */
1747         dvi = 0;
1748
1749         if (par->chip == S3_SAVAGE4) {
1750                 unsigned char sr30 = 0x00;
1751
1752                 vga_out8(0x3c4, 0x30, par);
1753                 /* clear bit 1 */
1754                 vga_out8(0x3c5, vga_in8(0x3c5, par) & ~0x02, par);
1755                 sr30 = vga_in8(0x3c5, par);
1756                 if (sr30 & 0x02 /*0x04 */) {
1757                         dvi = 1;
1758                         printk("savagefb: Digital Flat Panel Detected\n");
1759                 }
1760         }
1761
1762         if (S3_SAVAGE_MOBILE_SERIES(par->chip) && !par->crtonly)
1763                 par->display_type = DISP_LCD;
1764         else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
1765                 par->display_type = DISP_DFP;
1766         else
1767                 par->display_type = DISP_CRT;
1768
1769         /* Check LCD panel parrmation */
1770
1771         if (par->display_type == DISP_LCD) {
1772                 unsigned char cr6b = VGArCR( 0x6b, par);
1773
1774                 int panelX = (VGArSEQ (0x61, par) +
1775                               ((VGArSEQ (0x66, par) & 0x02) << 7) + 1) * 8;
1776                 int panelY = (VGArSEQ (0x69, par) +
1777                               ((VGArSEQ (0x6e, par) & 0x70) << 4) + 1);
1778
1779                 char * sTechnology = "Unknown";
1780
1781                 /* OK, I admit it.  I don't know how to limit the max dot clock
1782                  * for LCD panels of various sizes.  I thought I copied the
1783                  * formula from the BIOS, but many users have parrmed me of
1784                  * my folly.
1785                  *
1786                  * Instead, I'll abandon any attempt to automatically limit the
1787                  * clock, and add an LCDClock option to XF86Config.  Some day,
1788                  * I should come back to this.
1789                  */
1790
1791                 enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */
1792                         ActiveCRT = 0x01,
1793                         ActiveLCD = 0x02,
1794                         ActiveTV = 0x04,
1795                         ActiveCRT2 = 0x20,
1796                         ActiveDUO = 0x80
1797                 };
1798
1799                 if ((VGArSEQ (0x39, par) & 0x03) == 0) {
1800                         sTechnology = "TFT";
1801                 } else if ((VGArSEQ (0x30, par) & 0x01) == 0) {
1802                         sTechnology = "DSTN";
1803                 } else  {
1804                         sTechnology = "STN";
1805                 }
1806
1807                 printk (KERN_INFO "savagefb: %dx%d %s LCD panel detected %s\n",
1808                         panelX, panelY, sTechnology,
1809                         cr6b & ActiveLCD ? "and active" : "but not active");
1810
1811                 if( cr6b & ActiveLCD )  {
1812                         /*
1813                          * If the LCD is active and panel expansion is enabled,
1814                          * we probably want to kill the HW cursor.
1815                          */
1816
1817                         printk (KERN_INFO "savagefb: Limiting video mode to "
1818                                 "%dx%d\n", panelX, panelY );
1819
1820                         par->SavagePanelWidth = panelX;
1821                         par->SavagePanelHeight = panelY;
1822
1823                 } else
1824                         par->display_type = DISP_CRT;
1825         }
1826
1827         savage_get_default_par (par);
1828
1829         if( S3_SAVAGE4_SERIES(par->chip) ) {
1830                 /*
1831                  * The Savage4 and ProSavage have COB coherency bugs which
1832                  * render the buffer useless.  We disable it.
1833                  */
1834                 par->cob_index = 2;
1835                 par->cob_size = 0x8000 << par->cob_index;
1836                 par->cob_offset = videoRambytes;
1837         } else {
1838                 /* We use 128kB for the COB on all chips. */
1839
1840                 par->cob_index  = 7;
1841                 par->cob_size   = 0x400 << par->cob_index;
1842                 par->cob_offset = videoRambytes - par->cob_size;
1843         }
1844
1845         return videoRambytes;
1846 }
1847
1848 static int __devinit savage_init_fb_info (struct fb_info *info,
1849                                           struct pci_dev *dev,
1850                                           const struct pci_device_id *id)
1851 {
1852         struct savagefb_par *par = info->par;
1853         int err = 0;
1854
1855         par->pcidev  = dev;
1856
1857         info->fix.type     = FB_TYPE_PACKED_PIXELS;
1858         info->fix.type_aux         = 0;
1859         info->fix.ypanstep         = 1;
1860         info->fix.ywrapstep   = 0;
1861         info->fix.accel       = id->driver_data;
1862
1863         switch (info->fix.accel) {
1864         case FB_ACCEL_SUPERSAVAGE:
1865                 par->chip = S3_SUPERSAVAGE;
1866                 snprintf (info->fix.id, 16, "SuperSavage");
1867                 break;
1868         case FB_ACCEL_SAVAGE4:
1869                 par->chip = S3_SAVAGE4;
1870                 snprintf (info->fix.id, 16, "Savage4");
1871                 break;
1872         case FB_ACCEL_SAVAGE3D:
1873                 par->chip = S3_SAVAGE3D;
1874                 snprintf (info->fix.id, 16, "Savage3D");
1875                 break;
1876         case FB_ACCEL_SAVAGE3D_MV:
1877                 par->chip = S3_SAVAGE3D;
1878                 snprintf (info->fix.id, 16, "Savage3D-MV");
1879                 break;
1880         case FB_ACCEL_SAVAGE2000:
1881                 par->chip = S3_SAVAGE2000;
1882                 snprintf (info->fix.id, 16, "Savage2000");
1883                 break;
1884         case FB_ACCEL_SAVAGE_MX_MV:
1885                 par->chip = S3_SAVAGE_MX;
1886                 snprintf (info->fix.id, 16, "Savage/MX-MV");
1887                 break;
1888         case FB_ACCEL_SAVAGE_MX:
1889                 par->chip = S3_SAVAGE_MX;
1890                 snprintf (info->fix.id, 16, "Savage/MX");
1891                 break;
1892         case FB_ACCEL_SAVAGE_IX_MV:
1893                 par->chip = S3_SAVAGE_MX;
1894                 snprintf (info->fix.id, 16, "Savage/IX-MV");
1895                 break;
1896         case FB_ACCEL_SAVAGE_IX:
1897                 par->chip = S3_SAVAGE_MX;
1898                 snprintf (info->fix.id, 16, "Savage/IX");
1899                 break;
1900         case FB_ACCEL_PROSAVAGE_PM:
1901                 par->chip = S3_PROSAVAGE;
1902                 snprintf (info->fix.id, 16, "ProSavagePM");
1903                 break;
1904         case FB_ACCEL_PROSAVAGE_KM:
1905                 par->chip = S3_PROSAVAGE;
1906                 snprintf (info->fix.id, 16, "ProSavageKM");
1907                 break;
1908         case FB_ACCEL_S3TWISTER_P:
1909                 par->chip = S3_PROSAVAGE;
1910                 snprintf (info->fix.id, 16, "TwisterP");
1911                 break;
1912         case FB_ACCEL_S3TWISTER_K:
1913                 par->chip = S3_PROSAVAGE;
1914                 snprintf (info->fix.id, 16, "TwisterK");
1915                 break;
1916         case FB_ACCEL_PROSAVAGE_DDR:
1917                 par->chip = S3_PROSAVAGE;
1918                 snprintf (info->fix.id, 16, "ProSavageDDR");
1919                 break;
1920         case FB_ACCEL_PROSAVAGE_DDRK:
1921                 par->chip = S3_PROSAVAGE;
1922                 snprintf (info->fix.id, 16, "ProSavage8");
1923                 break;
1924         }
1925
1926         if (S3_SAVAGE3D_SERIES(par->chip)) {
1927                 par->SavageWaitIdle = savage3D_waitidle;
1928                 par->SavageWaitFifo = savage3D_waitfifo;
1929         } else if (S3_SAVAGE4_SERIES(par->chip) ||
1930                    S3_SUPERSAVAGE == par->chip) {
1931                 par->SavageWaitIdle = savage4_waitidle;
1932                 par->SavageWaitFifo = savage4_waitfifo;
1933         } else {
1934                 par->SavageWaitIdle = savage2000_waitidle;
1935                 par->SavageWaitFifo = savage2000_waitfifo;
1936         }
1937
1938         info->var.nonstd      = 0;
1939         info->var.activate    = FB_ACTIVATE_NOW;
1940         info->var.width       = -1;
1941         info->var.height      = -1;
1942         info->var.accel_flags = 0;
1943
1944         info->fbops          = &savagefb_ops;
1945         info->flags          = FBINFO_DEFAULT |
1946                                FBINFO_HWACCEL_YPAN |
1947                                FBINFO_HWACCEL_XPAN;
1948
1949         info->pseudo_palette = par->pseudo_palette;
1950
1951 #if defined(CONFIG_FB_SAVAGE_ACCEL)
1952         /* FIFO size + padding for commands */
1953         info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL);
1954
1955         err = -ENOMEM;
1956         if (info->pixmap.addr) {
1957                 memset(info->pixmap.addr, 0, 8*1024);
1958                 info->pixmap.size = 8*1024;
1959                 info->pixmap.scan_align = 4;
1960                 info->pixmap.buf_align = 4;
1961                 info->pixmap.access_align = 32;
1962
1963                 err = fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
1964                 if (!err)
1965                 info->flags |= FBINFO_HWACCEL_COPYAREA |
1966                                FBINFO_HWACCEL_FILLRECT |
1967                                FBINFO_HWACCEL_IMAGEBLIT;
1968         }
1969 #endif
1970         return err;
1971 }
1972
1973 /* --------------------------------------------------------------------- */
1974
1975 static int __devinit savagefb_probe (struct pci_dev* dev,
1976                                      const struct pci_device_id* id)
1977 {
1978         struct fb_info *info;
1979         struct savagefb_par *par;
1980         u_int h_sync, v_sync;
1981         int err, lpitch;
1982         int video_len;
1983
1984         DBG("savagefb_probe");
1985         SavagePrintRegs();
1986
1987         info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev);
1988         if (!info)
1989                 return -ENOMEM;
1990         par = info->par;
1991         err = pci_enable_device(dev);
1992         if (err)
1993                 goto failed_enable;
1994
1995         if ((err = pci_request_regions(dev, "savagefb"))) {
1996                 printk(KERN_ERR "cannot request PCI regions\n");
1997                 goto failed_enable;
1998         }
1999
2000         err = -ENOMEM;
2001
2002         if ((err = savage_init_fb_info(info, dev, id)))
2003                 goto failed_init;
2004
2005         err = savage_map_mmio(info);
2006         if (err)
2007                 goto failed_mmio;
2008
2009         video_len = savage_init_hw(par);
2010         /* FIXME: cant be negative */
2011         if (video_len < 0) {
2012                 err = video_len;
2013                 goto failed_mmio;
2014         }
2015
2016         err = savage_map_video(info, video_len);
2017         if (err)
2018                 goto failed_video;
2019
2020         INIT_LIST_HEAD(&info->modelist);
2021 #if defined(CONFIG_FB_SAVAGE_I2C)
2022         savagefb_create_i2c_busses(info);
2023         savagefb_probe_i2c_connector(info, &par->edid);
2024         fb_edid_to_monspecs(par->edid, &info->monspecs);
2025         kfree(par->edid);
2026         fb_videomode_to_modelist(info->monspecs.modedb,
2027                                  info->monspecs.modedb_len,
2028                                  &info->modelist);
2029 #endif
2030         info->var = savagefb_var800x600x8;
2031
2032         if (mode_option) {
2033                 fb_find_mode(&info->var, info, mode_option,
2034                              info->monspecs.modedb, info->monspecs.modedb_len,
2035                              NULL, 8);
2036         } else if (info->monspecs.modedb != NULL) {
2037                 struct fb_videomode *modedb;
2038
2039                 modedb = fb_find_best_display(&info->monspecs,
2040                                               &info->modelist);
2041                 savage_update_var(&info->var, modedb);
2042         }
2043
2044         /* maximize virtual vertical length */
2045         lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);
2046         info->var.yres_virtual = info->fix.smem_len/lpitch;
2047
2048         if (info->var.yres_virtual < info->var.yres)
2049                 goto failed;
2050
2051 #if defined(CONFIG_FB_SAVAGE_ACCEL)
2052         /*
2053          * The clipping coordinates are masked with 0xFFF, so limit our
2054          * virtual resolutions to these sizes.
2055          */
2056         if (info->var.yres_virtual > 0x1000)
2057                 info->var.yres_virtual = 0x1000;
2058
2059         if (info->var.xres_virtual > 0x1000)
2060                 info->var.xres_virtual = 0x1000;
2061 #endif
2062         savagefb_check_var(&info->var, info);
2063         savagefb_set_fix(info);
2064
2065         /*
2066          * Calculate the hsync and vsync frequencies.  Note that
2067          * we split the 1e12 constant up so that we can preserve
2068          * the precision and fit the results into 32-bit registers.
2069          *  (1953125000 * 512 = 1e12)
2070          */
2071         h_sync = 1953125000 / info->var.pixclock;
2072         h_sync = h_sync * 512 / (info->var.xres + info->var.left_margin +
2073                                  info->var.right_margin +
2074                                  info->var.hsync_len);
2075         v_sync = h_sync / (info->var.yres + info->var.upper_margin +
2076                            info->var.lower_margin + info->var.vsync_len);
2077
2078         printk(KERN_INFO "savagefb v" SAVAGEFB_VERSION ": "
2079                "%dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
2080                info->fix.smem_len >> 10,
2081                info->var.xres, info->var.yres,
2082                h_sync / 1000, h_sync % 1000, v_sync);
2083
2084
2085         fb_destroy_modedb(info->monspecs.modedb);
2086         info->monspecs.modedb = NULL;
2087
2088         err = register_framebuffer (info);
2089         if (err < 0)
2090                 goto failed;
2091
2092         printk (KERN_INFO "fb: S3 %s frame buffer device\n",
2093                 info->fix.id);
2094
2095         /*
2096          * Our driver data
2097          */
2098         pci_set_drvdata(dev, info);
2099
2100         return 0;
2101
2102  failed:
2103 #ifdef CONFIG_FB_SAVAGE_I2C
2104         savagefb_delete_i2c_busses(info);
2105 #endif
2106         fb_alloc_cmap (&info->cmap, 0, 0);
2107         savage_unmap_video(info);
2108  failed_video:
2109         savage_unmap_mmio (info);
2110  failed_mmio:
2111         kfree(info->pixmap.addr);
2112  failed_init:
2113         pci_release_regions(dev);
2114  failed_enable:
2115         framebuffer_release(info);
2116
2117         return err;
2118 }
2119
2120 static void __devexit savagefb_remove (struct pci_dev *dev)
2121 {
2122         struct fb_info *info = pci_get_drvdata(dev);
2123
2124         DBG("savagefb_remove");
2125
2126         if (info) {
2127                 /*
2128                  * If unregister_framebuffer fails, then
2129                  * we will be leaving hooks that could cause
2130                  * oopsen laying around.
2131                  */
2132                 if (unregister_framebuffer (info))
2133                         printk (KERN_WARNING "savagefb: danger danger! "
2134                                 "Oopsen imminent!\n");
2135
2136 #ifdef CONFIG_FB_SAVAGE_I2C
2137                 savagefb_delete_i2c_busses(info);
2138 #endif
2139                 fb_alloc_cmap (&info->cmap, 0, 0);
2140                 savage_unmap_video (info);
2141                 savage_unmap_mmio (info);
2142                 kfree(info->pixmap.addr);
2143                 pci_release_regions(dev);
2144                 framebuffer_release(info);
2145
2146                 /*
2147                  * Ensure that the driver data is no longer
2148                  * valid.
2149                  */
2150                 pci_set_drvdata(dev, NULL);
2151         }
2152 }
2153
2154 static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
2155 {
2156         struct fb_info *info = pci_get_drvdata(dev);
2157         struct savagefb_par *par = info->par;
2158
2159         DBG("savagefb_suspend");
2160
2161
2162         par->pm_state = state.event;
2163
2164         /*
2165          * For PM_EVENT_FREEZE, do not power down so the console
2166          * can remain active.
2167          */
2168         if (state.event == PM_EVENT_FREEZE) {
2169                 dev->dev.power.power_state = state;
2170                 return 0;
2171         }
2172
2173         acquire_console_sem();
2174         fb_set_suspend(info, 1);
2175
2176         if (info->fbops->fb_sync)
2177                 info->fbops->fb_sync(info);
2178
2179         savagefb_blank(FB_BLANK_POWERDOWN, info);
2180         savage_disable_mmio(par);
2181         pci_save_state(dev);
2182         pci_disable_device(dev);
2183         pci_set_power_state(dev, pci_choose_state(dev, state));
2184         release_console_sem();
2185
2186         return 0;
2187 }
2188
2189 static int savagefb_resume (struct pci_dev* dev)
2190 {
2191         struct fb_info *info = pci_get_drvdata(dev);
2192         struct savagefb_par *par = info->par;
2193         int cur_state = par->pm_state;
2194
2195         DBG("savage_resume");
2196
2197         par->pm_state = PM_EVENT_ON;
2198
2199         /*
2200          * The adapter was not powered down coming back from a
2201          * PM_EVENT_FREEZE.
2202          */
2203         if (cur_state == PM_EVENT_FREEZE) {
2204                 pci_set_power_state(dev, PCI_D0);
2205                 return 0;
2206         }
2207
2208         acquire_console_sem();
2209
2210         pci_set_power_state(dev, PCI_D0);
2211         pci_restore_state(dev);
2212
2213         if(pci_enable_device(dev))
2214                 DBG("err");
2215
2216         pci_set_master(dev);
2217         savage_enable_mmio(par);
2218         savage_init_hw(par);
2219         savagefb_set_par (info);
2220         savagefb_blank(FB_BLANK_UNBLANK, info);
2221         fb_set_suspend (info, 0);
2222         release_console_sem();
2223
2224         return 0;
2225 }
2226
2227
2228 static struct pci_device_id savagefb_devices[] __devinitdata = {
2229         {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX128,
2230          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
2231
2232         {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64,
2233          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
2234
2235         {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64C,
2236          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
2237
2238         {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128SDR,
2239          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
2240
2241         {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128DDR,
2242          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
2243
2244         {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64SDR,
2245          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
2246
2247         {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64DDR,
2248          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
2249
2250         {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCSDR,
2251          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
2252
2253         {PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCDDR,
2254          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
2255
2256         {PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4,
2257          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE4},
2258
2259         {PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D,
2260          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D},
2261
2262         {PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D_MV,
2263          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D_MV},
2264
2265         {PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000,
2266          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE2000},
2267
2268         {PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX_MV,
2269          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX_MV},
2270
2271         {PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX,
2272          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX},
2273
2274         {PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX_MV,
2275          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX_MV},
2276
2277         {PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX,
2278          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX},
2279
2280         {PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_PM,
2281          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_PM},
2282
2283         {PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_KM,
2284          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_KM},
2285
2286         {PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_P,
2287          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_P},
2288
2289         {PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_K,
2290          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_K},
2291
2292         {PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDR,
2293          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDR},
2294
2295         {PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDRK,
2296          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDRK},
2297
2298         {0, 0, 0, 0, 0, 0, 0}
2299 };
2300
2301 MODULE_DEVICE_TABLE(pci, savagefb_devices);
2302
2303 static struct pci_driver savagefb_driver = {
2304         .name =     "savagefb",
2305         .id_table = savagefb_devices,
2306         .probe =    savagefb_probe,
2307         .suspend =  savagefb_suspend,
2308         .resume =   savagefb_resume,
2309         .remove =   __devexit_p(savagefb_remove)
2310 };
2311
2312 /* **************************** exit-time only **************************** */
2313
2314 static void __exit savage_done (void)
2315 {
2316         DBG("savage_done");
2317         pci_unregister_driver (&savagefb_driver);
2318 }
2319
2320
2321 /* ************************* init in-kernel code ************************** */
2322
2323 static int __init savagefb_setup(char *options)
2324 {
2325 #ifndef MODULE
2326         char *this_opt;
2327
2328         if (!options || !*options)
2329                 return 0;
2330
2331         while ((this_opt = strsep(&options, ",")) != NULL) {
2332                 mode_option = this_opt;
2333         }
2334 #endif /* !MODULE */
2335         return 0;
2336 }
2337
2338 static int __init savagefb_init(void)
2339 {
2340         char *option;
2341
2342         DBG("savagefb_init");
2343
2344         if (fb_get_options("savagefb", &option))
2345                 return -ENODEV;
2346
2347         savagefb_setup(option);
2348         return pci_register_driver (&savagefb_driver);
2349
2350 }
2351
2352 module_init(savagefb_init);
2353 module_exit(savage_done);
2354
2355 module_param(mode_option, charp, 0);
2356 MODULE_PARM_DESC(mode_option, "Specify initial video mode");