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

📄 neofb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver * * Copyright (c) 2001  Denis Oliver Kropp <dok@convergence.de> * * * Card specific code is based on XFree86's neomagic driver. * Framebuffer framework code is based on code of cyber2000fb. * * 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. * * * 0.3.2 *  - got rid of all floating point (dok) * * 0.3.1 *  - added module license (dok) * * 0.3 *  - hardware accelerated clear and move for 2200 and above (dok) *  - maximum allowed dotclock is handled now (dok) * * 0.2.1 *  - correct panning after X usage (dok) *  - added module and kernel parameters (dok) *  - no stretching if external display is enabled (dok) * * 0.2 *  - initial version (dok) * * * TODO * - ioctl for internal/external switching * - blanking * - 32bit depth support, maybe impossible * - disable pan-on-sync, need specs * * BUGS * - white margin on bootup like with tdfxfb (colormap problem?) * */#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/delay.h>#include <linux/fb.h>#include <linux/pci.h>#include <linux/init.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/pgtable.h>#include <asm/system.h>#include <asm/uaccess.h>#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb24.h>#include <video/fbcon-cfb32.h>#include "neofb.h"#define NEOFB_VERSION "0.3.2"/* --------------------------------------------------------------------- */static int disabled   = 0;static int internal   = 0;static int external   = 0;static int nostretch  = 0;static int nopciburst = 0;#ifdef MODULEMODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@convergence.de>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");MODULE_PARM(disabled, "i");MODULE_PARM_DESC(disabled, "Disable this driver's initialization.");MODULE_PARM(internal, "i");MODULE_PARM_DESC(internal, "Enable output on internal LCD Display.");MODULE_PARM(external, "i");MODULE_PARM_DESC(external, "Enable output on external CRT.");MODULE_PARM(nostretch, "i");MODULE_PARM_DESC(nostretch, "Disable stretching of modes smaller than LCD.");MODULE_PARM(nopciburst, "i");MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");#endif/* --------------------------------------------------------------------- */static biosMode bios8[] = {	    { 320, 240, 0x40 },    { 300, 400, 0x42 },        { 640, 400, 0x20 },    { 640, 480, 0x21 },    { 800, 600, 0x23 },    { 1024, 768, 0x25 },};static biosMode bios16[] = {    { 320, 200, 0x2e },    { 320, 240, 0x41 },    { 300, 400, 0x43 },    { 640, 480, 0x31 },    { 800, 600, 0x34 },    { 1024, 768, 0x37 },};static biosMode bios24[] = {    { 640, 480, 0x32 },    { 800, 600, 0x35 },    { 1024, 768, 0x38 }};#ifdef NO_32BIT_SUPPORT_YET/* FIXME: guessed values, wrong */static biosMode bios32[] = {    { 640, 480, 0x33 },    { 800, 600, 0x36 },    { 1024, 768, 0x39 }    };#endifstatic int neoFindMode (int xres, int yres, int depth){  int xres_s;  int i, size;  biosMode *mode;  switch (depth)    {    case 8:      size = sizeof(bios8) / sizeof(biosMode);      mode = bios8;      break;    case 16:      size = sizeof(bios16) / sizeof(biosMode);      mode = bios16;      break;    case 24:      size = sizeof(bios24) / sizeof(biosMode);      mode = bios24;      break;#ifdef NO_32BIT_SUPPORT_YET    case 32:      size = sizeof(bios32) / sizeof(biosMode);      mode = bios32;      break;#endif    default:      return 0;    }  for (i = 0; i < size; i++)    {      if (xres <= mode[i].x_res)	{	  xres_s = mode[i].x_res;	  for (; i < size; i++)	    {	      if (mode[i].x_res != xres_s)		return mode[i-1].mode;	      if (yres <= mode[i].y_res)		return mode[i].mode;	    }	}    }  return mode[size - 1].mode;}/* -------------------- Hardware specific routines ------------------------- *//* * Hardware Acceleration for Neo2200+ */static inline void neo2200_wait_idle (struct neofb_info *fb){  int waitcycles;  while (fb->neo2200->bltStat & 1)    waitcycles++;}static inline void neo2200_wait_fifo (struct neofb_info *fb,                                      int requested_fifo_space){  //  ndev->neo.waitfifo_calls++;  //  ndev->neo.waitfifo_sum += requested_fifo_space;  /* FIXME: does not work  if (neo_fifo_space < requested_fifo_space)    {      neo_fifo_waitcycles++;      while (1)    {      neo_fifo_space = (neo2200->bltStat >> 8);      if (neo_fifo_space >= requested_fifo_space)        break;    }    }  else    {      neo_fifo_cache_hits++;    }  neo_fifo_space -= requested_fifo_space;  */  neo2200_wait_idle (fb);}static inline void neo2200_accel_init (struct neofb_info        *fb,				       struct fb_var_screeninfo *var){  Neo2200 *neo2200 = fb->neo2200;  u32 bltMod, pitch;  neo2200_wait_idle (fb);  switch (var->bits_per_pixel)    {    case 8:      bltMod = NEO_MODE1_DEPTH8;      pitch  = var->xres_virtual;      break;    case 15:    case 16:      bltMod = NEO_MODE1_DEPTH16;      pitch  = var->xres_virtual * 2;      break;    default:      printk( KERN_ERR "neofb: neo2200_accel_init: unexpected bits per pixel!\n" );      return;    }  neo2200->bltStat = bltMod << 16;  neo2200->pitch   = (pitch << 16) | pitch;}static void neo2200_accel_setup (struct display *p){  struct neofb_info        *fb  = (struct neofb_info *)p->fb_info;  struct fb_var_screeninfo *var = &p->fb_info->var;  fb->dispsw->setup(p);  neo2200_accel_init (fb, var);}static voidneo2200_accel_bmove (struct display *p, int sy, int sx, int dy, int dx,		     int height, int width){  struct neofb_info *fb = (struct neofb_info *)p->fb_info;  struct fb_var_screeninfo *var = &p->fb_info->var;  Neo2200 *neo2200 = fb->neo2200;  u_long src, dst;  int bpp, pitch, inc_y;  u_int fh, fw;  if (sx != dx)    {      neo2200_wait_idle (fb);      fb->dispsw->bmove(p, sy, sx, dy, dx, height, width);      return;    }  bpp    = (var->bits_per_pixel+7) / 8;  pitch  = var->xres_virtual * bpp;  fw     = fontwidth(p);  sx    *= fw * bpp;  dx    *= fw * bpp;  width *= fw;  fh     = fontheight(p);  sy    *= fh;  dy    *= fh;  if (sy > dy)    inc_y = fh;  else    {      inc_y  = -fh;      sy    += (height - 1) * fh;      dy    += (height - 1) * fh;    }  neo2200_wait_fifo (fb, 1);  /* set blt control */  neo2200->bltCntl = NEO_BC3_FIFO_EN      |                     NEO_BC3_SKIP_MAPPING |  0x0c0000;  while (height--)    {      src = sx + sy * pitch;      dst = dx + dy * pitch;      neo2200_wait_fifo (fb, 3);      neo2200->srcStart = src;      neo2200->dstStart = dst;      neo2200->xyExt = (fh << 16) | (width & 0xffff);      sy += inc_y;      dy += inc_y;    }}static voidneo2200_accel_clear (struct vc_data *conp, struct display *p, int sy, int sx,		     int height, int width){  struct neofb_info *fb = (struct neofb_info *)p->fb_info;  struct fb_var_screeninfo *var = &p->fb_info->var;  Neo2200 *neo2200 = fb->neo2200;  u_long dst;  u_int fw, fh;  u32 bgx = attr_bgcol_ec(p, conp);  fw = fontwidth(p);  fh = fontheight(p);  dst    = sx * fw + sy * var->xres_virtual * fh;  width  = width * fw;  height = height * fh;  neo2200_wait_fifo (fb, 4);  /* set blt control */  neo2200->bltCntl  = NEO_BC3_FIFO_EN      |                      NEO_BC0_SRC_IS_FG    |                      NEO_BC3_SKIP_MAPPING |  0x0c0000;  switch (var->bits_per_pixel)    {    case 8:      neo2200->fgColor = bgx;      break;    case 16:      neo2200->fgColor = ((u16 *)(p->fb_info)->pseudo_palette)[bgx];      break;    }  neo2200->dstStart = dst * ((var->bits_per_pixel+7) / 8);  neo2200->xyExt    = (height << 16) | (width & 0xffff);}static voidneo2200_accel_putc (struct vc_data *conp, struct display *p, int c,		    int yy, int xx){  struct neofb_info *fb = (struct neofb_info *)p->fb_info;  neo2200_wait_idle (fb);  fb->dispsw->putc(conp, p, c, yy, xx);}static voidneo2200_accel_putcs (struct vc_data *conp, struct display *p,		     const unsigned short *s, int count, int yy, int xx){  struct neofb_info *fb = (struct neofb_info *)p->fb_info;  neo2200_wait_idle (fb);  fb->dispsw->putcs(conp, p, s, count, yy, xx);}static void neo2200_accel_revc (struct display *p, int xx, int yy){  struct neofb_info *fb = (struct neofb_info *)p->fb_info;	  neo2200_wait_idle (fb);  fb->dispsw->revc (p, xx, yy);}static voidneo2200_accel_clear_margins (struct vc_data *conp, struct display *p,			     int bottom_only){  struct neofb_info *fb = (struct neofb_info *)p->fb_info;  fb->dispsw->clear_margins (conp, p, bottom_only);}static struct display_switch fbcon_neo2200_accel = {  setup:		neo2200_accel_setup,  bmove:		neo2200_accel_bmove,  clear:		neo2200_accel_clear,  putc:			neo2200_accel_putc,  putcs:		neo2200_accel_putcs,  revc:			neo2200_accel_revc,  clear_margins:	neo2200_accel_clear_margins,  fontwidthmask:	FONTWIDTH(8)|FONTWIDTH(16)};/* --------------------------------------------------------------------- *//* *    Set a single color register. Return != 0 for invalid regno. */static int neo_setcolreg(u_int regno, u_int red, u_int green, u_int blue,			 u_int transp, struct fb_info *fb){  struct neofb_info *info = (struct neofb_info *)fb;  if (regno >= NR_PALETTE)    return -EINVAL;  info->palette[regno].red    = red;  info->palette[regno].green  = green;  info->palette[regno].blue   = blue;  info->palette[regno].transp = transp;  switch (fb->var.bits_per_pixel)    {#ifdef FBCON_HAS_CFB8    case 8:      outb(regno, 0x3c8);      outb(red   >> 10, 0x3c9);      outb(green >> 10, 0x3c9);      outb(blue  >> 10, 0x3c9);      break;#endif#ifdef FBCON_HAS_CFB16    case 16:      if (regno < 16)	((u16 *)fb->pseudo_palette)[regno] = ((red   & 0xf800)      ) |	                                     ((green & 0xfc00) >>  5) |                                             ((blue  & 0xf800) >> 11);      break;#endif#ifdef FBCON_HAS_CFB24    case 24:      if (regno < 16)	((u32 *)fb->pseudo_palette)[regno] = ((red   & 0xff00) << 8) |                                             ((green & 0xff00)     ) |	                                     ((blue  & 0xff00) >> 8);      break;#endif#ifdef NO_32BIT_SUPPORT_YET#ifdef FBCON_HAS_CFB32    case 32:      if (regno < 16)	((u32 *)fb->pseudo_palette)[regno] = ((transp & 0xff00) << 16) |	                                     ((red    & 0xff00) <<  8) |                                             ((green  & 0xff00)      ) |	                                     ((blue   & 0xff00) >>  8);      break;#endif#endif    default:      return 1;    }  return 0;}static void vgaHWLock (void){  /* Protect CRTC[0-7] */  VGAwCR (0x11, VGArCR (0x11) | 0x80);}static void vgaHWUnlock (void){  /* Unprotect CRTC[0-7] */  VGAwCR (0x11, VGArCR (0x11) & ~0x80);}static void neoLock (void){  VGAwGR (0x09, 0x00);  vgaHWLock();}static void neoUnlock (void){  vgaHWUnlock();  VGAwGR (0x09, 0x26);}/* * vgaHWSeqReset *      perform a sequencer reset. */voidvgaHWSeqReset(int start){  if (start)    VGAwSEQ (0x00, 0x01);		/* Synchronous Reset */  else    VGAwSEQ (0x00, 0x03);		/* End Reset */}voidvgaHWProtect(int on){  unsigned char tmp;    if (on)    {      /*       * Turn off screen and disable sequencer.       */      tmp = VGArSEQ (0x01);      vgaHWSeqReset (1);			/* start synchronous reset */      VGAwSEQ (0x01, tmp | 0x20);	/* disable the display */      VGAenablePalette();    }  else    {      /*       * Reenable sequencer, then turn on screen.       */        tmp = VGArSEQ (0x01);      VGAwSEQ (0x01, tmp & ~0x20);	/* reenable display */      vgaHWSeqReset (0);		/* clear synchronousreset */      VGAdisablePalette();    }}static void vgaHWRestore (const struct neofb_info *info,			  const struct neofb_par  *par){  int i;  VGAwMISC (par->MiscOutReg);  for (i = 1; i < 5; i++)    VGAwSEQ (i, par->Sequencer[i]);    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */  VGAwCR (17, par->CRTC[17] & ~0x80);  for (i = 0; i < 25; i++)    VGAwCR (i, par->CRTC[i]);  for (i = 0; i < 9; i++)    VGAwGR (i, par->Graphics[i]);  VGAenablePalette();  for (i = 0; i < 21; i++)    VGAwATTR (i, par->Attribute[i]);  VGAdisablePalette();}static void neofb_set_par (struct neofb_info       *info,			   const struct neofb_par  *par){  unsigned char temp;  int i;  int clock_hi = 0;      DBG("neofb_set_par");  neoUnlock();  vgaHWProtect (1);		/* Blank the screen */  /* linear colormap for non palettized modes */  switch (par->depth)    {    case 8:      break;    case 16:      for (i=0; i<64; i++)	{	  outb(i, 0x3c8);	  	  outb(i << 1, 0x3c9);	  outb(i, 0x3c9);

⌨️ 快捷键说明

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