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
0068
0069
0070
0071
0072
0073
0074
0075
0076 #undef SST_DEBUG
0077
0078
0079
0080
0081
0082
0083 #include <linux/string.h>
0084 #include <linux/kernel.h>
0085 #include <linux/module.h>
0086 #include <linux/fb.h>
0087 #include <linux/pci.h>
0088 #include <linux/delay.h>
0089 #include <linux/init.h>
0090 #include <asm/io.h>
0091 #include <linux/uaccess.h>
0092 #include <video/sstfb.h>
0093
0094
0095
0096
0097 static bool vgapass;
0098 static int mem;
0099 static bool clipping = 1;
0100 static int gfxclk;
0101 static bool slowpci;
0102
0103
0104
0105
0106 #define DEFAULT_VIDEO_MODE "640x480@60"
0107
0108 static char *mode_option = DEFAULT_VIDEO_MODE;
0109
0110 enum {
0111 ID_VOODOO1 = 0,
0112 ID_VOODOO2 = 1,
0113 };
0114
0115 #define IS_VOODOO2(par) ((par)->type == ID_VOODOO2)
0116
0117 static struct sst_spec voodoo_spec[] = {
0118 { .name = "Voodoo Graphics", .default_gfx_clock = 50000, .max_gfxclk = 60 },
0119 { .name = "Voodoo2", .default_gfx_clock = 75000, .max_gfxclk = 85 },
0120 };
0121
0122
0123
0124
0125
0126
0127 #if (SST_DEBUG_REG > 0)
0128 static void sst_dbg_print_read_reg(u32 reg, u32 val) {
0129 const char *regname;
0130 switch (reg) {
0131 case FBIINIT0: regname = "FbiInit0"; break;
0132 case FBIINIT1: regname = "FbiInit1"; break;
0133 case FBIINIT2: regname = "FbiInit2"; break;
0134 case FBIINIT3: regname = "FbiInit3"; break;
0135 case FBIINIT4: regname = "FbiInit4"; break;
0136 case FBIINIT5: regname = "FbiInit5"; break;
0137 case FBIINIT6: regname = "FbiInit6"; break;
0138 default: regname = NULL; break;
0139 }
0140 if (regname == NULL)
0141 r_ddprintk("sst_read(%#x): %#x\n", reg, val);
0142 else
0143 r_dprintk(" sst_read(%s): %#x\n", regname, val);
0144 }
0145
0146 static void sst_dbg_print_write_reg(u32 reg, u32 val) {
0147 const char *regname;
0148 switch (reg) {
0149 case FBIINIT0: regname = "FbiInit0"; break;
0150 case FBIINIT1: regname = "FbiInit1"; break;
0151 case FBIINIT2: regname = "FbiInit2"; break;
0152 case FBIINIT3: regname = "FbiInit3"; break;
0153 case FBIINIT4: regname = "FbiInit4"; break;
0154 case FBIINIT5: regname = "FbiInit5"; break;
0155 case FBIINIT6: regname = "FbiInit6"; break;
0156 default: regname = NULL; break;
0157 }
0158 if (regname == NULL)
0159 r_ddprintk("sst_write(%#x, %#x)\n", reg, val);
0160 else
0161 r_dprintk(" sst_write(%s, %#x)\n", regname, val);
0162 }
0163 #else
0164 # define sst_dbg_print_read_reg(reg, val) do {} while(0)
0165 # define sst_dbg_print_write_reg(reg, val) do {} while(0)
0166 #endif
0167
0168
0169
0170
0171
0172
0173 #define sst_read(reg) __sst_read(par->mmio_vbase, reg)
0174 #define sst_write(reg,val) __sst_write(par->mmio_vbase, reg, val)
0175 #define sst_set_bits(reg,val) __sst_set_bits(par->mmio_vbase, reg, val)
0176 #define sst_unset_bits(reg,val) __sst_unset_bits(par->mmio_vbase, reg, val)
0177 #define sst_dac_read(reg) __sst_dac_read(par->mmio_vbase, reg)
0178 #define sst_dac_write(reg,val) __sst_dac_write(par->mmio_vbase, reg, val)
0179 #define dac_i_read(reg) __dac_i_read(par->mmio_vbase, reg)
0180 #define dac_i_write(reg,val) __dac_i_write(par->mmio_vbase, reg, val)
0181
0182 static inline u32 __sst_read(u8 __iomem *vbase, u32 reg)
0183 {
0184 u32 ret = readl(vbase + reg);
0185 sst_dbg_print_read_reg(reg, ret);
0186 return ret;
0187 }
0188
0189 static inline void __sst_write(u8 __iomem *vbase, u32 reg, u32 val)
0190 {
0191 sst_dbg_print_write_reg(reg, val);
0192 writel(val, vbase + reg);
0193 }
0194
0195 static inline void __sst_set_bits(u8 __iomem *vbase, u32 reg, u32 val)
0196 {
0197 r_dprintk("sst_set_bits(%#x, %#x)\n", reg, val);
0198 __sst_write(vbase, reg, __sst_read(vbase, reg) | val);
0199 }
0200
0201 static inline void __sst_unset_bits(u8 __iomem *vbase, u32 reg, u32 val)
0202 {
0203 r_dprintk("sst_unset_bits(%#x, %#x)\n", reg, val);
0204 __sst_write(vbase, reg, __sst_read(vbase, reg) & ~val);
0205 }
0206
0207
0208
0209
0210
0211
0212
0213
0214 #define sst_wait_idle() __sst_wait_idle(par->mmio_vbase)
0215
0216 static int __sst_wait_idle(u8 __iomem *vbase)
0217 {
0218 int count = 0;
0219
0220
0221
0222 while(1) {
0223 if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
0224 f_dddprintk("status: busy\n");
0225
0226
0227
0228 count = 0;
0229 } else {
0230 count++;
0231 f_dddprintk("status: idle(%d)\n", count);
0232 }
0233 if (count >= 5) return 1;
0234
0235 }
0236 }
0237
0238
0239
0240
0241 static u8 __sst_dac_read(u8 __iomem *vbase, u8 reg)
0242 {
0243 u8 ret;
0244
0245 reg &= 0x07;
0246 __sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD );
0247 __sst_wait_idle(vbase);
0248
0249 ret = __sst_read(vbase, DAC_READ) & 0xff;
0250 r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret);
0251
0252 return ret;
0253 }
0254
0255 static void __sst_dac_write(u8 __iomem *vbase, u8 reg, u8 val)
0256 {
0257 r_dprintk("sst_dac_write(%#x, %#x)\n", reg, val);
0258 reg &= 0x07;
0259 __sst_write(vbase, DAC_DATA,(((u32)reg << 8)) | (u32)val);
0260 __sst_wait_idle(vbase);
0261 }
0262
0263
0264 static u32 __dac_i_read(u8 __iomem *vbase, u8 reg)
0265 {
0266 u32 ret;
0267
0268 __sst_dac_write(vbase, DACREG_ADDR_I, reg);
0269 ret = __sst_dac_read(vbase, DACREG_DATA_I);
0270 r_dprintk("sst_dac_read_i(%#x): %#x\n", reg, ret);
0271 return ret;
0272 }
0273 static void __dac_i_write(u8 __iomem *vbase, u8 reg,u8 val)
0274 {
0275 r_dprintk("sst_dac_write_i(%#x, %#x)\n", reg, val);
0276 __sst_dac_write(vbase, DACREG_ADDR_I, reg);
0277 __sst_dac_write(vbase, DACREG_DATA_I, val);
0278 }
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291 static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
0292 {
0293 int m, m2, n, p, best_err, fout;
0294 int best_n = -1;
0295 int best_m = -1;
0296
0297 best_err = freq;
0298 p = 3;
0299
0300 while (((1 << p) * freq > VCO_MAX) && (p >= 0))
0301 p--;
0302 if (p == -1)
0303 return -EINVAL;
0304 for (n = 1; n < 32; n++) {
0305
0306 m2 = (2 * freq * (1 << p) * (n + 2) ) / DAC_FREF - 4 ;
0307
0308 m = (m2 % 2 ) ? m2/2+1 : m2/2 ;
0309 if (m >= 128)
0310 break;
0311 fout = (DAC_FREF * (m + 2)) / ((1 << p) * (n + 2));
0312 if ((abs(fout - freq) < best_err) && (m > 0)) {
0313 best_n = n;
0314 best_m = m;
0315 best_err = abs(fout - freq);
0316
0317 if (200*best_err < freq) break;
0318 }
0319 }
0320 if (best_n == -1)
0321 return -EINVAL;
0322 t->p = p;
0323 t->n = best_n;
0324 t->m = best_m;
0325 *freq_out = (DAC_FREF * (t->m + 2)) / ((1 << t->p) * (t->n + 2));
0326 f_ddprintk ("m: %d, n: %d, p: %d, F: %dKhz\n",
0327 t->m, t->n, t->p, *freq_out);
0328 return 0;
0329 }
0330
0331
0332
0333
0334 static void sstfb_clear_screen(struct fb_info *info)
0335 {
0336
0337 fb_memset(info->screen_base, 0, info->fix.smem_len);
0338 }
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350 static int sstfb_check_var(struct fb_var_screeninfo *var,
0351 struct fb_info *info)
0352 {
0353 struct sstfb_par *par = info->par;
0354 int hSyncOff = var->xres + var->right_margin + var->left_margin;
0355 int vSyncOff = var->yres + var->lower_margin + var->upper_margin;
0356 int vBackPorch = var->left_margin, yDim = var->yres;
0357 int vSyncOn = var->vsync_len;
0358 int tiles_in_X, real_length;
0359 unsigned int freq;
0360
0361 if (sst_calc_pll(PICOS2KHZ(var->pixclock), &freq, &par->pll)) {
0362 printk(KERN_ERR "sstfb: Pixclock at %ld KHZ out of range\n",
0363 PICOS2KHZ(var->pixclock));
0364 return -EINVAL;
0365 }
0366 var->pixclock = KHZ2PICOS(freq);
0367
0368 if (var->vmode & FB_VMODE_INTERLACED)
0369 vBackPorch += (vBackPorch % 2);
0370 if (var->vmode & FB_VMODE_DOUBLE) {
0371 vBackPorch <<= 1;
0372 yDim <<=1;
0373 vSyncOn <<=1;
0374 vSyncOff <<=1;
0375 }
0376
0377 switch (var->bits_per_pixel) {
0378 case 0 ... 16 :
0379 var->bits_per_pixel = 16;
0380 break;
0381 default :
0382 printk(KERN_ERR "sstfb: Unsupported bpp %d\n", var->bits_per_pixel);
0383 return -EINVAL;
0384 }
0385
0386
0387 if (var->xres <= 1 || yDim <= 0 || var->hsync_len <= 1 ||
0388 hSyncOff <= 1 || var->left_margin <= 2 || vSyncOn <= 0 ||
0389 vSyncOff <= 0 || vBackPorch <= 0) {
0390 return -EINVAL;
0391 }
0392
0393 if (IS_VOODOO2(par)) {
0394
0395 tiles_in_X = (var->xres + 63 ) / 64 * 2;
0396
0397 if (var->xres > POW2(11) || yDim >= POW2(11)) {
0398 printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n",
0399 var->xres, var->yres);
0400 return -EINVAL;
0401 }
0402
0403 if (var->hsync_len > POW2(9) || hSyncOff > POW2(11) ||
0404 var->left_margin - 2 >= POW2(9) || vSyncOn >= POW2(13) ||
0405 vSyncOff >= POW2(13) || vBackPorch >= POW2(9) ||
0406 tiles_in_X >= POW2(6) || tiles_in_X <= 0) {
0407 printk(KERN_ERR "sstfb: Unsupported timings\n");
0408 return -EINVAL;
0409 }
0410 } else {
0411
0412 tiles_in_X = (var->xres + 63 ) / 64;
0413
0414 if (var->vmode) {
0415 printk(KERN_ERR "sstfb: Interlace/doublescan not supported %#x\n",
0416 var->vmode);
0417 return -EINVAL;
0418 }
0419 if (var->xres > POW2(10) || var->yres >= POW2(10)) {
0420 printk(KERN_ERR "sstfb: Unsupported resolution %dx%d\n",
0421 var->xres, var->yres);
0422 return -EINVAL;
0423 }
0424 if (var->hsync_len > POW2(8) || hSyncOff - 1 > POW2(10) ||
0425 var->left_margin - 2 >= POW2(8) || vSyncOn >= POW2(12) ||
0426 vSyncOff >= POW2(12) || vBackPorch >= POW2(8) ||
0427 tiles_in_X >= POW2(4) || tiles_in_X <= 0) {
0428 printk(KERN_ERR "sstfb: Unsupported timings\n");
0429 return -EINVAL;
0430 }
0431 }
0432
0433
0434
0435 real_length = tiles_in_X * (IS_VOODOO2(par) ? 32 : 64 )
0436 * ((var->bits_per_pixel == 16) ? 2 : 4);
0437
0438 if (real_length * yDim > info->fix.smem_len) {
0439 printk(KERN_ERR "sstfb: Not enough video memory\n");
0440 return -ENOMEM;
0441 }
0442
0443 var->sync &= (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
0444 var->vmode &= (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE);
0445 var->xoffset = 0;
0446 var->yoffset = 0;
0447 var->height = -1;
0448 var->width = -1;
0449
0450
0451
0452
0453
0454
0455 switch (var->bits_per_pixel) {
0456 case 16:
0457 var->red.length = 5;
0458 var->green.length = 6;
0459 var->blue.length = 5;
0460 var->transp.length = 0;
0461
0462 var->red.offset = 11;
0463 var->green.offset = 5;
0464 var->blue.offset = 0;
0465 var->transp.offset = 0;
0466 break;
0467 default:
0468 return -EINVAL;
0469 }
0470 return 0;
0471 }
0472
0473
0474
0475
0476
0477 static int sstfb_set_par(struct fb_info *info)
0478 {
0479 struct sstfb_par *par = info->par;
0480 u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
0481 struct pci_dev *sst_dev = par->dev;
0482 unsigned int freq;
0483 int ntiles;
0484
0485 par->hSyncOff = info->var.xres + info->var.right_margin + info->var.left_margin;
0486
0487 par->yDim = info->var.yres;
0488 par->vSyncOn = info->var.vsync_len;
0489 par->vSyncOff = info->var.yres + info->var.lower_margin + info->var.upper_margin;
0490 par->vBackPorch = info->var.upper_margin;
0491
0492
0493 sst_calc_pll(PICOS2KHZ(info->var.pixclock), &freq, &par->pll);
0494
0495 if (info->var.vmode & FB_VMODE_INTERLACED)
0496 par->vBackPorch += (par->vBackPorch % 2);
0497 if (info->var.vmode & FB_VMODE_DOUBLE) {
0498 par->vBackPorch <<= 1;
0499 par->yDim <<=1;
0500 par->vSyncOn <<=1;
0501 par->vSyncOff <<=1;
0502 }
0503
0504 if (IS_VOODOO2(par)) {
0505
0506
0507 par->tiles_in_X = (info->var.xres + 63 ) / 64 * 2;
0508 } else {
0509
0510 par->tiles_in_X = (info->var.xres + 63 ) / 64;
0511 }
0512
0513 f_ddprintk("hsync_len hSyncOff vsync_len vSyncOff\n");
0514 f_ddprintk("%-7d %-8d %-7d %-8d\n",
0515 info->var.hsync_len, par->hSyncOff,
0516 par->vSyncOn, par->vSyncOff);
0517 f_ddprintk("left_margin upper_margin xres yres Freq\n");
0518 f_ddprintk("%-10d %-10d %-4d %-4d %-8ld\n",
0519 info->var.left_margin, info->var.upper_margin,
0520 info->var.xres, info->var.yres, PICOS2KHZ(info->var.pixclock));
0521
0522 sst_write(NOPCMD, 0);
0523 sst_wait_idle();
0524 pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
0525 sst_set_bits(FBIINIT1, VIDEO_RESET);
0526 sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
0527 sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
0528 sst_wait_idle();
0529
0530
0531
0532 sst_write(BACKPORCH, par->vBackPorch << 16 | (info->var.left_margin - 2));
0533 sst_write(VIDEODIMENSIONS, par->yDim << 16 | (info->var.xres - 1));
0534 sst_write(HSYNC, (par->hSyncOff - 1) << 16 | (info->var.hsync_len - 1));
0535 sst_write(VSYNC, par->vSyncOff << 16 | par->vSyncOn);
0536
0537 fbiinit2 = sst_read(FBIINIT2);
0538 fbiinit3 = sst_read(FBIINIT3);
0539
0540
0541 pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
0542 PCI_EN_INIT_WR | PCI_REMAP_DAC );
0543
0544 par->dac_sw.set_vidmod(info, info->var.bits_per_pixel);
0545
0546
0547 par->dac_sw.set_pll(info, &par->pll, VID_CLOCK);
0548
0549
0550 pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
0551 PCI_EN_INIT_WR);
0552
0553
0554 sst_write(FBIINIT2,fbiinit2);
0555 sst_write(FBIINIT3,fbiinit3);
0556
0557 fbiinit1 = (sst_read(FBIINIT1) & VIDEO_MASK)
0558 | EN_DATA_OE
0559 | EN_BLANK_OE
0560 | EN_HVSYNC_OE
0561 | EN_DCLK_OE
0562
0563 | SEL_INPUT_VCLK_2X
0564
0565 ;
0566
0567
0568
0569
0570
0571
0572
0573
0574 ntiles = par->tiles_in_X;
0575 if (IS_VOODOO2(par)) {
0576 fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT
0577 | ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT;
0578
0579
0580
0581
0582 fbiinit6 = (ntiles & 0x1) << TILES_IN_X_LSB_SHIFT;
0583 }
0584 else
0585 fbiinit1 |= ntiles << TILES_IN_X_SHIFT;
0586
0587 switch (info->var.bits_per_pixel) {
0588 case 16:
0589 fbiinit1 |= SEL_SOURCE_VCLK_2X_SEL;
0590 break;
0591 default:
0592 return -EINVAL;
0593 }
0594 sst_write(FBIINIT1, fbiinit1);
0595 if (IS_VOODOO2(par)) {
0596 sst_write(FBIINIT6, fbiinit6);
0597 fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;
0598 if (info->var.vmode & FB_VMODE_INTERLACED)
0599 fbiinit5 |= INTERLACE;
0600 if (info->var.vmode & FB_VMODE_DOUBLE)
0601 fbiinit5 |= VDOUBLESCAN;
0602 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
0603 fbiinit5 |= HSYNC_HIGH;
0604 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
0605 fbiinit5 |= VSYNC_HIGH;
0606 sst_write(FBIINIT5, fbiinit5);
0607 }
0608 sst_wait_idle();
0609 sst_unset_bits(FBIINIT1, VIDEO_RESET);
0610 sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
0611 sst_set_bits(FBIINIT2, EN_DRAM_REFRESH);
0612
0613 pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
0614
0615
0616
0617 switch (info->var.bits_per_pixel) {
0618 case 16:
0619 lfbmode = LFB_565;
0620 break;
0621 default:
0622 return -EINVAL;
0623 }
0624
0625 #if defined(__BIG_ENDIAN)
0626
0627
0628
0629
0630
0631 lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR |
0632 LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD );
0633 #endif
0634
0635 if (clipping) {
0636 sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE);
0637
0638
0639
0640
0641
0642
0643
0644
0645 f_ddprintk("setting clipping dimensions 0..%d, 0..%d\n",
0646 info->var.xres - 1, par->yDim - 1);
0647
0648 sst_write(CLIP_LEFT_RIGHT, info->var.xres);
0649 sst_write(CLIP_LOWY_HIGHY, par->yDim);
0650 sst_set_bits(FBZMODE, EN_CLIPPING | EN_RGB_WRITE);
0651 } else {
0652
0653 sst_write(LFBMODE, lfbmode);
0654 }
0655 return 0;
0656 }
0657
0658
0659
0660
0661
0662
0663
0664
0665
0666
0667 static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
0668 u_int transp, struct fb_info *info)
0669 {
0670 struct sstfb_par *par = info->par;
0671 u32 col;
0672
0673 f_dddprintk("sstfb_setcolreg\n");
0674 f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",
0675 regno, red, green, blue, transp);
0676 if (regno > 15)
0677 return 0;
0678
0679 red >>= (16 - info->var.red.length);
0680 green >>= (16 - info->var.green.length);
0681 blue >>= (16 - info->var.blue.length);
0682 transp >>= (16 - info->var.transp.length);
0683 col = (red << info->var.red.offset)
0684 | (green << info->var.green.offset)
0685 | (blue << info->var.blue.offset)
0686 | (transp << info->var.transp.offset);
0687
0688 par->palette[regno] = col;
0689
0690 return 0;
0691 }
0692
0693 static void sstfb_setvgapass( struct fb_info *info, int enable )
0694 {
0695 struct sstfb_par *par = info->par;
0696 struct pci_dev *sst_dev = par->dev;
0697 u32 fbiinit0, tmp;
0698
0699 enable = enable ? 1:0;
0700 if (par->vgapass == enable)
0701 return;
0702 par->vgapass = enable;
0703
0704 pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
0705 pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
0706 tmp | PCI_EN_INIT_WR );
0707 fbiinit0 = sst_read (FBIINIT0);
0708 if (par->vgapass) {
0709 sst_write(FBIINIT0, fbiinit0 & ~DIS_VGA_PASSTHROUGH);
0710 fb_info(info, "Enabling VGA pass-through\n");
0711 } else {
0712 sst_write(FBIINIT0, fbiinit0 | DIS_VGA_PASSTHROUGH);
0713 fb_info(info, "Disabling VGA pass-through\n");
0714 }
0715 pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
0716 }
0717
0718 static ssize_t store_vgapass(struct device *device, struct device_attribute *attr,
0719 const char *buf, size_t count)
0720 {
0721 struct fb_info *info = dev_get_drvdata(device);
0722 char ** last = NULL;
0723 int val;
0724
0725 val = simple_strtoul(buf, last, 0);
0726 sstfb_setvgapass(info, val);
0727
0728 return count;
0729 }
0730
0731 static ssize_t show_vgapass(struct device *device, struct device_attribute *attr,
0732 char *buf)
0733 {
0734 struct fb_info *info = dev_get_drvdata(device);
0735 struct sstfb_par *par = info->par;
0736 return sprintf(buf, "%d\n", par->vgapass);
0737 }
0738
0739 static struct device_attribute device_attrs[] = {
0740 __ATTR(vgapass, S_IRUGO|S_IWUSR, show_vgapass, store_vgapass)
0741 };
0742
0743 static int sstfb_ioctl(struct fb_info *info, unsigned int cmd,
0744 unsigned long arg)
0745 {
0746 struct sstfb_par *par;
0747 u32 val;
0748
0749 switch (cmd) {
0750
0751 case SSTFB_SET_VGAPASS:
0752 if (copy_from_user(&val, (void __user *)arg, sizeof(val)))
0753 return -EFAULT;
0754 sstfb_setvgapass(info, val);
0755 return 0;
0756 case SSTFB_GET_VGAPASS:
0757 par = info->par;
0758 val = par->vgapass;
0759 if (copy_to_user((void __user *)arg, &val, sizeof(val)))
0760 return -EFAULT;
0761 return 0;
0762 }
0763
0764 return -EINVAL;
0765 }
0766
0767
0768
0769
0770
0771 #if 0
0772 static void sstfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
0773 {
0774 struct sstfb_par *par = info->par;
0775 u32 stride = info->fix.line_length;
0776
0777 if (!IS_VOODOO2(par))
0778 return;
0779
0780 sst_write(BLTSRCBASEADDR, 0);
0781 sst_write(BLTDSTBASEADDR, 0);
0782 sst_write(BLTROP, BLTROP_COPY);
0783 sst_write(BLTXYSTRIDES, stride | (stride << 16));
0784 sst_write(BLTSRCXY, area->sx | (area->sy << 16));
0785 sst_write(BLTDSTXY, area->dx | (area->dy << 16));
0786 sst_write(BLTSIZE, area->width | (area->height << 16));
0787 sst_write(BLTCOMMAND, BLT_SCR2SCR_BITBLT | LAUNCH_BITBLT |
0788 (BLT_16BPP_FMT << 3) | BIT(15) );
0789 sst_wait_idle();
0790 }
0791 #endif
0792
0793
0794
0795
0796
0797 #if 0
0798 static void sstfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
0799 {
0800 struct sstfb_par *par = info->par;
0801 u32 stride = info->fix.line_length;
0802
0803 if (!IS_VOODOO2(par))
0804 return;
0805
0806 sst_write(BLTCLIPX, info->var.xres);
0807 sst_write(BLTCLIPY, info->var.yres);
0808
0809 sst_write(BLTDSTBASEADDR, 0);
0810 sst_write(BLTCOLOR, rect->color);
0811 sst_write(BLTROP, rect->rop == ROP_COPY ? BLTROP_COPY : BLTROP_XOR);
0812 sst_write(BLTXYSTRIDES, stride | (stride << 16));
0813 sst_write(BLTDSTXY, rect->dx | (rect->dy << 16));
0814 sst_write(BLTSIZE, rect->width | (rect->height << 16));
0815 sst_write(BLTCOMMAND, BLT_RECFILL_BITBLT | LAUNCH_BITBLT
0816 | (BLT_16BPP_FMT << 3) | BIT(15) | BIT(16) );
0817 sst_wait_idle();
0818 }
0819 #endif
0820
0821
0822
0823
0824
0825
0826 static int sst_get_memsize(struct fb_info *info, __u32 *memsize)
0827 {
0828 u8 __iomem *fbbase_virt = info->screen_base;
0829
0830
0831 if (mem >= 1 && mem <= 4) {
0832 *memsize = (mem * 0x100000);
0833 printk(KERN_INFO "supplied memsize: %#x\n", *memsize);
0834 return 1;
0835 }
0836
0837 writel(0xdeadbeef, fbbase_virt);
0838 writel(0xdeadbeef, fbbase_virt+0x100000);
0839 writel(0xdeadbeef, fbbase_virt+0x200000);
0840 f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",
0841 readl(fbbase_virt), readl(fbbase_virt + 0x100000),
0842 readl(fbbase_virt + 0x200000));
0843
0844 writel(0xabcdef01, fbbase_virt);
0845
0846 f_ddprintk("0MB: %#x, 1MB: %#x, 2MB: %#x\n",
0847 readl(fbbase_virt), readl(fbbase_virt + 0x100000),
0848 readl(fbbase_virt + 0x200000));
0849
0850
0851 if (readl(fbbase_virt + 0x200000) == 0xdeadbeef)
0852 *memsize = 0x400000;
0853 else if (readl(fbbase_virt + 0x100000) == 0xdeadbeef)
0854 *memsize = 0x200000;
0855 else
0856 *memsize = 0x100000;
0857 f_ddprintk("detected memsize: %dMB\n", *memsize >> 20);
0858 return 1;
0859 }
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869 static int sst_detect_att(struct fb_info *info)
0870 {
0871 struct sstfb_par *par = info->par;
0872 int i, mir, dir;
0873
0874 for (i = 0; i < 3; i++) {
0875 sst_dac_write(DACREG_WMA, 0);
0876 sst_dac_read(DACREG_RMR);
0877 sst_dac_read(DACREG_RMR);
0878 sst_dac_read(DACREG_RMR);
0879 sst_dac_read(DACREG_RMR);
0880
0881 sst_dac_read(DACREG_RMR);
0882
0883 mir = sst_dac_read(DACREG_RMR);
0884
0885 dir = sst_dac_read(DACREG_RMR);
0886 f_ddprintk("mir: %#x, dir: %#x\n", mir, dir);
0887 if (mir == DACREG_MIR_ATT && dir == DACREG_DIR_ATT) {
0888 return 1;
0889 }
0890 }
0891 return 0;
0892 }
0893
0894 static int sst_detect_ti(struct fb_info *info)
0895 {
0896 struct sstfb_par *par = info->par;
0897 int i, mir, dir;
0898
0899 for (i = 0; i<3; i++) {
0900 sst_dac_write(DACREG_WMA, 0);
0901 sst_dac_read(DACREG_RMR);
0902 sst_dac_read(DACREG_RMR);
0903 sst_dac_read(DACREG_RMR);
0904 sst_dac_read(DACREG_RMR);
0905
0906 sst_dac_read(DACREG_RMR);
0907
0908 mir = sst_dac_read(DACREG_RMR);
0909
0910 dir = sst_dac_read(DACREG_RMR);
0911 f_ddprintk("mir: %#x, dir: %#x\n", mir, dir);
0912 if ((mir == DACREG_MIR_TI ) && (dir == DACREG_DIR_TI)) {
0913 return 1;
0914 }
0915 }
0916 return 0;
0917 }
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930 static int sst_detect_ics(struct fb_info *info)
0931 {
0932 struct sstfb_par *par = info->par;
0933 int m_clk0_1, m_clk0_7, m_clk1_b;
0934 int n_clk0_1, n_clk0_7, n_clk1_b;
0935 int i;
0936
0937 for (i = 0; i<5; i++ ) {
0938 sst_dac_write(DACREG_ICS_PLLRMA, 0x1);
0939 m_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);
0940 n_clk0_1 = sst_dac_read(DACREG_ICS_PLLDATA);
0941 sst_dac_write(DACREG_ICS_PLLRMA, 0x7);
0942 m_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA);
0943 n_clk0_7 = sst_dac_read(DACREG_ICS_PLLDATA);
0944 sst_dac_write(DACREG_ICS_PLLRMA, 0xb);
0945 m_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA);
0946 n_clk1_b= sst_dac_read(DACREG_ICS_PLLDATA);
0947 f_ddprintk("m_clk0_1: %#x, m_clk0_7: %#x, m_clk1_b: %#x\n",
0948 m_clk0_1, m_clk0_7, m_clk1_b);
0949 f_ddprintk("n_clk0_1: %#x, n_clk0_7: %#x, n_clk1_b: %#x\n",
0950 n_clk0_1, n_clk0_7, n_clk1_b);
0951 if (( m_clk0_1 == DACREG_ICS_PLL_CLK0_1_INI)
0952 && (m_clk0_7 == DACREG_ICS_PLL_CLK0_7_INI)
0953 && (m_clk1_b == DACREG_ICS_PLL_CLK1_B_INI)) {
0954 return 1;
0955 }
0956 }
0957 return 0;
0958 }
0959
0960
0961
0962
0963
0964
0965
0966 static int sst_set_pll_att_ti(struct fb_info *info,
0967 const struct pll_timing *t, const int clock)
0968 {
0969 struct sstfb_par *par = info->par;
0970 u8 cr0, cc;
0971
0972
0973 sst_dac_write(DACREG_WMA, 0);
0974 sst_dac_read(DACREG_RMR);
0975 sst_dac_read(DACREG_RMR);
0976 sst_dac_read(DACREG_RMR);
0977 sst_dac_read(DACREG_RMR);
0978 cr0 = sst_dac_read(DACREG_RMR);
0979
0980 sst_dac_write(DACREG_WMA, 0);
0981 sst_dac_read(DACREG_RMR);
0982 sst_dac_read(DACREG_RMR);
0983 sst_dac_read(DACREG_RMR);
0984 sst_dac_read(DACREG_RMR);
0985 sst_dac_write(DACREG_RMR, (cr0 & 0xf0)
0986 | DACREG_CR0_EN_INDEXED
0987 | DACREG_CR0_8BIT
0988 | DACREG_CR0_PWDOWN );
0989
0990
0991
0992 udelay(300);
0993 cc = dac_i_read(DACREG_CC_I);
0994 switch (clock) {
0995 case VID_CLOCK:
0996 dac_i_write(DACREG_AC0_I, t->m);
0997 dac_i_write(DACREG_AC1_I, t->p << 6 | t->n);
0998 dac_i_write(DACREG_CC_I,
0999 (cc & 0x0f) | DACREG_CC_CLKA | DACREG_CC_CLKA_C);
1000 break;
1001 case GFX_CLOCK:
1002 dac_i_write(DACREG_BD0_I, t->m);
1003 dac_i_write(DACREG_BD1_I, t->p << 6 | t->n);
1004 dac_i_write(DACREG_CC_I,
1005 (cc & 0xf0) | DACREG_CC_CLKB | DACREG_CC_CLKB_D);
1006 break;
1007 default:
1008 dprintk("%s: wrong clock code '%d'\n",
1009 __func__, clock);
1010 return 0;
1011 }
1012 udelay(300);
1013
1014
1015 dac_i_write(DACREG_CR0_I,
1016 cr0 & ~DACREG_CR0_PWDOWN & ~DACREG_CR0_EN_INDEXED);
1017 return 1;
1018 }
1019
1020 static int sst_set_pll_ics(struct fb_info *info,
1021 const struct pll_timing *t, const int clock)
1022 {
1023 struct sstfb_par *par = info->par;
1024 u8 pll_ctrl;
1025
1026 sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);
1027 pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA);
1028 switch(clock) {
1029 case VID_CLOCK:
1030 sst_dac_write(DACREG_ICS_PLLWMA, 0x0);
1031 sst_dac_write(DACREG_ICS_PLLDATA, t->m);
1032 sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);
1033
1034 sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
1035 sst_dac_write(DACREG_ICS_PLLDATA,
1036 (pll_ctrl & 0xd8)
1037 | DACREG_ICS_CLK0
1038 | DACREG_ICS_CLK0_0);
1039 break;
1040 case GFX_CLOCK :
1041 sst_dac_write(DACREG_ICS_PLLWMA, 0xa);
1042 sst_dac_write(DACREG_ICS_PLLDATA, t->m);
1043 sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);
1044
1045 sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
1046 sst_dac_write(DACREG_ICS_PLLDATA,
1047 (pll_ctrl & 0xef) | DACREG_ICS_CLK1_A);
1048 break;
1049 default:
1050 dprintk("%s: wrong clock code '%d'\n",
1051 __func__, clock);
1052 return 0;
1053 }
1054 udelay(300);
1055 return 1;
1056 }
1057
1058 static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
1059 {
1060 struct sstfb_par *par = info->par;
1061 u8 cr0;
1062
1063 sst_dac_write(DACREG_WMA, 0);
1064 sst_dac_read(DACREG_RMR);
1065 sst_dac_read(DACREG_RMR);
1066 sst_dac_read(DACREG_RMR);
1067 sst_dac_read(DACREG_RMR);
1068
1069 cr0 = sst_dac_read(DACREG_RMR);
1070
1071 sst_dac_write(DACREG_WMA, 0);
1072 sst_dac_read(DACREG_RMR);
1073 sst_dac_read(DACREG_RMR);
1074 sst_dac_read(DACREG_RMR);
1075 sst_dac_read(DACREG_RMR);
1076
1077 switch(bpp) {
1078 case 16:
1079 sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP);
1080 break;
1081 default:
1082 dprintk("%s: bad depth '%u'\n", __func__, bpp);
1083 break;
1084 }
1085 }
1086
1087 static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
1088 {
1089 struct sstfb_par *par = info->par;
1090
1091 switch(bpp) {
1092 case 16:
1093 sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP);
1094 break;
1095 default:
1096 dprintk("%s: bad depth '%u'\n", __func__, bpp);
1097 break;
1098 }
1099 }
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109 static struct dac_switch dacs[] = {
1110 { .name = "TI TVP3409",
1111 .detect = sst_detect_ti,
1112 .set_pll = sst_set_pll_att_ti,
1113 .set_vidmod = sst_set_vidmod_att_ti },
1114
1115 { .name = "AT&T ATT20C409",
1116 .detect = sst_detect_att,
1117 .set_pll = sst_set_pll_att_ti,
1118 .set_vidmod = sst_set_vidmod_att_ti },
1119 { .name = "ICS ICS5342",
1120 .detect = sst_detect_ics,
1121 .set_pll = sst_set_pll_ics,
1122 .set_vidmod = sst_set_vidmod_ics },
1123 };
1124
1125 static int sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
1126 {
1127 int i, ret = 0;
1128
1129 for (i = 0; i < ARRAY_SIZE(dacs); i++) {
1130 ret = dacs[i].detect(info);
1131 if (ret)
1132 break;
1133 }
1134 if (!ret)
1135 return 0;
1136 f_dprintk("%s found %s\n", __func__, dacs[i].name);
1137 par->dac_sw = dacs[i];
1138 return 1;
1139 }
1140
1141
1142
1143
1144 static int sst_init(struct fb_info *info, struct sstfb_par *par)
1145 {
1146 u32 fbiinit0, fbiinit1, fbiinit4;
1147 struct pci_dev *dev = par->dev;
1148 struct pll_timing gfx_timings;
1149 struct sst_spec *spec;
1150 int Fout;
1151 int gfx_clock;
1152
1153 spec = &voodoo_spec[par->type];
1154 f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 "
1155 " fbiinit6\n");
1156 f_ddprintk("%0#10x %0#10x %0#10x %0#10x %0#10x %0#10x\n",
1157 sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2),
1158 sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6));
1159
1160 pci_write_config_dword(dev, PCI_VCLK_DISABLE, 0);
1161
1162
1163 pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
1164
1165 sst_set_bits(FBIINIT1, VIDEO_RESET);
1166 sst_wait_idle();
1167
1168 sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
1169 sst_wait_idle();
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179 sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
1180 sst_wait_idle();
1181
1182 pci_write_config_dword(dev, PCI_INIT_ENABLE,
1183 PCI_EN_INIT_WR | PCI_REMAP_DAC );
1184
1185 if (!sst_detect_dactype(info, par)) {
1186 printk(KERN_ERR "sstfb: unknown dac type.\n");
1187
1188 return 0;
1189 }
1190
1191
1192 gfx_clock = spec->default_gfx_clock;
1193 if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {
1194 printk(KERN_INFO "sstfb: Using supplied graphic freq : %dMHz\n", gfxclk);
1195 gfx_clock = gfxclk *1000;
1196 } else if (gfxclk) {
1197 printk(KERN_WARNING "sstfb: %dMhz is way out of spec! Using default\n", gfxclk);
1198 }
1199
1200 sst_calc_pll(gfx_clock, &Fout, &gfx_timings);
1201 par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
1202
1203
1204 pci_write_config_dword(dev, PCI_INIT_ENABLE,
1205 PCI_EN_INIT_WR| PCI_EN_FIFO_WR );
1206
1207
1208 fbiinit0 = FBIINIT0_DEFAULT;
1209 fbiinit1 = FBIINIT1_DEFAULT;
1210 fbiinit4 = FBIINIT4_DEFAULT;
1211 par->vgapass = vgapass;
1212 if (par->vgapass)
1213 fbiinit0 &= ~DIS_VGA_PASSTHROUGH;
1214 else
1215 fbiinit0 |= DIS_VGA_PASSTHROUGH;
1216 if (slowpci) {
1217 fbiinit1 |= SLOW_PCI_WRITES;
1218 fbiinit4 |= SLOW_PCI_READS;
1219 } else {
1220 fbiinit1 &= ~SLOW_PCI_WRITES;
1221 fbiinit4 &= ~SLOW_PCI_READS;
1222 }
1223 sst_write(FBIINIT0, fbiinit0);
1224 sst_wait_idle();
1225 sst_write(FBIINIT1, fbiinit1);
1226 sst_wait_idle();
1227 sst_write(FBIINIT2, FBIINIT2_DEFAULT);
1228 sst_wait_idle();
1229 sst_write(FBIINIT3, FBIINIT3_DEFAULT);
1230 sst_wait_idle();
1231 sst_write(FBIINIT4, fbiinit4);
1232 sst_wait_idle();
1233 if (IS_VOODOO2(par)) {
1234 sst_write(FBIINIT6, FBIINIT6_DEFAULT);
1235 sst_wait_idle();
1236 }
1237
1238 pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
1239 pci_write_config_dword(dev, PCI_VCLK_ENABLE, 0);
1240 return 1;
1241 }
1242
1243 static void sst_shutdown(struct fb_info *info)
1244 {
1245 struct sstfb_par *par = info->par;
1246 struct pci_dev *dev = par->dev;
1247 struct pll_timing gfx_timings;
1248 int Fout;
1249
1250
1251 pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
1252 sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING);
1253 sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
1254 sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
1255 sst_wait_idle();
1256 pci_write_config_dword(dev, PCI_INIT_ENABLE,
1257 PCI_EN_INIT_WR | PCI_REMAP_DAC);
1258
1259 sst_calc_pll(20000, &Fout, &gfx_timings);
1260 par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
1261
1262 pci_write_config_dword(dev, PCI_INIT_ENABLE,
1263 PCI_EN_INIT_WR);
1264 sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | DIS_VGA_PASSTHROUGH);
1265 pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
1266
1267
1268 pci_write_config_dword(dev, PCI_INIT_ENABLE, 0);
1269
1270 }
1271
1272
1273
1274
1275 static int sstfb_setup(char *options)
1276 {
1277 char *this_opt;
1278
1279 if (!options || !*options)
1280 return 0;
1281
1282 while ((this_opt = strsep(&options, ",")) != NULL) {
1283 if (!*this_opt) continue;
1284
1285 f_ddprintk("option %s\n", this_opt);
1286
1287 if (!strcmp(this_opt, "vganopass"))
1288 vgapass = 0;
1289 else if (!strcmp(this_opt, "vgapass"))
1290 vgapass = 1;
1291 else if (!strcmp(this_opt, "clipping"))
1292 clipping = 1;
1293 else if (!strcmp(this_opt, "noclipping"))
1294 clipping = 0;
1295 else if (!strcmp(this_opt, "fastpci"))
1296 slowpci = 0;
1297 else if (!strcmp(this_opt, "slowpci"))
1298 slowpci = 1;
1299 else if (!strncmp(this_opt, "mem:",4))
1300 mem = simple_strtoul (this_opt+4, NULL, 0);
1301 else if (!strncmp(this_opt, "gfxclk:",7))
1302 gfxclk = simple_strtoul (this_opt+7, NULL, 0);
1303 else
1304 mode_option = this_opt;
1305 }
1306 return 0;
1307 }
1308
1309
1310 static const struct fb_ops sstfb_ops = {
1311 .owner = THIS_MODULE,
1312 .fb_check_var = sstfb_check_var,
1313 .fb_set_par = sstfb_set_par,
1314 .fb_setcolreg = sstfb_setcolreg,
1315 .fb_fillrect = cfb_fillrect,
1316 .fb_copyarea = cfb_copyarea,
1317 .fb_imageblit = cfb_imageblit,
1318 .fb_ioctl = sstfb_ioctl,
1319 };
1320
1321 static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1322 {
1323 struct fb_info *info;
1324 struct fb_fix_screeninfo *fix;
1325 struct sstfb_par *par;
1326 struct sst_spec *spec;
1327 int err;
1328
1329
1330 if ((err=pci_enable_device(pdev))) {
1331 printk(KERN_ERR "cannot enable device\n");
1332 return err;
1333 }
1334
1335
1336 info = framebuffer_alloc(sizeof(struct sstfb_par), &pdev->dev);
1337 if (!info)
1338 return -ENOMEM;
1339
1340 pci_set_drvdata(pdev, info);
1341
1342 par = info->par;
1343 fix = &info->fix;
1344
1345 par->type = id->driver_data;
1346 spec = &voodoo_spec[par->type];
1347 f_ddprintk("found device : %s\n", spec->name);
1348
1349 par->dev = pdev;
1350 par->revision = pdev->revision;
1351
1352 fix->mmio_start = pci_resource_start(pdev,0);
1353 fix->mmio_len = 0x400000;
1354 fix->smem_start = fix->mmio_start + 0x400000;
1355
1356 if (!request_mem_region(fix->mmio_start, fix->mmio_len, "sstfb MMIO")) {
1357 printk(KERN_ERR "sstfb: cannot reserve mmio memory\n");
1358 goto fail_mmio_mem;
1359 }
1360
1361 if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) {
1362 printk(KERN_ERR "sstfb: cannot reserve fb memory\n");
1363 goto fail_fb_mem;
1364 }
1365
1366 par->mmio_vbase = ioremap(fix->mmio_start,
1367 fix->mmio_len);
1368 if (!par->mmio_vbase) {
1369 printk(KERN_ERR "sstfb: cannot remap register area %#lx\n",
1370 fix->mmio_start);
1371 goto fail_mmio_remap;
1372 }
1373 info->screen_base = ioremap(fix->smem_start, 0x400000);
1374 if (!info->screen_base) {
1375 printk(KERN_ERR "sstfb: cannot remap framebuffer %#lx\n",
1376 fix->smem_start);
1377 goto fail_fb_remap;
1378 }
1379
1380 if (!sst_init(info, par)) {
1381 printk(KERN_ERR "sstfb: Init failed\n");
1382 goto fail;
1383 }
1384 sst_get_memsize(info, &fix->smem_len);
1385 strscpy(fix->id, spec->name, sizeof(fix->id));
1386
1387 printk(KERN_INFO "%s (revision %d) with %s dac\n",
1388 fix->id, par->revision, par->dac_sw.name);
1389 printk(KERN_INFO "framebuffer at %#lx, mapped to 0x%p, size %dMB\n",
1390 fix->smem_start, info->screen_base,
1391 fix->smem_len >> 20);
1392
1393 f_ddprintk("regbase_virt: %p\n", par->mmio_vbase);
1394 f_ddprintk("membase_phys: %#lx\n", fix->smem_start);
1395 f_ddprintk("fbbase_virt: %p\n", info->screen_base);
1396
1397 info->flags = FBINFO_DEFAULT;
1398 info->fbops = &sstfb_ops;
1399 info->pseudo_palette = par->palette;
1400
1401 fix->type = FB_TYPE_PACKED_PIXELS;
1402 fix->visual = FB_VISUAL_TRUECOLOR;
1403 fix->accel = FB_ACCEL_NONE;
1404
1405
1406
1407
1408
1409 fix->line_length = 2048;
1410
1411 fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
1412
1413 if (sstfb_check_var(&info->var, info)) {
1414 printk(KERN_ERR "sstfb: invalid video mode.\n");
1415 goto fail;
1416 }
1417
1418 if (sstfb_set_par(info)) {
1419 printk(KERN_ERR "sstfb: can't set default video mode.\n");
1420 goto fail;
1421 }
1422
1423 if (fb_alloc_cmap(&info->cmap, 256, 0)) {
1424 printk(KERN_ERR "sstfb: can't alloc cmap memory.\n");
1425 goto fail;
1426 }
1427
1428
1429 info->device = &pdev->dev;
1430 if (register_framebuffer(info) < 0) {
1431 printk(KERN_ERR "sstfb: can't register framebuffer.\n");
1432 goto fail_register;
1433 }
1434
1435 sstfb_clear_screen(info);
1436
1437 if (device_create_file(info->dev, &device_attrs[0]))
1438 printk(KERN_WARNING "sstfb: can't create sysfs entry.\n");
1439
1440
1441 fb_info(info, "%s frame buffer device at 0x%p\n",
1442 fix->id, info->screen_base);
1443
1444 return 0;
1445
1446 fail_register:
1447 fb_dealloc_cmap(&info->cmap);
1448 fail:
1449 iounmap(info->screen_base);
1450 fail_fb_remap:
1451 iounmap(par->mmio_vbase);
1452 fail_mmio_remap:
1453 release_mem_region(fix->smem_start, 0x400000);
1454 fail_fb_mem:
1455 release_mem_region(fix->mmio_start, info->fix.mmio_len);
1456 fail_mmio_mem:
1457 framebuffer_release(info);
1458 return -ENXIO;
1459 }
1460
1461 static void sstfb_remove(struct pci_dev *pdev)
1462 {
1463 struct sstfb_par *par;
1464 struct fb_info *info;
1465
1466 info = pci_get_drvdata(pdev);
1467 par = info->par;
1468
1469 device_remove_file(info->dev, &device_attrs[0]);
1470 sst_shutdown(info);
1471 iounmap(info->screen_base);
1472 iounmap(par->mmio_vbase);
1473 release_mem_region(info->fix.smem_start, 0x400000);
1474 release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
1475 fb_dealloc_cmap(&info->cmap);
1476 unregister_framebuffer(info);
1477 framebuffer_release(info);
1478 }
1479
1480
1481 static const struct pci_device_id sstfb_id_tbl[] = {
1482 { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO ),
1483 .driver_data = ID_VOODOO1, },
1484 { PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2),
1485 .driver_data = ID_VOODOO2, },
1486 { 0 },
1487 };
1488
1489 static struct pci_driver sstfb_driver = {
1490 .name = "sstfb",
1491 .id_table = sstfb_id_tbl,
1492 .probe = sstfb_probe,
1493 .remove = sstfb_remove,
1494 };
1495
1496
1497 static int sstfb_init(void)
1498 {
1499 char *option = NULL;
1500
1501 if (fb_get_options("sstfb", &option))
1502 return -ENODEV;
1503 sstfb_setup(option);
1504
1505 return pci_register_driver(&sstfb_driver);
1506 }
1507
1508 static void sstfb_exit(void)
1509 {
1510 pci_unregister_driver(&sstfb_driver);
1511 }
1512
1513
1514 module_init(sstfb_init);
1515 module_exit(sstfb_exit);
1516
1517 MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");
1518 MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");
1519 MODULE_LICENSE("GPL");
1520
1521 module_param(mem, int, 0);
1522 MODULE_PARM_DESC(mem, "Size of frame buffer memory in MB (1, 2, 4 MB, default=autodetect)");
1523 module_param(vgapass, bool, 0);
1524 MODULE_PARM_DESC(vgapass, "Enable VGA PassThrough mode (0 or 1) (default=0)");
1525 module_param(clipping, bool, 0);
1526 MODULE_PARM_DESC(clipping, "Enable clipping (slower, safer) (0 or 1) (default=1)");
1527 module_param(gfxclk, int, 0);
1528 MODULE_PARM_DESC(gfxclk, "Force graphic chip frequency in MHz. DANGEROUS. (default=auto)");
1529 module_param(slowpci, bool, 0);
1530 MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
1531 module_param(mode_option, charp, 0);
1532 MODULE_PARM_DESC(mode_option, "Initial video mode (default=" DEFAULT_VIDEO_MODE ")");
1533