📄 radeon_driver.c
字号:
OUTREG(RADEON_DISP_OUTPUT_CNTL, ulOrigDISP_OUTPUT_CNTL); OUTREG(RADEON_FP2_GEN_CNTL, ulOrigFP2_GEN_CNTL); OUTREG(RADEON_GPIO_MONID, ulOrigGPIO_MONID); } else { unsigned long ulOrigPIXCLKSDATA; unsigned long ulOrigTV_MASTER_CNTL; unsigned long ulOrigTV_DAC_CNTL; unsigned long ulOrigTV_PRE_DAC_MUX_CNTL; unsigned long ulOrigDAC_CNTL2; unsigned long ulData; unsigned long ulMask; ulOrigPIXCLKSDATA = INPLL(pScrn, RADEON_PIXCLKS_CNTL); ulData = ulOrigPIXCLKSDATA; ulData &= ~(RADEON_PIX2CLK_ALWAYS_ONb | RADEON_PIX2CLK_DAC_ALWAYS_ONb); ulMask = ~(RADEON_PIX2CLK_ALWAYS_ONb | RADEON_PIX2CLK_DAC_ALWAYS_ONb); OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); ulOrigTV_MASTER_CNTL = INREG(RADEON_TV_MASTER_CNTL); ulData = ulOrigTV_MASTER_CNTL; ulData &= ~RADEON_TVCLK_ALWAYS_ONb; OUTREG(RADEON_TV_MASTER_CNTL, ulData); ulOrigDAC_CNTL2 = INREG(RADEON_DAC_CNTL2); ulData = ulOrigDAC_CNTL2; ulData &= ~RADEON_DAC2_DAC2_CLK_SEL; OUTREG(RADEON_DAC_CNTL2, ulData); ulOrigTV_DAC_CNTL = INREG(RADEON_TV_DAC_CNTL); ulData = 0x00880213; OUTREG(RADEON_TV_DAC_CNTL, ulData); ulOrigTV_PRE_DAC_MUX_CNTL = INREG(RADEON_TV_PRE_DAC_MUX_CNTL); ulData = (RADEON_Y_RED_EN | RADEON_C_GRN_EN | RADEON_CMP_BLU_EN | RADEON_RED_MX_FORCE_DAC_DATA | RADEON_GRN_MX_FORCE_DAC_DATA | RADEON_BLU_MX_FORCE_DAC_DATA); if (IS_R300_VARIANT) ulData |= 0x180 << RADEON_TV_FORCE_DAC_DATA_SHIFT; else ulData |= 0x1f5 << RADEON_TV_FORCE_DAC_DATA_SHIFT; OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulData); usleep(10000); ulData = INREG(RADEON_TV_DAC_CNTL); bConnected = (ulData & RADEON_TV_DAC_CMPOUT)?1:0; ulData = ulOrigPIXCLKSDATA; ulMask = 0xFFFFFFFFL; OUTPLLP(pScrn, RADEON_PIXCLKS_CNTL, ulData, ulMask); OUTREG(RADEON_TV_MASTER_CNTL, ulOrigTV_MASTER_CNTL); OUTREG(RADEON_DAC_CNTL2, ulOrigDAC_CNTL2); OUTREG(RADEON_TV_DAC_CNTL, ulOrigTV_DAC_CNTL); OUTREG(RADEON_TV_PRE_DAC_MUX_CNTL, ulOrigTV_PRE_DAC_MUX_CNTL); }#endif } return(bConnected ? MT_CRT : MT_NONE);}static Bool RADEONProbePLLParameters(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); RADEONPLLPtr pll = &info->pll; unsigned char *RADEONMMIO = info->MMIO; unsigned char ppll_div_sel; unsigned mpll_fb_div, spll_fb_div, M; unsigned xclk, tmp, ref_div; int hTotal, vTotal, num, denom, m, n; float hz, prev_xtal, vclk, xtal, mpll, spll; long start_secs, start_usecs, stop_secs, stop_usecs, total_usecs; long to1_secs, to1_usecs, to2_secs, to2_usecs; unsigned int f1, f2, f3; int tries = 0; prev_xtal = 0; again: xtal = 0; if (++tries > 10) goto failed; xf86getsecs(&to1_secs, &to1_usecs); f1 = INREG(RADEON_CRTC_CRNT_FRAME); for (;;) { f2 = INREG(RADEON_CRTC_CRNT_FRAME); if (f1 != f2) break; xf86getsecs(&to2_secs, &to2_usecs); if ((to2_secs - to1_secs) > 1) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Clock not counting...\n"); goto failed; } } xf86getsecs(&start_secs, &start_usecs); for(;;) { f3 = INREG(RADEON_CRTC_CRNT_FRAME); if (f3 != f2) break; xf86getsecs(&to2_secs, &to2_usecs); if ((to2_secs - start_secs) > 1) goto failed; } xf86getsecs(&stop_secs, &stop_usecs); if ((stop_secs - start_secs) != 0) goto again; total_usecs = abs(stop_usecs - start_usecs); if (total_usecs == 0) goto again; hz = 1000000.0/(float)total_usecs; hTotal = ((INREG(RADEON_CRTC_H_TOTAL_DISP) & 0x3ff) + 1) * 8; vTotal = ((INREG(RADEON_CRTC_V_TOTAL_DISP) & 0xfff) + 1); vclk = (float)(hTotal * (float)(vTotal * hz)); switch((INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x30000) >> 16) { case 0: default: num = 1; denom = 1; break; case 1: n = ((INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) >> 16) & 0xff); m = (INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) & 0xff); num = 2*n; denom = 2*m; break; case 2: n = ((INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) >> 8) & 0xff); m = (INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV) & 0xff); num = 2*n; denom = 2*m; break; } ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; RADEONPllErrataAfterIndex(info); n = (INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel) & 0x7ff); m = (INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x3ff); num *= n; denom *= m; switch ((INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7) { case 1: denom *= 2; break; case 2: denom *= 4; break; case 3: denom *= 8; break; case 4: denom *= 3; break; case 6: denom *= 6; break; case 7: denom *= 12; break; } xtal = (int)(vclk *(float)denom/(float)num); if ((xtal > 26900000) && (xtal < 27100000)) xtal = 2700; else if ((xtal > 14200000) && (xtal < 14400000)) xtal = 1432; else if ((xtal > 29400000) && (xtal < 29600000)) xtal = 2950; else goto again; failed: if (xtal == 0) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to probe xtal value ! " "Using default 27Mhz\n"); xtal = 2700; } else { if (prev_xtal == 0) { prev_xtal = xtal; tries = 0; goto again; } else if (prev_xtal != xtal) { prev_xtal = 0; goto again; } } tmp = INPLL(pScrn, RADEON_X_MPLL_REF_FB_DIV); ref_div = INPLL(pScrn, RADEON_PPLL_REF_DIV) & 0x3ff; /* Some sanity check based on the BIOS code .... */ if (ref_div < 2) { CARD32 tmp; tmp = INPLL(pScrn, RADEON_PPLL_REF_DIV); if (IS_R300_VARIANT || (info->ChipFamily == CHIP_FAMILY_RS300)) ref_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; else ref_div = tmp & RADEON_PPLL_REF_DIV_MASK; if (ref_div < 2) ref_div = 12; } /* Calculate "base" xclk straight from MPLL, though that isn't * really useful (hopefully). This isn't called XCLK anymore on * radeon's... */ mpll_fb_div = (tmp & 0xff00) >> 8; spll_fb_div = (tmp & 0xff0000) >> 16; M = (tmp & 0xff); xclk = RADEONDiv((2 * mpll_fb_div * xtal), (M)); /* * Calculate MCLK based on MCLK-A */ mpll = (2.0 * (float)mpll_fb_div * (xtal / 100.0)) / (float)M; spll = (2.0 * (float)spll_fb_div * (xtal / 100.0)) / (float)M; tmp = INPLL(pScrn, RADEON_MCLK_CNTL) & 0x7; switch(tmp) { case 1: info->mclk = mpll; break; case 2: info->mclk = mpll / 2.0; break; case 3: info->mclk = mpll / 4.0; break; case 4: info->mclk = mpll / 8.0; break; case 7: info->mclk = spll; break; default: info->mclk = 200.00; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unsupported MCLKA source" " setting %d, can't probe MCLK value !\n", tmp); } /* * Calculate SCLK */ tmp = INPLL(pScrn, RADEON_SCLK_CNTL) & 0x7; switch(tmp) { case 1: info->sclk = spll; break; case 2: info->sclk = spll / 2.0; break; case 3: info->sclk = spll / 4.0; break; case 4: info->sclk = spll / 8.0; break; case 7: info->sclk = mpll; default: info->sclk = 200.00; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unsupported SCLK source" " setting %d, can't probe SCLK value !\n", tmp); } /* we're done, hopefully these are sane values */ pll->reference_div = ref_div; pll->xclk = xclk; pll->reference_freq = xtal; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probed PLL values: xtal: %f Mhz, " "sclk: %f Mhz, mclk: %f Mhz\n", xtal/100.0, info->sclk, info->mclk); return TRUE;}static void RADEONGetPanelInfoFromReg (ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; CARD32 fp_vert_stretch = INREG(RADEON_FP_VERT_STRETCH); CARD32 fp_horz_stretch = INREG(RADEON_FP_HORZ_STRETCH); info->PanelPwrDly = 200; if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) { info->PanelYRes = (fp_vert_stretch>>12) + 1; } else { info->PanelYRes = (INREG(RADEON_CRTC_V_TOTAL_DISP)>>16) + 1; } if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) { info->PanelXRes = ((fp_horz_stretch>>16) + 1) * 8; } else { info->PanelXRes = ((INREG(RADEON_CRTC_H_TOTAL_DISP)>>16) + 1) * 8; } if ((info->PanelXRes < 640) || (info->PanelYRes < 480)) { info->PanelXRes = 640; info->PanelYRes = 480; } if (xf86ReturnOptValBool(info->Options, OPTION_LVDS_PROBE_PLL, TRUE)) { CARD32 ppll_div_sel, ppll_val; ppll_div_sel = INREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; RADEONPllErrataAfterIndex(info); ppll_val = INPLL(pScrn, RADEON_PPLL_DIV_0 + ppll_div_sel); if ((ppll_val & 0x000707ff) == 0x1bb) goto noprobe; info->FeedbackDivider = ppll_val & 0x7ff; info->PostDivider = (ppll_val >> 16) & 0x7; info->RefDivider = info->pll.reference_div; info->UseBiosDividers = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Existing panel PLL dividers will be used.\n"); } noprobe: xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Panel size %dx%d is derived, this may not be correct.\n" "If not, use PanelSize option to overwrite this setting\n", info->PanelXRes, info->PanelYRes);}static Bool RADEONGetLVDSInfo (ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); if (!RADEONGetLVDSInfoFromBIOS(pScrn)) RADEONGetPanelInfoFromReg(pScrn); /* The panel size we collected from BIOS may not be the * maximum size supported by the panel. If not, we update * it now. These will be used if no matching mode can be * found from EDID data. */ RADEONUpdatePanelSize(pScrn); /* No timing information for the native mode, * use whatever specified in the Modeline. * If no Modeline specified, we'll just pick * the VESA mode at 60Hz refresh rate which * is likely to be the best for a flat panel. */ if (info->DotClock == 0) { RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); DisplayModePtr tmp_mode = NULL; xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No valid timing info from BIOS.\n"); tmp_mode = pScrn->monitor->Modes; while(tmp_mode) { if ((tmp_mode->HDisplay == info->PanelXRes) && (tmp_mode->VDisplay == info->PanelYRes)) { float refresh = (float)tmp_mode->Clock * 1000.0 / tmp_mode->HTotal / tmp_mode->VTotal; if ((abs(60.0 - refresh) < 1.0) || (tmp_mode->type == 0)) { info->HBlank = tmp_mode->HTotal - tmp_mode->HDisplay; info->HOverPlus = tmp_mode->HSyncStart - tmp_mode->HDisplay; info->HSyncWidth = tmp_mode->HSyncEnd - tmp_mode->HSyncStart; info->VBlank = tmp_mode->VTotal - tmp_mode->VDisplay; info->VOverPlus = tmp_mode->VSyncStart - tmp_mode->VDisplay; info->VSyncWidth = tmp_mode->VSyncEnd - tmp_mode->VSyncStart; info->DotClock = tmp_mode->Clock; info->Flags = 0; break; } } tmp_mode = tmp_mode->next; } if ((info->DotClock == 0) && !pRADEONEnt->PortInfo[0].MonInfo) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Panel size is not correctly detected.\n" "Please try to use PanelSize option for correct settings.\n"); return FALSE; } } return TRUE;}static void RADEONGetTMDSInfo(ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); int i; for (i=0; i<4; i++) { info->tmds_pll[i].value = 0; info->tmds_pll[i].freq = 0; } if (RADEONGetTMDSInfoFromBIOS(pScrn)) return; for (i=0; i<4; i++) { info->tmds_pll[i].value = default_tmds_pll[info->ChipFamily][i].value; info->tmds_pll[i].freq = default_tmds_pll[info->ChipFamily][i].freq; }}static void RADEONGetPanelInfo (ScrnInfoPtr pScrn){ RADEONInfoPtr info = RADEONPTR(pScrn); char* s; if((s = xf86GetOptValString(info->Options, OPTION_PANEL_SIZE))) { info->PanelPwrDly = 200; if (sscanf (s, "%dx%d", &info->PanelXRes, &info->PanelYRes) != 2) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid PanelSize option: %s\n", s); RADEONGetPanelInfoFromReg(pScrn); } } else { if(info->DisplayType == MT_LCD) { RADEONGetLVDSInfo(pScrn); } else if ((info->DisplayType == MT_DFP) || (info->MergeType == MT_DFP)) { RADEONGetTMDSInfo(pScrn); if (!pScrn->monitor->DDC)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -