[Intel-gfx] [PATCH v2 08/15] drm/i915: Split cursor check_plane into i845 and i9xx variants
ville.syrjala at linux.intel.com
ville.syrjala at linux.intel.com
Mon Mar 27 18:55:39 UTC 2017
From: Ville Syrjälä <ville.syrjala at linux.intel.com>
The 845/865 and 830/855/9xx+ style cursor don't have that
much in common with each other, so let's just split the
.check_plane() hook into two variants as well.
v2: Keep the common stuff in one place (Chris)
Cc: Chris Wilson <chris at chris-wilson.co.uk>
Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk> #v1
---
drivers/gpu/drm/i915/intel_display.c | 275 ++++++++++++++++++++++-------------
1 file changed, 171 insertions(+), 104 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bba763b03d28..774f9668076f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9169,6 +9169,31 @@ static u32 intel_cursor_position(const struct intel_plane_state *plane_state)
return pos;
}
+static int intel_check_cursor(struct intel_crtc_state *crtc_state,
+ struct intel_plane_state *plane_state)
+{
+ const struct drm_framebuffer *fb = plane_state->base.fb;
+ int ret;
+
+ ret = drm_plane_helper_check_state(&plane_state->base,
+ &plane_state->clip,
+ DRM_PLANE_HELPER_NO_SCALING,
+ DRM_PLANE_HELPER_NO_SCALING,
+ true, true);
+ if (ret)
+ return ret;
+
+ if (!fb)
+ return 0;
+
+ if (fb->modifier != DRM_FORMAT_MOD_NONE) {
+ DRM_DEBUG_KMS("cursor cannot be tiled\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
{
@@ -9194,6 +9219,68 @@ static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
CURSOR_STRIDE(stride);
}
+static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
+{
+ struct drm_i915_private *dev_priv =
+ to_i915(plane_state->base.plane->dev);
+ int width = plane_state->base.crtc_w;
+ int height = plane_state->base.crtc_h;
+
+ if (width == 0 || height == 0)
+ return false;
+
+ /*
+ * 845g/865g are only limited by the width of their cursors,
+ * the height is arbitrary up to the precision of the register.
+ */
+ if (!IS_ALIGNED(width, 64))
+ return false;
+
+ if (width > (IS_I845G(dev_priv) ? 64 : 512))
+ return false;
+
+ if (height > 1023)
+ return false;
+
+ return true;
+}
+
+static int i845_check_cursor(struct intel_plane *plane,
+ struct intel_crtc_state *crtc_state,
+ struct intel_plane_state *plane_state)
+{
+ const struct drm_framebuffer *fb = plane_state->base.fb;
+ const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+ unsigned int stride;
+ int ret;
+
+ ret = intel_check_cursor(crtc_state, plane_state);
+ if (ret)
+ return ret;
+
+ /* if we want to turn off the cursor ignore width and height */
+ if (!obj)
+ return 0;
+
+ /* Check for which cursor types we support */
+ if (!i845_cursor_size_ok(plane_state)) {
+ DRM_DEBUG("Cursor dimension %dx%d not supported\n",
+ plane_state->base.crtc_w,
+ plane_state->base.crtc_h);
+ return -EINVAL;
+ }
+
+ stride = roundup_pow_of_two(plane_state->base.crtc_w) * 4;
+ if (obj->base.size < stride * plane_state->base.crtc_h) {
+ DRM_DEBUG_KMS("buffer is too small\n");
+ return -ENOMEM;
+ }
+
+ plane_state->ctl = i845_cursor_ctl(crtc_state, plane_state);
+
+ return 0;
+}
+
static void i845_update_cursor(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
@@ -9289,6 +9376,88 @@ static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
return cntl;
}
+static bool i9xx_cursor_size_ok(const struct intel_plane_state *plane_state)
+{
+ struct drm_i915_private *dev_priv =
+ to_i915(plane_state->base.plane->dev);
+ int width = plane_state->base.crtc_w;
+ int height = plane_state->base.crtc_h;
+
+ 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) {
+ case 256:
+ case 128:
+ if (IS_GEN2(dev_priv))
+ return false;
+ case 64:
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+static int i9xx_check_cursor(struct intel_plane *plane,
+ struct intel_crtc_state *crtc_state,
+ struct intel_plane_state *plane_state)
+{
+ struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+ const struct drm_framebuffer *fb = plane_state->base.fb;
+ const struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+ enum pipe pipe = plane->pipe;
+ unsigned int stride;
+ int ret;
+
+ ret = intel_check_cursor(crtc_state, plane_state);
+ if (ret)
+ return ret;
+
+ /* if we want to turn off the cursor ignore width and height */
+ if (!obj)
+ return 0;
+
+ /* Check for which cursor types we support */
+ if (!i9xx_cursor_size_ok(plane_state)) {
+ DRM_DEBUG("Cursor dimension %dx%d not supported\n",
+ plane_state->base.crtc_w,
+ plane_state->base.crtc_h);
+ return -EINVAL;
+ }
+
+ stride = roundup_pow_of_two(plane_state->base.crtc_w) * 4;
+ if (obj->base.size < stride * plane_state->base.crtc_h) {
+ DRM_DEBUG_KMS("buffer is too small\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * There's something wrong with the cursor on CHV pipe C.
+ * If it straddles the left edge of the screen then
+ * moving it away from the edge or disabling it often
+ * results in a pipe underrun, and often that can lead to
+ * dead pipe (constant underrun reported, and it scans
+ * out just a solid color). To recover from that, the
+ * display power well must be turned off and on again.
+ * Refuse the put the cursor into that compromised position.
+ */
+ if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
+ plane_state->base.visible && plane_state->base.crtc_x < 0) {
+ DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
+ return -EINVAL;
+ }
+
+ plane_state->ctl = i9xx_cursor_ctl(crtc_state, plane_state);
+
+ return 0;
+}
+
static void i9xx_update_cursor(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state)
@@ -9331,42 +9500,6 @@ static void i9xx_disable_cursor(struct intel_plane *plane,
i9xx_update_cursor(plane, NULL, NULL);
}
-static bool cursor_size_ok(struct drm_i915_private *dev_priv,
- uint32_t width, uint32_t height)
-{
- if (width == 0 || height == 0)
- return false;
-
- /*
- * 845g/865g are special in that they are only limited by
- * the width of their cursors, the height is arbitrary up to
- * the precision of the register. Everything else requires
- * square cursors, limited to a few power-of-two sizes.
- */
- if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
- if ((width & 63) != 0)
- return false;
-
- if (width > (IS_I845G(dev_priv) ? 64 : 512))
- return false;
-
- if (height > 1023)
- return false;
- } else {
- switch (width | height) {
- case 256:
- case 128:
- if (IS_GEN2(dev_priv))
- return false;
- case 64:
- break;
- default:
- return false;
- }
- }
-
- return true;
-}
/* VESA 640x480x72Hz mode to set on the pipe */
static struct drm_display_mode load_detect_mode = {
@@ -13690,73 +13823,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
return ERR_PTR(ret);
}
-static int
-intel_check_cursor_plane(struct intel_plane *plane,
- struct intel_crtc_state *crtc_state,
- struct intel_plane_state *state)
-{
- struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
- const struct drm_framebuffer *fb = state->base.fb;
- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
- enum pipe pipe = plane->pipe;
- unsigned stride;
- int ret;
-
- ret = drm_plane_helper_check_state(&state->base,
- &state->clip,
- DRM_PLANE_HELPER_NO_SCALING,
- DRM_PLANE_HELPER_NO_SCALING,
- true, true);
- if (ret)
- return ret;
-
- /* if we want to turn off the cursor ignore width and height */
- if (!obj)
- return 0;
-
- /* Check for which cursor types we support */
- if (!cursor_size_ok(dev_priv, state->base.crtc_w,
- state->base.crtc_h)) {
- DRM_DEBUG("Cursor dimension %dx%d not supported\n",
- state->base.crtc_w, state->base.crtc_h);
- return -EINVAL;
- }
-
- stride = roundup_pow_of_two(state->base.crtc_w) * 4;
- if (obj->base.size < stride * state->base.crtc_h) {
- DRM_DEBUG_KMS("buffer is too small\n");
- return -ENOMEM;
- }
-
- if (fb->modifier != DRM_FORMAT_MOD_NONE) {
- DRM_DEBUG_KMS("cursor cannot be tiled\n");
- return -EINVAL;
- }
-
- /*
- * There's something wrong with the cursor on CHV pipe C.
- * If it straddles the left edge of the screen then
- * moving it away from the edge or disabling it often
- * results in a pipe underrun, and often that can lead to
- * dead pipe (constant underrun reported, and it scans
- * out just a solid color). To recover from that, the
- * display power well must be turned off and on again.
- * Refuse the put the cursor into that compromised position.
- */
- if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_C &&
- state->base.visible && state->base.crtc_x < 0) {
- DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
- return -EINVAL;
- }
-
- if (IS_I845G(dev_priv) || IS_I865G(dev_priv))
- state->ctl = i845_cursor_ctl(crtc_state, state);
- else
- state->ctl = i9xx_cursor_ctl(crtc_state, state);
-
- return 0;
-}
-
static struct intel_plane *
intel_cursor_plane_create(struct drm_i915_private *dev_priv,
enum pipe pipe)
@@ -13785,14 +13851,15 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
cursor->plane = pipe;
cursor->id = PLANE_CURSOR;
cursor->frontbuffer_bit = INTEL_FRONTBUFFER_CURSOR(pipe);
- cursor->check_plane = intel_check_cursor_plane;
if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
cursor->update_plane = i845_update_cursor;
cursor->disable_plane = i845_disable_cursor;
+ cursor->check_plane = i845_check_cursor;
} else {
cursor->update_plane = i9xx_update_cursor;
cursor->disable_plane = i9xx_disable_cursor;
+ cursor->check_plane = i9xx_check_cursor;
}
cursor->cursor.base = ~0;
--
2.10.2
More information about the Intel-gfx
mailing list