neofb.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:58k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver
  3.  *
  4.  * Copyright (c) 2001  Denis Oliver Kropp <dok@convergence.de>
  5.  *
  6.  *
  7.  * Card specific code is based on XFree86's neomagic driver.
  8.  * Framebuffer framework code is based on code of cyber2000fb.
  9.  *
  10.  * This file is subject to the terms and conditions of the GNU General
  11.  * Public License.  See the file COPYING in the main directory of this
  12.  * archive for more details.
  13.  *
  14.  *
  15.  * 0.3.2
  16.  *  - got rid of all floating point (dok)
  17.  *
  18.  * 0.3.1
  19.  *  - added module license (dok)
  20.  *
  21.  * 0.3
  22.  *  - hardware accelerated clear and move for 2200 and above (dok)
  23.  *  - maximum allowed dotclock is handled now (dok)
  24.  *
  25.  * 0.2.1
  26.  *  - correct panning after X usage (dok)
  27.  *  - added module and kernel parameters (dok)
  28.  *  - no stretching if external display is enabled (dok)
  29.  *
  30.  * 0.2
  31.  *  - initial version (dok)
  32.  *
  33.  *
  34.  * TODO
  35.  * - ioctl for internal/external switching
  36.  * - blanking
  37.  * - 32bit depth support, maybe impossible
  38.  * - disable pan-on-sync, need specs
  39.  *
  40.  * BUGS
  41.  * - white margin on bootup like with tdfxfb (colormap problem?)
  42.  *
  43.  */
  44. #include <linux/config.h>
  45. #include <linux/module.h>
  46. #include <linux/kernel.h>
  47. #include <linux/errno.h>
  48. #include <linux/string.h>
  49. #include <linux/mm.h>
  50. #include <linux/tty.h>
  51. #include <linux/slab.h>
  52. #include <linux/delay.h>
  53. #include <linux/fb.h>
  54. #include <linux/pci.h>
  55. #include <linux/init.h>
  56. #include <asm/io.h>
  57. #include <asm/irq.h>
  58. #include <asm/pgtable.h>
  59. #include <asm/system.h>
  60. #include <asm/uaccess.h>
  61. #ifdef CONFIG_MTRR
  62. #include <asm/mtrr.h>
  63. #endif
  64. #include <video/fbcon.h>
  65. #include <video/fbcon-cfb8.h>
  66. #include <video/fbcon-cfb16.h>
  67. #include <video/fbcon-cfb24.h>
  68. #include <video/fbcon-cfb32.h>
  69. #include "neofb.h"
  70. #define NEOFB_VERSION "0.3.2"
  71. /* --------------------------------------------------------------------- */
  72. static int disabled   = 0;
  73. static int internal   = 0;
  74. static int external   = 0;
  75. static int nostretch  = 0;
  76. static int nopciburst = 0;
  77. #ifdef MODULE
  78. MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@convergence.de>");
  79. MODULE_LICENSE("GPL");
  80. MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");
  81. MODULE_PARM(disabled, "i");
  82. MODULE_PARM_DESC(disabled, "Disable this driver's initialization.");
  83. MODULE_PARM(internal, "i");
  84. MODULE_PARM_DESC(internal, "Enable output on internal LCD Display.");
  85. MODULE_PARM(external, "i");
  86. MODULE_PARM_DESC(external, "Enable output on external CRT.");
  87. MODULE_PARM(nostretch, "i");
  88. MODULE_PARM_DESC(nostretch, "Disable stretching of modes smaller than LCD.");
  89. MODULE_PARM(nopciburst, "i");
  90. MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
  91. #endif
  92. /* --------------------------------------------------------------------- */
  93. static biosMode bios8[] = {
  94.     { 320, 240, 0x40 },
  95.     { 300, 400, 0x42 },    
  96.     { 640, 400, 0x20 },
  97.     { 640, 480, 0x21 },
  98.     { 800, 600, 0x23 },
  99.     { 1024, 768, 0x25 },
  100. };
  101. static biosMode bios16[] = {
  102.     { 320, 200, 0x2e },
  103.     { 320, 240, 0x41 },
  104.     { 300, 400, 0x43 },
  105.     { 640, 480, 0x31 },
  106.     { 800, 600, 0x34 },
  107.     { 1024, 768, 0x37 },
  108. };
  109. static biosMode bios24[] = {
  110.     { 640, 480, 0x32 },
  111.     { 800, 600, 0x35 },
  112.     { 1024, 768, 0x38 }
  113. };
  114. #ifdef NO_32BIT_SUPPORT_YET
  115. /* FIXME: guessed values, wrong */
  116. static biosMode bios32[] = {
  117.     { 640, 480, 0x33 },
  118.     { 800, 600, 0x36 },
  119.     { 1024, 768, 0x39 }
  120.     };
  121. #endif
  122. static int neoFindMode (int xres, int yres, int depth)
  123. {
  124.   int xres_s;
  125.   int i, size;
  126.   biosMode *mode;
  127.   switch (depth)
  128.     {
  129.     case 8:
  130.       size = sizeof(bios8) / sizeof(biosMode);
  131.       mode = bios8;
  132.       break;
  133.     case 16:
  134.       size = sizeof(bios16) / sizeof(biosMode);
  135.       mode = bios16;
  136.       break;
  137.     case 24:
  138.       size = sizeof(bios24) / sizeof(biosMode);
  139.       mode = bios24;
  140.       break;
  141. #ifdef NO_32BIT_SUPPORT_YET
  142.     case 32:
  143.       size = sizeof(bios32) / sizeof(biosMode);
  144.       mode = bios32;
  145.       break;
  146. #endif
  147.     default:
  148.       return 0;
  149.     }
  150.   for (i = 0; i < size; i++)
  151.     {
  152.       if (xres <= mode[i].x_res)
  153. {
  154.   xres_s = mode[i].x_res;
  155.   for (; i < size; i++)
  156.     {
  157.       if (mode[i].x_res != xres_s)
  158. return mode[i-1].mode;
  159.       if (yres <= mode[i].y_res)
  160. return mode[i].mode;
  161.     }
  162. }
  163.     }
  164.   return mode[size - 1].mode;
  165. }
  166. /* -------------------- Hardware specific routines ------------------------- */
  167. /*
  168.  * Hardware Acceleration for Neo2200+
  169.  */
  170. static inline void neo2200_wait_idle (struct neofb_info *fb)
  171. {
  172.   int waitcycles;
  173.   while (fb->neo2200->bltStat & 1)
  174.     waitcycles++;
  175. }
  176. static inline void neo2200_wait_fifo (struct neofb_info *fb,
  177.                                       int requested_fifo_space)
  178. {
  179.   //  ndev->neo.waitfifo_calls++;
  180.   //  ndev->neo.waitfifo_sum += requested_fifo_space;
  181.   /* FIXME: does not work
  182.   if (neo_fifo_space < requested_fifo_space)
  183.     {
  184.       neo_fifo_waitcycles++;
  185.       while (1)
  186.     {
  187.       neo_fifo_space = (neo2200->bltStat >> 8);
  188.       if (neo_fifo_space >= requested_fifo_space)
  189.         break;
  190.     }
  191.     }
  192.   else
  193.     {
  194.       neo_fifo_cache_hits++;
  195.     }
  196.   neo_fifo_space -= requested_fifo_space;
  197.   */
  198.   neo2200_wait_idle (fb);
  199. }
  200. static inline void neo2200_accel_init (struct neofb_info        *fb,
  201.        struct fb_var_screeninfo *var)
  202. {
  203.   Neo2200 *neo2200 = fb->neo2200;
  204.   u32 bltMod, pitch;
  205.   neo2200_wait_idle (fb);
  206.   switch (var->bits_per_pixel)
  207.     {
  208.     case 8:
  209.       bltMod = NEO_MODE1_DEPTH8;
  210.       pitch  = var->xres_virtual;
  211.       break;
  212.     case 15:
  213.     case 16:
  214.       bltMod = NEO_MODE1_DEPTH16;
  215.       pitch  = var->xres_virtual * 2;
  216.       break;
  217.     default:
  218.       printk( KERN_ERR "neofb: neo2200_accel_init: unexpected bits per pixel!n" );
  219.       return;
  220.     }
  221.   neo2200->bltStat = bltMod << 16;
  222.   neo2200->pitch   = (pitch << 16) | pitch;
  223. }
  224. static void neo2200_accel_setup (struct display *p)
  225. {
  226.   struct neofb_info        *fb  = (struct neofb_info *)p->fb_info;
  227.   struct fb_var_screeninfo *var = &p->fb_info->var;
  228.   fb->dispsw->setup(p);
  229.   neo2200_accel_init (fb, var);
  230. }
  231. static void
  232. neo2200_accel_bmove (struct display *p, int sy, int sx, int dy, int dx,
  233.      int height, int width)
  234. {
  235.   struct neofb_info *fb = (struct neofb_info *)p->fb_info;
  236.   struct fb_var_screeninfo *var = &p->fb_info->var;
  237.   Neo2200 *neo2200 = fb->neo2200;
  238.   u_long src, dst;
  239.   int bpp, pitch, inc_y;
  240.   u_int fh, fw;
  241.   if (sx != dx)
  242.     {
  243.       neo2200_wait_idle (fb);
  244.       fb->dispsw->bmove(p, sy, sx, dy, dx, height, width);
  245.       return;
  246.     }
  247.   bpp    = (var->bits_per_pixel+7) / 8;
  248.   pitch  = var->xres_virtual * bpp;
  249.   fw     = fontwidth(p);
  250.   sx    *= fw * bpp;
  251.   dx    *= fw * bpp;
  252.   width *= fw;
  253.   fh     = fontheight(p);
  254.   sy    *= fh;
  255.   dy    *= fh;
  256.   if (sy > dy)
  257.     inc_y = fh;
  258.   else
  259.     {
  260.       inc_y  = -fh;
  261.       sy    += (height - 1) * fh;
  262.       dy    += (height - 1) * fh;
  263.     }
  264.   neo2200_wait_fifo (fb, 1);
  265.   /* set blt control */
  266.   neo2200->bltCntl = NEO_BC3_FIFO_EN      |
  267.                      NEO_BC3_SKIP_MAPPING |  0x0c0000;
  268.   while (height--)
  269.     {
  270.       src = sx + sy * pitch;
  271.       dst = dx + dy * pitch;
  272.       neo2200_wait_fifo (fb, 3);
  273.       neo2200->srcStart = src;
  274.       neo2200->dstStart = dst;
  275.       neo2200->xyExt = (fh << 16) | (width & 0xffff);
  276.       sy += inc_y;
  277.       dy += inc_y;
  278.     }
  279. }
  280. static void
  281. neo2200_accel_clear (struct vc_data *conp, struct display *p, int sy, int sx,
  282.      int height, int width)
  283. {
  284.   struct neofb_info *fb = (struct neofb_info *)p->fb_info;
  285.   struct fb_var_screeninfo *var = &p->fb_info->var;
  286.   Neo2200 *neo2200 = fb->neo2200;
  287.   u_long dst;
  288.   u_int fw, fh;
  289.   u32 bgx = attr_bgcol_ec(p, conp);
  290.   fw = fontwidth(p);
  291.   fh = fontheight(p);
  292.   dst    = sx * fw + sy * var->xres_virtual * fh;
  293.   width  = width * fw;
  294.   height = height * fh;
  295.   neo2200_wait_fifo (fb, 4);
  296.   /* set blt control */
  297.   neo2200->bltCntl  = NEO_BC3_FIFO_EN      |
  298.                       NEO_BC0_SRC_IS_FG    |
  299.                       NEO_BC3_SKIP_MAPPING |  0x0c0000;
  300.   switch (var->bits_per_pixel)
  301.     {
  302.     case 8:
  303.       neo2200->fgColor = bgx;
  304.       break;
  305.     case 16:
  306.       neo2200->fgColor = ((u16 *)(p->fb_info)->pseudo_palette)[bgx];
  307.       break;
  308.     }
  309.   neo2200->dstStart = dst * ((var->bits_per_pixel+7) / 8);
  310.   neo2200->xyExt    = (height << 16) | (width & 0xffff);
  311. }
  312. static void
  313. neo2200_accel_putc (struct vc_data *conp, struct display *p, int c,
  314.     int yy, int xx)
  315. {
  316.   struct neofb_info *fb = (struct neofb_info *)p->fb_info;
  317.   neo2200_wait_idle (fb);
  318.   fb->dispsw->putc(conp, p, c, yy, xx);
  319. }
  320. static void
  321. neo2200_accel_putcs (struct vc_data *conp, struct display *p,
  322.      const unsigned short *s, int count, int yy, int xx)
  323. {
  324.   struct neofb_info *fb = (struct neofb_info *)p->fb_info;
  325.   neo2200_wait_idle (fb);
  326.   fb->dispsw->putcs(conp, p, s, count, yy, xx);
  327. }
  328. static void neo2200_accel_revc (struct display *p, int xx, int yy)
  329. {
  330.   struct neofb_info *fb = (struct neofb_info *)p->fb_info;
  331.   neo2200_wait_idle (fb);
  332.   fb->dispsw->revc (p, xx, yy);
  333. }
  334. static void
  335. neo2200_accel_clear_margins (struct vc_data *conp, struct display *p,
  336.      int bottom_only)
  337. {
  338.   struct neofb_info *fb = (struct neofb_info *)p->fb_info;
  339.   fb->dispsw->clear_margins (conp, p, bottom_only);
  340. }
  341. static struct display_switch fbcon_neo2200_accel = {
  342.   setup: neo2200_accel_setup,
  343.   bmove: neo2200_accel_bmove,
  344.   clear: neo2200_accel_clear,
  345.   putc: neo2200_accel_putc,
  346.   putcs: neo2200_accel_putcs,
  347.   revc: neo2200_accel_revc,
  348.   clear_margins: neo2200_accel_clear_margins,
  349.   fontwidthmask: FONTWIDTH(8)|FONTWIDTH(16)
  350. };
  351. /* --------------------------------------------------------------------- */
  352. /*
  353.  *    Set a single color register. Return != 0 for invalid regno.
  354.  */
  355. static int neo_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  356.  u_int transp, struct fb_info *fb)
  357. {
  358.   struct neofb_info *info = (struct neofb_info *)fb;
  359.   if (regno >= NR_PALETTE)
  360.     return -EINVAL;
  361.   info->palette[regno].red    = red;
  362.   info->palette[regno].green  = green;
  363.   info->palette[regno].blue   = blue;
  364.   info->palette[regno].transp = transp;
  365.   switch (fb->var.bits_per_pixel)
  366.     {
  367. #ifdef FBCON_HAS_CFB8
  368.     case 8:
  369.       outb(regno, 0x3c8);
  370.       outb(red   >> 10, 0x3c9);
  371.       outb(green >> 10, 0x3c9);
  372.       outb(blue  >> 10, 0x3c9);
  373.       break;
  374. #endif
  375. #ifdef FBCON_HAS_CFB16
  376.     case 16:
  377.       if (regno < 16)
  378. ((u16 *)fb->pseudo_palette)[regno] = ((red   & 0xf800)      ) |
  379.                                      ((green & 0xfc00) >>  5) |
  380.                                              ((blue  & 0xf800) >> 11);
  381.       break;
  382. #endif
  383. #ifdef FBCON_HAS_CFB24
  384.     case 24:
  385.       if (regno < 16)
  386. ((u32 *)fb->pseudo_palette)[regno] = ((red   & 0xff00) << 8) |
  387.                                              ((green & 0xff00)     ) |
  388.                                      ((blue  & 0xff00) >> 8);
  389.       break;
  390. #endif
  391. #ifdef NO_32BIT_SUPPORT_YET
  392. #ifdef FBCON_HAS_CFB32
  393.     case 32:
  394.       if (regno < 16)
  395. ((u32 *)fb->pseudo_palette)[regno] = ((transp & 0xff00) << 16) |
  396.                                      ((red    & 0xff00) <<  8) |
  397.                                              ((green  & 0xff00)      ) |
  398.                                      ((blue   & 0xff00) >>  8);
  399.       break;
  400. #endif
  401. #endif
  402.     default:
  403.       return 1;
  404.     }
  405.   return 0;
  406. }
  407. static void vgaHWLock (void)
  408. {
  409.   /* Protect CRTC[0-7] */
  410.   VGAwCR (0x11, VGArCR (0x11) | 0x80);
  411. }
  412. static void vgaHWUnlock (void)
  413. {
  414.   /* Unprotect CRTC[0-7] */
  415.   VGAwCR (0x11, VGArCR (0x11) & ~0x80);
  416. }
  417. static void neoLock (void)
  418. {
  419.   VGAwGR (0x09, 0x00);
  420.   vgaHWLock();
  421. }
  422. static void neoUnlock (void)
  423. {
  424.   vgaHWUnlock();
  425.   VGAwGR (0x09, 0x26);
  426. }
  427. /*
  428.  * vgaHWSeqReset
  429.  *      perform a sequencer reset.
  430.  */
  431. void
  432. vgaHWSeqReset(int start)
  433. {
  434.   if (start)
  435.     VGAwSEQ (0x00, 0x01); /* Synchronous Reset */
  436.   else
  437.     VGAwSEQ (0x00, 0x03); /* End Reset */
  438. }
  439. void
  440. vgaHWProtect(int on)
  441. {
  442.   unsigned char tmp;
  443.   
  444.   if (on)
  445.     {
  446.       /*
  447.        * Turn off screen and disable sequencer.
  448.        */
  449.       tmp = VGArSEQ (0x01);
  450.       vgaHWSeqReset (1); /* start synchronous reset */
  451.       VGAwSEQ (0x01, tmp | 0x20); /* disable the display */
  452.       VGAenablePalette();
  453.     }
  454.   else
  455.     {
  456.       /*
  457.        * Reenable sequencer, then turn on screen.
  458.        */
  459.   
  460.       tmp = VGArSEQ (0x01);
  461.       VGAwSEQ (0x01, tmp & ~0x20); /* reenable display */
  462.       vgaHWSeqReset (0); /* clear synchronousreset */
  463.       VGAdisablePalette();
  464.     }
  465. }
  466. static void vgaHWRestore (const struct neofb_info *info,
  467.   const struct neofb_par  *par)
  468. {
  469.   int i;
  470.   VGAwMISC (par->MiscOutReg);
  471.   for (i = 1; i < 5; i++)
  472.     VGAwSEQ (i, par->Sequencer[i]);
  473.   
  474.   /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
  475.   VGAwCR (17, par->CRTC[17] & ~0x80);
  476.   for (i = 0; i < 25; i++)
  477.     VGAwCR (i, par->CRTC[i]);
  478.   for (i = 0; i < 9; i++)
  479.     VGAwGR (i, par->Graphics[i]);
  480.   VGAenablePalette();
  481.   for (i = 0; i < 21; i++)
  482.     VGAwATTR (i, par->Attribute[i]);
  483.   VGAdisablePalette();
  484. }
  485. static void neofb_set_par (struct neofb_info       *info,
  486.    const struct neofb_par  *par)
  487. {
  488.   unsigned char temp;
  489.   int i;
  490.   int clock_hi = 0;
  491.     
  492.   DBG("neofb_set_par");
  493.   neoUnlock();
  494.   vgaHWProtect (1); /* Blank the screen */
  495.   /* linear colormap for non palettized modes */
  496.   switch (par->depth)
  497.     {
  498.     case 8:
  499.       break;
  500.     case 16:
  501.       for (i=0; i<64; i++)
  502. {
  503.   outb(i, 0x3c8);
  504.   
  505.   outb(i << 1, 0x3c9);
  506.   outb(i, 0x3c9);
  507.   outb(i << 1, 0x3c9);
  508. }
  509.       break;
  510.     case 24:
  511. #ifdef NO_32BIT_SUPPORT_YET
  512.     case 32:
  513. #endif
  514.       for (i=0; i<256; i++)
  515. {
  516.   outb(i, 0x3c8);
  517.   
  518.   outb(i, 0x3c9);
  519.   outb(i, 0x3c9);
  520.   outb(i, 0x3c9);
  521. }
  522.       break;
  523.     }
  524.     
  525.   /* alread unlocked above */
  526.   /* BOGUS  VGAwGR (0x09, 0x26);*/
  527.     
  528.   /* don't know what this is, but it's 0 from bootup anyway */
  529.   VGAwGR (0x15, 0x00);
  530.   /* was set to 0x01 by my bios in text and vesa modes */
  531.   VGAwGR (0x0A, par->GeneralLockReg);
  532.   /*
  533.    * The color mode needs to be set before calling vgaHWRestore
  534.    * to ensure the DAC is initialized properly.
  535.    *
  536.    * NOTE: Make sure we don't change bits make sure we don't change
  537.    * any reserved bits.
  538.    */
  539.   temp = VGArGR(0x90);
  540.   switch (info->accel)
  541.     {
  542.     case FB_ACCEL_NEOMAGIC_NM2070:
  543.       temp &= 0xF0; /* Save bits 7:4 */
  544.       temp |= (par->ExtColorModeSelect & ~0xF0);
  545.       break;
  546.     case FB_ACCEL_NEOMAGIC_NM2090:
  547.     case FB_ACCEL_NEOMAGIC_NM2093:
  548.     case FB_ACCEL_NEOMAGIC_NM2097:
  549.     case FB_ACCEL_NEOMAGIC_NM2160:
  550.     case FB_ACCEL_NEOMAGIC_NM2200:
  551.     case FB_ACCEL_NEOMAGIC_NM2230:
  552.     case FB_ACCEL_NEOMAGIC_NM2360:
  553.     case FB_ACCEL_NEOMAGIC_NM2380:
  554.       temp &= 0x70; /* Save bits 6:4 */
  555.       temp |= (par->ExtColorModeSelect & ~0x70);
  556.       break;
  557.     }
  558.   VGAwGR(0x90,temp);
  559.   /*
  560.    * In some rare cases a lockup might occur if we don't delay
  561.    * here. (Reported by Miles Lane)
  562.    */
  563.   //mdelay(200);
  564.   /*
  565.    * Disable horizontal and vertical graphics and text expansions so
  566.    * that vgaHWRestore works properly.
  567.    */
  568.   temp = VGArGR(0x25);
  569.   temp &= 0x39;
  570.   VGAwGR (0x25, temp);
  571.   /*
  572.    * Sleep for 200ms to make sure that the two operations above have
  573.    * had time to take effect.
  574.    */
  575.   mdelay(200);
  576.   /*
  577.    * This function handles restoring the generic VGA registers.  */
  578.   vgaHWRestore (info, par);
  579.   VGAwGR(0x0E, par->ExtCRTDispAddr);
  580.   VGAwGR(0x0F, par->ExtCRTOffset);
  581.   temp = VGArGR(0x10);
  582.   temp &= 0x0F; /* Save bits 3:0 */
  583.   temp |= (par->SysIfaceCntl1 & ~0x0F); /* VESA Bios sets bit 1! */
  584.   VGAwGR(0x10, temp);
  585.   VGAwGR(0x11, par->SysIfaceCntl2);
  586.   VGAwGR(0x15, 0 /*par->SingleAddrPage*/);
  587.   VGAwGR(0x16, 0 /*par->DualAddrPage*/);
  588.   temp = VGArGR(0x20);
  589.   switch (info->accel)
  590.     {
  591.     case FB_ACCEL_NEOMAGIC_NM2070:
  592.       temp &= 0xFC; /* Save bits 7:2 */
  593.       temp |= (par->PanelDispCntlReg1 & ~0xFC);
  594.       break;
  595.     case FB_ACCEL_NEOMAGIC_NM2090:
  596.     case FB_ACCEL_NEOMAGIC_NM2093:
  597.     case FB_ACCEL_NEOMAGIC_NM2097:
  598.     case FB_ACCEL_NEOMAGIC_NM2160:
  599.       temp &= 0xDC; /* Save bits 7:6,4:2 */
  600.       temp |= (par->PanelDispCntlReg1 & ~0xDC);
  601.       break;
  602.     case FB_ACCEL_NEOMAGIC_NM2200:
  603.     case FB_ACCEL_NEOMAGIC_NM2230:
  604.     case FB_ACCEL_NEOMAGIC_NM2360:
  605.     case FB_ACCEL_NEOMAGIC_NM2380:
  606.       temp &= 0x98; /* Save bits 7,4:3 */
  607.       temp |= (par->PanelDispCntlReg1 & ~0x98);
  608.       break;
  609.     }
  610.   VGAwGR(0x20, temp);
  611.   temp = VGArGR(0x25);
  612.   temp &= 0x38; /* Save bits 5:3 */
  613.   temp |= (par->PanelDispCntlReg2 & ~0x38);
  614.   VGAwGR(0x25, temp);
  615.   if (info->accel != FB_ACCEL_NEOMAGIC_NM2070)
  616.     {
  617.       temp = VGArGR(0x30);
  618.       temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */
  619.       temp |= (par->PanelDispCntlReg3 & ~0xEF);
  620.       VGAwGR(0x30, temp);
  621.     }
  622.   VGAwGR(0x28, par->PanelVertCenterReg1);
  623.   VGAwGR(0x29, par->PanelVertCenterReg2);
  624.   VGAwGR(0x2a, par->PanelVertCenterReg3);
  625.   if (info->accel != FB_ACCEL_NEOMAGIC_NM2070)
  626.     {
  627.       VGAwGR(0x32, par->PanelVertCenterReg4);
  628.       VGAwGR(0x33, par->PanelHorizCenterReg1);
  629.       VGAwGR(0x34, par->PanelHorizCenterReg2);
  630.       VGAwGR(0x35, par->PanelHorizCenterReg3);
  631.     }
  632.   if (info->accel == FB_ACCEL_NEOMAGIC_NM2160)
  633.     VGAwGR(0x36, par->PanelHorizCenterReg4);
  634.   if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 ||
  635.       info->accel == FB_ACCEL_NEOMAGIC_NM2230 ||
  636.       info->accel == FB_ACCEL_NEOMAGIC_NM2360 ||
  637.       info->accel == FB_ACCEL_NEOMAGIC_NM2380)
  638.     {
  639.       VGAwGR(0x36, par->PanelHorizCenterReg4);
  640.       VGAwGR(0x37, par->PanelVertCenterReg5);
  641.       VGAwGR(0x38, par->PanelHorizCenterReg5);
  642.       clock_hi = 1;
  643.     }
  644.   /* Program VCLK3 if needed. */
  645.   if (par->ProgramVCLK
  646.       && ((VGArGR(0x9B) != par->VCLK3NumeratorLow)
  647.   || (VGArGR(0x9F) !=  par->VCLK3Denominator)
  648.   || (clock_hi && ((VGArGR(0x8F) & ~0x0f)
  649.    != (par->VCLK3NumeratorHigh & ~0x0F)))))
  650.     {
  651.       VGAwGR(0x9B, par->VCLK3NumeratorLow);
  652.       if (clock_hi)
  653. {
  654.   temp = VGArGR(0x8F);
  655.   temp &= 0x0F; /* Save bits 3:0 */
  656.   temp |= (par->VCLK3NumeratorHigh & ~0x0F);
  657.   VGAwGR(0x8F, temp);
  658. }
  659.       VGAwGR(0x9F, par->VCLK3Denominator);
  660.     }
  661.   if (par->biosMode)
  662.     VGAwCR(0x23, par->biosMode);
  663.     
  664.   VGAwGR (0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */
  665.   /* Program vertical extension register */
  666.   if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 ||
  667.       info->accel == FB_ACCEL_NEOMAGIC_NM2230 ||
  668.       info->accel == FB_ACCEL_NEOMAGIC_NM2360 ||
  669.       info->accel == FB_ACCEL_NEOMAGIC_NM2380)
  670.     {
  671.       VGAwCR(0x70, par->VerticalExt);
  672.     }
  673.   vgaHWProtect (0); /* Turn on screen */
  674.   /* Calling this also locks offset registers required in update_start */
  675.   neoLock();
  676. }
  677. static void neofb_update_start (struct neofb_info *info, struct fb_var_screeninfo *var)
  678. {
  679.   int oldExtCRTDispAddr;
  680.   int Base; 
  681.   DBG("neofb_update_start");
  682.   Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2;
  683.   Base *= (var->bits_per_pixel + 7) / 8;
  684.   neoUnlock();
  685.   /*
  686.    * These are the generic starting address registers.
  687.    */
  688.   VGAwCR(0x0C, (Base & 0x00FF00) >> 8);
  689.   VGAwCR(0x0D, (Base & 0x00FF));
  690.   /*
  691.    * Make sure we don't clobber some other bits that might already
  692.    * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
  693.    * be needed.
  694.    */
  695.   oldExtCRTDispAddr = VGArGR(0x0E);
  696.   VGAwGR(0x0E,(((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
  697.   neoLock();
  698. }
  699. /*
  700.  * Set the Colormap
  701.  */
  702. static int neofb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  703.   struct fb_info *fb)
  704. {
  705.   struct neofb_info *info = (struct neofb_info *)fb;
  706.   struct display* disp = (con < 0) ? fb->disp : (fb_display + con);
  707.   struct fb_cmap *dcmap = &disp->cmap;
  708.   int err = 0;
  709.   /* no colormap allocated? */
  710.   if (!dcmap->len)
  711.     {
  712.       int size;
  713.       if (fb->var.bits_per_pixel == 8)
  714. size = NR_PALETTE;
  715.       else
  716. size = 32;
  717.       err = fb_alloc_cmap (dcmap, size, 0);
  718.     }
  719.   /*
  720.    * we should be able to remove this test once fbcon has been
  721.    * "improved" --rmk
  722.    */
  723.   if (!err && con == info->currcon)
  724.     {
  725.       err = fb_set_cmap (cmap, kspc, neo_setcolreg, fb);
  726.       dcmap = &fb->cmap;
  727.     }
  728.   if (!err)
  729.     fb_copy_cmap (cmap, dcmap, kspc ? 0 : 1);
  730.   return err;
  731. }
  732. /*
  733.  * neoCalcVCLK --
  734.  *
  735.  * Determine the closest clock frequency to the one requested.
  736.  */
  737. #define REF_FREQ 0xe517  /* 14.31818 in 20.12 fixed point */
  738. #define MAX_N 127
  739. #define MAX_D 31
  740. #define MAX_F 1
  741. static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, long freq)
  742. {
  743.   int n, d, f;
  744.   int n_best = 0, d_best = 0, f_best = 0;
  745.   long f_best_diff = (0x7ffff << 12); /* 20.12 */
  746.   long f_target = (freq << 12) / 1000; /* 20.12 */
  747.   for (f = 0; f <= MAX_F; f++)
  748.     for (n = 0; n <= MAX_N; n++)
  749.       for (d = 0; d <= MAX_D; d++)
  750. {
  751.           long f_out;  /* 20.12 */
  752.           long f_diff; /* 20.12 */
  753.   f_out = ((((n+1) << 12)  /  ((d+1)*(1<<f))) >> 12)  *  REF_FREQ;
  754.   f_diff = abs(f_out-f_target);
  755.   if (f_diff < f_best_diff)
  756.     {
  757.       f_best_diff = f_diff;
  758.       n_best = n;
  759.       d_best = d;
  760.       f_best = f;
  761.     }
  762. }
  763.   if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 ||
  764.       info->accel == FB_ACCEL_NEOMAGIC_NM2230 ||
  765.       info->accel == FB_ACCEL_NEOMAGIC_NM2360 ||
  766.       info->accel == FB_ACCEL_NEOMAGIC_NM2380)
  767.     {
  768.       /* NOT_DONE:  We are trying the full range of the 2200 clock.
  769.  We should be able to try n up to 2047 */
  770.       par->VCLK3NumeratorLow  = n_best;
  771.       par->VCLK3NumeratorHigh = (f_best << 7);
  772.     }
  773.   else
  774.     par->VCLK3NumeratorLow  = n_best | (f_best << 7);
  775.   par->VCLK3Denominator = d_best;
  776. #ifdef NEOFB_DEBUG
  777.   printk ("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%dn",
  778.   f_target >> 12,
  779.   par->VCLK3NumeratorLow,
  780.   par->VCLK3NumeratorHigh,
  781.   par->VCLK3Denominator,
  782.   f_best_diff >> 12);
  783. #endif
  784. }
  785. /*
  786.  * vgaHWInit --
  787.  *      Handle the initialization, etc. of a screen.
  788.  *      Return FALSE on failure.
  789.  */
  790. static int vgaHWInit (const struct fb_var_screeninfo *var,
  791.       const struct neofb_info        *info,
  792.       struct neofb_par               *par,
  793.       struct xtimings                *timings)
  794. {
  795.   par->MiscOutReg = 0x23;
  796.   if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
  797.     par->MiscOutReg |= 0x40;
  798.   if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
  799.     par->MiscOutReg |= 0x80;
  800.     
  801.   /*
  802.    * Time Sequencer
  803.    */
  804.   par->Sequencer[0] = 0x00;
  805.   par->Sequencer[1] = 0x01;
  806.   par->Sequencer[2] = 0x0F;
  807.   par->Sequencer[3] = 0x00;                             /* Font select */
  808.   par->Sequencer[4] = 0x0E;                             /* Misc */
  809.   /*
  810.    * CRTC Controller
  811.    */
  812.   par->CRTC[0]  = (timings->HTotal >> 3) - 5;
  813.   par->CRTC[1]  = (timings->HDisplay >> 3) - 1;
  814.   par->CRTC[2]  = (timings->HDisplay >> 3) - 1;
  815.   par->CRTC[3]  = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80;
  816.   par->CRTC[4]  = (timings->HSyncStart >> 3);
  817.   par->CRTC[5]  = ((((timings->HTotal >> 3) - 1) & 0x20) << 2)
  818.     | (((timings->HSyncEnd >> 3)) & 0x1F);
  819.   par->CRTC[6]  = (timings->VTotal - 2) & 0xFF;
  820.   par->CRTC[7]  = (((timings->VTotal - 2) & 0x100) >> 8)
  821.     | (((timings->VDisplay - 1) & 0x100) >> 7)
  822.     | ((timings->VSyncStart & 0x100) >> 6)
  823.     | (((timings->VDisplay - 1) & 0x100) >> 5)
  824.     | 0x10
  825.     | (((timings->VTotal - 2) & 0x200)   >> 4)
  826.     | (((timings->VDisplay - 1) & 0x200) >> 3)
  827.     | ((timings->VSyncStart & 0x200) >> 2);
  828.   par->CRTC[8]  = 0x00;
  829.   par->CRTC[9]  = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40;
  830.   if (timings->dblscan)
  831.     par->CRTC[9] |= 0x80;
  832.   par->CRTC[10] = 0x00;
  833.   par->CRTC[11] = 0x00;
  834.   par->CRTC[12] = 0x00;
  835.   par->CRTC[13] = 0x00;
  836.   par->CRTC[14] = 0x00;
  837.   par->CRTC[15] = 0x00;
  838.   par->CRTC[16] = timings->VSyncStart & 0xFF;
  839.   par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20;
  840.   par->CRTC[18] = (timings->VDisplay - 1) & 0xFF;
  841.   par->CRTC[19] = var->xres_virtual >> 4;
  842.   par->CRTC[20] = 0x00;
  843.   par->CRTC[21] = (timings->VDisplay - 1) & 0xFF; 
  844.   par->CRTC[22] = (timings->VTotal - 1) & 0xFF;
  845.   par->CRTC[23] = 0xC3;
  846.   par->CRTC[24] = 0xFF;
  847.   /*
  848.    * are these unnecessary?
  849.    * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
  850.    * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
  851.    */
  852.   /*
  853.    * Graphics Display Controller
  854.    */
  855.   par->Graphics[0] = 0x00;
  856.   par->Graphics[1] = 0x00;
  857.   par->Graphics[2] = 0x00;
  858.   par->Graphics[3] = 0x00;
  859.   par->Graphics[4] = 0x00;
  860.   par->Graphics[5] = 0x40;
  861.   par->Graphics[6] = 0x05;   /* only map 64k VGA memory !!!! */
  862.   par->Graphics[7] = 0x0F;
  863.   par->Graphics[8] = 0xFF;
  864.   
  865.   par->Attribute[0]  = 0x00; /* standard colormap translation */
  866.   par->Attribute[1]  = 0x01;
  867.   par->Attribute[2]  = 0x02;
  868.   par->Attribute[3]  = 0x03;
  869.   par->Attribute[4]  = 0x04;
  870.   par->Attribute[5]  = 0x05;
  871.   par->Attribute[6]  = 0x06;
  872.   par->Attribute[7]  = 0x07;
  873.   par->Attribute[8]  = 0x08;
  874.   par->Attribute[9]  = 0x09;
  875.   par->Attribute[10] = 0x0A;
  876.   par->Attribute[11] = 0x0B;
  877.   par->Attribute[12] = 0x0C;
  878.   par->Attribute[13] = 0x0D;
  879.   par->Attribute[14] = 0x0E;
  880.   par->Attribute[15] = 0x0F;
  881.   par->Attribute[16] = 0x41;
  882.   par->Attribute[17] = 0xFF;
  883.   par->Attribute[18] = 0x0F;
  884.   par->Attribute[19] = 0x00;
  885.   par->Attribute[20] = 0x00;
  886.   return 0;
  887. }
  888. static int neofb_decode_var (struct fb_var_screeninfo        *var,
  889.                              const struct neofb_info         *info,
  890.                              struct neofb_par                *par)
  891. {
  892.   struct xtimings timings;
  893.   int lcd_stretch;
  894.   int hoffset, voffset;
  895.   int memlen, vramlen;
  896.   int mode_ok = 0;
  897.   unsigned int pixclock = var->pixclock;
  898.   DBG("neofb_decode_var");
  899.   if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */
  900.   timings.pixclock = 1000000000 / pixclock;
  901.   if (timings.pixclock < 1) timings.pixclock = 1;
  902.   timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
  903.   timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
  904.   timings.HDisplay = var->xres;
  905.   timings.HSyncStart = timings.HDisplay + var->right_margin;
  906.   timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
  907.   timings.HTotal = timings.HSyncEnd + var->left_margin;
  908.   timings.VDisplay = var->yres;
  909.   timings.VSyncStart = timings.VDisplay + var->lower_margin;
  910.   timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
  911.   timings.VTotal = timings.VSyncEnd + var->upper_margin;
  912.   timings.sync = var->sync;
  913.   if (timings.pixclock > info->maxClock)
  914.     return -EINVAL;
  915.   /* Is the mode larger than the LCD panel? */
  916.   if ((var->xres > info->NeoPanelWidth) ||
  917.       (var->yres > info->NeoPanelHeight))
  918.     {
  919.       printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel (%dx%d)n",
  920.       var->xres,
  921.       var->yres,
  922.       info->NeoPanelWidth,
  923.       info->NeoPanelHeight);
  924.       return -EINVAL;
  925.     }
  926.   /* Is the mode one of the acceptable sizes? */
  927.   switch (var->xres)
  928.     {
  929.     case 1280:
  930.       if (var->yres == 1024)
  931. mode_ok = 1;
  932.       break;
  933.     case 1024:
  934.       if (var->yres == 768)
  935. mode_ok = 1;
  936.       break;
  937.     case  800:
  938.       if (var->yres == 600)
  939. mode_ok = 1;
  940.       break;
  941.     case  640:
  942.       if (var->yres == 480)
  943. mode_ok = 1;
  944.       break;
  945.     }
  946.   if (!mode_ok)
  947.     {
  948.       printk (KERN_INFO "Mode (%dx%d) won't display properly on LCDn",
  949.       var->xres, var->yres);
  950.       return -EINVAL;
  951.     }
  952.   switch (var->bits_per_pixel)
  953.     {
  954. #ifdef FBCON_HAS_CFB8
  955.     case 8:
  956.       break;
  957. #endif
  958. #ifdef FBCON_HAS_CFB16
  959.     case 16:
  960.       break;
  961. #endif
  962. #ifdef FBCON_HAS_CFB24
  963.     case 24:
  964.       break;
  965. #endif
  966. #ifdef NO_32BIT_SUPPORT_YET
  967. # ifdef FBCON_HAS_CFB32
  968.     case 32:
  969.       break;
  970. # endif
  971. #endif
  972.     default:
  973.       return -EINVAL;
  974.     }
  975.   par->depth = var->bits_per_pixel;
  976.   vramlen = info->video.len;
  977.   if (vramlen > 4*1024*1024)
  978.     vramlen = 4*1024*1024;
  979.   if (var->yres_virtual < var->yres)
  980.     var->yres_virtual = var->yres;
  981.   if (var->xres_virtual < var->xres)
  982.     var->xres_virtual = var->xres;
  983.   memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
  984.   if (memlen > vramlen)
  985.     {
  986.       var->yres_virtual = vramlen * 8 / (var->xres_virtual * var->bits_per_pixel);
  987.       memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
  988.     }
  989.   /* we must round yres/xres down, we already rounded y/xres_virtual up
  990.      if it was possible. We should return -EINVAL, but I disagree */
  991.   if (var->yres_virtual < var->yres)
  992.     var->yres = var->yres_virtual;
  993.   if (var->xres_virtual < var->xres)
  994.     var->xres = var->xres_virtual;
  995.   if (var->xoffset + var->xres > var->xres_virtual)
  996.     var->xoffset = var->xres_virtual - var->xres;
  997.   if (var->yoffset + var->yres > var->yres_virtual)
  998.     var->yoffset = var->yres_virtual - var->yres;
  999.   /*
  1000.    * This will allocate the datastructure and initialize all of the
  1001.    * generic VGA registers.
  1002.    */
  1003.   if (vgaHWInit (var, info, par, &timings))
  1004.     return -EINVAL;
  1005.   /*
  1006.    * The default value assigned by vgaHW.c is 0x41, but this does
  1007.    * not work for NeoMagic.
  1008.    */
  1009.   par->Attribute[16] = 0x01;
  1010.   switch (var->bits_per_pixel)
  1011.     {
  1012.     case  8:
  1013.       par->CRTC[0x13]   = var->xres_virtual >> 3;
  1014.       par->ExtCRTOffset = var->xres_virtual >> 11;
  1015.       par->ExtColorModeSelect = 0x11;
  1016.       break;
  1017.     case 16:
  1018.       par->CRTC[0x13]   = var->xres_virtual >> 2;
  1019.       par->ExtCRTOffset = var->xres_virtual >> 10;
  1020.       par->ExtColorModeSelect = 0x13;
  1021.       break;
  1022.     case 24:
  1023.       par->CRTC[0x13]   = (var->xres_virtual * 3) >> 3;
  1024.       par->ExtCRTOffset = (var->xres_virtual * 3) >> 11;
  1025.       par->ExtColorModeSelect = 0x14;
  1026.       break;
  1027. #ifdef NO_32BIT_SUPPORT_YET
  1028.     case 32: /* FIXME: guessed values */
  1029.       par->CRTC[0x13]   = var->xres_virtual >> 1;
  1030.       par->ExtCRTOffset = var->xres_virtual >> 9;
  1031.       par->ExtColorModeSelect = 0x15;
  1032.       break;
  1033. #endif
  1034.     default:
  1035.       break;
  1036.     }
  1037.   par->ExtCRTDispAddr = 0x10;
  1038.   /* Vertical Extension */
  1039.   par->VerticalExt = (((timings.VTotal -2) & 0x400) >> 10 )
  1040.     | (((timings.VDisplay -1) & 0x400) >> 9 )
  1041.     | (((timings.VSyncStart) & 0x400) >> 8 )
  1042.     | (((timings.VSyncStart) & 0x400) >> 7 );
  1043.   /* Fast write bursts on unless disabled. */
  1044.   if (info->pci_burst)
  1045.     par->SysIfaceCntl1 = 0x30; 
  1046.   else
  1047.     par->SysIfaceCntl1 = 0x00; 
  1048.   par->SysIfaceCntl2 = 0xc0; /* VESA Bios sets this to 0x80! */
  1049.   /* Enable any user specified display devices. */
  1050.   par->PanelDispCntlReg1 = 0x00;
  1051.   if (info->internal_display)
  1052.     par->PanelDispCntlReg1 |= 0x02;
  1053.   if (info->external_display)
  1054.     par->PanelDispCntlReg1 |= 0x01;
  1055.   /* If the user did not specify any display devices, then... */
  1056.   if (par->PanelDispCntlReg1 == 0x00) {
  1057.     /* Default to internal (i.e., LCD) only. */
  1058.     par->PanelDispCntlReg1 |= 0x02;
  1059.   }
  1060.   /* If we are using a fixed mode, then tell the chip we are. */
  1061.   switch (var->xres)
  1062.     {
  1063.     case 1280:
  1064.       par->PanelDispCntlReg1 |= 0x60;
  1065.       break;
  1066.     case 1024:
  1067.       par->PanelDispCntlReg1 |= 0x40;
  1068.       break;
  1069.     case 800:
  1070.       par->PanelDispCntlReg1 |= 0x20;
  1071.       break;
  1072.     case 640:
  1073.     default:
  1074.       break;
  1075.     }
  1076.   
  1077.   /* Setup shadow register locking. */
  1078.   switch (par->PanelDispCntlReg1 & 0x03)
  1079.     {
  1080.     case 0x01: /* External CRT only mode: */
  1081.       par->GeneralLockReg = 0x00;
  1082.       /* We need to program the VCLK for external display only mode. */
  1083.       par->ProgramVCLK = 1;
  1084.       break;
  1085.     case 0x02: /* Internal LCD only mode: */
  1086.     case 0x03: /* Simultaneous internal/external (LCD/CRT) mode: */
  1087.       par->GeneralLockReg = 0x01;
  1088.       /* Don't program the VCLK when using the LCD. */
  1089.       par->ProgramVCLK = 0;
  1090.       break;
  1091.     }
  1092.   /*
  1093.    * If the screen is to be stretched, turn on stretching for the
  1094.    * various modes.
  1095.    *
  1096.    * OPTION_LCD_STRETCH means stretching should be turned off!
  1097.    */
  1098.   par->PanelDispCntlReg2 = 0x00;
  1099.   par->PanelDispCntlReg3 = 0x00;
  1100.   if (info->lcd_stretch &&
  1101.       (par->PanelDispCntlReg1 == 0x02) &&  /* LCD only */
  1102.       (var->xres != info->NeoPanelWidth))
  1103.     {
  1104.       switch (var->xres)
  1105. {
  1106. case  320: /* Needs testing.  KEM -- 24 May 98 */
  1107. case  400: /* Needs testing.  KEM -- 24 May 98 */
  1108. case  640:
  1109. case  800:
  1110. case 1024:
  1111.   lcd_stretch = 1;
  1112.   par->PanelDispCntlReg2 |= 0xC6;
  1113.   break;
  1114. default:
  1115.   lcd_stretch = 0;
  1116.   /* No stretching in these modes. */
  1117. }
  1118.     }
  1119.   else
  1120.     lcd_stretch = 0;
  1121.   /*
  1122.    * If the screen is to be centerd, turn on the centering for the
  1123.    * various modes.
  1124.    */
  1125.   par->PanelVertCenterReg1  = 0x00;
  1126.   par->PanelVertCenterReg2  = 0x00;
  1127.   par->PanelVertCenterReg3  = 0x00;
  1128.   par->PanelVertCenterReg4  = 0x00;
  1129.   par->PanelVertCenterReg5  = 0x00;
  1130.   par->PanelHorizCenterReg1 = 0x00;
  1131.   par->PanelHorizCenterReg2 = 0x00;
  1132.   par->PanelHorizCenterReg3 = 0x00;
  1133.   par->PanelHorizCenterReg4 = 0x00;
  1134.   par->PanelHorizCenterReg5 = 0x00;
  1135.   if (par->PanelDispCntlReg1 & 0x02)
  1136.     {
  1137.       if (var->xres == info->NeoPanelWidth)
  1138. {
  1139.   /*
  1140.    * No centering required when the requested display width
  1141.    * equals the panel width.
  1142.    */
  1143. }
  1144.       else
  1145. {
  1146.   par->PanelDispCntlReg2 |= 0x01;
  1147.   par->PanelDispCntlReg3 |= 0x10;
  1148.   /* Calculate the horizontal and vertical offsets. */
  1149.   if (!lcd_stretch)
  1150.     {
  1151.       hoffset = ((info->NeoPanelWidth - var->xres) >> 4) - 1;
  1152.       voffset = ((info->NeoPanelHeight - var->yres) >> 1) - 2;
  1153.     }
  1154.   else
  1155.     {
  1156.       /* Stretched modes cannot be centered. */
  1157.       hoffset = 0;
  1158.       voffset = 0;
  1159.     }
  1160.   switch (var->xres)
  1161.     {
  1162.     case  320: /* Needs testing.  KEM -- 24 May 98 */
  1163.       par->PanelHorizCenterReg3 = hoffset;
  1164.       par->PanelVertCenterReg2  = voffset;
  1165.       break;
  1166.     case  400: /* Needs testing.  KEM -- 24 May 98 */
  1167.       par->PanelHorizCenterReg4 = hoffset;
  1168.       par->PanelVertCenterReg1  = voffset;
  1169.       break;
  1170.     case  640:
  1171.       par->PanelHorizCenterReg1 = hoffset;
  1172.       par->PanelVertCenterReg3  = voffset;
  1173.       break;
  1174.     case  800:
  1175.       par->PanelHorizCenterReg2 = hoffset;
  1176.       par->PanelVertCenterReg4  = voffset;
  1177.       break;
  1178.     case 1024:
  1179.       par->PanelHorizCenterReg5 = hoffset;
  1180.       par->PanelVertCenterReg5  = voffset;
  1181.       break;
  1182.     case 1280:
  1183.     default:
  1184.       /* No centering in these modes. */
  1185.       break;
  1186.     }
  1187. }
  1188.     }
  1189.   par->biosMode = neoFindMode (var->xres, var->yres, var->bits_per_pixel);
  1190.     
  1191.   /*
  1192.    * Calculate the VCLK that most closely matches the requested dot
  1193.    * clock.
  1194.    */
  1195.   neoCalcVCLK (info, par, timings.pixclock);
  1196.   /* Since we program the clocks ourselves, always use VCLK3. */
  1197.   par->MiscOutReg |= 0x0C;
  1198.   return 0;
  1199. }
  1200. static int neofb_set_var (struct fb_var_screeninfo *var, int con,
  1201.                           struct fb_info *fb)
  1202. {
  1203.   struct neofb_info *info = (struct neofb_info *)fb;
  1204.   struct display *display;
  1205.   struct neofb_par par;
  1206.   int err, chgvar = 0;
  1207.   DBG("neofb_set_var");
  1208.   err = neofb_decode_var (var, info, &par);
  1209.   if (err)
  1210.     return err;
  1211.   if (var->activate & FB_ACTIVATE_TEST)
  1212.     return 0;
  1213.   if (con < 0)
  1214.     {
  1215.       display = fb->disp;
  1216.       chgvar = 0;
  1217.     }
  1218.   else
  1219.     {
  1220.       display = fb_display + con;
  1221.       if (fb->var.xres != var->xres)
  1222. chgvar = 1;
  1223.       if (fb->var.yres != var->yres)
  1224. chgvar = 1;
  1225.       if (fb->var.xres_virtual != var->xres_virtual)
  1226. chgvar = 1;
  1227.       if (fb->var.yres_virtual != var->yres_virtual)
  1228. chgvar = 1;
  1229.       if (fb->var.bits_per_pixel != var->bits_per_pixel)
  1230. chgvar = 1;
  1231.     }
  1232.   if (!info->neo2200)
  1233.     var->accel_flags &= ~FB_ACCELF_TEXT;
  1234.   var->red.msb_right = 0;
  1235.   var->green.msb_right = 0;
  1236.   var->blue.msb_right = 0;
  1237.   switch (var->bits_per_pixel)
  1238.     {
  1239. #ifdef FBCON_HAS_CFB8
  1240.     case 8: /* PSEUDOCOLOUR, 256 */
  1241.       var->transp.offset   = 0;
  1242.       var->transp.length   = 0;
  1243.       var->red.offset      = 0;
  1244.       var->red.length      = 8;
  1245.       var->green.offset    = 0;
  1246.       var->green.length    = 8;
  1247.       var->blue.offset    = 0;
  1248.       var->blue.length    = 8;
  1249.       
  1250.       fb->fix.visual       = FB_VISUAL_PSEUDOCOLOR;
  1251.       info->dispsw         = &fbcon_cfb8;
  1252.       display->dispsw_data = NULL;
  1253.       display->next_line   = var->xres_virtual;
  1254.       break;
  1255. #endif
  1256. #ifdef FBCON_HAS_CFB16
  1257.     case 16: /* DIRECTCOLOUR, 64k */
  1258.       var->transp.offset   = 0;
  1259.       var->transp.length   = 0;
  1260.       var->red.offset      = 11;
  1261.       var->red.length      = 5;
  1262.       var->green.offset    = 5;
  1263.       var->green.length    = 6;
  1264.       var->blue.offset     = 0;
  1265.       var->blue.length     = 5;
  1266.       fb->fix.visual       = FB_VISUAL_DIRECTCOLOR;
  1267.       info->dispsw         = &fbcon_cfb16;
  1268.       display->dispsw_data = fb->pseudo_palette;
  1269.       display->next_line   = var->xres_virtual * 2;
  1270.       break;
  1271. #endif
  1272. #ifdef FBCON_HAS_CFB24
  1273.     case 24: /* TRUECOLOUR, 16m */
  1274.       var->transp.offset   = 0;
  1275.       var->transp.length   = 0;
  1276.       var->red.offset      = 16;
  1277.       var->red.length      = 8;
  1278.       var->green.offset    = 8;
  1279.       var->green.length    = 8;
  1280.       var->blue.offset     = 0;
  1281.       var->blue.length     = 8;
  1282.       fb->fix.visual       = FB_VISUAL_TRUECOLOR;
  1283.       info->dispsw         = &fbcon_cfb24;
  1284.       display->dispsw_data = fb->pseudo_palette;
  1285.       display->next_line   = var->xres_virtual * 3;
  1286.       var->accel_flags    &= ~FB_ACCELF_TEXT;
  1287.       break;
  1288. #endif
  1289. #ifdef NO_32BIT_SUPPORT_YET
  1290. # ifdef FBCON_HAS_CFB32
  1291.     case 32: /* TRUECOLOUR, 16m */
  1292.       var->transp.offset   = 24;
  1293.       var->transp.length   = 8;
  1294.       var->red.offset      = 16;
  1295.       var->red.length      = 8;
  1296.       var->green.offset    = 8;
  1297.       var->green.length    = 8;
  1298.       var->blue.offset     = 0;
  1299.       var->blue.length     = 8;
  1300.       fb->fix.visual       = FB_VISUAL_TRUECOLOR;
  1301.       info->dispsw         = &fbcon_cfb32;
  1302.       display->dispsw_data = fb->pseudo_palette;
  1303.       display->next_line   = var->xres_virtual * 4;
  1304.       var->accel_flags    &= ~FB_ACCELF_TEXT;
  1305.       break;
  1306. # endif
  1307. #endif
  1308.     default:
  1309.       printk (KERN_WARNING "neofb: no support for %dbppn", var->bits_per_pixel);
  1310.       info->dispsw      = &fbcon_dummy;
  1311.       var->accel_flags &= ~FB_ACCELF_TEXT;
  1312.       break;
  1313.     }
  1314.   if (var->accel_flags & FB_ACCELF_TEXT)
  1315.     display->dispsw = &fbcon_neo2200_accel;
  1316.   else
  1317.     display->dispsw = info->dispsw;
  1318.   fb->fix.line_length = display->next_line;
  1319.   display->screen_base    = fb->screen_base;
  1320.   display->line_length    = fb->fix.line_length;
  1321.   display->visual         = fb->fix.visual;
  1322.   display->type           = fb->fix.type;
  1323.   display->type_aux       = fb->fix.type_aux;
  1324.   display->ypanstep       = fb->fix.ypanstep;
  1325.   display->ywrapstep      = fb->fix.ywrapstep;
  1326.   display->can_soft_blank = 1;
  1327.   display->inverse        = 0;
  1328.   fb->var = *var;
  1329.   fb->var.activate &= ~FB_ACTIVATE_ALL;
  1330.   /*
  1331.    * Update the old var.  The fbcon drivers still use this.
  1332.    * Once they are using cfb->fb.var, this can be dropped.
  1333.    * --rmk
  1334.    */
  1335.   display->var = fb->var;
  1336.   /*
  1337.    * If we are setting all the virtual consoles, also set the
  1338.    * defaults used to create new consoles.
  1339.    */
  1340.   if (var->activate & FB_ACTIVATE_ALL)
  1341.     fb->disp->var = fb->var;
  1342.   if (chgvar && fb && fb->changevar)
  1343.     fb->changevar (con);
  1344.   if (con == info->currcon)
  1345.     {
  1346.       if (chgvar || con < 0)
  1347.         neofb_set_par (info, &par);
  1348.       neofb_update_start (info, var);
  1349.       fb_set_cmap (&fb->cmap, 1, neo_setcolreg, fb);
  1350.       if (var->accel_flags & FB_ACCELF_TEXT)
  1351. neo2200_accel_init (info, var);
  1352.     }
  1353.   return 0;
  1354. }
  1355. /*
  1356.  *    Pan or Wrap the Display
  1357.  */
  1358. static int neofb_pan_display (struct fb_var_screeninfo *var, int con,
  1359.       struct fb_info *fb)
  1360. {
  1361.   struct neofb_info *info = (struct neofb_info *)fb;
  1362.   u_int y_bottom;
  1363.   y_bottom = var->yoffset;
  1364.   if (!(var->vmode & FB_VMODE_YWRAP))
  1365.     y_bottom += var->yres;
  1366.   if (var->xoffset > (var->xres_virtual - var->xres))
  1367.     return -EINVAL;
  1368.   if (y_bottom > fb->var.yres_virtual)
  1369.     return -EINVAL;
  1370.   neofb_update_start (info, var);
  1371.   fb->var.xoffset = var->xoffset;
  1372.   fb->var.yoffset = var->yoffset;
  1373.   if (var->vmode & FB_VMODE_YWRAP)
  1374.     fb->var.vmode |= FB_VMODE_YWRAP;
  1375.   else
  1376.     fb->var.vmode &= ~FB_VMODE_YWRAP;
  1377.   return 0;
  1378. }
  1379. /*
  1380.  *    Update the `var' structure (called by fbcon.c)
  1381.  *
  1382.  *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
  1383.  *    Since it's called by a kernel driver, no range checking is done.
  1384.  */
  1385. static int neofb_updatevar (int con, struct fb_info *fb)
  1386. {
  1387.   struct neofb_info *info = (struct neofb_info *)fb;
  1388.   neofb_update_start (info, &fb_display[con].var);
  1389.   return 0;
  1390. }
  1391. static int neofb_switch (int con, struct fb_info *fb)
  1392. {
  1393.   struct neofb_info *info = (struct neofb_info *)fb;
  1394.   struct display *disp;
  1395.   struct fb_cmap *cmap;
  1396.   if (info->currcon >= 0)
  1397.     {
  1398.       disp = fb_display + info->currcon;
  1399.       /*
  1400.        * Save the old colormap and video mode.
  1401.        */
  1402.       disp->var = fb->var;
  1403.       if (disp->cmap.len)
  1404. fb_copy_cmap(&fb->cmap, &disp->cmap, 0);
  1405.     }
  1406.   info->currcon = con;
  1407.   disp = fb_display + con;
  1408.   /*
  1409.    * Install the new colormap and change the video mode.  By default,
  1410.    * fbcon sets all the colormaps and video modes to the default
  1411.    * values at bootup.
  1412.    *
  1413.    * Really, we want to set the colourmap size depending on the
  1414.    * depth of the new video mode.  For now, we leave it at its
  1415.    * default 256 entry.
  1416.    */
  1417.   if (disp->cmap.len)
  1418.     cmap = &disp->cmap;
  1419.   else
  1420.     cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
  1421.   fb_copy_cmap(cmap, &fb->cmap, 0);
  1422.   disp->var.activate = FB_ACTIVATE_NOW;
  1423.   neofb_set_var(&disp->var, con, fb);
  1424.   return 0;
  1425. }
  1426. /*
  1427.  *    (Un)Blank the display.
  1428.  */
  1429. static void neofb_blank (int blank, struct fb_info *fb)
  1430. {
  1431.   //  struct neofb_info *info = (struct neofb_info *)fb;
  1432.   /*
  1433.    *  Blank the screen if blank_mode != 0, else unblank. If
  1434.    *  blank == NULL then the caller blanks by setting the CLUT
  1435.    *  (Color Look Up Table) to all black. Return 0 if blanking
  1436.    *  succeeded, != 0 if un-/blanking failed due to e.g. a
  1437.    *  video mode which doesn't support it. Implements VESA
  1438.    *  suspend and powerdown modes on hardware that supports
  1439.    *  disabling hsync/vsync:
  1440.    *    blank_mode == 2: suspend vsync
  1441.    *    blank_mode == 3: suspend hsync
  1442.    *    blank_mode == 4: powerdown
  1443.    *
  1444.    *  wms...Enable VESA DMPS compatible powerdown mode
  1445.    *  run "setterm -powersave powerdown" to take advantage
  1446.    */
  1447.      
  1448.   switch (blank)
  1449.     {
  1450.     case 4: /* powerdown - both sync lines down */
  1451.       break;
  1452.     case 3: /* hsync off */
  1453.       break;
  1454.     case 2: /* vsync off */
  1455.       break;
  1456.     case 1: /* just software blanking of screen */
  1457.       break;
  1458.     default: /* case 0, or anything else: unblank */
  1459.       break;
  1460.     }
  1461. }
  1462. /*
  1463.  * Get the currently displayed virtual consoles colormap.
  1464.  */
  1465. static int gen_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *fb)
  1466. {
  1467.   fb_copy_cmap (&fb->cmap, cmap, kspc ? 0 : 2);
  1468.   return 0;
  1469. }
  1470. /*
  1471.  * Get the currently displayed virtual consoles fixed part of the display.
  1472.  */
  1473. static int gen_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *fb)
  1474. {
  1475.   *fix = fb->fix;
  1476.   return 0;
  1477. }
  1478. /*
  1479.  * Get the current user defined part of the display.
  1480.  */
  1481. static int gen_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *fb)
  1482. {
  1483.   *var = fb->var;
  1484.   return 0;
  1485. }
  1486. static struct fb_ops neofb_ops = {
  1487.   owner:          THIS_MODULE,
  1488.   fb_set_var:     neofb_set_var,
  1489.   fb_set_cmap:    neofb_set_cmap,
  1490.   fb_pan_display: neofb_pan_display,
  1491.   fb_get_fix:     gen_get_fix,
  1492.   fb_get_var:     gen_get_var,
  1493.   fb_get_cmap:    gen_get_cmap,
  1494. };
  1495. /* --------------------------------------------------------------------- */
  1496. static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = {
  1497. accel_flags: FB_ACCELF_TEXT,
  1498. xres: 640,
  1499. yres: 480,
  1500. xres_virtual:   640,
  1501. yres_virtual:   30000,
  1502. bits_per_pixel: 8,
  1503. pixclock: 39722,
  1504. left_margin: 48,
  1505. right_margin: 16,
  1506. upper_margin: 33,
  1507. lower_margin: 10,
  1508. hsync_len: 96,
  1509. vsync_len: 2,
  1510. sync: 0,
  1511. vmode: FB_VMODE_NONINTERLACED
  1512. };
  1513. static struct fb_var_screeninfo __devinitdata neofb_var800x600x8 = {
  1514. accel_flags: FB_ACCELF_TEXT,
  1515. xres: 800,
  1516. yres: 600,
  1517. xres_virtual:   800,
  1518. yres_virtual:   30000,
  1519. bits_per_pixel: 8,
  1520. pixclock: 25000,
  1521. left_margin: 88,
  1522. right_margin: 40,
  1523. upper_margin: 23,
  1524. lower_margin: 1,
  1525. hsync_len: 128,
  1526. vsync_len: 4,
  1527. sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  1528. vmode: FB_VMODE_NONINTERLACED
  1529. };
  1530. static struct fb_var_screeninfo __devinitdata neofb_var1024x768x8 = {
  1531. accel_flags: FB_ACCELF_TEXT,
  1532. xres: 1024,
  1533. yres: 768,
  1534. xres_virtual:   1024,
  1535. yres_virtual:   30000,
  1536. bits_per_pixel: 8,
  1537. pixclock: 15385,
  1538. left_margin: 160,
  1539. right_margin: 24,
  1540. upper_margin: 29,
  1541. lower_margin: 3,
  1542. hsync_len: 136,
  1543. vsync_len: 6,
  1544. sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  1545. vmode: FB_VMODE_NONINTERLACED
  1546. };
  1547. #ifdef NOT_DONE
  1548. static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = {
  1549. accel_flags: FB_ACCELF_TEXT,
  1550. xres: 1280,
  1551. yres: 1024,
  1552. xres_virtual:   1280,
  1553. yres_virtual:   30000,
  1554. bits_per_pixel: 8,
  1555. pixclock: 9260,
  1556. left_margin: 248,
  1557. right_margin: 48,
  1558. upper_margin: 38,
  1559. lower_margin: 1,
  1560. hsync_len: 112,
  1561. vsync_len: 3,
  1562. sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
  1563. vmode: FB_VMODE_NONINTERLACED
  1564. };
  1565. #endif
  1566. static struct fb_var_screeninfo *neofb_var = NULL;
  1567. static int __devinit neo_map_mmio (struct neofb_info *info)
  1568. {
  1569.   DBG("neo_map_mmio");
  1570.   info->mmio.pbase = pci_resource_start (info->pcidev, 1);
  1571.   info->mmio.len   = MMIO_SIZE;
  1572.   if (!request_mem_region (info->mmio.pbase, MMIO_SIZE, "memory mapped I/O"))
  1573.     {
  1574.       printk ("neofb: memory mapped IO in usen");
  1575.       return -EBUSY;
  1576.     }
  1577.   info->mmio.vbase = ioremap (info->mmio.pbase, MMIO_SIZE);
  1578.   if (!info->mmio.vbase)
  1579.     {
  1580.       printk ("neofb: unable to map memory mapped IOn");
  1581.       release_mem_region (info->mmio.pbase, info->mmio.len);
  1582.       return -ENOMEM;
  1583.     }
  1584.   else
  1585.     printk (KERN_INFO "neofb: mapped io at %pn", info->mmio.vbase);
  1586.   info->fb.fix.mmio_start = info->mmio.pbase;
  1587.   info->fb.fix.mmio_len   = info->mmio.len;
  1588.   return 0;
  1589. }
  1590. static void __devinit neo_unmap_mmio (struct neofb_info *info)
  1591. {
  1592.   DBG("neo_unmap_mmio");
  1593.   if (info->mmio.vbase)
  1594.     {
  1595.       iounmap (info->mmio.vbase);
  1596.       info->mmio.vbase = NULL;
  1597.       release_mem_region (info->mmio.pbase, info->mmio.len);
  1598.     }
  1599. }
  1600. static int __devinit neo_map_video (struct neofb_info *info, int video_len)
  1601. {
  1602.   DBG("neo_map_video");
  1603.   info->video.pbase = pci_resource_start (info->pcidev, 0);
  1604.   info->video.len   = video_len;
  1605.   if (!request_mem_region (info->video.pbase, info->video.len, "frame buffer"))
  1606.     {
  1607.       printk ("neofb: frame buffer in usen");
  1608.       return -EBUSY;
  1609.     }
  1610.   info->video.vbase = ioremap (info->video.pbase, info->video.len);
  1611.   if (!info->video.vbase)
  1612.     {
  1613.       printk ("neofb: unable to map screen memoryn");
  1614.       release_mem_region (info->video.pbase, info->video.len);
  1615.       return -ENOMEM;
  1616.     }
  1617.   else
  1618.     printk (KERN_INFO "neofb: mapped framebuffer at %pn", info->video.vbase);
  1619.   info->fb.fix.smem_start = info->video.pbase;
  1620.   info->fb.fix.smem_len   = info->video.len;
  1621.   info->fb.screen_base    = info->video.vbase;
  1622. #ifdef CONFIG_MTRR
  1623.   info->video.mtrr = mtrr_add (info->video.pbase, pci_resource_len (info->pcidev, 0), MTRR_TYPE_WRCOMB, 1);
  1624. #endif
  1625.   /* Clear framebuffer, it's all white in memory after boot */
  1626.   memset (info->video.vbase, 0, info->video.len);
  1627.   return 0;
  1628. }
  1629. static void __devinit neo_unmap_video (struct neofb_info *info)
  1630. {
  1631.   DBG("neo_unmap_video");
  1632.   if (info->video.vbase)
  1633.     {
  1634. #ifdef CONFIG_MTRR
  1635.       mtrr_del (info->video.mtrr, info->video.pbase, info->video.len);
  1636. #endif
  1637.       iounmap (info->video.vbase);
  1638.       info->video.vbase = NULL;
  1639.       info->fb.screen_base = NULL;
  1640.       release_mem_region (info->video.pbase, info->video.len);
  1641.     }
  1642. }
  1643. static int __devinit neo_init_hw (struct neofb_info *info)
  1644. {
  1645.   int videoRam = 896;
  1646.   int maxClock = 65000;
  1647.   int CursorMem = 1024;
  1648.   int CursorOff = 0x100;
  1649.   int linearSize = 1024;
  1650.   int maxWidth = 1024;
  1651.   int maxHeight = 1024;
  1652.   unsigned char type, display;
  1653.   int w;
  1654.     
  1655.   DBG("neo_init_hw");
  1656.   neoUnlock();
  1657. #if 0
  1658.   printk (KERN_DEBUG "--- Neo extended register dump ---n");
  1659.   for (w=0; w<0x85; w++)
  1660.     printk (KERN_DEBUG "CR %p: %pn", (void*)w, (void*)VGArCR (w));
  1661.   for (w=0; w<0xC7; w++)
  1662.     printk (KERN_DEBUG "GR %p: %pn", (void*)w, (void*)VGArGR (w));
  1663. #endif
  1664.   /* Determine the panel type */
  1665.   VGAwGR(0x09,0x26);
  1666.   type = VGArGR(0x21);
  1667.   display = VGArGR(0x20);
  1668.     
  1669.   /* Determine panel width -- used in NeoValidMode. */
  1670.   w = VGArGR(0x20);
  1671.   VGAwGR(0x09,0x00);
  1672.   switch ((w & 0x18) >> 3)
  1673.     {
  1674.     case 0x00:
  1675.       info->NeoPanelWidth  = 640;
  1676.       info->NeoPanelHeight = 480;
  1677.       neofb_var = &neofb_var640x480x8;
  1678.       break;
  1679.     case 0x01:
  1680.       info->NeoPanelWidth  = 800;
  1681.       info->NeoPanelHeight = 600;
  1682.       neofb_var = &neofb_var800x600x8;
  1683.       break;
  1684.     case 0x02:
  1685.       info->NeoPanelWidth  = 1024;
  1686.       info->NeoPanelHeight = 768;
  1687.       neofb_var = &neofb_var1024x768x8;
  1688.       break;
  1689.     case 0x03:
  1690.       /* 1280x1024 panel support needs to be added */
  1691. #ifdef NOT_DONE
  1692.       info->NeoPanelWidth  = 1280;
  1693.       info->NeoPanelHeight = 1024;
  1694.       neofb_var = &neofb_var1280x1024x8;
  1695.       break;
  1696. #else
  1697.       printk (KERN_ERR "neofb: Only 640x480, 800x600 and 1024x768 panels are currently supportedn");
  1698.       return -1;
  1699. #endif
  1700.     default:
  1701.       info->NeoPanelWidth  = 640;
  1702.       info->NeoPanelHeight = 480;
  1703.       neofb_var = &neofb_var640x480x8;
  1704.       break;
  1705.     }
  1706.   printk (KERN_INFO "Panel is a %dx%d %s %s displayn",
  1707.   info->NeoPanelWidth,
  1708.   info->NeoPanelHeight,
  1709.   (type & 0x02) ? "color" : "monochrome",
  1710.   (type & 0x10) ? "TFT" : "dual scan");
  1711.   switch (info->accel)
  1712.     {
  1713.     case FB_ACCEL_NEOMAGIC_NM2070:
  1714.       videoRam   = 896;
  1715.       maxClock   = 65000;
  1716.       CursorMem  = 2048;
  1717.       CursorOff  = 0x100;
  1718.       linearSize = 1024;
  1719.       maxWidth   = 1024;
  1720.       maxHeight  = 1024;
  1721.       break;
  1722.     case FB_ACCEL_NEOMAGIC_NM2090:
  1723.     case FB_ACCEL_NEOMAGIC_NM2093:
  1724.       videoRam   = 1152;
  1725.       maxClock   = 80000;
  1726.       CursorMem  = 2048;
  1727.       CursorOff  = 0x100;
  1728.       linearSize = 2048;
  1729.       maxWidth   = 1024;
  1730.       maxHeight  = 1024;
  1731.       break;
  1732.     case FB_ACCEL_NEOMAGIC_NM2097:
  1733.       videoRam   = 1152;
  1734.       maxClock   = 80000;
  1735.       CursorMem  = 1024;
  1736.       CursorOff  = 0x100;
  1737.       linearSize = 2048;
  1738.       maxWidth   = 1024;
  1739.       maxHeight  = 1024;
  1740.       break;
  1741.     case FB_ACCEL_NEOMAGIC_NM2160:
  1742.       videoRam   = 2048;
  1743.       maxClock   = 90000;
  1744.       CursorMem  = 1024;
  1745.       CursorOff  = 0x100;
  1746.       linearSize = 2048;
  1747.       maxWidth   = 1024;
  1748.       maxHeight  = 1024;
  1749.       break;
  1750.     case FB_ACCEL_NEOMAGIC_NM2200:
  1751.       videoRam   = 2560;
  1752.       maxClock   = 110000;
  1753.       CursorMem  = 1024;
  1754.       CursorOff  = 0x1000;
  1755.       linearSize = 4096;
  1756.       maxWidth   = 1280;
  1757.       maxHeight  = 1024;  /* ???? */
  1758.       info->neo2200 = (Neo2200*) info->mmio.vbase;
  1759.       break;
  1760.     case FB_ACCEL_NEOMAGIC_NM2230:
  1761.       videoRam   = 3008;
  1762.       maxClock   = 110000;
  1763.       CursorMem  = 1024;
  1764.       CursorOff  = 0x1000;
  1765.       linearSize = 4096;
  1766.       maxWidth   = 1280;
  1767.       maxHeight  = 1024;  /* ???? */
  1768.       info->neo2200 = (Neo2200*) info->mmio.vbase;
  1769.       break;
  1770.     case FB_ACCEL_NEOMAGIC_NM2360:
  1771.       videoRam   = 4096;
  1772.       maxClock   = 110000;
  1773.       CursorMem  = 1024;
  1774.       CursorOff  = 0x1000;
  1775.       linearSize = 4096;
  1776.       maxWidth   = 1280;
  1777.       maxHeight  = 1024;  /* ???? */
  1778.       info->neo2200 = (Neo2200*) info->mmio.vbase;
  1779.       break;
  1780.     case FB_ACCEL_NEOMAGIC_NM2380:
  1781.       videoRam   = 6144;
  1782.       maxClock   = 110000;
  1783.       CursorMem  = 1024;
  1784.       CursorOff  = 0x1000;
  1785.       linearSize = 8192;
  1786.       maxWidth   = 1280;
  1787.       maxHeight  = 1024;  /* ???? */
  1788.       info->neo2200 = (Neo2200*) info->mmio.vbase;
  1789.       break;
  1790.     }
  1791.   info->maxClock = maxClock;
  1792.   return videoRam * 1024;
  1793. }
  1794. static struct neofb_info * __devinit neo_alloc_fb_info (struct pci_dev *dev,
  1795. const struct pci_device_id *id)
  1796. {
  1797.   struct neofb_info *info;
  1798.   info = kmalloc (sizeof(struct neofb_info) + sizeof(struct display) +
  1799.   sizeof(u32) * 16, GFP_KERNEL);
  1800.   if (!info)
  1801.     return NULL;
  1802.   memset (info, 0, sizeof(struct neofb_info) + sizeof(struct display));
  1803.   info->currcon = -1;
  1804.   info->pcidev  = dev;
  1805.   info->accel   = id->driver_data;
  1806.   info->pci_burst   = !nopciburst;
  1807.   info->lcd_stretch = !nostretch;
  1808.   if (!internal && !external)
  1809.     {
  1810.       info->internal_display = 1;
  1811.       info->external_display = 0;
  1812.     }
  1813.   else
  1814.     {
  1815.       info->internal_display = internal;
  1816.       info->external_display = external;
  1817.     }
  1818.   switch (info->accel)
  1819.     {
  1820.     case FB_ACCEL_NEOMAGIC_NM2070:
  1821.       sprintf (info->fb.fix.id, "MagicGraph 128");
  1822.       break;
  1823.     case FB_ACCEL_NEOMAGIC_NM2090:
  1824.       sprintf (info->fb.fix.id, "MagicGraph 128V");
  1825.       break;
  1826.     case FB_ACCEL_NEOMAGIC_NM2093:
  1827.       sprintf (info->fb.fix.id, "MagicGraph 128ZV");
  1828.       break;
  1829.     case FB_ACCEL_NEOMAGIC_NM2097:
  1830.       sprintf (info->fb.fix.id, "MagicGraph 128ZV+");
  1831.       break;
  1832.     case FB_ACCEL_NEOMAGIC_NM2160:
  1833.       sprintf (info->fb.fix.id, "MagicGraph 128XD");
  1834.       break;
  1835.     case FB_ACCEL_NEOMAGIC_NM2200:
  1836.       sprintf (info->fb.fix.id, "MagicGraph 256AV");
  1837.       break;
  1838.     case FB_ACCEL_NEOMAGIC_NM2230:
  1839.       sprintf (info->fb.fix.id, "MagicGraph 256AV+");
  1840.       break;
  1841.     case FB_ACCEL_NEOMAGIC_NM2360:
  1842.       sprintf (info->fb.fix.id, "MagicGraph 256ZX");
  1843.       break;
  1844.     case FB_ACCEL_NEOMAGIC_NM2380:
  1845.       sprintf (info->fb.fix.id, "MagicGraph 256XL+");
  1846.       break;
  1847.     }
  1848.   info->fb.fix.type    = FB_TYPE_PACKED_PIXELS;
  1849.   info->fb.fix.type_aux    = 0;
  1850.   info->fb.fix.xpanstep    = 0;
  1851.   info->fb.fix.ypanstep    = 4;
  1852.   info->fb.fix.ywrapstep   = 0;
  1853.   info->fb.fix.accel       = id->driver_data;
  1854.   info->fb.var.nonstd      = 0;
  1855.   info->fb.var.activate    = FB_ACTIVATE_NOW;
  1856.   info->fb.var.height      = -1;
  1857.   info->fb.var.width       = -1;
  1858.   info->fb.var.accel_flags = 0;
  1859.   strcpy (info->fb.modename, info->fb.fix.id);
  1860.   info->fb.fbops          = &neofb_ops;
  1861.   info->fb.changevar      = NULL;
  1862.   info->fb.switch_con     = neofb_switch;
  1863.   info->fb.updatevar      = neofb_updatevar;
  1864.   info->fb.blank          = neofb_blank;
  1865.   info->fb.flags          = FBINFO_FLAG_DEFAULT;
  1866.   info->fb.disp           = (struct display *)(info + 1);
  1867.   info->fb.pseudo_palette = (void *)(info->fb.disp + 1);
  1868.   fb_alloc_cmap (&info->fb.cmap, NR_PALETTE, 0);
  1869.   return info;
  1870. }
  1871. static void __devinit neo_free_fb_info (struct neofb_info *info)
  1872. {
  1873.   if (info)
  1874.     {
  1875.       /*
  1876.        * Free the colourmap
  1877.        */
  1878.       fb_alloc_cmap (&info->fb.cmap, 0, 0);
  1879.       kfree (info);
  1880.     }
  1881. }
  1882. /* --------------------------------------------------------------------- */
  1883. static int __devinit neofb_probe (struct pci_dev* dev, const struct pci_device_id* id)
  1884. {
  1885.   struct neofb_info *info;
  1886.   u_int h_sync, v_sync;
  1887.   int err;
  1888.   int video_len;
  1889.   DBG("neofb_probe");
  1890.   err = pci_enable_device (dev);
  1891.   if (err)
  1892.     return err;
  1893.   err = -ENOMEM;
  1894.   info = neo_alloc_fb_info (dev, id);
  1895.   if (!info)
  1896.     goto failed;
  1897.   err = neo_map_mmio (info);
  1898.   if (err)
  1899.     goto failed;
  1900.   video_len = neo_init_hw (info);
  1901.   if (video_len < 0)
  1902.     {
  1903.       err = video_len;
  1904.       goto failed;
  1905.     }
  1906.   err = neo_map_video (info, video_len);
  1907.   if (err)
  1908.     goto failed;
  1909.   neofb_set_var (neofb_var, -1, &info->fb);
  1910.   /*
  1911.    * Calculate the hsync and vsync frequencies.  Note that
  1912.    * we split the 1e12 constant up so that we can preserve
  1913.    * the precision and fit the results into 32-bit registers.
  1914.    *  (1953125000 * 512 = 1e12)
  1915.    */
  1916.   h_sync = 1953125000 / info->fb.var.pixclock;
  1917.   h_sync = h_sync * 512 / (info->fb.var.xres + info->fb.var.left_margin +
  1918.    info->fb.var.right_margin + info->fb.var.hsync_len);
  1919.   v_sync = h_sync / (info->fb.var.yres + info->fb.var.upper_margin +
  1920.      info->fb.var.lower_margin + info->fb.var.vsync_len);
  1921.   printk(KERN_INFO "neofb v" NEOFB_VERSION ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHzn",
  1922.  info->fb.fix.smem_len >> 10,
  1923.  info->fb.var.xres, info->fb.var.yres,
  1924.  h_sync / 1000, h_sync % 1000, v_sync);
  1925.   err = register_framebuffer (&info->fb);
  1926.   if (err < 0)
  1927.     goto failed;
  1928.   printk (KERN_INFO "fb%d: %s frame buffer devicen",
  1929.   GET_FB_IDX(info->fb.node), info->fb.modename);
  1930.   /*
  1931.    * Our driver data
  1932.    */
  1933.   dev->driver_data = info;
  1934.   return 0;
  1935. failed:
  1936.   neo_unmap_video (info);
  1937.   neo_unmap_mmio (info);
  1938.   neo_free_fb_info (info);
  1939.   return err;
  1940. }
  1941. static void __devexit neofb_remove (struct pci_dev *dev)
  1942. {
  1943.   struct neofb_info *info = (struct neofb_info *)dev->driver_data;
  1944.   DBG("neofb_remove");
  1945.   if (info)
  1946.     {
  1947.       /*
  1948.        * If unregister_framebuffer fails, then
  1949.        * we will be leaving hooks that could cause
  1950.        * oopsen laying around.
  1951.        */
  1952.       if (unregister_framebuffer (&info->fb))
  1953. printk (KERN_WARNING "neofb: danger danger!  Oopsen imminent!n");
  1954.       neo_unmap_video (info);
  1955.       neo_unmap_mmio (info);
  1956.       neo_free_fb_info (info);
  1957.       /*
  1958.        * Ensure that the driver data is no longer
  1959.        * valid.
  1960.        */
  1961.       dev->driver_data = NULL;
  1962.     }
  1963. }
  1964. static struct pci_device_id neofb_devices[] __devinitdata = {
  1965.   {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070,
  1966.    PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070},
  1967.   {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090,
  1968.    PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090},
  1969.   {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093,
  1970.    PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093},
  1971.   {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097,
  1972.    PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097},
  1973.   {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160,
  1974.    PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160},
  1975.   {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200,
  1976.    PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200},
  1977.   {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230,
  1978.    PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230},
  1979.   {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360,
  1980.    PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360},
  1981.   {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380,
  1982.    PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380},
  1983.   {0, 0, 0, 0, 0, 0, 0}
  1984. };
  1985. MODULE_DEVICE_TABLE(pci, neofb_devices);
  1986. static struct pci_driver neofb_driver = {
  1987.   name:      "neofb",
  1988.   id_table:  neofb_devices,
  1989.   probe:     neofb_probe,
  1990.   remove:    __devexit_p(neofb_remove)
  1991. };
  1992. /* **************************** init-time only **************************** */
  1993. static void __init neo_init (void)
  1994. {
  1995.   DBG("neo_init");
  1996.   pci_register_driver (&neofb_driver);
  1997. }
  1998. /* **************************** exit-time only **************************** */
  1999. static void __exit neo_done (void)
  2000. {
  2001.   DBG("neo_done");
  2002.   pci_unregister_driver (&neofb_driver);
  2003. }
  2004. #ifndef MODULE
  2005. /* ************************* init in-kernel code ************************** */
  2006. int __init neofb_setup (char *options)
  2007. {
  2008.   char *this_opt;
  2009.   DBG("neofb_setup");
  2010.   if (!options || !*options)
  2011.     return 0;
  2012.   for (this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,","))
  2013.     {
  2014.       if (!*this_opt) continue;
  2015.       if (!strncmp(this_opt, "disabled", 8))
  2016. disabled = 1;
  2017.       if (!strncmp(this_opt, "internal", 8))
  2018. internal = 1;
  2019.       if (!strncmp(this_opt, "external", 8))
  2020. external = 1;
  2021.       if (!strncmp(this_opt, "nostretch", 9))
  2022. nostretch = 1;
  2023.       if (!strncmp(this_opt, "nopciburst", 10))
  2024. nopciburst = 1;
  2025.     }
  2026.   return 0;
  2027. }
  2028. static int __initdata initialized = 0;
  2029. int __init neofb_init(void)
  2030. {
  2031.   DBG("neofb_init");
  2032.   if (disabled)
  2033.     return -ENXIO;
  2034.   if (!initialized)
  2035.     {
  2036.       initialized = 1;
  2037.       neo_init();
  2038.     }
  2039.   /* never return failure, user can hotplug card later... */
  2040.   return 0;
  2041. }
  2042. #else
  2043. /* *************************** init module code **************************** */
  2044. int __init init_module(void)
  2045. {
  2046.   DBG("init_module");
  2047.   if (disabled)
  2048.     return -ENXIO;
  2049.   neo_init();
  2050.   /* never return failure; user can hotplug card later... */
  2051.   return 0;
  2052. }
  2053. #endif /* MODULE */
  2054. module_exit(neo_done);