Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c936f44d authored by Zhao Yakui's avatar Zhao Yakui Committed by Eric Anholt
Browse files

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: default avatarZhao Yakui <yakui.zhao@intel.com>
Signed-off-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent 4fe5e611
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -2190,6 +2190,9 @@
#define ILK_DISPLAY_FIFO	128
#define ILK_DISPLAY_FIFO	128
#define ILK_DISPLAY_MAXWM	64
#define ILK_DISPLAY_MAXWM	64
#define ILK_DISPLAY_DFTWM	8
#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_SR_FIFO	512
#define ILK_DISPLAY_MAX_SRWM	0x1ff
#define ILK_DISPLAY_MAX_SRWM	0x1ff
+53 −3
Original line number Original line Diff line number Diff line
@@ -2590,6 +2590,14 @@ static struct intel_watermark_params ironlake_display_wm_info = {
	ILK_FIFO_LINE_SIZE
	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 = {
static struct intel_watermark_params ironlake_display_srwm_info = {
	ILK_DISPLAY_SR_FIFO,
	ILK_DISPLAY_SR_FIFO,
	ILK_DISPLAY_MAX_SRWM,
	ILK_DISPLAY_MAX_SRWM,
@@ -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_PLANE_LATENCY		700
#define ILK_LP0_CURSOR_LATENCY		1300


static void ironlake_update_wm(struct drm_device *dev,  int planea_clock,
static void ironlake_update_wm(struct drm_device *dev,  int planea_clock,
		       int planeb_clock, int sr_hdisplay, int sr_htotal,
		       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,
	unsigned long line_time_us;
	unsigned long line_time_us;
	int sr_clock, entries_required;
	int sr_clock, entries_required;
	u32 reg_value;
	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 */
	/* Calculate and update the watermark for plane A */
	if (planea_clock) {
	if (planea_clock) {
@@ -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)
		if (planea_wm > (int)ironlake_display_wm_info.max_wm)
			planea_wm = 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 = I915_READ(WM0_PIPEA_ILK);
		reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
		reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
		reg_value |= (planea_wm << WM0_PIPE_PLANE_SHIFT) |
		reg_value |= (planea_wm << WM0_PIPE_PLANE_SHIFT) |
@@ -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)
		if (planeb_wm > (int)ironlake_display_wm_info.max_wm)
			planeb_wm = 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 = I915_READ(WM0_PIPEB_ILK);
		reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
		reg_value &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
		reg_value |= (planeb_wm << WM0_PIPE_PLANE_SHIFT) |
		reg_value |= (planeb_wm << WM0_PIPE_PLANE_SHIFT) |
@@ -3202,7 +3252,7 @@ static void ironlake_update_wm(struct drm_device *dev, int planea_clock,
	 * display plane is used.
	 * display plane is used.
	 */
	 */
	if (!planea_clock || !planeb_clock) {
	if (!planea_clock || !planeb_clock) {
		int line_count;

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