From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> 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. Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/i915/intel_display.c | 232 ++++++++++++++++++++++------------- 1 file changed, 145 insertions(+), 87 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 222f54ffd113..41cbaee66f1b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9269,6 +9269,74 @@ static void i845_disable_cursor(struct intel_plane *plane, i845_update_cursor(plane, NULL, NULL); } +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 ((width & 63) != 0) + 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 *state) +{ + struct drm_framebuffer *fb = state->base.fb; + struct drm_i915_gem_object *obj = intel_fb_obj(fb); + 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 (!i845_cursor_size_ok(state)) { + 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; + } + + 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) @@ -9328,41 +9396,92 @@ 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) +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; /* - * 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. + * Cursors are limited to a few power-of-two + * sizes, and they must be square. */ - if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) { - if ((width & 63) != 0) + switch (width | height) { + case 256: + case 128: + if (IS_GEN2(dev_priv)) return false; + case 64: + break; + default: + return false; + } - if (width > (IS_I845G(dev_priv) ? 64 : 512)) - return false; + return true; +} - 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; - } +static int i9xx_check_cursor(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); + 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 (!i9xx_cursor_size_ok(state)) { + DRM_DEBUG("Cursor dimension %dx%d not supported\n", + state->base.crtc_w, state->base.crtc_h); + return -EINVAL; } - return true; + 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; + } + + return 0; } /* VESA 640x480x72Hz mode to set on the pipe */ @@ -13671,68 +13790,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); - 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; - } - - return 0; -} - static struct intel_plane * intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) @@ -13761,14 +13818,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 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx