aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2010-06-12 02:32:23 -0400
committerEric Anholt <eric@anholt.net>2010-08-01 22:03:43 -0400
commitfa143215b11056b878875f87edac78a1cfb9d1c0 (patch)
treeb8711846ac593583fca7df8c3e95c72ef02e0624
parent36e83a187ca7517e9bdce7148b1c2c27661ef38f (diff)
drm/i915: Fix watermark calculation in self-refresh mode
For self-refresh mode WM calculation's "line time" should use mode's htotal instead of hdisplay. "surface width" is the hdisplay for display plane and 64 for cursor plane. Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h3
-rw-r--r--drivers/gpu/drm/i915/intel_display.c42
2 files changed, 27 insertions, 18 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d147ab2f5bfc..7fba852455f4 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -176,7 +176,8 @@ struct drm_i915_display_funcs {
176 int (*get_display_clock_speed)(struct drm_device *dev); 176 int (*get_display_clock_speed)(struct drm_device *dev);
177 int (*get_fifo_size)(struct drm_device *dev, int plane); 177 int (*get_fifo_size)(struct drm_device *dev, int plane);
178 void (*update_wm)(struct drm_device *dev, int planea_clock, 178 void (*update_wm)(struct drm_device *dev, int planea_clock,
179 int planeb_clock, int sr_hdisplay, int pixel_size); 179 int planeb_clock, int sr_hdisplay, int sr_htotal,
180 int pixel_size);
180 /* clock updates for mode set */ 181 /* clock updates for mode set */
181 /* cursor updates */ 182 /* cursor updates */
182 /* render clock increase/decrease */ 183 /* render clock increase/decrease */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 926470d9c63c..274d78d023a1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2809,7 +2809,8 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane)
2809} 2809}
2810 2810
2811static void pineview_update_wm(struct drm_device *dev, int planea_clock, 2811static void pineview_update_wm(struct drm_device *dev, int planea_clock,
2812 int planeb_clock, int sr_hdisplay, int pixel_size) 2812 int planeb_clock, int sr_hdisplay, int unused,
2813 int pixel_size)
2813{ 2814{
2814 struct drm_i915_private *dev_priv = dev->dev_private; 2815 struct drm_i915_private *dev_priv = dev->dev_private;
2815 u32 reg; 2816 u32 reg;
@@ -2874,7 +2875,8 @@ static void pineview_update_wm(struct drm_device *dev, int planea_clock,
2874} 2875}
2875 2876
2876static void g4x_update_wm(struct drm_device *dev, int planea_clock, 2877static void g4x_update_wm(struct drm_device *dev, int planea_clock,
2877 int planeb_clock, int sr_hdisplay, int pixel_size) 2878 int planeb_clock, int sr_hdisplay, int sr_htotal,
2879 int pixel_size)
2878{ 2880{
2879 struct drm_i915_private *dev_priv = dev->dev_private; 2881 struct drm_i915_private *dev_priv = dev->dev_private;
2880 int total_size, cacheline_size; 2882 int total_size, cacheline_size;
@@ -2917,11 +2919,11 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock,
2917 static const int sr_latency_ns = 12000; 2919 static const int sr_latency_ns = 12000;
2918 2920
2919 sr_clock = planea_clock ? planea_clock : planeb_clock; 2921 sr_clock = planea_clock ? planea_clock : planeb_clock;
2920 line_time_us = ((sr_hdisplay * 1000) / sr_clock); 2922 line_time_us = ((sr_htotal * 1000) / sr_clock);
2921 2923
2922 /* Use ns/us then divide to preserve precision */ 2924 /* Use ns/us then divide to preserve precision */
2923 sr_entries = (((sr_latency_ns / line_time_us) + 1) * 2925 sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
2924 pixel_size * sr_hdisplay) / 1000; 2926 pixel_size * sr_hdisplay;
2925 sr_entries = roundup(sr_entries / cacheline_size, 1); 2927 sr_entries = roundup(sr_entries / cacheline_size, 1);
2926 DRM_DEBUG("self-refresh entries: %d\n", sr_entries); 2928 DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
2927 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN); 2929 I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
@@ -2948,7 +2950,8 @@ static void g4x_update_wm(struct drm_device *dev, int planea_clock,
2948} 2950}
2949 2951
2950static void i965_update_wm(struct drm_device *dev, int planea_clock, 2952static void i965_update_wm(struct drm_device *dev, int planea_clock,
2951 int planeb_clock, int sr_hdisplay, int pixel_size) 2953 int planeb_clock, int sr_hdisplay, int sr_htotal,
2954 int pixel_size)
2952{ 2955{
2953 struct drm_i915_private *dev_priv = dev->dev_private; 2956 struct drm_i915_private *dev_priv = dev->dev_private;
2954 unsigned long line_time_us; 2957 unsigned long line_time_us;
@@ -2960,11 +2963,11 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
2960 static const int sr_latency_ns = 12000; 2963 static const int sr_latency_ns = 12000;
2961 2964
2962 sr_clock = planea_clock ? planea_clock : planeb_clock; 2965 sr_clock = planea_clock ? planea_clock : planeb_clock;
2963 line_time_us = ((sr_hdisplay * 1000) / sr_clock); 2966 line_time_us = ((sr_htotal * 1000) / sr_clock);
2964 2967
2965 /* Use ns/us then divide to preserve precision */ 2968 /* Use ns/us then divide to preserve precision */
2966 sr_entries = (((sr_latency_ns / line_time_us) + 1) * 2969 sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
2967 pixel_size * sr_hdisplay) / 1000; 2970 pixel_size * sr_hdisplay;
2968 sr_entries = roundup(sr_entries / I915_FIFO_LINE_SIZE, 1); 2971 sr_entries = roundup(sr_entries / I915_FIFO_LINE_SIZE, 1);
2969 DRM_DEBUG("self-refresh entries: %d\n", sr_entries); 2972 DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
2970 srwm = I945_FIFO_SIZE - sr_entries; 2973 srwm = I945_FIFO_SIZE - sr_entries;
@@ -2990,7 +2993,8 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
2990} 2993}
2991 2994
2992static void i9xx_update_wm(struct drm_device *dev, int planea_clock, 2995static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
2993 int planeb_clock, int sr_hdisplay, int pixel_size) 2996 int planeb_clock, int sr_hdisplay, int sr_htotal,
2997 int pixel_size)
2994{ 2998{
2995 struct drm_i915_private *dev_priv = dev->dev_private; 2999 struct drm_i915_private *dev_priv = dev->dev_private;
2996 uint32_t fwater_lo; 3000 uint32_t fwater_lo;
@@ -3035,11 +3039,11 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
3035 static const int sr_latency_ns = 6000; 3039 static const int sr_latency_ns = 6000;
3036 3040
3037 sr_clock = planea_clock ? planea_clock : planeb_clock; 3041 sr_clock = planea_clock ? planea_clock : planeb_clock;
3038 line_time_us = ((sr_hdisplay * 1000) / sr_clock); 3042 line_time_us = ((sr_htotal * 1000) / sr_clock);
3039 3043
3040 /* Use ns/us then divide to preserve precision */ 3044 /* Use ns/us then divide to preserve precision */
3041 sr_entries = (((sr_latency_ns / line_time_us) + 1) * 3045 sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
3042 pixel_size * sr_hdisplay) / 1000; 3046 pixel_size * sr_hdisplay;
3043 sr_entries = roundup(sr_entries / cacheline_size, 1); 3047 sr_entries = roundup(sr_entries / cacheline_size, 1);
3044 DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries); 3048 DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries);
3045 srwm = total_size - sr_entries; 3049 srwm = total_size - sr_entries;
@@ -3078,7 +3082,7 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
3078} 3082}
3079 3083
3080static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused, 3084static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused,
3081 int unused2, int pixel_size) 3085 int unused2, int unused3, int pixel_size)
3082{ 3086{
3083 struct drm_i915_private *dev_priv = dev->dev_private; 3087 struct drm_i915_private *dev_priv = dev->dev_private;
3084 uint32_t fwater_lo = I915_READ(FW_BLC) & ~0xfff; 3088 uint32_t fwater_lo = I915_READ(FW_BLC) & ~0xfff;
@@ -3098,7 +3102,8 @@ static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused,
3098#define ILK_LP0_PLANE_LATENCY 700 3102#define ILK_LP0_PLANE_LATENCY 700
3099 3103
3100static void ironlake_update_wm(struct drm_device *dev, int planea_clock, 3104static void ironlake_update_wm(struct drm_device *dev, int planea_clock,
3101 int planeb_clock, int sr_hdisplay, int pixel_size) 3105 int planeb_clock, int sr_hdisplay, int sr_htotal,
3106 int pixel_size)
3102{ 3107{
3103 struct drm_i915_private *dev_priv = dev->dev_private; 3108 struct drm_i915_private *dev_priv = dev->dev_private;
3104 int planea_wm, planeb_wm, cursora_wm, cursorb_wm; 3109 int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
@@ -3160,7 +3165,7 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock,
3160 int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK; 3165 int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK;
3161 3166
3162 sr_clock = planea_clock ? planea_clock : planeb_clock; 3167 sr_clock = planea_clock ? planea_clock : planeb_clock;
3163 line_time_us = ((sr_hdisplay * 1000) / sr_clock); 3168 line_time_us = ((sr_htotal * 1000) / sr_clock);
3164 3169
3165 /* Use ns/us then divide to preserve precision */ 3170 /* Use ns/us then divide to preserve precision */
3166 line_count = ((ilk_sr_latency * 500) / line_time_us + 1000) 3171 line_count = ((ilk_sr_latency * 500) / line_time_us + 1000)
@@ -3220,6 +3225,7 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock,
3220 * bytes per pixel 3225 * bytes per pixel
3221 * where 3226 * where
3222 * line time = htotal / dotclock 3227 * line time = htotal / dotclock
3228 * surface width = hdisplay for normal plane and 64 for cursor
3223 * and latency is assumed to be high, as above. 3229 * and latency is assumed to be high, as above.
3224 * 3230 *
3225 * The final value programmed to the register should always be rounded up, 3231 * The final value programmed to the register should always be rounded up,
@@ -3236,6 +3242,7 @@ static void intel_update_watermarks(struct drm_device *dev)
3236 int sr_hdisplay = 0; 3242 int sr_hdisplay = 0;
3237 unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0; 3243 unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
3238 int enabled = 0, pixel_size = 0; 3244 int enabled = 0, pixel_size = 0;
3245 int sr_htotal = 0;
3239 3246
3240 if (!dev_priv->display.update_wm) 3247 if (!dev_priv->display.update_wm)
3241 return; 3248 return;
@@ -3256,6 +3263,7 @@ static void intel_update_watermarks(struct drm_device *dev)
3256 } 3263 }
3257 sr_hdisplay = crtc->mode.hdisplay; 3264 sr_hdisplay = crtc->mode.hdisplay;
3258 sr_clock = crtc->mode.clock; 3265 sr_clock = crtc->mode.clock;
3266 sr_htotal = crtc->mode.htotal;
3259 if (crtc->fb) 3267 if (crtc->fb)
3260 pixel_size = crtc->fb->bits_per_pixel / 8; 3268 pixel_size = crtc->fb->bits_per_pixel / 8;
3261 else 3269 else
@@ -3267,7 +3275,7 @@ static void intel_update_watermarks(struct drm_device *dev)
3267 return; 3275 return;
3268 3276
3269 dev_priv->display.update_wm(dev, planea_clock, planeb_clock, 3277 dev_priv->display.update_wm(dev, planea_clock, planeb_clock,
3270 sr_hdisplay, pixel_size); 3278 sr_hdisplay, sr_htotal, pixel_size);
3271} 3279}
3272 3280
3273static int intel_crtc_mode_set(struct drm_crtc *crtc, 3281static int intel_crtc_mode_set(struct drm_crtc *crtc,