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 #include <linux/module.h>
0058 #include <linux/kernel.h>
0059 #include <linux/errno.h>
0060 #include <linux/string.h>
0061 #include <linux/mm.h>
0062 #include <linux/slab.h>
0063 #include <linux/delay.h>
0064 #include <linux/fb.h>
0065 #include <linux/pci.h>
0066 #include <linux/init.h>
0067 #ifdef CONFIG_TOSHIBA
0068 #include <linux/toshiba.h>
0069 #endif
0070
0071 #include <asm/io.h>
0072 #include <asm/irq.h>
0073 #include <video/vga.h>
0074 #include <video/neomagic.h>
0075
0076 #define NEOFB_VERSION "0.4.2"
0077
0078
0079
0080 static bool internal;
0081 static bool external;
0082 static bool libretto;
0083 static bool nostretch;
0084 static bool nopciburst;
0085 static char *mode_option = NULL;
0086
0087 #ifdef MODULE
0088
0089 MODULE_AUTHOR("(c) 2001-2002 Denis Oliver Kropp <dok@convergence.de>");
0090 MODULE_LICENSE("GPL");
0091 MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");
0092 module_param(internal, bool, 0);
0093 MODULE_PARM_DESC(internal, "Enable output on internal LCD Display.");
0094 module_param(external, bool, 0);
0095 MODULE_PARM_DESC(external, "Enable output on external CRT.");
0096 module_param(libretto, bool, 0);
0097 MODULE_PARM_DESC(libretto, "Force Libretto 100/110 800x480 LCD.");
0098 module_param(nostretch, bool, 0);
0099 MODULE_PARM_DESC(nostretch,
0100 "Disable stretching of modes smaller than LCD.");
0101 module_param(nopciburst, bool, 0);
0102 MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
0103 module_param(mode_option, charp, 0);
0104 MODULE_PARM_DESC(mode_option, "Preferred video mode ('640x480-8@60', etc)");
0105
0106 #endif
0107
0108
0109
0110
0111 static biosMode bios8[] = {
0112 {320, 240, 0x40},
0113 {300, 400, 0x42},
0114 {640, 400, 0x20},
0115 {640, 480, 0x21},
0116 {800, 600, 0x23},
0117 {1024, 768, 0x25},
0118 };
0119
0120 static biosMode bios16[] = {
0121 {320, 200, 0x2e},
0122 {320, 240, 0x41},
0123 {300, 400, 0x43},
0124 {640, 480, 0x31},
0125 {800, 600, 0x34},
0126 {1024, 768, 0x37},
0127 };
0128
0129 static biosMode bios24[] = {
0130 {640, 480, 0x32},
0131 {800, 600, 0x35},
0132 {1024, 768, 0x38}
0133 };
0134
0135 #ifdef NO_32BIT_SUPPORT_YET
0136
0137 static biosMode bios32[] = {
0138 {640, 480, 0x33},
0139 {800, 600, 0x36},
0140 {1024, 768, 0x39}
0141 };
0142 #endif
0143
0144 static inline void write_le32(int regindex, u32 val, const struct neofb_par *par)
0145 {
0146 writel(val, par->neo2200 + par->cursorOff + regindex);
0147 }
0148
0149 static int neoFindMode(int xres, int yres, int depth)
0150 {
0151 int xres_s;
0152 int i, size;
0153 biosMode *mode;
0154
0155 switch (depth) {
0156 case 8:
0157 size = ARRAY_SIZE(bios8);
0158 mode = bios8;
0159 break;
0160 case 16:
0161 size = ARRAY_SIZE(bios16);
0162 mode = bios16;
0163 break;
0164 case 24:
0165 size = ARRAY_SIZE(bios24);
0166 mode = bios24;
0167 break;
0168 #ifdef NO_32BIT_SUPPORT_YET
0169 case 32:
0170 size = ARRAY_SIZE(bios32);
0171 mode = bios32;
0172 break;
0173 #endif
0174 default:
0175 return 0;
0176 }
0177
0178 for (i = 0; i < size; i++) {
0179 if (xres <= mode[i].x_res) {
0180 xres_s = mode[i].x_res;
0181 for (; i < size; i++) {
0182 if (mode[i].x_res != xres_s)
0183 return mode[i - 1].mode;
0184 if (yres <= mode[i].y_res)
0185 return mode[i].mode;
0186 }
0187 }
0188 }
0189 return mode[size - 1].mode;
0190 }
0191
0192
0193
0194
0195
0196
0197 #define MAX_N 127
0198 #define MAX_D 31
0199 #define MAX_F 1
0200
0201 static void neoCalcVCLK(const struct fb_info *info,
0202 struct neofb_par *par, long freq)
0203 {
0204 int n, d, f;
0205 int n_best = 0, d_best = 0, f_best = 0;
0206 long f_best_diff = 0x7ffff;
0207
0208 for (f = 0; f <= MAX_F; f++)
0209 for (d = 0; d <= MAX_D; d++)
0210 for (n = 0; n <= MAX_N; n++) {
0211 long f_out;
0212 long f_diff;
0213
0214 f_out = ((14318 * (n + 1)) / (d + 1)) >> f;
0215 f_diff = abs(f_out - freq);
0216 if (f_diff <= f_best_diff) {
0217 f_best_diff = f_diff;
0218 n_best = n;
0219 d_best = d;
0220 f_best = f;
0221 }
0222 if (f_out > freq)
0223 break;
0224 }
0225
0226 if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
0227 info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
0228 info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
0229 info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
0230
0231
0232 par->VCLK3NumeratorLow = n_best;
0233 par->VCLK3NumeratorHigh = (f_best << 7);
0234 } else
0235 par->VCLK3NumeratorLow = n_best | (f_best << 7);
0236
0237 par->VCLK3Denominator = d_best;
0238
0239 #ifdef NEOFB_DEBUG
0240 printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n",
0241 freq,
0242 par->VCLK3NumeratorLow,
0243 par->VCLK3NumeratorHigh,
0244 par->VCLK3Denominator, f_best_diff);
0245 #endif
0246 }
0247
0248
0249
0250
0251
0252
0253
0254 static int vgaHWInit(const struct fb_var_screeninfo *var,
0255 struct neofb_par *par)
0256 {
0257 int hsync_end = var->xres + var->right_margin + var->hsync_len;
0258 int htotal = (hsync_end + var->left_margin) >> 3;
0259 int vsync_start = var->yres + var->lower_margin;
0260 int vsync_end = vsync_start + var->vsync_len;
0261 int vtotal = vsync_end + var->upper_margin;
0262
0263 par->MiscOutReg = 0x23;
0264
0265 if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
0266 par->MiscOutReg |= 0x40;
0267
0268 if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
0269 par->MiscOutReg |= 0x80;
0270
0271
0272
0273
0274 par->Sequencer[0] = 0x00;
0275 par->Sequencer[1] = 0x01;
0276 par->Sequencer[2] = 0x0F;
0277 par->Sequencer[3] = 0x00;
0278 par->Sequencer[4] = 0x0E;
0279
0280
0281
0282
0283 par->CRTC[0] = htotal - 5;
0284 par->CRTC[1] = (var->xres >> 3) - 1;
0285 par->CRTC[2] = (var->xres >> 3) - 1;
0286 par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
0287 par->CRTC[4] = ((var->xres + var->right_margin) >> 3);
0288 par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
0289 | (((hsync_end >> 3)) & 0x1F);
0290 par->CRTC[6] = (vtotal - 2) & 0xFF;
0291 par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
0292 | (((var->yres - 1) & 0x100) >> 7)
0293 | ((vsync_start & 0x100) >> 6)
0294 | (((var->yres - 1) & 0x100) >> 5)
0295 | 0x10 | (((vtotal - 2) & 0x200) >> 4)
0296 | (((var->yres - 1) & 0x200) >> 3)
0297 | ((vsync_start & 0x200) >> 2);
0298 par->CRTC[8] = 0x00;
0299 par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40;
0300
0301 if (var->vmode & FB_VMODE_DOUBLE)
0302 par->CRTC[9] |= 0x80;
0303
0304 par->CRTC[10] = 0x00;
0305 par->CRTC[11] = 0x00;
0306 par->CRTC[12] = 0x00;
0307 par->CRTC[13] = 0x00;
0308 par->CRTC[14] = 0x00;
0309 par->CRTC[15] = 0x00;
0310 par->CRTC[16] = vsync_start & 0xFF;
0311 par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
0312 par->CRTC[18] = (var->yres - 1) & 0xFF;
0313 par->CRTC[19] = var->xres_virtual >> 4;
0314 par->CRTC[20] = 0x00;
0315 par->CRTC[21] = (var->yres - 1) & 0xFF;
0316 par->CRTC[22] = (vtotal - 1) & 0xFF;
0317 par->CRTC[23] = 0xC3;
0318 par->CRTC[24] = 0xFF;
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329 par->Graphics[0] = 0x00;
0330 par->Graphics[1] = 0x00;
0331 par->Graphics[2] = 0x00;
0332 par->Graphics[3] = 0x00;
0333 par->Graphics[4] = 0x00;
0334 par->Graphics[5] = 0x40;
0335 par->Graphics[6] = 0x05;
0336 par->Graphics[7] = 0x0F;
0337 par->Graphics[8] = 0xFF;
0338
0339
0340 par->Attribute[0] = 0x00;
0341 par->Attribute[1] = 0x01;
0342 par->Attribute[2] = 0x02;
0343 par->Attribute[3] = 0x03;
0344 par->Attribute[4] = 0x04;
0345 par->Attribute[5] = 0x05;
0346 par->Attribute[6] = 0x06;
0347 par->Attribute[7] = 0x07;
0348 par->Attribute[8] = 0x08;
0349 par->Attribute[9] = 0x09;
0350 par->Attribute[10] = 0x0A;
0351 par->Attribute[11] = 0x0B;
0352 par->Attribute[12] = 0x0C;
0353 par->Attribute[13] = 0x0D;
0354 par->Attribute[14] = 0x0E;
0355 par->Attribute[15] = 0x0F;
0356 par->Attribute[16] = 0x41;
0357 par->Attribute[17] = 0xFF;
0358 par->Attribute[18] = 0x0F;
0359 par->Attribute[19] = 0x00;
0360 par->Attribute[20] = 0x00;
0361 return 0;
0362 }
0363
0364 static void vgaHWLock(struct vgastate *state)
0365 {
0366
0367 vga_wcrt(state->vgabase, 0x11, vga_rcrt(state->vgabase, 0x11) | 0x80);
0368 }
0369
0370 static void vgaHWUnlock(void)
0371 {
0372
0373 vga_wcrt(NULL, 0x11, vga_rcrt(NULL, 0x11) & ~0x80);
0374 }
0375
0376 static void neoLock(struct vgastate *state)
0377 {
0378 vga_wgfx(state->vgabase, 0x09, 0x00);
0379 vgaHWLock(state);
0380 }
0381
0382 static void neoUnlock(void)
0383 {
0384 vgaHWUnlock();
0385 vga_wgfx(NULL, 0x09, 0x26);
0386 }
0387
0388
0389
0390
0391 static int paletteEnabled = 0;
0392
0393 static inline void VGAenablePalette(void)
0394 {
0395 vga_r(NULL, VGA_IS1_RC);
0396 vga_w(NULL, VGA_ATT_W, 0x00);
0397 paletteEnabled = 1;
0398 }
0399
0400 static inline void VGAdisablePalette(void)
0401 {
0402 vga_r(NULL, VGA_IS1_RC);
0403 vga_w(NULL, VGA_ATT_W, 0x20);
0404 paletteEnabled = 0;
0405 }
0406
0407 static inline void VGAwATTR(u8 index, u8 value)
0408 {
0409 if (paletteEnabled)
0410 index &= ~0x20;
0411 else
0412 index |= 0x20;
0413
0414 vga_r(NULL, VGA_IS1_RC);
0415 vga_wattr(NULL, index, value);
0416 }
0417
0418 static void vgaHWProtect(int on)
0419 {
0420 unsigned char tmp;
0421
0422 tmp = vga_rseq(NULL, 0x01);
0423 if (on) {
0424
0425
0426
0427 vga_wseq(NULL, 0x00, 0x01);
0428 vga_wseq(NULL, 0x01, tmp | 0x20);
0429
0430 VGAenablePalette();
0431 } else {
0432
0433
0434
0435 vga_wseq(NULL, 0x01, tmp & ~0x20);
0436 vga_wseq(NULL, 0x00, 0x03);
0437
0438 VGAdisablePalette();
0439 }
0440 }
0441
0442 static void vgaHWRestore(const struct fb_info *info,
0443 const struct neofb_par *par)
0444 {
0445 int i;
0446
0447 vga_w(NULL, VGA_MIS_W, par->MiscOutReg);
0448
0449 for (i = 1; i < 5; i++)
0450 vga_wseq(NULL, i, par->Sequencer[i]);
0451
0452
0453 vga_wcrt(NULL, 17, par->CRTC[17] & ~0x80);
0454
0455 for (i = 0; i < 25; i++)
0456 vga_wcrt(NULL, i, par->CRTC[i]);
0457
0458 for (i = 0; i < 9; i++)
0459 vga_wgfx(NULL, i, par->Graphics[i]);
0460
0461 VGAenablePalette();
0462
0463 for (i = 0; i < 21; i++)
0464 VGAwATTR(i, par->Attribute[i]);
0465
0466 VGAdisablePalette();
0467 }
0468
0469
0470
0471
0472
0473
0474
0475 static inline int neo2200_sync(struct fb_info *info)
0476 {
0477 struct neofb_par *par = info->par;
0478
0479 while (readl(&par->neo2200->bltStat) & 1)
0480 cpu_relax();
0481 return 0;
0482 }
0483
0484 static inline void neo2200_wait_fifo(struct fb_info *info,
0485 int requested_fifo_space)
0486 {
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510 neo2200_sync(info);
0511 }
0512
0513 static inline void neo2200_accel_init(struct fb_info *info,
0514 struct fb_var_screeninfo *var)
0515 {
0516 struct neofb_par *par = info->par;
0517 Neo2200 __iomem *neo2200 = par->neo2200;
0518 u32 bltMod, pitch;
0519
0520 neo2200_sync(info);
0521
0522 switch (var->bits_per_pixel) {
0523 case 8:
0524 bltMod = NEO_MODE1_DEPTH8;
0525 pitch = var->xres_virtual;
0526 break;
0527 case 15:
0528 case 16:
0529 bltMod = NEO_MODE1_DEPTH16;
0530 pitch = var->xres_virtual * 2;
0531 break;
0532 case 24:
0533 bltMod = NEO_MODE1_DEPTH24;
0534 pitch = var->xres_virtual * 3;
0535 break;
0536 default:
0537 printk(KERN_ERR
0538 "neofb: neo2200_accel_init: unexpected bits per pixel!\n");
0539 return;
0540 }
0541
0542 writel(bltMod << 16, &neo2200->bltStat);
0543 writel((pitch << 16) | pitch, &neo2200->pitch);
0544 }
0545
0546
0547
0548 static int
0549 neofb_open(struct fb_info *info, int user)
0550 {
0551 struct neofb_par *par = info->par;
0552
0553 if (!par->ref_count) {
0554 memset(&par->state, 0, sizeof(struct vgastate));
0555 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
0556 save_vga(&par->state);
0557 }
0558 par->ref_count++;
0559
0560 return 0;
0561 }
0562
0563 static int
0564 neofb_release(struct fb_info *info, int user)
0565 {
0566 struct neofb_par *par = info->par;
0567
0568 if (!par->ref_count)
0569 return -EINVAL;
0570
0571 if (par->ref_count == 1) {
0572 restore_vga(&par->state);
0573 }
0574 par->ref_count--;
0575
0576 return 0;
0577 }
0578
0579 static int
0580 neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
0581 {
0582 struct neofb_par *par = info->par;
0583 int memlen, vramlen;
0584 int mode_ok = 0;
0585
0586 DBG("neofb_check_var");
0587
0588 if (!var->pixclock || PICOS2KHZ(var->pixclock) > par->maxClock)
0589 return -EINVAL;
0590
0591
0592 if (par->internal_display &&
0593 ((var->xres > par->NeoPanelWidth) ||
0594 (var->yres > par->NeoPanelHeight))) {
0595 printk(KERN_INFO
0596 "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",
0597 var->xres, var->yres, par->NeoPanelWidth,
0598 par->NeoPanelHeight);
0599 return -EINVAL;
0600 }
0601
0602
0603 if (!par->internal_display)
0604 mode_ok = 1;
0605 else {
0606 switch (var->xres) {
0607 case 1280:
0608 if (var->yres == 1024)
0609 mode_ok = 1;
0610 break;
0611 case 1024:
0612 if (var->yres == 768)
0613 mode_ok = 1;
0614 break;
0615 case 800:
0616 if (var->yres == (par->libretto ? 480 : 600))
0617 mode_ok = 1;
0618 break;
0619 case 640:
0620 if (var->yres == 480)
0621 mode_ok = 1;
0622 break;
0623 }
0624 }
0625
0626 if (!mode_ok) {
0627 printk(KERN_INFO
0628 "Mode (%dx%d) won't display properly on LCD\n",
0629 var->xres, var->yres);
0630 return -EINVAL;
0631 }
0632
0633 var->red.msb_right = 0;
0634 var->green.msb_right = 0;
0635 var->blue.msb_right = 0;
0636 var->transp.msb_right = 0;
0637
0638 var->transp.offset = 0;
0639 var->transp.length = 0;
0640 switch (var->bits_per_pixel) {
0641 case 8:
0642 var->red.offset = 0;
0643 var->red.length = 8;
0644 var->green.offset = 0;
0645 var->green.length = 8;
0646 var->blue.offset = 0;
0647 var->blue.length = 8;
0648 break;
0649
0650 case 16:
0651 var->red.offset = 11;
0652 var->red.length = 5;
0653 var->green.offset = 5;
0654 var->green.length = 6;
0655 var->blue.offset = 0;
0656 var->blue.length = 5;
0657 break;
0658
0659 case 24:
0660 var->red.offset = 16;
0661 var->red.length = 8;
0662 var->green.offset = 8;
0663 var->green.length = 8;
0664 var->blue.offset = 0;
0665 var->blue.length = 8;
0666 break;
0667
0668 #ifdef NO_32BIT_SUPPORT_YET
0669 case 32:
0670 var->transp.offset = 24;
0671 var->transp.length = 8;
0672 var->red.offset = 16;
0673 var->red.length = 8;
0674 var->green.offset = 8;
0675 var->green.length = 8;
0676 var->blue.offset = 0;
0677 var->blue.length = 8;
0678 break;
0679 #endif
0680 default:
0681 printk(KERN_WARNING "neofb: no support for %dbpp\n",
0682 var->bits_per_pixel);
0683 return -EINVAL;
0684 }
0685
0686 vramlen = info->fix.smem_len;
0687 if (vramlen > 4 * 1024 * 1024)
0688 vramlen = 4 * 1024 * 1024;
0689
0690 if (var->xres_virtual < var->xres)
0691 var->xres_virtual = var->xres;
0692
0693 memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual >> 3;
0694
0695 if (memlen > vramlen) {
0696 var->yres_virtual = vramlen * 8 / (var->xres_virtual *
0697 var->bits_per_pixel);
0698 memlen = var->xres_virtual * var->bits_per_pixel *
0699 var->yres_virtual / 8;
0700 }
0701
0702
0703
0704 if (var->yres_virtual < var->yres)
0705 var->yres = var->yres_virtual;
0706 if (var->xoffset + var->xres > var->xres_virtual)
0707 var->xoffset = var->xres_virtual - var->xres;
0708 if (var->yoffset + var->yres > var->yres_virtual)
0709 var->yoffset = var->yres_virtual - var->yres;
0710
0711 var->nonstd = 0;
0712 var->height = -1;
0713 var->width = -1;
0714
0715 if (var->bits_per_pixel >= 24 || !par->neo2200)
0716 var->accel_flags &= ~FB_ACCELF_TEXT;
0717 return 0;
0718 }
0719
0720 static int neofb_set_par(struct fb_info *info)
0721 {
0722 struct neofb_par *par = info->par;
0723 unsigned char temp;
0724 int i, clock_hi = 0;
0725 int lcd_stretch;
0726 int hoffset, voffset;
0727 int vsync_start, vtotal;
0728
0729 DBG("neofb_set_par");
0730
0731 neoUnlock();
0732
0733 vgaHWProtect(1);
0734
0735 vsync_start = info->var.yres + info->var.lower_margin;
0736 vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;
0737
0738
0739
0740
0741
0742
0743 if (vgaHWInit(&info->var, par))
0744 return -EINVAL;
0745
0746
0747
0748
0749
0750 par->Attribute[16] = 0x01;
0751
0752 switch (info->var.bits_per_pixel) {
0753 case 8:
0754 par->CRTC[0x13] = info->var.xres_virtual >> 3;
0755 par->ExtCRTOffset = info->var.xres_virtual >> 11;
0756 par->ExtColorModeSelect = 0x11;
0757 break;
0758 case 16:
0759 par->CRTC[0x13] = info->var.xres_virtual >> 2;
0760 par->ExtCRTOffset = info->var.xres_virtual >> 10;
0761 par->ExtColorModeSelect = 0x13;
0762 break;
0763 case 24:
0764 par->CRTC[0x13] = (info->var.xres_virtual * 3) >> 3;
0765 par->ExtCRTOffset = (info->var.xres_virtual * 3) >> 11;
0766 par->ExtColorModeSelect = 0x14;
0767 break;
0768 #ifdef NO_32BIT_SUPPORT_YET
0769 case 32:
0770 par->CRTC[0x13] = info->var.xres_virtual >> 1;
0771 par->ExtCRTOffset = info->var.xres_virtual >> 9;
0772 par->ExtColorModeSelect = 0x15;
0773 break;
0774 #endif
0775 default:
0776 break;
0777 }
0778
0779 par->ExtCRTDispAddr = 0x10;
0780
0781
0782 par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
0783 | (((info->var.yres - 1) & 0x400) >> 9)
0784 | (((vsync_start) & 0x400) >> 8)
0785 | (((vsync_start) & 0x400) >> 7);
0786
0787
0788 if (par->pci_burst)
0789 par->SysIfaceCntl1 = 0x30;
0790 else
0791 par->SysIfaceCntl1 = 0x00;
0792
0793 par->SysIfaceCntl2 = 0xc0;
0794
0795
0796 par->PanelDispCntlRegRead = 1;
0797
0798
0799 par->PanelDispCntlReg1 = 0x00;
0800 if (par->internal_display)
0801 par->PanelDispCntlReg1 |= 0x02;
0802 if (par->external_display)
0803 par->PanelDispCntlReg1 |= 0x01;
0804
0805
0806 if (par->PanelDispCntlReg1 == 0x00) {
0807
0808 par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
0809 }
0810
0811
0812 switch (info->var.xres) {
0813 case 1280:
0814 par->PanelDispCntlReg1 |= 0x60;
0815 break;
0816 case 1024:
0817 par->PanelDispCntlReg1 |= 0x40;
0818 break;
0819 case 800:
0820 par->PanelDispCntlReg1 |= 0x20;
0821 break;
0822 case 640:
0823 default:
0824 break;
0825 }
0826
0827
0828 switch (par->PanelDispCntlReg1 & 0x03) {
0829 case 0x01:
0830 par->GeneralLockReg = 0x00;
0831
0832 par->ProgramVCLK = 1;
0833 break;
0834 case 0x02:
0835 case 0x03:
0836 par->GeneralLockReg = 0x01;
0837
0838 par->ProgramVCLK = 0;
0839 break;
0840 }
0841
0842
0843
0844
0845
0846
0847
0848 par->PanelDispCntlReg2 = 0x00;
0849 par->PanelDispCntlReg3 = 0x00;
0850
0851 if (par->lcd_stretch && (par->PanelDispCntlReg1 == 0x02) &&
0852 (info->var.xres != par->NeoPanelWidth)) {
0853 switch (info->var.xres) {
0854 case 320:
0855 case 400:
0856 case 640:
0857 case 800:
0858 case 1024:
0859 lcd_stretch = 1;
0860 par->PanelDispCntlReg2 |= 0xC6;
0861 break;
0862 default:
0863 lcd_stretch = 0;
0864
0865 }
0866 } else
0867 lcd_stretch = 0;
0868
0869
0870
0871
0872
0873 par->PanelVertCenterReg1 = 0x00;
0874 par->PanelVertCenterReg2 = 0x00;
0875 par->PanelVertCenterReg3 = 0x00;
0876 par->PanelVertCenterReg4 = 0x00;
0877 par->PanelVertCenterReg5 = 0x00;
0878 par->PanelHorizCenterReg1 = 0x00;
0879 par->PanelHorizCenterReg2 = 0x00;
0880 par->PanelHorizCenterReg3 = 0x00;
0881 par->PanelHorizCenterReg4 = 0x00;
0882 par->PanelHorizCenterReg5 = 0x00;
0883
0884
0885 if (par->PanelDispCntlReg1 & 0x02) {
0886 if (info->var.xres == par->NeoPanelWidth) {
0887
0888
0889
0890
0891 } else {
0892 par->PanelDispCntlReg2 |= 0x01;
0893 par->PanelDispCntlReg3 |= 0x10;
0894
0895
0896 if (!lcd_stretch) {
0897 hoffset =
0898 ((par->NeoPanelWidth -
0899 info->var.xres) >> 4) - 1;
0900 voffset =
0901 ((par->NeoPanelHeight -
0902 info->var.yres) >> 1) - 2;
0903 } else {
0904
0905 hoffset = 0;
0906 voffset = 0;
0907 }
0908
0909 switch (info->var.xres) {
0910 case 320:
0911 par->PanelHorizCenterReg3 = hoffset;
0912 par->PanelVertCenterReg2 = voffset;
0913 break;
0914 case 400:
0915 par->PanelHorizCenterReg4 = hoffset;
0916 par->PanelVertCenterReg1 = voffset;
0917 break;
0918 case 640:
0919 par->PanelHorizCenterReg1 = hoffset;
0920 par->PanelVertCenterReg3 = voffset;
0921 break;
0922 case 800:
0923 par->PanelHorizCenterReg2 = hoffset;
0924 par->PanelVertCenterReg4 = voffset;
0925 break;
0926 case 1024:
0927 par->PanelHorizCenterReg5 = hoffset;
0928 par->PanelVertCenterReg5 = voffset;
0929 break;
0930 case 1280:
0931 default:
0932
0933 break;
0934 }
0935 }
0936 }
0937
0938 par->biosMode =
0939 neoFindMode(info->var.xres, info->var.yres,
0940 info->var.bits_per_pixel);
0941
0942
0943
0944
0945
0946 neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));
0947
0948
0949 par->MiscOutReg |= 0x0C;
0950
0951
0952
0953
0954
0955 vga_wgfx(NULL, 0x15, 0x00);
0956
0957
0958 vga_wgfx(NULL, 0x0A, par->GeneralLockReg);
0959
0960
0961
0962
0963
0964
0965
0966
0967 temp = vga_rgfx(NULL, 0x90);
0968 switch (info->fix.accel) {
0969 case FB_ACCEL_NEOMAGIC_NM2070:
0970 temp &= 0xF0;
0971 temp |= (par->ExtColorModeSelect & ~0xF0);
0972 break;
0973 case FB_ACCEL_NEOMAGIC_NM2090:
0974 case FB_ACCEL_NEOMAGIC_NM2093:
0975 case FB_ACCEL_NEOMAGIC_NM2097:
0976 case FB_ACCEL_NEOMAGIC_NM2160:
0977 case FB_ACCEL_NEOMAGIC_NM2200:
0978 case FB_ACCEL_NEOMAGIC_NM2230:
0979 case FB_ACCEL_NEOMAGIC_NM2360:
0980 case FB_ACCEL_NEOMAGIC_NM2380:
0981 temp &= 0x70;
0982 temp |= (par->ExtColorModeSelect & ~0x70);
0983 break;
0984 }
0985
0986 vga_wgfx(NULL, 0x90, temp);
0987
0988
0989
0990
0991
0992
0993
0994
0995
0996
0997
0998 temp = vga_rgfx(NULL, 0x25);
0999 temp &= 0x39;
1000 vga_wgfx(NULL, 0x25, temp);
1001
1002
1003
1004
1005
1006 mdelay(200);
1007
1008
1009
1010 vgaHWRestore(info, par);
1011
1012
1013 switch (info->var.bits_per_pixel) {
1014 case 8:
1015
1016 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
1017 break;
1018 case 16:
1019
1020 info->fix.visual = FB_VISUAL_TRUECOLOR;
1021
1022 for (i = 0; i < 64; i++) {
1023 outb(i, 0x3c8);
1024
1025 outb(i << 1, 0x3c9);
1026 outb(i, 0x3c9);
1027 outb(i << 1, 0x3c9);
1028 }
1029 break;
1030 case 24:
1031 #ifdef NO_32BIT_SUPPORT_YET
1032 case 32:
1033 #endif
1034
1035 info->fix.visual = FB_VISUAL_TRUECOLOR;
1036
1037 for (i = 0; i < 256; i++) {
1038 outb(i, 0x3c8);
1039
1040 outb(i, 0x3c9);
1041 outb(i, 0x3c9);
1042 outb(i, 0x3c9);
1043 }
1044 break;
1045 }
1046
1047 vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr);
1048 vga_wgfx(NULL, 0x0F, par->ExtCRTOffset);
1049 temp = vga_rgfx(NULL, 0x10);
1050 temp &= 0x0F;
1051 temp |= (par->SysIfaceCntl1 & ~0x0F);
1052 vga_wgfx(NULL, 0x10, temp);
1053
1054 vga_wgfx(NULL, 0x11, par->SysIfaceCntl2);
1055 vga_wgfx(NULL, 0x15, 0 );
1056 vga_wgfx(NULL, 0x16, 0 );
1057
1058 temp = vga_rgfx(NULL, 0x20);
1059 switch (info->fix.accel) {
1060 case FB_ACCEL_NEOMAGIC_NM2070:
1061 temp &= 0xFC;
1062 temp |= (par->PanelDispCntlReg1 & ~0xFC);
1063 break;
1064 case FB_ACCEL_NEOMAGIC_NM2090:
1065 case FB_ACCEL_NEOMAGIC_NM2093:
1066 case FB_ACCEL_NEOMAGIC_NM2097:
1067 case FB_ACCEL_NEOMAGIC_NM2160:
1068 temp &= 0xDC;
1069 temp |= (par->PanelDispCntlReg1 & ~0xDC);
1070 break;
1071 case FB_ACCEL_NEOMAGIC_NM2200:
1072 case FB_ACCEL_NEOMAGIC_NM2230:
1073 case FB_ACCEL_NEOMAGIC_NM2360:
1074 case FB_ACCEL_NEOMAGIC_NM2380:
1075 temp &= 0x98;
1076 temp |= (par->PanelDispCntlReg1 & ~0x98);
1077 break;
1078 }
1079 vga_wgfx(NULL, 0x20, temp);
1080
1081 temp = vga_rgfx(NULL, 0x25);
1082 temp &= 0x38;
1083 temp |= (par->PanelDispCntlReg2 & ~0x38);
1084 vga_wgfx(NULL, 0x25, temp);
1085
1086 if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
1087 temp = vga_rgfx(NULL, 0x30);
1088 temp &= 0xEF;
1089 temp |= (par->PanelDispCntlReg3 & ~0xEF);
1090 vga_wgfx(NULL, 0x30, temp);
1091 }
1092
1093 vga_wgfx(NULL, 0x28, par->PanelVertCenterReg1);
1094 vga_wgfx(NULL, 0x29, par->PanelVertCenterReg2);
1095 vga_wgfx(NULL, 0x2a, par->PanelVertCenterReg3);
1096
1097 if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
1098 vga_wgfx(NULL, 0x32, par->PanelVertCenterReg4);
1099 vga_wgfx(NULL, 0x33, par->PanelHorizCenterReg1);
1100 vga_wgfx(NULL, 0x34, par->PanelHorizCenterReg2);
1101 vga_wgfx(NULL, 0x35, par->PanelHorizCenterReg3);
1102 }
1103
1104 if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2160)
1105 vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
1106
1107 if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
1108 info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
1109 info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
1110 info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
1111 vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
1112 vga_wgfx(NULL, 0x37, par->PanelVertCenterReg5);
1113 vga_wgfx(NULL, 0x38, par->PanelHorizCenterReg5);
1114
1115 clock_hi = 1;
1116 }
1117
1118
1119 if (par->ProgramVCLK && ((vga_rgfx(NULL, 0x9B) != par->VCLK3NumeratorLow)
1120 || (vga_rgfx(NULL, 0x9F) != par->VCLK3Denominator)
1121 || (clock_hi && ((vga_rgfx(NULL, 0x8F) & ~0x0f)
1122 != (par->VCLK3NumeratorHigh &
1123 ~0x0F))))) {
1124 vga_wgfx(NULL, 0x9B, par->VCLK3NumeratorLow);
1125 if (clock_hi) {
1126 temp = vga_rgfx(NULL, 0x8F);
1127 temp &= 0x0F;
1128 temp |= (par->VCLK3NumeratorHigh & ~0x0F);
1129 vga_wgfx(NULL, 0x8F, temp);
1130 }
1131 vga_wgfx(NULL, 0x9F, par->VCLK3Denominator);
1132 }
1133
1134 if (par->biosMode)
1135 vga_wcrt(NULL, 0x23, par->biosMode);
1136
1137 vga_wgfx(NULL, 0x93, 0xc0);
1138
1139
1140 if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
1141 info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
1142 info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
1143 info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
1144 vga_wcrt(NULL, 0x70, par->VerticalExt);
1145 }
1146
1147 vgaHWProtect(0);
1148
1149
1150 neoLock(&par->state);
1151
1152 info->fix.line_length =
1153 info->var.xres_virtual * (info->var.bits_per_pixel >> 3);
1154
1155 switch (info->fix.accel) {
1156 case FB_ACCEL_NEOMAGIC_NM2200:
1157 case FB_ACCEL_NEOMAGIC_NM2230:
1158 case FB_ACCEL_NEOMAGIC_NM2360:
1159 case FB_ACCEL_NEOMAGIC_NM2380:
1160 neo2200_accel_init(info, &info->var);
1161 break;
1162 default:
1163 break;
1164 }
1165 return 0;
1166 }
1167
1168
1169
1170
1171 static int neofb_pan_display(struct fb_var_screeninfo *var,
1172 struct fb_info *info)
1173 {
1174 struct neofb_par *par = info->par;
1175 struct vgastate *state = &par->state;
1176 int oldExtCRTDispAddr;
1177 int Base;
1178
1179 DBG("neofb_update_start");
1180
1181 Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2;
1182 Base *= (info->var.bits_per_pixel + 7) / 8;
1183
1184 neoUnlock();
1185
1186
1187
1188
1189 vga_wcrt(state->vgabase, 0x0C, (Base & 0x00FF00) >> 8);
1190 vga_wcrt(state->vgabase, 0x0D, (Base & 0x00FF));
1191
1192
1193
1194
1195
1196
1197 oldExtCRTDispAddr = vga_rgfx(NULL, 0x0E);
1198 vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
1199
1200 neoLock(state);
1201
1202 return 0;
1203 }
1204
1205 static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1206 u_int transp, struct fb_info *fb)
1207 {
1208 if (regno >= fb->cmap.len || regno > 255)
1209 return -EINVAL;
1210
1211 if (fb->var.bits_per_pixel <= 8) {
1212 outb(regno, 0x3c8);
1213
1214 outb(red >> 10, 0x3c9);
1215 outb(green >> 10, 0x3c9);
1216 outb(blue >> 10, 0x3c9);
1217 } else if (regno < 16) {
1218 switch (fb->var.bits_per_pixel) {
1219 case 16:
1220 ((u32 *) fb->pseudo_palette)[regno] =
1221 ((red & 0xf800)) | ((green & 0xfc00) >> 5) |
1222 ((blue & 0xf800) >> 11);
1223 break;
1224 case 24:
1225 ((u32 *) fb->pseudo_palette)[regno] =
1226 ((red & 0xff00) << 8) | ((green & 0xff00)) |
1227 ((blue & 0xff00) >> 8);
1228 break;
1229 #ifdef NO_32BIT_SUPPORT_YET
1230 case 32:
1231 ((u32 *) fb->pseudo_palette)[regno] =
1232 ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
1233 ((green & 0xff00)) | ((blue & 0xff00) >> 8);
1234 break;
1235 #endif
1236 default:
1237 return 1;
1238 }
1239 }
1240
1241 return 0;
1242 }
1243
1244
1245
1246
1247 static int neofb_blank(int blank_mode, struct fb_info *info)
1248 {
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263 struct neofb_par *par = info->par;
1264 int seqflags, lcdflags, dpmsflags, reg, tmpdisp;
1265
1266
1267
1268
1269
1270 neoUnlock();
1271 tmpdisp = vga_rgfx(NULL, 0x20) & 0x03;
1272 neoLock(&par->state);
1273
1274
1275
1276
1277
1278 if (par->PanelDispCntlRegRead) {
1279 par->PanelDispCntlReg1 = tmpdisp;
1280 }
1281 par->PanelDispCntlRegRead = !blank_mode;
1282
1283 switch (blank_mode) {
1284 case FB_BLANK_POWERDOWN:
1285 seqflags = VGA_SR01_SCREEN_OFF;
1286 lcdflags = 0;
1287 dpmsflags = NEO_GR01_SUPPRESS_HSYNC |
1288 NEO_GR01_SUPPRESS_VSYNC;
1289 #ifdef CONFIG_TOSHIBA
1290
1291
1292 {
1293 SMMRegisters regs;
1294
1295 regs.eax = 0xff00;
1296 regs.ebx = 0x0002;
1297 regs.ecx = 0x0000;
1298 tosh_smm(®s);
1299 }
1300 #endif
1301 break;
1302 case FB_BLANK_HSYNC_SUSPEND:
1303 seqflags = VGA_SR01_SCREEN_OFF;
1304 lcdflags = 0;
1305 dpmsflags = NEO_GR01_SUPPRESS_HSYNC;
1306 break;
1307 case FB_BLANK_VSYNC_SUSPEND:
1308 seqflags = VGA_SR01_SCREEN_OFF;
1309 lcdflags = 0;
1310 dpmsflags = NEO_GR01_SUPPRESS_VSYNC;
1311 break;
1312 case FB_BLANK_NORMAL:
1313 seqflags = VGA_SR01_SCREEN_OFF;
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323 lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02);
1324 dpmsflags = 0x00;
1325 break;
1326 case FB_BLANK_UNBLANK:
1327 seqflags = 0;
1328 lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02);
1329 dpmsflags = 0x00;
1330 #ifdef CONFIG_TOSHIBA
1331
1332
1333 {
1334 SMMRegisters regs;
1335
1336 regs.eax = 0xff00;
1337 regs.ebx = 0x0002;
1338 regs.ecx = 0x0001;
1339 tosh_smm(®s);
1340 }
1341 #endif
1342 break;
1343 default:
1344
1345 return 1;
1346 }
1347
1348 neoUnlock();
1349 reg = (vga_rseq(NULL, 0x01) & ~0x20) | seqflags;
1350 vga_wseq(NULL, 0x01, reg);
1351 reg = (vga_rgfx(NULL, 0x20) & ~0x02) | lcdflags;
1352 vga_wgfx(NULL, 0x20, reg);
1353 reg = (vga_rgfx(NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags;
1354 vga_wgfx(NULL, 0x01, reg);
1355 neoLock(&par->state);
1356 return 0;
1357 }
1358
1359 static void
1360 neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
1361 {
1362 struct neofb_par *par = info->par;
1363 u_long dst, rop;
1364
1365 dst = rect->dx + rect->dy * info->var.xres_virtual;
1366 rop = rect->rop ? 0x060000 : 0x0c0000;
1367
1368 neo2200_wait_fifo(info, 4);
1369
1370
1371 writel(NEO_BC3_FIFO_EN |
1372 NEO_BC0_SRC_IS_FG | NEO_BC3_SKIP_MAPPING |
1373
1374
1375 rop, &par->neo2200->bltCntl);
1376
1377 switch (info->var.bits_per_pixel) {
1378 case 8:
1379 writel(rect->color, &par->neo2200->fgColor);
1380 break;
1381 case 16:
1382 case 24:
1383 writel(((u32 *) (info->pseudo_palette))[rect->color],
1384 &par->neo2200->fgColor);
1385 break;
1386 }
1387
1388 writel(dst * ((info->var.bits_per_pixel + 7) >> 3),
1389 &par->neo2200->dstStart);
1390 writel((rect->height << 16) | (rect->width & 0xffff),
1391 &par->neo2200->xyExt);
1392 }
1393
1394 static void
1395 neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1396 {
1397 u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
1398 struct neofb_par *par = info->par;
1399 u_long src, dst, bltCntl;
1400
1401 bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
1402
1403 if ((dy > sy) || ((dy == sy) && (dx > sx))) {
1404
1405 sy += (area->height - 1);
1406 dy += (area->height - 1);
1407 sx += (area->width - 1);
1408 dx += (area->width - 1);
1409
1410 bltCntl |= NEO_BC0_X_DEC | NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC;
1411 }
1412
1413 src = sx * (info->var.bits_per_pixel >> 3) + sy*info->fix.line_length;
1414 dst = dx * (info->var.bits_per_pixel >> 3) + dy*info->fix.line_length;
1415
1416 neo2200_wait_fifo(info, 4);
1417
1418
1419 writel(bltCntl, &par->neo2200->bltCntl);
1420
1421 writel(src, &par->neo2200->srcStart);
1422 writel(dst, &par->neo2200->dstStart);
1423 writel((area->height << 16) | (area->width & 0xffff),
1424 &par->neo2200->xyExt);
1425 }
1426
1427 static void
1428 neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
1429 {
1430 struct neofb_par *par = info->par;
1431 int s_pitch = (image->width * image->depth + 7) >> 3;
1432 int scan_align = info->pixmap.scan_align - 1;
1433 int buf_align = info->pixmap.buf_align - 1;
1434 int bltCntl_flags, d_pitch, data_len;
1435
1436
1437 d_pitch = (s_pitch + scan_align) & ~scan_align;
1438 data_len = ((d_pitch * image->height) + buf_align) & ~buf_align;
1439
1440 neo2200_sync(info);
1441
1442 if (image->depth == 1) {
1443 if (info->var.bits_per_pixel == 24 && image->width < 16) {
1444
1445
1446
1447
1448
1449 cfb_imageblit(info, image);
1450 return;
1451 }
1452 bltCntl_flags = NEO_BC0_SRC_MONO;
1453 } else if (image->depth == info->var.bits_per_pixel) {
1454 bltCntl_flags = 0;
1455 } else {
1456
1457
1458 cfb_imageblit(info, image);
1459 return;
1460 }
1461
1462 switch (info->var.bits_per_pixel) {
1463 case 8:
1464 writel(image->fg_color, &par->neo2200->fgColor);
1465 writel(image->bg_color, &par->neo2200->bgColor);
1466 break;
1467 case 16:
1468 case 24:
1469 writel(((u32 *) (info->pseudo_palette))[image->fg_color],
1470 &par->neo2200->fgColor);
1471 writel(((u32 *) (info->pseudo_palette))[image->bg_color],
1472 &par->neo2200->bgColor);
1473 break;
1474 }
1475
1476 writel(NEO_BC0_SYS_TO_VID |
1477 NEO_BC3_SKIP_MAPPING | bltCntl_flags |
1478
1479 0x0c0000, &par->neo2200->bltCntl);
1480
1481 writel(0, &par->neo2200->srcStart);
1482
1483 writel(((image->dx & 0xffff) * (info->var.bits_per_pixel >> 3) +
1484 image->dy * info->fix.line_length), &par->neo2200->dstStart);
1485 writel((image->height << 16) | (image->width & 0xffff),
1486 &par->neo2200->xyExt);
1487
1488 memcpy_toio(par->mmio_vbase + 0x100000, image->data, data_len);
1489 }
1490
1491 static void
1492 neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
1493 {
1494 switch (info->fix.accel) {
1495 case FB_ACCEL_NEOMAGIC_NM2200:
1496 case FB_ACCEL_NEOMAGIC_NM2230:
1497 case FB_ACCEL_NEOMAGIC_NM2360:
1498 case FB_ACCEL_NEOMAGIC_NM2380:
1499 neo2200_fillrect(info, rect);
1500 break;
1501 default:
1502 cfb_fillrect(info, rect);
1503 break;
1504 }
1505 }
1506
1507 static void
1508 neofb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1509 {
1510 switch (info->fix.accel) {
1511 case FB_ACCEL_NEOMAGIC_NM2200:
1512 case FB_ACCEL_NEOMAGIC_NM2230:
1513 case FB_ACCEL_NEOMAGIC_NM2360:
1514 case FB_ACCEL_NEOMAGIC_NM2380:
1515 neo2200_copyarea(info, area);
1516 break;
1517 default:
1518 cfb_copyarea(info, area);
1519 break;
1520 }
1521 }
1522
1523 static void
1524 neofb_imageblit(struct fb_info *info, const struct fb_image *image)
1525 {
1526 switch (info->fix.accel) {
1527 case FB_ACCEL_NEOMAGIC_NM2200:
1528 case FB_ACCEL_NEOMAGIC_NM2230:
1529 case FB_ACCEL_NEOMAGIC_NM2360:
1530 case FB_ACCEL_NEOMAGIC_NM2380:
1531 neo2200_imageblit(info, image);
1532 break;
1533 default:
1534 cfb_imageblit(info, image);
1535 break;
1536 }
1537 }
1538
1539 static int
1540 neofb_sync(struct fb_info *info)
1541 {
1542 switch (info->fix.accel) {
1543 case FB_ACCEL_NEOMAGIC_NM2200:
1544 case FB_ACCEL_NEOMAGIC_NM2230:
1545 case FB_ACCEL_NEOMAGIC_NM2360:
1546 case FB_ACCEL_NEOMAGIC_NM2380:
1547 neo2200_sync(info);
1548 break;
1549 default:
1550 break;
1551 }
1552 return 0;
1553 }
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612 static const struct fb_ops neofb_ops = {
1613 .owner = THIS_MODULE,
1614 .fb_open = neofb_open,
1615 .fb_release = neofb_release,
1616 .fb_check_var = neofb_check_var,
1617 .fb_set_par = neofb_set_par,
1618 .fb_setcolreg = neofb_setcolreg,
1619 .fb_pan_display = neofb_pan_display,
1620 .fb_blank = neofb_blank,
1621 .fb_sync = neofb_sync,
1622 .fb_fillrect = neofb_fillrect,
1623 .fb_copyarea = neofb_copyarea,
1624 .fb_imageblit = neofb_imageblit,
1625 };
1626
1627
1628
1629 static struct fb_videomode mode800x480 = {
1630 .xres = 800,
1631 .yres = 480,
1632 .pixclock = 25000,
1633 .left_margin = 88,
1634 .right_margin = 40,
1635 .upper_margin = 23,
1636 .lower_margin = 1,
1637 .hsync_len = 128,
1638 .vsync_len = 4,
1639 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
1640 .vmode = FB_VMODE_NONINTERLACED
1641 };
1642
1643 static int neo_map_mmio(struct fb_info *info, struct pci_dev *dev)
1644 {
1645 struct neofb_par *par = info->par;
1646
1647 DBG("neo_map_mmio");
1648
1649 switch (info->fix.accel) {
1650 case FB_ACCEL_NEOMAGIC_NM2070:
1651 info->fix.mmio_start = pci_resource_start(dev, 0)+
1652 0x100000;
1653 break;
1654 case FB_ACCEL_NEOMAGIC_NM2090:
1655 case FB_ACCEL_NEOMAGIC_NM2093:
1656 info->fix.mmio_start = pci_resource_start(dev, 0)+
1657 0x200000;
1658 break;
1659 case FB_ACCEL_NEOMAGIC_NM2160:
1660 case FB_ACCEL_NEOMAGIC_NM2097:
1661 case FB_ACCEL_NEOMAGIC_NM2200:
1662 case FB_ACCEL_NEOMAGIC_NM2230:
1663 case FB_ACCEL_NEOMAGIC_NM2360:
1664 case FB_ACCEL_NEOMAGIC_NM2380:
1665 info->fix.mmio_start = pci_resource_start(dev, 1);
1666 break;
1667 default:
1668 info->fix.mmio_start = pci_resource_start(dev, 0);
1669 }
1670 info->fix.mmio_len = MMIO_SIZE;
1671
1672 if (!request_mem_region
1673 (info->fix.mmio_start, MMIO_SIZE, "memory mapped I/O")) {
1674 printk("neofb: memory mapped IO in use\n");
1675 return -EBUSY;
1676 }
1677
1678 par->mmio_vbase = ioremap(info->fix.mmio_start, MMIO_SIZE);
1679 if (!par->mmio_vbase) {
1680 printk("neofb: unable to map memory mapped IO\n");
1681 release_mem_region(info->fix.mmio_start,
1682 info->fix.mmio_len);
1683 return -ENOMEM;
1684 } else
1685 printk(KERN_INFO "neofb: mapped io at %p\n",
1686 par->mmio_vbase);
1687 return 0;
1688 }
1689
1690 static void neo_unmap_mmio(struct fb_info *info)
1691 {
1692 struct neofb_par *par = info->par;
1693
1694 DBG("neo_unmap_mmio");
1695
1696 iounmap(par->mmio_vbase);
1697 par->mmio_vbase = NULL;
1698
1699 release_mem_region(info->fix.mmio_start,
1700 info->fix.mmio_len);
1701 }
1702
1703 static int neo_map_video(struct fb_info *info, struct pci_dev *dev,
1704 int video_len)
1705 {
1706
1707 struct neofb_par *par = info->par;
1708
1709 DBG("neo_map_video");
1710
1711 info->fix.smem_start = pci_resource_start(dev, 0);
1712 info->fix.smem_len = video_len;
1713
1714 if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
1715 "frame buffer")) {
1716 printk("neofb: frame buffer in use\n");
1717 return -EBUSY;
1718 }
1719
1720 info->screen_base =
1721 ioremap_wc(info->fix.smem_start, info->fix.smem_len);
1722 if (!info->screen_base) {
1723 printk("neofb: unable to map screen memory\n");
1724 release_mem_region(info->fix.smem_start,
1725 info->fix.smem_len);
1726 return -ENOMEM;
1727 } else
1728 printk(KERN_INFO "neofb: mapped framebuffer at %p\n",
1729 info->screen_base);
1730
1731 par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
1732 pci_resource_len(dev, 0));
1733
1734
1735 memset_io(info->screen_base, 0, info->fix.smem_len);
1736
1737
1738
1739
1740
1741
1742
1743
1744 return 0;
1745 }
1746
1747 static void neo_unmap_video(struct fb_info *info)
1748 {
1749 struct neofb_par *par = info->par;
1750
1751 DBG("neo_unmap_video");
1752
1753 arch_phys_wc_del(par->wc_cookie);
1754 iounmap(info->screen_base);
1755 info->screen_base = NULL;
1756
1757 release_mem_region(info->fix.smem_start,
1758 info->fix.smem_len);
1759 }
1760
1761 static int neo_scan_monitor(struct fb_info *info)
1762 {
1763 struct neofb_par *par = info->par;
1764 unsigned char type, display;
1765 int w;
1766
1767
1768 info->monspecs.modedb = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);
1769 if (!info->monspecs.modedb)
1770 return -ENOMEM;
1771 info->monspecs.modedb_len = 1;
1772
1773
1774 vga_wgfx(NULL, 0x09, 0x26);
1775 type = vga_rgfx(NULL, 0x21);
1776 display = vga_rgfx(NULL, 0x20);
1777 if (!par->internal_display && !par->external_display) {
1778 par->internal_display = display & 2 || !(display & 3) ? 1 : 0;
1779 par->external_display = display & 1;
1780 printk (KERN_INFO "Autodetected %s display\n",
1781 par->internal_display && par->external_display ? "simultaneous" :
1782 par->internal_display ? "internal" : "external");
1783 }
1784
1785
1786 w = vga_rgfx(NULL, 0x20);
1787 vga_wgfx(NULL, 0x09, 0x00);
1788 switch ((w & 0x18) >> 3) {
1789 case 0x00:
1790
1791 par->NeoPanelWidth = 640;
1792 par->NeoPanelHeight = 480;
1793 memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
1794 break;
1795 case 0x01:
1796 par->NeoPanelWidth = 800;
1797 if (par->libretto) {
1798 par->NeoPanelHeight = 480;
1799 memcpy(info->monspecs.modedb, &mode800x480, sizeof(struct fb_videomode));
1800 } else {
1801
1802 par->NeoPanelHeight = 600;
1803 memcpy(info->monspecs.modedb, &vesa_modes[8], sizeof(struct fb_videomode));
1804 }
1805 break;
1806 case 0x02:
1807
1808 par->NeoPanelWidth = 1024;
1809 par->NeoPanelHeight = 768;
1810 memcpy(info->monspecs.modedb, &vesa_modes[13], sizeof(struct fb_videomode));
1811 break;
1812 case 0x03:
1813
1814 #ifdef NOT_DONE
1815 par->NeoPanelWidth = 1280;
1816 par->NeoPanelHeight = 1024;
1817 memcpy(info->monspecs.modedb, &vesa_modes[20], sizeof(struct fb_videomode));
1818 break;
1819 #else
1820 printk(KERN_ERR
1821 "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n");
1822 kfree(info->monspecs.modedb);
1823 return -1;
1824 #endif
1825 default:
1826
1827 par->NeoPanelWidth = 640;
1828 par->NeoPanelHeight = 480;
1829 memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
1830 break;
1831 }
1832
1833 printk(KERN_INFO "Panel is a %dx%d %s %s display\n",
1834 par->NeoPanelWidth,
1835 par->NeoPanelHeight,
1836 (type & 0x02) ? "color" : "monochrome",
1837 (type & 0x10) ? "TFT" : "dual scan");
1838 return 0;
1839 }
1840
1841 static int neo_init_hw(struct fb_info *info)
1842 {
1843 struct neofb_par *par = info->par;
1844 int videoRam = 896;
1845 int maxClock = 65000;
1846 int CursorOff = 0x100;
1847
1848 DBG("neo_init_hw");
1849
1850 neoUnlock();
1851
1852 #if 0
1853 printk(KERN_DEBUG "--- Neo extended register dump ---\n");
1854 for (int w = 0; w < 0x85; w++)
1855 printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
1856 (void *) vga_rcrt(NULL, w));
1857 for (int w = 0; w < 0xC7; w++)
1858 printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
1859 (void *) vga_rgfx(NULL, w));
1860 #endif
1861 switch (info->fix.accel) {
1862 case FB_ACCEL_NEOMAGIC_NM2070:
1863 videoRam = 896;
1864 maxClock = 65000;
1865 break;
1866 case FB_ACCEL_NEOMAGIC_NM2090:
1867 case FB_ACCEL_NEOMAGIC_NM2093:
1868 case FB_ACCEL_NEOMAGIC_NM2097:
1869 videoRam = 1152;
1870 maxClock = 80000;
1871 break;
1872 case FB_ACCEL_NEOMAGIC_NM2160:
1873 videoRam = 2048;
1874 maxClock = 90000;
1875 break;
1876 case FB_ACCEL_NEOMAGIC_NM2200:
1877 videoRam = 2560;
1878 maxClock = 110000;
1879 break;
1880 case FB_ACCEL_NEOMAGIC_NM2230:
1881 videoRam = 3008;
1882 maxClock = 110000;
1883 break;
1884 case FB_ACCEL_NEOMAGIC_NM2360:
1885 videoRam = 4096;
1886 maxClock = 110000;
1887 break;
1888 case FB_ACCEL_NEOMAGIC_NM2380:
1889 videoRam = 6144;
1890 maxClock = 110000;
1891 break;
1892 }
1893 switch (info->fix.accel) {
1894 case FB_ACCEL_NEOMAGIC_NM2070:
1895 case FB_ACCEL_NEOMAGIC_NM2090:
1896 case FB_ACCEL_NEOMAGIC_NM2093:
1897 CursorOff = 0x100;
1898 break;
1899 case FB_ACCEL_NEOMAGIC_NM2097:
1900 case FB_ACCEL_NEOMAGIC_NM2160:
1901 CursorOff = 0x100;
1902 break;
1903 case FB_ACCEL_NEOMAGIC_NM2200:
1904 case FB_ACCEL_NEOMAGIC_NM2230:
1905 case FB_ACCEL_NEOMAGIC_NM2360:
1906 case FB_ACCEL_NEOMAGIC_NM2380:
1907 CursorOff = 0x1000;
1908
1909 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
1910 break;
1911 }
1912
1913
1914
1915
1916
1917
1918
1919 par->maxClock = maxClock;
1920 par->cursorOff = CursorOff;
1921 return videoRam * 1024;
1922 }
1923
1924
1925 static struct fb_info *neo_alloc_fb_info(struct pci_dev *dev,
1926 const struct pci_device_id *id)
1927 {
1928 struct fb_info *info;
1929 struct neofb_par *par;
1930
1931 info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);
1932
1933 if (!info)
1934 return NULL;
1935
1936 par = info->par;
1937
1938 info->fix.accel = id->driver_data;
1939
1940 par->pci_burst = !nopciburst;
1941 par->lcd_stretch = !nostretch;
1942 par->libretto = libretto;
1943
1944 par->internal_display = internal;
1945 par->external_display = external;
1946 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1947
1948 switch (info->fix.accel) {
1949 case FB_ACCEL_NEOMAGIC_NM2070:
1950 snprintf(info->fix.id, sizeof(info->fix.id),
1951 "MagicGraph 128");
1952 break;
1953 case FB_ACCEL_NEOMAGIC_NM2090:
1954 snprintf(info->fix.id, sizeof(info->fix.id),
1955 "MagicGraph 128V");
1956 break;
1957 case FB_ACCEL_NEOMAGIC_NM2093:
1958 snprintf(info->fix.id, sizeof(info->fix.id),
1959 "MagicGraph 128ZV");
1960 break;
1961 case FB_ACCEL_NEOMAGIC_NM2097:
1962 snprintf(info->fix.id, sizeof(info->fix.id),
1963 "MagicGraph 128ZV+");
1964 break;
1965 case FB_ACCEL_NEOMAGIC_NM2160:
1966 snprintf(info->fix.id, sizeof(info->fix.id),
1967 "MagicGraph 128XD");
1968 break;
1969 case FB_ACCEL_NEOMAGIC_NM2200:
1970 snprintf(info->fix.id, sizeof(info->fix.id),
1971 "MagicGraph 256AV");
1972 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
1973 FBINFO_HWACCEL_COPYAREA |
1974 FBINFO_HWACCEL_FILLRECT;
1975 break;
1976 case FB_ACCEL_NEOMAGIC_NM2230:
1977 snprintf(info->fix.id, sizeof(info->fix.id),
1978 "MagicGraph 256AV+");
1979 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
1980 FBINFO_HWACCEL_COPYAREA |
1981 FBINFO_HWACCEL_FILLRECT;
1982 break;
1983 case FB_ACCEL_NEOMAGIC_NM2360:
1984 snprintf(info->fix.id, sizeof(info->fix.id),
1985 "MagicGraph 256ZX");
1986 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
1987 FBINFO_HWACCEL_COPYAREA |
1988 FBINFO_HWACCEL_FILLRECT;
1989 break;
1990 case FB_ACCEL_NEOMAGIC_NM2380:
1991 snprintf(info->fix.id, sizeof(info->fix.id),
1992 "MagicGraph 256XL+");
1993 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
1994 FBINFO_HWACCEL_COPYAREA |
1995 FBINFO_HWACCEL_FILLRECT;
1996 break;
1997 }
1998
1999 info->fix.type = FB_TYPE_PACKED_PIXELS;
2000 info->fix.type_aux = 0;
2001 info->fix.xpanstep = 0;
2002 info->fix.ypanstep = 4;
2003 info->fix.ywrapstep = 0;
2004 info->fix.accel = id->driver_data;
2005
2006 info->fbops = &neofb_ops;
2007 info->pseudo_palette = par->palette;
2008 return info;
2009 }
2010
2011 static void neo_free_fb_info(struct fb_info *info)
2012 {
2013 if (info) {
2014
2015
2016
2017 fb_dealloc_cmap(&info->cmap);
2018 framebuffer_release(info);
2019 }
2020 }
2021
2022
2023
2024 static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id)
2025 {
2026 struct fb_info *info;
2027 u_int h_sync, v_sync;
2028 int video_len, err;
2029
2030 DBG("neofb_probe");
2031
2032 err = pci_enable_device(dev);
2033 if (err)
2034 return err;
2035
2036 err = -ENOMEM;
2037 info = neo_alloc_fb_info(dev, id);
2038 if (!info)
2039 return err;
2040
2041 err = neo_map_mmio(info, dev);
2042 if (err)
2043 goto err_map_mmio;
2044
2045 err = neo_scan_monitor(info);
2046 if (err)
2047 goto err_scan_monitor;
2048
2049 video_len = neo_init_hw(info);
2050 if (video_len < 0) {
2051 err = video_len;
2052 goto err_init_hw;
2053 }
2054
2055 err = neo_map_video(info, dev, video_len);
2056 if (err)
2057 goto err_init_hw;
2058
2059 if (!fb_find_mode(&info->var, info, mode_option, NULL, 0,
2060 info->monspecs.modedb, 16)) {
2061 printk(KERN_ERR "neofb: Unable to find usable video mode.\n");
2062 err = -EINVAL;
2063 goto err_map_video;
2064 }
2065
2066
2067
2068
2069
2070
2071
2072 h_sync = 1953125000 / info->var.pixclock;
2073 h_sync =
2074 h_sync * 512 / (info->var.xres + info->var.left_margin +
2075 info->var.right_margin + info->var.hsync_len);
2076 v_sync =
2077 h_sync / (info->var.yres + info->var.upper_margin +
2078 info->var.lower_margin + info->var.vsync_len);
2079
2080 printk(KERN_INFO "neofb v" NEOFB_VERSION
2081 ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
2082 info->fix.smem_len >> 10, info->var.xres,
2083 info->var.yres, h_sync / 1000, h_sync % 1000, v_sync);
2084
2085 err = fb_alloc_cmap(&info->cmap, 256, 0);
2086 if (err < 0)
2087 goto err_map_video;
2088
2089 err = register_framebuffer(info);
2090 if (err < 0)
2091 goto err_reg_fb;
2092
2093 fb_info(info, "%s frame buffer device\n", info->fix.id);
2094
2095
2096
2097
2098 pci_set_drvdata(dev, info);
2099 return 0;
2100
2101 err_reg_fb:
2102 fb_dealloc_cmap(&info->cmap);
2103 err_map_video:
2104 neo_unmap_video(info);
2105 err_init_hw:
2106 fb_destroy_modedb(info->monspecs.modedb);
2107 err_scan_monitor:
2108 neo_unmap_mmio(info);
2109 err_map_mmio:
2110 neo_free_fb_info(info);
2111 return err;
2112 }
2113
2114 static void neofb_remove(struct pci_dev *dev)
2115 {
2116 struct fb_info *info = pci_get_drvdata(dev);
2117
2118 DBG("neofb_remove");
2119
2120 if (info) {
2121 unregister_framebuffer(info);
2122
2123 neo_unmap_video(info);
2124 fb_destroy_modedb(info->monspecs.modedb);
2125 neo_unmap_mmio(info);
2126 neo_free_fb_info(info);
2127 }
2128 }
2129
2130 static const struct pci_device_id neofb_devices[] = {
2131 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070,
2132 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070},
2133
2134 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090,
2135 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090},
2136
2137 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093,
2138 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093},
2139
2140 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097,
2141 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097},
2142
2143 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160,
2144 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160},
2145
2146 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200,
2147 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200},
2148
2149 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230,
2150 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230},
2151
2152 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360,
2153 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360},
2154
2155 {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380,
2156 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380},
2157
2158 {0, 0, 0, 0, 0, 0, 0}
2159 };
2160
2161 MODULE_DEVICE_TABLE(pci, neofb_devices);
2162
2163 static struct pci_driver neofb_driver = {
2164 .name = "neofb",
2165 .id_table = neofb_devices,
2166 .probe = neofb_probe,
2167 .remove = neofb_remove,
2168 };
2169
2170
2171
2172 #ifndef MODULE
2173 static int __init neofb_setup(char *options)
2174 {
2175 char *this_opt;
2176
2177 DBG("neofb_setup");
2178
2179 if (!options || !*options)
2180 return 0;
2181
2182 while ((this_opt = strsep(&options, ",")) != NULL) {
2183 if (!*this_opt)
2184 continue;
2185
2186 if (!strncmp(this_opt, "internal", 8))
2187 internal = 1;
2188 else if (!strncmp(this_opt, "external", 8))
2189 external = 1;
2190 else if (!strncmp(this_opt, "nostretch", 9))
2191 nostretch = 1;
2192 else if (!strncmp(this_opt, "nopciburst", 10))
2193 nopciburst = 1;
2194 else if (!strncmp(this_opt, "libretto", 8))
2195 libretto = 1;
2196 else
2197 mode_option = this_opt;
2198 }
2199 return 0;
2200 }
2201 #endif
2202
2203 static int __init neofb_init(void)
2204 {
2205 #ifndef MODULE
2206 char *option = NULL;
2207
2208 if (fb_get_options("neofb", &option))
2209 return -ENODEV;
2210 neofb_setup(option);
2211 #endif
2212 return pci_register_driver(&neofb_driver);
2213 }
2214
2215 module_init(neofb_init);
2216
2217 #ifdef MODULE
2218 static void __exit neofb_exit(void)
2219 {
2220 pci_unregister_driver(&neofb_driver);
2221 }
2222
2223 module_exit(neofb_exit);
2224 #endif