diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2013-04-17 18:54:58 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-04-18 04:15:43 -0400 |
commit | 0a073b843bcd9a660f76e497182aac97cafddc4c (patch) | |
tree | a4665fb1ced6aa9f09150438e260544543d6335a /drivers | |
parent | 855ba3be12badf6228151ca3ccf54632cfdd463d (diff) |
drm/i915: turbo & RC6 support for VLV v7
Uses slightly different interfaces than other platforms.
v2: track actual set freq, not requested (Rohit)
fix debug prints in init code (Jesse)
v3: don't write sleep reg (Jesse)
re-add RC6 wake limit write (Ben)
fixup thresholds to match other platforms (Ben)
clean up mem freq calculation (Ben)
clean up debug prints (Ben)
v4: move defines from punit patch (Ville)
v5: remove writes to nonexistent regs (Jesse)
put RP and RC regs together (Jesse)
fix RC6 enable (Jesse)
v6: use correct fuse reads from NC (Jesse)
split out min/max funcs for use in sysfs (Jesse)
add debugfs & sysfs freq controls (Jesse)
v7: update with Ben's hw_max changes (Jesse)
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Ben Widawsky <ben@bwidawsk.net> (v6)
[danvet: Follow checkpatch sugggestion to use min_t to avoid casting
fun.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 58 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 21 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_sysfs.c | 71 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 199 |
6 files changed, 320 insertions, 39 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e913d325d5b8..367b534d2260 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -941,7 +941,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) | |||
941 | MEMSTAT_VID_SHIFT); | 941 | MEMSTAT_VID_SHIFT); |
942 | seq_printf(m, "Current P-state: %d\n", | 942 | seq_printf(m, "Current P-state: %d\n", |
943 | (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); | 943 | (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); |
944 | } else if (IS_GEN6(dev) || IS_GEN7(dev)) { | 944 | } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { |
945 | u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); | 945 | u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); |
946 | u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); | 946 | u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); |
947 | u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | 947 | u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); |
@@ -1009,6 +1009,25 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused) | |||
1009 | 1009 | ||
1010 | seq_printf(m, "Max overclocked frequency: %dMHz\n", | 1010 | seq_printf(m, "Max overclocked frequency: %dMHz\n", |
1011 | dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER); | 1011 | dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER); |
1012 | } else if (IS_VALLEYVIEW(dev)) { | ||
1013 | u32 freq_sts, val; | ||
1014 | |||
1015 | valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, | ||
1016 | &freq_sts); | ||
1017 | seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); | ||
1018 | seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq); | ||
1019 | |||
1020 | valleyview_punit_read(dev_priv, PUNIT_FUSE_BUS1, &val); | ||
1021 | seq_printf(m, "max GPU freq: %d MHz\n", | ||
1022 | vlv_gpu_freq(dev_priv->mem_freq, val)); | ||
1023 | |||
1024 | valleyview_punit_read(dev_priv, PUNIT_REG_GPU_LFM, &val); | ||
1025 | seq_printf(m, "min GPU freq: %d MHz\n", | ||
1026 | vlv_gpu_freq(dev_priv->mem_freq, val)); | ||
1027 | |||
1028 | seq_printf(m, "current GPU freq: %d MHz\n", | ||
1029 | vlv_gpu_freq(dev_priv->mem_freq, | ||
1030 | (freq_sts >> 8) & 0xff)); | ||
1012 | } else { | 1031 | } else { |
1013 | seq_printf(m, "no P-state info available\n"); | 1032 | seq_printf(m, "no P-state info available\n"); |
1014 | } | 1033 | } |
@@ -1812,7 +1831,11 @@ i915_max_freq_get(void *data, u64 *val) | |||
1812 | if (ret) | 1831 | if (ret) |
1813 | return ret; | 1832 | return ret; |
1814 | 1833 | ||
1815 | *val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; | 1834 | if (IS_VALLEYVIEW(dev)) |
1835 | *val = vlv_gpu_freq(dev_priv->mem_freq, | ||
1836 | dev_priv->rps.max_delay); | ||
1837 | else | ||
1838 | *val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; | ||
1816 | mutex_unlock(&dev_priv->rps.hw_lock); | 1839 | mutex_unlock(&dev_priv->rps.hw_lock); |
1817 | 1840 | ||
1818 | return 0; | 1841 | return 0; |
@@ -1837,9 +1860,16 @@ i915_max_freq_set(void *data, u64 val) | |||
1837 | /* | 1860 | /* |
1838 | * Turbo will still be enabled, but won't go above the set value. | 1861 | * Turbo will still be enabled, but won't go above the set value. |
1839 | */ | 1862 | */ |
1840 | do_div(val, GT_FREQUENCY_MULTIPLIER); | 1863 | if (IS_VALLEYVIEW(dev)) { |
1841 | dev_priv->rps.max_delay = val; | 1864 | val = vlv_freq_opcode(dev_priv->mem_freq, val); |
1842 | gen6_set_rps(dev, val); | 1865 | dev_priv->rps.max_delay = val; |
1866 | gen6_set_rps(dev, val); | ||
1867 | } else { | ||
1868 | do_div(val, GT_FREQUENCY_MULTIPLIER); | ||
1869 | dev_priv->rps.max_delay = val; | ||
1870 | gen6_set_rps(dev, val); | ||
1871 | } | ||
1872 | |||
1843 | mutex_unlock(&dev_priv->rps.hw_lock); | 1873 | mutex_unlock(&dev_priv->rps.hw_lock); |
1844 | 1874 | ||
1845 | return 0; | 1875 | return 0; |
@@ -1863,7 +1893,11 @@ i915_min_freq_get(void *data, u64 *val) | |||
1863 | if (ret) | 1893 | if (ret) |
1864 | return ret; | 1894 | return ret; |
1865 | 1895 | ||
1866 | *val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; | 1896 | if (IS_VALLEYVIEW(dev)) |
1897 | *val = vlv_gpu_freq(dev_priv->mem_freq, | ||
1898 | dev_priv->rps.min_delay); | ||
1899 | else | ||
1900 | *val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; | ||
1867 | mutex_unlock(&dev_priv->rps.hw_lock); | 1901 | mutex_unlock(&dev_priv->rps.hw_lock); |
1868 | 1902 | ||
1869 | return 0; | 1903 | return 0; |
@@ -1888,9 +1922,15 @@ i915_min_freq_set(void *data, u64 val) | |||
1888 | /* | 1922 | /* |
1889 | * Turbo will still be enabled, but won't go below the set value. | 1923 | * Turbo will still be enabled, but won't go below the set value. |
1890 | */ | 1924 | */ |
1891 | do_div(val, GT_FREQUENCY_MULTIPLIER); | 1925 | if (IS_VALLEYVIEW(dev)) { |
1892 | dev_priv->rps.min_delay = val; | 1926 | val = vlv_freq_opcode(dev_priv->mem_freq, val); |
1893 | gen6_set_rps(dev, val); | 1927 | dev_priv->rps.min_delay = val; |
1928 | valleyview_set_rps(dev, val); | ||
1929 | } else { | ||
1930 | do_div(val, GT_FREQUENCY_MULTIPLIER); | ||
1931 | dev_priv->rps.min_delay = val; | ||
1932 | gen6_set_rps(dev, val); | ||
1933 | } | ||
1894 | mutex_unlock(&dev_priv->rps.hw_lock); | 1934 | mutex_unlock(&dev_priv->rps.hw_lock); |
1895 | 1935 | ||
1896 | return 0; | 1936 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index abb065502deb..bd2d7f17393e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -1856,6 +1856,9 @@ extern void intel_disable_fbc(struct drm_device *dev); | |||
1856 | extern bool ironlake_set_drps(struct drm_device *dev, u8 val); | 1856 | extern bool ironlake_set_drps(struct drm_device *dev, u8 val); |
1857 | extern void intel_init_pch_refclk(struct drm_device *dev); | 1857 | extern void intel_init_pch_refclk(struct drm_device *dev); |
1858 | extern void gen6_set_rps(struct drm_device *dev, u8 val); | 1858 | extern void gen6_set_rps(struct drm_device *dev, u8 val); |
1859 | extern void valleyview_set_rps(struct drm_device *dev, u8 val); | ||
1860 | extern int valleyview_rps_max_freq(struct drm_i915_private *dev_priv); | ||
1861 | extern int valleyview_rps_min_freq(struct drm_i915_private *dev_priv); | ||
1859 | extern void intel_detect_pch(struct drm_device *dev); | 1862 | extern void intel_detect_pch(struct drm_device *dev); |
1860 | extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); | 1863 | extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); |
1861 | extern int intel_enable_rc6(const struct drm_device *dev); | 1864 | extern int intel_enable_rc6(const struct drm_device *dev); |
@@ -1887,6 +1890,8 @@ int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val) | |||
1887 | int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val); | 1890 | int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val); |
1888 | int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val); | 1891 | int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val); |
1889 | int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val); | 1892 | int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val); |
1893 | int valleyview_nc_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val); | ||
1894 | |||
1890 | int vlv_gpu_freq(int ddr_freq, int val); | 1895 | int vlv_gpu_freq(int ddr_freq, int val); |
1891 | int vlv_freq_opcode(int ddr_freq, int val); | 1896 | int vlv_freq_opcode(int ddr_freq, int val); |
1892 | 1897 | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 3af983fad67c..932e7f8b6d5c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -482,7 +482,10 @@ static void gen6_pm_rps_work(struct work_struct *work) | |||
482 | */ | 482 | */ |
483 | if (!(new_delay > dev_priv->rps.max_delay || | 483 | if (!(new_delay > dev_priv->rps.max_delay || |
484 | new_delay < dev_priv->rps.min_delay)) { | 484 | new_delay < dev_priv->rps.min_delay)) { |
485 | gen6_set_rps(dev_priv->dev, new_delay); | 485 | if (IS_VALLEYVIEW(dev_priv->dev)) |
486 | valleyview_set_rps(dev_priv->dev, new_delay); | ||
487 | else | ||
488 | gen6_set_rps(dev_priv->dev, new_delay); | ||
486 | } | 489 | } |
487 | 490 | ||
488 | mutex_unlock(&dev_priv->rps.hw_lock); | 491 | mutex_unlock(&dev_priv->rps.hw_lock); |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 31de7e4b1f3e..66fb8dd28225 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -4315,6 +4315,7 @@ | |||
4315 | #define GEN6_RC_CTL_RC6_ENABLE (1<<18) | 4315 | #define GEN6_RC_CTL_RC6_ENABLE (1<<18) |
4316 | #define GEN6_RC_CTL_RC1e_ENABLE (1<<20) | 4316 | #define GEN6_RC_CTL_RC1e_ENABLE (1<<20) |
4317 | #define GEN6_RC_CTL_RC7_ENABLE (1<<22) | 4317 | #define GEN6_RC_CTL_RC7_ENABLE (1<<22) |
4318 | #define GEN7_RC_CTL_TO_MODE (1<<28) | ||
4318 | #define GEN6_RC_CTL_EI_MODE(x) ((x)<<27) | 4319 | #define GEN6_RC_CTL_EI_MODE(x) ((x)<<27) |
4319 | #define GEN6_RC_CTL_HW_ENABLE (1<<31) | 4320 | #define GEN6_RC_CTL_HW_ENABLE (1<<31) |
4320 | #define GEN6_RP_DOWN_TIMEOUT 0xA010 | 4321 | #define GEN6_RP_DOWN_TIMEOUT 0xA010 |
@@ -4406,12 +4407,32 @@ | |||
4406 | #define IOSF_BAR_SHIFT 1 | 4407 | #define IOSF_BAR_SHIFT 1 |
4407 | #define IOSF_SB_BUSY (1<<0) | 4408 | #define IOSF_SB_BUSY (1<<0) |
4408 | #define IOSF_PORT_PUNIT 0x4 | 4409 | #define IOSF_PORT_PUNIT 0x4 |
4410 | #define IOSF_PORT_NC 0x11 | ||
4409 | #define VLV_IOSF_DATA 0x182104 | 4411 | #define VLV_IOSF_DATA 0x182104 |
4410 | #define VLV_IOSF_ADDR 0x182108 | 4412 | #define VLV_IOSF_ADDR 0x182108 |
4411 | 4413 | ||
4412 | #define PUNIT_OPCODE_REG_READ 6 | 4414 | #define PUNIT_OPCODE_REG_READ 6 |
4413 | #define PUNIT_OPCODE_REG_WRITE 7 | 4415 | #define PUNIT_OPCODE_REG_WRITE 7 |
4414 | 4416 | ||
4417 | #define PUNIT_REG_GPU_LFM 0xd3 | ||
4418 | #define PUNIT_REG_GPU_FREQ_REQ 0xd4 | ||
4419 | #define PUNIT_REG_GPU_FREQ_STS 0xd8 | ||
4420 | #define PUNIT_REG_MEDIA_TURBO_FREQ_REQ 0xdc | ||
4421 | |||
4422 | #define PUNIT_FUSE_BUS2 0xf6 /* bits 47:40 */ | ||
4423 | #define PUNIT_FUSE_BUS1 0xf5 /* bits 55:48 */ | ||
4424 | |||
4425 | #define IOSF_NC_FB_GFX_FREQ_FUSE 0x1c | ||
4426 | #define FB_GFX_MAX_FREQ_FUSE_SHIFT 3 | ||
4427 | #define FB_GFX_MAX_FREQ_FUSE_MASK 0x000007f8 | ||
4428 | #define FB_GFX_FGUARANTEED_FREQ_FUSE_SHIFT 11 | ||
4429 | #define FB_GFX_FGUARANTEED_FREQ_FUSE_MASK 0x0007f800 | ||
4430 | #define IOSF_NC_FB_GFX_FMAX_FUSE_HI 0x34 | ||
4431 | #define FB_FMAX_VMIN_FREQ_HI_MASK 0x00000007 | ||
4432 | #define IOSF_NC_FB_GFX_FMAX_FUSE_LO 0x30 | ||
4433 | #define FB_FMAX_VMIN_FREQ_LO_SHIFT 27 | ||
4434 | #define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000 | ||
4435 | |||
4415 | #define GEN6_GT_CORE_STATUS 0x138060 | 4436 | #define GEN6_GT_CORE_STATUS 0x138060 |
4416 | #define GEN6_CORE_CPD_STATE_MASK (7<<4) | 4437 | #define GEN6_CORE_CPD_STATE_MASK (7<<4) |
4417 | #define GEN6_RCn_MASK 7 | 4438 | #define GEN6_RCn_MASK 7 |
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index d5e1890678f9..ca00df2de07b 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c | |||
@@ -212,7 +212,10 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev, | |||
212 | int ret; | 212 | int ret; |
213 | 213 | ||
214 | mutex_lock(&dev_priv->rps.hw_lock); | 214 | mutex_lock(&dev_priv->rps.hw_lock); |
215 | ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER; | 215 | if (IS_VALLEYVIEW(dev_priv->dev)) |
216 | ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.cur_delay); | ||
217 | else | ||
218 | ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER; | ||
216 | mutex_unlock(&dev_priv->rps.hw_lock); | 219 | mutex_unlock(&dev_priv->rps.hw_lock); |
217 | 220 | ||
218 | return snprintf(buf, PAGE_SIZE, "%d\n", ret); | 221 | return snprintf(buf, PAGE_SIZE, "%d\n", ret); |
@@ -226,7 +229,10 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute | |||
226 | int ret; | 229 | int ret; |
227 | 230 | ||
228 | mutex_lock(&dev_priv->rps.hw_lock); | 231 | mutex_lock(&dev_priv->rps.hw_lock); |
229 | ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; | 232 | if (IS_VALLEYVIEW(dev_priv->dev)) |
233 | ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay); | ||
234 | else | ||
235 | ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER; | ||
230 | mutex_unlock(&dev_priv->rps.hw_lock); | 236 | mutex_unlock(&dev_priv->rps.hw_lock); |
231 | 237 | ||
232 | return snprintf(buf, PAGE_SIZE, "%d\n", ret); | 238 | return snprintf(buf, PAGE_SIZE, "%d\n", ret); |
@@ -246,16 +252,25 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, | |||
246 | if (ret) | 252 | if (ret) |
247 | return ret; | 253 | return ret; |
248 | 254 | ||
249 | val /= GT_FREQUENCY_MULTIPLIER; | ||
250 | |||
251 | mutex_lock(&dev_priv->rps.hw_lock); | 255 | mutex_lock(&dev_priv->rps.hw_lock); |
252 | 256 | ||
253 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | 257 | if (IS_VALLEYVIEW(dev_priv->dev)) { |
254 | hw_max = dev_priv->rps.hw_max; | 258 | val = vlv_freq_opcode(dev_priv->mem_freq, val); |
255 | non_oc_max = (rp_state_cap & 0xff); | 259 | |
256 | hw_min = ((rp_state_cap & 0xff0000) >> 16); | 260 | hw_max = valleyview_rps_max_freq(dev_priv); |
261 | hw_min = valleyview_rps_min_freq(dev_priv); | ||
262 | non_oc_max = hw_max; | ||
263 | } else { | ||
264 | val /= GT_FREQUENCY_MULTIPLIER; | ||
257 | 265 | ||
258 | if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) { | 266 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); |
267 | hw_max = dev_priv->rps.hw_max; | ||
268 | non_oc_max = (rp_state_cap & 0xff); | ||
269 | hw_min = ((rp_state_cap & 0xff0000) >> 16); | ||
270 | } | ||
271 | |||
272 | if (val < hw_min || val > hw_max || | ||
273 | val < dev_priv->rps.min_delay) { | ||
259 | mutex_unlock(&dev_priv->rps.hw_lock); | 274 | mutex_unlock(&dev_priv->rps.hw_lock); |
260 | return -EINVAL; | 275 | return -EINVAL; |
261 | } | 276 | } |
@@ -264,8 +279,12 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, | |||
264 | DRM_DEBUG("User requested overclocking to %d\n", | 279 | DRM_DEBUG("User requested overclocking to %d\n", |
265 | val * GT_FREQUENCY_MULTIPLIER); | 280 | val * GT_FREQUENCY_MULTIPLIER); |
266 | 281 | ||
267 | if (dev_priv->rps.cur_delay > val) | 282 | if (dev_priv->rps.cur_delay > val) { |
268 | gen6_set_rps(dev_priv->dev, val); | 283 | if (IS_VALLEYVIEW(dev_priv->dev)) |
284 | valleyview_set_rps(dev_priv->dev, val); | ||
285 | else | ||
286 | gen6_set_rps(dev_priv->dev, val); | ||
287 | } | ||
269 | 288 | ||
270 | dev_priv->rps.max_delay = val; | 289 | dev_priv->rps.max_delay = val; |
271 | 290 | ||
@@ -282,7 +301,10 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute | |||
282 | int ret; | 301 | int ret; |
283 | 302 | ||
284 | mutex_lock(&dev_priv->rps.hw_lock); | 303 | mutex_lock(&dev_priv->rps.hw_lock); |
285 | ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; | 304 | if (IS_VALLEYVIEW(dev_priv->dev)) |
305 | ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay); | ||
306 | else | ||
307 | ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER; | ||
286 | mutex_unlock(&dev_priv->rps.hw_lock); | 308 | mutex_unlock(&dev_priv->rps.hw_lock); |
287 | 309 | ||
288 | return snprintf(buf, PAGE_SIZE, "%d\n", ret); | 310 | return snprintf(buf, PAGE_SIZE, "%d\n", ret); |
@@ -302,21 +324,32 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, | |||
302 | if (ret) | 324 | if (ret) |
303 | return ret; | 325 | return ret; |
304 | 326 | ||
305 | val /= GT_FREQUENCY_MULTIPLIER; | ||
306 | |||
307 | mutex_lock(&dev_priv->rps.hw_lock); | 327 | mutex_lock(&dev_priv->rps.hw_lock); |
308 | 328 | ||
309 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | 329 | if (IS_VALLEYVIEW(dev)) { |
310 | hw_max = dev_priv->rps.hw_max; | 330 | val = vlv_freq_opcode(dev_priv->mem_freq, val); |
311 | hw_min = ((rp_state_cap & 0xff0000) >> 16); | 331 | |
332 | hw_max = valleyview_rps_max_freq(dev_priv); | ||
333 | hw_min = valleyview_rps_min_freq(dev_priv); | ||
334 | } else { | ||
335 | val /= GT_FREQUENCY_MULTIPLIER; | ||
336 | |||
337 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | ||
338 | hw_max = dev_priv->rps.hw_max; | ||
339 | hw_min = ((rp_state_cap & 0xff0000) >> 16); | ||
340 | } | ||
312 | 341 | ||
313 | if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) { | 342 | if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) { |
314 | mutex_unlock(&dev_priv->rps.hw_lock); | 343 | mutex_unlock(&dev_priv->rps.hw_lock); |
315 | return -EINVAL; | 344 | return -EINVAL; |
316 | } | 345 | } |
317 | 346 | ||
318 | if (dev_priv->rps.cur_delay < val) | 347 | if (dev_priv->rps.cur_delay < val) { |
319 | gen6_set_rps(dev_priv->dev, val); | 348 | if (IS_VALLEYVIEW(dev)) |
349 | valleyview_set_rps(dev, val); | ||
350 | else | ||
351 | gen6_set_rps(dev_priv->dev, val); | ||
352 | } | ||
320 | 353 | ||
321 | dev_priv->rps.min_delay = val; | 354 | dev_priv->rps.min_delay = val; |
322 | 355 | ||
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f802368e8e9d..2557926553b3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -2481,6 +2481,52 @@ void gen6_set_rps(struct drm_device *dev, u8 val) | |||
2481 | trace_intel_gpu_freq_change(val * 50); | 2481 | trace_intel_gpu_freq_change(val * 50); |
2482 | } | 2482 | } |
2483 | 2483 | ||
2484 | void valleyview_set_rps(struct drm_device *dev, u8 val) | ||
2485 | { | ||
2486 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2487 | unsigned long timeout = jiffies + msecs_to_jiffies(10); | ||
2488 | u32 limits = gen6_rps_limits(dev_priv, &val); | ||
2489 | u32 pval; | ||
2490 | |||
2491 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); | ||
2492 | WARN_ON(val > dev_priv->rps.max_delay); | ||
2493 | WARN_ON(val < dev_priv->rps.min_delay); | ||
2494 | |||
2495 | DRM_DEBUG_DRIVER("gpu freq request from %d to %d\n", | ||
2496 | vlv_gpu_freq(dev_priv->mem_freq, | ||
2497 | dev_priv->rps.cur_delay), | ||
2498 | vlv_gpu_freq(dev_priv->mem_freq, val)); | ||
2499 | |||
2500 | if (val == dev_priv->rps.cur_delay) | ||
2501 | return; | ||
2502 | |||
2503 | valleyview_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val); | ||
2504 | |||
2505 | do { | ||
2506 | valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &pval); | ||
2507 | if (time_after(jiffies, timeout)) { | ||
2508 | DRM_DEBUG_DRIVER("timed out waiting for Punit\n"); | ||
2509 | break; | ||
2510 | } | ||
2511 | udelay(10); | ||
2512 | } while (pval & 1); | ||
2513 | |||
2514 | valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &pval); | ||
2515 | if ((pval >> 8) != val) | ||
2516 | DRM_DEBUG_DRIVER("punit overrode freq: %d requested, but got %d\n", | ||
2517 | val, pval >> 8); | ||
2518 | |||
2519 | /* Make sure we continue to get interrupts | ||
2520 | * until we hit the minimum or maximum frequencies. | ||
2521 | */ | ||
2522 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); | ||
2523 | |||
2524 | dev_priv->rps.cur_delay = pval >> 8; | ||
2525 | |||
2526 | trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv->mem_freq, val)); | ||
2527 | } | ||
2528 | |||
2529 | |||
2484 | static void gen6_disable_rps(struct drm_device *dev) | 2530 | static void gen6_disable_rps(struct drm_device *dev) |
2485 | { | 2531 | { |
2486 | struct drm_i915_private *dev_priv = dev->dev_private; | 2532 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -2742,6 +2788,127 @@ static void gen6_update_ring_freq(struct drm_device *dev) | |||
2742 | } | 2788 | } |
2743 | } | 2789 | } |
2744 | 2790 | ||
2791 | int valleyview_rps_max_freq(struct drm_i915_private *dev_priv) | ||
2792 | { | ||
2793 | u32 val, rp0; | ||
2794 | |||
2795 | valleyview_nc_read(dev_priv, IOSF_NC_FB_GFX_FREQ_FUSE, &val); | ||
2796 | |||
2797 | rp0 = (val & FB_GFX_MAX_FREQ_FUSE_MASK) >> FB_GFX_MAX_FREQ_FUSE_SHIFT; | ||
2798 | /* Clamp to max */ | ||
2799 | rp0 = min_t(u32, rp0, 0xea); | ||
2800 | |||
2801 | return rp0; | ||
2802 | } | ||
2803 | |||
2804 | static int valleyview_rps_rpe_freq(struct drm_i915_private *dev_priv) | ||
2805 | { | ||
2806 | u32 val, rpe; | ||
2807 | |||
2808 | valleyview_nc_read(dev_priv, IOSF_NC_FB_GFX_FMAX_FUSE_LO, &val); | ||
2809 | rpe = (val & FB_FMAX_VMIN_FREQ_LO_MASK) >> FB_FMAX_VMIN_FREQ_LO_SHIFT; | ||
2810 | valleyview_nc_read(dev_priv, IOSF_NC_FB_GFX_FMAX_FUSE_HI, &val); | ||
2811 | rpe |= (val & FB_FMAX_VMIN_FREQ_HI_MASK) << 5; | ||
2812 | |||
2813 | return rpe; | ||
2814 | } | ||
2815 | |||
2816 | int valleyview_rps_min_freq(struct drm_i915_private *dev_priv) | ||
2817 | { | ||
2818 | u32 val; | ||
2819 | |||
2820 | valleyview_punit_read(dev_priv, PUNIT_REG_GPU_LFM, &val); | ||
2821 | |||
2822 | return val & 0xff; | ||
2823 | } | ||
2824 | |||
2825 | static void valleyview_enable_rps(struct drm_device *dev) | ||
2826 | { | ||
2827 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2828 | struct intel_ring_buffer *ring; | ||
2829 | u32 gtfifodbg, val, rpe; | ||
2830 | int i; | ||
2831 | |||
2832 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); | ||
2833 | |||
2834 | if ((gtfifodbg = I915_READ(GTFIFODBG))) { | ||
2835 | DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg); | ||
2836 | I915_WRITE(GTFIFODBG, gtfifodbg); | ||
2837 | } | ||
2838 | |||
2839 | gen6_gt_force_wake_get(dev_priv); | ||
2840 | |||
2841 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); | ||
2842 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); | ||
2843 | I915_WRITE(GEN6_RP_UP_EI, 66000); | ||
2844 | I915_WRITE(GEN6_RP_DOWN_EI, 350000); | ||
2845 | |||
2846 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); | ||
2847 | |||
2848 | I915_WRITE(GEN6_RP_CONTROL, | ||
2849 | GEN6_RP_MEDIA_TURBO | | ||
2850 | GEN6_RP_MEDIA_HW_NORMAL_MODE | | ||
2851 | GEN6_RP_MEDIA_IS_GFX | | ||
2852 | GEN6_RP_ENABLE | | ||
2853 | GEN6_RP_UP_BUSY_AVG | | ||
2854 | GEN6_RP_DOWN_IDLE_CONT); | ||
2855 | |||
2856 | I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 0x00280000); | ||
2857 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); | ||
2858 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); | ||
2859 | |||
2860 | for_each_ring(ring, dev_priv, i) | ||
2861 | I915_WRITE(RING_MAX_IDLE(ring->mmio_base), 10); | ||
2862 | |||
2863 | I915_WRITE(GEN6_RC6_THRESHOLD, 0xc350); | ||
2864 | |||
2865 | /* allows RC6 residency counter to work */ | ||
2866 | I915_WRITE(0x138104, _MASKED_BIT_ENABLE(0x3)); | ||
2867 | I915_WRITE(GEN6_RC_CONTROL, | ||
2868 | GEN7_RC_CTL_TO_MODE); | ||
2869 | |||
2870 | valleyview_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS, &val); | ||
2871 | dev_priv->mem_freq = 800 + (266 * (val >> 6) & 3); | ||
2872 | DRM_DEBUG_DRIVER("DDR speed: %d MHz", dev_priv->mem_freq); | ||
2873 | |||
2874 | DRM_DEBUG_DRIVER("GPLL enabled? %s\n", val & 0x10 ? "yes" : "no"); | ||
2875 | DRM_DEBUG_DRIVER("GPU status: 0x%08x\n", val); | ||
2876 | |||
2877 | DRM_DEBUG_DRIVER("current GPU freq: %d\n", | ||
2878 | vlv_gpu_freq(dev_priv->mem_freq, (val >> 8) & 0xff)); | ||
2879 | dev_priv->rps.cur_delay = (val >> 8) & 0xff; | ||
2880 | |||
2881 | dev_priv->rps.max_delay = valleyview_rps_max_freq(dev_priv); | ||
2882 | dev_priv->rps.hw_max = dev_priv->rps.max_delay; | ||
2883 | DRM_DEBUG_DRIVER("max GPU freq: %d\n", vlv_gpu_freq(dev_priv->mem_freq, | ||
2884 | dev_priv->rps.max_delay)); | ||
2885 | |||
2886 | rpe = valleyview_rps_rpe_freq(dev_priv); | ||
2887 | DRM_DEBUG_DRIVER("RPe GPU freq: %d\n", | ||
2888 | vlv_gpu_freq(dev_priv->mem_freq, rpe)); | ||
2889 | |||
2890 | val = valleyview_rps_min_freq(dev_priv); | ||
2891 | DRM_DEBUG_DRIVER("min GPU freq: %d\n", vlv_gpu_freq(dev_priv->mem_freq, | ||
2892 | val)); | ||
2893 | dev_priv->rps.min_delay = val; | ||
2894 | |||
2895 | DRM_DEBUG_DRIVER("setting GPU freq to %d\n", | ||
2896 | vlv_gpu_freq(dev_priv->mem_freq, rpe)); | ||
2897 | |||
2898 | valleyview_set_rps(dev_priv->dev, rpe); | ||
2899 | |||
2900 | /* requires MSI enabled */ | ||
2901 | I915_WRITE(GEN6_PMIER, GEN6_PM_DEFERRED_EVENTS); | ||
2902 | spin_lock_irq(&dev_priv->rps.lock); | ||
2903 | WARN_ON(dev_priv->rps.pm_iir != 0); | ||
2904 | I915_WRITE(GEN6_PMIMR, 0); | ||
2905 | spin_unlock_irq(&dev_priv->rps.lock); | ||
2906 | /* enable all PM interrupts */ | ||
2907 | I915_WRITE(GEN6_PMINTRMSK, 0); | ||
2908 | |||
2909 | gen6_gt_force_wake_put(dev_priv); | ||
2910 | } | ||
2911 | |||
2745 | void ironlake_teardown_rc6(struct drm_device *dev) | 2912 | void ironlake_teardown_rc6(struct drm_device *dev) |
2746 | { | 2913 | { |
2747 | struct drm_i915_private *dev_priv = dev->dev_private; | 2914 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -3468,7 +3635,7 @@ void intel_disable_gt_powersave(struct drm_device *dev) | |||
3468 | if (IS_IRONLAKE_M(dev)) { | 3635 | if (IS_IRONLAKE_M(dev)) { |
3469 | ironlake_disable_drps(dev); | 3636 | ironlake_disable_drps(dev); |
3470 | ironlake_disable_rc6(dev); | 3637 | ironlake_disable_rc6(dev); |
3471 | } else if (INTEL_INFO(dev)->gen >= 6 && !IS_VALLEYVIEW(dev)) { | 3638 | } else if (INTEL_INFO(dev)->gen >= 6) { |
3472 | cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work); | 3639 | cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work); |
3473 | mutex_lock(&dev_priv->rps.hw_lock); | 3640 | mutex_lock(&dev_priv->rps.hw_lock); |
3474 | gen6_disable_rps(dev); | 3641 | gen6_disable_rps(dev); |
@@ -3484,8 +3651,13 @@ static void intel_gen6_powersave_work(struct work_struct *work) | |||
3484 | struct drm_device *dev = dev_priv->dev; | 3651 | struct drm_device *dev = dev_priv->dev; |
3485 | 3652 | ||
3486 | mutex_lock(&dev_priv->rps.hw_lock); | 3653 | mutex_lock(&dev_priv->rps.hw_lock); |
3487 | gen6_enable_rps(dev); | 3654 | |
3488 | gen6_update_ring_freq(dev); | 3655 | if (IS_VALLEYVIEW(dev)) { |
3656 | valleyview_enable_rps(dev); | ||
3657 | } else { | ||
3658 | gen6_enable_rps(dev); | ||
3659 | gen6_update_ring_freq(dev); | ||
3660 | } | ||
3489 | mutex_unlock(&dev_priv->rps.hw_lock); | 3661 | mutex_unlock(&dev_priv->rps.hw_lock); |
3490 | } | 3662 | } |
3491 | 3663 | ||
@@ -3497,7 +3669,7 @@ void intel_enable_gt_powersave(struct drm_device *dev) | |||
3497 | ironlake_enable_drps(dev); | 3669 | ironlake_enable_drps(dev); |
3498 | ironlake_enable_rc6(dev); | 3670 | ironlake_enable_rc6(dev); |
3499 | intel_init_emon(dev); | 3671 | intel_init_emon(dev); |
3500 | } else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) { | 3672 | } else if (IS_GEN6(dev) || IS_GEN7(dev)) { |
3501 | /* | 3673 | /* |
3502 | * PCU communication is slow and this doesn't need to be | 3674 | * PCU communication is slow and this doesn't need to be |
3503 | * done at any specific time, so do this out of our fast path | 3675 | * done at any specific time, so do this out of our fast path |
@@ -4568,14 +4740,13 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val) | |||
4568 | return 0; | 4740 | return 0; |
4569 | } | 4741 | } |
4570 | 4742 | ||
4571 | static int vlv_punit_rw(struct drm_i915_private *dev_priv, u8 opcode, | 4743 | static int vlv_punit_rw(struct drm_i915_private *dev_priv, u32 port, u8 opcode, |
4572 | u8 addr, u32 *val) | 4744 | u8 addr, u32 *val) |
4573 | { | 4745 | { |
4574 | u32 cmd, devfn, port, be, bar; | 4746 | u32 cmd, devfn, be, bar; |
4575 | 4747 | ||
4576 | bar = 0; | 4748 | bar = 0; |
4577 | be = 0xf; | 4749 | be = 0xf; |
4578 | port = IOSF_PORT_PUNIT; | ||
4579 | devfn = PCI_DEVFN(2, 0); | 4750 | devfn = PCI_DEVFN(2, 0); |
4580 | 4751 | ||
4581 | cmd = (devfn << IOSF_DEVFN_SHIFT) | (opcode << IOSF_OPCODE_SHIFT) | | 4752 | cmd = (devfn << IOSF_DEVFN_SHIFT) | (opcode << IOSF_OPCODE_SHIFT) | |
@@ -4597,7 +4768,7 @@ static int vlv_punit_rw(struct drm_i915_private *dev_priv, u8 opcode, | |||
4597 | I915_WRITE(VLV_IOSF_DOORBELL_REQ, cmd); | 4768 | I915_WRITE(VLV_IOSF_DOORBELL_REQ, cmd); |
4598 | 4769 | ||
4599 | if (wait_for((I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) == 0, | 4770 | if (wait_for((I915_READ(VLV_IOSF_DOORBELL_REQ) & IOSF_SB_BUSY) == 0, |
4600 | 500)) { | 4771 | 5)) { |
4601 | DRM_ERROR("timeout waiting for pcode %s (%d) to finish\n", | 4772 | DRM_ERROR("timeout waiting for pcode %s (%d) to finish\n", |
4602 | opcode == PUNIT_OPCODE_REG_READ ? "read" : "write", | 4773 | opcode == PUNIT_OPCODE_REG_READ ? "read" : "write", |
4603 | addr); | 4774 | addr); |
@@ -4613,12 +4784,20 @@ static int vlv_punit_rw(struct drm_i915_private *dev_priv, u8 opcode, | |||
4613 | 4784 | ||
4614 | int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val) | 4785 | int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val) |
4615 | { | 4786 | { |
4616 | return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_READ, addr, val); | 4787 | return vlv_punit_rw(dev_priv, IOSF_PORT_PUNIT, PUNIT_OPCODE_REG_READ, |
4788 | addr, val); | ||
4617 | } | 4789 | } |
4618 | 4790 | ||
4619 | int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val) | 4791 | int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val) |
4620 | { | 4792 | { |
4621 | return vlv_punit_rw(dev_priv, PUNIT_OPCODE_REG_WRITE, addr, &val); | 4793 | return vlv_punit_rw(dev_priv, IOSF_PORT_PUNIT, PUNIT_OPCODE_REG_WRITE, |
4794 | addr, &val); | ||
4795 | } | ||
4796 | |||
4797 | int valleyview_nc_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val) | ||
4798 | { | ||
4799 | return vlv_punit_rw(dev_priv, IOSF_PORT_NC, PUNIT_OPCODE_REG_READ, | ||
4800 | addr, val); | ||
4622 | } | 4801 | } |
4623 | 4802 | ||
4624 | int vlv_gpu_freq(int ddr_freq, int val) | 4803 | int vlv_gpu_freq(int ddr_freq, int val) |