0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 #include <linux/module.h>
0068 #include <linux/kernel.h>
0069 #include <linux/errno.h>
0070 #include <linux/string.h>
0071 #include <linux/mm.h>
0072 #include <linux/slab.h>
0073 #include <linux/fb.h>
0074 #include <linux/init.h>
0075 #include <linux/pci.h>
0076 #include <asm/io.h>
0077
0078 #include <video/tdfx.h>
0079
0080 #define DPRINTK(a, b...) pr_debug("fb: %s: " a, __func__ , ## b)
0081
0082 #define BANSHEE_MAX_PIXCLOCK 270000
0083 #define VOODOO3_MAX_PIXCLOCK 300000
0084 #define VOODOO5_MAX_PIXCLOCK 350000
0085
0086 static const struct fb_fix_screeninfo tdfx_fix = {
0087 .type = FB_TYPE_PACKED_PIXELS,
0088 .visual = FB_VISUAL_PSEUDOCOLOR,
0089 .ypanstep = 1,
0090 .ywrapstep = 1,
0091 .accel = FB_ACCEL_3DFX_BANSHEE
0092 };
0093
0094 static const struct fb_var_screeninfo tdfx_var = {
0095
0096 .xres = 640,
0097 .yres = 480,
0098 .xres_virtual = 640,
0099 .yres_virtual = 1024,
0100 .bits_per_pixel = 8,
0101 .red = {0, 8, 0},
0102 .blue = {0, 8, 0},
0103 .green = {0, 8, 0},
0104 .activate = FB_ACTIVATE_NOW,
0105 .height = -1,
0106 .width = -1,
0107 .accel_flags = FB_ACCELF_TEXT,
0108 .pixclock = 39722,
0109 .left_margin = 40,
0110 .right_margin = 24,
0111 .upper_margin = 32,
0112 .lower_margin = 11,
0113 .hsync_len = 96,
0114 .vsync_len = 2,
0115 .vmode = FB_VMODE_NONINTERLACED
0116 };
0117
0118
0119
0120
0121 static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
0122 static void tdfxfb_remove(struct pci_dev *pdev);
0123
0124 static const struct pci_device_id tdfxfb_id_table[] = {
0125 { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE,
0126 PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
0127 0xff0000, 0 },
0128 { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3,
0129 PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
0130 0xff0000, 0 },
0131 { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO5,
0132 PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
0133 0xff0000, 0 },
0134 { 0, }
0135 };
0136
0137 static struct pci_driver tdfxfb_driver = {
0138 .name = "tdfxfb",
0139 .id_table = tdfxfb_id_table,
0140 .probe = tdfxfb_probe,
0141 .remove = tdfxfb_remove,
0142 };
0143
0144 MODULE_DEVICE_TABLE(pci, tdfxfb_id_table);
0145
0146
0147
0148
0149 static int nopan;
0150 static int nowrap = 1;
0151 static int hwcursor = 1;
0152 static char *mode_option;
0153 static bool nomtrr;
0154
0155
0156
0157
0158
0159 static inline u8 vga_inb(struct tdfx_par *par, u32 reg)
0160 {
0161 return inb(par->iobase + reg - 0x300);
0162 }
0163
0164 static inline void vga_outb(struct tdfx_par *par, u32 reg, u8 val)
0165 {
0166 outb(val, par->iobase + reg - 0x300);
0167 }
0168
0169 static inline void gra_outb(struct tdfx_par *par, u32 idx, u8 val)
0170 {
0171 vga_outb(par, GRA_I, idx);
0172 wmb();
0173 vga_outb(par, GRA_D, val);
0174 wmb();
0175 }
0176
0177 static inline void seq_outb(struct tdfx_par *par, u32 idx, u8 val)
0178 {
0179 vga_outb(par, SEQ_I, idx);
0180 wmb();
0181 vga_outb(par, SEQ_D, val);
0182 wmb();
0183 }
0184
0185 static inline u8 seq_inb(struct tdfx_par *par, u32 idx)
0186 {
0187 vga_outb(par, SEQ_I, idx);
0188 mb();
0189 return vga_inb(par, SEQ_D);
0190 }
0191
0192 static inline void crt_outb(struct tdfx_par *par, u32 idx, u8 val)
0193 {
0194 vga_outb(par, CRT_I, idx);
0195 wmb();
0196 vga_outb(par, CRT_D, val);
0197 wmb();
0198 }
0199
0200 static inline u8 crt_inb(struct tdfx_par *par, u32 idx)
0201 {
0202 vga_outb(par, CRT_I, idx);
0203 mb();
0204 return vga_inb(par, CRT_D);
0205 }
0206
0207 static inline void att_outb(struct tdfx_par *par, u32 idx, u8 val)
0208 {
0209 vga_inb(par, IS1_R);
0210 vga_outb(par, ATT_IW, idx);
0211 vga_outb(par, ATT_IW, val);
0212 }
0213
0214 static inline void vga_disable_video(struct tdfx_par *par)
0215 {
0216 unsigned char s;
0217
0218 s = seq_inb(par, 0x01) | 0x20;
0219 seq_outb(par, 0x00, 0x01);
0220 seq_outb(par, 0x01, s);
0221 seq_outb(par, 0x00, 0x03);
0222 }
0223
0224 static inline void vga_enable_video(struct tdfx_par *par)
0225 {
0226 unsigned char s;
0227
0228 s = seq_inb(par, 0x01) & 0xdf;
0229 seq_outb(par, 0x00, 0x01);
0230 seq_outb(par, 0x01, s);
0231 seq_outb(par, 0x00, 0x03);
0232 }
0233
0234 static inline void vga_enable_palette(struct tdfx_par *par)
0235 {
0236 vga_inb(par, IS1_R);
0237 mb();
0238 vga_outb(par, ATT_IW, 0x20);
0239 }
0240
0241 static inline u32 tdfx_inl(struct tdfx_par *par, unsigned int reg)
0242 {
0243 return readl(par->regbase_virt + reg);
0244 }
0245
0246 static inline void tdfx_outl(struct tdfx_par *par, unsigned int reg, u32 val)
0247 {
0248 writel(val, par->regbase_virt + reg);
0249 }
0250
0251 static inline void banshee_make_room(struct tdfx_par *par, int size)
0252 {
0253
0254
0255 while ((tdfx_inl(par, STATUS) & 0x1f) < size - 1)
0256 cpu_relax();
0257 }
0258
0259 static int banshee_wait_idle(struct fb_info *info)
0260 {
0261 struct tdfx_par *par = info->par;
0262 int i = 0;
0263
0264 banshee_make_room(par, 1);
0265 tdfx_outl(par, COMMAND_3D, COMMAND_3D_NOP);
0266
0267 do {
0268 if ((tdfx_inl(par, STATUS) & STATUS_BUSY) == 0)
0269 i++;
0270 } while (i < 3);
0271
0272 return 0;
0273 }
0274
0275
0276
0277
0278 static inline void do_setpalentry(struct tdfx_par *par, unsigned regno, u32 c)
0279 {
0280 banshee_make_room(par, 2);
0281 tdfx_outl(par, DACADDR, regno);
0282
0283 tdfx_inl(par, DACADDR);
0284 tdfx_outl(par, DACDATA, c);
0285 }
0286
0287 static u32 do_calc_pll(int freq, int *freq_out)
0288 {
0289 int m, n, k, best_m, best_n, best_k, best_error;
0290 int fref = 14318;
0291
0292 best_error = freq;
0293 best_n = best_m = best_k = 0;
0294
0295 for (k = 3; k >= 0; k--) {
0296 for (m = 63; m >= 0; m--) {
0297
0298
0299
0300
0301 int n_estimated = ((freq * (m + 2) << k) / fref) - 2;
0302
0303
0304 for (n = max(0, n_estimated);
0305 n <= min(255, n_estimated + 1);
0306 n++) {
0307
0308
0309
0310
0311 int f = (fref * (n + 2) / (m + 2)) >> k;
0312 int error = abs(f - freq);
0313
0314
0315
0316
0317
0318 if (error < best_error) {
0319 best_error = error;
0320 best_n = n;
0321 best_m = m;
0322 best_k = k;
0323 }
0324 }
0325 }
0326 }
0327
0328 n = best_n;
0329 m = best_m;
0330 k = best_k;
0331 *freq_out = (fref * (n + 2) / (m + 2)) >> k;
0332
0333 return (n << 8) | (m << 2) | k;
0334 }
0335
0336 static void do_write_regs(struct fb_info *info, struct banshee_reg *reg)
0337 {
0338 struct tdfx_par *par = info->par;
0339 int i;
0340
0341 banshee_wait_idle(info);
0342
0343 tdfx_outl(par, MISCINIT1, tdfx_inl(par, MISCINIT1) | 0x01);
0344
0345 crt_outb(par, 0x11, crt_inb(par, 0x11) & 0x7f);
0346
0347 banshee_make_room(par, 3);
0348 tdfx_outl(par, VGAINIT1, reg->vgainit1 & 0x001FFFFF);
0349 tdfx_outl(par, VIDPROCCFG, reg->vidcfg & ~0x00000001);
0350 #if 0
0351 tdfx_outl(par, PLLCTRL1, reg->mempll);
0352 tdfx_outl(par, PLLCTRL2, reg->gfxpll);
0353 #endif
0354 tdfx_outl(par, PLLCTRL0, reg->vidpll);
0355
0356 vga_outb(par, MISC_W, reg->misc[0x00] | 0x01);
0357
0358 for (i = 0; i < 5; i++)
0359 seq_outb(par, i, reg->seq[i]);
0360
0361 for (i = 0; i < 25; i++)
0362 crt_outb(par, i, reg->crt[i]);
0363
0364 for (i = 0; i < 9; i++)
0365 gra_outb(par, i, reg->gra[i]);
0366
0367 for (i = 0; i < 21; i++)
0368 att_outb(par, i, reg->att[i]);
0369
0370 crt_outb(par, 0x1a, reg->ext[0]);
0371 crt_outb(par, 0x1b, reg->ext[1]);
0372
0373 vga_enable_palette(par);
0374 vga_enable_video(par);
0375
0376 banshee_make_room(par, 9);
0377 tdfx_outl(par, VGAINIT0, reg->vgainit0);
0378 tdfx_outl(par, DACMODE, reg->dacmode);
0379 tdfx_outl(par, VIDDESKSTRIDE, reg->stride);
0380 tdfx_outl(par, HWCURPATADDR, reg->curspataddr);
0381
0382 tdfx_outl(par, VIDSCREENSIZE, reg->screensize);
0383 tdfx_outl(par, VIDDESKSTART, reg->startaddr);
0384 tdfx_outl(par, VIDPROCCFG, reg->vidcfg);
0385 tdfx_outl(par, VGAINIT1, reg->vgainit1);
0386 tdfx_outl(par, MISCINIT0, reg->miscinit0);
0387
0388 banshee_make_room(par, 8);
0389 tdfx_outl(par, SRCBASE, reg->startaddr);
0390 tdfx_outl(par, DSTBASE, reg->startaddr);
0391 tdfx_outl(par, COMMANDEXTRA_2D, 0);
0392 tdfx_outl(par, CLIP0MIN, 0);
0393 tdfx_outl(par, CLIP0MAX, 0x0fff0fff);
0394 tdfx_outl(par, CLIP1MIN, 0);
0395 tdfx_outl(par, CLIP1MAX, 0x0fff0fff);
0396 tdfx_outl(par, SRCXY, 0);
0397
0398 banshee_wait_idle(info);
0399 }
0400
0401 static unsigned long do_lfb_size(struct tdfx_par *par, unsigned short dev_id)
0402 {
0403 u32 draminit0 = tdfx_inl(par, DRAMINIT0);
0404 u32 draminit1 = tdfx_inl(par, DRAMINIT1);
0405 u32 miscinit1;
0406 int num_chips = (draminit0 & DRAMINIT0_SGRAM_NUM) ? 8 : 4;
0407 int chip_size;
0408 int has_sgram = draminit1 & DRAMINIT1_MEM_SDRAM;
0409
0410 if (dev_id < PCI_DEVICE_ID_3DFX_VOODOO5) {
0411
0412 chip_size = 2;
0413 if (has_sgram && !(draminit0 & DRAMINIT0_SGRAM_TYPE))
0414 chip_size = 1;
0415 } else {
0416
0417 has_sgram = 0;
0418 chip_size = draminit0 & DRAMINIT0_SGRAM_TYPE_MASK;
0419 chip_size = 1 << (chip_size >> DRAMINIT0_SGRAM_TYPE_SHIFT);
0420 }
0421
0422
0423 miscinit1 = tdfx_inl(par, MISCINIT1);
0424 miscinit1 |= has_sgram ? 0 : MISCINIT1_2DBLOCK_DIS;
0425 miscinit1 |= MISCINIT1_CLUT_INV;
0426
0427 banshee_make_room(par, 1);
0428 tdfx_outl(par, MISCINIT1, miscinit1);
0429 return num_chips * chip_size * 1024l * 1024;
0430 }
0431
0432
0433
0434 static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
0435 {
0436 struct tdfx_par *par = info->par;
0437 u32 lpitch;
0438
0439 if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 &&
0440 var->bits_per_pixel != 24 && var->bits_per_pixel != 32) {
0441 DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
0442 return -EINVAL;
0443 }
0444
0445 if (var->xres != var->xres_virtual)
0446 var->xres_virtual = var->xres;
0447
0448 if (var->yres > var->yres_virtual)
0449 var->yres_virtual = var->yres;
0450
0451 if (var->xoffset) {
0452 DPRINTK("xoffset not supported\n");
0453 return -EINVAL;
0454 }
0455 var->yoffset = 0;
0456
0457
0458
0459
0460
0461
0462
0463 if (((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) &&
0464 (par->max_pixclock < VOODOO3_MAX_PIXCLOCK)) {
0465 DPRINTK("interlace not supported\n");
0466 return -EINVAL;
0467 }
0468
0469 if (info->monspecs.hfmax && info->monspecs.vfmax &&
0470 info->monspecs.dclkmax && fb_validate_mode(var, info) < 0) {
0471 DPRINTK("mode outside monitor's specs\n");
0472 return -EINVAL;
0473 }
0474
0475 var->xres = (var->xres + 15) & ~15;
0476 lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
0477
0478 if (var->xres < 320 || var->xres > 2048) {
0479 DPRINTK("width not supported: %u\n", var->xres);
0480 return -EINVAL;
0481 }
0482
0483 if (var->yres < 200 || var->yres > 2048) {
0484 DPRINTK("height not supported: %u\n", var->yres);
0485 return -EINVAL;
0486 }
0487
0488 if (lpitch * var->yres_virtual > info->fix.smem_len) {
0489 var->yres_virtual = info->fix.smem_len / lpitch;
0490 if (var->yres_virtual < var->yres) {
0491 DPRINTK("no memory for screen (%ux%ux%u)\n",
0492 var->xres, var->yres_virtual,
0493 var->bits_per_pixel);
0494 return -EINVAL;
0495 }
0496 }
0497
0498 if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {
0499 DPRINTK("pixclock too high (%ldKHz)\n",
0500 PICOS2KHZ(var->pixclock));
0501 return -EINVAL;
0502 }
0503
0504 var->transp.offset = 0;
0505 var->transp.length = 0;
0506 switch (var->bits_per_pixel) {
0507 case 8:
0508 var->red.length = 8;
0509 var->red.offset = 0;
0510 var->green = var->red;
0511 var->blue = var->red;
0512 break;
0513 case 16:
0514 var->red.offset = 11;
0515 var->red.length = 5;
0516 var->green.offset = 5;
0517 var->green.length = 6;
0518 var->blue.offset = 0;
0519 var->blue.length = 5;
0520 break;
0521 case 32:
0522 var->transp.offset = 24;
0523 var->transp.length = 8;
0524 fallthrough;
0525 case 24:
0526 var->red.offset = 16;
0527 var->green.offset = 8;
0528 var->blue.offset = 0;
0529 var->red.length = var->green.length = var->blue.length = 8;
0530 break;
0531 }
0532 var->width = -1;
0533 var->height = -1;
0534
0535 var->accel_flags = FB_ACCELF_TEXT;
0536
0537 DPRINTK("Checking graphics mode at %dx%d depth %d\n",
0538 var->xres, var->yres, var->bits_per_pixel);
0539 return 0;
0540 }
0541
0542 static int tdfxfb_set_par(struct fb_info *info)
0543 {
0544 struct tdfx_par *par = info->par;
0545 u32 hdispend = info->var.xres;
0546 u32 hsyncsta = hdispend + info->var.right_margin;
0547 u32 hsyncend = hsyncsta + info->var.hsync_len;
0548 u32 htotal = hsyncend + info->var.left_margin;
0549 u32 hd, hs, he, ht, hbs, hbe;
0550 u32 vd, vs, ve, vt, vbs, vbe;
0551 struct banshee_reg reg;
0552 int fout, freq;
0553 u32 wd;
0554 u32 cpp = (info->var.bits_per_pixel + 7) >> 3;
0555
0556 memset(®, 0, sizeof(reg));
0557
0558 reg.vidcfg = VIDCFG_VIDPROC_ENABLE | VIDCFG_DESK_ENABLE |
0559 VIDCFG_CURS_X11 |
0560 ((cpp - 1) << VIDCFG_PIXFMT_SHIFT) |
0561 (cpp != 1 ? VIDCFG_CLUT_BYPASS : 0);
0562
0563
0564 freq = PICOS2KHZ(info->var.pixclock);
0565
0566 reg.vidcfg &= ~VIDCFG_2X;
0567
0568 if (freq > par->max_pixclock / 2) {
0569 freq = freq > par->max_pixclock ? par->max_pixclock : freq;
0570 reg.dacmode |= DACMODE_2X;
0571 reg.vidcfg |= VIDCFG_2X;
0572 hdispend >>= 1;
0573 hsyncsta >>= 1;
0574 hsyncend >>= 1;
0575 htotal >>= 1;
0576 }
0577
0578 wd = (hdispend >> 3) - 1;
0579 hd = wd;
0580 hs = (hsyncsta >> 3) - 1;
0581 he = (hsyncend >> 3) - 1;
0582 ht = (htotal >> 3) - 1;
0583 hbs = hd;
0584 hbe = ht;
0585
0586 if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
0587 vd = (info->var.yres << 1) - 1;
0588 vs = vd + (info->var.lower_margin << 1);
0589 ve = vs + (info->var.vsync_len << 1);
0590 vt = ve + (info->var.upper_margin << 1) - 1;
0591 reg.screensize = info->var.xres | (info->var.yres << 13);
0592 reg.vidcfg |= VIDCFG_HALF_MODE;
0593 reg.crt[0x09] = 0x80;
0594 } else {
0595 vd = info->var.yres - 1;
0596 vs = vd + info->var.lower_margin;
0597 ve = vs + info->var.vsync_len;
0598 vt = ve + info->var.upper_margin - 1;
0599 reg.screensize = info->var.xres | (info->var.yres << 12);
0600 reg.vidcfg &= ~VIDCFG_HALF_MODE;
0601 }
0602 vbs = vd;
0603 vbe = vt;
0604
0605
0606 reg.misc[0x00] = 0x0f |
0607 (info->var.xres < 400 ? 0xa0 :
0608 info->var.xres < 480 ? 0x60 :
0609 info->var.xres < 768 ? 0xe0 : 0x20);
0610
0611 reg.gra[0x05] = 0x40;
0612 reg.gra[0x06] = 0x05;
0613 reg.gra[0x07] = 0x0f;
0614 reg.gra[0x08] = 0xff;
0615
0616 reg.att[0x00] = 0x00;
0617 reg.att[0x01] = 0x01;
0618 reg.att[0x02] = 0x02;
0619 reg.att[0x03] = 0x03;
0620 reg.att[0x04] = 0x04;
0621 reg.att[0x05] = 0x05;
0622 reg.att[0x06] = 0x06;
0623 reg.att[0x07] = 0x07;
0624 reg.att[0x08] = 0x08;
0625 reg.att[0x09] = 0x09;
0626 reg.att[0x0a] = 0x0a;
0627 reg.att[0x0b] = 0x0b;
0628 reg.att[0x0c] = 0x0c;
0629 reg.att[0x0d] = 0x0d;
0630 reg.att[0x0e] = 0x0e;
0631 reg.att[0x0f] = 0x0f;
0632 reg.att[0x10] = 0x41;
0633 reg.att[0x12] = 0x0f;
0634
0635 reg.seq[0x00] = 0x03;
0636 reg.seq[0x01] = 0x01;
0637 reg.seq[0x02] = 0x0f;
0638 reg.seq[0x03] = 0x00;
0639 reg.seq[0x04] = 0x0e;
0640
0641 reg.crt[0x00] = ht - 4;
0642 reg.crt[0x01] = hd;
0643 reg.crt[0x02] = hbs;
0644 reg.crt[0x03] = 0x80 | (hbe & 0x1f);
0645 reg.crt[0x04] = hs;
0646 reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
0647 reg.crt[0x06] = vt;
0648 reg.crt[0x07] = ((vs & 0x200) >> 2) |
0649 ((vd & 0x200) >> 3) |
0650 ((vt & 0x200) >> 4) | 0x10 |
0651 ((vbs & 0x100) >> 5) |
0652 ((vs & 0x100) >> 6) |
0653 ((vd & 0x100) >> 7) |
0654 ((vt & 0x100) >> 8);
0655 reg.crt[0x09] |= 0x40 | ((vbs & 0x200) >> 4);
0656 reg.crt[0x10] = vs;
0657 reg.crt[0x11] = (ve & 0x0f) | 0x20;
0658 reg.crt[0x12] = vd;
0659 reg.crt[0x13] = wd;
0660 reg.crt[0x15] = vbs;
0661 reg.crt[0x16] = vbe + 1;
0662 reg.crt[0x17] = 0xc3;
0663 reg.crt[0x18] = 0xff;
0664
0665
0666 reg.ext[0x00] = (((ht & 0x100) >> 8) |
0667 ((hd & 0x100) >> 6) |
0668 ((hbs & 0x100) >> 4) |
0669 ((hbe & 0x40) >> 1) |
0670 ((hs & 0x100) >> 2) |
0671 ((he & 0x20) << 2));
0672 reg.ext[0x01] = (((vt & 0x400) >> 10) |
0673 ((vd & 0x400) >> 8) |
0674 ((vbs & 0x400) >> 6) |
0675 ((vbe & 0x400) >> 4));
0676
0677 reg.vgainit0 = VGAINIT0_8BIT_DAC |
0678 VGAINIT0_EXT_ENABLE |
0679 VGAINIT0_WAKEUP_3C3 |
0680 VGAINIT0_ALT_READBACK |
0681 VGAINIT0_EXTSHIFTOUT;
0682 reg.vgainit1 = tdfx_inl(par, VGAINIT1) & 0x1fffff;
0683
0684 if (hwcursor)
0685 reg.curspataddr = info->fix.smem_len;
0686
0687 reg.cursloc = 0;
0688
0689 reg.cursc0 = 0;
0690 reg.cursc1 = 0xffffff;
0691
0692 reg.stride = info->var.xres * cpp;
0693 reg.startaddr = info->var.yoffset * reg.stride
0694 + info->var.xoffset * cpp;
0695
0696 reg.vidpll = do_calc_pll(freq, &fout);
0697 #if 0
0698 reg.mempll = do_calc_pll(..., &fout);
0699 reg.gfxpll = do_calc_pll(..., &fout);
0700 #endif
0701
0702 if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
0703 reg.vidcfg |= VIDCFG_INTERLACE;
0704 reg.miscinit0 = tdfx_inl(par, MISCINIT0);
0705
0706 #if defined(__BIG_ENDIAN)
0707 switch (info->var.bits_per_pixel) {
0708 case 8:
0709 case 24:
0710 reg.miscinit0 &= ~(1 << 30);
0711 reg.miscinit0 &= ~(1 << 31);
0712 break;
0713 case 16:
0714 reg.miscinit0 |= (1 << 30);
0715 reg.miscinit0 |= (1 << 31);
0716 break;
0717 case 32:
0718 reg.miscinit0 |= (1 << 30);
0719 reg.miscinit0 &= ~(1 << 31);
0720 break;
0721 }
0722 #endif
0723 do_write_regs(info, ®);
0724
0725
0726 info->fix.line_length = reg.stride;
0727 info->fix.visual = (info->var.bits_per_pixel == 8)
0728 ? FB_VISUAL_PSEUDOCOLOR
0729 : FB_VISUAL_TRUECOLOR;
0730 DPRINTK("Graphics mode is now set at %dx%d depth %d\n",
0731 info->var.xres, info->var.yres, info->var.bits_per_pixel);
0732 return 0;
0733 }
0734
0735
0736 #define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
0737
0738 static int tdfxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
0739 unsigned blue, unsigned transp,
0740 struct fb_info *info)
0741 {
0742 struct tdfx_par *par = info->par;
0743 u32 rgbcol;
0744
0745 if (regno >= info->cmap.len || regno > 255)
0746 return 1;
0747
0748
0749 if (info->var.grayscale) {
0750
0751 blue = (red * 77 + green * 151 + blue * 28) >> 8;
0752 green = blue;
0753 red = blue;
0754 }
0755
0756 switch (info->fix.visual) {
0757 case FB_VISUAL_PSEUDOCOLOR:
0758 rgbcol = (((u32)red & 0xff00) << 8) |
0759 (((u32)green & 0xff00) << 0) |
0760 (((u32)blue & 0xff00) >> 8);
0761 do_setpalentry(par, regno, rgbcol);
0762 break;
0763
0764 case FB_VISUAL_TRUECOLOR:
0765 if (regno < 16) {
0766 rgbcol = (CNVT_TOHW(red, info->var.red.length) <<
0767 info->var.red.offset) |
0768 (CNVT_TOHW(green, info->var.green.length) <<
0769 info->var.green.offset) |
0770 (CNVT_TOHW(blue, info->var.blue.length) <<
0771 info->var.blue.offset) |
0772 (CNVT_TOHW(transp, info->var.transp.length) <<
0773 info->var.transp.offset);
0774 par->palette[regno] = rgbcol;
0775 }
0776
0777 break;
0778 default:
0779 DPRINTK("bad depth %u\n", info->var.bits_per_pixel);
0780 break;
0781 }
0782
0783 return 0;
0784 }
0785
0786
0787 static int tdfxfb_blank(int blank, struct fb_info *info)
0788 {
0789 struct tdfx_par *par = info->par;
0790 int vgablank = 1;
0791 u32 dacmode = tdfx_inl(par, DACMODE);
0792
0793 dacmode &= ~(BIT(1) | BIT(3));
0794
0795 switch (blank) {
0796 case FB_BLANK_UNBLANK:
0797 vgablank = 0;
0798 break;
0799 case FB_BLANK_NORMAL:
0800 break;
0801 case FB_BLANK_VSYNC_SUSPEND:
0802 dacmode |= BIT(3);
0803 break;
0804 case FB_BLANK_HSYNC_SUSPEND:
0805 dacmode |= BIT(1);
0806 break;
0807 case FB_BLANK_POWERDOWN:
0808 dacmode |= BIT(1) | BIT(3);
0809 break;
0810 }
0811
0812 banshee_make_room(par, 1);
0813 tdfx_outl(par, DACMODE, dacmode);
0814 if (vgablank)
0815 vga_disable_video(par);
0816 else
0817 vga_enable_video(par);
0818 return 0;
0819 }
0820
0821
0822
0823
0824 static int tdfxfb_pan_display(struct fb_var_screeninfo *var,
0825 struct fb_info *info)
0826 {
0827 struct tdfx_par *par = info->par;
0828 u32 addr = var->yoffset * info->fix.line_length;
0829
0830 if (nopan || var->xoffset)
0831 return -EINVAL;
0832
0833 banshee_make_room(par, 1);
0834 tdfx_outl(par, VIDDESKSTART, addr);
0835
0836 return 0;
0837 }
0838
0839 #ifdef CONFIG_FB_3DFX_ACCEL
0840
0841
0842
0843 static void tdfxfb_fillrect(struct fb_info *info,
0844 const struct fb_fillrect *rect)
0845 {
0846 struct tdfx_par *par = info->par;
0847 u32 bpp = info->var.bits_per_pixel;
0848 u32 stride = info->fix.line_length;
0849 u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
0850 int tdfx_rop;
0851 u32 dx = rect->dx;
0852 u32 dy = rect->dy;
0853 u32 dstbase = 0;
0854
0855 if (rect->rop == ROP_COPY)
0856 tdfx_rop = TDFX_ROP_COPY;
0857 else
0858 tdfx_rop = TDFX_ROP_XOR;
0859
0860
0861 if (dy + rect->height > 4095) {
0862 dstbase = stride * dy;
0863 dy = 0;
0864 }
0865
0866 if (dx + rect->width > 4095) {
0867 dstbase += dx * bpp >> 3;
0868 dx = 0;
0869 }
0870 banshee_make_room(par, 6);
0871 tdfx_outl(par, DSTFORMAT, fmt);
0872 if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) {
0873 tdfx_outl(par, COLORFORE, rect->color);
0874 } else {
0875 tdfx_outl(par, COLORFORE, par->palette[rect->color]);
0876 }
0877 tdfx_outl(par, COMMAND_2D, COMMAND_2D_FILLRECT | (tdfx_rop << 24));
0878 tdfx_outl(par, DSTBASE, dstbase);
0879 tdfx_outl(par, DSTSIZE, rect->width | (rect->height << 16));
0880 tdfx_outl(par, LAUNCH_2D, dx | (dy << 16));
0881 }
0882
0883
0884
0885
0886 static void tdfxfb_copyarea(struct fb_info *info,
0887 const struct fb_copyarea *area)
0888 {
0889 struct tdfx_par *par = info->par;
0890 u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
0891 u32 bpp = info->var.bits_per_pixel;
0892 u32 stride = info->fix.line_length;
0893 u32 blitcmd = COMMAND_2D_S2S_BITBLT | (TDFX_ROP_COPY << 24);
0894 u32 fmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
0895 u32 dstbase = 0;
0896 u32 srcbase = 0;
0897
0898
0899 if (sy + area->height > 4095) {
0900 srcbase = stride * sy;
0901 sy = 0;
0902 }
0903
0904 if (sx + area->width > 4095) {
0905 srcbase += sx * bpp >> 3;
0906 sx = 0;
0907 }
0908
0909 if (dy + area->height > 4095) {
0910 dstbase = stride * dy;
0911 dy = 0;
0912 }
0913
0914 if (dx + area->width > 4095) {
0915 dstbase += dx * bpp >> 3;
0916 dx = 0;
0917 }
0918
0919 if (area->sx <= area->dx) {
0920
0921 blitcmd |= BIT(14);
0922 sx += area->width - 1;
0923 dx += area->width - 1;
0924 }
0925 if (area->sy <= area->dy) {
0926
0927 blitcmd |= BIT(15);
0928 sy += area->height - 1;
0929 dy += area->height - 1;
0930 }
0931
0932 banshee_make_room(par, 8);
0933
0934 tdfx_outl(par, SRCFORMAT, fmt);
0935 tdfx_outl(par, DSTFORMAT, fmt);
0936 tdfx_outl(par, COMMAND_2D, blitcmd);
0937 tdfx_outl(par, DSTSIZE, area->width | (area->height << 16));
0938 tdfx_outl(par, DSTXY, dx | (dy << 16));
0939 tdfx_outl(par, SRCBASE, srcbase);
0940 tdfx_outl(par, DSTBASE, dstbase);
0941 tdfx_outl(par, LAUNCH_2D, sx | (sy << 16));
0942 }
0943
0944 static void tdfxfb_imageblit(struct fb_info *info, const struct fb_image *image)
0945 {
0946 struct tdfx_par *par = info->par;
0947 int size = image->height * ((image->width * image->depth + 7) >> 3);
0948 int fifo_free;
0949 int i, stride = info->fix.line_length;
0950 u32 bpp = info->var.bits_per_pixel;
0951 u32 dstfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13);
0952 u8 *chardata = (u8 *) image->data;
0953 u32 srcfmt;
0954 u32 dx = image->dx;
0955 u32 dy = image->dy;
0956 u32 dstbase = 0;
0957
0958 if (image->depth != 1) {
0959 #ifdef BROKEN_CODE
0960 banshee_make_room(par, 6 + ((size + 3) >> 2));
0961 srcfmt = stride | ((bpp + ((bpp == 8) ? 0 : 8)) << 13) |
0962 0x400000;
0963 #else
0964 cfb_imageblit(info, image);
0965 #endif
0966 return;
0967 }
0968 banshee_make_room(par, 9);
0969 switch (info->fix.visual) {
0970 case FB_VISUAL_PSEUDOCOLOR:
0971 tdfx_outl(par, COLORFORE, image->fg_color);
0972 tdfx_outl(par, COLORBACK, image->bg_color);
0973 break;
0974 case FB_VISUAL_TRUECOLOR:
0975 default:
0976 tdfx_outl(par, COLORFORE,
0977 par->palette[image->fg_color]);
0978 tdfx_outl(par, COLORBACK,
0979 par->palette[image->bg_color]);
0980 }
0981 #ifdef __BIG_ENDIAN
0982 srcfmt = 0x400000 | BIT(20);
0983 #else
0984 srcfmt = 0x400000;
0985 #endif
0986
0987 if (dy + image->height > 4095) {
0988 dstbase = stride * dy;
0989 dy = 0;
0990 }
0991
0992 if (dx + image->width > 4095) {
0993 dstbase += dx * bpp >> 3;
0994 dx = 0;
0995 }
0996
0997 tdfx_outl(par, DSTBASE, dstbase);
0998 tdfx_outl(par, SRCXY, 0);
0999 tdfx_outl(par, DSTXY, dx | (dy << 16));
1000 tdfx_outl(par, COMMAND_2D,
1001 COMMAND_2D_H2S_BITBLT | (TDFX_ROP_COPY << 24));
1002 tdfx_outl(par, SRCFORMAT, srcfmt);
1003 tdfx_outl(par, DSTFORMAT, dstfmt);
1004 tdfx_outl(par, DSTSIZE, image->width | (image->height << 16));
1005
1006
1007
1008 fifo_free = 0;
1009
1010
1011 for (i = (size >> 2); i > 0; i--) {
1012 if (--fifo_free < 0) {
1013 fifo_free = 31;
1014 banshee_make_room(par, fifo_free);
1015 }
1016 tdfx_outl(par, LAUNCH_2D, *(u32 *)chardata);
1017 chardata += 4;
1018 }
1019
1020
1021 banshee_make_room(par, 3);
1022 switch (size % 4) {
1023 case 0:
1024 break;
1025 case 1:
1026 tdfx_outl(par, LAUNCH_2D, *chardata);
1027 break;
1028 case 2:
1029 tdfx_outl(par, LAUNCH_2D, *(u16 *)chardata);
1030 break;
1031 case 3:
1032 tdfx_outl(par, LAUNCH_2D,
1033 *(u16 *)chardata | (chardata[3] << 24));
1034 break;
1035 }
1036 }
1037 #endif
1038
1039 static int tdfxfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1040 {
1041 struct tdfx_par *par = info->par;
1042 u32 vidcfg;
1043
1044 if (!hwcursor)
1045 return -EINVAL;
1046
1047
1048 if (cursor->image.width > 64 ||
1049 cursor->image.height > 64 ||
1050 cursor->image.depth > 1)
1051 return -EINVAL;
1052
1053 vidcfg = tdfx_inl(par, VIDPROCCFG);
1054 if (cursor->enable)
1055 tdfx_outl(par, VIDPROCCFG, vidcfg | VIDCFG_HWCURSOR_ENABLE);
1056 else
1057 tdfx_outl(par, VIDPROCCFG, vidcfg & ~VIDCFG_HWCURSOR_ENABLE);
1058
1059
1060
1061
1062
1063
1064 if (!cursor->set)
1065 return 0;
1066
1067
1068 if (cursor->set & FB_CUR_SETCMAP) {
1069 struct fb_cmap cmap = info->cmap;
1070 u32 bg_idx = cursor->image.bg_color;
1071 u32 fg_idx = cursor->image.fg_color;
1072 unsigned long bg_color, fg_color;
1073
1074 fg_color = (((u32)cmap.red[fg_idx] & 0xff00) << 8) |
1075 (((u32)cmap.green[fg_idx] & 0xff00) << 0) |
1076 (((u32)cmap.blue[fg_idx] & 0xff00) >> 8);
1077 bg_color = (((u32)cmap.red[bg_idx] & 0xff00) << 8) |
1078 (((u32)cmap.green[bg_idx] & 0xff00) << 0) |
1079 (((u32)cmap.blue[bg_idx] & 0xff00) >> 8);
1080 banshee_make_room(par, 2);
1081 tdfx_outl(par, HWCURC0, bg_color);
1082 tdfx_outl(par, HWCURC1, fg_color);
1083 }
1084
1085 if (cursor->set & FB_CUR_SETPOS) {
1086 int x = cursor->image.dx;
1087 int y = cursor->image.dy - info->var.yoffset;
1088
1089 x += 63;
1090 y += 63;
1091 banshee_make_room(par, 1);
1092 tdfx_outl(par, HWCURLOC, (y << 16) + x);
1093 }
1094 if (cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) {
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113 u8 __iomem *cursorbase = info->screen_base + info->fix.smem_len;
1114 u8 *bitmap = (u8 *)cursor->image.data;
1115 u8 *mask = (u8 *)cursor->mask;
1116 int i;
1117
1118 fb_memset(cursorbase, 0, 1024);
1119
1120 for (i = 0; i < cursor->image.height; i++) {
1121 int h = 0;
1122 int j = (cursor->image.width + 7) >> 3;
1123
1124 for (; j > 0; j--) {
1125 u8 data = *mask ^ *bitmap;
1126 if (cursor->rop == ROP_COPY)
1127 data = *mask & *bitmap;
1128
1129 fb_writeb(*mask, cursorbase + h);
1130 mask++;
1131
1132 fb_writeb(data, cursorbase + h + 8);
1133 bitmap++;
1134 h++;
1135 }
1136 cursorbase += 16;
1137 }
1138 }
1139 return 0;
1140 }
1141
1142 static const struct fb_ops tdfxfb_ops = {
1143 .owner = THIS_MODULE,
1144 .fb_check_var = tdfxfb_check_var,
1145 .fb_set_par = tdfxfb_set_par,
1146 .fb_setcolreg = tdfxfb_setcolreg,
1147 .fb_blank = tdfxfb_blank,
1148 .fb_pan_display = tdfxfb_pan_display,
1149 .fb_sync = banshee_wait_idle,
1150 .fb_cursor = tdfxfb_cursor,
1151 #ifdef CONFIG_FB_3DFX_ACCEL
1152 .fb_fillrect = tdfxfb_fillrect,
1153 .fb_copyarea = tdfxfb_copyarea,
1154 .fb_imageblit = tdfxfb_imageblit,
1155 #else
1156 .fb_fillrect = cfb_fillrect,
1157 .fb_copyarea = cfb_copyarea,
1158 .fb_imageblit = cfb_imageblit,
1159 #endif
1160 };
1161
1162 #ifdef CONFIG_FB_3DFX_I2C
1163
1164
1165
1166 static void tdfxfb_i2c_setscl(void *data, int val)
1167 {
1168 struct tdfxfb_i2c_chan *chan = data;
1169 struct tdfx_par *par = chan->par;
1170 unsigned int r;
1171
1172 r = tdfx_inl(par, VIDSERPARPORT);
1173 if (val)
1174 r |= I2C_SCL_OUT;
1175 else
1176 r &= ~I2C_SCL_OUT;
1177 tdfx_outl(par, VIDSERPARPORT, r);
1178 tdfx_inl(par, VIDSERPARPORT);
1179 }
1180
1181 static void tdfxfb_i2c_setsda(void *data, int val)
1182 {
1183 struct tdfxfb_i2c_chan *chan = data;
1184 struct tdfx_par *par = chan->par;
1185 unsigned int r;
1186
1187 r = tdfx_inl(par, VIDSERPARPORT);
1188 if (val)
1189 r |= I2C_SDA_OUT;
1190 else
1191 r &= ~I2C_SDA_OUT;
1192 tdfx_outl(par, VIDSERPARPORT, r);
1193 tdfx_inl(par, VIDSERPARPORT);
1194 }
1195
1196
1197
1198
1199
1200 static int tdfxfb_i2c_getscl(void *data)
1201 {
1202 struct tdfxfb_i2c_chan *chan = data;
1203 struct tdfx_par *par = chan->par;
1204
1205 return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SCL_IN));
1206 }
1207
1208 static int tdfxfb_i2c_getsda(void *data)
1209 {
1210 struct tdfxfb_i2c_chan *chan = data;
1211 struct tdfx_par *par = chan->par;
1212
1213 return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SDA_IN));
1214 }
1215
1216 static void tdfxfb_ddc_setscl(void *data, int val)
1217 {
1218 struct tdfxfb_i2c_chan *chan = data;
1219 struct tdfx_par *par = chan->par;
1220 unsigned int r;
1221
1222 r = tdfx_inl(par, VIDSERPARPORT);
1223 if (val)
1224 r |= DDC_SCL_OUT;
1225 else
1226 r &= ~DDC_SCL_OUT;
1227 tdfx_outl(par, VIDSERPARPORT, r);
1228 tdfx_inl(par, VIDSERPARPORT);
1229 }
1230
1231 static void tdfxfb_ddc_setsda(void *data, int val)
1232 {
1233 struct tdfxfb_i2c_chan *chan = data;
1234 struct tdfx_par *par = chan->par;
1235 unsigned int r;
1236
1237 r = tdfx_inl(par, VIDSERPARPORT);
1238 if (val)
1239 r |= DDC_SDA_OUT;
1240 else
1241 r &= ~DDC_SDA_OUT;
1242 tdfx_outl(par, VIDSERPARPORT, r);
1243 tdfx_inl(par, VIDSERPARPORT);
1244 }
1245
1246 static int tdfxfb_ddc_getscl(void *data)
1247 {
1248 struct tdfxfb_i2c_chan *chan = data;
1249 struct tdfx_par *par = chan->par;
1250
1251 return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SCL_IN));
1252 }
1253
1254 static int tdfxfb_ddc_getsda(void *data)
1255 {
1256 struct tdfxfb_i2c_chan *chan = data;
1257 struct tdfx_par *par = chan->par;
1258
1259 return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SDA_IN));
1260 }
1261
1262 static int tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan, const char *name,
1263 struct device *dev)
1264 {
1265 int rc;
1266
1267 strscpy(chan->adapter.name, name, sizeof(chan->adapter.name));
1268 chan->adapter.owner = THIS_MODULE;
1269 chan->adapter.class = I2C_CLASS_DDC;
1270 chan->adapter.algo_data = &chan->algo;
1271 chan->adapter.dev.parent = dev;
1272 chan->algo.setsda = tdfxfb_ddc_setsda;
1273 chan->algo.setscl = tdfxfb_ddc_setscl;
1274 chan->algo.getsda = tdfxfb_ddc_getsda;
1275 chan->algo.getscl = tdfxfb_ddc_getscl;
1276 chan->algo.udelay = 10;
1277 chan->algo.timeout = msecs_to_jiffies(500);
1278 chan->algo.data = chan;
1279
1280 i2c_set_adapdata(&chan->adapter, chan);
1281
1282 rc = i2c_bit_add_bus(&chan->adapter);
1283 if (rc == 0)
1284 DPRINTK("I2C bus %s registered.\n", name);
1285 else
1286 chan->par = NULL;
1287
1288 return rc;
1289 }
1290
1291 static int tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan, const char *name,
1292 struct device *dev)
1293 {
1294 int rc;
1295
1296 strscpy(chan->adapter.name, name, sizeof(chan->adapter.name));
1297 chan->adapter.owner = THIS_MODULE;
1298 chan->adapter.algo_data = &chan->algo;
1299 chan->adapter.dev.parent = dev;
1300 chan->algo.setsda = tdfxfb_i2c_setsda;
1301 chan->algo.setscl = tdfxfb_i2c_setscl;
1302 chan->algo.getsda = tdfxfb_i2c_getsda;
1303 chan->algo.getscl = tdfxfb_i2c_getscl;
1304 chan->algo.udelay = 10;
1305 chan->algo.timeout = msecs_to_jiffies(500);
1306 chan->algo.data = chan;
1307
1308 i2c_set_adapdata(&chan->adapter, chan);
1309
1310 rc = i2c_bit_add_bus(&chan->adapter);
1311 if (rc == 0)
1312 DPRINTK("I2C bus %s registered.\n", name);
1313 else
1314 chan->par = NULL;
1315
1316 return rc;
1317 }
1318
1319 static void tdfxfb_create_i2c_busses(struct fb_info *info)
1320 {
1321 struct tdfx_par *par = info->par;
1322
1323 tdfx_outl(par, VIDINFORMAT, 0x8160);
1324 tdfx_outl(par, VIDSERPARPORT, 0xcffc0020);
1325
1326 par->chan[0].par = par;
1327 par->chan[1].par = par;
1328
1329 tdfxfb_setup_ddc_bus(&par->chan[0], "Voodoo3-DDC", info->dev);
1330 tdfxfb_setup_i2c_bus(&par->chan[1], "Voodoo3-I2C", info->dev);
1331 }
1332
1333 static void tdfxfb_delete_i2c_busses(struct tdfx_par *par)
1334 {
1335 if (par->chan[0].par)
1336 i2c_del_adapter(&par->chan[0].adapter);
1337 par->chan[0].par = NULL;
1338
1339 if (par->chan[1].par)
1340 i2c_del_adapter(&par->chan[1].adapter);
1341 par->chan[1].par = NULL;
1342 }
1343
1344 static int tdfxfb_probe_i2c_connector(struct tdfx_par *par,
1345 struct fb_monspecs *specs)
1346 {
1347 u8 *edid = NULL;
1348
1349 DPRINTK("Probe DDC Bus\n");
1350 if (par->chan[0].par)
1351 edid = fb_ddc_read(&par->chan[0].adapter);
1352
1353 if (edid) {
1354 fb_edid_to_monspecs(edid, specs);
1355 kfree(edid);
1356 return 0;
1357 }
1358 return 1;
1359 }
1360 #endif
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371 static int tdfxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1372 {
1373 struct tdfx_par *default_par;
1374 struct fb_info *info;
1375 int err, lpitch;
1376 struct fb_monspecs *specs;
1377 bool found;
1378
1379 err = pci_enable_device(pdev);
1380 if (err) {
1381 printk(KERN_ERR "tdfxfb: Can't enable pdev: %d\n", err);
1382 return err;
1383 }
1384
1385 info = framebuffer_alloc(sizeof(struct tdfx_par), &pdev->dev);
1386
1387 if (!info)
1388 return -ENOMEM;
1389
1390 default_par = info->par;
1391 info->fix = tdfx_fix;
1392
1393
1394 switch (pdev->device) {
1395 case PCI_DEVICE_ID_3DFX_BANSHEE:
1396 strcpy(info->fix.id, "3Dfx Banshee");
1397 default_par->max_pixclock = BANSHEE_MAX_PIXCLOCK;
1398 break;
1399 case PCI_DEVICE_ID_3DFX_VOODOO3:
1400 strcpy(info->fix.id, "3Dfx Voodoo3");
1401 default_par->max_pixclock = VOODOO3_MAX_PIXCLOCK;
1402 break;
1403 case PCI_DEVICE_ID_3DFX_VOODOO5:
1404 strcpy(info->fix.id, "3Dfx Voodoo5");
1405 default_par->max_pixclock = VOODOO5_MAX_PIXCLOCK;
1406 break;
1407 }
1408
1409 info->fix.mmio_start = pci_resource_start(pdev, 0);
1410 info->fix.mmio_len = pci_resource_len(pdev, 0);
1411 if (!request_mem_region(info->fix.mmio_start, info->fix.mmio_len,
1412 "tdfx regbase")) {
1413 printk(KERN_ERR "tdfxfb: Can't reserve regbase\n");
1414 goto out_err;
1415 }
1416
1417 default_par->regbase_virt =
1418 ioremap(info->fix.mmio_start, info->fix.mmio_len);
1419 if (!default_par->regbase_virt) {
1420 printk(KERN_ERR "fb: Can't remap %s register area.\n",
1421 info->fix.id);
1422 goto out_err_regbase;
1423 }
1424
1425 info->fix.smem_start = pci_resource_start(pdev, 1);
1426 info->fix.smem_len = do_lfb_size(default_par, pdev->device);
1427 if (!info->fix.smem_len) {
1428 printk(KERN_ERR "fb: Can't count %s memory.\n", info->fix.id);
1429 goto out_err_regbase;
1430 }
1431
1432 if (!request_mem_region(info->fix.smem_start,
1433 pci_resource_len(pdev, 1), "tdfx smem")) {
1434 printk(KERN_ERR "tdfxfb: Can't reserve smem\n");
1435 goto out_err_regbase;
1436 }
1437
1438 info->screen_base = ioremap_wc(info->fix.smem_start,
1439 info->fix.smem_len);
1440 if (!info->screen_base) {
1441 printk(KERN_ERR "fb: Can't remap %s framebuffer.\n",
1442 info->fix.id);
1443 goto out_err_screenbase;
1444 }
1445
1446 default_par->iobase = pci_resource_start(pdev, 2);
1447
1448 if (!request_region(pci_resource_start(pdev, 2),
1449 pci_resource_len(pdev, 2), "tdfx iobase")) {
1450 printk(KERN_ERR "tdfxfb: Can't reserve iobase\n");
1451 goto out_err_screenbase;
1452 }
1453
1454 printk(KERN_INFO "fb: %s memory = %dK\n", info->fix.id,
1455 info->fix.smem_len >> 10);
1456
1457 if (!nomtrr)
1458 default_par->wc_cookie= arch_phys_wc_add(info->fix.smem_start,
1459 info->fix.smem_len);
1460
1461 info->fix.ypanstep = nopan ? 0 : 1;
1462 info->fix.ywrapstep = nowrap ? 0 : 1;
1463
1464 info->fbops = &tdfxfb_ops;
1465 info->pseudo_palette = default_par->palette;
1466 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1467 #ifdef CONFIG_FB_3DFX_ACCEL
1468 info->flags |= FBINFO_HWACCEL_FILLRECT |
1469 FBINFO_HWACCEL_COPYAREA |
1470 FBINFO_HWACCEL_IMAGEBLIT |
1471 FBINFO_READS_FAST;
1472 #endif
1473
1474
1475 if (hwcursor)
1476 info->fix.smem_len = (info->fix.smem_len - 1024) &
1477 (PAGE_MASK << 1);
1478 specs = &info->monspecs;
1479 found = false;
1480 info->var.bits_per_pixel = 8;
1481 #ifdef CONFIG_FB_3DFX_I2C
1482 tdfxfb_create_i2c_busses(info);
1483 err = tdfxfb_probe_i2c_connector(default_par, specs);
1484
1485 if (!err) {
1486 if (specs->modedb == NULL)
1487 DPRINTK("Unable to get Mode Database\n");
1488 else {
1489 const struct fb_videomode *m;
1490
1491 fb_videomode_to_modelist(specs->modedb,
1492 specs->modedb_len,
1493 &info->modelist);
1494 m = fb_find_best_display(specs, &info->modelist);
1495 if (m) {
1496 fb_videomode_to_var(&info->var, m);
1497
1498 if (tdfxfb_check_var(&info->var, info) < 0)
1499 info->var = tdfx_var;
1500 else
1501 found = true;
1502 }
1503 }
1504 }
1505 #endif
1506 if (!mode_option && !found)
1507 mode_option = "640x480@60";
1508
1509 if (mode_option) {
1510 err = fb_find_mode(&info->var, info, mode_option,
1511 specs->modedb, specs->modedb_len,
1512 NULL, info->var.bits_per_pixel);
1513 if (!err || err == 4)
1514 info->var = tdfx_var;
1515 }
1516
1517 if (found) {
1518 fb_destroy_modedb(specs->modedb);
1519 specs->modedb = NULL;
1520 }
1521
1522
1523 lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);
1524 info->var.yres_virtual = info->fix.smem_len / lpitch;
1525 if (info->var.yres_virtual < info->var.yres)
1526 goto out_err_iobase;
1527
1528 if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
1529 printk(KERN_ERR "tdfxfb: Can't allocate color map\n");
1530 goto out_err_iobase;
1531 }
1532
1533 if (register_framebuffer(info) < 0) {
1534 printk(KERN_ERR "tdfxfb: can't register framebuffer\n");
1535 fb_dealloc_cmap(&info->cmap);
1536 goto out_err_iobase;
1537 }
1538
1539
1540
1541 pci_set_drvdata(pdev, info);
1542 return 0;
1543
1544 out_err_iobase:
1545 #ifdef CONFIG_FB_3DFX_I2C
1546 tdfxfb_delete_i2c_busses(default_par);
1547 #endif
1548 arch_phys_wc_del(default_par->wc_cookie);
1549 release_region(pci_resource_start(pdev, 2),
1550 pci_resource_len(pdev, 2));
1551 out_err_screenbase:
1552 if (info->screen_base)
1553 iounmap(info->screen_base);
1554 release_mem_region(info->fix.smem_start, pci_resource_len(pdev, 1));
1555 out_err_regbase:
1556
1557
1558
1559 if (default_par->regbase_virt)
1560 iounmap(default_par->regbase_virt);
1561 release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
1562 out_err:
1563 framebuffer_release(info);
1564 return -ENXIO;
1565 }
1566
1567 #ifndef MODULE
1568 static void __init tdfxfb_setup(char *options)
1569 {
1570 char *this_opt;
1571
1572 if (!options || !*options)
1573 return;
1574
1575 while ((this_opt = strsep(&options, ",")) != NULL) {
1576 if (!*this_opt)
1577 continue;
1578 if (!strcmp(this_opt, "nopan")) {
1579 nopan = 1;
1580 } else if (!strcmp(this_opt, "nowrap")) {
1581 nowrap = 1;
1582 } else if (!strncmp(this_opt, "hwcursor=", 9)) {
1583 hwcursor = simple_strtoul(this_opt + 9, NULL, 0);
1584 } else if (!strncmp(this_opt, "nomtrr", 6)) {
1585 nomtrr = 1;
1586 } else {
1587 mode_option = this_opt;
1588 }
1589 }
1590 }
1591 #endif
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602 static void tdfxfb_remove(struct pci_dev *pdev)
1603 {
1604 struct fb_info *info = pci_get_drvdata(pdev);
1605 struct tdfx_par *par = info->par;
1606
1607 unregister_framebuffer(info);
1608 #ifdef CONFIG_FB_3DFX_I2C
1609 tdfxfb_delete_i2c_busses(par);
1610 #endif
1611 arch_phys_wc_del(par->wc_cookie);
1612 iounmap(par->regbase_virt);
1613 iounmap(info->screen_base);
1614
1615
1616 release_region(pci_resource_start(pdev, 2),
1617 pci_resource_len(pdev, 2));
1618 release_mem_region(pci_resource_start(pdev, 1),
1619 pci_resource_len(pdev, 1));
1620 release_mem_region(pci_resource_start(pdev, 0),
1621 pci_resource_len(pdev, 0));
1622 fb_dealloc_cmap(&info->cmap);
1623 framebuffer_release(info);
1624 }
1625
1626 static int __init tdfxfb_init(void)
1627 {
1628 #ifndef MODULE
1629 char *option = NULL;
1630
1631 if (fb_get_options("tdfxfb", &option))
1632 return -ENODEV;
1633
1634 tdfxfb_setup(option);
1635 #endif
1636 return pci_register_driver(&tdfxfb_driver);
1637 }
1638
1639 static void __exit tdfxfb_exit(void)
1640 {
1641 pci_unregister_driver(&tdfxfb_driver);
1642 }
1643
1644 MODULE_AUTHOR("Hannu Mallat <hmallat@cc.hut.fi>");
1645 MODULE_DESCRIPTION("3Dfx framebuffer device driver");
1646 MODULE_LICENSE("GPL");
1647
1648 module_param(hwcursor, int, 0644);
1649 MODULE_PARM_DESC(hwcursor, "Enable hardware cursor "
1650 "(1=enable, 0=disable, default=1)");
1651 module_param(mode_option, charp, 0);
1652 MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
1653 module_param(nomtrr, bool, 0);
1654 MODULE_PARM_DESC(nomtrr, "Disable MTRR support (default: enabled)");
1655
1656 module_init(tdfxfb_init);
1657 module_exit(tdfxfb_exit);