vserver 1.9.5.x5
[linux-2.6.git] / drivers / video / tdfxfb.c
1 /*
2  *
3  * tdfxfb.c
4  *
5  * Author: Hannu Mallat <hmallat@cc.hut.fi>
6  *
7  * Copyright © 1999 Hannu Mallat
8  * All rights reserved
9  *
10  * Created      : Thu Sep 23 18:17:43 1999, hmallat
11  * Last modified: Tue Nov  2 21:19:47 1999, hmallat
12  *
13  * Lots of the information here comes from the Daryll Strauss' Banshee 
14  * patches to the XF86 server, and the rest comes from the 3dfx
15  * Banshee specification. I'm very much indebted to Daryll for his
16  * work on the X server.
17  *
18  * Voodoo3 support was contributed Harold Oga. Lots of additions
19  * (proper acceleration, 24 bpp, hardware cursor) and bug fixes by Attila
20  * Kesmarki. Thanks guys!
21  *
22  * Voodoo1 and Voodoo2 support aren't relevant to this driver as they
23  * behave very differently from the Voodoo3/4/5. For anyone wanting to
24  * use frame buffer on the Voodoo1/2, see the sstfb driver (which is
25  * located at http://www.sourceforge.net/projects/sstfb).
26  * 
27  * While I _am_ grateful to 3Dfx for releasing the specs for Banshee,
28  * I do wish the next version is a bit more complete. Without the XF86
29  * patches I couldn't have gotten even this far... for instance, the
30  * extensions to the VGA register set go completely unmentioned in the
31  * spec! Also, lots of references are made to the 'SST core', but no
32  * spec is publicly available, AFAIK.
33  *
34  * The structure of this driver comes pretty much from the Permedia
35  * driver by Ilario Nardinocchi, which in turn is based on skeletonfb.
36  * 
37  * TODO:
38  * - support for 16/32 bpp needs fixing (funky bootup penguin)
39  * - multihead support (basically need to support an array of fb_infos)
40  * - support other architectures (PPC, Alpha); does the fact that the VGA
41  *   core can be accessed only thru I/O (not memory mapped) complicate
42  *   things?
43  *
44  * Version history:
45  *
46  * 0.1.4 (released 2002-05-28) ported over to new fbdev api by James Simmons
47  *
48  * 0.1.3 (released 1999-11-02) added Attila's panning support, code
49  *                             reorg, hwcursor address page size alignment
50  *                             (for mmaping both frame buffer and regs),
51  *                             and my changes to get rid of hardcoded
52  *                             VGA i/o register locations (uses PCI
53  *                             configuration info now)
54  * 0.1.2 (released 1999-10-19) added Attila Kesmarki's bug fixes and
55  *                             improvements
56  * 0.1.1 (released 1999-10-07) added Voodoo3 support by Harold Oga.
57  * 0.1.0 (released 1999-10-06) initial version
58  *
59  */
60
61 #include <linux/config.h>
62 #include <linux/module.h>
63 #include <linux/kernel.h>
64 #include <linux/errno.h>
65 #include <linux/string.h>
66 #include <linux/mm.h>
67 #include <linux/tty.h>
68 #include <linux/slab.h>
69 #include <linux/delay.h>
70 #include <linux/interrupt.h>
71 #include <linux/fb.h>
72 #include <linux/init.h>
73 #include <linux/pci.h>
74 #include <linux/nvram.h>
75 #include <asm/io.h>
76 #include <linux/timer.h>
77 #include <linux/spinlock.h>
78
79 #include <video/tdfx.h>
80
81 #undef TDFXFB_DEBUG 
82 #ifdef TDFXFB_DEBUG
83 #define DPRINTK(a,b...) printk(KERN_DEBUG "fb: %s: " a, __FUNCTION__ , ## b)
84 #else
85 #define DPRINTK(a,b...)
86 #endif 
87
88 #define BANSHEE_MAX_PIXCLOCK 270000
89 #define VOODOO3_MAX_PIXCLOCK 300000
90 #define VOODOO5_MAX_PIXCLOCK 350000
91
92 static struct fb_fix_screeninfo tdfx_fix __initdata = {
93         .id =           "3Dfx",
94         .type =         FB_TYPE_PACKED_PIXELS,
95         .visual =       FB_VISUAL_PSEUDOCOLOR, 
96         .ypanstep =     1,
97         .ywrapstep =    1, 
98         .accel =        FB_ACCEL_3DFX_BANSHEE
99 };
100
101 static struct fb_var_screeninfo tdfx_var __initdata = {
102         /* "640x480, 8 bpp @ 60 Hz */
103         .xres =         640,
104         .yres =         480,
105         .xres_virtual = 640,
106         .yres_virtual = 1024,
107         .bits_per_pixel =8,
108         .red =          {0, 8, 0},
109         .blue =         {0, 8, 0},
110         .green =        {0, 8, 0},
111         .activate =     FB_ACTIVATE_NOW,
112         .height =       -1,
113         .width =        -1,
114         .accel_flags =  FB_ACCELF_TEXT,
115         .pixclock =     39722,
116         .left_margin =  40,
117         .right_margin = 24,
118         .upper_margin = 32,
119         .lower_margin = 11,
120         .hsync_len =    96,
121         .vsync_len =    2,
122         .vmode =        FB_VMODE_NONINTERLACED
123 };
124
125 /*
126  * PCI driver prototypes
127  */
128 static int __devinit tdfxfb_probe(struct pci_dev *pdev,
129                                   const struct pci_device_id *id);
130 static void __devexit tdfxfb_remove(struct pci_dev *pdev);
131
132 static struct pci_device_id tdfxfb_id_table[] = {
133         { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE,
134           PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
135           0xff0000, 0 },
136         { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3,
137           PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
138           0xff0000, 0 },
139         { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5,
140           PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
141           0xff0000, 0 },
142         { 0, }
143 };
144
145 static struct pci_driver tdfxfb_driver = {
146         .name           = "tdfxfb",
147         .id_table       = tdfxfb_id_table,
148         .probe          = tdfxfb_probe,
149         .remove         = __devexit_p(tdfxfb_remove),
150 };
151
152 MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
153
154 /*
155  *  Frame buffer device API
156  */
157 int tdfxfb_init(void);
158 void tdfxfb_setup(char *options);
159
160 static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb); 
161 static int tdfxfb_set_par(struct fb_info *info); 
162 static int tdfxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 
163                             u_int transp, struct fb_info *info); 
164 static int tdfxfb_blank(int blank, struct fb_info *info); 
165 static int tdfxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
166 static int banshee_wait_idle(struct fb_info *info);
167 #ifdef CONFIG_FB_3DFX_ACCEL
168 static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
169 static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);  
170 static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image); 
171 #endif /* CONFIG_FB_3DFX_ACCEL */
172
173 static struct fb_ops tdfxfb_ops = {
174         .owner          = THIS_MODULE,
175         .fb_check_var   = tdfxfb_check_var,
176         .fb_set_par     = tdfxfb_set_par,
177         .fb_setcolreg   = tdfxfb_setcolreg,
178         .fb_blank       = tdfxfb_blank,
179         .fb_pan_display = tdfxfb_pan_display,
180         .fb_sync        = banshee_wait_idle,
181 #ifdef CONFIG_FB_3DFX_ACCEL
182         .fb_fillrect    = tdfxfb_fillrect,
183         .fb_copyarea    = tdfxfb_copyarea,
184         .fb_imageblit   = tdfxfb_imageblit,
185 #else
186         .fb_fillrect    = cfb_fillrect,
187         .fb_copyarea    = cfb_copyarea,
188         .fb_imageblit   = cfb_imageblit,
189 #endif
190         .fb_cursor      = soft_cursor,
191 };
192
193 /*
194  * do_xxx: Hardware-specific functions
195  */
196 static u32 do_calc_pll(int freq, int *freq_out);
197 static void  do_write_regs(struct fb_info *info, struct banshee_reg *reg);
198 static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short);
199
200 /*
201  * Driver data 
202  */
203 static int  nopan   = 0;
204 static int  nowrap  = 1;      // not implemented (yet)
205 static char *mode_option __initdata = NULL;
206
207 /* ------------------------------------------------------------------------- 
208  *                      Hardware-specific funcions
209  * ------------------------------------------------------------------------- */
210
211 #ifdef VGA_REG_IO 
212 static inline  u8 vga_inb(struct tdfx_par *par, u32 reg) { return inb(reg); }
213
214 static inline void vga_outb(struct tdfx_par *par, u32 reg,  u8 val) { outb(val, reg); }
215 #else
216 static inline  u8 vga_inb(struct tdfx_par *par, u32 reg) { 
217         return inb(par->iobase + reg - 0x300); 
218 }
219 static inline void vga_outb(struct tdfx_par *par, u32 reg,  u8 val) { 
220         outb(val, par->iobase + reg - 0x300); 
221 }
222 #endif
223
224 static inline void gra_outb(struct tdfx_par *par, u32 idx, u8 val) {
225         vga_outb(par, GRA_I, idx); vga_outb(par, GRA_D, val);
226 }
227
228 static inline void seq_outb(struct tdfx_par *par, u32 idx, u8 val) {
229         vga_outb(par, SEQ_I, idx); vga_outb(par, SEQ_D, val);
230 }
231
232 static inline u8 seq_inb(struct tdfx_par *par, u32 idx) {
233         vga_outb(par, SEQ_I, idx); return vga_inb(par, SEQ_D);
234 }
235
236 static inline void crt_outb(struct tdfx_par *par, u32 idx, u8 val) {
237         vga_outb(par, CRT_I, idx); vga_outb(par, CRT_D, val);
238 }
239
240 static inline u8 crt_inb(struct tdfx_par *par, u32 idx) {
241         vga_outb(par, CRT_I, idx); return vga_inb(par, CRT_D);
242 }
243
244 static inline void att_outb(struct tdfx_par *par, u32 idx, u8 val) 
245 {
246         unsigned char tmp;
247         
248         tmp = vga_inb(par, IS1_R);
249         vga_outb(par, ATT_IW, idx);
250         vga_outb(par, ATT_IW, val);
251 }
252
253 static inline void vga_disable_video(struct tdfx_par *par)
254 {
255         unsigned char s;
256
257         s = seq_inb(par, 0x01) | 0x20;
258         seq_outb(par, 0x00, 0x01);
259         seq_outb(par, 0x01, s);
260         seq_outb(par, 0x00, 0x03);
261 }
262
263 static inline void vga_enable_video(struct tdfx_par *par)
264 {
265         unsigned char s;
266
267         s = seq_inb(par, 0x01) & 0xdf;
268         seq_outb(par, 0x00, 0x01);
269         seq_outb(par, 0x01, s);
270         seq_outb(par, 0x00, 0x03);
271 }
272
273 static inline void vga_enable_palette(struct tdfx_par *par)
274 {
275         vga_inb(par, IS1_R);
276         vga_outb(par, ATT_IW, 0x20);
277 }
278
279 static inline u32 tdfx_inl(struct tdfx_par *par, unsigned int reg) 
280 {
281         return readl(par->regbase_virt + reg);
282 }
283
284 static inline void tdfx_outl(struct tdfx_par *par, unsigned int reg, u32 val)
285 {
286         writel(val, par->regbase_virt + reg);
287 }
288
289 static inline void banshee_make_room(struct tdfx_par *par, int size)
290 {
291         /* Note: The Voodoo3's onboard FIFO has 32 slots. This loop
292          * won't quit if you ask for more. */
293         while((tdfx_inl(par, STATUS) & 0x1f) < size-1);
294 }
295  
296 static int banshee_wait_idle(struct fb_info *info)
297 {
298         struct tdfx_par *par = (struct tdfx_par *) info->par; 
299         int i = 0;
300
301         banshee_make_room(par, 1);
302         tdfx_outl(par, COMMAND_3D, COMMAND_3D_NOP);
303
304         while(1) {
305                 i = (tdfx_inl(par, STATUS) & STATUS_BUSY) ? 0 : i + 1;
306                 if(i == 3) break;
307         }
308         return 0;
309 }
310
311 /*
312  * Set the color of a palette entry in 8bpp mode 
313  */
314 static inline void do_setpalentry(struct tdfx_par *par, unsigned regno, u32 c)
315 {  
316         banshee_make_room(par, 2);
317         tdfx_outl(par, DACADDR, regno);
318         tdfx_outl(par, DACDATA, c);
319 }
320
321 static u32 do_calc_pll(int freq, int* freq_out) 
322 {
323         int m, n, k, best_m, best_n, best_k, f_cur, best_error;
324         int fref = 14318;
325   
326         /* this really could be done with more intelligence --
327            255*63*4 = 64260 iterations is silly */
328         best_error = freq;
329         best_n = best_m = best_k = 0;
330         for (n = 1; n < 256; n++) {
331                 for (m = 1; m < 64; m++) {
332                         for (k = 0; k < 4; k++) {
333                                 f_cur = fref*(n + 2)/(m + 2)/(1 << k);
334                                 if (abs(f_cur - freq) < best_error) {
335                                         best_error = abs(f_cur-freq);
336                                         best_n = n;
337                                         best_m = m;
338                                         best_k = k;
339                                 }
340                         }
341                 }
342         }
343         n = best_n;
344         m = best_m;
345         k = best_k;
346         *freq_out = fref*(n + 2)/(m + 2)/(1 << k);
347         return (n << 8) | (m << 2) | k;
348 }
349
350 static void do_write_regs(struct fb_info *info, struct banshee_reg* reg) 
351 {
352         struct tdfx_par *par = (struct tdfx_par *) info->par; 
353         int i;
354
355         banshee_wait_idle(info);
356
357         tdfx_outl(par, MISCINIT1, tdfx_inl(par, MISCINIT1) | 0x01);
358
359         crt_outb(par, 0x11, crt_inb(par, 0x11) & 0x7f); /* CRT unprotect */
360
361         banshee_make_room(par, 3);
362         tdfx_outl(par, VGAINIT1,        reg->vgainit1 &  0x001FFFFF);
363         tdfx_outl(par, VIDPROCCFG,      reg->vidcfg   & ~0x00000001);
364 #if 0
365         tdfx_outl(par, PLLCTRL1, reg->mempll);
366         tdfx_outl(par, PLLCTRL2, reg->gfxpll);
367 #endif
368         tdfx_outl(par, PLLCTRL0,        reg->vidpll);
369
370         vga_outb(par, MISC_W, reg->misc[0x00] | 0x01);
371
372         for (i = 0; i < 5; i++)
373                 seq_outb(par, i, reg->seq[i]);
374
375         for (i = 0; i < 25; i++)
376                 crt_outb(par, i, reg->crt[i]);
377
378         for (i = 0; i < 9; i++)
379                 gra_outb(par, i, reg->gra[i]);
380
381         for (i = 0; i < 21; i++)
382                 att_outb(par, i, reg->att[i]);
383
384         crt_outb(par, 0x1a, reg->ext[0]);
385         crt_outb(par, 0x1b, reg->ext[1]);
386
387         vga_enable_palette(par);
388         vga_enable_video(par);
389
390         banshee_make_room(par, 11);
391         tdfx_outl(par,  VGAINIT0,      reg->vgainit0);
392         tdfx_outl(par,  DACMODE,       reg->dacmode);
393         tdfx_outl(par,  VIDDESKSTRIDE, reg->stride);
394         tdfx_outl(par,  HWCURPATADDR,  0);
395    
396         tdfx_outl(par,  VIDSCREENSIZE,reg->screensize);
397         tdfx_outl(par,  VIDDESKSTART,   reg->startaddr);
398         tdfx_outl(par,  VIDPROCCFG,     reg->vidcfg);
399         tdfx_outl(par,  VGAINIT1,       reg->vgainit1);  
400         tdfx_outl(par,  MISCINIT0,      reg->miscinit0);        
401
402         banshee_make_room(par,  8);
403         tdfx_outl(par,  SRCBASE,         reg->srcbase);
404         tdfx_outl(par,  DSTBASE,         reg->dstbase);
405         tdfx_outl(par,  COMMANDEXTRA_2D, 0);
406         tdfx_outl(par,  CLIP0MIN,        0);
407         tdfx_outl(par,  CLIP0MAX,        0x0fff0fff);
408         tdfx_outl(par,  CLIP1MIN,        0);
409         tdfx_outl(par,  CLIP1MAX,        0x0fff0fff);
410         tdfx_outl(par,  SRCXY,     0);
411
412         banshee_wait_idle(info);
413 }
414
415 static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id) 
416 {
417         u32 draminit0 = 0;
418         u32 draminit1 = 0;
419         u32 miscinit1 = 0;
420         u32 lfbsize   = 0;
421         int sgram_p   = 0;
422
423         draminit0 = tdfx_inl(par, DRAMINIT0);  
424         draminit1 = tdfx_inl(par, DRAMINIT1);
425  
426         if ((dev_id == PCI_DEVICE_ID_3DFX_BANSHEE) ||
427             (dev_id == PCI_DEVICE_ID_3DFX_VOODOO3)) {                    
428                 sgram_p = (draminit1 & DRAMINIT1_MEM_SDRAM) ? 0 : 1;
429   
430         lfbsize = sgram_p ?
431                 (((draminit0 & DRAMINIT0_SGRAM_NUM)  ? 2 : 1) * 
432                 ((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 8 : 4) * 1024 * 1024) :
433                 16 * 1024 * 1024;
434         } else {
435                 /* Voodoo4/5 */
436                 u32 chips, psize, banks;
437
438                 chips = ((draminit0 & (1 << 26)) == 0) ? 4 : 8;
439                 psize = 1 << ((draminit0 & 0x38000000) >> 28);
440                 banks = ((draminit0 & (1 << 30)) == 0) ? 2 : 4;
441                 lfbsize = chips * psize * banks;
442                 lfbsize <<= 20;
443         }                 
444         /* disable block writes for SDRAM (why?) */
445         miscinit1 = tdfx_inl(par, MISCINIT1);
446         miscinit1 |= sgram_p ? 0 : MISCINIT1_2DBLOCK_DIS;
447         miscinit1 |= MISCINIT1_CLUT_INV;
448
449         banshee_make_room(par, 1); 
450         tdfx_outl(par, MISCINIT1, miscinit1);
451         return lfbsize;
452 }
453
454 /* ------------------------------------------------------------------------- */
455
456 static int tdfxfb_check_var(struct fb_var_screeninfo *var,struct fb_info *info) 
457 {
458         struct tdfx_par *par = (struct tdfx_par *) info->par; 
459         u32 lpitch;
460
461         if (var->bits_per_pixel != 8  && var->bits_per_pixel != 16 &&
462             var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
463                 DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
464                 return -EINVAL;
465         }
466
467         if (var->xres != var->xres_virtual)
468                 var->xres_virtual = var->xres;
469
470         if (var->yres > var->yres_virtual)
471                 var->yres_virtual = var->yres;
472
473         if (var->xoffset) {
474                 DPRINTK("xoffset not supported\n");
475                 return -EINVAL;
476         }
477
478         /* Banshee doesn't support interlace, but Voodoo4/5 and probably Voodoo3 do. */
479         /* no direct information about device id now? use max_pixclock for this... */
480         if (((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) &&
481                         (par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) {
482                 DPRINTK("interlace not supported\n");
483                 return -EINVAL;
484         }
485
486         var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
487         lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
488   
489         if (var->xres < 320 || var->xres > 2048) {
490                 DPRINTK("width not supported: %u\n", var->xres);
491                 return -EINVAL;
492         }
493   
494         if (var->yres < 200 || var->yres > 2048) {
495                 DPRINTK("height not supported: %u\n", var->yres);
496                 return -EINVAL;
497         }
498   
499         if (lpitch * var->yres_virtual > info->fix.smem_len) {
500                 var->yres_virtual = info->fix.smem_len/lpitch;
501                 if (var->yres_virtual < var->yres) {
502                         DPRINTK("no memory for screen (%ux%ux%u)\n",
503                         var->xres, var->yres_virtual, var->bits_per_pixel);
504                         return -EINVAL;
505                 }
506         }
507   
508         if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {
509                 DPRINTK("pixclock too high (%ldKHz)\n",PICOS2KHZ(var->pixclock));
510                 return -EINVAL;
511         }
512
513         switch(var->bits_per_pixel) {
514                 case 8:
515                         var->red.length = var->green.length = var->blue.length = 8;
516                         break;
517                 case 16:
518                         var->red.offset   = 11;
519                         var->red.length   = 5;
520                         var->green.offset = 5;
521                         var->green.length = 6;
522                         var->blue.offset  = 0;
523                         var->blue.length  = 5;
524                         break;
525                 case 24:
526                         var->red.offset=16;
527                         var->green.offset=8;
528                         var->blue.offset=0;
529                         var->red.length = var->green.length = var->blue.length = 8;
530                 case 32:
531                         var->red.offset   = 16;
532                         var->green.offset = 8;
533                         var->blue.offset  = 0;
534                         var->red.length = var->green.length = var->blue.length = 8;
535                         break;
536         }
537         var->height = var->width = -1;
538   
539         var->accel_flags = FB_ACCELF_TEXT;
540         
541         DPRINTK("Checking graphics mode at %dx%d depth %d\n",  var->xres, var->yres, var->bits_per_pixel);
542         return 0;
543 }
544
545 static int tdfxfb_set_par(struct fb_info *info)
546 {
547         struct tdfx_par *par = (struct tdfx_par *) info->par;   
548         u32 hdispend, hsyncsta, hsyncend, htotal;
549         u32 hd, hs, he, ht, hbs, hbe;
550         u32 vd, vs, ve, vt, vbs, vbe;
551         struct banshee_reg reg;
552         int fout, freq;
553         u32 wd, cpp;
554   
555         par->baseline  = 0;
556  
557         memset(&reg, 0, sizeof(reg));
558         cpp = (info->var.bits_per_pixel + 7)/8;
559  
560         reg.vidcfg = VIDCFG_VIDPROC_ENABLE | VIDCFG_DESK_ENABLE | VIDCFG_CURS_X11 | ((cpp - 1) << VIDCFG_PIXFMT_SHIFT) | (cpp != 1 ? VIDCFG_CLUT_BYPASS : 0);
561
562         /* PLL settings */
563         freq = PICOS2KHZ(info->var.pixclock);
564
565         reg.dacmode = 0;
566         reg.vidcfg  &= ~VIDCFG_2X;
567
568         hdispend = info->var.xres;
569         hsyncsta = hdispend + info->var.right_margin;
570         hsyncend = hsyncsta + info->var.hsync_len;
571         htotal   = hsyncend + info->var.left_margin;    
572
573         if (freq > par->max_pixclock/2) {
574                 freq = freq > par->max_pixclock ? par->max_pixclock : freq;
575                 reg.dacmode |= DACMODE_2X;
576                 reg.vidcfg  |= VIDCFG_2X;
577                 hdispend >>= 1;
578                 hsyncsta >>= 1;
579                 hsyncend >>= 1;
580                 htotal   >>= 1;
581         }
582   
583         hd  = wd = (hdispend >> 3) - 1;
584         hs  = (hsyncsta >> 3) - 1;
585         he  = (hsyncend >> 3) - 1;
586         ht  = (htotal >> 3) - 1;
587         hbs = hd;
588         hbe = ht;
589
590         if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
591                 vbs = vd = (info->var.yres << 1) - 1;
592                 vs  = vd + (info->var.lower_margin << 1);
593                 ve  = vs + (info->var.vsync_len << 1);
594                 vbe = vt = ve + (info->var.upper_margin << 1) - 1;
595         } else {
596                 vbs = vd = info->var.yres - 1;
597                 vs  = vd + info->var.lower_margin;
598                 ve  = vs + info->var.vsync_len;
599                 vbe = vt = ve + info->var.upper_margin - 1;
600         }
601   
602         /* this is all pretty standard VGA register stuffing */
603         reg.misc[0x00] = 0x0f | 
604                         (info->var.xres < 400 ? 0xa0 :
605                          info->var.xres < 480 ? 0x60 :
606                          info->var.xres < 768 ? 0xe0 : 0x20);
607      
608         reg.gra[0x00] = 0x00;
609         reg.gra[0x01] = 0x00;
610         reg.gra[0x02] = 0x00;
611         reg.gra[0x03] = 0x00;
612         reg.gra[0x04] = 0x00;
613         reg.gra[0x05] = 0x40;
614         reg.gra[0x06] = 0x05;
615         reg.gra[0x07] = 0x0f;
616         reg.gra[0x08] = 0xff;
617
618         reg.att[0x00] = 0x00;
619         reg.att[0x01] = 0x01;
620         reg.att[0x02] = 0x02;
621         reg.att[0x03] = 0x03;
622         reg.att[0x04] = 0x04;
623         reg.att[0x05] = 0x05;
624         reg.att[0x06] = 0x06;
625         reg.att[0x07] = 0x07;
626         reg.att[0x08] = 0x08;
627         reg.att[0x09] = 0x09;
628         reg.att[0x0a] = 0x0a;
629         reg.att[0x0b] = 0x0b;
630         reg.att[0x0c] = 0x0c;
631         reg.att[0x0d] = 0x0d;
632         reg.att[0x0e] = 0x0e;
633         reg.att[0x0f] = 0x0f;
634         reg.att[0x10] = 0x41;
635         reg.att[0x11] = 0x00;
636         reg.att[0x12] = 0x0f;
637         reg.att[0x13] = 0x00;
638         reg.att[0x14] = 0x00;
639
640         reg.seq[0x00] = 0x03;
641         reg.seq[0x01] = 0x01; /* fixme: clkdiv2? */
642         reg.seq[0x02] = 0x0f;
643         reg.seq[0x03] = 0x00;
644         reg.seq[0x04] = 0x0e;
645
646         reg.crt[0x00] = ht - 4;
647         reg.crt[0x01] = hd;
648         reg.crt[0x02] = hbs;
649         reg.crt[0x03] = 0x80 | (hbe & 0x1f);
650         reg.crt[0x04] = hs;
651         reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f); 
652         reg.crt[0x06] = vt;
653         reg.crt[0x07] = ((vs & 0x200) >> 2) |
654                         ((vd & 0x200) >> 3) |
655                         ((vt & 0x200) >> 4) | 0x10 |
656                         ((vbs & 0x100) >> 5) |
657                         ((vs  & 0x100) >> 6) |
658                         ((vd  & 0x100) >> 7) |
659                         ((vt  & 0x100) >> 8);
660         reg.crt[0x08] = 0x00;
661         reg.crt[0x09] = 0x40 | ((vbs & 0x200) >> 4); 
662         reg.crt[0x0a] = 0x00;
663         reg.crt[0x0b] = 0x00;
664         reg.crt[0x0c] = 0x00;
665         reg.crt[0x0d] = 0x00;
666         reg.crt[0x0e] = 0x00;
667         reg.crt[0x0f] = 0x00;
668         reg.crt[0x10] = vs;
669         reg.crt[0x11] = (ve & 0x0f) | 0x20; 
670         reg.crt[0x12] = vd;
671         reg.crt[0x13] = wd;
672         reg.crt[0x14] = 0x00;
673         reg.crt[0x15] = vbs;
674         reg.crt[0x16] = vbe + 1; 
675         reg.crt[0x17] = 0xc3;
676         reg.crt[0x18] = 0xff;
677  
678         /* Banshee's nonvga stuff */
679         reg.ext[0x00] = (((ht  & 0x100) >> 8) | 
680                         ((hd  & 0x100) >> 6) |
681                         ((hbs & 0x100) >> 4) |
682                         ((hbe &  0x40) >> 1) |
683                         ((hs  & 0x100) >> 2) |
684                         ((he  &  0x20) << 2)); 
685         reg.ext[0x01] = (((vt  & 0x400) >> 10) |
686                         ((vd  & 0x400) >>  8) | 
687                         ((vbs & 0x400) >>  6) |
688                         ((vbe & 0x400) >>  4));
689
690         reg.vgainit0 =  VGAINIT0_8BIT_DAC     |
691                         VGAINIT0_EXT_ENABLE   |
692                         VGAINIT0_WAKEUP_3C3   |
693                         VGAINIT0_ALT_READBACK |
694                         VGAINIT0_EXTSHIFTOUT;
695         reg.vgainit1 = tdfx_inl(par, VGAINIT1) & 0x1fffff;
696
697         reg.cursloc   = 0;
698    
699         reg.cursc0    = 0; 
700         reg.cursc1    = 0xffffff;
701    
702         reg.stride    = info->var.xres * cpp;
703         reg.startaddr = par->baseline * reg.stride;
704         reg.srcbase   = reg.startaddr;
705         reg.dstbase   = reg.startaddr;
706
707         /* PLL settings */
708         freq = PICOS2KHZ(info->var.pixclock);
709
710         reg.dacmode &= ~DACMODE_2X;
711         reg.vidcfg  &= ~VIDCFG_2X;
712         if (freq > par->max_pixclock/2) {
713                 freq = freq > par->max_pixclock ? par->max_pixclock : freq;
714                 reg.dacmode |= DACMODE_2X;
715                 reg.vidcfg  |= VIDCFG_2X;
716         }
717         reg.vidpll = do_calc_pll(freq, &fout);
718 #if 0
719         reg.mempll = do_calc_pll(..., &fout);
720         reg.gfxpll = do_calc_pll(..., &fout);
721 #endif
722
723         if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
724                 reg.screensize = info->var.xres | (info->var.yres << 13);
725                 reg.vidcfg |= VIDCFG_HALF_MODE;
726                 reg.crt[0x09] |= 0x80;
727         } else {
728                 reg.screensize = info->var.xres | (info->var.yres << 12);
729                 reg.vidcfg &= ~VIDCFG_HALF_MODE;
730         }
731         if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
732                 reg.vidcfg |= VIDCFG_INTERLACE;
733         reg.miscinit0 = tdfx_inl(par, MISCINIT0);
734
735 #if defined(__BIG_ENDIAN)
736         switch (info->var.bits_per_pixel) {
737                 case 8:
738                 case 24:
739                         reg.miscinit0 &= ~(1 << 30);
740                         reg.miscinit0 &= ~(1 << 31);
741                         break;
742                 case 16:
743                         reg.miscinit0 |= (1 << 30);
744                         reg.miscinit0 |= (1 << 31);
745                         break;
746                 case 32:
747                         reg.miscinit0 |= (1 << 30);
748                         reg.miscinit0 &= ~(1 << 31);
749                         break;
750         }
751 #endif 
752         do_write_regs(info, &reg);
753
754         /* Now change fb_fix_screeninfo according to changes in par */
755         info->fix.line_length = info->var.xres * ((info->var.bits_per_pixel + 7)>>3);
756         info->fix.visual = (info->var.bits_per_pixel == 8) 
757                                 ? FB_VISUAL_PSEUDOCOLOR
758                                 : FB_VISUAL_TRUECOLOR;
759         DPRINTK("Graphics mode is now set at %dx%d depth %d\n", info->var.xres, info->var.yres, info->var.bits_per_pixel);
760         return 0;       
761 }
762
763 /* A handy macro shamelessly pinched from matroxfb */
764 #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
765
766 static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,  
767                             unsigned blue,unsigned transp,struct fb_info *info) 
768 {
769         struct tdfx_par *par = (struct tdfx_par *) info->par;
770         u32 rgbcol;
771    
772         if (regno >= info->cmap.len || regno > 255) return 1;
773    
774         switch (info->fix.visual) {
775                 case FB_VISUAL_PSEUDOCOLOR:
776                         rgbcol =(((u32)red   & 0xff00) << 8) |
777                                 (((u32)green & 0xff00) << 0) |
778                                 (((u32)blue  & 0xff00) >> 8);
779                         do_setpalentry(par, regno, rgbcol);
780                         break;
781                 /* Truecolor has no hardware color palettes. */
782                 case FB_VISUAL_TRUECOLOR:
783                         rgbcol = (CNVT_TOHW( red, info->var.red.length) << info->var.red.offset) |
784                                  (CNVT_TOHW( green, info->var.green.length) << info->var.green.offset) |
785                                  (CNVT_TOHW( blue, info->var.blue.length) << info->var.blue.offset) |
786                                  (CNVT_TOHW( transp, info->var.transp.length) << info->var.transp.offset);
787                                 ((u32*)(info->pseudo_palette))[regno] = rgbcol;
788                         break;
789                 default:
790                         DPRINTK("bad depth %u\n", info->var.bits_per_pixel);
791                         break;
792         }
793         return 0;
794 }
795
796 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
797 static int tdfxfb_blank(int blank, struct fb_info *info)
798
799         struct tdfx_par *par = (struct tdfx_par *) info->par;
800         u32 dacmode, state = 0, vgablank = 0;
801
802         dacmode = tdfx_inl(par, DACMODE);
803
804         switch (blank) {
805                 case FB_BLANK_UNBLANK: /* Screen: On; HSync: On, VSync: On */
806                         state    = 0;
807                         vgablank = 0;
808                         break;
809                 case FB_BLANK_NORMAL: /* Screen: Off; HSync: On, VSync: On */
810                         state    = 0;
811                         vgablank = 1;
812                         break;
813                 case FB_BLANK_VSYNC_SUSPEND: /* Screen: Off; HSync: On, VSync: Off */
814                         state    = BIT(3);
815                         vgablank = 1;
816                         break;
817                 case FB_BLANK_HSYNC_SUSPEND: /* Screen: Off; HSync: Off, VSync: On */
818                         state    = BIT(1);
819                         vgablank = 1;
820                         break;
821                 case FB_BLANK_POWERDOWN: /* Screen: Off; HSync: Off, VSync: Off */
822                         state    = BIT(1) | BIT(3);
823                         vgablank = 1;
824                         break;
825         }
826
827         dacmode &= ~(BIT(1) | BIT(3));
828         dacmode |= state;
829         banshee_make_room(par, 1); 
830         tdfx_outl(par, DACMODE, dacmode);
831         if (vgablank) 
832                 vga_disable_video(par);
833         else
834                 vga_enable_video(par);
835         return 0;
836 }
837
838 /*   
839  * Set the starting position of the visible screen to var->yoffset
840  */   
841 static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
842                               struct fb_info *info) 
843 {
844         struct tdfx_par *par = (struct tdfx_par *) info->par;
845         u32 addr;       
846
847         if (nopan || var->xoffset || (var->yoffset > var->yres_virtual))
848                 return -EINVAL;
849         if ((var->yoffset + var->yres > var->yres_virtual && nowrap))
850                 return -EINVAL;
851
852         addr = var->yoffset * info->fix.line_length;
853         banshee_make_room(par, 1);
854         tdfx_outl(par, VIDDESKSTART, addr);
855    
856         info->var.xoffset = var->xoffset;
857         info->var.yoffset = var->yoffset; 
858         return 0;
859 }
860
861 #ifdef CONFIG_FB_3DFX_ACCEL
862 /*
863  * FillRect 2D command (solidfill or invert (via ROP_XOR))   
864  */
865 static void tdfxfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 
866 {
867         struct tdfx_par *par = (struct tdfx_par *) info->par;
868         u32 bpp = info->var.bits_per_pixel;
869         u32 stride = info->fix.line_length;
870         u32 fmt= stride | ((bpp+((bpp==8) ? 0 : 8)) << 13); 
871         int tdfx_rop;
872         
873         if (rect->rop == ROP_COPY) 
874                 tdfx_rop = TDFX_ROP_COPY;
875         else                     
876                 tdfx_rop = TDFX_ROP_XOR;
877
878         banshee_make_room(par, 5);
879         tdfx_outl(par,  DSTFORMAT, fmt);
880         if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
881                 tdfx_outl(par,  COLORFORE, rect->color);
882         } else { /* FB_VISUAL_TRUECOLOR */
883                 tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[rect->color]);
884         }
885         tdfx_outl(par,  COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
886         tdfx_outl(par,  DSTSIZE,    rect->width | (rect->height << 16));
887         tdfx_outl(par,  LAUNCH_2D,  rect->dx | (rect->dy << 16));
888 }
889
890 /*
891  * Screen-to-Screen BitBlt 2D command (for the bmove fb op.) 
892  */
893 static void tdfxfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)  
894 {
895         struct tdfx_par *par = (struct tdfx_par *) info->par;
896         u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
897         u32 bpp = info->var.bits_per_pixel;
898         u32 stride = info->fix.line_length;
899         u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24);
900         u32 fmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13); 
901         
902         if (area->sx <= area->dx) {
903                 //-X 
904                 blitcmd |= BIT(14);
905                 sx += area->width - 1;
906                 dx += area->width - 1;
907         }
908         if (area->sy <= area->dy) {
909                 //-Y  
910                 blitcmd |= BIT(15);
911                 sy += area->height - 1;
912                 dy += area->height - 1;
913         }
914    
915         banshee_make_room(par, 6);
916
917         tdfx_outl(par,  SRCFORMAT, fmt);
918         tdfx_outl(par,  DSTFORMAT, fmt);
919         tdfx_outl(par,  COMMAND_2D, blitcmd); 
920         tdfx_outl(par,  DSTSIZE,   area->width | (area->height << 16));
921         tdfx_outl(par,  DSTXY,     dx | (dy << 16));
922         tdfx_outl(par,  LAUNCH_2D, sx | (sy << 16)); 
923 }
924
925 static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image) 
926 {
927         struct tdfx_par *par = (struct tdfx_par *) info->par;
928         int size = image->height * ((image->width * image->depth + 7)>>3);
929         int fifo_free;
930         int i, stride = info->fix.line_length;
931         u32 bpp = info->var.bits_per_pixel;
932         u32 dstfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13); 
933         u8 *chardata = (u8 *) image->data;
934         u32 srcfmt;
935
936         if (image->depth != 1) {
937                 //banshee_make_room(par, 6 + ((size + 3) >> 2));
938                 //srcfmt = stride | ((bpp+((bpp==8) ? 0 : 8)) << 13) | 0x400000;
939                 cfb_imageblit(info, image);
940                 return;
941         } else {
942                 banshee_make_room(par, 8);
943                 switch (info->fix.visual) {
944                         case FB_VISUAL_PSEUDOCOLOR:
945                 tdfx_outl(par, COLORFORE, image->fg_color);
946                 tdfx_outl(par, COLORBACK, image->bg_color);
947                                 break;
948                         case FB_VISUAL_TRUECOLOR:
949                         default:
950                                 tdfx_outl(par, COLORFORE, ((u32*)(info->pseudo_palette))[image->fg_color]);
951                                 tdfx_outl(par, COLORBACK, ((u32*)(info->pseudo_palette))[image->bg_color]);
952                 }
953 #ifdef __BIG_ENDIAN
954                 srcfmt = 0x400000 | BIT(20);
955 #else
956                 srcfmt = 0x400000;
957 #endif
958         }       
959
960         tdfx_outl(par,  SRCXY,     0);
961         tdfx_outl(par,  DSTXY,     image->dx | (image->dy << 16));
962         tdfx_outl(par,  COMMAND_2D, COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
963         tdfx_outl(par,  SRCFORMAT, srcfmt);
964         tdfx_outl(par,  DSTFORMAT, dstfmt);
965         tdfx_outl(par,  DSTSIZE,   image->width | (image->height << 16));
966
967         /* A count of how many free FIFO entries we've requested.
968          * When this goes negative, we need to request more. */
969         fifo_free = 0;
970
971         /* Send four bytes at a time of data */ 
972         for (i = (size >> 2) ; i > 0; i--) { 
973                 if(--fifo_free < 0) {
974                         fifo_free=31;
975                         banshee_make_room(par,fifo_free);
976                 }
977                 tdfx_outl(par,  LAUNCH_2D,*(u32*)chardata);
978                 chardata += 4; 
979         }       
980
981         /* Send the leftovers now */    
982         banshee_make_room(par,3);
983         i = size%4;     
984         switch (i) {
985                 case 0: break;
986                 case 1:  tdfx_outl(par, LAUNCH_2D,*chardata); break;
987                 case 2:  tdfx_outl(par, LAUNCH_2D,*(u16*)chardata); break;
988                 case 3:  tdfx_outl(par, LAUNCH_2D,*(u16*)chardata | ((chardata[3]) << 24)); break;
989         }
990 }
991 #endif /* CONFIG_FB_3DFX_ACCEL */
992
993 #ifdef TDFX_HARDWARE_CURSOR
994 static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
995 {
996         struct tdfx_par *par = (struct tdfx_par *) info->par;
997         unsigned long flags;
998
999         /*
1000          * If the cursor is not be changed this means either we want the 
1001          * current cursor state (if enable is set) or we want to query what
1002          * we can do with the cursor (if enable is not set) 
1003          */
1004         if (!cursor->set) return 0;
1005
1006         /* Too large of a cursor :-( */
1007         if (cursor->image.width > 64 || cursor->image.height > 64)
1008                 return -ENXIO;
1009
1010         /* 
1011          * If we are going to be changing things we should disable
1012          * the cursor first 
1013          */
1014         if (info->cursor.enable) {
1015                 spin_lock_irqsave(&par->DAClock, flags);
1016                 info->cursor.enable = 0;
1017                 del_timer(&(par->hwcursor.timer));
1018                 tdfx_outl(par, VIDPROCCFG, par->hwcursor.disable);
1019                 spin_unlock_irqrestore(&par->DAClock, flags);
1020         }
1021
1022         /* Disable the Cursor */
1023         if ((cursor->set && FB_CUR_SETCUR) && !cursor->enable)
1024                 return 0;
1025
1026         /* fix cursor color - XFree86 forgets to restore it properly */
1027         if (cursor->set && FB_CUR_SETCMAP) {
1028                 struct fb_cmap cmap = cursor->image.cmap;
1029                 unsigned long bg_color, fg_color;
1030
1031                 cmap.len = 2; /* Voodoo 3+ only support 2 color cursors */
1032                 fg_color = ((cmap.red[cmap.start] << 16) |
1033                             (cmap.green[cmap.start] << 8)  |
1034                             (cmap.blue[cmap.start]));
1035                 bg_color = ((cmap.red[cmap.start+1] << 16) |
1036                             (cmap.green[cmap.start+1] << 8) |
1037                             (cmap.blue[cmap.start+1]));
1038                 fb_copy_cmap(&cmap, &info->cursor.image.cmap);
1039                 spin_lock_irqsave(&par->DAClock, flags);
1040                 banshee_make_room(par, 2);
1041                 tdfx_outl(par, HWCURC0, bg_color);
1042                 tdfx_outl(par, HWCURC1, fg_color);
1043                 spin_unlock_irqrestore(&par->DAClock, flags);
1044         }
1045
1046         if (cursor->set && FB_CUR_SETPOS) {
1047                 int x, y;
1048
1049                 x = cursor->image.dx;
1050                 y = cursor->image.dy;
1051                 y -= info->var.yoffset;
1052                 info->cursor.image.dx = x;
1053                 info->cursor.image.dy = y;
1054                 x += 63;
1055                 y += 63;
1056                 spin_lock_irqsave(&par->DAClock, flags);
1057                 banshee_make_room(par, 1);
1058                 tdfx_outl(par, HWCURLOC, (y << 16) + x);
1059                 spin_unlock_irqrestore(&par->DAClock, flags);
1060         }
1061
1062         /* Not supported so we fake it */
1063         if (cursor->set && FB_CUR_SETHOT) {
1064                 info->cursor.hot.x = cursor->hot.x;
1065                 info->cursor.hot.y = cursor->hot.y;
1066         }
1067
1068         if (cursor->set && FB_CUR_SETSHAPE) {
1069                 /*
1070                  * Voodoo 3 and above cards use 2 monochrome cursor patterns.
1071                  *    The reason is so the card can fetch 8 words at a time
1072                  * and are stored on chip for use for the next 8 scanlines.
1073                  * This reduces the number of times for access to draw the
1074                  * cursor for each screen refresh.
1075                  *    Each pattern is a bitmap of 64 bit wide and 64 bit high
1076                  * (total of 8192 bits or 1024 Kbytes). The two patterns are
1077                  * stored in such a way that pattern 0 always resides in the
1078                  * lower half (least significant 64 bits) of a 128 bit word
1079                  * and pattern 1 the upper half. If you examine the data of
1080                  * the cursor image the graphics card uses then from the
1081                  * begining you see line one of pattern 0, line one of
1082                  * pattern 1, line two of pattern 0, line two of pattern 1,
1083                  * etc etc. The linear stride for the cursor is always 16 bytes
1084                  * (128 bits) which is the maximum cursor width times two for
1085                  * the two monochrome patterns.
1086                  */
1087                 u8 *cursorbase = (u8 *) info->cursor.image.data;
1088                 char *bitmap = (char *)cursor->image.data;
1089                 char *mask = (char *) cursor->mask;
1090                 int i, j, k, h = 0;
1091
1092                 for (i = 0; i < 64; i++) {
1093                         if (i < cursor->image.height) {
1094                                 j = (cursor->image.width + 7) >> 3;
1095                                 k = 8 - j;
1096
1097                                 for (;j > 0; j--) {
1098                                 /* Pattern 0. Copy the cursor bitmap to it */
1099                                         fb_writeb(*bitmap, cursorbase + h);
1100                                         bitmap++;
1101                                 /* Pattern 1. Copy the cursor mask to it */
1102                                         fb_writeb(*mask, cursorbase + h + 8);
1103                                         mask++;
1104                                         h++;
1105                                 }
1106                                 for (;k > 0; k--) {
1107                                         fb_writeb(0, cursorbase + h);
1108                                         fb_writeb(~0, cursorbase + h + 8);
1109                                         h++;
1110                                 }
1111                         } else {
1112                                 fb_writel(0, cursorbase + h);
1113                                 fb_writel(0, cursorbase + h + 4);
1114                                 fb_writel(~0, cursorbase + h + 8);
1115                                 fb_writel(~0, cursorbase + h + 12);
1116                                 h += 16;
1117                         }
1118                 }
1119         }
1120         /* Turn the cursor on */
1121         cursor->enable = 1;
1122         info->cursor = *cursor;
1123         mod_timer(&par->hwcursor.timer, jiffies+HZ/2);
1124         spin_lock_irqsave(&par->DAClock, flags);
1125         banshee_make_room(par, 1);
1126         tdfx_outl(par, VIDPROCCFG, par->hwcursor.enable);
1127         spin_unlock_irqrestore(&par->DAClock, flags);
1128         return 0;
1129 }
1130 #endif
1131
1132 /**
1133  *      tdfxfb_probe - Device Initializiation
1134  *
1135  *      @pdev:  PCI Device to initialize
1136  *      @id:    PCI Device ID
1137  *
1138  *      Initializes and allocates resources for PCI device @pdev.
1139  *
1140  */
1141 static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1142                                   const struct pci_device_id *id)
1143 {
1144         struct tdfx_par *default_par;
1145         struct fb_info *info;
1146         int size, err, lpitch;
1147
1148         if ((err = pci_enable_device(pdev))) {
1149                 printk(KERN_WARNING "tdfxfb: Can't enable pdev: %d\n", err);
1150                 return err;
1151         }
1152
1153         size = sizeof(struct tdfx_par)+256*sizeof(u32);
1154
1155         info = framebuffer_alloc(size, &pdev->dev);
1156
1157         if (!info)      return -ENOMEM;
1158                 
1159         default_par = info->par;
1160  
1161         /* Configure the default fb_fix_screeninfo first */
1162         switch (pdev->device) {
1163                 case PCI_DEVICE_ID_3DFX_BANSHEE:        
1164                         strcat(tdfx_fix.id, " Banshee");
1165                         default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
1166                         break;
1167                 case PCI_DEVICE_ID_3DFX_VOODOO3:
1168                         strcat(tdfx_fix.id, " Voodoo3");
1169                         default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
1170                         break;
1171                 case PCI_DEVICE_ID_3DFX_VOODOO5:
1172                         strcat(tdfx_fix.id, " Voodoo5");
1173                         default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
1174                         break;
1175         }
1176
1177         tdfx_fix.mmio_start = pci_resource_start(pdev, 0);
1178         tdfx_fix.mmio_len = pci_resource_len(pdev, 0);
1179         default_par->regbase_virt = ioremap_nocache(tdfx_fix.mmio_start, tdfx_fix.mmio_len);
1180         if (!default_par->regbase_virt) {
1181                 printk("fb: Can't remap %s register area.\n", tdfx_fix.id);
1182                 goto out_err;
1183         }
1184     
1185         if (!request_mem_region(pci_resource_start(pdev, 0),
1186             pci_resource_len(pdev, 0), "tdfx regbase")) {
1187                 printk(KERN_WARNING "tdfxfb: Can't reserve regbase\n");
1188                 goto out_err;
1189         } 
1190
1191         tdfx_fix.smem_start = pci_resource_start(pdev, 1);
1192         if (!(tdfx_fix.smem_len = do_lfb_size(default_par, pdev->device))) {
1193                 printk("fb: Can't count %s memory.\n", tdfx_fix.id);
1194                 release_mem_region(pci_resource_start(pdev, 0),
1195                                    pci_resource_len(pdev, 0));
1196                 goto out_err;   
1197         }
1198
1199         if (!request_mem_region(pci_resource_start(pdev, 1),
1200              pci_resource_len(pdev, 1), "tdfx smem")) {
1201                 printk(KERN_WARNING "tdfxfb: Can't reserve smem\n");
1202                 release_mem_region(pci_resource_start(pdev, 0),
1203                                    pci_resource_len(pdev, 0));
1204                 goto out_err;
1205         }
1206
1207         info->screen_base = ioremap_nocache(tdfx_fix.smem_start, 
1208                                             tdfx_fix.smem_len);
1209         if (!info->screen_base) {
1210                 printk("fb: Can't remap %s framebuffer.\n", tdfx_fix.id);
1211                 release_mem_region(pci_resource_start(pdev, 1),
1212                                    pci_resource_len(pdev, 1));
1213                 release_mem_region(pci_resource_start(pdev, 0),
1214                                    pci_resource_len(pdev, 0));
1215                 goto out_err;
1216         }
1217
1218         default_par->iobase = pci_resource_start(pdev, 2);
1219     
1220         if (!request_region(pci_resource_start(pdev, 2),
1221             pci_resource_len(pdev, 2), "tdfx iobase")) {
1222                 printk(KERN_WARNING "tdfxfb: Can't reserve iobase\n");
1223                 release_mem_region(pci_resource_start(pdev, 1),
1224                                    pci_resource_len(pdev, 1));
1225                 release_mem_region(pci_resource_start(pdev, 0),
1226                                    pci_resource_len(pdev, 0));
1227                 goto out_err;
1228         }
1229
1230         printk("fb: %s memory = %dK\n", tdfx_fix.id, tdfx_fix.smem_len >> 10);
1231
1232         tdfx_fix.ypanstep       = nopan ? 0 : 1;
1233         tdfx_fix.ywrapstep      = nowrap ? 0 : 1;
1234    
1235         info->fbops             = &tdfxfb_ops;
1236         info->fix               = tdfx_fix;     
1237         info->pseudo_palette    = (void *)(default_par + 1); 
1238         info->flags             = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1239 #ifdef CONFIG_FB_3DFX_ACCEL
1240         info->flags             |= FBINFO_HWACCEL_FILLRECT |
1241                 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_IMAGEBLIT;
1242 #endif
1243
1244         if (!mode_option)
1245                 mode_option = "640x480@60";
1246          
1247         err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); 
1248         if (!err || err == 4)
1249                 info->var = tdfx_var;
1250
1251         /* maximize virtual vertical length */
1252         lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);
1253         info->var.yres_virtual = info->fix.smem_len/lpitch;
1254         if (info->var.yres_virtual < info->var.yres)
1255                 goto out_err;
1256
1257 #ifdef CONFIG_FB_3DFX_ACCEL
1258         /*
1259          * FIXME: Limit var->yres_virtual to 4096 because of screen artifacts
1260          * during scrolling. This is only present if 2D acceleration is
1261          * enabled.
1262          */
1263         if (info->var.yres_virtual > 4096)
1264                 info->var.yres_virtual = 4096;
1265 #endif /* CONFIG_FB_3DFX_ACCEL */
1266
1267         if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
1268                 printk(KERN_WARNING "tdfxfb: Can't allocate color map\n");
1269                 goto out_err;
1270         }
1271
1272         if (register_framebuffer(info) < 0) {
1273                 printk("tdfxfb: can't register framebuffer\n");
1274                 fb_dealloc_cmap(&info->cmap);
1275                 goto out_err;
1276         }
1277         /*
1278          * Our driver data
1279          */
1280         pci_set_drvdata(pdev, info);
1281         return 0; 
1282
1283 out_err:
1284         /*
1285          * Cleanup after anything that was remapped/allocated.
1286          */
1287         if (default_par->regbase_virt)
1288                 iounmap(default_par->regbase_virt);
1289         if (info->screen_base)
1290                 iounmap(info->screen_base);
1291         framebuffer_release(info);
1292         return -ENXIO;
1293 }
1294
1295 /**
1296  *      tdfxfb_remove - Device removal
1297  *
1298  *      @pdev:  PCI Device to cleanup
1299  *
1300  *      Releases all resources allocated during the course of the driver's
1301  *      lifetime for the PCI device @pdev.
1302  *
1303  */
1304 static void __devexit tdfxfb_remove(struct pci_dev *pdev)
1305 {
1306         struct fb_info *info = pci_get_drvdata(pdev);
1307         struct tdfx_par *par = (struct tdfx_par *) info->par;
1308
1309         unregister_framebuffer(info);
1310         iounmap(par->regbase_virt);
1311         iounmap(info->screen_base);
1312
1313         /* Clean up after reserved regions */
1314         release_region(pci_resource_start(pdev, 2),
1315                        pci_resource_len(pdev, 2));
1316         release_mem_region(pci_resource_start(pdev, 1),
1317                            pci_resource_len(pdev, 1));
1318         release_mem_region(pci_resource_start(pdev, 0),
1319                            pci_resource_len(pdev, 0));
1320         pci_set_drvdata(pdev, NULL);
1321         framebuffer_release(info);
1322 }
1323
1324 int __init tdfxfb_init(void)
1325 {
1326 #ifndef MODULE
1327         char *option = NULL;
1328
1329         if (fb_get_options("tdfxfb", &option))
1330                 return -ENODEV;
1331
1332         tdfxfb_setup(option);
1333 #endif
1334         return pci_module_init(&tdfxfb_driver);
1335 }
1336
1337 static void __exit tdfxfb_exit(void)
1338 {
1339         pci_unregister_driver(&tdfxfb_driver);
1340 }
1341
1342 MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>");
1343 MODULE_DESCRIPTION("3Dfx framebuffer device driver");
1344 MODULE_LICENSE("GPL");
1345  
1346 module_init(tdfxfb_init);
1347 module_exit(tdfxfb_exit);
1348
1349
1350 #ifndef MODULE
1351 void tdfxfb_setup(char *options)
1352
1353         char* this_opt;
1354
1355         if (!options || !*options)
1356                 return;
1357
1358         while ((this_opt = strsep(&options, ",")) != NULL) {    
1359                 if (!*this_opt)
1360                         continue;
1361                 if(!strcmp(this_opt, "nopan")) {
1362                         nopan = 1;
1363                 } else if(!strcmp(this_opt, "nowrap")) {
1364                         nowrap = 1;
1365                 } else {
1366                         mode_option = this_opt;
1367                 }
1368         } 
1369 }
1370 #endif
1371