summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_pm.c
diff options
context:
space:
mode:
authorVille Syrjälä2017-03-02 18:15:03 +0100
committerVille Syrjälä2017-03-03 15:50:10 +0100
commit1a10ae6ba8c3df4af9bcdb6f40348af71e72bd13 (patch)
treeb0b578f47b2779b25d8a93873f4b3b6b2cf76cb7 /drivers/gpu/drm/i915/intel_pm.c
parentdrm/i915: Sanitize VLV/CHV watermarks properly (diff)
downloadkernel-qcow2-linux-1a10ae6ba8c3df4af9bcdb6f40348af71e72bd13.tar.gz
kernel-qcow2-linux-1a10ae6ba8c3df4af9bcdb6f40348af71e72bd13.tar.xz
kernel-qcow2-linux-1a10ae6ba8c3df4af9bcdb6f40348af71e72bd13.zip
drm/i915: Workaround VLV/CHV sprite1->sprite0 enable underrun
On VLV/CHV enabling sprite0 when sprite1 has already been enabled may lead to an underrun. This only happens when sprite0 FIFO size is zero prior to enabling it. Hence an effective workaround is to always allocate at least one cacheline for sprite0 when sprite1 is active. I've not observed this sort of failure during any other type of plane enable/disable sequence. v2: s/noninverted/raw/ for consistency with other platforms Testcase: igt/kms_plane_blinker Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170302171508.1666-14-ville.syrjala@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7caed0006ee7..6e2acfd687a1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1028,6 +1028,12 @@ static uint16_t vlv_compute_wm_level(const struct intel_crtc_state *crtc_state,
return min_t(int, wm, USHRT_MAX);
}
+static bool vlv_need_sprite0_fifo_workaround(unsigned int active_planes)
+{
+ return (active_planes & (BIT(PLANE_SPRITE0) |
+ BIT(PLANE_SPRITE1))) == BIT(PLANE_SPRITE1);
+}
+
static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
@@ -1038,12 +1044,25 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
int num_active_planes = hweight32(active_planes);
const int fifo_size = 511;
int fifo_extra, fifo_left = fifo_size;
+ int sprite0_fifo_extra = 0;
unsigned int total_rate;
enum plane_id plane_id;
+ /*
+ * When enabling sprite0 after sprite1 has already been enabled
+ * we tend to get an underrun unless sprite0 already has some
+ * FIFO space allcoated. Hence we always allocate at least one
+ * cacheline for sprite0 whenever sprite1 is enabled.
+ *
+ * All other plane enable sequences appear immune to this problem.
+ */
+ if (vlv_need_sprite0_fifo_workaround(active_planes))
+ sprite0_fifo_extra = 1;
+
total_rate = raw->plane[PLANE_PRIMARY] +
raw->plane[PLANE_SPRITE0] +
- raw->plane[PLANE_SPRITE1];
+ raw->plane[PLANE_SPRITE1] +
+ sprite0_fifo_extra;
if (total_rate > fifo_size)
return -EINVAL;
@@ -1064,6 +1083,9 @@ static int vlv_compute_fifo(struct intel_crtc_state *crtc_state)
fifo_left -= fifo_state->plane[plane_id];
}
+ fifo_state->plane[PLANE_SPRITE0] += sprite0_fifo_extra;
+ fifo_left -= sprite0_fifo_extra;
+
fifo_state->plane[PLANE_CURSOR] = 63;
fifo_extra = DIV_ROUND_UP(fifo_left, num_active_planes ?: 1);