Skip to content

Commit

Permalink
drm/i915: Calculate cursor watermark under non-SR state for Ironlake
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Zhenyu Wang <[email protected]>
Signed-off-by: Eric Anholt <[email protected]>
  • Loading branch information
yakuizhao authored and anholt committed Aug 2, 2010
1 parent 4fe5e61 commit c936f44
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -2190,6 +2190,9 @@
#define ILK_DISPLAY_FIFO 128
#define ILK_DISPLAY_MAXWM 64
#define ILK_DISPLAY_DFTWM 8
#define ILK_CURSOR_FIFO 32
#define ILK_CURSOR_MAXWM 16
#define ILK_CURSOR_DFTWM 8

#define ILK_DISPLAY_SR_FIFO 512
#define ILK_DISPLAY_MAX_SRWM 0x1ff
Expand Down
56 changes: 53 additions & 3 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -2590,6 +2590,14 @@ static struct intel_watermark_params ironlake_display_wm_info = {
ILK_FIFO_LINE_SIZE
};

static struct intel_watermark_params ironlake_cursor_wm_info = {
ILK_CURSOR_FIFO,
ILK_CURSOR_MAXWM,
ILK_CURSOR_DFTWM,
2,
ILK_FIFO_LINE_SIZE
};

static struct intel_watermark_params ironlake_display_srwm_info = {
ILK_DISPLAY_SR_FIFO,
ILK_DISPLAY_MAX_SRWM,
Expand Down Expand Up @@ -3142,6 +3150,7 @@ static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused,
}

#define ILK_LP0_PLANE_LATENCY 700
#define ILK_LP0_CURSOR_LATENCY 1300

static void ironlake_update_wm(struct drm_device *dev, int planea_clock,
int planeb_clock, int sr_hdisplay, int sr_htotal,
Expand All @@ -3153,6 +3162,21 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock,
unsigned long line_time_us;
int sr_clock, entries_required;
u32 reg_value;
int line_count;
int planea_htotal = 0, planeb_htotal = 0;
struct drm_crtc *crtc;
struct intel_crtc *intel_crtc;

/* Need htotal for all active display plane */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
intel_crtc = to_intel_crtc(crtc);
if (crtc->enabled) {
if (intel_crtc->plane == 0)
planea_htotal = crtc->mode.htotal;
else
planeb_htotal = crtc->mode.htotal;
}
}

/* Calculate and update the watermark for plane A */
if (planea_clock) {
Expand All @@ -3166,7 +3190,20 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock,
if (planea_wm > (int)ironlake_display_wm_info.max_wm)
planea_wm = ironlake_display_wm_info.max_wm;

cursora_wm = 16;
/* Use the large buffer method to calculate cursor watermark */
line_time_us = (planea_htotal * 1000) / planea_clock;

/* Use ns/us then divide to preserve precision */
line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000;

/* calculate the cursor watermark for cursor A */
entries_required = line_count * 64 * pixel_size;
entries_required = DIV_ROUND_UP(entries_required,
ironlake_cursor_wm_info.cacheline_size);
cursora_wm = entries_required + ironlake_cursor_wm_info.guard_size;
if (cursora_wm > ironlake_cursor_wm_info.max_wm)
cursora_wm = ironlake_cursor_wm_info.max_wm;

reg_value = I915_READ(WM0_PIPEA_ILK);
reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
reg_value |= (planea_wm << WM0_PIPE_PLANE_SHIFT) |
Expand All @@ -3187,7 +3224,20 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock,
if (planeb_wm > (int)ironlake_display_wm_info.max_wm)
planeb_wm = ironlake_display_wm_info.max_wm;

cursorb_wm = 16;
/* Use the large buffer method to calculate cursor watermark */
line_time_us = (planeb_htotal * 1000) / planeb_clock;

/* Use ns/us then divide to preserve precision */
line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000;

/* calculate the cursor watermark for cursor B */
entries_required = line_count * 64 * pixel_size;
entries_required = DIV_ROUND_UP(entries_required,
ironlake_cursor_wm_info.cacheline_size);
cursorb_wm = entries_required + ironlake_cursor_wm_info.guard_size;
if (cursorb_wm > ironlake_cursor_wm_info.max_wm)
cursorb_wm = ironlake_cursor_wm_info.max_wm;

reg_value = I915_READ(WM0_PIPEB_ILK);
reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
reg_value |= (planeb_wm << WM0_PIPE_PLANE_SHIFT) |
Expand All @@ -3202,7 +3252,7 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock,
* display plane is used.
*/
if (!planea_clock || !planeb_clock) {
int line_count;

/* Read the self-refresh latency. The unit is 0.5us */
int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK;

Expand Down

0 comments on commit c936f44

Please sign in to comment.