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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/video/sgivwfb.c -- SGI DBE frame buffer device
  3.  *
  4.  * Copyright (C) 1999 Silicon Graphics, Inc.
  5.  *      Jeffrey Newquist, newquist@engr.sgi.som
  6.  *
  7.  *  This file is subject to the terms and conditions of the GNU General Public
  8.  *  License. See the file COPYING in the main directory of this archive for
  9.  *  more details.
  10.  */
  11. #include <linux/config.h>
  12. #include <linux/module.h>
  13. #include <linux/kernel.h>
  14. #include <linux/errno.h>
  15. #include <linux/string.h>
  16. #include <linux/mm.h>
  17. #include <linux/tty.h>
  18. #include <linux/slab.h>
  19. #include <linux/vmalloc.h>
  20. #include <linux/delay.h>
  21. #include <linux/interrupt.h>
  22. #include <asm/uaccess.h>
  23. #include <linux/fb.h>
  24. #include <linux/init.h>
  25. #include <asm/io.h>
  26. #include <asm/mtrr.h>
  27. #include <video/fbcon.h>
  28. #include <video/fbcon-cfb8.h>
  29. #include <video/fbcon-cfb16.h>
  30. #include <video/fbcon-cfb32.h>
  31. #define INCLUDE_TIMING_TABLE_DATA
  32. #define DBE_REG_BASE regs
  33. #include "sgivwfb.h"
  34. struct sgivwfb_par {
  35.   struct fb_var_screeninfo var;
  36.   u_long timing_num;
  37.   int valid;
  38. };
  39. /*
  40.  *  RAM we reserve for the frame buffer. This defines the maximum screen
  41.  *  size
  42.  *
  43.  *  The default can be overridden if the driver is compiled as a module
  44.  */
  45. /* set by arch/i386/kernel/setup.c */
  46. u_long                sgivwfb_mem_phys;
  47. u_long                sgivwfb_mem_size;
  48. static volatile char  *fbmem;
  49. static asregs         *regs;
  50. static struct fb_info fb_info;
  51. static struct { u_char red, green, blue, pad; } palette[256];
  52. static char           sgivwfb_name[16] = "SGI Vis WS FB";
  53. static u32            cmap_fifo;
  54. static int            ypan       = 0;
  55. static int            ywrap      = 0;
  56. /* console related variables */
  57. static int currcon = 0;
  58. static struct display disp;
  59. static union {
  60. #ifdef FBCON_HAS_CFB16
  61.   u16 cfb16[16];
  62. #endif
  63. #ifdef FBCON_HAS_CFB32
  64.   u32 cfb32[16];
  65. #endif
  66. } fbcon_cmap;
  67. static struct sgivwfb_par par_current = {
  68.   {                             /* var (screeninfo) */
  69.     /* 640x480, 8 bpp */
  70.     640, 480, 640, 480, 0, 0, 8, 0,
  71.     {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  72.     0, 0, -1, -1, 0, 20000, 64, 64, 32, 32, 64, 2,
  73.     0, FB_VMODE_NONINTERLACED
  74.   },
  75.   0,                            /* timing_num */
  76.   0 /* par not activated */
  77. };
  78. /*
  79.  *  Interface used by the world
  80.  */
  81. int sgivwfb_setup(char*);
  82. static int sgivwfb_get_fix(struct fb_fix_screeninfo *fix, int con,
  83.    struct fb_info *info);
  84. static int sgivwfb_get_var(struct fb_var_screeninfo *var, int con,
  85.    struct fb_info *info);
  86. static int sgivwfb_set_var(struct fb_var_screeninfo *var, int con,
  87.    struct fb_info *info);
  88. static int sgivwfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  89.     struct fb_info *info);
  90. static int sgivwfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  91.     struct fb_info *info);
  92. static int sgivwfb_mmap(struct fb_info *info, struct file *file,
  93.                         struct vm_area_struct *vma);
  94. static struct fb_ops sgivwfb_ops = {
  95. owner: THIS_MODULE,
  96. fb_get_fix: sgivwfb_get_fix,
  97. fb_get_var: sgivwfb_get_var,
  98. fb_set_var: sgivwfb_set_var,
  99. fb_get_cmap: sgivwfb_get_cmap,
  100. fb_set_cmap: sgivwfb_set_cmap,
  101. fb_mmap: sgivwfb_mmap,
  102. };
  103. /*
  104.  *  Interface to the low level console driver
  105.  */
  106. int sgivwfb_init(void);
  107. static int sgivwfbcon_switch(int con, struct fb_info *info);
  108. static int sgivwfbcon_updatevar(int con, struct fb_info *info);
  109. static void sgivwfbcon_blank(int blank, struct fb_info *info);
  110. /*
  111.  *  Internal routines
  112.  */
  113. static u_long get_line_length(int xres_virtual, int bpp);
  114. static unsigned long bytes_per_pixel(int bpp);
  115. static void activate_par(struct sgivwfb_par *par);
  116. static void sgivwfb_encode_fix(struct fb_fix_screeninfo *fix,
  117.        struct fb_var_screeninfo *var);
  118. static int sgivwfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
  119.      u_int *transp, struct fb_info *info);
  120. static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  121.      u_int transp, struct fb_info *info);
  122. static void do_install_cmap(int con, struct fb_info *info);
  123. static unsigned long get_line_length(int xres_virtual, int bpp)
  124. {
  125.   return(xres_virtual * bytes_per_pixel(bpp));
  126. }
  127. static unsigned long bytes_per_pixel(int bpp)
  128. {
  129.   unsigned long length;
  130.   switch (bpp) {
  131.   case 8:
  132.     length = 1;
  133.     break;
  134.   case 16:
  135.     length = 2;
  136.     break;
  137.   case 32:
  138.     length = 4;
  139.     break;
  140.   default:
  141.     printk(KERN_INFO "sgivwfb: unsupported bpp=%dn", bpp);
  142.     length = 0;
  143.     break;
  144.   }
  145.   return(length);
  146. }
  147. /*
  148.  * Function: dbe_TurnOffDma
  149.  * Parameters: (None)
  150.  * Description: This should turn off the monitor and dbe.  This is used
  151.  *              when switching between the serial console and the graphics
  152.  *              console.
  153.  */
  154. static void dbe_TurnOffDma(void)
  155. {
  156.   int i;
  157.   unsigned int readVal;
  158.   // Check to see if things are already turned off:
  159.   // 1) Check to see if dbe is not using the internal dotclock.
  160.   // 2) Check to see if the xy counter in dbe is already off.
  161.   DBE_GETREG(ctrlstat, readVal);
  162.   if (GET_DBE_FIELD(CTRLSTAT, PCLKSEL, readVal) < 2)
  163.     return;
  164.   DBE_GETREG(vt_xy, readVal);
  165.   if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)
  166.     return;
  167.   // Otherwise, turn off dbe
  168.   DBE_GETREG(ovr_control, readVal);
  169.   SET_DBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, readVal, 0);
  170.   DBE_SETREG(ovr_control, readVal);
  171.   udelay(1000);
  172.   DBE_GETREG(frm_control, readVal);
  173.   SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, readVal, 0);
  174.   DBE_SETREG(frm_control, readVal);
  175.   udelay(1000);
  176.   DBE_GETREG(did_control, readVal);
  177.   SET_DBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, readVal, 0);
  178.   DBE_SETREG(did_control, readVal);
  179.   udelay(1000);
  180.   // XXX HACK:
  181.   //
  182.   //    This was necessary for GBE--we had to wait through two
  183.   //    vertical retrace periods before the pixel DMA was
  184.   //    turned off for sure.  I've left this in for now, in
  185.   //    case dbe needs it.
  186.   for (i = 0; i < 10000; i++)
  187.     {
  188.       DBE_GETREG(frm_inhwctrl, readVal);
  189.       if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) == 0)
  190.         udelay(10);
  191.       else
  192.         {
  193.           DBE_GETREG(ovr_inhwctrl, readVal);
  194.           if (GET_DBE_FIELD(OVR_INHWCTRL, OVR_DMA_ENABLE, readVal) == 0)
  195.             udelay(10);
  196.           else
  197.             {
  198.               DBE_GETREG(did_inhwctrl, readVal);
  199.               if (GET_DBE_FIELD(DID_INHWCTRL, DID_DMA_ENABLE, readVal) == 0)
  200.                 udelay(10);
  201.               else
  202.                 break;
  203.             }
  204.         }
  205.     }
  206. }
  207. /*
  208.  *  Set the hardware according to 'par'.
  209.  */
  210. static void activate_par(struct sgivwfb_par *par)
  211. {
  212.   int i,j, htmp, temp;
  213.   u32 readVal, outputVal;
  214.   int wholeTilesX, maxPixelsPerTileX;
  215.   int frmWrite1, frmWrite2, frmWrite3b;
  216.   dbe_timing_info_t *currentTiming;    /* Current Video Timing */
  217.   int xpmax, ypmax;                       // Monitor resolution
  218.   int bytesPerPixel;                      // Bytes per pixel
  219.   currentTiming = &dbeVTimings[par->timing_num];
  220.   bytesPerPixel = bytes_per_pixel(par->var.bits_per_pixel);
  221.   xpmax = currentTiming->width;
  222.   ypmax = currentTiming->height;
  223.   /* dbe_InitGraphicsBase(); */
  224.   /* Turn on dotclock PLL */
  225.   DBE_SETREG(ctrlstat, 0x20000000);
  226.   dbe_TurnOffDma();
  227.   /* dbe_CalculateScreenParams(); */
  228.   maxPixelsPerTileX = 512/bytesPerPixel;
  229.   wholeTilesX = xpmax/maxPixelsPerTileX;
  230.   if (wholeTilesX*maxPixelsPerTileX < xpmax)
  231.     wholeTilesX++;
  232.   printk(KERN_DEBUG "sgivwfb: pixPerTile=%d wholeTilesX=%dn",
  233.  maxPixelsPerTileX, wholeTilesX);
  234.   /* dbe_InitGammaMap(); */
  235.   udelay(10);
  236.   for (i = 0; i < 256; i++)
  237.     {
  238.       DBE_ISETREG(gmap, i, (i << 24) | (i << 16) | (i << 8));
  239.     }
  240.   /* dbe_TurnOn(); */
  241.   DBE_GETREG(vt_xy, readVal);
  242.   if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)
  243.     {
  244.       DBE_SETREG(vt_xy, 0x00000000);
  245.       udelay(1);
  246.     }
  247.   else
  248.     dbe_TurnOffDma();
  249.   /* dbe_Initdbe(); */
  250.   for (i = 0; i < 256; i++)
  251.     {
  252.       for (j = 0; j < 100; j++)
  253.         {
  254.           DBE_GETREG(cm_fifo, readVal);
  255.           if (readVal != 0x00000000)
  256.             break;
  257.           else
  258.             udelay(10);
  259.         }
  260.       // DBE_ISETREG(cmap, i, 0x00000000);
  261.       DBE_ISETREG(cmap, i, (i<<8)|(i<<16)|(i<<24));
  262.     }
  263.   /* dbe_InitFramebuffer(); */
  264.   frmWrite1 = 0;
  265.   SET_DBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, frmWrite1, wholeTilesX);
  266.   SET_DBE_FIELD(FRM_SIZE_TILE, FRM_RHS, frmWrite1, 0);
  267.   switch(bytesPerPixel)
  268.     {
  269.       case 1:
  270.         SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_8);
  271.         break;
  272.       case 2:
  273.         SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_16);
  274.         break;
  275.       case 4:
  276.         SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_32);
  277.         break;
  278.     }
  279.   frmWrite2 = 0;
  280.   SET_DBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, frmWrite2, ypmax);
  281.   // Tell dbe about the framebuffer location and type
  282.   // XXX What format is the FRM_TILE_PTR??  64K aligned address?
  283.   frmWrite3b = 0;
  284.   SET_DBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, frmWrite3b, sgivwfb_mem_phys>>9);
  285.   SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, frmWrite3b, 1);
  286.   SET_DBE_FIELD(FRM_CONTROL, FRM_LINEAR, frmWrite3b, 1);
  287.   /* Initialize DIDs */
  288.   outputVal = 0;
  289.   switch(bytesPerPixel)
  290.     {
  291.       case 1:
  292.         SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_I8);
  293.         break;
  294.       case 2:
  295.         SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGBA5);
  296.         break;
  297.       case 4:
  298.         SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGB8);
  299.         break;
  300.     }
  301.   SET_DBE_FIELD(WID, BUF, outputVal, DBE_BMODE_BOTH);
  302.   for (i = 0; i < 32; i++)
  303.     {
  304.       DBE_ISETREG(mode_regs, i, outputVal);
  305.     }
  306.   /* dbe_InitTiming(); */
  307.   DBE_SETREG(vt_intr01, 0xffffffff);
  308.   DBE_SETREG(vt_intr23, 0xffffffff);
  309.   DBE_GETREG(dotclock, readVal);
  310.   DBE_SETREG(dotclock, readVal & 0xffff);
  311.   DBE_SETREG(vt_xymax, 0x00000000);
  312.   outputVal = 0;
  313.   SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_ON, outputVal, currentTiming->vsync_start);
  314.   SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_OFF, outputVal, currentTiming->vsync_end);
  315.   DBE_SETREG(vt_vsync, outputVal);
  316.   outputVal = 0;
  317.   SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_ON, outputVal, currentTiming->hsync_start);
  318.   SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_OFF, outputVal, currentTiming->hsync_end);
  319.   DBE_SETREG(vt_hsync, outputVal);
  320.   outputVal = 0;
  321.   SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_ON, outputVal, currentTiming->vblank_start);
  322.   SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_OFF, outputVal, currentTiming->vblank_end);
  323.   DBE_SETREG(vt_vblank, outputVal);
  324.   outputVal = 0;
  325.   SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_ON, outputVal, currentTiming->hblank_start);
  326.   SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_OFF, outputVal, currentTiming->hblank_end-3);
  327.   DBE_SETREG(vt_hblank, outputVal);
  328.   outputVal = 0;
  329.   SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_ON, outputVal, currentTiming->vblank_start);
  330.   SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_OFF, outputVal, currentTiming->vblank_end);
  331.   DBE_SETREG(vt_vcmap, outputVal);
  332.   outputVal = 0;
  333.   SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_ON, outputVal, currentTiming->hblank_start);
  334.   SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_OFF, outputVal, currentTiming->hblank_end-3);
  335.   DBE_SETREG(vt_hcmap, outputVal);
  336.   outputVal = 0;
  337.   temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;
  338.   if (temp > 0)
  339.     temp = -temp;
  340.   SET_DBE_FIELD(DID_START_XY, DID_STARTY, outputVal, (u32)temp);
  341.   if (currentTiming->hblank_end >= 20)
  342.     SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
  343.                       currentTiming->hblank_end - 20);
  344.   else
  345.     SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,
  346.                       currentTiming->htotal - (20 - currentTiming->hblank_end));
  347.   DBE_SETREG(did_start_xy, outputVal);
  348.   outputVal = 0;
  349.   SET_DBE_FIELD(CRS_START_XY, CRS_STARTY, outputVal, (u32)(temp+1));
  350.   if (currentTiming->hblank_end >= DBE_CRS_MAGIC)
  351.     SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
  352.                       currentTiming->hblank_end - DBE_CRS_MAGIC);
  353.   else
  354.     SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,
  355.                       currentTiming->htotal - (DBE_CRS_MAGIC - currentTiming->hblank_end));
  356.   DBE_SETREG(crs_start_xy, outputVal);
  357.   outputVal = 0;
  358.   SET_DBE_FIELD(VC_START_XY, VC_STARTY, outputVal, (u32)temp);
  359.   SET_DBE_FIELD(VC_START_XY, VC_STARTX, outputVal,
  360.                     currentTiming->hblank_end - 4);
  361.   DBE_SETREG(vc_start_xy, outputVal);
  362.   DBE_SETREG(frm_size_tile, frmWrite1);
  363.   DBE_SETREG(frm_size_pixel, frmWrite2);
  364.   outputVal = 0;
  365.   SET_DBE_FIELD(DOTCLK, M, outputVal, currentTiming->pll_m-1);
  366.   SET_DBE_FIELD(DOTCLK, N, outputVal, currentTiming->pll_n-1);
  367.   SET_DBE_FIELD(DOTCLK, P, outputVal, currentTiming->pll_p);
  368.   SET_DBE_FIELD(DOTCLK, RUN, outputVal, 1);
  369.   DBE_SETREG(dotclock, outputVal);
  370.   udelay(11*1000);
  371.   DBE_SETREG(vt_vpixen, 0xffffff);
  372.   DBE_SETREG(vt_hpixen, 0xffffff);
  373.   outputVal = 0;
  374.   SET_DBE_FIELD(VT_XYMAX, VT_MAXX, outputVal, currentTiming->htotal);
  375.   SET_DBE_FIELD(VT_XYMAX, VT_MAXY, outputVal, currentTiming->vtotal);
  376.   DBE_SETREG(vt_xymax, outputVal);
  377.   outputVal = frmWrite1;
  378.   SET_DBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, outputVal, 1);
  379.   DBE_SETREG(frm_size_tile, outputVal);
  380.   DBE_SETREG(frm_size_tile, frmWrite1);
  381.   outputVal = 0;
  382.   SET_DBE_FIELD(OVR_WIDTH_TILE, OVR_FIFO_RESET, outputVal, 1);
  383.   DBE_SETREG(ovr_width_tile, outputVal);
  384.   DBE_SETREG(ovr_width_tile, 0);
  385.   DBE_SETREG(frm_control, frmWrite3b);
  386.   DBE_SETREG(did_control, 0);
  387.   // Wait for dbe to take frame settings
  388.   for (i=0; i<100000; i++)
  389.     {
  390.       DBE_GETREG(frm_inhwctrl, readVal);
  391.       if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) != 0)
  392.         break;
  393.       else
  394.         udelay(1);
  395.     }
  396.   if (i==100000)
  397.     printk(KERN_INFO "sgivwfb: timeout waiting for frame DMA enable.n");
  398.   outputVal = 0;
  399.   htmp = currentTiming->hblank_end - 19;
  400.   if (htmp < 0)
  401.     htmp += currentTiming->htotal;    /* allow blank to wrap around */
  402.   SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_ON, outputVal, htmp);
  403.   SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_OFF, outputVal,
  404.                     ((htmp + currentTiming->width - 2) % currentTiming->htotal));
  405.   DBE_SETREG(vt_hpixen, outputVal);
  406.   outputVal = 0;
  407.   SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_OFF, outputVal,
  408.                     currentTiming->vblank_start);
  409.   SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_ON, outputVal,
  410.                     currentTiming->vblank_end);
  411.   DBE_SETREG(vt_vpixen, outputVal);
  412.   // Turn off mouse cursor
  413.   regs->crs_ctl = 0;
  414.   // XXX What's this section for??
  415.   DBE_GETREG(ctrlstat, readVal);
  416.   readVal &= 0x02000000;
  417.   if (readVal != 0)
  418.     {
  419.       DBE_SETREG(ctrlstat, 0x30000000);
  420.     }
  421. }
  422. static void sgivwfb_encode_fix(struct fb_fix_screeninfo *fix,
  423.        struct fb_var_screeninfo *var)
  424. {
  425.   memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  426.   strcpy(fix->id, sgivwfb_name);
  427.   fix->smem_start = sgivwfb_mem_phys;
  428.   fix->smem_len = sgivwfb_mem_size;
  429.   fix->type = FB_TYPE_PACKED_PIXELS;
  430.   fix->type_aux = 0;
  431.   switch (var->bits_per_pixel) {
  432.   case 8:
  433.     fix->visual = FB_VISUAL_PSEUDOCOLOR;
  434.     break;
  435.   default:
  436.     fix->visual = FB_VISUAL_TRUECOLOR;
  437.     break;
  438.   }
  439.   fix->ywrapstep = ywrap;
  440.   fix->xpanstep = 0;
  441.   fix->ypanstep = ypan;
  442.   fix->line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
  443.   fix->mmio_start = DBE_REG_PHYS;
  444.   fix->mmio_len = DBE_REG_SIZE;
  445. }
  446. /*
  447.  *  Read a single color register and split it into
  448.  *  colors/transparent. Return != 0 for invalid regno.
  449.  */
  450. static int sgivwfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
  451.                              u_int *transp, struct fb_info *info)
  452. {
  453.   if (regno > 255)
  454.     return 1;
  455.   *red =   palette[regno].red << 8;
  456.   *green = palette[regno].green << 8;
  457.   *blue =  palette[regno].blue << 8;
  458.   *transp = 0;
  459.   return 0;
  460. }
  461. /*
  462.  *  Set a single color register. The values supplied are already
  463.  *  rounded down to the hardware's capabilities (according to the
  464.  *  entries in the var structure). Return != 0 for invalid regno.
  465.  */
  466. static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
  467.                              u_int transp, struct fb_info *info)
  468. {
  469.   if (regno > 255)
  470.     return 1;
  471.   red >>= 8;
  472.   green >>= 8;
  473.   blue >>= 8;
  474.   palette[regno].red = red;
  475.   palette[regno].green = green;
  476.   palette[regno].blue = blue;
  477.   /* wait for the color map FIFO to have a free entry */
  478.   while (cmap_fifo == 0)
  479.     cmap_fifo = regs->cm_fifo;
  480.   regs->cmap[regno] = (red << 24) | (green << 16) | (blue << 8);
  481.   cmap_fifo--; /* assume FIFO is filling up */
  482.   return 0;
  483. }
  484. static void do_install_cmap(int con, struct fb_info *info)
  485. {
  486.     if (con != currcon)
  487. return;
  488.     if (fb_display[con].cmap.len)
  489. fb_set_cmap(&fb_display[con].cmap, 1, sgivwfb_setcolreg, info);
  490.     else
  491. fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1,
  492.     sgivwfb_setcolreg, info);
  493. }
  494. /* ---------------------------------------------------- */
  495. /*
  496.  *  Get the Fixed Part of the Display
  497.  */
  498. static int sgivwfb_get_fix(struct fb_fix_screeninfo *fix, int con,
  499.    struct fb_info *info)
  500. {
  501.   struct fb_var_screeninfo *var;
  502.   if (con == -1)
  503.     var = &par_current.var;
  504.   else
  505.     var = &fb_display[con].var;
  506.   sgivwfb_encode_fix(fix, var);
  507.   return 0;
  508. }
  509. /*
  510.  *  Get the User Defined Part of the Display. If a real par get it form there
  511.  */
  512. static int sgivwfb_get_var(struct fb_var_screeninfo *var, int con,
  513.    struct fb_info *info)
  514. {
  515.   if (con == -1)
  516.     *var = par_current.var;
  517.   else
  518.     *var = fb_display[con].var;
  519.   return 0;
  520. }
  521. /*
  522.  *  Set the User Defined Part of the Display. Again if par use it to get
  523.  *  real video mode.
  524.  */
  525. static int sgivwfb_set_var(struct fb_var_screeninfo *var, int con,
  526.    struct fb_info *info)
  527. {
  528.   int err, activate = var->activate;
  529.   int oldxres, oldyres, oldvxres, oldvyres, oldbpp;
  530.   u_long line_length;
  531.   u_long min_mode;
  532.   int req_dot;
  533.   int test_mode;
  534.   struct dbe_timing_info *timing;
  535.   struct display *display;
  536.   if (con >= 0)
  537.     display = &fb_display[con];
  538.   else
  539.     display = &disp; /* used during initialization */
  540.   /*
  541.    *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
  542.    *  as FB_VMODE_SMOOTH_XPAN is only used internally
  543.    */
  544.   if (var->vmode & FB_VMODE_CONUPDATE) {
  545.     var->vmode |= FB_VMODE_YWRAP;
  546.     var->xoffset = display->var.xoffset;
  547.     var->yoffset = display->var.yoffset;
  548.   }
  549.   /* XXX FIXME - forcing var's */
  550.   var->xoffset = 0;
  551.   var->yoffset = 0;
  552.   /* Limit bpp to 8, 16, and 32 */
  553.   if (var->bits_per_pixel <= 8)
  554.     var->bits_per_pixel = 8;
  555.   else if (var->bits_per_pixel <= 16)
  556.     var->bits_per_pixel = 16;
  557.   else if (var->bits_per_pixel <= 32)
  558.     var->bits_per_pixel = 32;
  559.   else
  560.     return -EINVAL;
  561.   var->grayscale = 0;           /* No grayscale for now */
  562.   /* determine valid resolution and timing */
  563.   for (min_mode=0; min_mode<DBE_VT_SIZE; min_mode++) {
  564.     if (dbeVTimings[min_mode].width >= var->xres &&
  565.         dbeVTimings[min_mode].height >= var->yres)
  566.       break;
  567.   }
  568.   if (min_mode == DBE_VT_SIZE)
  569.     return -EINVAL;             /* Resolution to high */
  570.   /* XXX FIXME - should try to pick best refresh rate */
  571.   /* for now, pick closest dot-clock within 3MHz*/
  572. #error "Floating point not allowed in kernel"  
  573.   req_dot = (int)((1.0e3/1.0e6) / (1.0e-12 * (float)var->pixclock));
  574.   printk(KERN_INFO "sgivwfb: requested pixclock=%d ps (%d KHz)n", var->pixclock,
  575.  req_dot);
  576.   test_mode=min_mode;
  577.   while (dbeVTimings[min_mode].width == dbeVTimings[test_mode].width) {
  578.     if (dbeVTimings[test_mode].cfreq+3000 > req_dot)
  579.       break;
  580.     test_mode++;
  581.   }
  582.   if (dbeVTimings[min_mode].width != dbeVTimings[test_mode].width)
  583.     test_mode--;
  584.   min_mode = test_mode;
  585.   timing = &dbeVTimings[min_mode];
  586.   printk(KERN_INFO "sgivwfb: granted dot-clock=%d KHzn", timing->cfreq);
  587.   /* Adjust virtual resolution, if necessary */
  588.   if (var->xres > var->xres_virtual || (!ywrap && !ypan))
  589.     var->xres_virtual = var->xres;
  590.   if (var->yres > var->yres_virtual || (!ywrap && !ypan))
  591.     var->yres_virtual = var->yres;
  592.   /*
  593.    *  Memory limit
  594.    */
  595.   line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
  596.   if (line_length*var->yres_virtual > sgivwfb_mem_size)
  597.     return -ENOMEM;             /* Virtual resolution to high */
  598.   switch (var->bits_per_pixel)
  599.     {
  600.     case 8:
  601.       var->red.offset = 0;
  602.       var->red.length = 8;
  603.       var->green.offset = 0;
  604.       var->green.length = 8;
  605.       var->blue.offset = 0;
  606.       var->blue.length = 8;
  607.       var->transp.offset = 0;
  608.       var->transp.length = 0;
  609.       break;
  610.     case 16: /* RGBA 5551 */
  611.       var->red.offset = 11;
  612.       var->red.length = 5;
  613.       var->green.offset = 6;
  614.       var->green.length = 5;
  615.       var->blue.offset = 1;
  616.       var->blue.length = 5;
  617.       var->transp.offset = 0;
  618.       var->transp.length = 0;
  619.       break;
  620.     case 32: /* RGB 8888 */
  621.       var->red.offset = 0;
  622.       var->red.length = 8;
  623.       var->green.offset = 8;
  624.       var->green.length = 8;
  625.       var->blue.offset = 16;
  626.       var->blue.length = 8;
  627.       var->transp.offset = 24;
  628.       var->transp.length = 8;
  629.       break;
  630.     }
  631.   var->red.msb_right = 0;
  632.   var->green.msb_right = 0;
  633.   var->blue.msb_right = 0;
  634.   var->transp.msb_right = 0;
  635.   /* set video timing information */
  636.   var->pixclock = (__u32)(1.0e+9/(float)timing->cfreq);
  637.   var->left_margin = timing->htotal - timing->hsync_end;
  638.   var->right_margin = timing->hsync_start - timing->width;
  639.   var->upper_margin = timing->vtotal - timing->vsync_end;
  640.   var->lower_margin = timing->vsync_start - timing->height;
  641.   var->hsync_len = timing->hsync_end - timing->hsync_start;
  642.   var->vsync_len = timing->vsync_end -  timing->vsync_start;
  643.   if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
  644.     oldxres = display->var.xres;
  645.     oldyres = display->var.yres;
  646.     oldvxres = display->var.xres_virtual;
  647.     oldvyres = display->var.yres_virtual;
  648.     oldbpp = display->var.bits_per_pixel;
  649.     display->var = *var;
  650.     par_current.var = *var;
  651.     par_current.timing_num = min_mode;
  652.     if (oldxres != var->xres || oldyres != var->yres ||
  653. oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
  654. oldbpp != var->bits_per_pixel || !par_current.valid) {
  655.       struct fb_fix_screeninfo fix;
  656.       printk(KERN_INFO "sgivwfb: new video mode xres=%d yres=%d bpp=%dn",
  657.      var->xres, var->yres, var->bits_per_pixel);
  658.       printk(KERN_INFO "         vxres=%d vyres=%dn",
  659.      var->xres_virtual, var->yres_virtual);
  660.       activate_par(&par_current);
  661.       sgivwfb_encode_fix(&fix, var);
  662.       display->screen_base = (char *)fbmem;
  663.       display->visual = fix.visual;
  664.       display->type = fix.type;
  665.       display->type_aux = fix.type_aux;
  666.       display->ypanstep = fix.ypanstep;
  667.       display->ywrapstep = fix.ywrapstep;
  668.       display->line_length = fix.line_length;
  669.       display->can_soft_blank = 1;
  670.       display->inverse = 0;
  671.       if (oldbpp != var->bits_per_pixel || !par_current.valid) {
  672. if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
  673.   return err;
  674. do_install_cmap(con, info);
  675.       }
  676.       switch (var->bits_per_pixel) {
  677. #ifdef FBCON_HAS_CFB8
  678.       case 8:
  679. display->dispsw = &fbcon_cfb8;
  680. break;
  681. #endif
  682. #ifdef FBCON_HAS_CFB16
  683.       case 16:
  684. display->dispsw = &fbcon_cfb16;
  685. display->dispsw_data = fbcon_cmap.cfb16;
  686. break;
  687. #endif
  688. #ifdef FBCON_HAS_CFB32
  689.       case 32:
  690. display->dispsw = &fbcon_cfb32;
  691. display->dispsw_data = fbcon_cmap.cfb32;
  692. break;
  693. #endif
  694.       default:
  695. display->dispsw = &fbcon_dummy;
  696. break;
  697.       }
  698.       par_current.valid = 1;
  699.       if (fb_info.changevar)
  700. (*fb_info.changevar)(con);
  701.     }
  702.   }
  703.   return 0;
  704. }
  705. /*
  706.  *  Get the Colormap
  707.  */
  708. static int sgivwfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  709.     struct fb_info *info)
  710. {
  711.   if (con == currcon) /* current console? */
  712.     return fb_get_cmap(cmap, kspc, sgivwfb_getcolreg, info);
  713.   else if (fb_display[con].cmap.len) /* non default colormap? */
  714.     fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  715.   else
  716.     fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
  717.  cmap, kspc ? 0 : 2);
  718.   return 0;
  719. }
  720. /*
  721.  *  Set the Colormap
  722.  */
  723. static int sgivwfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  724.     struct fb_info *info)
  725. {
  726.   int err;
  727.   if (!fb_display[con].cmap.len) { /* no colormap allocated? */
  728.     int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
  729.     if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
  730.       return err;
  731.   }
  732.   if (con == currcon) /* current console? */
  733.     return fb_set_cmap(cmap, kspc, sgivwfb_setcolreg, info);
  734.   else
  735.     fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  736.   return 0;
  737. }
  738. static int sgivwfb_mmap(struct fb_info *info, struct file *file,
  739.                         struct vm_area_struct *vma)
  740. {
  741.   unsigned long size = vma->vm_end - vma->vm_start;
  742.   unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
  743.   if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
  744. return -EINVAL;
  745.   if (offset+size > sgivwfb_mem_size)
  746.     return -EINVAL;
  747.   offset += sgivwfb_mem_phys;
  748.   pgprot_val(vma->vm_page_prot) = pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
  749.   if (remap_page_range(vma->vm_start, offset, size, vma->vm_page_prot))
  750.     return -EAGAIN;
  751.   vma->vm_file = file;
  752.   printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)n", offset, vma->vm_start);
  753.   return 0;
  754. }
  755. int __init sgivwfb_setup(char *options)
  756. {
  757.   char *this_opt;
  758.   fb_info.fontname[0] = '';
  759.   if (!options || !*options)
  760.     return 0;
  761.   while ((this_opt = strsep(&options, ",")) != NULL) {
  762.     if (!strncmp(this_opt, "font:", 5))
  763.       strcpy(fb_info.fontname, this_opt+5);
  764.   }
  765.   return 0;
  766. }
  767. /*
  768.  *  Initialisation
  769.  */
  770. int __init sgivwfb_init(void)
  771. {
  772.   printk(KERN_INFO "sgivwfb: framebuffer at 0x%lx, size %ldkn",
  773.  sgivwfb_mem_phys, sgivwfb_mem_size/1024);
  774.   regs = (asregs*)ioremap_nocache(DBE_REG_PHYS, DBE_REG_SIZE);
  775.   if (!regs) {
  776.     printk(KERN_ERR "sgivwfb: couldn't ioremap registersn");
  777.     goto fail_ioremap_regs;
  778.   }
  779. #ifdef CONFIG_MTRR
  780.   mtrr_add((unsigned long)sgivwfb_mem_phys, sgivwfb_mem_size, MTRR_TYPE_WRCOMB, 1);
  781. #endif
  782.   strcpy(fb_info.modename, sgivwfb_name);
  783.   fb_info.changevar = NULL;
  784.   fb_info.node = -1;
  785.   fb_info.fbops = &sgivwfb_ops;
  786.   fb_info.disp = &disp;
  787.   fb_info.switch_con = &sgivwfbcon_switch;
  788.   fb_info.updatevar = &sgivwfbcon_updatevar;
  789.   fb_info.blank = &sgivwfbcon_blank;
  790.   fb_info.flags = FBINFO_FLAG_DEFAULT;
  791.   fbmem = ioremap_nocache((unsigned long)sgivwfb_mem_phys, sgivwfb_mem_size);
  792.   if (!fbmem) {
  793.     printk(KERN_ERR "sgivwfb: couldn't ioremap fbmemn");
  794.     goto fail_ioremap_fbmem;
  795.   }
  796.   /* turn on default video mode */
  797.   sgivwfb_set_var(&par_current.var, -1, &fb_info);
  798.   if (register_framebuffer(&fb_info) < 0) {
  799.     printk(KERN_ERR "sgivwfb: couldn't register framebuffern");
  800.     goto fail_register_framebuffer;
  801.   }
  802.   printk(KERN_INFO "fb%d: Virtual frame buffer device, using %ldK of video memoryn",
  803.  GET_FB_IDX(fb_info.node), sgivwfb_mem_size>>10);
  804.   return 0;
  805.  fail_register_framebuffer:
  806.   iounmap((char*)fbmem);
  807.  fail_ioremap_fbmem:
  808.   iounmap(regs);
  809.  fail_ioremap_regs:
  810.   return -ENXIO;
  811. }
  812. static int sgivwfbcon_switch(int con, struct fb_info *info)
  813. {
  814.   /* Do we have to save the colormap? */
  815.   if (fb_display[currcon].cmap.len)
  816.     fb_get_cmap(&fb_display[currcon].cmap, 1, sgivwfb_getcolreg, info);
  817.   currcon = con;
  818.   /* Install new colormap */
  819.   do_install_cmap(con, info);
  820.   return 0;
  821. }
  822. /*
  823.  *  Update the `var' structure (called by fbcon.c)
  824.  */
  825. static int sgivwfbcon_updatevar(int con, struct fb_info *info)
  826. {
  827.     /* Nothing */
  828.     return 0;
  829. }
  830. /*
  831.  *  Blank the display.
  832.  */
  833. static void sgivwfbcon_blank(int blank, struct fb_info *info)
  834. {
  835.     /* Nothing */
  836. }
  837. #ifdef MODULE
  838. MODULE_LICENSE("GPL");
  839. int init_module(void)
  840. {
  841.   return sgivwfb_init();
  842. }
  843. void cleanup_module(void)
  844. {
  845.   unregister_framebuffer(&fb_info);
  846.   dbe_TurnOffDma();
  847.   iounmap(regs);
  848.   iounmap(fbmem);
  849. }
  850. #endif /* MODULE */