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 + -
显示快捷键?