aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h3
-rw-r--r--drivers/gpu/drm/i915/intel_display.c56
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 1f741a6d0b1..d0ccfa0c72d 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 b580cd872b1..cca6ce80d46 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
2593static 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
2593static struct intel_watermark_params ironlake_display_srwm_info = { 2601static 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
3146static void ironlake_update_wm(struct drm_device *dev, int planea_clock, 3155static 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