cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

savagefb_driver.c (66305B)


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