drm/i915: Split cursor check_plane into i845 and i9xx variants
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 27 Mar 2017 18:55:39 +0000 (21:55 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Wed, 10 May 2017 16:28:25 +0000 (19:28 +0300)
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)
v3: s/DRM_FORMAT_MOD_NONE/DRM_FORMAT_MOD_LINEAR/

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> #v1
Link: http://patchwork.freedesktop.org/patch/msgid/20170327185546.2977-9-ville.syrjala@linux.intel.com
drivers/gpu/drm/i915/intel_display.c

index cb20de08f39d554fb776d093873dd55f88121f3f..ed01632071a66a4998c63f7740fd8693c3893d44 100644 (file)
@@ -9178,6 +9178,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_LINEAR) {
+               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)
 {
@@ -9203,6 +9228,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)
@@ -9298,6 +9385,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)
@@ -9340,42 +9509,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 = {
@@ -13668,73 +13801,6 @@ fail:
        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_LINEAR) {
-               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)
@@ -13763,14 +13829,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;