i810_driver.c

来自「是由intel提供的针对intel显卡915以上系列的linux驱动」· C语言 代码 · 共 2,368 行 · 第 1/5 页

C
2,368
字号
   /*    * Turn on 8 bit dac mode, if requested.  This is needed to make    * sure that vgaHWRestore writes the values into the DAC properly.    * The problem occurs if 8 bit dac mode is requested and the HW is    * in 6 bit dac mode.  If this happens, all the values are    * automatically shifted left twice by the HW and incorrect colors    * will be displayed on the screen.  The only time this can happen    * is at server startup time and when switching back from a VT.    */   temp = INREG8(PIXPIPE_CONFIG_0);   temp &= 0x7F;			/* Save all but the 8 bit dac mode bit */   temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT);   OUTREG8(PIXPIPE_CONFIG_0, temp);   /*    * Code to restore any SVGA registers that have been saved/modified    * goes here.  Note that it is allowable, and often correct, to    * only modify certain bits in a register by a read/modify/write cycle.    *    * A special case - when using an external clock-setting program,    * this function must not change bits associated with the clock    * selection.  This condition can be checked by the condition:    *    *   if (i810Reg->std.NoClock >= 0)    *           restore clock-select bits.    */   if (restoreFonts)      vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);   else      vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);   hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i810Reg->ExtVertTotal);   hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd);   hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart);   hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart);   hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal);   hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank);   hwp->writeCrtc(hwp, EXT_OFFSET, i810Reg->ExtOffset);   temp = hwp->readCrtc(hwp, INTERLACE_CNTL);   temp &= ~INTERLACE_ENABLE;   temp |= i810Reg->InterlaceControl;   hwp->writeCrtc(hwp, INTERLACE_CNTL, temp);   temp = pI810->readControl(pI810, GRX, ADDRESS_MAPPING);   temp &= 0xE0;			/* Save reserved bits 7:5 */   temp |= i810Reg->AddressMapping;   pI810->writeControl(pI810, GRX, ADDRESS_MAPPING, temp);   /* Setting the OVRACT Register for video overlay */   {       CARD32 LCD_TV_Control = INREG(LCD_TV_C);       CARD32 TV_HTotal = INREG(LCD_TV_HTOTAL);       CARD32 ActiveStart, ActiveEnd;              if((LCD_TV_Control & LCD_TV_ENABLE)	  && !(LCD_TV_Control & LCD_TV_VGAMOD)	   && TV_HTotal) {	   ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31;	   ActiveEnd = (TV_HTotal & 0x3ff) - 31;       } else {	   ActiveStart = i810Reg->OverlayActiveStart;	   ActiveEnd = i810Reg->OverlayActiveEnd;       }       OUTREG(LCD_TV_OVRACT,	      (ActiveEnd << 16) | ActiveStart);   }      /* Turn on DRAM Refresh */   temp = INREG8(DRAM_ROW_CNTL_HI);   temp &= ~DRAM_REFRESH_RATE;   temp |= DRAM_REFRESH_60HZ;   OUTREG8(DRAM_ROW_CNTL_HI, temp);   temp = INREG8(BITBLT_CNTL);   temp &= ~COLEXP_MODE;   temp |= i810Reg->BitBLTControl;   OUTREG8(BITBLT_CNTL, temp);   temp = INREG8(DISPLAY_CNTL);   temp &= ~(VGA_WRAP_MODE | GUI_MODE);   temp |= i810Reg->DisplayControl;   OUTREG8(DISPLAY_CNTL, temp);   temp = INREG8(PIXPIPE_CONFIG_0);   temp &= 0x64;			/* Save reserved bits 6:5,2 */   temp |= i810Reg->PixelPipeCfg0;   OUTREG8(PIXPIPE_CONFIG_0, temp);   temp = INREG8(PIXPIPE_CONFIG_2);   temp &= 0xF3;			/* Save reserved bits 7:4,1:0 */   temp |= i810Reg->PixelPipeCfg2;   OUTREG8(PIXPIPE_CONFIG_2, temp);   temp = INREG8(PIXPIPE_CONFIG_1);   temp &= ~DISPLAY_COLOR_MODE;   temp &= 0xEF;			/* Restore the CRT control bit */   temp |= i810Reg->PixelPipeCfg1;   OUTREG8(PIXPIPE_CONFIG_1, temp);   OUTREG16(EIR, 0);   itemp = INREG(FWATER_BLC);   itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK |	      MM_BURST_LENGTH | MM_FIFO_WATERMARK);   itemp |= i810Reg->LMI_FIFO_Watermark;   OUTREG(FWATER_BLC, itemp);   for (i = 0; i < 8; i++) {      OUTREG(FENCE + i * 4, i810Reg->Fence[i]);      if (I810_DEBUG & DEBUG_VERBOSE_VGA)	 ErrorF("Fence Register : %x\n", i810Reg->Fence[i]);   }   /* First disable the ring buffer (Need to wait for empty first?, if so    * should probably do it before entering this section)    */   itemp = INREG(LP_RING + RING_LEN);   itemp &= ~RING_VALID_MASK;   OUTREG(LP_RING + RING_LEN, itemp);   /* Set up the low priority ring buffer.    */   OUTREG(LP_RING + RING_TAIL, 0);   OUTREG(LP_RING + RING_HEAD, 0);   pI810->LpRing->head = 0;   pI810->LpRing->tail = 0;   itemp = INREG(LP_RING + RING_START);   itemp &= ~(START_ADDR);   itemp |= i810Reg->LprbStart;   OUTREG(LP_RING + RING_START, itemp);   itemp = INREG(LP_RING + RING_LEN);   itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);   itemp |= i810Reg->LprbLen;   OUTREG(LP_RING + RING_LEN, itemp);   if (!(vgaReg->Attribute[0x10] & 0x1)) {      usleep(50000);      if (restoreFonts)	 vgaHWRestore(pScrn, vgaReg,		      VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);      else	 vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);   }   vgaHWProtect(pScrn, FALSE);   temp = hwp->readCrtc(hwp, IO_CTNL);   temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);   temp |= i810Reg->IOControl;   hwp->writeCrtc(hwp, IO_CTNL, temp);}static voidI810SetRingRegs(ScrnInfoPtr pScrn){   unsigned int itemp;   I810Ptr pI810 = I810PTR(pScrn);   OUTREG(LP_RING + RING_TAIL, 0);   OUTREG(LP_RING + RING_HEAD, 0);   itemp = INREG(LP_RING + RING_START);   itemp &= ~(START_ADDR);   itemp |= pI810->LpRing->mem.Start;   OUTREG(LP_RING + RING_START, itemp);   itemp = INREG(LP_RING + RING_LEN);   itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);   itemp |= ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID);   OUTREG(LP_RING + RING_LEN, itemp);}static voidI810Restore(ScrnInfoPtr pScrn){   vgaHWPtr hwp;   I810Ptr pI810;   hwp = VGAHWPTR(pScrn);   pI810 = I810PTR(pScrn);   DoRestore(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);}/* * I810CalcVCLK -- * * Determine the closest clock frequency to the one requested. */#define MAX_VCO_FREQ 600.0#define TARGET_MAX_N 30#define REF_FREQ 24.0#define CALC_VCLK(m,n,p) \    (double)m / ((double)n * (1 << p)) * 4 * REF_FREQstatic voidI810CalcVCLK(ScrnInfoPtr pScrn, double freq){   I810Ptr pI810 = I810PTR(pScrn);   I810RegPtr i810Reg = &pI810->ModeReg;   int m, n, p;   double f_out, f_best;   double f_err;   double f_vco;   int m_best = 0, n_best = 0, p_best = 0;   double f_target = freq;   double err_max = 0.005;   double err_target = 0.001;   double err_best = 999999.0;   p_best = p = log(MAX_VCO_FREQ / f_target) / log((double)2);   /* Make sure p is within range. */   if (p_best > 5) {      p_best = p = 5;   }   f_vco = f_target * (1 << p);   n = 2;   do {      n++;      m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5;      if (m < 3)	 m = 3;      f_out = CALC_VCLK(m, n, p);      f_err = 1.0 - (f_target / f_out);      if (fabs(f_err) < err_max) {	 m_best = m;	 n_best = n;	 f_best = f_out;	 err_best = f_err;      }   } while ((fabs(f_err) >= err_target) &&	    ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max)));   if (fabs(f_err) < err_target) {      m_best = m;      n_best = n;   }   i810Reg->VideoClk2_M = (m_best - 2) & 0x3FF;   i810Reg->VideoClk2_N = (n_best - 2) & 0x3FF;   i810Reg->VideoClk2_DivisorSel = (p_best << 4);   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,		  "Setting dot clock to %.1f MHz " "[ 0x%x 0x%x 0x%x ] "		  "[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best),		  i810Reg->VideoClk2_M, i810Reg->VideoClk2_N,		  i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best);}static BoolI810SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode){   I810Ptr pI810 = I810PTR(pScrn);   I810RegPtr i810Reg = &pI810->ModeReg;   vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;   double dclk = mode->Clock / 1000.0;   switch (pScrn->bitsPerPixel) {   case 8:      pVga->CRTC[0x13] = pScrn->displayWidth >> 3;      i810Reg->ExtOffset = pScrn->displayWidth >> 11;      i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;      i810Reg->BitBLTControl = COLEXP_8BPP;      break;   case 16:      if (pScrn->weight.green == 5) {	 i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE;      } else {	 i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;      }      pVga->CRTC[0x13] = pScrn->displayWidth >> 2;      i810Reg->ExtOffset = pScrn->displayWidth >> 10;      i810Reg->BitBLTControl = COLEXP_16BPP;      /* Enable Palette Programming for Direct Color visuals. -jens */      i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;      break;   case 24:      pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3;      i810Reg->ExtOffset = (pScrn->displayWidth * 3) >> 11;      i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;      i810Reg->BitBLTControl = COLEXP_24BPP;      /* Enable Palette Programming for Direct Color visuals. -jens */      i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;      break;   default:      break;   }   /* Turn on 8 bit dac if requested */   if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))      i810Reg->PixelPipeCfg0 = DAC_6_BIT;   else      i810Reg->PixelPipeCfg0 = DAC_8_BIT;   /* Do not delay CRT Blank: needed for video overlay */   i810Reg->PixelPipeCfg1 |= 0x10;   /* Turn on Extended VGA Interpretation */   i810Reg->IOControl = EXTENDED_CRTC_CNTL;   /* Turn on linear and page mapping */   i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE);   /* Turn on GUI mode */   i810Reg->DisplayControl = HIRES_MODE;   /* Calculate the extended CRTC regs */   i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8;   i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8;   i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8;   i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8;   i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8;   i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6;   /*    * the KGA fix in vgaHW.c results in the first    * scanline and the first character clock (8 pixels)    * of each scanline thereafter on display with an i810    * to be blank. Restoring CRTC 3, 5, & 22 to their    * "theoretical" values corrects the problem. KAO.    */   pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;   pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)	 | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);   pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;   i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0);   vgaHWVBlankKGA(mode, pVga, 8, 0);   /*    * The following workarounds are needed to get video overlay working    * at 1024x768 and 1280x1024 display resolutions.    */   if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) {      i810Reg->ExtVertBlankStart = 2;   }   if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) {      i810Reg->ExtVertBlankStart = 3;   }   /* OVRACT Register */   i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32;   i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32;   /* Turn on interlaced mode if necessary */   if (mode->Flags & V_INTERLACE) {      i810Reg->InterlaceControl = INTERLACE_ENABLE;      i810Reg->ExtVertDispEnd *= 2;   } else      i810Reg->InterlaceControl = INTERLACE_DISABLE;   /*    * Set the overscan color to 0.    * NOTE: This only affects >8bpp mode.    */   pVga->Attribute[0x11] = 0;   /*    * Calculate the VCLK that most closely matches the requested dot    * clock.    */   I810CalcVCLK(pScrn, dclk);   /* Since we program the clocks ourselves, always use VCLK2. */   pVga->MiscOutReg |= 0x0C;   /* Calculate the FIFO Watermark and Burst Length. */   i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(pScrn, dclk, FALSE);   /* Setup the ring buffer */   i810Reg->LprbTail = 0;   i810Reg->LprbHead = 0;   i810Reg->LprbStart = pI810->LpRing->mem.Start;   if (i810Reg->LprbStart)      i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) |			  RING_NO_REPORT | RING_VALID);   else      i810Reg->LprbLen = RING_INVALID;   return TRUE;}static BoolI810ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode){   vgaHWPtr hwp;   I810Ptr pI810;   hwp = VGAHWPTR(pScrn);   pI810 = I810PTR(pScrn);   vgaHWUnlock(hwp);   if (!vgaHWInit(pScrn, mode))      return FALSE;   pScrn->vtSema = TRUE;   if (!I810SetMode(pScrn, mode))      return FALSE;#ifdef XF86DRI   if (pI810->directRenderingEnabled) {      DRILock(screenInfo.screens[pScrn->scrnIndex], 0);      pI810->LockHeld = 1;   }#endif   DoRestore(pScrn, &hwp->ModeReg, &pI810->ModeReg, FALSE);#ifdef XF86DRI   if (pI810->directRenderingEnabled) {      DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);      pI810->LockHeld = 0;   }#endif   return TRUE;}static voidI810LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices,		  LOCO * colors, VisualPtr pVisual){   I810Ptr pI810;   vgaHWPtr hwp;   int i, j, index;   unsigned char r, g, b;   pI810 = I810PTR(pScrn);   hwp = VGAHWPTR(pScrn);   for (i = 0; i < numColors; i++) {      index = indices[i];      r = colors[index].red;      g = colors[index].green;      b = colors[index].blue;      for (j = 0; j < 8; j++) {	 hwp->writeDacWriteAddr(hwp, (index << 3) + j);	 hwp->writeDacData(hwp, r);	 hwp->writeDacData(hwp, g);	 hwp->writeDacData(hwp, b);      }   }}static voidI810LoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices,		  LOCO * colors, VisualPtr pVisual){   I810Ptr pI810;   vgaHWPtr hwp;   int i, index;   unsigned char r, g, b;   pI810 = I810PTR(pScrn);   hwp = VGAHWPTR(pScrn);   /* Load all four entries in each of the 64 color ranges.  -jens */   for (i = 0; i < numColors; i++) {      index = indices[i / 2];      r = colors[index].red;

⌨️ 快捷键说明

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