diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2009-03-31 17:13:11 -0400 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2009-04-15 11:45:52 -0400 |
commit | adb099409768e695b9928fa6aa5760f93dadd9af (patch) | |
tree | 4e62fb6e1c4a9d65cb37681400c7a2e64003a0ab /src | |
parent | 68e2a959ccc3d1a5d0731f1b55fdf1b2412635b2 (diff) |
radeon: Add functions to set sclk/mclk on r1xx-r4xx
Diffstat (limited to 'src')
-rw-r--r-- | src/radeon_pm.c | 62 | ||||
-rw-r--r-- | src/radeon_reg.h | 7 |
2 files changed, 69 insertions, 0 deletions
diff --git a/src/radeon_pm.c b/src/radeon_pm.c index 4f3f4c7a..89e1d8ab 100644 --- a/src/radeon_pm.c +++ b/src/radeon_pm.c @@ -38,6 +38,68 @@ #include "radeon_macros.h" #include "radeon_atombios.h" +static int calc_div(int num, int den) +{ + int div = (num + (den / 2)) / den; + + if ((div < 2) || (div > 0xff)) + return 0; + else + return div; + +} + +/* 10 khz */ +static void +RADEONSetEngineClock(ScrnInfoPtr pScrn, int eng_clock) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONPLLPtr pll = &info->pll; + uint32_t ref_div, fb_div; + uint32_t m_spll_ref_fb_div; + + RADEONWaitForIdleMMIO(pScrn); + + m_spll_ref_fb_div = INPLL(pScrn, RADEON_M_SPLL_REF_FB_DIV); + ref_div = m_spll_ref_fb_div & RADEON_M_SPLL_REF_DIV_MASK; + fb_div = calc_div(eng_clock * ref_div, pll->reference_freq); + + if (!fb_div) + return; + + m_spll_ref_fb_div &= ~(RADEON_SPLL_FB_DIV_MASK << RADEON_SPLL_FB_DIV_SHIFT); + m_spll_ref_fb_div |= (fb_div & RADEON_SPLL_FB_DIV_MASK) << RADEON_SPLL_FB_DIV_SHIFT; + OUTPLL(pScrn, RADEON_M_SPLL_REF_FB_DIV, m_spll_ref_fb_div); + usleep(16000); /* Let the pll settle */ +} + +/* 10 khz */ +static void +RADEONSetMemoryClock(ScrnInfoPtr pScrn, int mem_clock) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONPLLPtr pll = &info->pll; + uint32_t ref_div, fb_div; + uint32_t m_spll_ref_fb_div; + + if (info->IsIGP) + return; + + RADEONWaitForIdleMMIO(pScrn); + + m_spll_ref_fb_div = INPLL(pScrn, RADEON_M_SPLL_REF_FB_DIV); + ref_div = m_spll_ref_fb_div & RADEON_M_SPLL_REF_DIV_MASK; + fb_div = calc_div(mem_clock * ref_div, pll->reference_freq); + + if (!fb_div) + return; + + m_spll_ref_fb_div &= ~(RADEON_MPLL_FB_DIV_MASK << RADEON_MPLL_FB_DIV_SHIFT); + m_spll_ref_fb_div |= (fb_div & RADEON_MPLL_FB_DIV_MASK) << RADEON_MPLL_FB_DIV_SHIFT; + OUTPLL(pScrn, RADEON_M_SPLL_REF_FB_DIV, m_spll_ref_fb_div); + usleep(16000); /* Let the pll settle */ +} + static void LegacySetClockGating(ScrnInfoPtr pScrn, Bool enable) { RADEONInfoPtr info = RADEONPTR(pScrn); diff --git a/src/radeon_reg.h b/src/radeon_reg.h index d74a30a4..e8af027f 100644 --- a/src/radeon_reg.h +++ b/src/radeon_reg.h @@ -288,6 +288,13 @@ # define RADEON_PLL_WR_EN (1 << 7) # define RADEON_PLL_DIV_SEL (3 << 8) # define RADEON_PLL2_DIV_SEL_MASK ~(3 << 8) +#define RADEON_M_SPLL_REF_FB_DIV 0x000a +# define RADEON_M_SPLL_REF_DIV_MASK 0xff +# define RADEON_M_SPLL_REF_DIV_SHIFT 0 +# define RADEON_MPLL_FB_DIV_MASK 0xff +# define RADEON_MPLL_FB_DIV_SHIFT 8 +# define RADEON_SPLL_FB_DIV_MASK 0xff +# define RADEON_SPLL_FB_DIV_SHIFT 16 #define RADEON_CLK_PWRMGT_CNTL 0x0014 # define RADEON_ENGIN_DYNCLK_MODE (1 << 12) # define RADEON_ACTIVE_HILO_LAT_MASK (3 << 13) |