diff options
author | Zhao Yakui <yakui.zhao@intel.com> | 2010-06-12 02:32:26 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-08-01 22:03:43 -0400 |
commit | c936f44d1b2daea2fd1d52300cab792abe01e28c (patch) | |
tree | 336c4098a9ca13fdec59d45bcb8473e147f02ca0 | |
parent | 4fe5e61180d8ea2268d6e64972d90efbe2bab4aa (diff) |
drm/i915: Calculate cursor watermark under non-SR state for Ironlake
The hardware team suggest that the "large buffer" method should be
used to calculate the cursor watermark under non-SR state as well,
which is to avoid the flicker when FBC is enabled on Ironlake.
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_reg.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 56 |
2 files changed, 56 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1f741a6d0b12..d0ccfa0c72de 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -2190,6 +2190,9 @@ | |||
2190 | #define ILK_DISPLAY_FIFO 128 | 2190 | #define ILK_DISPLAY_FIFO 128 |
2191 | #define ILK_DISPLAY_MAXWM 64 | 2191 | #define ILK_DISPLAY_MAXWM 64 |
2192 | #define ILK_DISPLAY_DFTWM 8 | 2192 | #define ILK_DISPLAY_DFTWM 8 |
2193 | #define ILK_CURSOR_FIFO 32 | ||
2194 | #define ILK_CURSOR_MAXWM 16 | ||
2195 | #define ILK_CURSOR_DFTWM 8 | ||
2193 | 2196 | ||
2194 | #define ILK_DISPLAY_SR_FIFO 512 | 2197 | #define ILK_DISPLAY_SR_FIFO 512 |
2195 | #define ILK_DISPLAY_MAX_SRWM 0x1ff | 2198 | #define ILK_DISPLAY_MAX_SRWM 0x1ff |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b580cd872b10..cca6ce80d464 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -2590,6 +2590,14 @@ static struct intel_watermark_params ironlake_display_wm_info = { | |||
2590 | ILK_FIFO_LINE_SIZE | 2590 | ILK_FIFO_LINE_SIZE |
2591 | }; | 2591 | }; |
2592 | 2592 | ||
2593 | static struct intel_watermark_params ironlake_cursor_wm_info = { | ||
2594 | ILK_CURSOR_FIFO, | ||
2595 | ILK_CURSOR_MAXWM, | ||
2596 | ILK_CURSOR_DFTWM, | ||
2597 | 2, | ||
2598 | ILK_FIFO_LINE_SIZE | ||
2599 | }; | ||
2600 | |||
2593 | static struct intel_watermark_params ironlake_display_srwm_info = { | 2601 | static struct intel_watermark_params ironlake_display_srwm_info = { |
2594 | ILK_DISPLAY_SR_FIFO, | 2602 | ILK_DISPLAY_SR_FIFO, |
2595 | ILK_DISPLAY_MAX_SRWM, | 2603 | ILK_DISPLAY_MAX_SRWM, |
@@ -3142,6 +3150,7 @@ static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused, | |||
3142 | } | 3150 | } |
3143 | 3151 | ||
3144 | #define ILK_LP0_PLANE_LATENCY 700 | 3152 | #define ILK_LP0_PLANE_LATENCY 700 |
3153 | #define ILK_LP0_CURSOR_LATENCY 1300 | ||
3145 | 3154 | ||
3146 | static void ironlake_update_wm(struct drm_device *dev, int planea_clock, | 3155 | static void ironlake_update_wm(struct drm_device *dev, int planea_clock, |
3147 | int planeb_clock, int sr_hdisplay, int sr_htotal, | 3156 | int planeb_clock, int sr_hdisplay, int sr_htotal, |
@@ -3153,6 +3162,21 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock, | |||
3153 | unsigned long line_time_us; | 3162 | unsigned long line_time_us; |
3154 | int sr_clock, entries_required; | 3163 | int sr_clock, entries_required; |
3155 | u32 reg_value; | 3164 | u32 reg_value; |
3165 | int line_count; | ||
3166 | int planea_htotal = 0, planeb_htotal = 0; | ||
3167 | struct drm_crtc *crtc; | ||
3168 | struct intel_crtc *intel_crtc; | ||
3169 | |||
3170 | /* Need htotal for all active display plane */ | ||
3171 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
3172 | intel_crtc = to_intel_crtc(crtc); | ||
3173 | if (crtc->enabled) { | ||
3174 | if (intel_crtc->plane == 0) | ||
3175 | planea_htotal = crtc->mode.htotal; | ||
3176 | else | ||
3177 | planeb_htotal = crtc->mode.htotal; | ||
3178 | } | ||
3179 | } | ||
3156 | 3180 | ||
3157 | /* Calculate and update the watermark for plane A */ | 3181 | /* Calculate and update the watermark for plane A */ |
3158 | if (planea_clock) { | 3182 | if (planea_clock) { |
@@ -3166,7 +3190,20 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock, | |||
3166 | if (planea_wm > (int)ironlake_display_wm_info.max_wm) | 3190 | if (planea_wm > (int)ironlake_display_wm_info.max_wm) |
3167 | planea_wm = ironlake_display_wm_info.max_wm; | 3191 | planea_wm = ironlake_display_wm_info.max_wm; |
3168 | 3192 | ||
3169 | cursora_wm = 16; | 3193 | /* Use the large buffer method to calculate cursor watermark */ |
3194 | line_time_us = (planea_htotal * 1000) / planea_clock; | ||
3195 | |||
3196 | /* Use ns/us then divide to preserve precision */ | ||
3197 | line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000; | ||
3198 | |||
3199 | /* calculate the cursor watermark for cursor A */ | ||
3200 | entries_required = line_count * 64 * pixel_size; | ||
3201 | entries_required = DIV_ROUND_UP(entries_required, | ||
3202 | ironlake_cursor_wm_info.cacheline_size); | ||
3203 | cursora_wm = entries_required + ironlake_cursor_wm_info.guard_size; | ||
3204 | if (cursora_wm > ironlake_cursor_wm_info.max_wm) | ||
3205 | cursora_wm = ironlake_cursor_wm_info.max_wm; | ||
3206 | |||
3170 | reg_value = I915_READ(WM0_PIPEA_ILK); | 3207 | reg_value = I915_READ(WM0_PIPEA_ILK); |
3171 | reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | 3208 | reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); |
3172 | reg_value |= (planea_wm << WM0_PIPE_PLANE_SHIFT) | | 3209 | reg_value |= (planea_wm << WM0_PIPE_PLANE_SHIFT) | |
@@ -3187,7 +3224,20 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock, | |||
3187 | if (planeb_wm > (int)ironlake_display_wm_info.max_wm) | 3224 | if (planeb_wm > (int)ironlake_display_wm_info.max_wm) |
3188 | planeb_wm = ironlake_display_wm_info.max_wm; | 3225 | planeb_wm = ironlake_display_wm_info.max_wm; |
3189 | 3226 | ||
3190 | cursorb_wm = 16; | 3227 | /* Use the large buffer method to calculate cursor watermark */ |
3228 | line_time_us = (planeb_htotal * 1000) / planeb_clock; | ||
3229 | |||
3230 | /* Use ns/us then divide to preserve precision */ | ||
3231 | line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000; | ||
3232 | |||
3233 | /* calculate the cursor watermark for cursor B */ | ||
3234 | entries_required = line_count * 64 * pixel_size; | ||
3235 | entries_required = DIV_ROUND_UP(entries_required, | ||
3236 | ironlake_cursor_wm_info.cacheline_size); | ||
3237 | cursorb_wm = entries_required + ironlake_cursor_wm_info.guard_size; | ||
3238 | if (cursorb_wm > ironlake_cursor_wm_info.max_wm) | ||
3239 | cursorb_wm = ironlake_cursor_wm_info.max_wm; | ||
3240 | |||
3191 | reg_value = I915_READ(WM0_PIPEB_ILK); | 3241 | reg_value = I915_READ(WM0_PIPEB_ILK); |
3192 | reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); | 3242 | reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); |
3193 | reg_value |= (planeb_wm << WM0_PIPE_PLANE_SHIFT) | | 3243 | reg_value |= (planeb_wm << WM0_PIPE_PLANE_SHIFT) | |
@@ -3202,7 +3252,7 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock, | |||
3202 | * display plane is used. | 3252 | * display plane is used. |
3203 | */ | 3253 | */ |
3204 | if (!planea_clock || !planeb_clock) { | 3254 | if (!planea_clock || !planeb_clock) { |
3205 | int line_count; | 3255 | |
3206 | /* Read the self-refresh latency. The unit is 0.5us */ | 3256 | /* Read the self-refresh latency. The unit is 0.5us */ |
3207 | int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK; | 3257 | int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK; |
3208 | 3258 | ||