diff options
author | Zhao Yakui <yakui.zhao@intel.com> | 2010-06-12 02:32:23 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-08-01 22:03:43 -0400 |
commit | fa143215b11056b878875f87edac78a1cfb9d1c0 (patch) | |
tree | b8711846ac593583fca7df8c3e95c72ef02e0624 | |
parent | 36e83a187ca7517e9bdce7148b1c2c27661ef38f (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.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 42 |
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 | ||
2811 | static void pineview_update_wm(struct drm_device *dev, int planea_clock, | 2811 | static 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 | ||
2876 | static void g4x_update_wm(struct drm_device *dev, int planea_clock, | 2877 | static 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 | ||
2950 | static void i965_update_wm(struct drm_device *dev, int planea_clock, | 2952 | static 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 | ||
2992 | static void i9xx_update_wm(struct drm_device *dev, int planea_clock, | 2995 | static 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 | ||
3080 | static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused, | 3084 | static 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 | ||
3100 | static void ironlake_update_wm(struct drm_device *dev, int planea_clock, | 3104 | static 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 | ||
3273 | static int intel_crtc_mode_set(struct drm_crtc *crtc, | 3281 | static int intel_crtc_mode_set(struct drm_crtc *crtc, |