xf86-video-ati: Branch 'master'

Alex Deucher agd5f at kemper.freedesktop.org
Tue May 19 14:24:30 PDT 2009


 src/radeon_pm.c  |  147 +++++++++++++++++++++++++++++++++++++++----------------
 src/radeon_reg.h |   16 ++++-
 2 files changed, 119 insertions(+), 44 deletions(-)

New commits:
commit 88a9e98341d96e5e7f48b69aed597d1bada6313a
Author: Alex Deucher <alexdeucher at gmail.com>
Date:   Tue May 19 17:11:34 2009 -0400

    Pre-atom: Improve engine clock setup code
    
    Also remove SetMemoryClk() for pre-atom cards for now
    as it requires quite a bit more asic specific work.
    To set the mclk we'll need to use the mem reset/dll tables
    in the bios.

diff --git a/src/radeon_pm.c b/src/radeon_pm.c
index 5267fbc..131a9fd 100644
--- a/src/radeon_pm.c
+++ b/src/radeon_pm.c
@@ -38,66 +38,131 @@
 #include "radeon_macros.h"
 #include "radeon_atombios.h"
 
-static int calc_div(uint32_t num, uint32_t den)
+/* 10 khz */
+static uint32_t calc_eng_mem_clock(ScrnInfoPtr pScrn,
+				   uint32_t req_clock,
+				   int ref_div,
+				   int *fb_div,
+				   int *post_div)
 {
-    int div = (num + (den / 2)) / den;
+    RADEONInfoPtr info = RADEONPTR(pScrn);
+    RADEONPLLPtr pll = &info->pll;
 
-    if ((div < 2) || (div > 0xff))
-	return 0;
-    else
-	return div;
+    if (req_clock < 15000) {
+	*post_div = 8;
+	req_clock *= 8;
+    } else if (req_clock < 30000) {
+	*post_div = 4;
+	req_clock *= 4;
+    } else if (req_clock < 60000) {
+	*post_div = 2;
+	req_clock *= 2;
+    } else
+	*post_div = 1;
+
+    req_clock *= ref_div;
+    req_clock += pll->reference_freq;
+    req_clock /= (2 * pll->reference_freq);
+
+    *fb_div = req_clock & 0xff;
+
+    req_clock = (req_clock & 0xffff) << 1;
+    req_clock *= pll->reference_freq;
+    req_clock /= ref_div;
+    req_clock /= *post_div;
+
+    return req_clock;
 
 }
 
-/* 10 khz */
 static void
 RADEONSetEngineClock(ScrnInfoPtr pScrn, uint32_t eng_clock)
 {
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    RADEONPLLPtr pll = &info->pll;
-    uint32_t ref_div, fb_div;
-    uint32_t m_spll_ref_fb_div;
+    uint32_t tmp;
+    int ref_div, fb_div, post_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);
+    tmp = INPLL(pScrn, RADEON_M_SPLL_REF_FB_DIV);
+    ref_div = tmp & RADEON_M_SPLL_REF_DIV_MASK;
 
-    if (!fb_div)
-	return;
+    eng_clock = calc_eng_mem_clock(pScrn, eng_clock, ref_div, &fb_div, &post_div);
 
-    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 */
-}
+    tmp = INPLL(pScrn, RADEON_CLK_PIN_CNTL);
+    tmp &= ~RADEON_DONT_USE_XTALIN;
+    OUTPLL(pScrn, RADEON_CLK_PIN_CNTL, tmp);
 
-/* 10 khz */
-static void
-RADEONSetMemoryClock(ScrnInfoPtr pScrn, uint32_t mem_clock)
-{
-    RADEONInfoPtr  info       = RADEONPTR(pScrn);
-    RADEONPLLPtr pll = &info->pll;
-    uint32_t ref_div, fb_div;
-    uint32_t m_spll_ref_fb_div;
+    tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
+    tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
+    OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
 
-    if (info->IsIGP)
-	return;
+    usleep(10);
 
-    RADEONWaitForIdleMMIO(pScrn);
+    tmp = INPLL(pScrn, RADEON_SPLL_CNTL);
+    tmp |= RADEON_SPLL_SLEEP;
+    OUTPLL(pScrn, RADEON_SPLL_CNTL, tmp);
 
-    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);
+    usleep(2);
 
-    if (!fb_div)
-	return;
+    tmp = INPLL(pScrn, RADEON_SPLL_CNTL);
+    tmp |= RADEON_SPLL_RESET;
+    OUTPLL(pScrn, RADEON_SPLL_CNTL, tmp);
+
+    usleep(200);
+
+    tmp = INPLL(pScrn, RADEON_M_SPLL_REF_FB_DIV);
+    tmp &= ~(RADEON_SPLL_FB_DIV_MASK << RADEON_SPLL_FB_DIV_SHIFT);
+    tmp |= (fb_div & RADEON_SPLL_FB_DIV_MASK) << RADEON_SPLL_FB_DIV_SHIFT;
+    OUTPLL(pScrn, RADEON_M_SPLL_REF_FB_DIV, tmp);
+
+    /* XXX: verify on different asics */
+    tmp = INPLL(pScrn, RADEON_SPLL_CNTL);
+    tmp &= ~RADEON_SPLL_PVG_MASK;
+    if ((eng_clock * post_div) >= 90000)
+	tmp |= (0x7 << RADEON_SPLL_PVG_SHIFT);
+    else
+	tmp |= (0x4 << RADEON_SPLL_PVG_SHIFT);
+    OUTPLL(pScrn, RADEON_SPLL_CNTL, tmp);
+
+    tmp = INPLL(pScrn, RADEON_SPLL_CNTL);
+    tmp &= ~RADEON_SPLL_SLEEP;
+    OUTPLL(pScrn, RADEON_SPLL_CNTL, tmp);
+
+    usleep(2);
+
+    tmp = INPLL(pScrn, RADEON_SPLL_CNTL);
+    tmp &= ~RADEON_SPLL_RESET;
+    OUTPLL(pScrn, RADEON_SPLL_CNTL, tmp);
+
+    usleep(200);
+
+    tmp = INPLL(pScrn, RADEON_SCLK_CNTL);
+    tmp &= ~RADEON_SCLK_SRC_SEL_MASK;
+    switch (post_div) {
+    case 1:
+    default:
+	tmp |= 1;
+	break;
+    case 2:
+	tmp |= 2;
+	break;
+    case 4:
+	tmp |= 3;
+	break;
+    case 8:
+	tmp |= 4;
+	break;
+    }
+    OUTPLL(pScrn, RADEON_SCLK_CNTL, tmp);
+
+    usleep(20);
+
+    tmp = INPLL(pScrn, RADEON_CLK_PIN_CNTL);
+    tmp |= RADEON_DONT_USE_XTALIN;
+    OUTPLL(pScrn, RADEON_CLK_PIN_CNTL, tmp);
+
+    usleep(10);
 
-    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)
diff --git a/src/radeon_reg.h b/src/radeon_reg.h
index 9261b39..8da513b 100644
--- a/src/radeon_reg.h
+++ b/src/radeon_reg.h
@@ -305,20 +305,30 @@
 #define RADEON_CAPABILITIES_ID              0x0f50 /* PCI */
 #define RADEON_CAPABILITIES_PTR             0x0f34 /* PCI */
 #define RADEON_CLK_PIN_CNTL                 0x0001 /* PLL */
+#       define RADEON_DONT_USE_XTALIN       (1 << 4)
 #       define RADEON_SCLK_DYN_START_CNTL   (1 << 15)
 #define RADEON_CLOCK_CNTL_DATA              0x000c
 #define RADEON_CLOCK_CNTL_INDEX             0x0008
 #       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_FB_DIV            0x000a /* PLL */
 #       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_SPLL_CNTL                    0x000c /* PLL */
+#       define RADEON_SPLL_SLEEP            (1 << 0)
+#       define RADEON_SPLL_RESET            (1 << 1)
+#       define RADEON_SPLL_PCP_MASK         0x7
+#       define RADEON_SPLL_PCP_SHIFT        8
+#       define RADEON_SPLL_PVG_MASK         0x7
+#       define RADEON_SPLL_PVG_SHIFT        11
+#       define RADEON_SPLL_PDC_MASK         0x3
+#       define RADEON_SPLL_PDC_SHIFT        14
+#define RADEON_CLK_PWRMGT_CNTL              0x0014 /* PLL */
 #       define RADEON_ENGIN_DYNCLK_MODE     (1 << 12)
 #       define RADEON_ACTIVE_HILO_LAT_MASK  (3 << 13)
 #       define RADEON_ACTIVE_HILO_LAT_SHIFT 13
@@ -330,7 +340,7 @@
 #       define RADEON_DYN_STOP_MODE_MASK    (7 << 21)
 #       define RADEON_TVPLL_PWRMGT_OFF      (1 << 30)
 #       define RADEON_TVCLK_TURNOFF         (1 << 31)
-#define RADEON_PLL_PWRMGT_CNTL              0x0015
+#define RADEON_PLL_PWRMGT_CNTL              0x0015 /* PLL */
 #       define RADEON_TCL_BYPASS_DISABLE    (1 << 20)
 #define RADEON_CLR_CMP_CLR_3D               0x1a24
 #define RADEON_CLR_CMP_CLR_DST              0x15c8


More information about the xorg-commit mailing list