diff options
Diffstat (limited to 'drivers/gpu/drm/i915/soc/intel_dram.c')
-rw-r--r-- | drivers/gpu/drm/i915/soc/intel_dram.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c index bba8cb6e8ae4..9f0651d48d41 100644 --- a/drivers/gpu/drm/i915/soc/intel_dram.c +++ b/drivers/gpu/drm/i915/soc/intel_dram.c @@ -10,6 +10,7 @@ #include "intel_dram.h" #include "intel_mchbar_regs.h" #include "intel_pcode.h" +#include "vlv_sideband.h" struct dram_dimm_info { u16 size; @@ -42,6 +43,155 @@ static const char *intel_dram_type_str(enum intel_dram_type type) #undef DRAM_TYPE_STR +static void pnv_detect_mem_freq(struct drm_i915_private *dev_priv) +{ + u32 tmp; + + tmp = intel_uncore_read(&dev_priv->uncore, CLKCFG); + + switch (tmp & CLKCFG_FSB_MASK) { + case CLKCFG_FSB_533: + dev_priv->fsb_freq = 533; /* 133*4 */ + break; + case CLKCFG_FSB_800: + dev_priv->fsb_freq = 800; /* 200*4 */ + break; + case CLKCFG_FSB_667: + dev_priv->fsb_freq = 667; /* 167*4 */ + break; + case CLKCFG_FSB_400: + dev_priv->fsb_freq = 400; /* 100*4 */ + break; + } + + switch (tmp & CLKCFG_MEM_MASK) { + case CLKCFG_MEM_533: + dev_priv->mem_freq = 533; + break; + case CLKCFG_MEM_667: + dev_priv->mem_freq = 667; + break; + case CLKCFG_MEM_800: + dev_priv->mem_freq = 800; + break; + } + + /* detect pineview DDR3 setting */ + tmp = intel_uncore_read(&dev_priv->uncore, CSHRDDR3CTL); + dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0; +} + +static void ilk_detect_mem_freq(struct drm_i915_private *dev_priv) +{ + u16 ddrpll, csipll; + + ddrpll = intel_uncore_read16(&dev_priv->uncore, DDRMPLL1); + switch (ddrpll & 0xff) { + case 0xc: + dev_priv->mem_freq = 800; + break; + case 0x10: + dev_priv->mem_freq = 1066; + break; + case 0x14: + dev_priv->mem_freq = 1333; + break; + case 0x18: + dev_priv->mem_freq = 1600; + break; + default: + drm_dbg(&dev_priv->drm, "unknown memory frequency 0x%02x\n", + ddrpll & 0xff); + dev_priv->mem_freq = 0; + break; + } + + csipll = intel_uncore_read16(&dev_priv->uncore, CSIPLL0); + switch (csipll & 0x3ff) { + case 0x00c: + dev_priv->fsb_freq = 3200; + break; + case 0x00e: + dev_priv->fsb_freq = 3733; + break; + case 0x010: + dev_priv->fsb_freq = 4266; + break; + case 0x012: + dev_priv->fsb_freq = 4800; + break; + case 0x014: + dev_priv->fsb_freq = 5333; + break; + case 0x016: + dev_priv->fsb_freq = 5866; + break; + case 0x018: + dev_priv->fsb_freq = 6400; + break; + default: + drm_dbg(&dev_priv->drm, "unknown fsb frequency 0x%04x\n", + csipll & 0x3ff); + dev_priv->fsb_freq = 0; + break; + } +} + +static void chv_detect_mem_freq(struct drm_i915_private *i915) +{ + u32 val; + + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_CCK)); + val = vlv_cck_read(i915, CCK_FUSE_REG); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_CCK)); + + switch ((val >> 2) & 0x7) { + case 3: + i915->mem_freq = 2000; + break; + default: + i915->mem_freq = 1600; + break; + } +} + +static void vlv_detect_mem_freq(struct drm_i915_private *i915) +{ + u32 val; + + vlv_iosf_sb_get(i915, BIT(VLV_IOSF_SB_PUNIT)); + val = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); + vlv_iosf_sb_put(i915, BIT(VLV_IOSF_SB_PUNIT)); + + switch ((val >> 6) & 3) { + case 0: + case 1: + i915->mem_freq = 800; + break; + case 2: + i915->mem_freq = 1066; + break; + case 3: + i915->mem_freq = 1333; + break; + } +} + +static void detect_mem_freq(struct drm_i915_private *i915) +{ + if (IS_PINEVIEW(i915)) + pnv_detect_mem_freq(i915); + else if (GRAPHICS_VER(i915) == 5) + ilk_detect_mem_freq(i915); + else if (IS_CHERRYVIEW(i915)) + chv_detect_mem_freq(i915); + else if (IS_VALLEYVIEW(i915)) + vlv_detect_mem_freq(i915); + + if (i915->mem_freq) + drm_dbg(&i915->drm, "DDR speed: %d MHz\n", i915->mem_freq); +} + static int intel_dimm_num_devices(const struct dram_dimm_info *dimm) { return dimm->ranks * 64 / (dimm->width ?: 1); @@ -507,6 +657,8 @@ void intel_dram_detect(struct drm_i915_private *i915) struct dram_info *dram_info = &i915->dram_info; int ret; + detect_mem_freq(i915); + if (GRAPHICS_VER(i915) < 9 || IS_DG2(i915) || !HAS_DISPLAY(i915)) return; |