diff mbox

[10/10] drm/i915: Support variable cursor height on ivb+

Message ID 20170307152709.31957-11-ville.syrjala@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ville Syrjälä March 7, 2017, 3:27 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

IVB introduced the CUR_FBC_CTL register which allows reducing the cursor
height down to 8 lines from the otherwise square cursor dimensions.
Implement support for it. CUR_FBC_CTL can't be used when the cursor
is rotated.

Commandeer the otherwise unused cursor->cursor.size to track the
current value of CUR_FBC_CTL to optimize away redundant CUR_FBC_CTL
writes, and to notice when we need to arm the update via CURBASE if
just CUR_FBC_CTL changes.

v2: Reverse the gen check to make it sane
v3: Only enable CUR_FBC_CTL when cursor is enabled, adapt to
    earlier code changes which means we now actually turn off
    the cursor when we're supposed to unlike v2
v4: Add a comment about rotation vs. CUR_FBC_CTL,
    rebase due to 'dirty' (Chris)
v5: Rebase to the atomic world
    Handle 180 degree rotation
    Add HAS_CUR_FBC()
v6: Rebase

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |  1 +
 drivers/gpu/drm/i915/i915_reg.h      |  5 ++++-
 drivers/gpu/drm/i915/intel_display.c | 36 +++++++++++++++++++++++++++++-------
 3 files changed, 34 insertions(+), 8 deletions(-)

Comments

Chris Wilson March 7, 2017, 10:32 p.m. UTC | #1
On Tue, Mar 07, 2017 at 05:27:09PM +0200, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> IVB introduced the CUR_FBC_CTL register which allows reducing the cursor
> height down to 8 lines from the otherwise square cursor dimensions.
> Implement support for it. CUR_FBC_CTL can't be used when the cursor
> is rotated.
> 
> Commandeer the otherwise unused cursor->cursor.size to track the
> current value of CUR_FBC_CTL to optimize away redundant CUR_FBC_CTL
> writes, and to notice when we need to arm the update via CURBASE if
> just CUR_FBC_CTL changes.

For userspace to discover this, they should just use trial and error
during startup (using the legacy SetCursor)? Though the easiest way
would cause the cursor to flicker - just hope the cursor is
off/invisible on startup.

Code makes a lot of sense after all the refactoring, but I'll leave the
register checking to somebody else unless they are lazier than I am.
-Chris
Ville Syrjälä March 8, 2017, 10:40 a.m. UTC | #2
On Tue, Mar 07, 2017 at 10:32:14PM +0000, Chris Wilson wrote:
> On Tue, Mar 07, 2017 at 05:27:09PM +0200, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > IVB introduced the CUR_FBC_CTL register which allows reducing the cursor
> > height down to 8 lines from the otherwise square cursor dimensions.
> > Implement support for it. CUR_FBC_CTL can't be used when the cursor
> > is rotated.
> > 
> > Commandeer the otherwise unused cursor->cursor.size to track the
> > current value of CUR_FBC_CTL to optimize away redundant CUR_FBC_CTL
> > writes, and to notice when we need to arm the update via CURBASE if
> > just CUR_FBC_CTL changes.
> 
> For userspace to discover this, they should just use trial and error
> during startup (using the legacy SetCursor)? Though the easiest way
> would cause the cursor to flicker - just hope the cursor is
> off/invisible on startup.

I don't have any decent answer for how to discover this feature. Atomic
would allow the trial and error approach without flickers. Otherwise I
guess one could defer the check until the cursor size actually changes.
Although maybe that won't really work for Xorg. ISTR it wants to know
things about the cursor size upfront?

> Code makes a lot of sense after all the refactoring, but I'll leave the
> register checking to somebody else unless they are lazier than I am.
> -Chris
> 
> -- 
> Chris Wilson, Intel Open Source Technology Centre
Daniel Vetter March 8, 2017, 10:45 a.m. UTC | #3
On Tue, Mar 07, 2017 at 10:32:14PM +0000, Chris Wilson wrote:
> On Tue, Mar 07, 2017 at 05:27:09PM +0200, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > IVB introduced the CUR_FBC_CTL register which allows reducing the cursor
> > height down to 8 lines from the otherwise square cursor dimensions.
> > Implement support for it. CUR_FBC_CTL can't be used when the cursor
> > is rotated.
> > 
> > Commandeer the otherwise unused cursor->cursor.size to track the
> > current value of CUR_FBC_CTL to optimize away redundant CUR_FBC_CTL
> > writes, and to notice when we need to arm the update via CURBASE if
> > just CUR_FBC_CTL changes.
> 
> For userspace to discover this, they should just use trial and error
> during startup (using the legacy SetCursor)? Though the easiest way
> would cause the cursor to flicker - just hope the cursor is
> off/invisible on startup.
> 
> Code makes a lot of sense after all the refactoring, but I'll leave the
> register checking to somebody else unless they are lazier than I am.

TEST_ONLY atomic commits on the cursor plane. That's pretty much how it's
meant to be used (although no one yet figured out how to tell generic
userspace about fancy constraints like this one here).
-Daniel
Chris Wilson March 8, 2017, 11 a.m. UTC | #4
On Wed, Mar 08, 2017 at 12:40:53PM +0200, Ville Syrjälä wrote:
> On Tue, Mar 07, 2017 at 10:32:14PM +0000, Chris Wilson wrote:
> > On Tue, Mar 07, 2017 at 05:27:09PM +0200, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > 
> > > IVB introduced the CUR_FBC_CTL register which allows reducing the cursor
> > > height down to 8 lines from the otherwise square cursor dimensions.
> > > Implement support for it. CUR_FBC_CTL can't be used when the cursor
> > > is rotated.
> > > 
> > > Commandeer the otherwise unused cursor->cursor.size to track the
> > > current value of CUR_FBC_CTL to optimize away redundant CUR_FBC_CTL
> > > writes, and to notice when we need to arm the update via CURBASE if
> > > just CUR_FBC_CTL changes.
> > 
> > For userspace to discover this, they should just use trial and error
> > during startup (using the legacy SetCursor)? Though the easiest way
> > would cause the cursor to flicker - just hope the cursor is
> > off/invisible on startup.
> 
> I don't have any decent answer for how to discover this feature. Atomic
> would allow the trial and error approach without flickers. Otherwise I
> guess one could defer the check until the cursor size actually changes.
> Although maybe that won't really work for Xorg. ISTR it wants to know
> things about the cursor size upfront?

We resize the cursor on the fly, so we could do a trial-and-error after
a resize. But yes, the old cursor code used a static one-size fits all.

(gem bo alloc is signalsafe, but malloc isn't -- so we just need to make
sure we have a spare slot to create a new cursor in.)
-Chris
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b7ec6636e2a0..c96b667d6e6e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2900,6 +2900,7 @@  intel_info(const struct drm_i915_private *dev_priv)
 #define HAS_FW_BLC(dev_priv) 	(INTEL_GEN(dev_priv) > 2)
 #define HAS_PIPE_CXSR(dev_priv) ((dev_priv)->info.has_pipe_cxsr)
 #define HAS_FBC(dev_priv)	((dev_priv)->info.has_fbc)
+#define HAS_CUR_FBC(dev_priv)	(!HAS_GMCH_DISPLAY(dev_priv) && INTEL_INFO(dev_priv)->gen >= 7)
 
 #define HAS_IPS(dev_priv)	(IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv))
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 07cae03e8727..cfcb139e5952 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -5449,7 +5449,9 @@  enum {
 #define   CURSOR_POS_SIGN       0x8000
 #define   CURSOR_X_SHIFT        0
 #define   CURSOR_Y_SHIFT        16
-#define CURSIZE			_MMIO(0x700a0)
+#define CURSIZE			_MMIO(0x700a0) /* 845/865 */
+#define _CUR_FBC_CTL_A		0x700a0 /* ivb+ */
+#define   CUR_FBC_CTL_EN	(1 << 31)
 #define _CURBCNTR		0x700c0
 #define _CURBBASE		0x700c4
 #define _CURBPOS		0x700c8
@@ -5465,6 +5467,7 @@  enum {
 #define CURCNTR(pipe) _CURSOR2(pipe, _CURACNTR)
 #define CURBASE(pipe) _CURSOR2(pipe, _CURABASE)
 #define CURPOS(pipe) _CURSOR2(pipe, _CURAPOS)
+#define CUR_FBC_CTL(pipe) _CURSOR2(pipe, _CUR_FBC_CTL_A)
 
 #define CURSOR_A_OFFSET 0x70080
 #define CURSOR_B_OFFSET 0x700c0
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 17362dc9f438..13b31e929631 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9347,7 +9347,7 @@  static void i9xx_update_cursor(struct intel_plane *plane,
 {
 	struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 	enum pipe pipe = plane->pipe;
-	u32 cntl = 0, base = 0, pos = 0;
+	u32 cntl = 0, base = 0, pos = 0, size = 0;
 
 	if (plane_state && plane_state->base.visible) {
 		cntl = MCURSOR_GAMMA_ENABLE;
@@ -9376,15 +9376,22 @@  static void i9xx_update_cursor(struct intel_plane *plane,
 
 		base = intel_cursor_base(plane, plane_state);
 		pos = intel_cursor_position(plane, plane_state);
+
+		if (plane_state->base.crtc_h != plane_state->base.crtc_w)
+			size = CUR_FBC_CTL_EN | (plane_state->base.crtc_h - 1);
 	}
 
 	if (plane->cursor.cntl != cntl)
 		I915_WRITE(CURCNTR(pipe), cntl);
 
+	if (plane->cursor.size != size)
+		I915_WRITE(CUR_FBC_CTL(pipe), size);
+
 	if (cntl)
 		I915_WRITE(CURPOS(pipe), pos);
 
 	if (plane->cursor.cntl != cntl ||
+	    plane->cursor.size != size ||
 	    plane->cursor.base != base)
 		I915_WRITE(CURBASE(pipe), base);
 
@@ -9392,6 +9399,7 @@  static void i9xx_update_cursor(struct intel_plane *plane,
 
 	plane->cursor.cntl = cntl;
 	plane->cursor.base = base;
+	plane->cursor.size = size;
 }
 
 static void i9xx_disable_cursor(struct intel_plane *plane,
@@ -9410,11 +9418,8 @@  static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
 	if (width == 0 || height == 0)
 		return false;
 
-	/*
-	 * Cursors are limited to a few power-of-two
-	 * sizes, and they must be square.
-	 */
-	switch (width | height) {
+	/* Cursor width is limited to a few power-of-two sizes */
+	switch (width) {
 	case 256:
 	case 128:
 		if (IS_GEN2(dev_priv))
@@ -9425,6 +9430,21 @@  static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
 		return false;
 	}
 
+	/*
+	 * IVB+ have CUR_FBC_CTL which allows an arbitrary cursor
+	 * height from 8 lines up to the cursor width, when the
+	 * cursor is not rotated. Everything else requires square
+	 * cursors.
+	 */
+	if (HAS_CUR_FBC(dev_priv) &&
+	    plane_state->base.rotation & DRM_ROTATE_0) {
+		if (height < 8 || height > width)
+			return false;
+	} else {
+		if (height != width)
+			return false;
+	}
+
 	return true;
 }
 
@@ -13833,7 +13853,9 @@  intel_cursor_plane_create(struct drm_i915_private *dev_priv,
 
 	cursor->cursor.base = ~0;
 	cursor->cursor.cntl = ~0;
-	cursor->cursor.size = ~0;
+
+	if (IS_I845G(dev_priv) || IS_I865G(dev_priv) || HAS_CUR_FBC(dev_priv))
+		cursor->cursor.size = ~0;
 
 	ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
 				       0, &intel_cursor_plane_funcs,