This source file includes following definitions.
- write_le32
- neoFindMode
- neoCalcVCLK
- vgaHWInit
- vgaHWLock
- vgaHWUnlock
- neoLock
- neoUnlock
- VGAenablePalette
- VGAdisablePalette
- VGAwATTR
- vgaHWProtect
- vgaHWRestore
- neo2200_sync
- neo2200_wait_fifo
- neo2200_accel_init
- neofb_open
- neofb_release
- neofb_check_var
- neofb_set_par
- neofb_pan_display
- neofb_setcolreg
- neofb_blank
- neo2200_fillrect
- neo2200_copyarea
- neo2200_imageblit
- neofb_fillrect
- neofb_copyarea
- neofb_imageblit
- neofb_sync
- neo_map_mmio
- neo_unmap_mmio
- neo_map_video
- neo_unmap_video
- neo_scan_monitor
- neo_init_hw
- neo_alloc_fb_info
- neo_free_fb_info
- neofb_probe
- neofb_remove
- neofb_setup
- neofb_init
- neofb_exit
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 
  57 #include <linux/module.h>
  58 #include <linux/kernel.h>
  59 #include <linux/errno.h>
  60 #include <linux/string.h>
  61 #include <linux/mm.h>
  62 #include <linux/slab.h>
  63 #include <linux/delay.h>
  64 #include <linux/fb.h>
  65 #include <linux/pci.h>
  66 #include <linux/init.h>
  67 #ifdef CONFIG_TOSHIBA
  68 #include <linux/toshiba.h>
  69 #endif
  70 
  71 #include <asm/io.h>
  72 #include <asm/irq.h>
  73 #include <asm/pgtable.h>
  74 #include <video/vga.h>
  75 #include <video/neomagic.h>
  76 
  77 #define NEOFB_VERSION "0.4.2"
  78 
  79 
  80 
  81 static bool internal;
  82 static bool external;
  83 static bool libretto;
  84 static bool nostretch;
  85 static bool nopciburst;
  86 static char *mode_option = NULL;
  87 
  88 #ifdef MODULE
  89 
  90 MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@convergence.de>");
  91 MODULE_LICENSE("GPL");
  92 MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");
  93 module_param(internal, bool, 0);
  94 MODULE_PARM_DESC(internal, "Enable output on internal LCD Display.");
  95 module_param(external, bool, 0);
  96 MODULE_PARM_DESC(external, "Enable output on external CRT.");
  97 module_param(libretto, bool, 0);
  98 MODULE_PARM_DESC(libretto, "Force Libretto 100/110 800x480 LCD.");
  99 module_param(nostretch, bool, 0);
 100 MODULE_PARM_DESC(nostretch,
 101                  "Disable stretching of modes smaller than LCD.");
 102 module_param(nopciburst, bool, 0);
 103 MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
 104 module_param(mode_option, charp, 0);
 105 MODULE_PARM_DESC(mode_option, "Preferred video mode ('640x480-8@60', etc)");
 106 
 107 #endif
 108 
 109 
 110 
 111 
 112 static biosMode bios8[] = {
 113         {320, 240, 0x40},
 114         {300, 400, 0x42},
 115         {640, 400, 0x20},
 116         {640, 480, 0x21},
 117         {800, 600, 0x23},
 118         {1024, 768, 0x25},
 119 };
 120 
 121 static biosMode bios16[] = {
 122         {320, 200, 0x2e},
 123         {320, 240, 0x41},
 124         {300, 400, 0x43},
 125         {640, 480, 0x31},
 126         {800, 600, 0x34},
 127         {1024, 768, 0x37},
 128 };
 129 
 130 static biosMode bios24[] = {
 131         {640, 480, 0x32},
 132         {800, 600, 0x35},
 133         {1024, 768, 0x38}
 134 };
 135 
 136 #ifdef NO_32BIT_SUPPORT_YET
 137 
 138 static biosMode bios32[] = {
 139         {640, 480, 0x33},
 140         {800, 600, 0x36},
 141         {1024, 768, 0x39}
 142 };
 143 #endif
 144 
 145 static inline void write_le32(int regindex, u32 val, const struct neofb_par *par)
 146 {
 147         writel(val, par->neo2200 + par->cursorOff + regindex);
 148 }
 149 
 150 static int neoFindMode(int xres, int yres, int depth)
 151 {
 152         int xres_s;
 153         int i, size;
 154         biosMode *mode;
 155 
 156         switch (depth) {
 157         case 8:
 158                 size = ARRAY_SIZE(bios8);
 159                 mode = bios8;
 160                 break;
 161         case 16:
 162                 size = ARRAY_SIZE(bios16);
 163                 mode = bios16;
 164                 break;
 165         case 24:
 166                 size = ARRAY_SIZE(bios24);
 167                 mode = bios24;
 168                 break;
 169 #ifdef NO_32BIT_SUPPORT_YET
 170         case 32:
 171                 size = ARRAY_SIZE(bios32);
 172                 mode = bios32;
 173                 break;
 174 #endif
 175         default:
 176                 return 0;
 177         }
 178 
 179         for (i = 0; i < size; i++) {
 180                 if (xres <= mode[i].x_res) {
 181                         xres_s = mode[i].x_res;
 182                         for (; i < size; i++) {
 183                                 if (mode[i].x_res != xres_s)
 184                                         return mode[i - 1].mode;
 185                                 if (yres <= mode[i].y_res)
 186                                         return mode[i].mode;
 187                         }
 188                 }
 189         }
 190         return mode[size - 1].mode;
 191 }
 192 
 193 
 194 
 195 
 196 
 197 
 198 #define MAX_N 127
 199 #define MAX_D 31
 200 #define MAX_F 1
 201 
 202 static void neoCalcVCLK(const struct fb_info *info,
 203                         struct neofb_par *par, long freq)
 204 {
 205         int n, d, f;
 206         int n_best = 0, d_best = 0, f_best = 0;
 207         long f_best_diff = 0x7ffff;
 208 
 209         for (f = 0; f <= MAX_F; f++)
 210                 for (d = 0; d <= MAX_D; d++)
 211                         for (n = 0; n <= MAX_N; n++) {
 212                                 long f_out;
 213                                 long f_diff;
 214 
 215                                 f_out = ((14318 * (n + 1)) / (d + 1)) >> f;
 216                                 f_diff = abs(f_out - freq);
 217                                 if (f_diff <= f_best_diff) {
 218                                         f_best_diff = f_diff;
 219                                         n_best = n;
 220                                         d_best = d;
 221                                         f_best = f;
 222                                 }
 223                                 if (f_out > freq)
 224                                         break;
 225                         }
 226 
 227         if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
 228             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
 229             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
 230             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
 231                 
 232 
 233                 par->VCLK3NumeratorLow = n_best;
 234                 par->VCLK3NumeratorHigh = (f_best << 7);
 235         } else
 236                 par->VCLK3NumeratorLow = n_best | (f_best << 7);
 237 
 238         par->VCLK3Denominator = d_best;
 239 
 240 #ifdef NEOFB_DEBUG
 241         printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n",
 242                freq,
 243                par->VCLK3NumeratorLow,
 244                par->VCLK3NumeratorHigh,
 245                par->VCLK3Denominator, f_best_diff);
 246 #endif
 247 }
 248 
 249 
 250 
 251 
 252 
 253 
 254 
 255 static int vgaHWInit(const struct fb_var_screeninfo *var,
 256                      struct neofb_par *par)
 257 {
 258         int hsync_end = var->xres + var->right_margin + var->hsync_len;
 259         int htotal = (hsync_end + var->left_margin) >> 3;
 260         int vsync_start = var->yres + var->lower_margin;
 261         int vsync_end = vsync_start + var->vsync_len;
 262         int vtotal = vsync_end + var->upper_margin;
 263 
 264         par->MiscOutReg = 0x23;
 265 
 266         if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
 267                 par->MiscOutReg |= 0x40;
 268 
 269         if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
 270                 par->MiscOutReg |= 0x80;
 271 
 272         
 273 
 274 
 275         par->Sequencer[0] = 0x00;
 276         par->Sequencer[1] = 0x01;
 277         par->Sequencer[2] = 0x0F;
 278         par->Sequencer[3] = 0x00;       
 279         par->Sequencer[4] = 0x0E;       
 280 
 281         
 282 
 283 
 284         par->CRTC[0] = htotal - 5;
 285         par->CRTC[1] = (var->xres >> 3) - 1;
 286         par->CRTC[2] = (var->xres >> 3) - 1;
 287         par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
 288         par->CRTC[4] = ((var->xres + var->right_margin) >> 3);
 289         par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
 290             | (((hsync_end >> 3)) & 0x1F);
 291         par->CRTC[6] = (vtotal - 2) & 0xFF;
 292         par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
 293             | (((var->yres - 1) & 0x100) >> 7)
 294             | ((vsync_start & 0x100) >> 6)
 295             | (((var->yres - 1) & 0x100) >> 5)
 296             | 0x10 | (((vtotal - 2) & 0x200) >> 4)
 297             | (((var->yres - 1) & 0x200) >> 3)
 298             | ((vsync_start & 0x200) >> 2);
 299         par->CRTC[8] = 0x00;
 300         par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40;
 301 
 302         if (var->vmode & FB_VMODE_DOUBLE)
 303                 par->CRTC[9] |= 0x80;
 304 
 305         par->CRTC[10] = 0x00;
 306         par->CRTC[11] = 0x00;
 307         par->CRTC[12] = 0x00;
 308         par->CRTC[13] = 0x00;
 309         par->CRTC[14] = 0x00;
 310         par->CRTC[15] = 0x00;
 311         par->CRTC[16] = vsync_start & 0xFF;
 312         par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
 313         par->CRTC[18] = (var->yres - 1) & 0xFF;
 314         par->CRTC[19] = var->xres_virtual >> 4;
 315         par->CRTC[20] = 0x00;
 316         par->CRTC[21] = (var->yres - 1) & 0xFF;
 317         par->CRTC[22] = (vtotal - 1) & 0xFF;
 318         par->CRTC[23] = 0xC3;
 319         par->CRTC[24] = 0xFF;
 320 
 321         
 322 
 323 
 324 
 325 
 326 
 327         
 328 
 329 
 330         par->Graphics[0] = 0x00;
 331         par->Graphics[1] = 0x00;
 332         par->Graphics[2] = 0x00;
 333         par->Graphics[3] = 0x00;
 334         par->Graphics[4] = 0x00;
 335         par->Graphics[5] = 0x40;
 336         par->Graphics[6] = 0x05;        
 337         par->Graphics[7] = 0x0F;
 338         par->Graphics[8] = 0xFF;
 339 
 340 
 341         par->Attribute[0] = 0x00;       
 342         par->Attribute[1] = 0x01;
 343         par->Attribute[2] = 0x02;
 344         par->Attribute[3] = 0x03;
 345         par->Attribute[4] = 0x04;
 346         par->Attribute[5] = 0x05;
 347         par->Attribute[6] = 0x06;
 348         par->Attribute[7] = 0x07;
 349         par->Attribute[8] = 0x08;
 350         par->Attribute[9] = 0x09;
 351         par->Attribute[10] = 0x0A;
 352         par->Attribute[11] = 0x0B;
 353         par->Attribute[12] = 0x0C;
 354         par->Attribute[13] = 0x0D;
 355         par->Attribute[14] = 0x0E;
 356         par->Attribute[15] = 0x0F;
 357         par->Attribute[16] = 0x41;
 358         par->Attribute[17] = 0xFF;
 359         par->Attribute[18] = 0x0F;
 360         par->Attribute[19] = 0x00;
 361         par->Attribute[20] = 0x00;
 362         return 0;
 363 }
 364 
 365 static void vgaHWLock(struct vgastate *state)
 366 {
 367         
 368         vga_wcrt(state->vgabase, 0x11, vga_rcrt(state->vgabase, 0x11) | 0x80);
 369 }
 370 
 371 static void vgaHWUnlock(void)
 372 {
 373         
 374         vga_wcrt(NULL, 0x11, vga_rcrt(NULL, 0x11) & ~0x80);
 375 }
 376 
 377 static void neoLock(struct vgastate *state)
 378 {
 379         vga_wgfx(state->vgabase, 0x09, 0x00);
 380         vgaHWLock(state);
 381 }
 382 
 383 static void neoUnlock(void)
 384 {
 385         vgaHWUnlock();
 386         vga_wgfx(NULL, 0x09, 0x26);
 387 }
 388 
 389 
 390 
 391 
 392 static int paletteEnabled = 0;
 393 
 394 static inline void VGAenablePalette(void)
 395 {
 396         vga_r(NULL, VGA_IS1_RC);
 397         vga_w(NULL, VGA_ATT_W, 0x00);
 398         paletteEnabled = 1;
 399 }
 400 
 401 static inline void VGAdisablePalette(void)
 402 {
 403         vga_r(NULL, VGA_IS1_RC);
 404         vga_w(NULL, VGA_ATT_W, 0x20);
 405         paletteEnabled = 0;
 406 }
 407 
 408 static inline void VGAwATTR(u8 index, u8 value)
 409 {
 410         if (paletteEnabled)
 411                 index &= ~0x20;
 412         else
 413                 index |= 0x20;
 414 
 415         vga_r(NULL, VGA_IS1_RC);
 416         vga_wattr(NULL, index, value);
 417 }
 418 
 419 static void vgaHWProtect(int on)
 420 {
 421         unsigned char tmp;
 422 
 423         tmp = vga_rseq(NULL, 0x01);
 424         if (on) {
 425                 
 426 
 427 
 428                 vga_wseq(NULL, 0x00, 0x01);             
 429                 vga_wseq(NULL, 0x01, tmp | 0x20);       
 430 
 431                 VGAenablePalette();
 432         } else {
 433                 
 434 
 435 
 436                 vga_wseq(NULL, 0x01, tmp & ~0x20);      
 437                 vga_wseq(NULL, 0x00, 0x03);             
 438 
 439                 VGAdisablePalette();
 440         }
 441 }
 442 
 443 static void vgaHWRestore(const struct fb_info *info,
 444                          const struct neofb_par *par)
 445 {
 446         int i;
 447 
 448         vga_w(NULL, VGA_MIS_W, par->MiscOutReg);
 449 
 450         for (i = 1; i < 5; i++)
 451                 vga_wseq(NULL, i, par->Sequencer[i]);
 452 
 453         
 454         vga_wcrt(NULL, 17, par->CRTC[17] & ~0x80);
 455 
 456         for (i = 0; i < 25; i++)
 457                 vga_wcrt(NULL, i, par->CRTC[i]);
 458 
 459         for (i = 0; i < 9; i++)
 460                 vga_wgfx(NULL, i, par->Graphics[i]);
 461 
 462         VGAenablePalette();
 463 
 464         for (i = 0; i < 21; i++)
 465                 VGAwATTR(i, par->Attribute[i]);
 466 
 467         VGAdisablePalette();
 468 }
 469 
 470 
 471 
 472 
 473 
 474 
 475 
 476 static inline int neo2200_sync(struct fb_info *info)
 477 {
 478         struct neofb_par *par = info->par;
 479 
 480         while (readl(&par->neo2200->bltStat) & 1)
 481                 cpu_relax();
 482         return 0;
 483 }
 484 
 485 static inline void neo2200_wait_fifo(struct fb_info *info,
 486                                      int requested_fifo_space)
 487 {
 488         
 489         
 490 
 491         
 492 
 493 
 494 
 495 
 496 
 497 
 498 
 499 
 500 
 501 
 502 
 503 
 504 
 505 
 506 
 507 
 508 
 509 
 510 
 511         neo2200_sync(info);
 512 }
 513 
 514 static inline void neo2200_accel_init(struct fb_info *info,
 515                                       struct fb_var_screeninfo *var)
 516 {
 517         struct neofb_par *par = info->par;
 518         Neo2200 __iomem *neo2200 = par->neo2200;
 519         u32 bltMod, pitch;
 520 
 521         neo2200_sync(info);
 522 
 523         switch (var->bits_per_pixel) {
 524         case 8:
 525                 bltMod = NEO_MODE1_DEPTH8;
 526                 pitch = var->xres_virtual;
 527                 break;
 528         case 15:
 529         case 16:
 530                 bltMod = NEO_MODE1_DEPTH16;
 531                 pitch = var->xres_virtual * 2;
 532                 break;
 533         case 24:
 534                 bltMod = NEO_MODE1_DEPTH24;
 535                 pitch = var->xres_virtual * 3;
 536                 break;
 537         default:
 538                 printk(KERN_ERR
 539                        "neofb: neo2200_accel_init: unexpected bits per pixel!\n");
 540                 return;
 541         }
 542 
 543         writel(bltMod << 16, &neo2200->bltStat);
 544         writel((pitch << 16) | pitch, &neo2200->pitch);
 545 }
 546 
 547 
 548 
 549 static int
 550 neofb_open(struct fb_info *info, int user)
 551 {
 552         struct neofb_par *par = info->par;
 553 
 554         if (!par->ref_count) {
 555                 memset(&par->state, 0, sizeof(struct vgastate));
 556                 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
 557                 save_vga(&par->state);
 558         }
 559         par->ref_count++;
 560 
 561         return 0;
 562 }
 563 
 564 static int
 565 neofb_release(struct fb_info *info, int user)
 566 {
 567         struct neofb_par *par = info->par;
 568 
 569         if (!par->ref_count)
 570                 return -EINVAL;
 571 
 572         if (par->ref_count == 1) {
 573                 restore_vga(&par->state);
 574         }
 575         par->ref_count--;
 576 
 577         return 0;
 578 }
 579 
 580 static int
 581 neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 582 {
 583         struct neofb_par *par = info->par;
 584         int memlen, vramlen;
 585         int mode_ok = 0;
 586 
 587         DBG("neofb_check_var");
 588 
 589         if (PICOS2KHZ(var->pixclock) > par->maxClock)
 590                 return -EINVAL;
 591 
 592         
 593         if (par->internal_display &&
 594             ((var->xres > par->NeoPanelWidth) ||
 595              (var->yres > par->NeoPanelHeight))) {
 596                 printk(KERN_INFO
 597                        "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",
 598                        var->xres, var->yres, par->NeoPanelWidth,
 599                        par->NeoPanelHeight);
 600                 return -EINVAL;
 601         }
 602 
 603         
 604         if (!par->internal_display)
 605                 mode_ok = 1;
 606         else {
 607                 switch (var->xres) {
 608                 case 1280:
 609                         if (var->yres == 1024)
 610                                 mode_ok = 1;
 611                         break;
 612                 case 1024:
 613                         if (var->yres == 768)
 614                                 mode_ok = 1;
 615                         break;
 616                 case 800:
 617                         if (var->yres == (par->libretto ? 480 : 600))
 618                                 mode_ok = 1;
 619                         break;
 620                 case 640:
 621                         if (var->yres == 480)
 622                                 mode_ok = 1;
 623                         break;
 624                 }
 625         }
 626 
 627         if (!mode_ok) {
 628                 printk(KERN_INFO
 629                        "Mode (%dx%d) won't display properly on LCD\n",
 630                        var->xres, var->yres);
 631                 return -EINVAL;
 632         }
 633 
 634         var->red.msb_right = 0;
 635         var->green.msb_right = 0;
 636         var->blue.msb_right = 0;
 637         var->transp.msb_right = 0;
 638 
 639         var->transp.offset = 0;
 640         var->transp.length = 0;
 641         switch (var->bits_per_pixel) {
 642         case 8:         
 643                 var->red.offset = 0;
 644                 var->red.length = 8;
 645                 var->green.offset = 0;
 646                 var->green.length = 8;
 647                 var->blue.offset = 0;
 648                 var->blue.length = 8;
 649                 break;
 650 
 651         case 16:                
 652                 var->red.offset = 11;
 653                 var->red.length = 5;
 654                 var->green.offset = 5;
 655                 var->green.length = 6;
 656                 var->blue.offset = 0;
 657                 var->blue.length = 5;
 658                 break;
 659 
 660         case 24:                
 661                 var->red.offset = 16;
 662                 var->red.length = 8;
 663                 var->green.offset = 8;
 664                 var->green.length = 8;
 665                 var->blue.offset = 0;
 666                 var->blue.length = 8;
 667                 break;
 668 
 669 #ifdef NO_32BIT_SUPPORT_YET
 670         case 32:                
 671                 var->transp.offset = 24;
 672                 var->transp.length = 8;
 673                 var->red.offset = 16;
 674                 var->red.length = 8;
 675                 var->green.offset = 8;
 676                 var->green.length = 8;
 677                 var->blue.offset = 0;
 678                 var->blue.length = 8;
 679                 break;
 680 #endif
 681         default:
 682                 printk(KERN_WARNING "neofb: no support for %dbpp\n",
 683                        var->bits_per_pixel);
 684                 return -EINVAL;
 685         }
 686 
 687         vramlen = info->fix.smem_len;
 688         if (vramlen > 4 * 1024 * 1024)
 689                 vramlen = 4 * 1024 * 1024;
 690 
 691         if (var->xres_virtual < var->xres)
 692                 var->xres_virtual = var->xres;
 693 
 694         memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual >> 3;
 695 
 696         if (memlen > vramlen) {
 697                 var->yres_virtual =  vramlen * 8 / (var->xres_virtual *
 698                                         var->bits_per_pixel);
 699                 memlen = var->xres_virtual * var->bits_per_pixel *
 700                                 var->yres_virtual / 8;
 701         }
 702 
 703         
 704 
 705         if (var->yres_virtual < var->yres)
 706                 var->yres = var->yres_virtual;
 707         if (var->xoffset + var->xres > var->xres_virtual)
 708                 var->xoffset = var->xres_virtual - var->xres;
 709         if (var->yoffset + var->yres > var->yres_virtual)
 710                 var->yoffset = var->yres_virtual - var->yres;
 711 
 712         var->nonstd = 0;
 713         var->height = -1;
 714         var->width = -1;
 715 
 716         if (var->bits_per_pixel >= 24 || !par->neo2200)
 717                 var->accel_flags &= ~FB_ACCELF_TEXT;
 718         return 0;
 719 }
 720 
 721 static int neofb_set_par(struct fb_info *info)
 722 {
 723         struct neofb_par *par = info->par;
 724         unsigned char temp;
 725         int i, clock_hi = 0;
 726         int lcd_stretch;
 727         int hoffset, voffset;
 728         int vsync_start, vtotal;
 729 
 730         DBG("neofb_set_par");
 731 
 732         neoUnlock();
 733 
 734         vgaHWProtect(1);        
 735 
 736         vsync_start = info->var.yres + info->var.lower_margin;
 737         vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;
 738 
 739         
 740 
 741 
 742 
 743 
 744         if (vgaHWInit(&info->var, par))
 745                 return -EINVAL;
 746 
 747         
 748 
 749 
 750 
 751         par->Attribute[16] = 0x01;
 752 
 753         switch (info->var.bits_per_pixel) {
 754         case 8:
 755                 par->CRTC[0x13] = info->var.xres_virtual >> 3;
 756                 par->ExtCRTOffset = info->var.xres_virtual >> 11;
 757                 par->ExtColorModeSelect = 0x11;
 758                 break;
 759         case 16:
 760                 par->CRTC[0x13] = info->var.xres_virtual >> 2;
 761                 par->ExtCRTOffset = info->var.xres_virtual >> 10;
 762                 par->ExtColorModeSelect = 0x13;
 763                 break;
 764         case 24:
 765                 par->CRTC[0x13] = (info->var.xres_virtual * 3) >> 3;
 766                 par->ExtCRTOffset = (info->var.xres_virtual * 3) >> 11;
 767                 par->ExtColorModeSelect = 0x14;
 768                 break;
 769 #ifdef NO_32BIT_SUPPORT_YET
 770         case 32:                
 771                 par->CRTC[0x13] = info->var.xres_virtual >> 1;
 772                 par->ExtCRTOffset = info->var.xres_virtual >> 9;
 773                 par->ExtColorModeSelect = 0x15;
 774                 break;
 775 #endif
 776         default:
 777                 break;
 778         }
 779 
 780         par->ExtCRTDispAddr = 0x10;
 781 
 782         
 783         par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
 784             | (((info->var.yres - 1) & 0x400) >> 9)
 785             | (((vsync_start) & 0x400) >> 8)
 786             | (((vsync_start) & 0x400) >> 7);
 787 
 788         
 789         if (par->pci_burst)
 790                 par->SysIfaceCntl1 = 0x30;
 791         else
 792                 par->SysIfaceCntl1 = 0x00;
 793 
 794         par->SysIfaceCntl2 = 0xc0;      
 795 
 796         
 797         par->PanelDispCntlRegRead = 1;
 798 
 799         
 800         par->PanelDispCntlReg1 = 0x00;
 801         if (par->internal_display)
 802                 par->PanelDispCntlReg1 |= 0x02;
 803         if (par->external_display)
 804                 par->PanelDispCntlReg1 |= 0x01;
 805 
 806         
 807         if (par->PanelDispCntlReg1 == 0x00) {
 808                 
 809                 par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
 810         }
 811 
 812         
 813         switch (info->var.xres) {
 814         case 1280:
 815                 par->PanelDispCntlReg1 |= 0x60;
 816                 break;
 817         case 1024:
 818                 par->PanelDispCntlReg1 |= 0x40;
 819                 break;
 820         case 800:
 821                 par->PanelDispCntlReg1 |= 0x20;
 822                 break;
 823         case 640:
 824         default:
 825                 break;
 826         }
 827 
 828         
 829         switch (par->PanelDispCntlReg1 & 0x03) {
 830         case 0x01:              
 831                 par->GeneralLockReg = 0x00;
 832                 
 833                 par->ProgramVCLK = 1;
 834                 break;
 835         case 0x02:              
 836         case 0x03:              
 837                 par->GeneralLockReg = 0x01;
 838                 
 839                 par->ProgramVCLK = 0;
 840                 break;
 841         }
 842 
 843         
 844 
 845 
 846 
 847 
 848 
 849         par->PanelDispCntlReg2 = 0x00;
 850         par->PanelDispCntlReg3 = 0x00;
 851 
 852         if (par->lcd_stretch && (par->PanelDispCntlReg1 == 0x02) &&     
 853             (info->var.xres != par->NeoPanelWidth)) {
 854                 switch (info->var.xres) {
 855                 case 320:       
 856                 case 400:       
 857                 case 640:
 858                 case 800:
 859                 case 1024:
 860                         lcd_stretch = 1;
 861                         par->PanelDispCntlReg2 |= 0xC6;
 862                         break;
 863                 default:
 864                         lcd_stretch = 0;
 865                         
 866                 }
 867         } else
 868                 lcd_stretch = 0;
 869 
 870         
 871 
 872 
 873 
 874         par->PanelVertCenterReg1 = 0x00;
 875         par->PanelVertCenterReg2 = 0x00;
 876         par->PanelVertCenterReg3 = 0x00;
 877         par->PanelVertCenterReg4 = 0x00;
 878         par->PanelVertCenterReg5 = 0x00;
 879         par->PanelHorizCenterReg1 = 0x00;
 880         par->PanelHorizCenterReg2 = 0x00;
 881         par->PanelHorizCenterReg3 = 0x00;
 882         par->PanelHorizCenterReg4 = 0x00;
 883         par->PanelHorizCenterReg5 = 0x00;
 884 
 885 
 886         if (par->PanelDispCntlReg1 & 0x02) {
 887                 if (info->var.xres == par->NeoPanelWidth) {
 888                         
 889 
 890 
 891 
 892                 } else {
 893                         par->PanelDispCntlReg2 |= 0x01;
 894                         par->PanelDispCntlReg3 |= 0x10;
 895 
 896                         
 897                         if (!lcd_stretch) {
 898                                 hoffset =
 899                                     ((par->NeoPanelWidth -
 900                                       info->var.xres) >> 4) - 1;
 901                                 voffset =
 902                                     ((par->NeoPanelHeight -
 903                                       info->var.yres) >> 1) - 2;
 904                         } else {
 905                                 
 906                                 hoffset = 0;
 907                                 voffset = 0;
 908                         }
 909 
 910                         switch (info->var.xres) {
 911                         case 320:       
 912                                 par->PanelHorizCenterReg3 = hoffset;
 913                                 par->PanelVertCenterReg2 = voffset;
 914                                 break;
 915                         case 400:       
 916                                 par->PanelHorizCenterReg4 = hoffset;
 917                                 par->PanelVertCenterReg1 = voffset;
 918                                 break;
 919                         case 640:
 920                                 par->PanelHorizCenterReg1 = hoffset;
 921                                 par->PanelVertCenterReg3 = voffset;
 922                                 break;
 923                         case 800:
 924                                 par->PanelHorizCenterReg2 = hoffset;
 925                                 par->PanelVertCenterReg4 = voffset;
 926                                 break;
 927                         case 1024:
 928                                 par->PanelHorizCenterReg5 = hoffset;
 929                                 par->PanelVertCenterReg5 = voffset;
 930                                 break;
 931                         case 1280:
 932                         default:
 933                                 
 934                                 break;
 935                         }
 936                 }
 937         }
 938 
 939         par->biosMode =
 940             neoFindMode(info->var.xres, info->var.yres,
 941                         info->var.bits_per_pixel);
 942 
 943         
 944 
 945 
 946 
 947         neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));
 948 
 949         
 950         par->MiscOutReg |= 0x0C;
 951 
 952         
 953         
 954 
 955         
 956         vga_wgfx(NULL, 0x15, 0x00);
 957 
 958         
 959         vga_wgfx(NULL, 0x0A, par->GeneralLockReg);
 960 
 961         
 962 
 963 
 964 
 965 
 966 
 967 
 968         temp = vga_rgfx(NULL, 0x90);
 969         switch (info->fix.accel) {
 970         case FB_ACCEL_NEOMAGIC_NM2070:
 971                 temp &= 0xF0;   
 972                 temp |= (par->ExtColorModeSelect & ~0xF0);
 973                 break;
 974         case FB_ACCEL_NEOMAGIC_NM2090:
 975         case FB_ACCEL_NEOMAGIC_NM2093:
 976         case FB_ACCEL_NEOMAGIC_NM2097:
 977         case FB_ACCEL_NEOMAGIC_NM2160:
 978         case FB_ACCEL_NEOMAGIC_NM2200:
 979         case FB_ACCEL_NEOMAGIC_NM2230:
 980         case FB_ACCEL_NEOMAGIC_NM2360:
 981         case FB_ACCEL_NEOMAGIC_NM2380:
 982                 temp &= 0x70;   
 983                 temp |= (par->ExtColorModeSelect & ~0x70);
 984                 break;
 985         }
 986 
 987         vga_wgfx(NULL, 0x90, temp);
 988 
 989         
 990 
 991 
 992 
 993         
 994 
 995         
 996 
 997 
 998 
 999         temp = vga_rgfx(NULL, 0x25);
1000         temp &= 0x39;
1001         vga_wgfx(NULL, 0x25, temp);
1002 
1003         
1004 
1005 
1006 
1007         mdelay(200);
1008 
1009         
1010 
1011         vgaHWRestore(info, par);
1012 
1013         
1014         switch (info->var.bits_per_pixel) {
1015         case 8:
1016                 
1017                 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
1018                 break;
1019         case 16:
1020                 
1021                 info->fix.visual = FB_VISUAL_TRUECOLOR;
1022 
1023                 for (i = 0; i < 64; i++) {
1024                         outb(i, 0x3c8);
1025 
1026                         outb(i << 1, 0x3c9);
1027                         outb(i, 0x3c9);
1028                         outb(i << 1, 0x3c9);
1029                 }
1030                 break;
1031         case 24:
1032 #ifdef NO_32BIT_SUPPORT_YET
1033         case 32:
1034 #endif
1035                 
1036                 info->fix.visual = FB_VISUAL_TRUECOLOR;
1037 
1038                 for (i = 0; i < 256; i++) {
1039                         outb(i, 0x3c8);
1040 
1041                         outb(i, 0x3c9);
1042                         outb(i, 0x3c9);
1043                         outb(i, 0x3c9);
1044                 }
1045                 break;
1046         }
1047 
1048         vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr);
1049         vga_wgfx(NULL, 0x0F, par->ExtCRTOffset);
1050         temp = vga_rgfx(NULL, 0x10);
1051         temp &= 0x0F;           
1052         temp |= (par->SysIfaceCntl1 & ~0x0F);   
1053         vga_wgfx(NULL, 0x10, temp);
1054 
1055         vga_wgfx(NULL, 0x11, par->SysIfaceCntl2);
1056         vga_wgfx(NULL, 0x15, 0  );
1057         vga_wgfx(NULL, 0x16, 0  );
1058 
1059         temp = vga_rgfx(NULL, 0x20);
1060         switch (info->fix.accel) {
1061         case FB_ACCEL_NEOMAGIC_NM2070:
1062                 temp &= 0xFC;   
1063                 temp |= (par->PanelDispCntlReg1 & ~0xFC);
1064                 break;
1065         case FB_ACCEL_NEOMAGIC_NM2090:
1066         case FB_ACCEL_NEOMAGIC_NM2093:
1067         case FB_ACCEL_NEOMAGIC_NM2097:
1068         case FB_ACCEL_NEOMAGIC_NM2160:
1069                 temp &= 0xDC;   
1070                 temp |= (par->PanelDispCntlReg1 & ~0xDC);
1071                 break;
1072         case FB_ACCEL_NEOMAGIC_NM2200:
1073         case FB_ACCEL_NEOMAGIC_NM2230:
1074         case FB_ACCEL_NEOMAGIC_NM2360:
1075         case FB_ACCEL_NEOMAGIC_NM2380:
1076                 temp &= 0x98;   
1077                 temp |= (par->PanelDispCntlReg1 & ~0x98);
1078                 break;
1079         }
1080         vga_wgfx(NULL, 0x20, temp);
1081 
1082         temp = vga_rgfx(NULL, 0x25);
1083         temp &= 0x38;           
1084         temp |= (par->PanelDispCntlReg2 & ~0x38);
1085         vga_wgfx(NULL, 0x25, temp);
1086 
1087         if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
1088                 temp = vga_rgfx(NULL, 0x30);
1089                 temp &= 0xEF;   
1090                 temp |= (par->PanelDispCntlReg3 & ~0xEF);
1091                 vga_wgfx(NULL, 0x30, temp);
1092         }
1093 
1094         vga_wgfx(NULL, 0x28, par->PanelVertCenterReg1);
1095         vga_wgfx(NULL, 0x29, par->PanelVertCenterReg2);
1096         vga_wgfx(NULL, 0x2a, par->PanelVertCenterReg3);
1097 
1098         if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
1099                 vga_wgfx(NULL, 0x32, par->PanelVertCenterReg4);
1100                 vga_wgfx(NULL, 0x33, par->PanelHorizCenterReg1);
1101                 vga_wgfx(NULL, 0x34, par->PanelHorizCenterReg2);
1102                 vga_wgfx(NULL, 0x35, par->PanelHorizCenterReg3);
1103         }
1104 
1105         if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2160)
1106                 vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
1107 
1108         if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
1109             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
1110             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
1111             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
1112                 vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
1113                 vga_wgfx(NULL, 0x37, par->PanelVertCenterReg5);
1114                 vga_wgfx(NULL, 0x38, par->PanelHorizCenterReg5);
1115 
1116                 clock_hi = 1;
1117         }
1118 
1119         
1120         if (par->ProgramVCLK && ((vga_rgfx(NULL, 0x9B) != par->VCLK3NumeratorLow)
1121                                  || (vga_rgfx(NULL, 0x9F) != par->VCLK3Denominator)
1122                                  || (clock_hi && ((vga_rgfx(NULL, 0x8F) & ~0x0f)
1123                                                   != (par->VCLK3NumeratorHigh &
1124                                                       ~0x0F))))) {
1125                 vga_wgfx(NULL, 0x9B, par->VCLK3NumeratorLow);
1126                 if (clock_hi) {
1127                         temp = vga_rgfx(NULL, 0x8F);
1128                         temp &= 0x0F;   
1129                         temp |= (par->VCLK3NumeratorHigh & ~0x0F);
1130                         vga_wgfx(NULL, 0x8F, temp);
1131                 }
1132                 vga_wgfx(NULL, 0x9F, par->VCLK3Denominator);
1133         }
1134 
1135         if (par->biosMode)
1136                 vga_wcrt(NULL, 0x23, par->biosMode);
1137 
1138         vga_wgfx(NULL, 0x93, 0xc0);     
1139 
1140         
1141         if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
1142             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
1143             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
1144             info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
1145                 vga_wcrt(NULL, 0x70, par->VerticalExt);
1146         }
1147 
1148         vgaHWProtect(0);        
1149 
1150         
1151         neoLock(&par->state);
1152 
1153         info->fix.line_length =
1154             info->var.xres_virtual * (info->var.bits_per_pixel >> 3);
1155 
1156         switch (info->fix.accel) {
1157                 case FB_ACCEL_NEOMAGIC_NM2200:
1158                 case FB_ACCEL_NEOMAGIC_NM2230: 
1159                 case FB_ACCEL_NEOMAGIC_NM2360: 
1160                 case FB_ACCEL_NEOMAGIC_NM2380: 
1161                         neo2200_accel_init(info, &info->var);
1162                         break;
1163                 default:
1164                         break;
1165         }       
1166         return 0;
1167 }
1168 
1169 
1170 
1171 
1172 static int neofb_pan_display(struct fb_var_screeninfo *var,
1173                              struct fb_info *info)
1174 {
1175         struct neofb_par *par = info->par;
1176         struct vgastate *state = &par->state;
1177         int oldExtCRTDispAddr;
1178         int Base;
1179 
1180         DBG("neofb_update_start");
1181 
1182         Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2;
1183         Base *= (info->var.bits_per_pixel + 7) / 8;
1184 
1185         neoUnlock();
1186 
1187         
1188 
1189 
1190         vga_wcrt(state->vgabase, 0x0C, (Base & 0x00FF00) >> 8);
1191         vga_wcrt(state->vgabase, 0x0D, (Base & 0x00FF));
1192 
1193         
1194 
1195 
1196 
1197 
1198         oldExtCRTDispAddr = vga_rgfx(NULL, 0x0E);
1199         vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
1200 
1201         neoLock(state);
1202 
1203         return 0;
1204 }
1205 
1206 static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1207                            u_int transp, struct fb_info *fb)
1208 {
1209         if (regno >= fb->cmap.len || regno > 255)
1210                 return -EINVAL;
1211 
1212         if (fb->var.bits_per_pixel <= 8) {
1213                 outb(regno, 0x3c8);
1214 
1215                 outb(red >> 10, 0x3c9);
1216                 outb(green >> 10, 0x3c9);
1217                 outb(blue >> 10, 0x3c9);
1218         } else if (regno < 16) {
1219                 switch (fb->var.bits_per_pixel) {
1220                 case 16:
1221                         ((u32 *) fb->pseudo_palette)[regno] =
1222                                 ((red & 0xf800)) | ((green & 0xfc00) >> 5) |
1223                                 ((blue & 0xf800) >> 11);
1224                         break;
1225                 case 24:
1226                         ((u32 *) fb->pseudo_palette)[regno] =
1227                                 ((red & 0xff00) << 8) | ((green & 0xff00)) |
1228                                 ((blue & 0xff00) >> 8);
1229                         break;
1230 #ifdef NO_32BIT_SUPPORT_YET
1231                 case 32:
1232                         ((u32 *) fb->pseudo_palette)[regno] =
1233                                 ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
1234                                 ((green & 0xff00)) | ((blue & 0xff00) >> 8);
1235                         break;
1236 #endif
1237                 default:
1238                         return 1;
1239                 }
1240         }
1241 
1242         return 0;
1243 }
1244 
1245 
1246 
1247 
1248 static int neofb_blank(int blank_mode, struct fb_info *info)
1249 {
1250         
1251 
1252 
1253 
1254 
1255 
1256 
1257 
1258 
1259 
1260 
1261 
1262 
1263 
1264         struct neofb_par *par = info->par;
1265         int seqflags, lcdflags, dpmsflags, reg, tmpdisp;
1266 
1267         
1268 
1269 
1270 
1271         neoUnlock();
1272         tmpdisp = vga_rgfx(NULL, 0x20) & 0x03;
1273         neoLock(&par->state);
1274 
1275         
1276 
1277 
1278 
1279         if (par->PanelDispCntlRegRead) {
1280                 par->PanelDispCntlReg1 = tmpdisp;
1281         }
1282         par->PanelDispCntlRegRead = !blank_mode;
1283 
1284         switch (blank_mode) {
1285         case FB_BLANK_POWERDOWN:        
1286                 seqflags = VGA_SR01_SCREEN_OFF; 
1287                 lcdflags = 0;                   
1288                 dpmsflags = NEO_GR01_SUPPRESS_HSYNC |
1289                             NEO_GR01_SUPPRESS_VSYNC;
1290 #ifdef CONFIG_TOSHIBA
1291                 
1292                 
1293                 {
1294                         SMMRegisters regs;
1295 
1296                         regs.eax = 0xff00; 
1297                         regs.ebx = 0x0002; 
1298                         regs.ecx = 0x0000; 
1299                         tosh_smm(®s);
1300                 }
1301 #endif
1302                 break;
1303         case FB_BLANK_HSYNC_SUSPEND:            
1304                 seqflags = VGA_SR01_SCREEN_OFF; 
1305                 lcdflags = 0;                   
1306                 dpmsflags = NEO_GR01_SUPPRESS_HSYNC;
1307                 break;
1308         case FB_BLANK_VSYNC_SUSPEND:            
1309                 seqflags = VGA_SR01_SCREEN_OFF; 
1310                 lcdflags = 0;                   
1311                 dpmsflags = NEO_GR01_SUPPRESS_VSYNC;
1312                 break;
1313         case FB_BLANK_NORMAL:           
1314                 seqflags = VGA_SR01_SCREEN_OFF; 
1315                 
1316 
1317 
1318 
1319 
1320 
1321 
1322 
1323 
1324                 lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); 
1325                 dpmsflags = 0x00;       
1326                 break;
1327         case FB_BLANK_UNBLANK:          
1328                 seqflags = 0;                   
1329                 lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); 
1330                 dpmsflags = 0x00;       
1331 #ifdef CONFIG_TOSHIBA
1332                 
1333                 
1334                 {
1335                         SMMRegisters regs;
1336 
1337                         regs.eax = 0xff00; 
1338                         regs.ebx = 0x0002; 
1339                         regs.ecx = 0x0001; 
1340                         tosh_smm(®s);
1341                 }
1342 #endif
1343                 break;
1344         default:        
1345 
1346                 return 1;
1347         }
1348 
1349         neoUnlock();
1350         reg = (vga_rseq(NULL, 0x01) & ~0x20) | seqflags;
1351         vga_wseq(NULL, 0x01, reg);
1352         reg = (vga_rgfx(NULL, 0x20) & ~0x02) | lcdflags;
1353         vga_wgfx(NULL, 0x20, reg);
1354         reg = (vga_rgfx(NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags;
1355         vga_wgfx(NULL, 0x01, reg);
1356         neoLock(&par->state);
1357         return 0;
1358 }
1359 
1360 static void
1361 neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
1362 {
1363         struct neofb_par *par = info->par;
1364         u_long dst, rop;
1365 
1366         dst = rect->dx + rect->dy * info->var.xres_virtual;
1367         rop = rect->rop ? 0x060000 : 0x0c0000;
1368 
1369         neo2200_wait_fifo(info, 4);
1370 
1371         
1372         writel(NEO_BC3_FIFO_EN |
1373                NEO_BC0_SRC_IS_FG | NEO_BC3_SKIP_MAPPING |
1374                
1375                
1376                rop, &par->neo2200->bltCntl);
1377 
1378         switch (info->var.bits_per_pixel) {
1379         case 8:
1380                 writel(rect->color, &par->neo2200->fgColor);
1381                 break;
1382         case 16:
1383         case 24:
1384                 writel(((u32 *) (info->pseudo_palette))[rect->color],
1385                        &par->neo2200->fgColor);
1386                 break;
1387         }
1388 
1389         writel(dst * ((info->var.bits_per_pixel + 7) >> 3),
1390                &par->neo2200->dstStart);
1391         writel((rect->height << 16) | (rect->width & 0xffff),
1392                &par->neo2200->xyExt);
1393 }
1394 
1395 static void
1396 neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1397 {
1398         u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
1399         struct neofb_par *par = info->par;
1400         u_long src, dst, bltCntl;
1401 
1402         bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
1403 
1404         if ((dy > sy) || ((dy == sy) && (dx > sx))) {
1405                 
1406                 sy += (area->height - 1);
1407                 dy += (area->height - 1);
1408                 sx += (area->width - 1);
1409                 dx += (area->width - 1);
1410 
1411                 bltCntl |= NEO_BC0_X_DEC | NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC;
1412         }
1413 
1414         src = sx * (info->var.bits_per_pixel >> 3) + sy*info->fix.line_length;
1415         dst = dx * (info->var.bits_per_pixel >> 3) + dy*info->fix.line_length;
1416 
1417         neo2200_wait_fifo(info, 4);
1418 
1419         
1420         writel(bltCntl, &par->neo2200->bltCntl);
1421 
1422         writel(src, &par->neo2200->srcStart);
1423         writel(dst, &par->neo2200->dstStart);
1424         writel((area->height << 16) | (area->width & 0xffff),
1425                &par->neo2200->xyExt);
1426 }
1427 
1428 static void
1429 neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
1430 {
1431         struct neofb_par *par = info->par;
1432         int s_pitch = (image->width * image->depth + 7) >> 3;
1433         int scan_align = info->pixmap.scan_align - 1;
1434         int buf_align = info->pixmap.buf_align - 1;
1435         int bltCntl_flags, d_pitch, data_len;
1436 
1437         
1438         d_pitch = (s_pitch + scan_align) & ~scan_align;
1439         data_len = ((d_pitch * image->height) + buf_align) & ~buf_align;
1440 
1441         neo2200_sync(info);
1442 
1443         if (image->depth == 1) {
1444                 if (info->var.bits_per_pixel == 24 && image->width < 16) {
1445                         
1446 
1447 
1448 
1449 
1450                         cfb_imageblit(info, image);
1451                         return;
1452                 }
1453                 bltCntl_flags = NEO_BC0_SRC_MONO;
1454         } else if (image->depth == info->var.bits_per_pixel) {
1455                 bltCntl_flags = 0;
1456         } else {
1457                 
1458 
1459                 cfb_imageblit(info, image);
1460                 return;
1461         }
1462 
1463         switch (info->var.bits_per_pixel) {
1464         case 8:
1465                 writel(image->fg_color, &par->neo2200->fgColor);
1466                 writel(image->bg_color, &par->neo2200->bgColor);
1467                 break;
1468         case 16:
1469         case 24:
1470                 writel(((u32 *) (info->pseudo_palette))[image->fg_color],
1471                        &par->neo2200->fgColor);
1472                 writel(((u32 *) (info->pseudo_palette))[image->bg_color],
1473                        &par->neo2200->bgColor);
1474                 break;
1475         }
1476 
1477         writel(NEO_BC0_SYS_TO_VID |
1478                 NEO_BC3_SKIP_MAPPING | bltCntl_flags |
1479                 
1480                 0x0c0000, &par->neo2200->bltCntl);
1481 
1482         writel(0, &par->neo2200->srcStart);
1483 
1484         writel(((image->dx & 0xffff) * (info->var.bits_per_pixel >> 3) +
1485                 image->dy * info->fix.line_length), &par->neo2200->dstStart);
1486         writel((image->height << 16) | (image->width & 0xffff),
1487                &par->neo2200->xyExt);
1488 
1489         memcpy_toio(par->mmio_vbase + 0x100000, image->data, data_len);
1490 }
1491 
1492 static void
1493 neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
1494 {
1495         switch (info->fix.accel) {
1496                 case FB_ACCEL_NEOMAGIC_NM2200:
1497                 case FB_ACCEL_NEOMAGIC_NM2230: 
1498                 case FB_ACCEL_NEOMAGIC_NM2360: 
1499                 case FB_ACCEL_NEOMAGIC_NM2380:
1500                         neo2200_fillrect(info, rect);
1501                         break;
1502                 default:
1503                         cfb_fillrect(info, rect);
1504                         break;
1505         }       
1506 }
1507 
1508 static void
1509 neofb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
1510 {
1511         switch (info->fix.accel) {
1512                 case FB_ACCEL_NEOMAGIC_NM2200:
1513                 case FB_ACCEL_NEOMAGIC_NM2230: 
1514                 case FB_ACCEL_NEOMAGIC_NM2360: 
1515                 case FB_ACCEL_NEOMAGIC_NM2380: 
1516                         neo2200_copyarea(info, area);
1517                         break;
1518                 default:
1519                         cfb_copyarea(info, area);
1520                         break;
1521         }       
1522 }
1523 
1524 static void
1525 neofb_imageblit(struct fb_info *info, const struct fb_image *image)
1526 {
1527         switch (info->fix.accel) {
1528                 case FB_ACCEL_NEOMAGIC_NM2200:
1529                 case FB_ACCEL_NEOMAGIC_NM2230:
1530                 case FB_ACCEL_NEOMAGIC_NM2360:
1531                 case FB_ACCEL_NEOMAGIC_NM2380:
1532                         neo2200_imageblit(info, image);
1533                         break;
1534                 default:
1535                         cfb_imageblit(info, image);
1536                         break;
1537         }
1538 }
1539 
1540 static int 
1541 neofb_sync(struct fb_info *info)
1542 {
1543         switch (info->fix.accel) {
1544                 case FB_ACCEL_NEOMAGIC_NM2200:
1545                 case FB_ACCEL_NEOMAGIC_NM2230: 
1546                 case FB_ACCEL_NEOMAGIC_NM2360: 
1547                 case FB_ACCEL_NEOMAGIC_NM2380: 
1548                         neo2200_sync(info);
1549                         break;
1550                 default:
1551                         break;
1552         }
1553         return 0;               
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 
1613 static struct fb_ops neofb_ops = {
1614         .owner          = THIS_MODULE,
1615         .fb_open        = neofb_open,
1616         .fb_release     = neofb_release,
1617         .fb_check_var   = neofb_check_var,
1618         .fb_set_par     = neofb_set_par,
1619         .fb_setcolreg   = neofb_setcolreg,
1620         .fb_pan_display = neofb_pan_display,
1621         .fb_blank       = neofb_blank,
1622         .fb_sync        = neofb_sync,
1623         .fb_fillrect    = neofb_fillrect,
1624         .fb_copyarea    = neofb_copyarea,
1625         .fb_imageblit   = neofb_imageblit,
1626 };
1627 
1628 
1629 
1630 static struct fb_videomode mode800x480 = {
1631         .xres           = 800,
1632         .yres           = 480,
1633         .pixclock       = 25000,
1634         .left_margin    = 88,
1635         .right_margin   = 40,
1636         .upper_margin   = 23,
1637         .lower_margin   = 1,
1638         .hsync_len      = 128,
1639         .vsync_len      = 4,
1640         .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
1641         .vmode          = FB_VMODE_NONINTERLACED
1642 };
1643 
1644 static int neo_map_mmio(struct fb_info *info, struct pci_dev *dev)
1645 {
1646         struct neofb_par *par = info->par;
1647 
1648         DBG("neo_map_mmio");
1649 
1650         switch (info->fix.accel) {
1651                 case FB_ACCEL_NEOMAGIC_NM2070:
1652                         info->fix.mmio_start = pci_resource_start(dev, 0)+
1653                                 0x100000;
1654                         break;
1655                 case FB_ACCEL_NEOMAGIC_NM2090:
1656                 case FB_ACCEL_NEOMAGIC_NM2093:
1657                         info->fix.mmio_start = pci_resource_start(dev, 0)+
1658                                 0x200000;
1659                         break;
1660                 case FB_ACCEL_NEOMAGIC_NM2160:
1661                 case FB_ACCEL_NEOMAGIC_NM2097:
1662                 case FB_ACCEL_NEOMAGIC_NM2200:
1663                 case FB_ACCEL_NEOMAGIC_NM2230:
1664                 case FB_ACCEL_NEOMAGIC_NM2360:
1665                 case FB_ACCEL_NEOMAGIC_NM2380:
1666                         info->fix.mmio_start = pci_resource_start(dev, 1);
1667                         break;
1668                 default:
1669                         info->fix.mmio_start = pci_resource_start(dev, 0);
1670         }
1671         info->fix.mmio_len = MMIO_SIZE;
1672 
1673         if (!request_mem_region
1674             (info->fix.mmio_start, MMIO_SIZE, "memory mapped I/O")) {
1675                 printk("neofb: memory mapped IO in use\n");
1676                 return -EBUSY;
1677         }
1678 
1679         par->mmio_vbase = ioremap(info->fix.mmio_start, MMIO_SIZE);
1680         if (!par->mmio_vbase) {
1681                 printk("neofb: unable to map memory mapped IO\n");
1682                 release_mem_region(info->fix.mmio_start,
1683                                    info->fix.mmio_len);
1684                 return -ENOMEM;
1685         } else
1686                 printk(KERN_INFO "neofb: mapped io at %p\n",
1687                        par->mmio_vbase);
1688         return 0;
1689 }
1690 
1691 static void neo_unmap_mmio(struct fb_info *info)
1692 {
1693         struct neofb_par *par = info->par;
1694 
1695         DBG("neo_unmap_mmio");
1696 
1697         iounmap(par->mmio_vbase);
1698         par->mmio_vbase = NULL;
1699 
1700         release_mem_region(info->fix.mmio_start,
1701                            info->fix.mmio_len);
1702 }
1703 
1704 static int neo_map_video(struct fb_info *info, struct pci_dev *dev,
1705                          int video_len)
1706 {
1707         
1708         struct neofb_par *par = info->par;
1709 
1710         DBG("neo_map_video");
1711 
1712         info->fix.smem_start = pci_resource_start(dev, 0);
1713         info->fix.smem_len = video_len;
1714 
1715         if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
1716                                 "frame buffer")) {
1717                 printk("neofb: frame buffer in use\n");
1718                 return -EBUSY;
1719         }
1720 
1721         info->screen_base =
1722             ioremap_wc(info->fix.smem_start, info->fix.smem_len);
1723         if (!info->screen_base) {
1724                 printk("neofb: unable to map screen memory\n");
1725                 release_mem_region(info->fix.smem_start,
1726                                    info->fix.smem_len);
1727                 return -ENOMEM;
1728         } else
1729                 printk(KERN_INFO "neofb: mapped framebuffer at %p\n",
1730                        info->screen_base);
1731 
1732         par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
1733                                           pci_resource_len(dev, 0));
1734 
1735         
1736         memset_io(info->screen_base, 0, info->fix.smem_len);
1737 
1738         
1739 
1740 
1741 
1742 
1743 
1744 
1745         return 0;
1746 }
1747 
1748 static void neo_unmap_video(struct fb_info *info)
1749 {
1750         struct neofb_par *par = info->par;
1751 
1752         DBG("neo_unmap_video");
1753 
1754         arch_phys_wc_del(par->wc_cookie);
1755         iounmap(info->screen_base);
1756         info->screen_base = NULL;
1757 
1758         release_mem_region(info->fix.smem_start,
1759                            info->fix.smem_len);
1760 }
1761 
1762 static int neo_scan_monitor(struct fb_info *info)
1763 {
1764         struct neofb_par *par = info->par;
1765         unsigned char type, display;
1766         int w;
1767 
1768         
1769         info->monspecs.modedb = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);
1770         if (!info->monspecs.modedb)
1771                 return -ENOMEM;
1772         info->monspecs.modedb_len = 1;
1773 
1774         
1775         vga_wgfx(NULL, 0x09, 0x26);
1776         type = vga_rgfx(NULL, 0x21);
1777         display = vga_rgfx(NULL, 0x20);
1778         if (!par->internal_display && !par->external_display) {
1779                 par->internal_display = display & 2 || !(display & 3) ? 1 : 0;
1780                 par->external_display = display & 1;
1781                 printk (KERN_INFO "Autodetected %s display\n",
1782                         par->internal_display && par->external_display ? "simultaneous" :
1783                         par->internal_display ? "internal" : "external");
1784         }
1785 
1786         
1787         w = vga_rgfx(NULL, 0x20);
1788         vga_wgfx(NULL, 0x09, 0x00);
1789         switch ((w & 0x18) >> 3) {
1790         case 0x00:
1791                 
1792                 par->NeoPanelWidth = 640;
1793                 par->NeoPanelHeight = 480;
1794                 memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
1795                 break;
1796         case 0x01:
1797                 par->NeoPanelWidth = 800;
1798                 if (par->libretto) {
1799                         par->NeoPanelHeight = 480;
1800                         memcpy(info->monspecs.modedb, &mode800x480, sizeof(struct fb_videomode));
1801                 } else {
1802                         
1803                         par->NeoPanelHeight = 600;
1804                         memcpy(info->monspecs.modedb, &vesa_modes[8], sizeof(struct fb_videomode));
1805                 }
1806                 break;
1807         case 0x02:
1808                 
1809                 par->NeoPanelWidth = 1024;
1810                 par->NeoPanelHeight = 768;
1811                 memcpy(info->monspecs.modedb, &vesa_modes[13], sizeof(struct fb_videomode));
1812                 break;
1813         case 0x03:
1814                 
1815 #ifdef NOT_DONE
1816                 par->NeoPanelWidth = 1280;
1817                 par->NeoPanelHeight = 1024;
1818                 memcpy(info->monspecs.modedb, &vesa_modes[20], sizeof(struct fb_videomode));
1819                 break;
1820 #else
1821                 printk(KERN_ERR
1822                        "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n");
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 CursorMem = 1024;
1847         int CursorOff = 0x100;
1848 
1849         DBG("neo_init_hw");
1850 
1851         neoUnlock();
1852 
1853 #if 0
1854         printk(KERN_DEBUG "--- Neo extended register dump ---\n");
1855         for (int w = 0; w < 0x85; w++)
1856                 printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
1857                        (void *) vga_rcrt(NULL, w));
1858         for (int w = 0; w < 0xC7; w++)
1859                 printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
1860                        (void *) vga_rgfx(NULL, w));
1861 #endif
1862         switch (info->fix.accel) {
1863         case FB_ACCEL_NEOMAGIC_NM2070:
1864                 videoRam = 896;
1865                 maxClock = 65000;
1866                 break;
1867         case FB_ACCEL_NEOMAGIC_NM2090:
1868         case FB_ACCEL_NEOMAGIC_NM2093:
1869         case FB_ACCEL_NEOMAGIC_NM2097:
1870                 videoRam = 1152;
1871                 maxClock = 80000;
1872                 break;
1873         case FB_ACCEL_NEOMAGIC_NM2160:
1874                 videoRam = 2048;
1875                 maxClock = 90000;
1876                 break;
1877         case FB_ACCEL_NEOMAGIC_NM2200:
1878                 videoRam = 2560;
1879                 maxClock = 110000;
1880                 break;
1881         case FB_ACCEL_NEOMAGIC_NM2230:
1882                 videoRam = 3008;
1883                 maxClock = 110000;
1884                 break;
1885         case FB_ACCEL_NEOMAGIC_NM2360:
1886                 videoRam = 4096;
1887                 maxClock = 110000;
1888                 break;
1889         case FB_ACCEL_NEOMAGIC_NM2380:
1890                 videoRam = 6144;
1891                 maxClock = 110000;
1892                 break;
1893         }
1894         switch (info->fix.accel) {
1895         case FB_ACCEL_NEOMAGIC_NM2070:
1896         case FB_ACCEL_NEOMAGIC_NM2090:
1897         case FB_ACCEL_NEOMAGIC_NM2093:
1898                 CursorMem = 2048;
1899                 CursorOff = 0x100;
1900                 break;
1901         case FB_ACCEL_NEOMAGIC_NM2097:
1902         case FB_ACCEL_NEOMAGIC_NM2160:
1903                 CursorMem = 1024;
1904                 CursorOff = 0x100;
1905                 break;
1906         case FB_ACCEL_NEOMAGIC_NM2200:
1907         case FB_ACCEL_NEOMAGIC_NM2230:
1908         case FB_ACCEL_NEOMAGIC_NM2360:
1909         case FB_ACCEL_NEOMAGIC_NM2380:
1910                 CursorMem = 1024;
1911                 CursorOff = 0x1000;
1912 
1913                 par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
1914                 break;
1915         }
1916 
1917 
1918 
1919 
1920 
1921 
1922 
1923         par->maxClock = maxClock;
1924         par->cursorOff = CursorOff;
1925         return videoRam * 1024;
1926 }
1927 
1928 
1929 static struct fb_info *neo_alloc_fb_info(struct pci_dev *dev,
1930                                          const struct pci_device_id *id)
1931 {
1932         struct fb_info *info;
1933         struct neofb_par *par;
1934 
1935         info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);
1936 
1937         if (!info)
1938                 return NULL;
1939 
1940         par = info->par;
1941 
1942         info->fix.accel = id->driver_data;
1943 
1944         par->pci_burst = !nopciburst;
1945         par->lcd_stretch = !nostretch;
1946         par->libretto = libretto;
1947 
1948         par->internal_display = internal;
1949         par->external_display = external;
1950         info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1951 
1952         switch (info->fix.accel) {
1953         case FB_ACCEL_NEOMAGIC_NM2070:
1954                 snprintf(info->fix.id, sizeof(info->fix.id),
1955                                 "MagicGraph 128");
1956                 break;
1957         case FB_ACCEL_NEOMAGIC_NM2090:
1958                 snprintf(info->fix.id, sizeof(info->fix.id),
1959                                 "MagicGraph 128V");
1960                 break;
1961         case FB_ACCEL_NEOMAGIC_NM2093:
1962                 snprintf(info->fix.id, sizeof(info->fix.id),
1963                                 "MagicGraph 128ZV");
1964                 break;
1965         case FB_ACCEL_NEOMAGIC_NM2097:
1966                 snprintf(info->fix.id, sizeof(info->fix.id),
1967                                 "MagicGraph 128ZV+");
1968                 break;
1969         case FB_ACCEL_NEOMAGIC_NM2160:
1970                 snprintf(info->fix.id, sizeof(info->fix.id),
1971                                 "MagicGraph 128XD");
1972                 break;
1973         case FB_ACCEL_NEOMAGIC_NM2200:
1974                 snprintf(info->fix.id, sizeof(info->fix.id),
1975                                 "MagicGraph 256AV");
1976                 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
1977                                FBINFO_HWACCEL_COPYAREA |
1978                                FBINFO_HWACCEL_FILLRECT;
1979                 break;
1980         case FB_ACCEL_NEOMAGIC_NM2230:
1981                 snprintf(info->fix.id, sizeof(info->fix.id),
1982                                 "MagicGraph 256AV+");
1983                 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
1984                                FBINFO_HWACCEL_COPYAREA |
1985                                FBINFO_HWACCEL_FILLRECT;
1986                 break;
1987         case FB_ACCEL_NEOMAGIC_NM2360:
1988                 snprintf(info->fix.id, sizeof(info->fix.id),
1989                                 "MagicGraph 256ZX");
1990                 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
1991                                FBINFO_HWACCEL_COPYAREA |
1992                                FBINFO_HWACCEL_FILLRECT;
1993                 break;
1994         case FB_ACCEL_NEOMAGIC_NM2380:
1995                 snprintf(info->fix.id, sizeof(info->fix.id),
1996                                 "MagicGraph 256XL+");
1997                 info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
1998                                FBINFO_HWACCEL_COPYAREA |
1999                                FBINFO_HWACCEL_FILLRECT;
2000                 break;
2001         }
2002 
2003         info->fix.type = FB_TYPE_PACKED_PIXELS;
2004         info->fix.type_aux = 0;
2005         info->fix.xpanstep = 0;
2006         info->fix.ypanstep = 4;
2007         info->fix.ywrapstep = 0;
2008         info->fix.accel = id->driver_data;
2009 
2010         info->fbops = &neofb_ops;
2011         info->pseudo_palette = par->palette;
2012         return info;
2013 }
2014 
2015 static void neo_free_fb_info(struct fb_info *info)
2016 {
2017         if (info) {
2018                 
2019 
2020 
2021                 fb_dealloc_cmap(&info->cmap);
2022                 framebuffer_release(info);
2023         }
2024 }
2025 
2026 
2027 
2028 static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id)
2029 {
2030         struct fb_info *info;
2031         u_int h_sync, v_sync;
2032         int video_len, err;
2033 
2034         DBG("neofb_probe");
2035 
2036         err = pci_enable_device(dev);
2037         if (err)
2038                 return err;
2039 
2040         err = -ENOMEM;
2041         info = neo_alloc_fb_info(dev, id);
2042         if (!info)
2043                 return err;
2044 
2045         err = neo_map_mmio(info, dev);
2046         if (err)
2047                 goto err_map_mmio;
2048 
2049         err = neo_scan_monitor(info);
2050         if (err)
2051                 goto err_scan_monitor;
2052 
2053         video_len = neo_init_hw(info);
2054         if (video_len < 0) {
2055                 err = video_len;
2056                 goto err_init_hw;
2057         }
2058 
2059         err = neo_map_video(info, dev, video_len);
2060         if (err)
2061                 goto err_init_hw;
2062 
2063         if (!fb_find_mode(&info->var, info, mode_option, NULL, 0,
2064                         info->monspecs.modedb, 16)) {
2065                 printk(KERN_ERR "neofb: Unable to find usable video mode.\n");
2066                 err = -EINVAL;
2067                 goto err_map_video;
2068         }
2069 
2070         
2071 
2072 
2073 
2074 
2075 
2076         h_sync = 1953125000 / info->var.pixclock;
2077         h_sync =
2078             h_sync * 512 / (info->var.xres + info->var.left_margin +
2079                             info->var.right_margin + info->var.hsync_len);
2080         v_sync =
2081             h_sync / (info->var.yres + info->var.upper_margin +
2082                       info->var.lower_margin + info->var.vsync_len);
2083 
2084         printk(KERN_INFO "neofb v" NEOFB_VERSION
2085                ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
2086                info->fix.smem_len >> 10, info->var.xres,
2087                info->var.yres, h_sync / 1000, h_sync % 1000, v_sync);
2088 
2089         err = fb_alloc_cmap(&info->cmap, 256, 0);
2090         if (err < 0)
2091                 goto err_map_video;
2092 
2093         err = register_framebuffer(info);
2094         if (err < 0)
2095                 goto err_reg_fb;
2096 
2097         fb_info(info, "%s frame buffer device\n", info->fix.id);
2098 
2099         
2100 
2101 
2102         pci_set_drvdata(dev, info);
2103         return 0;
2104 
2105 err_reg_fb:
2106         fb_dealloc_cmap(&info->cmap);
2107 err_map_video:
2108         neo_unmap_video(info);
2109 err_init_hw:
2110         fb_destroy_modedb(info->monspecs.modedb);
2111 err_scan_monitor:
2112         neo_unmap_mmio(info);
2113 err_map_mmio:
2114         neo_free_fb_info(info);
2115         return err;
2116 }
2117 
2118 static void neofb_remove(struct pci_dev *dev)
2119 {
2120         struct fb_info *info = pci_get_drvdata(dev);
2121 
2122         DBG("neofb_remove");
2123 
2124         if (info) {
2125                 unregister_framebuffer(info);
2126 
2127                 neo_unmap_video(info);
2128                 fb_destroy_modedb(info->monspecs.modedb);
2129                 neo_unmap_mmio(info);
2130                 neo_free_fb_info(info);
2131         }
2132 }
2133 
2134 static const struct pci_device_id neofb_devices[] = {
2135         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070,
2136          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070},
2137 
2138         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090,
2139          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090},
2140 
2141         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093,
2142          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093},
2143 
2144         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097,
2145          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097},
2146 
2147         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160,
2148          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160},
2149 
2150         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200,
2151          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200},
2152 
2153         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230,
2154          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230},
2155 
2156         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360,
2157          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360},
2158 
2159         {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380,
2160          PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380},
2161 
2162         {0, 0, 0, 0, 0, 0, 0}
2163 };
2164 
2165 MODULE_DEVICE_TABLE(pci, neofb_devices);
2166 
2167 static struct pci_driver neofb_driver = {
2168         .name =         "neofb",
2169         .id_table =     neofb_devices,
2170         .probe =        neofb_probe,
2171         .remove =       neofb_remove,
2172 };
2173 
2174 
2175 
2176 #ifndef MODULE
2177 static int __init neofb_setup(char *options)
2178 {
2179         char *this_opt;
2180 
2181         DBG("neofb_setup");
2182 
2183         if (!options || !*options)
2184                 return 0;
2185 
2186         while ((this_opt = strsep(&options, ",")) != NULL) {
2187                 if (!*this_opt)
2188                         continue;
2189 
2190                 if (!strncmp(this_opt, "internal", 8))
2191                         internal = 1;
2192                 else if (!strncmp(this_opt, "external", 8))
2193                         external = 1;
2194                 else if (!strncmp(this_opt, "nostretch", 9))
2195                         nostretch = 1;
2196                 else if (!strncmp(this_opt, "nopciburst", 10))
2197                         nopciburst = 1;
2198                 else if (!strncmp(this_opt, "libretto", 8))
2199                         libretto = 1;
2200                 else
2201                         mode_option = this_opt;
2202         }
2203         return 0;
2204 }
2205 #endif  
2206 
2207 static int __init neofb_init(void)
2208 {
2209 #ifndef MODULE
2210         char *option = NULL;
2211 
2212         if (fb_get_options("neofb", &option))
2213                 return -ENODEV;
2214         neofb_setup(option);
2215 #endif
2216         return pci_register_driver(&neofb_driver);
2217 }
2218 
2219 module_init(neofb_init);
2220 
2221 #ifdef MODULE
2222 static void __exit neofb_exit(void)
2223 {
2224         pci_unregister_driver(&neofb_driver);
2225 }
2226 
2227 module_exit(neofb_exit);
2228 #endif