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

sstfb.c (44419B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * linux/drivers/video/sstfb.c -- voodoo graphics frame buffer
      4 *
      5 *     Copyright (c) 2000-2002 Ghozlane Toumi <gtoumi@laposte.net>
      6 *
      7 *     Created 15 Jan 2000 by Ghozlane Toumi
      8 *
      9 * Contributions (and many thanks) :
     10 *
     11 * 03/2001 James Simmons   <jsimmons@infradead.org>
     12 * 04/2001 Paul Mundt      <lethal@chaoticdreams.org>
     13 * 05/2001 Urs Ganse       <ursg@uni.de>
     14 *	(initial work on voodoo2 port, interlace)
     15 * 09/2002 Helge Deller    <deller@gmx.de>
     16 *	(enable driver on big-endian machines (hppa), ioctl fixes)
     17 * 12/2002 Helge Deller    <deller@gmx.de>
     18 *	(port driver to new frambuffer infrastructure)
     19 * 01/2003 Helge Deller    <deller@gmx.de>
     20 *	(initial work on fb hardware acceleration for voodoo2)
     21 * 08/2006 Alan Cox 	   <alan@redhat.com>
     22 *	Remove never finished and bogus 24/32bit support
     23 *	Clean up macro abuse
     24 *	Minor tidying for format.
     25 * 12/2006 Helge Deller    <deller@gmx.de>
     26 *	add /sys/class/graphics/fbX/vgapass sysfs-interface
     27 *	add module option "mode_option" to set initial screen mode
     28 *	use fbdev default videomode database
     29 *	remove debug functions from ioctl
     30 */
     31
     32/*
     33 * The voodoo1 has the following memory mapped address space:
     34 * 0x000000 - 0x3fffff : registers              (4MB)
     35 * 0x400000 - 0x7fffff : linear frame buffer    (4MB)
     36 * 0x800000 - 0xffffff : texture memory         (8MB)
     37 */
     38
     39/*
     40 * misc notes, TODOs, toASKs, and deep thoughts
     41
     42-TODO: at one time or another test that the mode is acceptable by the monitor
     43-ASK: Can I choose different ordering for the color bitfields (rgba argb ...)
     44      which one should i use ? is there any preferred one ? It seems ARGB is
     45      the one ...
     46-TODO: in  set_var check the validity of timings (hsync vsync)...
     47-TODO: check and recheck the use of sst_wait_idle : we don't flush the fifo via
     48       a nop command. so it's ok as long as the commands we pass don't go
     49       through the fifo. warning: issuing a nop command seems to need pci_fifo
     50-FIXME: in case of failure in the init sequence, be sure we return to a safe
     51        state.
     52- FIXME: Use accelerator for 2D scroll
     53-FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20)
     54 */
     55
     56/*
     57 * debug info
     58 * SST_DEBUG : enable debugging
     59 * SST_DEBUG_REG : debug registers
     60 *   0 :  no debug
     61 *   1 : dac calls, [un]set_bits, FbiInit
     62 *   2 : insane debug level (log every register read/write)
     63 * SST_DEBUG_FUNC : functions
     64 *   0 : no debug
     65 *   1 : function call / debug ioctl
     66 *   2 : variables
     67 *   3 : flood . you don't want to do that. trust me.
     68 * SST_DEBUG_VAR : debug display/var structs
     69 *   0 : no debug
     70 *   1 : dumps display, fb_var
     71 *
     72 * sstfb specific ioctls:
     73 *   		toggle vga (0x46db) : toggle vga_pass_through
     74 */
     75
     76#undef SST_DEBUG
     77
     78
     79/*
     80 * Includes
     81 */
     82
     83#include <linux/string.h>
     84#include <linux/kernel.h>
     85#include <linux/module.h>
     86#include <linux/fb.h>
     87#include <linux/pci.h>
     88#include <linux/delay.h>
     89#include <linux/init.h>
     90#include <asm/io.h>
     91#include <linux/uaccess.h>
     92#include <video/sstfb.h>
     93
     94
     95/* initialized by setup */
     96
     97static bool vgapass;		/* enable VGA passthrough cable */
     98static int mem;			/* mem size in MB, 0 = autodetect */
     99static bool clipping = 1;	/* use clipping (slower, safer) */
    100static int gfxclk;		/* force FBI freq in Mhz . Dangerous */
    101static bool slowpci;		/* slow PCI settings */
    102
    103/*
    104  Possible default video modes: 800x600@60, 640x480@75, 1024x768@76, 640x480@60
    105*/
    106#define DEFAULT_VIDEO_MODE "640x480@60"
    107
    108static char *mode_option = DEFAULT_VIDEO_MODE;
    109
    110enum {
    111	ID_VOODOO1 = 0,
    112	ID_VOODOO2 = 1,
    113};
    114
    115#define IS_VOODOO2(par) ((par)->type == ID_VOODOO2)
    116
    117static struct sst_spec voodoo_spec[] = {
    118 { .name = "Voodoo Graphics", .default_gfx_clock = 50000, .max_gfxclk = 60 },
    119 { .name = "Voodoo2",	      .default_gfx_clock = 75000, .max_gfxclk = 85 },
    120};
    121
    122
    123/*
    124 * debug functions
    125 */
    126
    127#if (SST_DEBUG_REG > 0)
    128static void sst_dbg_print_read_reg(u32 reg, u32 val) {
    129	const char *regname;
    130	switch (reg) {
    131	case FBIINIT0:	regname = "FbiInit0"; break;
    132	case FBIINIT1:	regname = "FbiInit1"; break;
    133	case FBIINIT2:	regname = "FbiInit2"; break;
    134	case FBIINIT3:	regname = "FbiInit3"; break;
    135	case FBIINIT4:	regname = "FbiInit4"; break;
    136	case FBIINIT5:	regname = "FbiInit5"; break;
    137	case FBIINIT6:	regname = "FbiInit6"; break;
    138	default:	regname = NULL;       break;
    139	}
    140	if (regname == NULL)
    141		r_ddprintk("sst_read(%#x): %#x\n", reg, val);
    142	else
    143		r_dprintk(" sst_read(%s): %#x\n", regname, val);
    144}
    145
    146static void sst_dbg_print_write_reg(u32 reg, u32 val) {
    147	const char *regname;
    148	switch (reg) {
    149	case FBIINIT0:	regname = "FbiInit0"; break;
    150	case FBIINIT1:	regname = "FbiInit1"; break;
    151	case FBIINIT2:	regname = "FbiInit2"; break;
    152	case FBIINIT3:	regname = "FbiInit3"; break;
    153	case FBIINIT4:	regname = "FbiInit4"; break;
    154	case FBIINIT5:	regname = "FbiInit5"; break;
    155	case FBIINIT6:	regname = "FbiInit6"; break;
    156	default:	regname = NULL;       break;
    157	}
    158	if (regname == NULL)
    159		r_ddprintk("sst_write(%#x, %#x)\n", reg, val);
    160	else
    161		r_dprintk(" sst_write(%s, %#x)\n", regname, val);
    162}
    163#else /*  (SST_DEBUG_REG > 0) */
    164#  define sst_dbg_print_read_reg(reg, val)	do {} while(0)
    165#  define sst_dbg_print_write_reg(reg, val)	do {} while(0)
    166#endif /*  (SST_DEBUG_REG > 0) */
    167
    168/*
    169 * hardware access functions
    170 */
    171
    172/* register access */
    173#define sst_read(reg)		__sst_read(par->mmio_vbase, reg)
    174#define sst_write(reg,val)	__sst_write(par->mmio_vbase, reg, val)
    175#define sst_set_bits(reg,val)	__sst_set_bits(par->mmio_vbase, reg, val)
    176#define sst_unset_bits(reg,val)	__sst_unset_bits(par->mmio_vbase, reg, val)
    177#define sst_dac_read(reg)	__sst_dac_read(par->mmio_vbase, reg)
    178#define sst_dac_write(reg,val)	__sst_dac_write(par->mmio_vbase, reg, val)
    179#define dac_i_read(reg)		__dac_i_read(par->mmio_vbase, reg)
    180#define dac_i_write(reg,val)	__dac_i_write(par->mmio_vbase, reg, val)
    181
    182static inline u32 __sst_read(u8 __iomem *vbase, u32 reg)
    183{
    184	u32 ret = readl(vbase + reg);
    185	sst_dbg_print_read_reg(reg, ret);
    186	return ret;
    187}
    188
    189static inline void __sst_write(u8 __iomem *vbase, u32 reg, u32 val)
    190{
    191	sst_dbg_print_write_reg(reg, val);
    192	writel(val, vbase + reg);
    193}
    194
    195static inline void __sst_set_bits(u8 __iomem *vbase, u32 reg, u32 val)
    196{
    197	r_dprintk("sst_set_bits(%#x, %#x)\n", reg, val);
    198	__sst_write(vbase, reg, __sst_read(vbase, reg) | val);
    199}
    200
    201static inline void __sst_unset_bits(u8 __iomem *vbase, u32 reg, u32 val)
    202{
    203	r_dprintk("sst_unset_bits(%#x, %#x)\n", reg, val);
    204	__sst_write(vbase, reg, __sst_read(vbase, reg) & ~val);
    205}
    206
    207/*
    208 * wait for the fbi chip. ASK: what happens if the fbi is stuck ?
    209 *
    210 * the FBI is supposed to be ready if we receive 5 time
    211 * in a row a "idle" answer to our requests
    212 */
    213
    214#define sst_wait_idle() __sst_wait_idle(par->mmio_vbase)
    215
    216static int __sst_wait_idle(u8 __iomem *vbase)
    217{
    218	int count = 0;
    219
    220	/* if (doFBINOP) __sst_write(vbase, NOPCMD, 0); */
    221
    222	while(1) {
    223		if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
    224			f_dddprintk("status: busy\n");
    225/* FIXME basically, this is a busy wait. maybe not that good. oh well;
    226 * this is a small loop after all.
    227 * Or maybe we should use mdelay() or udelay() here instead ? */
    228			count = 0;
    229		} else {
    230			count++;
    231			f_dddprintk("status: idle(%d)\n", count);
    232		}
    233		if (count >= 5) return 1;
    234/* XXX  do something to avoid hanging the machine if the voodoo is out */
    235	}
    236}
    237
    238
    239/* dac access */
    240/* dac_read should be remaped to FbiInit2 (via the pci reg init_enable) */
    241static u8 __sst_dac_read(u8 __iomem *vbase, u8 reg)
    242{
    243	u8 ret;
    244
    245	reg &= 0x07;
    246	__sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD );
    247	__sst_wait_idle(vbase);
    248	/* udelay(10); */
    249	ret = __sst_read(vbase, DAC_READ) & 0xff;
    250	r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret);
    251
    252	return ret;
    253}
    254
    255static void __sst_dac_write(u8 __iomem *vbase, u8 reg, u8 val)
    256{
    257	r_dprintk("sst_dac_write(%#x, %#x)\n", reg, val);
    258	reg &= 0x07;
    259	__sst_write(vbase, DAC_DATA,(((u32)reg << 8)) | (u32)val);
    260	__sst_wait_idle(vbase);
    261}
    262
    263/* indexed access to ti/att dacs */
    264static u32 __dac_i_read(u8 __iomem *vbase, u8 reg)
    265{
    266	u32 ret;
    267
    268	__sst_dac_write(vbase, DACREG_ADDR_I, reg);
    269	ret = __sst_dac_read(vbase, DACREG_DATA_I);
    270	r_dprintk("sst_dac_read_i(%#x): %#x\n", reg, ret);
    271	return ret;
    272}
    273static void __dac_i_write(u8 __iomem *vbase, u8 reg,u8 val)
    274{
    275	r_dprintk("sst_dac_write_i(%#x, %#x)\n", reg, val);
    276	__sst_dac_write(vbase, DACREG_ADDR_I, reg);
    277	__sst_dac_write(vbase, DACREG_DATA_I, val);
    278}
    279
    280/* compute the m,n,p  , returns the real freq
    281 * (ics datasheet :  N <-> N1 , P <-> N2)
    282 *
    283 * Fout= Fref * (M+2)/( 2^P * (N+2))
    284 *  we try to get close to the asked freq
    285 *  with P as high, and M as low as possible
    286 * range:
    287 * ti/att : 0 <= M <= 255; 0 <= P <= 3; 0<= N <= 63
    288 * ics    : 1 <= M <= 127; 0 <= P <= 3; 1<= N <= 31
    289 * we'll use the lowest limitation, should be precise enouth
    290 */
    291static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
    292{
    293	int m, m2, n, p, best_err, fout;
    294	int best_n = -1;
    295	int best_m = -1;
    296
    297	best_err = freq;
    298	p = 3;
    299	/* f * 2^P = vco should be less than VCOmax ~ 250 MHz for ics*/
    300	while (((1 << p) * freq > VCO_MAX) && (p >= 0))
    301		p--;
    302	if (p == -1)
    303		return -EINVAL;
    304	for (n = 1; n < 32; n++) {
    305		/* calc 2 * m so we can round it later*/
    306		m2 = (2 * freq * (1 << p) * (n + 2) ) / DAC_FREF - 4 ;
    307
    308		m = (m2 % 2 ) ? m2/2+1 : m2/2 ;
    309		if (m >= 128)
    310			break;
    311		fout = (DAC_FREF * (m + 2)) / ((1 << p) * (n + 2));
    312		if ((abs(fout - freq) < best_err) && (m > 0)) {
    313			best_n = n;
    314			best_m = m;
    315			best_err = abs(fout - freq);
    316			/* we get the lowest m , allowing 0.5% error in freq*/
    317			if (200*best_err < freq) break;
    318		}
    319	}
    320	if (best_n == -1)  /* unlikely, but who knows ? */
    321		return -EINVAL;
    322	t->p = p;
    323	t->n = best_n;
    324	t->m = best_m;
    325	*freq_out = (DAC_FREF * (t->m + 2)) / ((1 << t->p) * (t->n + 2));
    326	f_ddprintk ("m: %d, n: %d, p: %d, F: %dKhz\n",
    327		  t->m, t->n, t->p, *freq_out);
    328	return 0;
    329}
    330
    331/*
    332 * clear lfb screen
    333 */
    334static void sstfb_clear_screen(struct fb_info *info)
    335{
    336	/* clear screen */
    337	fb_memset(info->screen_base, 0, info->fix.smem_len);
    338}
    339
    340
    341/**
    342 *      sstfb_check_var - Optional function.  Validates a var passed in.
    343 *      @var: frame buffer variable screen structure
    344 *      @info: frame buffer structure that represents a single frame buffer
    345 *
    346 *	Limit to the abilities of a single chip as SLI is not supported
    347 *	by this driver.
    348 */
    349
    350static int sstfb_check_var(struct fb_var_screeninfo *var,
    351		struct fb_info *info)
    352{
    353	struct sstfb_par *par = info->par;
    354	int hSyncOff   = var->xres + var->right_margin + var->left_margin;
    355	int vSyncOff   = var->yres + var->lower_margin + var->upper_margin;
    356	int vBackPorch = var->left_margin, yDim = var->yres;
    357	int vSyncOn    = var->vsync_len;
    358	int tiles_in_X, real_length;
    359	unsigned int freq;
    360
    361	if (sst_calc_pll(PICOS2KHZ(var->pixclock), &freq, &par->pll)) {
    362		printk(KERN_ERR "sstfb: Pixclock at %ld KHZ out of range\n",
    363				PICOS2KHZ(var->pixclock));
    364		return -EINVAL;
    365	}
    366	var->pixclock = KHZ2PICOS(freq);
    367	
    368	if (var->vmode & FB_VMODE_INTERLACED)
    369		vBackPorch += (vBackPorch % 2);
    370	if (var->vmode & FB_VMODE_DOUBLE) {
    371		vBackPorch <<= 1;
    372		yDim <<=1;
    373		vSyncOn <<=1;
    374		vSyncOff <<=1;
    375	}
    376
    377	switch (var->bits_per_pixel) {
    378	case 0 ... 16 :
    379		var->bits_per_pixel = 16;
    380		break;
    381	default :
    382		printk(KERN_ERR "sstfb: Unsupported bpp %d\n", var->bits_per_pixel);
    383		return -EINVAL;
    384	}
    385	
    386	/* validity tests */
    387	if (var->xres <= 1 || yDim <= 0 || var->hsync_len <= 1  ||
    388	    hSyncOff <= 1  || var->left_margin <= 2  || vSyncOn <= 0 ||
    389	    vSyncOff <= 0 || vBackPorch <= 0) {
    390		return -EINVAL;
    391	}
    392
    393	if (IS_VOODOO2(par)) {
    394		/* Voodoo 2 limits */
    395		tiles_in_X = (var->xres + 63 ) / 64 * 2;		
    396
    397		if (var->xres  > POW2(11) || yDim >= POW2(11)) {
    398			printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n",
    399			         var->xres, var->yres);
    400			return -EINVAL;
    401		}
    402
    403		if (var->hsync_len > POW2(9) || hSyncOff > POW2(11) ||
    404		    var->left_margin - 2 >= POW2(9) || vSyncOn >= POW2(13) ||
    405		    vSyncOff >= POW2(13) || vBackPorch >= POW2(9) ||
    406		    tiles_in_X >= POW2(6) || tiles_in_X <= 0) {
    407			printk(KERN_ERR "sstfb: Unsupported timings\n");
    408			return -EINVAL;
    409		}
    410	} else {
    411		/* Voodoo limits */
    412		tiles_in_X = (var->xres + 63 ) / 64;
    413
    414		if (var->vmode) {
    415			printk(KERN_ERR "sstfb: Interlace/doublescan not supported %#x\n",
    416				var->vmode);
    417			return -EINVAL;
    418		}
    419		if (var->xres > POW2(10) || var->yres >= POW2(10)) {
    420			printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n",
    421			         var->xres, var->yres);
    422			return -EINVAL;
    423		}
    424		if (var->hsync_len > POW2(8) || hSyncOff - 1 > POW2(10) ||
    425		    var->left_margin - 2 >= POW2(8) || vSyncOn >= POW2(12) ||
    426		    vSyncOff >= POW2(12) || vBackPorch >= POW2(8) ||
    427		    tiles_in_X >= POW2(4) || tiles_in_X <= 0) {
    428			printk(KERN_ERR "sstfb: Unsupported timings\n");
    429			return -EINVAL;
    430		}
    431	}
    432
    433	/* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem */
    434	/* FIXME: i don't like this... looks wrong */
    435	real_length = tiles_in_X  * (IS_VOODOO2(par) ? 32 : 64 )
    436	              * ((var->bits_per_pixel == 16) ? 2 : 4);
    437
    438	if (real_length * yDim > info->fix.smem_len) {
    439		printk(KERN_ERR "sstfb: Not enough video memory\n");
    440		return -ENOMEM;
    441	}
    442
    443	var->sync &= (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
    444	var->vmode &= (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE);
    445	var->xoffset = 0;
    446	var->yoffset = 0;
    447	var->height  = -1;
    448	var->width   = -1;
    449
    450	/*
    451	 * correct the color bit fields
    452	 */
    453	/* var->{red|green|blue}.msb_right = 0; */
    454
    455	switch (var->bits_per_pixel) {
    456	case 16:	/* RGB 565  LfbMode 0 */
    457		var->red.length    = 5;
    458		var->green.length  = 6;
    459		var->blue.length   = 5;
    460		var->transp.length = 0;
    461
    462		var->red.offset    = 11;
    463		var->green.offset  = 5;
    464		var->blue.offset   = 0;
    465		var->transp.offset = 0;
    466		break;
    467	default:
    468		return -EINVAL;
    469	}
    470	return 0;
    471}
    472
    473/**
    474 *      sstfb_set_par - Optional function.  Alters the hardware state.
    475 *      @info: frame buffer structure that represents a single frame buffer
    476 */
    477static int sstfb_set_par(struct fb_info *info)
    478{
    479	struct sstfb_par *par = info->par;
    480	u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
    481	struct pci_dev *sst_dev = par->dev;
    482	unsigned int freq;
    483	int ntiles;
    484
    485	par->hSyncOff	= info->var.xres + info->var.right_margin + info->var.left_margin;
    486
    487	par->yDim 	= info->var.yres;
    488	par->vSyncOn 	= info->var.vsync_len;
    489	par->vSyncOff	= info->var.yres + info->var.lower_margin + info->var.upper_margin;
    490	par->vBackPorch = info->var.upper_margin;
    491
    492	/* We need par->pll */
    493	sst_calc_pll(PICOS2KHZ(info->var.pixclock), &freq, &par->pll);
    494
    495	if (info->var.vmode & FB_VMODE_INTERLACED)
    496		par->vBackPorch += (par->vBackPorch % 2);
    497	if (info->var.vmode & FB_VMODE_DOUBLE) {
    498		par->vBackPorch <<= 1;
    499		par->yDim <<=1;
    500		par->vSyncOn <<=1;
    501		par->vSyncOff <<=1;
    502	}
    503
    504	if (IS_VOODOO2(par)) {
    505		/* voodoo2 has 32 pixel wide tiles , BUT strange things
    506		   happen with odd number of tiles */
    507		par->tiles_in_X = (info->var.xres + 63 ) / 64 * 2;
    508	} else {
    509		/* voodoo1 has 64 pixels wide tiles. */
    510		par->tiles_in_X = (info->var.xres + 63 ) / 64;
    511	}
    512
    513	f_ddprintk("hsync_len hSyncOff vsync_len vSyncOff\n");
    514	f_ddprintk("%-7d %-8d %-7d %-8d\n",
    515	           info->var.hsync_len, par->hSyncOff,
    516	           par->vSyncOn, par->vSyncOff);
    517	f_ddprintk("left_margin upper_margin xres yres Freq\n");
    518	f_ddprintk("%-10d %-10d %-4d %-4d %-8ld\n",
    519	           info->var.left_margin, info->var.upper_margin,
    520	           info->var.xres, info->var.yres, PICOS2KHZ(info->var.pixclock));
    521
    522	sst_write(NOPCMD, 0);
    523	sst_wait_idle();
    524	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
    525	sst_set_bits(FBIINIT1, VIDEO_RESET);
    526	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
    527	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
    528	sst_wait_idle();
    529
    530	/*sst_unset_bits (FBIINIT0, FBI_RESET); / reenable FBI ? */
    531
    532	sst_write(BACKPORCH, par->vBackPorch << 16 | (info->var.left_margin - 2));
    533	sst_write(VIDEODIMENSIONS, par->yDim << 16 | (info->var.xres - 1));
    534	sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (info->var.hsync_len - 1));
    535	sst_write(VSYNC,       par->vSyncOff << 16 | par->vSyncOn);
    536
    537	fbiinit2 = sst_read(FBIINIT2);
    538	fbiinit3 = sst_read(FBIINIT3);
    539
    540	/* everything is reset. we enable fbiinit2/3 remap : dac access ok */
    541	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
    542	                       PCI_EN_INIT_WR | PCI_REMAP_DAC );
    543
    544	par->dac_sw.set_vidmod(info, info->var.bits_per_pixel);
    545
    546	/* set video clock */
    547	par->dac_sw.set_pll(info, &par->pll, VID_CLOCK);
    548
    549	/* disable fbiinit2/3 remap */
    550	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
    551	                       PCI_EN_INIT_WR);
    552
    553	/* restore fbiinit2/3 */
    554	sst_write(FBIINIT2,fbiinit2);
    555	sst_write(FBIINIT3,fbiinit3);
    556
    557	fbiinit1 = (sst_read(FBIINIT1) & VIDEO_MASK)
    558	            | EN_DATA_OE
    559	            | EN_BLANK_OE
    560	            | EN_HVSYNC_OE
    561	            | EN_DCLK_OE
    562		 /* | (15 << TILES_IN_X_SHIFT) */
    563	            | SEL_INPUT_VCLK_2X
    564		 /* | (2 << VCLK_2X_SEL_DEL_SHIFT)
    565	            | (2 << VCLK_DEL_SHIFT) */;
    566/* try with vclk_in_delay =0 (bits 29:30) , vclk_out_delay =0 (bits(27:28)
    567 in (near) future set them accordingly to revision + resolution (cf glide)
    568 first understand what it stands for :)
    569 FIXME: there are some artefacts... check for the vclk_in_delay
    570 lets try with 6ns delay in both vclk_out & in...
    571 doh... they're still there :\
    572*/
    573
    574	ntiles = par->tiles_in_X;
    575	if (IS_VOODOO2(par)) {
    576		fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT
    577		            | ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT;
    578/* as the only value of importance for us in fbiinit6 is tiles in X (lsb),
    579   and as reading fbinit 6 will return crap (see FBIINIT6_DEFAULT) we just
    580   write our value. BTW due to the dac unable to read odd number of tiles, this
    581   field is always null ... */
    582		fbiinit6 = (ntiles & 0x1) << TILES_IN_X_LSB_SHIFT;
    583	}
    584	else
    585		fbiinit1 |= ntiles << TILES_IN_X_SHIFT;
    586
    587	switch (info->var.bits_per_pixel) {
    588	case 16:
    589		fbiinit1 |=  SEL_SOURCE_VCLK_2X_SEL;
    590		break;
    591	default:
    592		return -EINVAL;
    593	}
    594	sst_write(FBIINIT1, fbiinit1);
    595	if (IS_VOODOO2(par)) {
    596		sst_write(FBIINIT6, fbiinit6);
    597		fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;
    598		if (info->var.vmode & FB_VMODE_INTERLACED)
    599			fbiinit5 |= INTERLACE;
    600		if (info->var.vmode & FB_VMODE_DOUBLE)
    601			fbiinit5 |= VDOUBLESCAN;
    602		if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
    603			fbiinit5 |= HSYNC_HIGH;
    604		if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
    605			fbiinit5 |= VSYNC_HIGH;
    606		sst_write(FBIINIT5, fbiinit5);
    607	}
    608	sst_wait_idle();
    609	sst_unset_bits(FBIINIT1, VIDEO_RESET);
    610	sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
    611	sst_set_bits(FBIINIT2, EN_DRAM_REFRESH);
    612	/* disables fbiinit writes */
    613	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
    614
    615	/* set lfbmode : set mode + front buffer for reads/writes
    616	   + disable pipeline */
    617	switch (info->var.bits_per_pixel) {
    618	case 16:
    619		lfbmode = LFB_565;
    620		break;
    621	default:
    622		return -EINVAL;
    623	}
    624
    625#if defined(__BIG_ENDIAN)
    626	/* Enable byte-swizzle functionality in hardware.
    627	 * With this enabled, all our read- and write-accesses to
    628	 * the voodoo framebuffer can be done in native format, and
    629	 * the hardware will automatically convert it to little-endian.
    630	 * - tested on HP-PARISC, Helge Deller <deller@gmx.de> */
    631	lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR |
    632		     LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD );
    633#endif
    634	
    635	if (clipping) {
    636		sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE);
    637	/*
    638	 * Set "clipping" dimensions. If clipping is disabled and
    639	 * writes to offscreen areas of the framebuffer are performed,
    640	 * the "behaviour is undefined" (_very_ undefined) - Urs
    641	 */
    642	/* btw, it requires enabling pixel pipeline in LFBMODE .
    643	   off screen read/writes will just wrap and read/print pixels
    644	   on screen. Ugly but not that dangerous */
    645		f_ddprintk("setting clipping dimensions 0..%d, 0..%d\n",
    646		            info->var.xres - 1, par->yDim - 1);
    647
    648		sst_write(CLIP_LEFT_RIGHT, info->var.xres);
    649		sst_write(CLIP_LOWY_HIGHY, par->yDim);
    650		sst_set_bits(FBZMODE, EN_CLIPPING | EN_RGB_WRITE);
    651	} else {
    652		/* no clipping : direct access, no pipeline */
    653		sst_write(LFBMODE, lfbmode);
    654	}
    655	return 0;
    656}
    657
    658/**
    659 *      sstfb_setcolreg - Optional function. Sets a color register.
    660 *      @regno: hardware colormap register
    661 *      @red: frame buffer colormap structure
    662 *      @green: The green value which can be up to 16 bits wide
    663 *      @blue:  The blue value which can be up to 16 bits wide.
    664 *      @transp: If supported the alpha value which can be up to 16 bits wide.
    665 *      @info: frame buffer info structure
    666 */
    667static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
    668                           u_int transp, struct fb_info *info)
    669{
    670	struct sstfb_par *par = info->par;
    671	u32 col;
    672
    673	f_dddprintk("sstfb_setcolreg\n");
    674	f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",
    675	            regno, red, green, blue, transp);
    676	if (regno > 15)
    677		return 0;
    678
    679	red    >>= (16 - info->var.red.length);
    680	green  >>= (16 - info->var.green.length);
    681	blue   >>= (16 - info->var.blue.length);
    682	transp >>= (16 - info->var.transp.length);
    683	col = (red << info->var.red.offset)
    684	    | (green << info->var.green.offset)
    685	    | (blue  << info->var.blue.offset)
    686	    | (transp << info->var.transp.offset);
    687	
    688	par->palette[regno] = col;
    689
    690	return 0;
    691}
    692
    693static void sstfb_setvgapass( struct fb_info *info, int enable )
    694{
    695	struct sstfb_par *par = info->par;
    696	struct pci_dev *sst_dev = par->dev;
    697	u32 fbiinit0, tmp;
    698
    699	enable = enable ? 1:0;
    700	if (par->vgapass == enable)
    701		return;
    702	par->vgapass = enable;
    703
    704	pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
    705	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
    706			       tmp | PCI_EN_INIT_WR );
    707	fbiinit0 = sst_read (FBIINIT0);
    708	if (par->vgapass) {
    709		sst_write(FBIINIT0, fbiinit0 & ~DIS_VGA_PASSTHROUGH);
    710		fb_info(info, "Enabling VGA pass-through\n");
    711	} else {
    712		sst_write(FBIINIT0, fbiinit0 | DIS_VGA_PASSTHROUGH);
    713		fb_info(info, "Disabling VGA pass-through\n");
    714	}
    715	pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
    716}
    717
    718static ssize_t store_vgapass(struct device *device, struct device_attribute *attr,
    719			const char *buf, size_t count)
    720{
    721	struct fb_info *info = dev_get_drvdata(device);
    722	char ** last = NULL;
    723	int val;
    724
    725	val = simple_strtoul(buf, last, 0);
    726	sstfb_setvgapass(info, val);
    727
    728	return count;
    729}
    730
    731static ssize_t show_vgapass(struct device *device, struct device_attribute *attr,
    732			char *buf)
    733{
    734	struct fb_info *info = dev_get_drvdata(device);
    735	struct sstfb_par *par = info->par;
    736	return sprintf(buf, "%d\n", par->vgapass);
    737}
    738
    739static struct device_attribute device_attrs[] = {
    740	__ATTR(vgapass, S_IRUGO|S_IWUSR, show_vgapass, store_vgapass)
    741	};
    742
    743static int sstfb_ioctl(struct fb_info *info, unsigned int cmd,
    744			unsigned long arg)
    745{
    746	struct sstfb_par *par;
    747	u32 val;
    748
    749	switch (cmd) {
    750	/* set/get VGA pass_through mode */
    751	case SSTFB_SET_VGAPASS:
    752		if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
    753			return -EFAULT;
    754		sstfb_setvgapass(info, val);
    755		return 0;
    756	case SSTFB_GET_VGAPASS:
    757		par = info->par;
    758		val = par->vgapass;
    759		if (copy_to_user((void __user *)arg, &val, sizeof(val)))
    760			return -EFAULT;
    761		return 0;
    762	}
    763
    764	return -EINVAL;
    765}
    766
    767
    768/*
    769 * Screen-to-Screen BitBlt 2D command (for the bmove fb op.) - Voodoo2 only
    770 */
    771#if 0
    772static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
    773{
    774	struct sstfb_par *par = info->par;
    775	u32 stride = info->fix.line_length;
    776   
    777	if (!IS_VOODOO2(par))
    778		return;
    779
    780	sst_write(BLTSRCBASEADDR, 0);
    781	sst_write(BLTDSTBASEADDR, 0);
    782	sst_write(BLTROP, BLTROP_COPY);
    783	sst_write(BLTXYSTRIDES, stride | (stride << 16));
    784	sst_write(BLTSRCXY, area->sx | (area->sy << 16));
    785	sst_write(BLTDSTXY, area->dx | (area->dy << 16));
    786	sst_write(BLTSIZE, area->width | (area->height << 16));
    787	sst_write(BLTCOMMAND, BLT_SCR2SCR_BITBLT | LAUNCH_BITBLT |
    788		(BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) );
    789	sst_wait_idle();
    790}
    791#endif
    792
    793
    794/*
    795 * FillRect 2D command (solidfill or invert (via ROP_XOR)) - Voodoo2 only
    796 */
    797#if 0
    798static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 
    799{
    800	struct sstfb_par *par = info->par;
    801	u32 stride = info->fix.line_length;
    802
    803	if (!IS_VOODOO2(par))
    804		return;
    805   	
    806	sst_write(BLTCLIPX, info->var.xres);
    807	sst_write(BLTCLIPY, info->var.yres);
    808	
    809	sst_write(BLTDSTBASEADDR, 0);
    810	sst_write(BLTCOLOR, rect->color);
    811	sst_write(BLTROP, rect->rop == ROP_COPY ? BLTROP_COPY : BLTROP_XOR);
    812	sst_write(BLTXYSTRIDES, stride | (stride << 16));
    813	sst_write(BLTDSTXY, rect->dx | (rect->dy << 16));
    814	sst_write(BLTSIZE, rect->width | (rect->height << 16));
    815	sst_write(BLTCOMMAND, BLT_RECFILL_BITBLT | LAUNCH_BITBLT
    816		 | (BLT_16BPP_FMT << 3) /* | BIT(14) */ | BIT(15) | BIT(16) );
    817	sst_wait_idle();
    818}
    819#endif
    820
    821
    822
    823/* 
    824 * get lfb size 
    825 */
    826static int sst_get_memsize(struct fb_info *info, __u32 *memsize)
    827{
    828	u8 __iomem *fbbase_virt = info->screen_base;
    829
    830	/* force memsize */
    831	if (mem >= 1  && mem <= 4) {
    832		*memsize = (mem * 0x100000);
    833		printk(KERN_INFO "supplied memsize: %#x\n", *memsize);
    834		return 1;
    835	}
    836
    837	writel(0xdeadbeef, fbbase_virt);
    838	writel(0xdeadbeef, fbbase_virt+0x100000);
    839	writel(0xdeadbeef, fbbase_virt+0x200000);
    840	f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",
    841	           readl(fbbase_virt), readl(fbbase_virt + 0x100000),
    842	           readl(fbbase_virt + 0x200000));
    843
    844	writel(0xabcdef01, fbbase_virt);
    845
    846	f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",
    847	           readl(fbbase_virt), readl(fbbase_virt + 0x100000),
    848	           readl(fbbase_virt + 0x200000));
    849
    850	/* checks for 4mb lfb, then 2, then defaults to 1 */
    851	if (readl(fbbase_virt + 0x200000) == 0xdeadbeef)
    852		*memsize = 0x400000;
    853	else if (readl(fbbase_virt + 0x100000) == 0xdeadbeef)
    854		*memsize = 0x200000;
    855	else
    856		*memsize = 0x100000;
    857	f_ddprintk("detected memsize: %dMB\n", *memsize >> 20);
    858	return 1;
    859}
    860
    861
    862/* 
    863 * DAC detection routines 
    864 */
    865
    866/* fbi should be idle, and fifo emty and mem disabled */
    867/* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */
    868
    869static int sst_detect_att(struct fb_info *info)
    870{
    871	struct sstfb_par *par = info->par;
    872	int i, mir, dir;
    873
    874	for (i = 0; i < 3; i++) {
    875		sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
    876		sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
    877		sst_dac_read(DACREG_RMR);
    878		sst_dac_read(DACREG_RMR);
    879		sst_dac_read(DACREG_RMR);
    880		/* the fifth time,  CR0 is read */
    881		sst_dac_read(DACREG_RMR);
    882		/* the 6th, manufacturer id register */
    883		mir = sst_dac_read(DACREG_RMR);
    884		/*the 7th, device ID register */
    885		dir = sst_dac_read(DACREG_RMR);
    886		f_ddprintk("mir: %#x, dir: %#x\n", mir, dir);
    887		if (mir == DACREG_MIR_ATT && dir == DACREG_DIR_ATT) {
    888			return 1;
    889		}
    890	}
    891	return 0;
    892}
    893
    894static int sst_detect_ti(struct fb_info *info)
    895{
    896	struct sstfb_par *par = info->par;
    897	int i, mir, dir;
    898
    899	for (i = 0; i<3; i++) {
    900		sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
    901		sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
    902		sst_dac_read(DACREG_RMR);
    903		sst_dac_read(DACREG_RMR);
    904		sst_dac_read(DACREG_RMR);
    905		/* the fifth time,  CR0 is read */
    906		sst_dac_read(DACREG_RMR);
    907		/* the 6th, manufacturer id register */
    908		mir = sst_dac_read(DACREG_RMR);
    909		/*the 7th, device ID register */
    910		dir = sst_dac_read(DACREG_RMR);
    911		f_ddprintk("mir: %#x, dir: %#x\n", mir, dir);
    912		if ((mir == DACREG_MIR_TI ) && (dir == DACREG_DIR_TI)) {
    913			return 1;
    914		}
    915	}
    916	return 0;
    917}
    918
    919/*
    920 * try to detect ICS5342  ramdac
    921 * we get the 1st byte (M value) of preset f1,f7 and fB
    922 * why those 3 ? mmmh... for now, i'll do it the glide way...
    923 * and ask questions later. anyway, it seems that all the freq registers are
    924 * really at their default state (cf specs) so i ask again, why those 3 regs ?
    925 * mmmmh.. it seems that's much more ugly than i thought. we use f0 and fA for
    926 * pll programming, so in fact, we *hope* that the f1, f7 & fB won't be
    927 * touched...
    928 * is it really safe ? how can i reset this ramdac ? geee...
    929 */
    930static int sst_detect_ics(struct fb_info *info)
    931{
    932	struct sstfb_par *par = info->par;
    933	int m_clk0_1, m_clk0_7, m_clk1_b;
    934	int n_clk0_1, n_clk0_7, n_clk1_b;
    935	int i;
    936
    937	for (i = 0; i<5; i++ ) {
    938		sst_dac_write(DACREG_ICS_PLLRMA, 0x1);	/* f1 */
    939		m_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);
    940		n_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);
    941		sst_dac_write(DACREG_ICS_PLLRMA, 0x7);	/* f7 */
    942		m_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA);
    943		n_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA);
    944		sst_dac_write(DACREG_ICS_PLLRMA, 0xb);	/* fB */
    945		m_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA);
    946		n_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA);
    947		f_ddprintk("m_clk0_1: %#x, m_clk0_7: %#x, m_clk1_b: %#x\n",
    948			m_clk0_1, m_clk0_7, m_clk1_b);
    949		f_ddprintk("n_clk0_1: %#x, n_clk0_7: %#x, n_clk1_b: %#x\n",
    950			n_clk0_1, n_clk0_7, n_clk1_b);
    951		if ((   m_clk0_1 == DACREG_ICS_PLL_CLK0_1_INI)
    952		    && (m_clk0_7 == DACREG_ICS_PLL_CLK0_7_INI)
    953		    && (m_clk1_b == DACREG_ICS_PLL_CLK1_B_INI)) {
    954			return 1;
    955		}
    956	}
    957	return 0;
    958}
    959
    960
    961/*
    962 * gfx, video, pci fifo should be reset, dram refresh disabled
    963 * see detect_dac
    964 */
    965
    966static int sst_set_pll_att_ti(struct fb_info *info, 
    967		const struct pll_timing *t, const int clock)
    968{
    969	struct sstfb_par *par = info->par;
    970	u8 cr0, cc;
    971
    972	/* enable indexed mode */
    973	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
    974	sst_dac_read(DACREG_RMR);	/* 1 time:  RMR */
    975	sst_dac_read(DACREG_RMR);	/* 2 RMR */
    976	sst_dac_read(DACREG_RMR);	/* 3 //  */
    977	sst_dac_read(DACREG_RMR);	/* 4 //  */
    978	cr0 = sst_dac_read(DACREG_RMR);	/* 5 CR0 */
    979
    980	sst_dac_write(DACREG_WMA, 0);
    981	sst_dac_read(DACREG_RMR);
    982	sst_dac_read(DACREG_RMR);
    983	sst_dac_read(DACREG_RMR);
    984	sst_dac_read(DACREG_RMR);
    985	sst_dac_write(DACREG_RMR, (cr0 & 0xf0)
    986	              | DACREG_CR0_EN_INDEXED
    987	              | DACREG_CR0_8BIT
    988	              | DACREG_CR0_PWDOWN );
    989	/* so, now we are in indexed mode . dunno if its common, but
    990	   i find this way of doing things a little bit weird :p */
    991
    992	udelay(300);
    993	cc = dac_i_read(DACREG_CC_I);
    994	switch (clock) {
    995	case VID_CLOCK:
    996		dac_i_write(DACREG_AC0_I, t->m);
    997		dac_i_write(DACREG_AC1_I, t->p << 6 | t->n);
    998		dac_i_write(DACREG_CC_I,
    999		            (cc & 0x0f) | DACREG_CC_CLKA | DACREG_CC_CLKA_C);
   1000		break;
   1001	case GFX_CLOCK:
   1002		dac_i_write(DACREG_BD0_I, t->m);
   1003		dac_i_write(DACREG_BD1_I, t->p << 6 | t->n);
   1004		dac_i_write(DACREG_CC_I,
   1005		            (cc & 0xf0) | DACREG_CC_CLKB | DACREG_CC_CLKB_D);
   1006		break;
   1007	default:
   1008		dprintk("%s: wrong clock code '%d'\n",
   1009		        __func__, clock);
   1010		return 0;
   1011		}
   1012	udelay(300);
   1013
   1014	/* power up the dac & return to "normal" non-indexed mode */
   1015	dac_i_write(DACREG_CR0_I,
   1016	            cr0 & ~DACREG_CR0_PWDOWN & ~DACREG_CR0_EN_INDEXED);
   1017	return 1;
   1018}
   1019
   1020static int sst_set_pll_ics(struct fb_info *info,
   1021		const struct pll_timing *t, const int clock)
   1022{
   1023	struct sstfb_par *par = info->par;
   1024	u8 pll_ctrl;
   1025
   1026	sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);
   1027	pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA);
   1028	switch(clock) {
   1029	case VID_CLOCK:
   1030		sst_dac_write(DACREG_ICS_PLLWMA, 0x0);	/* CLK0, f0 */
   1031		sst_dac_write(DACREG_ICS_PLLDATA, t->m);
   1032		sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);
   1033		/* selects freq f0 for clock 0 */
   1034		sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
   1035		sst_dac_write(DACREG_ICS_PLLDATA,
   1036		              (pll_ctrl & 0xd8)
   1037		              | DACREG_ICS_CLK0
   1038		              | DACREG_ICS_CLK0_0);
   1039		break;
   1040	case GFX_CLOCK :
   1041		sst_dac_write(DACREG_ICS_PLLWMA, 0xa);	/* CLK1, fA */
   1042		sst_dac_write(DACREG_ICS_PLLDATA, t->m);
   1043		sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);
   1044		/* selects freq fA for clock 1 */
   1045		sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
   1046		sst_dac_write(DACREG_ICS_PLLDATA,
   1047		              (pll_ctrl & 0xef) | DACREG_ICS_CLK1_A);
   1048		break;
   1049	default:
   1050		dprintk("%s: wrong clock code '%d'\n",
   1051		        __func__, clock);
   1052		return 0;
   1053		}
   1054	udelay(300);
   1055	return 1;
   1056}
   1057
   1058static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
   1059{
   1060	struct sstfb_par *par = info->par;
   1061	u8 cr0;
   1062
   1063	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
   1064	sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
   1065	sst_dac_read(DACREG_RMR);
   1066	sst_dac_read(DACREG_RMR);
   1067	sst_dac_read(DACREG_RMR);
   1068	/* the fifth time,  CR0 is read */
   1069	cr0 = sst_dac_read(DACREG_RMR);
   1070
   1071	sst_dac_write(DACREG_WMA, 0); 	/* backdoor */
   1072	sst_dac_read(DACREG_RMR);	/* read 4 times RMR */
   1073	sst_dac_read(DACREG_RMR);
   1074	sst_dac_read(DACREG_RMR);
   1075	sst_dac_read(DACREG_RMR);
   1076	/* cr0 */
   1077	switch(bpp) {
   1078	case 16:
   1079		sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP);
   1080		break;
   1081	default:
   1082		dprintk("%s: bad depth '%u'\n", __func__, bpp);
   1083		break;
   1084	}
   1085}
   1086
   1087static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
   1088{
   1089	struct sstfb_par *par = info->par;
   1090
   1091	switch(bpp) {
   1092	case 16:
   1093		sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP);
   1094		break;
   1095	default:
   1096		dprintk("%s: bad depth '%u'\n", __func__, bpp);
   1097		break;
   1098	}
   1099}
   1100
   1101/*
   1102 * detect dac type
   1103 * prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset,
   1104 * dram refresh disabled, FbiInit remaped.
   1105 * TODO: mmh.. maybe i should put the "prerequisite" in the func ...
   1106 */
   1107
   1108
   1109static struct dac_switch dacs[] = {
   1110	{	.name		= "TI TVP3409",
   1111		.detect		= sst_detect_ti,
   1112		.set_pll	= sst_set_pll_att_ti,
   1113		.set_vidmod	= sst_set_vidmod_att_ti },
   1114
   1115	{	.name		= "AT&T ATT20C409",
   1116		.detect		= sst_detect_att,
   1117		.set_pll	= sst_set_pll_att_ti,
   1118		.set_vidmod	= sst_set_vidmod_att_ti },
   1119	{	.name		= "ICS ICS5342",
   1120		.detect		= sst_detect_ics,
   1121		.set_pll	= sst_set_pll_ics,
   1122		.set_vidmod	= sst_set_vidmod_ics },
   1123};
   1124
   1125static int sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
   1126{
   1127	int i, ret = 0;
   1128
   1129	for (i = 0; i < ARRAY_SIZE(dacs); i++) {
   1130		ret = dacs[i].detect(info);
   1131		if (ret)
   1132			break;
   1133	}
   1134	if (!ret)
   1135		return 0;
   1136	f_dprintk("%s found %s\n", __func__, dacs[i].name);
   1137	par->dac_sw = dacs[i];
   1138	return 1;
   1139}
   1140
   1141/*
   1142 * Internal Routines
   1143 */
   1144static int sst_init(struct fb_info *info, struct sstfb_par *par)
   1145{
   1146	u32 fbiinit0, fbiinit1, fbiinit4;
   1147	struct pci_dev *dev = par->dev;
   1148	struct pll_timing gfx_timings;
   1149	struct sst_spec *spec;
   1150	int Fout;
   1151	int gfx_clock;
   1152
   1153	spec = &voodoo_spec[par->type];
   1154	f_ddprintk(" fbiinit0   fbiinit1   fbiinit2   fbiinit3   fbiinit4  "
   1155	           " fbiinit6\n");
   1156	f_ddprintk("%0#10x %0#10x %0#10x %0#10x %0#10x %0#10x\n",
   1157	            sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2),
   1158	            sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6));
   1159	/* disable video clock */
   1160	pci_write_config_dword(dev, PCI_VCLK_DISABLE, 0);
   1161
   1162	/* enable writing to init registers, disable pci fifo */
   1163	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
   1164	/* reset video */
   1165	sst_set_bits(FBIINIT1, VIDEO_RESET);
   1166	sst_wait_idle();
   1167	/* reset gfx + pci fifo */
   1168	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
   1169	sst_wait_idle();
   1170
   1171	/* unreset fifo */
   1172	/*sst_unset_bits(FBIINIT0, FIFO_RESET);
   1173	sst_wait_idle();*/
   1174	/* unreset FBI */
   1175	/*sst_unset_bits(FBIINIT0, FBI_RESET);
   1176	sst_wait_idle();*/
   1177
   1178	/* disable dram refresh */
   1179	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
   1180	sst_wait_idle();
   1181	/* remap fbinit2/3 to dac */
   1182	pci_write_config_dword(dev, PCI_INIT_ENABLE,
   1183				PCI_EN_INIT_WR | PCI_REMAP_DAC );
   1184	/* detect dac type */
   1185	if (!sst_detect_dactype(info, par)) {
   1186		printk(KERN_ERR "sstfb: unknown dac type.\n");
   1187		//FIXME watch it: we are not in a safe state, bad bad bad.
   1188		return 0;
   1189	}
   1190
   1191	/* set graphic clock */
   1192	gfx_clock = spec->default_gfx_clock;
   1193	if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {
   1194		printk(KERN_INFO "sstfb: Using supplied graphic freq : %dMHz\n", gfxclk);
   1195		 gfx_clock = gfxclk *1000;
   1196	} else if (gfxclk) {
   1197		printk(KERN_WARNING "sstfb: %dMhz is way out of spec! Using default\n", gfxclk);
   1198	}
   1199
   1200	sst_calc_pll(gfx_clock, &Fout, &gfx_timings);
   1201	par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
   1202
   1203	/* disable fbiinit remap */
   1204	pci_write_config_dword(dev, PCI_INIT_ENABLE,
   1205	                       PCI_EN_INIT_WR| PCI_EN_FIFO_WR );
   1206	/* defaults init registers */
   1207	/* FbiInit0: unreset gfx, unreset fifo */
   1208	fbiinit0 = FBIINIT0_DEFAULT;
   1209	fbiinit1 = FBIINIT1_DEFAULT;
   1210	fbiinit4 = FBIINIT4_DEFAULT;
   1211	par->vgapass = vgapass;
   1212	if (par->vgapass)
   1213		fbiinit0 &= ~DIS_VGA_PASSTHROUGH;
   1214	else
   1215		fbiinit0 |= DIS_VGA_PASSTHROUGH;
   1216	if (slowpci) {
   1217		fbiinit1 |= SLOW_PCI_WRITES;
   1218		fbiinit4 |= SLOW_PCI_READS;
   1219	} else {
   1220		fbiinit1 &= ~SLOW_PCI_WRITES;
   1221		fbiinit4 &= ~SLOW_PCI_READS;
   1222	}
   1223	sst_write(FBIINIT0, fbiinit0);
   1224	sst_wait_idle();
   1225	sst_write(FBIINIT1, fbiinit1);
   1226	sst_wait_idle();
   1227	sst_write(FBIINIT2, FBIINIT2_DEFAULT);
   1228	sst_wait_idle();
   1229	sst_write(FBIINIT3, FBIINIT3_DEFAULT);
   1230	sst_wait_idle();
   1231	sst_write(FBIINIT4, fbiinit4);
   1232	sst_wait_idle();
   1233	if (IS_VOODOO2(par)) {
   1234		sst_write(FBIINIT6, FBIINIT6_DEFAULT);
   1235		sst_wait_idle();
   1236	}
   1237
   1238	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
   1239	pci_write_config_dword(dev, PCI_VCLK_ENABLE, 0);
   1240	return 1;
   1241}
   1242
   1243static void sst_shutdown(struct fb_info *info)
   1244{
   1245	struct sstfb_par *par = info->par;
   1246	struct pci_dev *dev = par->dev;
   1247	struct pll_timing gfx_timings;
   1248	int Fout;
   1249
   1250	/* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */
   1251	pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
   1252	sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING);
   1253	sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
   1254	sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
   1255	sst_wait_idle();
   1256	pci_write_config_dword(dev, PCI_INIT_ENABLE,
   1257	                       PCI_EN_INIT_WR | PCI_REMAP_DAC);
   1258	/* set 20Mhz gfx clock */
   1259	sst_calc_pll(20000, &Fout, &gfx_timings);
   1260	par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
   1261	/* TODO maybe shutdown the dac, vrefresh and so on... */
   1262	pci_write_config_dword(dev, PCI_INIT_ENABLE,
   1263	                       PCI_EN_INIT_WR);
   1264	sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | DIS_VGA_PASSTHROUGH);
   1265	pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
   1266	/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct
   1267	 * from start ? */
   1268	pci_write_config_dword(dev, PCI_INIT_ENABLE, 0);
   1269
   1270}
   1271
   1272/*
   1273 * Interface to the world
   1274 */
   1275static int sstfb_setup(char *options)
   1276{
   1277	char *this_opt;
   1278
   1279	if (!options || !*options)
   1280		return 0;
   1281
   1282	while ((this_opt = strsep(&options, ",")) != NULL) {
   1283		if (!*this_opt) continue;
   1284
   1285		f_ddprintk("option %s\n", this_opt);
   1286
   1287		if (!strcmp(this_opt, "vganopass"))
   1288			vgapass = 0;
   1289		else if (!strcmp(this_opt, "vgapass"))
   1290			vgapass = 1;
   1291		else if (!strcmp(this_opt, "clipping"))
   1292		        clipping = 1;
   1293		else if (!strcmp(this_opt, "noclipping"))
   1294		        clipping = 0;
   1295		else if (!strcmp(this_opt, "fastpci"))
   1296		        slowpci = 0;
   1297		else if (!strcmp(this_opt, "slowpci"))
   1298		        slowpci = 1;
   1299		else if (!strncmp(this_opt, "mem:",4))
   1300			mem = simple_strtoul (this_opt+4, NULL, 0);
   1301		else if (!strncmp(this_opt, "gfxclk:",7))
   1302			gfxclk = simple_strtoul (this_opt+7, NULL, 0);
   1303		else
   1304			mode_option = this_opt;
   1305	}
   1306	return 0;
   1307}
   1308
   1309
   1310static const struct fb_ops sstfb_ops = {
   1311	.owner		= THIS_MODULE,
   1312	.fb_check_var	= sstfb_check_var,
   1313	.fb_set_par	= sstfb_set_par,
   1314	.fb_setcolreg	= sstfb_setcolreg,
   1315	.fb_fillrect	= cfb_fillrect, /* sstfb_fillrect */
   1316	.fb_copyarea	= cfb_copyarea, /* sstfb_copyarea */
   1317	.fb_imageblit	= cfb_imageblit,
   1318	.fb_ioctl	= sstfb_ioctl,
   1319};
   1320
   1321static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
   1322{
   1323	struct fb_info *info;
   1324	struct fb_fix_screeninfo *fix;
   1325	struct sstfb_par *par;
   1326	struct sst_spec *spec;
   1327	int err;
   1328
   1329	/* Enable device in PCI config. */
   1330	if ((err=pci_enable_device(pdev))) {
   1331		printk(KERN_ERR "cannot enable device\n");
   1332		return err;
   1333	}
   1334
   1335	/* Allocate the fb and par structures.  */
   1336	info = framebuffer_alloc(sizeof(struct sstfb_par), &pdev->dev);
   1337	if (!info)
   1338		return -ENOMEM;
   1339
   1340	pci_set_drvdata(pdev, info);
   1341	
   1342	par  = info->par;
   1343	fix  = &info->fix;
   1344	
   1345	par->type = id->driver_data;
   1346	spec = &voodoo_spec[par->type];
   1347	f_ddprintk("found device : %s\n", spec->name);
   1348
   1349	par->dev = pdev;
   1350	par->revision = pdev->revision;
   1351
   1352	fix->mmio_start = pci_resource_start(pdev,0);
   1353	fix->mmio_len	= 0x400000;
   1354	fix->smem_start = fix->mmio_start + 0x400000;
   1355
   1356	if (!request_mem_region(fix->mmio_start, fix->mmio_len, "sstfb MMIO")) {
   1357		printk(KERN_ERR "sstfb: cannot reserve mmio memory\n");
   1358		goto fail_mmio_mem;
   1359	}
   1360
   1361	if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) {
   1362		printk(KERN_ERR "sstfb: cannot reserve fb memory\n");
   1363		goto fail_fb_mem;
   1364	}
   1365
   1366	par->mmio_vbase = ioremap(fix->mmio_start,
   1367					fix->mmio_len);
   1368	if (!par->mmio_vbase) {
   1369		printk(KERN_ERR "sstfb: cannot remap register area %#lx\n",
   1370		        fix->mmio_start);
   1371		goto fail_mmio_remap;
   1372	}
   1373	info->screen_base = ioremap(fix->smem_start, 0x400000);
   1374	if (!info->screen_base) {
   1375		printk(KERN_ERR "sstfb: cannot remap framebuffer %#lx\n",
   1376		        fix->smem_start);
   1377		goto fail_fb_remap;
   1378	}
   1379
   1380	if (!sst_init(info, par)) {
   1381		printk(KERN_ERR "sstfb: Init failed\n");
   1382		goto fail;
   1383	}
   1384	sst_get_memsize(info, &fix->smem_len);
   1385	strlcpy(fix->id, spec->name, sizeof(fix->id));
   1386
   1387	printk(KERN_INFO "%s (revision %d) with %s dac\n",
   1388		fix->id, par->revision, par->dac_sw.name);
   1389	printk(KERN_INFO "framebuffer at %#lx, mapped to 0x%p, size %dMB\n",
   1390	        fix->smem_start, info->screen_base,
   1391	        fix->smem_len >> 20);
   1392
   1393	f_ddprintk("regbase_virt: %p\n", par->mmio_vbase);
   1394	f_ddprintk("membase_phys: %#lx\n", fix->smem_start);
   1395	f_ddprintk("fbbase_virt: %p\n", info->screen_base);
   1396
   1397	info->flags	= FBINFO_DEFAULT;
   1398	info->fbops	= &sstfb_ops;
   1399	info->pseudo_palette = par->palette;
   1400
   1401	fix->type	= FB_TYPE_PACKED_PIXELS;
   1402	fix->visual	= FB_VISUAL_TRUECOLOR;
   1403	fix->accel	= FB_ACCEL_NONE;  /* FIXME */
   1404	/*
   1405	 * According to the specs, the linelength must be of 1024 *pixels*
   1406	 * and the 24bpp mode is in fact a 32 bpp mode (and both are in
   1407	 * fact dithered to 16bit).
   1408	 */
   1409	fix->line_length = 2048; /* default value, for 24 or 32bit: 4096 */
   1410	
   1411	fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
   1412
   1413	if (sstfb_check_var(&info->var, info)) {
   1414		printk(KERN_ERR "sstfb: invalid video mode.\n");
   1415		goto fail;
   1416	}
   1417
   1418	if (sstfb_set_par(info)) {
   1419		printk(KERN_ERR "sstfb: can't set default video mode.\n");
   1420		goto fail;
   1421	}
   1422	
   1423	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
   1424		printk(KERN_ERR "sstfb: can't alloc cmap memory.\n");
   1425		goto fail;
   1426	}
   1427
   1428	/* register fb */
   1429	info->device = &pdev->dev;
   1430	if (register_framebuffer(info) < 0) {
   1431		printk(KERN_ERR "sstfb: can't register framebuffer.\n");
   1432		goto fail_register;
   1433	}
   1434
   1435	sstfb_clear_screen(info);
   1436
   1437	if (device_create_file(info->dev, &device_attrs[0]))
   1438		printk(KERN_WARNING "sstfb: can't create sysfs entry.\n");
   1439
   1440
   1441	fb_info(info, "%s frame buffer device at 0x%p\n",
   1442		fix->id, info->screen_base);
   1443
   1444	return 0;
   1445
   1446fail_register:
   1447	fb_dealloc_cmap(&info->cmap);
   1448fail:
   1449	iounmap(info->screen_base);
   1450fail_fb_remap:
   1451	iounmap(par->mmio_vbase);
   1452fail_mmio_remap:
   1453	release_mem_region(fix->smem_start, 0x400000);
   1454fail_fb_mem:
   1455	release_mem_region(fix->mmio_start, info->fix.mmio_len);
   1456fail_mmio_mem:
   1457	framebuffer_release(info);
   1458	return -ENXIO; 	/* no voodoo detected */
   1459}
   1460
   1461static void sstfb_remove(struct pci_dev *pdev)
   1462{
   1463	struct sstfb_par *par;
   1464	struct fb_info *info;
   1465
   1466	info = pci_get_drvdata(pdev);
   1467	par = info->par;
   1468	
   1469	device_remove_file(info->dev, &device_attrs[0]);
   1470	sst_shutdown(info);
   1471	iounmap(info->screen_base);
   1472	iounmap(par->mmio_vbase);
   1473	release_mem_region(info->fix.smem_start, 0x400000);
   1474	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
   1475	fb_dealloc_cmap(&info->cmap);
   1476	unregister_framebuffer(info);
   1477	framebuffer_release(info);
   1478}
   1479
   1480
   1481static const struct pci_device_id sstfb_id_tbl[] = {
   1482	{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO ),
   1483		.driver_data = ID_VOODOO1, },
   1484	{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2),
   1485		.driver_data = ID_VOODOO2, },
   1486	{ 0 },
   1487};
   1488
   1489static struct pci_driver sstfb_driver = {
   1490	.name		= "sstfb",
   1491	.id_table	= sstfb_id_tbl,
   1492	.probe		= sstfb_probe,
   1493	.remove		= sstfb_remove,
   1494};
   1495
   1496
   1497static int sstfb_init(void)
   1498{
   1499	char *option = NULL;
   1500
   1501	if (fb_get_options("sstfb", &option))
   1502		return -ENODEV;
   1503	sstfb_setup(option);
   1504
   1505	return pci_register_driver(&sstfb_driver);
   1506}
   1507
   1508static void sstfb_exit(void)
   1509{
   1510	pci_unregister_driver(&sstfb_driver);
   1511}
   1512
   1513
   1514module_init(sstfb_init);
   1515module_exit(sstfb_exit);
   1516
   1517MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");
   1518MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");
   1519MODULE_LICENSE("GPL");
   1520
   1521module_param(mem, int, 0);
   1522MODULE_PARM_DESC(mem, "Size of frame buffer memory in MB (1, 2, 4 MB, default=autodetect)");
   1523module_param(vgapass, bool, 0);
   1524MODULE_PARM_DESC(vgapass, "Enable VGA PassThrough mode (0 or 1) (default=0)");
   1525module_param(clipping, bool, 0);
   1526MODULE_PARM_DESC(clipping, "Enable clipping (slower, safer) (0 or 1) (default=1)");
   1527module_param(gfxclk, int, 0);
   1528MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");
   1529module_param(slowpci, bool, 0);
   1530MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
   1531module_param(mode_option, charp, 0);
   1532MODULE_PARM_DESC(mode_option, "Initial video mode (default=" DEFAULT_VIDEO_MODE ")");
   1533