⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sgivwfb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/drivers/video/sgivwfb.c -- SGI DBE frame buffer device * *	Copyright (C) 1999 Silicon Graphics, Inc. *      Jeffrey Newquist, newquist@engr.sgi.som * *  This file is subject to the terms and conditions of the GNU General Public *  License. See the file COPYING in the main directory of this archive for *  more details. */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <asm/uaccess.h>#include <linux/fb.h>#include <linux/init.h>#include <asm/io.h>#include <asm/mtrr.h>#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb32.h>#define INCLUDE_TIMING_TABLE_DATA#define DBE_REG_BASE regs#include "sgivwfb.h"struct sgivwfb_par {  struct fb_var_screeninfo var;  u_long timing_num;  int valid;};/* *  RAM we reserve for the frame buffer. This defines the maximum screen *  size * *  The default can be overridden if the driver is compiled as a module *//* set by arch/i386/kernel/setup.c */u_long                sgivwfb_mem_phys;u_long                sgivwfb_mem_size;static volatile char  *fbmem;static asregs         *regs;static struct fb_info fb_info;static struct { u_char red, green, blue, pad; } palette[256];static char           sgivwfb_name[16] = "SGI Vis WS FB";static u32            cmap_fifo;static int            ypan       = 0;static int            ywrap      = 0;/* console related variables */static int currcon = 0;static struct display disp;static union {#ifdef FBCON_HAS_CFB16  u16 cfb16[16];#endif#ifdef FBCON_HAS_CFB32  u32 cfb32[16];#endif} fbcon_cmap;static struct sgivwfb_par par_current = {  {                             /* var (screeninfo) */    /* 640x480, 8 bpp */    640, 480, 640, 480, 0, 0, 8, 0,    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},    0, 0, -1, -1, 0, 20000, 64, 64, 32, 32, 64, 2,    0, FB_VMODE_NONINTERLACED  },  0,                            /* timing_num */  0				/* par not activated */};/* *  Interface used by the world */int sgivwfb_setup(char*);static int sgivwfb_get_fix(struct fb_fix_screeninfo *fix, int con,			   struct fb_info *info);static int sgivwfb_get_var(struct fb_var_screeninfo *var, int con,			   struct fb_info *info);static int sgivwfb_set_var(struct fb_var_screeninfo *var, int con,			   struct fb_info *info);static int sgivwfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,			    struct fb_info *info);static int sgivwfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,			    struct fb_info *info);static int sgivwfb_mmap(struct fb_info *info, struct file *file,                        struct vm_area_struct *vma);static struct fb_ops sgivwfb_ops = {	owner:		THIS_MODULE,	fb_get_fix:	sgivwfb_get_fix,	fb_get_var:	sgivwfb_get_var,	fb_set_var:	sgivwfb_set_var,	fb_get_cmap:	sgivwfb_get_cmap,	fb_set_cmap:	sgivwfb_set_cmap,	fb_mmap:	sgivwfb_mmap,};/* *  Interface to the low level console driver */int sgivwfb_init(void);static int sgivwfbcon_switch(int con, struct fb_info *info);static int sgivwfbcon_updatevar(int con, struct fb_info *info);static void sgivwfbcon_blank(int blank, struct fb_info *info);/* *  Internal routines */static u_long get_line_length(int xres_virtual, int bpp);static unsigned long bytes_per_pixel(int bpp);static void activate_par(struct sgivwfb_par *par);static void sgivwfb_encode_fix(struct fb_fix_screeninfo *fix,			       struct fb_var_screeninfo *var);static int sgivwfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,			     u_int *transp, struct fb_info *info);static int sgivwfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,			     u_int transp, struct fb_info *info);static void do_install_cmap(int con, struct fb_info *info);static unsigned long get_line_length(int xres_virtual, int bpp){  return(xres_virtual * bytes_per_pixel(bpp));}static unsigned long bytes_per_pixel(int bpp){  unsigned long length;  switch (bpp) {  case 8:    length = 1;    break;  case 16:    length = 2;    break;  case 32:    length = 4;    break;  default:    printk(KERN_INFO "sgivwfb: unsupported bpp=%d\n", bpp);    length = 0;    break;  }  return(length);}/* * Function:	dbe_TurnOffDma * Parameters:	(None) * Description:	This should turn off the monitor and dbe.  This is used *              when switching between the serial console and the graphics *              console. */static void dbe_TurnOffDma(void){  int i;  unsigned int readVal;  // Check to see if things are already turned off:  // 1) Check to see if dbe is not using the internal dotclock.  // 2) Check to see if the xy counter in dbe is already off.  DBE_GETREG(ctrlstat, readVal);  if (GET_DBE_FIELD(CTRLSTAT, PCLKSEL, readVal) < 2)    return;  DBE_GETREG(vt_xy, readVal);  if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)    return;  // Otherwise, turn off dbe  DBE_GETREG(ovr_control, readVal);  SET_DBE_FIELD(OVR_CONTROL, OVR_DMA_ENABLE, readVal, 0);  DBE_SETREG(ovr_control, readVal);  udelay(1000);  DBE_GETREG(frm_control, readVal);  SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, readVal, 0);  DBE_SETREG(frm_control, readVal);  udelay(1000);  DBE_GETREG(did_control, readVal);  SET_DBE_FIELD(DID_CONTROL, DID_DMA_ENABLE, readVal, 0);  DBE_SETREG(did_control, readVal);  udelay(1000);  // XXX HACK:  //  //    This was necessary for GBE--we had to wait through two  //    vertical retrace periods before the pixel DMA was  //    turned off for sure.  I've left this in for now, in  //    case dbe needs it.  for (i = 0; i < 10000; i++)    {      DBE_GETREG(frm_inhwctrl, readVal);      if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) == 0)        udelay(10);      else        {          DBE_GETREG(ovr_inhwctrl, readVal);          if (GET_DBE_FIELD(OVR_INHWCTRL, OVR_DMA_ENABLE, readVal) == 0)            udelay(10);          else            {              DBE_GETREG(did_inhwctrl, readVal);              if (GET_DBE_FIELD(DID_INHWCTRL, DID_DMA_ENABLE, readVal) == 0)                udelay(10);              else                break;            }        }    }}/* *  Set the hardware according to 'par'. */static void activate_par(struct sgivwfb_par *par){  int i,j, htmp, temp;  u32 readVal, outputVal;  int wholeTilesX, maxPixelsPerTileX;  int frmWrite1, frmWrite2, frmWrite3b;  dbe_timing_info_t *currentTiming;    /* Current Video Timing */  int xpmax, ypmax;                       // Monitor resolution  int bytesPerPixel;                      // Bytes per pixel  currentTiming = &dbeVTimings[par->timing_num];  bytesPerPixel = bytes_per_pixel(par->var.bits_per_pixel);  xpmax = currentTiming->width;  ypmax = currentTiming->height;  /* dbe_InitGraphicsBase(); */  /* Turn on dotclock PLL */  DBE_SETREG(ctrlstat, 0x20000000);  dbe_TurnOffDma();  /* dbe_CalculateScreenParams(); */  maxPixelsPerTileX = 512/bytesPerPixel;  wholeTilesX = xpmax/maxPixelsPerTileX;  if (wholeTilesX*maxPixelsPerTileX < xpmax)    wholeTilesX++;  printk(KERN_DEBUG "sgivwfb: pixPerTile=%d wholeTilesX=%d\n",	 maxPixelsPerTileX, wholeTilesX);  /* dbe_InitGammaMap(); */  udelay(10);  for (i = 0; i < 256; i++)    {      DBE_ISETREG(gmap, i, (i << 24) | (i << 16) | (i << 8));    }  /* dbe_TurnOn(); */  DBE_GETREG(vt_xy, readVal);  if (GET_DBE_FIELD(VT_XY, VT_FREEZE, readVal) == 1)    {      DBE_SETREG(vt_xy, 0x00000000);      udelay(1);    }  else    dbe_TurnOffDma();  /* dbe_Initdbe(); */  for (i = 0; i < 256; i++)    {      for (j = 0; j < 100; j++)        {          DBE_GETREG(cm_fifo, readVal);          if (readVal != 0x00000000)            break;          else            udelay(10);        }      // DBE_ISETREG(cmap, i, 0x00000000);      DBE_ISETREG(cmap, i, (i<<8)|(i<<16)|(i<<24));    }  /* dbe_InitFramebuffer(); */  frmWrite1 = 0;  SET_DBE_FIELD(FRM_SIZE_TILE, FRM_WIDTH_TILE, frmWrite1, wholeTilesX);  SET_DBE_FIELD(FRM_SIZE_TILE, FRM_RHS, frmWrite1, 0);  switch(bytesPerPixel)    {      case 1:        SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_8);        break;      case 2:        SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_16);        break;      case 4:        SET_DBE_FIELD(FRM_SIZE_TILE, FRM_DEPTH, frmWrite1, DBE_FRM_DEPTH_32);        break;    }  frmWrite2 = 0;  SET_DBE_FIELD(FRM_SIZE_PIXEL, FB_HEIGHT_PIX, frmWrite2, ypmax);  // Tell dbe about the framebuffer location and type  // XXX What format is the FRM_TILE_PTR??  64K aligned address?  frmWrite3b = 0;  SET_DBE_FIELD(FRM_CONTROL, FRM_TILE_PTR, frmWrite3b, sgivwfb_mem_phys>>9);  SET_DBE_FIELD(FRM_CONTROL, FRM_DMA_ENABLE, frmWrite3b, 1);  SET_DBE_FIELD(FRM_CONTROL, FRM_LINEAR, frmWrite3b, 1);  /* Initialize DIDs */  outputVal = 0;  switch(bytesPerPixel)    {      case 1:        SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_I8);        break;      case 2:        SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGBA5);        break;      case 4:        SET_DBE_FIELD(WID, TYP, outputVal, DBE_CMODE_RGB8);        break;    }  SET_DBE_FIELD(WID, BUF, outputVal, DBE_BMODE_BOTH);  for (i = 0; i < 32; i++)    {      DBE_ISETREG(mode_regs, i, outputVal);    }  /* dbe_InitTiming(); */  DBE_SETREG(vt_intr01, 0xffffffff);  DBE_SETREG(vt_intr23, 0xffffffff);  DBE_GETREG(dotclock, readVal);  DBE_SETREG(dotclock, readVal & 0xffff);  DBE_SETREG(vt_xymax, 0x00000000);  outputVal = 0;  SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_ON, outputVal, currentTiming->vsync_start);  SET_DBE_FIELD(VT_VSYNC, VT_VSYNC_OFF, outputVal, currentTiming->vsync_end);  DBE_SETREG(vt_vsync, outputVal);  outputVal = 0;  SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_ON, outputVal, currentTiming->hsync_start);  SET_DBE_FIELD(VT_HSYNC, VT_HSYNC_OFF, outputVal, currentTiming->hsync_end);  DBE_SETREG(vt_hsync, outputVal);  outputVal = 0;  SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_ON, outputVal, currentTiming->vblank_start);  SET_DBE_FIELD(VT_VBLANK, VT_VBLANK_OFF, outputVal, currentTiming->vblank_end);  DBE_SETREG(vt_vblank, outputVal);  outputVal = 0;  SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_ON, outputVal, currentTiming->hblank_start);  SET_DBE_FIELD(VT_HBLANK, VT_HBLANK_OFF, outputVal, currentTiming->hblank_end-3);  DBE_SETREG(vt_hblank, outputVal);  outputVal = 0;  SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_ON, outputVal, currentTiming->vblank_start);  SET_DBE_FIELD(VT_VCMAP, VT_VCMAP_OFF, outputVal, currentTiming->vblank_end);  DBE_SETREG(vt_vcmap, outputVal);  outputVal = 0;  SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_ON, outputVal, currentTiming->hblank_start);  SET_DBE_FIELD(VT_HCMAP, VT_HCMAP_OFF, outputVal, currentTiming->hblank_end-3);  DBE_SETREG(vt_hcmap, outputVal);  outputVal = 0;  temp = currentTiming->vblank_start - currentTiming->vblank_end - 1;  if (temp > 0)    temp = -temp;  SET_DBE_FIELD(DID_START_XY, DID_STARTY, outputVal, (u32)temp);  if (currentTiming->hblank_end >= 20)    SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,                      currentTiming->hblank_end - 20);  else    SET_DBE_FIELD(DID_START_XY, DID_STARTX, outputVal,                      currentTiming->htotal - (20 - currentTiming->hblank_end));  DBE_SETREG(did_start_xy, outputVal);  outputVal = 0;  SET_DBE_FIELD(CRS_START_XY, CRS_STARTY, outputVal, (u32)(temp+1));  if (currentTiming->hblank_end >= DBE_CRS_MAGIC)    SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,                      currentTiming->hblank_end - DBE_CRS_MAGIC);  else    SET_DBE_FIELD(CRS_START_XY, CRS_STARTX, outputVal,                      currentTiming->htotal - (DBE_CRS_MAGIC - currentTiming->hblank_end));  DBE_SETREG(crs_start_xy, outputVal);  outputVal = 0;  SET_DBE_FIELD(VC_START_XY, VC_STARTY, outputVal, (u32)temp);  SET_DBE_FIELD(VC_START_XY, VC_STARTX, outputVal,                    currentTiming->hblank_end - 4);  DBE_SETREG(vc_start_xy, outputVal);  DBE_SETREG(frm_size_tile, frmWrite1);  DBE_SETREG(frm_size_pixel, frmWrite2);  outputVal = 0;  SET_DBE_FIELD(DOTCLK, M, outputVal, currentTiming->pll_m-1);  SET_DBE_FIELD(DOTCLK, N, outputVal, currentTiming->pll_n-1);  SET_DBE_FIELD(DOTCLK, P, outputVal, currentTiming->pll_p);  SET_DBE_FIELD(DOTCLK, RUN, outputVal, 1);  DBE_SETREG(dotclock, outputVal);  udelay(11*1000);  DBE_SETREG(vt_vpixen, 0xffffff);  DBE_SETREG(vt_hpixen, 0xffffff);  outputVal = 0;  SET_DBE_FIELD(VT_XYMAX, VT_MAXX, outputVal, currentTiming->htotal);  SET_DBE_FIELD(VT_XYMAX, VT_MAXY, outputVal, currentTiming->vtotal);  DBE_SETREG(vt_xymax, outputVal);  outputVal = frmWrite1;  SET_DBE_FIELD(FRM_SIZE_TILE, FRM_FIFO_RESET, outputVal, 1);  DBE_SETREG(frm_size_tile, outputVal);  DBE_SETREG(frm_size_tile, frmWrite1);  outputVal = 0;  SET_DBE_FIELD(OVR_WIDTH_TILE, OVR_FIFO_RESET, outputVal, 1);  DBE_SETREG(ovr_width_tile, outputVal);  DBE_SETREG(ovr_width_tile, 0);  DBE_SETREG(frm_control, frmWrite3b);  DBE_SETREG(did_control, 0);  // Wait for dbe to take frame settings  for (i=0; i<100000; i++)    {      DBE_GETREG(frm_inhwctrl, readVal);      if (GET_DBE_FIELD(FRM_INHWCTRL, FRM_DMA_ENABLE, readVal) != 0)        break;      else        udelay(1);    }  if (i==100000)    printk(KERN_INFO "sgivwfb: timeout waiting for frame DMA enable.\n");  outputVal = 0;  htmp = currentTiming->hblank_end - 19;  if (htmp < 0)    htmp += currentTiming->htotal;    /* allow blank to wrap around */  SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_ON, outputVal, htmp);  SET_DBE_FIELD(VT_HPIXEN, VT_HPIXEN_OFF, outputVal,                    ((htmp + currentTiming->width - 2) % currentTiming->htotal));  DBE_SETREG(vt_hpixen, outputVal);  outputVal = 0;  SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_OFF, outputVal,                    currentTiming->vblank_start);  SET_DBE_FIELD(VT_VPIXEN, VT_VPIXEN_ON, outputVal,                    currentTiming->vblank_end);  DBE_SETREG(vt_vpixen, outputVal);  // Turn off mouse cursor  regs->crs_ctl = 0;  // XXX What's this section for??  DBE_GETREG(ctrlstat, readVal);  readVal &= 0x02000000;  if (readVal != 0)    {      DBE_SETREG(ctrlstat, 0x30000000);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -