📄 radeon_driver.c
字号:
#ifdef USE_XAA xaaSymbols,#endif#if 0 xf8_32bppSymbols,#endif ramdacSymbols,#ifdef XF86DRI drmSymbols, driSymbols, driShadowFBSymbols,#endif fbdevHWSymbols, vbeSymbols, int10Symbols, i2cSymbols, ddcSymbols, NULL);}/* Established timings from EDID standard */static struct{ int hsize; int vsize; int refresh;} est_timings[] = { {1280, 1024, 75}, {1024, 768, 75}, {1024, 768, 70}, {1024, 768, 60}, {1024, 768, 87}, {832, 624, 75}, {800, 600, 75}, {800, 600, 72}, {800, 600, 60}, {800, 600, 56}, {640, 480, 75}, {640, 480, 72}, {640, 480, 67}, {640, 480, 60}, {720, 400, 88}, {720, 400, 70},};static const RADEONTMDSPll default_tmds_pll[CHIP_FAMILY_LAST][4] ={ {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_UNKNOW*/ {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_LEGACY*/ {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RADEON*/ {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV100*/ {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS100*/ {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV200*/ {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS200*/ {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R200*/ {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV250*/ {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS300*/ {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /*CHIP_FAMILY_RV280*/ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R300*/ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R350*/ {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV350*/ {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV380*/ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_R420*/ {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RV410*/ /* FIXME: just values from r420 used... */ {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /*CHIP_FAMILY_RS400*/ /* FIXME: just values from rv380 used... */};#ifdef XFree86LOADERstatic int getRADEONEntityIndex(void){ int *radeon_entity_index = LoaderSymbol("gRADEONEntityIndex"); if (!radeon_entity_index) return -1; else return *radeon_entity_index;}#elseextern int gRADEONEntityIndex;static int getRADEONEntityIndex(void){ return gRADEONEntityIndex;}#endifstruct RADEONInt10Save { CARD32 MEM_CNTL; CARD32 MEMSIZE; CARD32 MPP_TB_CONFIG;};static Bool RADEONMapMMIO(ScrnInfoPtr pScrn);static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn);RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn){ DevUnion *pPriv; RADEONInfoPtr info = RADEONPTR(pScrn); pPriv = xf86GetEntityPrivate(info->pEnt->index, getRADEONEntityIndex()); return pPriv->ptr;}static voidRADEONPreInt10Save(ScrnInfoPtr pScrn, void **pPtr){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 CardTmp; static struct RADEONInt10Save SaveStruct = { 0, 0, 0 }; /* Save the values and zap MEM_CNTL */ 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){ RADEONInfoPtr info = RADEONPTR(pScrn); if(info->CRT2HSync) xfree(info->CRT2HSync); info->CRT2HSync = NULL; if(info->CRT2VRefresh) xfree(info->CRT2VRefresh); info->CRT2VRefresh = NULL; if(info->MetaModes) xfree(info->MetaModes); info->MetaModes = NULL; if(info->CRT2pScrn) { if(info->CRT2pScrn->modes) { while(info->CRT2pScrn->modes) xf86DeleteMode(&info->CRT2pScrn->modes, info->CRT2pScrn->modes); } if(info->CRT2pScrn->monitor) { if(info->CRT2pScrn->monitor->Modes) { while(info->CRT2pScrn->monitor->Modes) xf86DeleteMode(&info->CRT2pScrn->monitor->Modes, info->CRT2pScrn->monitor->Modes); } if(info->CRT2pScrn->monitor->DDC) xfree(info->CRT2pScrn->monitor->DDC); xfree(info->CRT2pScrn->monitor); } xfree(info->CRT2pScrn); info->CRT2pScrn = NULL; } if(info->CRT1Modes) { if(info->CRT1Modes != pScrn->modes) { if(pScrn->modes) { pScrn->currentMode = pScrn->modes; do { DisplayModePtr p = pScrn->currentMode->next; if(pScrn->currentMode->Private) xfree(pScrn->currentMode->Private); xfree(pScrn->currentMode); pScrn->currentMode = p; } while(pScrn->currentMode != pScrn->modes); } pScrn->currentMode = info->CRT1CurrentMode; pScrn->modes = info->CRT1Modes; info->CRT1CurrentMode = NULL; info->CRT1Modes = NULL; } } 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, info->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, info->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 { RADEONTRACE(("Map: 0x%08lx, 0x%08lx\n", info->LinearAddr, info->FbMapSize)); 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;}void RADEONPllErrataAfterIndex(RADEONInfoPtr info){ unsigned char *RADEONMMIO = info->MMIO; if (!(info->ChipErrata & CHIP_ERRATA_PLL_DUMMYREADS)) return; /* This workaround is necessary on rv200 and RS200 or PLL * reads may return garbage (among others...) */ (void)INREG(RADEON_CLOCK_CNTL_DATA); (void)INREG(RADEON_CRTC_GEN_CNTL);}void RADEONPllErrataAfterData(RADEONInfoPtr info){ unsigned char *RADEONMMIO = info->MMIO; /* This workarounds is necessary on RV100, RS100 and RS200 chips * or the chip could hang on a subsequent access */ if (info->ChipErrata & CHIP_ERRATA_PLL_DELAY) { /* we can't deal with posted writes here ... */ usleep(5000); } /* 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. */ if (info->ChipErrata & CHIP_ERRATA_R300_CG) { 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 register */unsigned RADEONINPLL(ScrnInfoPtr pScrn, int addr){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 data; OUTREG8(RADEON_CLOCK_CNTL_INDEX, addr & 0x3f); RADEONPllErrataAfterIndex(info); data = INREG(RADEON_CLOCK_CNTL_DATA); RADEONPllErrataAfterData(info); return data;}/* Write PLL information */void RADEONOUTPLL(ScrnInfoPtr pScrn, int addr, CARD32 data){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; OUTREG8(RADEON_CLOCK_CNTL_INDEX, (((addr) & 0x3f) | RADEON_PLL_WR_EN)); RADEONPllErrataAfterIndex(info); OUTREG(RADEON_CLOCK_CNTL_DATA, data); RADEONPllErrataAfterData(info);}#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; CARD32 crtc_gen_cntl; int i; crtc_gen_cntl = INREG(RADEON_CRTC_GEN_CNTL); if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -