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

📄 neofb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	  outb(i << 1, 0x3c9);	}      break;    case 24:#ifdef NO_32BIT_SUPPORT_YET    case 32:#endif      for (i=0; i<256; i++)	{	  outb(i, 0x3c8);	  	  outb(i, 0x3c9);	  outb(i, 0x3c9);	  outb(i, 0x3c9);	}      break;    }      /* alread unlocked above */  /* BOGUS  VGAwGR (0x09, 0x26);*/      /* don't know what this is, but it's 0 from bootup anyway */  VGAwGR (0x15, 0x00);  /* was set to 0x01 by my bios in text and vesa modes */  VGAwGR (0x0A, par->GeneralLockReg);  /*   * The color mode needs to be set before calling vgaHWRestore   * to ensure the DAC is initialized properly.   *   * NOTE: Make sure we don't change bits make sure we don't change   * any reserved bits.   */  temp = VGArGR(0x90);  switch (info->accel)    {    case FB_ACCEL_NEOMAGIC_NM2070:      temp &= 0xF0; /* Save bits 7:4 */      temp |= (par->ExtColorModeSelect & ~0xF0);      break;    case FB_ACCEL_NEOMAGIC_NM2090:    case FB_ACCEL_NEOMAGIC_NM2093:    case FB_ACCEL_NEOMAGIC_NM2097:    case FB_ACCEL_NEOMAGIC_NM2160:    case FB_ACCEL_NEOMAGIC_NM2200:    case FB_ACCEL_NEOMAGIC_NM2230:    case FB_ACCEL_NEOMAGIC_NM2360:    case FB_ACCEL_NEOMAGIC_NM2380:      temp &= 0x70; /* Save bits 6:4 */      temp |= (par->ExtColorModeSelect & ~0x70);      break;    }  VGAwGR(0x90,temp);  /*   * In some rare cases a lockup might occur if we don't delay   * here. (Reported by Miles Lane)   */  //mdelay(200);  /*   * Disable horizontal and vertical graphics and text expansions so   * that vgaHWRestore works properly.   */  temp = VGArGR(0x25);  temp &= 0x39;  VGAwGR (0x25, temp);  /*   * Sleep for 200ms to make sure that the two operations above have   * had time to take effect.   */  mdelay(200);  /*   * This function handles restoring the generic VGA registers.  */  vgaHWRestore (info, par);  VGAwGR(0x0E, par->ExtCRTDispAddr);  VGAwGR(0x0F, par->ExtCRTOffset);  temp = VGArGR(0x10);  temp &= 0x0F; /* Save bits 3:0 */  temp |= (par->SysIfaceCntl1 & ~0x0F); /* VESA Bios sets bit 1! */  VGAwGR(0x10, temp);  VGAwGR(0x11, par->SysIfaceCntl2);  VGAwGR(0x15, 0 /*par->SingleAddrPage*/);  VGAwGR(0x16, 0 /*par->DualAddrPage*/);  temp = VGArGR(0x20);  switch (info->accel)    {    case FB_ACCEL_NEOMAGIC_NM2070:      temp &= 0xFC; /* Save bits 7:2 */      temp |= (par->PanelDispCntlReg1 & ~0xFC);      break;    case FB_ACCEL_NEOMAGIC_NM2090:    case FB_ACCEL_NEOMAGIC_NM2093:    case FB_ACCEL_NEOMAGIC_NM2097:    case FB_ACCEL_NEOMAGIC_NM2160:      temp &= 0xDC; /* Save bits 7:6,4:2 */      temp |= (par->PanelDispCntlReg1 & ~0xDC);      break;    case FB_ACCEL_NEOMAGIC_NM2200:    case FB_ACCEL_NEOMAGIC_NM2230:    case FB_ACCEL_NEOMAGIC_NM2360:    case FB_ACCEL_NEOMAGIC_NM2380:      temp &= 0x98; /* Save bits 7,4:3 */      temp |= (par->PanelDispCntlReg1 & ~0x98);      break;    }  VGAwGR(0x20, temp);  temp = VGArGR(0x25);  temp &= 0x38; /* Save bits 5:3 */  temp |= (par->PanelDispCntlReg2 & ~0x38);  VGAwGR(0x25, temp);  if (info->accel != FB_ACCEL_NEOMAGIC_NM2070)    {      temp = VGArGR(0x30);      temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */      temp |= (par->PanelDispCntlReg3 & ~0xEF);      VGAwGR(0x30, temp);    }  VGAwGR(0x28, par->PanelVertCenterReg1);  VGAwGR(0x29, par->PanelVertCenterReg2);  VGAwGR(0x2a, par->PanelVertCenterReg3);  if (info->accel != FB_ACCEL_NEOMAGIC_NM2070)    {      VGAwGR(0x32, par->PanelVertCenterReg4);      VGAwGR(0x33, par->PanelHorizCenterReg1);      VGAwGR(0x34, par->PanelHorizCenterReg2);      VGAwGR(0x35, par->PanelHorizCenterReg3);    }  if (info->accel == FB_ACCEL_NEOMAGIC_NM2160)    VGAwGR(0x36, par->PanelHorizCenterReg4);  if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 ||      info->accel == FB_ACCEL_NEOMAGIC_NM2230 ||      info->accel == FB_ACCEL_NEOMAGIC_NM2360 ||      info->accel == FB_ACCEL_NEOMAGIC_NM2380)    {      VGAwGR(0x36, par->PanelHorizCenterReg4);      VGAwGR(0x37, par->PanelVertCenterReg5);      VGAwGR(0x38, par->PanelHorizCenterReg5);      clock_hi = 1;    }  /* Program VCLK3 if needed. */  if (par->ProgramVCLK      && ((VGArGR(0x9B) != par->VCLK3NumeratorLow)	  || (VGArGR(0x9F) !=  par->VCLK3Denominator)	  || (clock_hi && ((VGArGR(0x8F) & ~0x0f)			   != (par->VCLK3NumeratorHigh & ~0x0F)))))    {      VGAwGR(0x9B, par->VCLK3NumeratorLow);      if (clock_hi)	{	  temp = VGArGR(0x8F);	  temp &= 0x0F; /* Save bits 3:0 */	  temp |= (par->VCLK3NumeratorHigh & ~0x0F);	  VGAwGR(0x8F, temp);	}      VGAwGR(0x9F, par->VCLK3Denominator);    }  if (par->biosMode)    VGAwCR(0x23, par->biosMode);      VGAwGR (0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */  /* Program vertical extension register */  if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 ||      info->accel == FB_ACCEL_NEOMAGIC_NM2230 ||      info->accel == FB_ACCEL_NEOMAGIC_NM2360 ||      info->accel == FB_ACCEL_NEOMAGIC_NM2380)    {      VGAwCR(0x70, par->VerticalExt);    }  vgaHWProtect (0);		/* Turn on screen */  /* Calling this also locks offset registers required in update_start */  neoLock();}static void neofb_update_start (struct neofb_info *info, struct fb_var_screeninfo *var){  int oldExtCRTDispAddr;  int Base;   DBG("neofb_update_start");  Base = (var->yoffset * var->xres_virtual + var->xoffset) >> 2;  Base *= (var->bits_per_pixel + 7) / 8;  neoUnlock();  /*   * These are the generic starting address registers.   */  VGAwCR(0x0C, (Base & 0x00FF00) >> 8);  VGAwCR(0x0D, (Base & 0x00FF));  /*   * Make sure we don't clobber some other bits that might already   * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't   * be needed.   */  oldExtCRTDispAddr = VGArGR(0x0E);  VGAwGR(0x0E,(((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));  neoLock();}/* * Set the Colormap */static int neofb_set_cmap(struct fb_cmap *cmap, int kspc, int con,			  struct fb_info *fb){  struct neofb_info *info = (struct neofb_info *)fb;  struct display* disp = (con < 0) ? fb->disp : (fb_display + con);  struct fb_cmap *dcmap = &disp->cmap;  int err = 0;  /* no colormap allocated? */  if (!dcmap->len)    {      int size;      if (fb->var.bits_per_pixel == 8)	size = NR_PALETTE;      else	size = 32;      err = fb_alloc_cmap (dcmap, size, 0);    }  /*   * we should be able to remove this test once fbcon has been   * "improved" --rmk   */  if (!err && con == info->currcon)    {      err = fb_set_cmap (cmap, kspc, neo_setcolreg, fb);      dcmap = &fb->cmap;    }  if (!err)    fb_copy_cmap (cmap, dcmap, kspc ? 0 : 1);  return err;}/* * neoCalcVCLK -- * * Determine the closest clock frequency to the one requested. */#define REF_FREQ 0xe517  /* 14.31818 in 20.12 fixed point */#define MAX_N 127#define MAX_D 31#define MAX_F 1static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, long freq){  int n, d, f;  int n_best = 0, d_best = 0, f_best = 0;  long f_best_diff = (0x7ffff << 12); /* 20.12 */  long f_target = (freq << 12) / 1000; /* 20.12 */  for (f = 0; f <= MAX_F; f++)    for (n = 0; n <= MAX_N; n++)      for (d = 0; d <= MAX_D; d++)	{          long f_out;  /* 20.12 */          long f_diff; /* 20.12 */	  f_out = ((((n+1) << 12)  /  ((d+1)*(1<<f))) >> 12)  *  REF_FREQ;	  f_diff = abs(f_out-f_target);	  if (f_diff < f_best_diff)	    {	      f_best_diff = f_diff;	      n_best = n;	      d_best = d;	      f_best = f;	    }	}  if (info->accel == FB_ACCEL_NEOMAGIC_NM2200 ||      info->accel == FB_ACCEL_NEOMAGIC_NM2230 ||      info->accel == FB_ACCEL_NEOMAGIC_NM2360 ||      info->accel == FB_ACCEL_NEOMAGIC_NM2380)    {      /* NOT_DONE:  We are trying the full range of the 2200 clock.	 We should be able to try n up to 2047 */      par->VCLK3NumeratorLow  = n_best;      par->VCLK3NumeratorHigh = (f_best << 7);    }  else    par->VCLK3NumeratorLow  = n_best | (f_best << 7);  par->VCLK3Denominator = d_best;#ifdef NEOFB_DEBUG  printk ("neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d\n",	  f_target >> 12,	  par->VCLK3NumeratorLow,	  par->VCLK3NumeratorHigh,	  par->VCLK3Denominator,	  f_best_diff >> 12);#endif}/* * vgaHWInit -- *      Handle the initialization, etc. of a screen. *      Return FALSE on failure. */static int vgaHWInit (const struct fb_var_screeninfo *var,		      const struct neofb_info        *info,		      struct neofb_par               *par,		      struct xtimings                *timings){  par->MiscOutReg = 0x23;  if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))    par->MiscOutReg |= 0x40;  if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))    par->MiscOutReg |= 0x80;      /*   * Time Sequencer   */  par->Sequencer[0] = 0x00;  par->Sequencer[1] = 0x01;  par->Sequencer[2] = 0x0F;  par->Sequencer[3] = 0x00;                             /* Font select */  par->Sequencer[4] = 0x0E;                             /* Misc */  /*   * CRTC Controller   */  par->CRTC[0]  = (timings->HTotal >> 3) - 5;  par->CRTC[1]  = (timings->HDisplay >> 3) - 1;  par->CRTC[2]  = (timings->HDisplay >> 3) - 1;  par->CRTC[3]  = (((timings->HTotal >> 3) - 1) & 0x1F) | 0x80;  par->CRTC[4]  = (timings->HSyncStart >> 3);  par->CRTC[5]  = ((((timings->HTotal >> 3) - 1) & 0x20) << 2)    | (((timings->HSyncEnd >> 3)) & 0x1F);  par->CRTC[6]  = (timings->VTotal - 2) & 0xFF;  par->CRTC[7]  = (((timings->VTotal - 2) & 0x100) >> 8)    | (((timings->VDisplay - 1) & 0x100) >> 7)    | ((timings->VSyncStart & 0x100) >> 6)    | (((timings->VDisplay - 1) & 0x100) >> 5)    | 0x10    | (((timings->VTotal - 2) & 0x200)   >> 4)    | (((timings->VDisplay - 1) & 0x200) >> 3)    | ((timings->VSyncStart & 0x200) >> 2);  par->CRTC[8]  = 0x00;  par->CRTC[9]  = (((timings->VDisplay - 1) & 0x200) >> 4) | 0x40;  if (timings->dblscan)    par->CRTC[9] |= 0x80;  par->CRTC[10] = 0x00;  par->CRTC[11] = 0x00;  par->CRTC[12] = 0x00;  par->CRTC[13] = 0x00;  par->CRTC[14] = 0x00;  par->CRTC[15] = 0x00;  par->CRTC[16] = timings->VSyncStart & 0xFF;  par->CRTC[17] = (timings->VSyncEnd & 0x0F) | 0x20;  par->CRTC[18] = (timings->VDisplay - 1) & 0xFF;  par->CRTC[19] = var->xres_virtual >> 4;  par->CRTC[20] = 0x00;  par->CRTC[21] = (timings->VDisplay - 1) & 0xFF;   par->CRTC[22] = (timings->VTotal - 1) & 0xFF;  par->CRTC[23] = 0xC3;  par->CRTC[24] = 0xFF;  /*   * are these unnecessary?   * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);   * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);   */  /*   * Graphics Display Controller   */  par->Graphics[0] = 0x00;  par->Graphics[1] = 0x00;  par->Graphics[2] = 0x00;  par->Graphics[3] = 0x00;  par->Graphics[4] = 0x00;  par->Graphics[5] = 0x40;  par->Graphics[6] = 0x05;   /* only map 64k VGA memory !!!! */  par->Graphics[7] = 0x0F;  par->Graphics[8] = 0xFF;    par->Attribute[0]  = 0x00; /* standard colormap translation */  par->Attribute[1]  = 0x01;  par->Attribute[2]  = 0x02;  par->Attribute[3]  = 0x03;  par->Attribute[4]  = 0x04;  par->Attribute[5]  = 0x05;  par->Attribute[6]  = 0x06;  par->Attribute[7]  = 0x07;  par->Attribute[8]  = 0x08;  par->Attribute[9]  = 0x09;  par->Attribute[10] = 0x0A;  par->Attribute[11] = 0x0B;  par->Attribute[12] = 0x0C;  par->Attribute[13] = 0x0D;  par->Attribute[14] = 0x0E;  par->Attribute[15] = 0x0F;  par->Attribute[16] = 0x41;  par->Attribute[17] = 0xFF;  par->Attribute[18] = 0x0F;  par->Attribute[19] = 0x00;  par->Attribute[20] = 0x00;  return 0;}static int neofb_decode_var (struct fb_var_screeninfo        *var,                             const struct neofb_info         *info,                             struct neofb_par                *par){  struct xtimings timings;  int lcd_stretch;  int hoffset, voffset;  int memlen, vramlen;  int mode_ok = 0;  unsigned int pixclock = var->pixclock;  DBG("neofb_decode_var");  if (!pixclock) pixclock = 10000;	/* 10ns = 100MHz */  timings.pixclock = 1000000000 / pixclock;  if (timings.pixclock < 1) timings.pixclock = 1;  timings.dblscan = var->vmode & FB_VMODE_DOUBLE;  timings.interlaced = var->vmode & FB_VMODE_INTERLACED;  timings.HDisplay = var->xres;  timings.HSyncStart = timings.HDisplay + var->right_margin;  timings.HSyncEnd = timings.HSyncStart + var->hsync_len;  timings.HTotal = timings.HSyncEnd + var->left_margin;  timings.VDisplay = var->yres;  timings.VSyncStart = timings.VDisplay + var->lower_margin;  timings.VSyncEnd = timings.VSyncStart + var->vsync_len;  timings.VTotal = timings.VSyncEnd + var->upper_margin;  timings.sync = var->sync;  if (timings.pixclock > info->maxClock)    return -EINVAL;  /* Is the mode larger than the LCD panel? */  if ((var->xres > info->NeoPanelWidth) ||      (var->yres > info->NeoPanelHeight))    {      printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",	      var->xres,	      var->yres,	      info->NeoPanelWidth,	      info->NeoPanelHeight);      return -EINVAL;    }  /* Is the mode one of the acceptable sizes? */  switch (var->xres)    {    case 1280:      if (var->yres == 1024)	mode_ok = 1;      break;    case 1024:      if (var->yres == 768)	mode_ok = 1;      break;    case  800:      if (var->yres == 600)	mode_ok = 1;      break;    case  640:      if (var->yres == 480)	mode_ok = 1;      break;    }  if (!mode_ok)    {      printk (KERN_INFO "Mode (%dx%d) won't display properly on LCD\n",	      var->xres, var->yres);      return -EINVAL;    }  switch (var->bits_per_pixel)    {#ifdef FBCON_HAS_CFB8    case 8:      break;#endif#ifdef FBCON_HAS_CFB16    case 16:      break;#endif#ifdef FBCON_HAS_CFB24    case 24:      break;#endif#ifdef NO_32BIT_SUPPORT_YET# ifdef FBCON_HAS_CFB32    case 32:      break;# endif#endif    default:      return -EINVAL;    }  par->depth = var->bits_per_pixel;  vramlen = info->video.len;  if (vramlen > 4*1024*1024)    vramlen = 4*1024*1024;  if (var->yres_virtual < var->yres)    var->yres_virtual = var->yres;  if (var->xres_virtual < var->xres)    var->xres_virtual = var->xres;  memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;  if (memlen > vramlen)    {      var->yres_virtual = vramlen * 8 / (var->xres_virtual * var->bits_per_pixel);      memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;    }  /* we must round yres/xres down, we already rounded y/xres_virtual up     if it was possible. We should return -EINVAL, but I disagree */  if (var->yres_virtual < var->yres)    var->yres = var->yres_virtual;  if (var->xres_virtual < var->xres)    var->xres = var->xres_virtual;  if (var->xoffset + var->xres > var->xres_virtual)    var->xoffset = var->xres_virtual - var->xres;  if (var->yoffset + var->yres > var->yres_virtual)    var->yoffset = var->yres_virtual - var->yres;  /*   * This will allocate the datastructure and initialize all of the   * generic VGA registers.   */  if (vgaHWInit (var, info, par, &timings))    return -EINVAL;  /*   * The default value assigned by vgaHW.c is 0x41, but this does   * not work for NeoMagic.   */  par->Attribute[16] = 0x01;  switch (var->bits_per_pixel)    {    case  8:      par->CRTC[0x13]   = var->xres_virtual >> 3;      par->ExtCRTOffset = var->xres_virtual >> 11;      par->ExtColorModeSelect = 0x11;      break;    case 16:      par->CRTC[0x13]   = var->xres_virtual >> 2;      par->ExtCRTOffset = var->xres_virtual >> 10;      par->ExtColorModeSelect = 0x13;      break;    case 24:      par->CRTC[0x13]   = (var->xres_virtual * 3) >> 3;      par->ExtCRTOffset = (var->xres_virtual * 3) >> 11;      par->ExtColorModeSelect = 0x14;      break;#ifdef NO_32BIT_SUPPORT_YET    case 32: /* FIXME: guessed values */      par->CRTC[0x13]   = var->xres_virtual >> 1;      par->ExtCRTOffset = var->xres_virtual >> 9;      par->ExtColorModeSelect = 0x15;      break;#endif

⌨️ 快捷键说明

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