Signed-off-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx> --- Changes since v1: - Clear intel_crtc->atomic at the start of the check function (paranoia). drivers/gpu/drm/i915/intel_atomic_plane.c | 18 +-- drivers/gpu/drm/i915/intel_display.c | 196 ++++++++++++++++++++---------- drivers/gpu/drm/i915/intel_sprite.c | 25 +--- 3 files changed, 134 insertions(+), 105 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index a27ee8cbb627..4b639b54583d 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -123,8 +123,10 @@ static int intel_plane_atomic_check(struct drm_plane *plane, * anything driver-specific we need to test in that case, so * just return success. */ - if (!crtc) + if (!crtc || !intel_crtc->active || !state->fb) { + intel_state->visible = 0; return 0; + } /* * The original src/dest coordinates are stored in state->base, but @@ -148,20 +150,6 @@ static int intel_plane_atomic_check(struct drm_plane *plane, intel_state->clip.y2 = intel_crtc->active ? intel_crtc->config->pipe_src_h : 0; - /* - * Disabling a plane is always okay; we just need to update - * fb tracking in a special way since cleanup_fb() won't - * get called by the plane helpers. - */ - if (state->fb == NULL && plane->state->fb != NULL) { - /* - * 'prepare' is never called when plane is being disabled, so - * we need to handle frontbuffer tracking as a special case - */ - intel_crtc->atomic.disabled_planes |= - (1 << drm_plane_index(plane)); - } - if (state->fb && intel_rotation_90_or_270(state->rotation)) { if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) { diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 61a29f142c70..4965743053b1 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -101,6 +101,8 @@ static void vlv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); static void chv_prepare_pll(struct intel_crtc *crtc, const struct intel_crtc_state *pipe_config); +static int intel_atomic_check_crtc(struct drm_crtc *crtc, + struct drm_crtc_state *crtc_state); static void intel_begin_crtc_commit(struct drm_crtc *crtc); static void intel_finish_crtc_commit(struct drm_crtc *crtc); static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc, @@ -10656,6 +10658,7 @@ static struct drm_crtc_helper_funcs intel_helper_funcs = { .load_lut = intel_crtc_load_lut, .atomic_begin = intel_begin_crtc_commit, .atomic_flush = intel_finish_crtc_commit, + .atomic_check = intel_atomic_check_crtc, }; /** @@ -12783,6 +12786,9 @@ bool intel_wm_need_update(struct drm_plane *plane, plane->state->rotation != state->rotation) return true; + if (plane->type == DRM_PLANE_TYPE_CURSOR) + return plane->state->crtc_w != state->crtc_w; + return false; } @@ -12877,7 +12883,6 @@ intel_check_primary_plane(struct drm_plane *plane, struct intel_plane_state *state) { struct drm_device *dev = plane->dev; - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = state->base.crtc; struct intel_crtc *intel_crtc; struct drm_framebuffer *fb = state->base.fb; @@ -12885,7 +12890,6 @@ intel_check_primary_plane(struct drm_plane *plane, struct drm_rect *src = &state->src; const struct drm_rect *clip = &state->clip; bool can_position = false; - int ret; crtc = crtc ? crtc : plane->crtc; intel_crtc = to_intel_crtc(crtc); @@ -12893,58 +12897,12 @@ intel_check_primary_plane(struct drm_plane *plane, if (INTEL_INFO(dev)->gen >= 9) can_position = true; - ret = drm_plane_helper_check_update(plane, crtc, fb, - src, dest, clip, - DRM_PLANE_HELPER_NO_SCALING, - DRM_PLANE_HELPER_NO_SCALING, - can_position, true, - &state->visible); - if (ret) - return ret; - - if (intel_crtc->active) { - struct intel_plane_state *old_state = - to_intel_plane_state(plane->state); - - intel_crtc->atomic.wait_for_flips = true; - - /* - * FBC does not work on some platforms for rotated - * planes, so disable it when rotation is not 0 and - * update it when rotation is set back to 0. - * - * FIXME: This is redundant with the fbc update done in - * the primary plane enable function except that that - * one is done too late. We eventually need to unify - * this. - */ - if (state->visible && - INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && - dev_priv->fbc.crtc == intel_crtc && - state->base.rotation != BIT(DRM_ROTATE_0)) { - intel_crtc->atomic.disable_fbc = true; - } - - if (state->visible && !old_state->visible) { - /* - * BDW signals flip done immediately if the plane - * is disabled, even if the plane enable is already - * armed to occur at the next vblank :( - */ - if (IS_BROADWELL(dev)) - intel_crtc->atomic.wait_vblank = true; - } - - intel_crtc->atomic.fb_bits |= - INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); - - intel_crtc->atomic.update_fbc = true; - - if (intel_wm_need_update(plane, &state->base)) - intel_crtc->atomic.update_wm = true; - } - - return 0; + return drm_plane_helper_check_update(plane, crtc, fb, + src, dest, clip, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + can_position, true, + &state->visible); } static void @@ -12986,6 +12944,121 @@ intel_disable_primary_plane(struct drm_plane *plane, dev_priv->display.update_primary_plane(crtc, NULL, 0, 0); } +/* Transitional checking here, mostly for plane updates */ +static int intel_atomic_check_crtc(struct drm_crtc *crtc, + struct drm_crtc_state *crtc_state) +{ + struct intel_crtc_state *pipe_config = to_intel_crtc_state(crtc_state); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_atomic_state *state = crtc_state->state; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned plane_mask; + int i, nplanes = dev->mode_config.num_total_plane; + bool mode_changed = crtc_state->mode_changed; + + if (!crtc_state->planes_changed) + return 0; + + if (!intel_crtc->active) + return 0; + + memset(&intel_crtc->atomic, 0, sizeof(intel_crtc->atomic)); + intel_crtc->atomic.update_wm = mode_changed; + + DRM_DEBUG_ATOMIC("Crtc %i was enabled %i now enabled: %i\n", drm_crtc_index(crtc), crtc->state->enable, crtc_state->enable); + + plane_mask = crtc_state->plane_mask | crtc->state->plane_mask; + for (i = 0; i < nplanes; i++) { + struct intel_plane_state *plane_state, *old_plane_state; + struct intel_plane *plane = to_intel_plane(state->planes[i]); + bool turn_off, turn_on, visible, was_visible; + + if (!plane) + continue; + + plane_state = to_intel_plane_state(state->plane_states[i]); + old_plane_state = to_intel_plane_state(plane->base.state); + + was_visible = old_plane_state->visible && crtc->state->enable; + visible = plane_state->visible && crtc_state->enable; + + turn_off = was_visible && (!visible || mode_changed); + turn_on = visible && (!was_visible || mode_changed); + + DRM_DEBUG_ATOMIC("Plane %i with fb %p and crtc %p, was_visible %i, visible %i, turn_off %i, turn_on %i, modeset: %i\n", + i, plane_state->base.fb, plane_state->base.crtc, was_visible, visible, turn_off, turn_on, mode_changed); + + /* plane being turned off as part of modeset or changes? */ + if (intel_wm_need_update(&plane->base, &plane_state->base)) + intel_crtc->atomic.update_wm = true; + + if (old_plane_state->base.fb && !plane_state->base.fb) + /* + * 'prepare' is never called when plane is being disabled, so + * we need to handle frontbuffer tracking as a special case + */ + intel_crtc->atomic.disabled_planes |= + (1 << drm_plane_index(&plane->base)); + + switch (plane->base.type) { + case DRM_PLANE_TYPE_PRIMARY: + intel_crtc->atomic.fb_bits |= + INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe); + + intel_crtc->atomic.wait_for_flips = true; + intel_crtc->atomic.pre_disable_primary = turn_off; + intel_crtc->atomic.post_enable_primary = turn_on; + + if (turn_off) + intel_crtc->atomic.disable_fbc = true; + + /* + * FBC does not work on some platforms for rotated + * planes, so disable it when rotation is not 0 and + * update it when rotation is set back to 0. + * + * FIXME: This is redundant with the fbc update done in + * the primary plane enable function except that that + * one is done too late. We eventually need to unify + * this. + */ + + if (visible && + INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev) && + dev_priv->fbc.crtc == intel_crtc && + plane_state->base.rotation != BIT(DRM_ROTATE_0)) + intel_crtc->atomic.disable_fbc = true; + + /* + * BDW signals flip done immediately if the plane + * is disabled, even if the plane enable is already + * armed to occur at the next vblank :( + */ + if (turn_on && IS_BROADWELL(dev)) + intel_crtc->atomic.wait_vblank = true; + + intel_crtc->atomic.update_fbc = true; + break; + case DRM_PLANE_TYPE_CURSOR: + intel_crtc->atomic.fb_bits |= + INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe); + break; + case DRM_PLANE_TYPE_OVERLAY: + intel_crtc->atomic.fb_bits |= + INTEL_FRONTBUFFER_SPRITE(intel_crtc->pipe); + + if (turn_off) { + intel_crtc->atomic.wait_vblank = true; + intel_crtc->atomic.update_sprite_watermarks |= + (1 << drm_plane_index(&plane->base)); + } + break; + } + } + return 0; +} + static void intel_begin_crtc_commit(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -13200,7 +13273,7 @@ intel_check_cursor_plane(struct drm_plane *plane, /* if we want to turn off the cursor ignore width and height */ if (!obj) - goto finish; + return 0; /* Check for which cursor types we support */ if (!cursor_size_ok(dev, state->base.crtc_w, state->base.crtc_h)) { @@ -13217,19 +13290,10 @@ intel_check_cursor_plane(struct drm_plane *plane, if (fb->modifier[0] != DRM_FORMAT_MOD_NONE) { DRM_DEBUG_KMS("cursor cannot be tiled\n"); - ret = -EINVAL; - } - -finish: - if (intel_crtc->active) { - if (plane->state->crtc_w != state->base.crtc_w) - intel_crtc->atomic.update_wm = true; - - intel_crtc->atomic.fb_bits |= - INTEL_FRONTBUFFER_CURSOR(intel_crtc->pipe); + return -EINVAL; } - return ret; + return 0; } static void diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 7419e04b113f..9cf35c33bc61 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -815,7 +815,7 @@ intel_check_sprite_plane(struct drm_plane *plane, if (!fb) { state->visible = false; - goto finish; + return 0; } /* Don't modify another pipe's plane */ @@ -952,29 +952,6 @@ intel_check_sprite_plane(struct drm_plane *plane, dst->y1 = crtc_y; dst->y2 = crtc_y + crtc_h; -finish: - /* - * If the sprite is completely covering the primary plane, - * we can disable the primary and save power. - */ - if (intel_crtc->active) { - intel_crtc->atomic.fb_bits |= - INTEL_FRONTBUFFER_SPRITE(intel_crtc->pipe); - - if (intel_wm_need_update(plane, &state->base)) - intel_crtc->atomic.update_wm = true; - - if (!state->visible) { - /* - * Avoid underruns when disabling the sprite. - * FIXME remove once watermark updates are done properly. - */ - intel_crtc->atomic.wait_vblank = true; - intel_crtc->atomic.update_sprite_watermarks |= - (1 << drm_plane_index(plane)); - } - } - return 0; } -- 2.1.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx