📄 radeon_driver.c
字号:
SaveStruct.MEM_CNTL = INREG(RADEON_MEM_CNTL); SaveStruct.MEMSIZE = INREG(RADEON_CONFIG_MEMSIZE); SaveStruct.MPP_TB_CONFIG = INREG(RADEON_MPP_TB_CONFIG); /* * Zap MEM_CNTL and set MPP_TB_CONFIG<31:24> to 4 */ OUTREG(RADEON_MEM_CNTL, 0); CardTmp = SaveStruct.MPP_TB_CONFIG & 0x00ffffffu; CardTmp |= 0x04 << 24; OUTREG(RADEON_MPP_TB_CONFIG, CardTmp); *pPtr = (void *)&SaveStruct;}static voidRADEONPostInt10Check(ScrnInfoPtr pScrn, void *ptr){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; struct RADEONInt10Save *pSave = ptr; CARD32 CardTmp; /* If we don't have a valid (non-zero) saved MEM_CNTL, get out now */ if (!pSave || !pSave->MEM_CNTL) return; /* * If either MEM_CNTL is currently zero or inconistent (configured for * two channels with the two channels configured differently), restore * the saved registers. */ CardTmp = INREG(RADEON_MEM_CNTL); if (!CardTmp || ((CardTmp & 1) && (((CardTmp >> 8) & 0xff) != ((CardTmp >> 24) & 0xff)))) { /* Restore the saved registers */ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Restoring MEM_CNTL (%08lx), setting to %08lx\n", (unsigned long)CardTmp, (unsigned long)pSave->MEM_CNTL); OUTREG(RADEON_MEM_CNTL, pSave->MEM_CNTL); CardTmp = INREG(RADEON_CONFIG_MEMSIZE); if (CardTmp != pSave->MEMSIZE) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Restoring CONFIG_MEMSIZE (%08lx), setting to %08lx\n", (unsigned long)CardTmp, (unsigned long)pSave->MEMSIZE); OUTREG(RADEON_CONFIG_MEMSIZE, pSave->MEMSIZE); } } CardTmp = INREG(RADEON_MPP_TB_CONFIG); if ((CardTmp & 0xff000000u) != (pSave->MPP_TB_CONFIG & 0xff000000u)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Restoring MPP_TB_CONFIG<31:24> (%02lx), setting to %02lx\n", (unsigned long)CardTmp >> 24, (unsigned long)pSave->MPP_TB_CONFIG >> 24); CardTmp &= 0x00ffffffu; CardTmp |= (pSave->MPP_TB_CONFIG & 0xff000000u); OUTREG(RADEON_MPP_TB_CONFIG, CardTmp); }}/* Allocate our private RADEONInfoRec */static Bool RADEONGetRec(ScrnInfoPtr pScrn){ if (pScrn->driverPrivate) return TRUE; pScrn->driverPrivate = xnfcalloc(sizeof(RADEONInfoRec), 1); return TRUE;}/* Free our private RADEONInfoRec */static void RADEONFreeRec(ScrnInfoPtr pScrn){ if (!pScrn || !pScrn->driverPrivate) return; xfree(pScrn->driverPrivate); pScrn->driverPrivate = NULL;}/* Memory map the MMIO region. Used during pre-init and by RADEONMapMem, * below */static Bool RADEONMapMMIO(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); if (info->FBDev) { info->MMIO = fbdevHWMapMMIO(pScrn); } else { info->MMIO = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO | VIDMEM_READSIDEEFFECT, info->PciTag, info->MMIOAddr, RADEON_MMIOSIZE); } if (!info->MMIO) return FALSE; return TRUE;}/* Unmap the MMIO region. Used during pre-init and by RADEONUnmapMem, * below */static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); if (info->FBDev) fbdevHWUnmapMMIO(pScrn); else { xf86UnMapVidMem(pScrn->scrnIndex, info->MMIO, RADEON_MMIOSIZE); } info->MMIO = NULL; return TRUE;}/* Memory map the frame buffer. Used by RADEONMapMem, below. */static Bool RADEONMapFB(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); if (info->FBDev) { info->FB = fbdevHWMapVidmem(pScrn); } else { info->FB = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, info->PciTag, info->LinearAddr, info->FbMapSize); } if (!info->FB) return FALSE; return TRUE;}/* Unmap the frame buffer. Used by RADEONUnmapMem, below. */static Bool RADEONUnmapFB(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); if (info->FBDev) fbdevHWUnmapVidmem(pScrn); else xf86UnMapVidMem(pScrn->scrnIndex, info->FB, info->FbMapSize); info->FB = NULL; return TRUE;}/* Memory map the MMIO region and the frame buffer */static Bool RADEONMapMem(ScrnInfoPtr pScrn){ if (!RADEONMapMMIO(pScrn)) return FALSE; if (!RADEONMapFB(pScrn)) { RADEONUnmapMMIO(pScrn); return FALSE; } return TRUE;}/* Unmap the MMIO region and the frame buffer */static Bool RADEONUnmapMem(ScrnInfoPtr pScrn){ if (!RADEONUnmapMMIO(pScrn) || !RADEONUnmapFB(pScrn)) return FALSE; return TRUE;}/* This function is required to workaround a hardware bug in some (all?) * revisions of the R300. This workaround should be called after every * CLOCK_CNTL_INDEX register access. If not, register reads afterward * may not be correct. */void R300CGWorkaround(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 save, tmp; save = INREG(RADEON_CLOCK_CNTL_INDEX); tmp = save & ~(0x3f | RADEON_PLL_WR_EN); OUTREG(RADEON_CLOCK_CNTL_INDEX, tmp); tmp = INREG(RADEON_CLOCK_CNTL_DATA); OUTREG(RADEON_CLOCK_CNTL_INDEX, save);}/* Read PLL information */unsigned RADEONINPLL(ScrnInfoPtr pScrn, int addr){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 data; OUTREG8(RADEON_CLOCK_CNTL_INDEX, addr & 0x3f); data = INREG(RADEON_CLOCK_CNTL_DATA); if (info->R300CGWorkaround) R300CGWorkaround(pScrn); return data;}#if 0/* Read PAL information (only used for debugging) */static int RADEONINPAL(int idx){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; OUTREG(RADEON_PALETTE_INDEX, idx << 16); return INREG(RADEON_PALETTE_DATA);}#endif/* Wait for vertical sync on primary CRTC */void RADEONWaitForVerticalSync(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; int i; /* Clear the CRTC_VBLANK_SAVE bit */ OUTREG(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); /* Wait for it to go back up */ for (i = 0; i < RADEON_TIMEOUT/1000; i++) { if (INREG(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_SAVE) break; usleep(1); }}/* Wait for vertical sync on secondary CRTC */void RADEONWaitForVerticalSync2(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; int i; /* Clear the CRTC2_VBLANK_SAVE bit */ OUTREG(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); /* Wait for it to go back up */ for (i = 0; i < RADEON_TIMEOUT/1000; i++) { if (INREG(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_SAVE) break; usleep(1); }}/* Blank screen */static void RADEONBlank(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; if (!info->IsSecondary) { switch(info->DisplayType) { case MT_LCD: case MT_CRT: case MT_DFP: OUTREGP(RADEON_CRTC_EXT_CNTL, RADEON_CRTC_DISPLAY_DIS, ~(RADEON_CRTC_DISPLAY_DIS)); break; case MT_NONE: default: break; } if (info->Clone) OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS, ~(RADEON_CRTC2_DISP_DIS)); } else { OUTREGP(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_DISP_DIS, ~(RADEON_CRTC2_DISP_DIS)); }}/* Unblank screen */static void RADEONUnblank(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; if (!info->IsSecondary) { switch (info->DisplayType) { case MT_LCD: case MT_CRT: case MT_DFP: OUTREGP(RADEON_CRTC_EXT_CNTL, RADEON_CRTC_CRT_ON, ~(RADEON_CRTC_DISPLAY_DIS)); break; case MT_NONE: default: break; } if (info->Clone) OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~(RADEON_CRTC2_DISP_DIS)); } else { switch (info->DisplayType) { case MT_LCD: case MT_DFP: case MT_CRT: OUTREGP(RADEON_CRTC2_GEN_CNTL, 0, ~(RADEON_CRTC2_DISP_DIS)); break; case MT_NONE: default: break; } }}/* Compute log base 2 of val */int RADEONMinBits(int val){ int bits; if (!val) return 1; for (bits = 0; val; val >>= 1, ++bits); return bits;}/* Compute n/d with rounding */static int RADEONDiv(int n, int d){ return (n + (d / 2)) / d;}static RADEONMonitorType RADEONDisplayDDCConnected(ScrnInfoPtr pScrn, RADEONDDCType DDCType, xf86MonPtr* MonInfo){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; unsigned long DDCReg; RADEONMonitorType MonType = MT_NONE; int i, j; DDCReg = info->DDCReg; switch(DDCType) { case DDC_MONID: info->DDCReg = RADEON_GPIO_MONID; break; case DDC_DVI: info->DDCReg = RADEON_GPIO_DVI_DDC; break; case DDC_VGA: info->DDCReg = RADEON_GPIO_VGA_DDC; break; case DDC_CRT2: info->DDCReg = RADEON_GPIO_CRT2_DDC; break; default: info->DDCReg = DDCReg; return MT_NONE; } /* Read and output monitor info using DDC2 over I2C bus */ if (info->pI2CBus && info->ddc2) { OUTREG(info->DDCReg, INREG(info->DDCReg) & (CARD32)~(RADEON_GPIO_A_0 | RADEON_GPIO_A_1)); /* For some old monitors (like Compaq Presario FP500), we need * following process to initialize/stop DDC */ OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); for (j = 0; j < 3; j++) { OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); usleep(13000); OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); for (i = 0; i < 3; i++) { usleep(15000); if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) break; } if (i == 10) continue; usleep(15000); OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); usleep(15000); OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); usleep(15000); OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); usleep(15000); *MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, info->pI2CBus); OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); usleep(15000); OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_1)); for (i = 0; i < 5; i++) { usleep(15000); if (INREG(info->DDCReg) & RADEON_GPIO_Y_1) break; } usleep(15000); OUTREG(info->DDCReg, INREG(info->DDCReg) & ~(RADEON_GPIO_EN_0)); usleep(15000); OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_1); OUTREG(info->DDCReg, INREG(info->DDCReg) | RADEON_GPIO_EN_0); usleep(15000); if(*MonInfo) break; } } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); MonType = MT_NONE; } if (*MonInfo) { if ((*MonInfo)->rawData[0x14] & 0x80) { if (INREG(RADEON_LVDS_GEN_CNTL) & RADEON_LVDS_ON) MonType = MT_LCD; else MonType = MT_DFP; } else MonType = MT_CRT; } else MonType = MT_NONE; info->DDCReg = DDCReg; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Type: %d, Detected Type: %d\n", DDCType, MonType); return MonType;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -