summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-03-31 17:13:11 -0400
committerAlex Deucher <alexdeucher@gmail.com>2009-04-15 11:45:52 -0400
commitadb099409768e695b9928fa6aa5760f93dadd9af (patch)
tree4e62fb6e1c4a9d65cb37681400c7a2e64003a0ab
parent68e2a959ccc3d1a5d0731f1b55fdf1b2412635b2 (diff)
radeon: Add functions to set sclk/mclk on r1xx-r4xx
-rw-r--r--src/radeon_pm.c62
-rw-r--r--src/radeon_reg.h7
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)