Read out the initial state, and add a quirk to force disable all plane
that were initially active. Use this to disable planes during modeset
too.

Signed-off-by: Maarten Lankhorst <maarten.lankho...@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_atomic.c  |   7 ++
 drivers/gpu/drm/i915/intel_display.c | 139 +++++++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_drv.h     |   7 ++
 3 files changed, 114 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 8447a1fef332..5627df2807b0 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -96,6 +96,13 @@ int intel_atomic_check(struct drm_device *dev,
                return -EINVAL;
        }
 
+       if (crtc_state &&
+           crtc_state->quirks & PIPE_CONFIG_QUIRK_INHERITED_MODE) {
+               ret = drm_atomic_add_affected_planes(state, 
&nuclear_crtc->base);
+               if (ret)
+                       return ret;
+       }
+
        ret = drm_atomic_helper_check_planes(dev, state);
        if (ret)
                return ret;
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index b72724121f57..3b5d23692935 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4830,11 +4830,20 @@ static void intel_crtc_enable_planes(struct drm_crtc 
*crtc)
        intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_ALL_MASK(pipe));
 }
 
+static void intel_disable_planes_on_crtc(struct drm_crtc *c)
+{
+       struct intel_crtc *crtc = to_intel_crtc(c);
+       struct drm_plane *plane;
+
+       drm_for_each_plane_mask(plane, crtc->base.dev,
+                               crtc->atomic.force_disabled_planes)
+               to_intel_plane(plane)->disable_plane(plane, c);
+}
+
 static void intel_crtc_disable_planes(struct drm_crtc *crtc)
 {
        struct drm_device *dev = crtc->dev;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-       struct intel_plane *intel_plane;
        int pipe = intel_crtc->pipe;
 
        intel_crtc_wait_for_pending_flips(crtc);
@@ -4842,14 +4851,7 @@ static void intel_crtc_disable_planes(struct drm_crtc 
*crtc)
        intel_pre_disable_primary(crtc);
 
        intel_crtc_dpms_overlay_disable(intel_crtc);
-       for_each_intel_plane(dev, intel_plane) {
-               if (intel_plane->pipe == pipe) {
-                       struct drm_crtc *from = intel_plane->base.crtc;
-
-                       intel_plane->disable_plane(&intel_plane->base,
-                                                  from ?: crtc);
-               }
-       }
+       intel_disable_planes_on_crtc(crtc);
 
        /*
         * FIXME: Once we grow proper nuclear flip support out of this we need
@@ -11554,6 +11556,21 @@ int intel_plane_atomic_calc_changes(struct 
drm_crtc_state *crtc_state,
        if (!intel_crtc->active || mode_changed)
                return 0;
 
+       if (to_intel_crtc_state(crtc_state)->quirks &
+           PIPE_CONFIG_QUIRK_INITIAL_PLANES) {
+               if (!plane_state->crtc) {
+                       intel_crtc->atomic.force_disabled_planes |=
+                               1 << drm_plane_index(plane);
+                       crtc_state->plane_mask &=
+                               ~(1 << drm_plane_index(plane));
+               }
+
+               /* Initial state for sprite planes is unknown,
+                * no need to update sprite watermarks */
+               if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+                       mode_changed = true;
+       }
+
        was_visible = old_plane_state->visible;
        visible = to_intel_plane_state(plane_state)->visible;
 
@@ -11633,7 +11650,7 @@ int intel_plane_atomic_calc_changes(struct 
drm_crtc_state *crtc_state,
                        intel_crtc->atomic.fb_bits |=
                            INTEL_FRONTBUFFER_SPRITE(intel_crtc->pipe);
 
-               if (turn_off && is_crtc_enabled) {
+               if (turn_off && !mode_changed) {
                        intel_crtc->atomic.wait_vblank = true;
                        intel_crtc->atomic.update_sprite_watermarks |=
                                1 << i;
@@ -11714,6 +11731,11 @@ static int intel_crtc_atomic_check(struct drm_crtc 
*crtc,
                "[CRTC:%i] mismatch between state->active(%i) and 
crtc->active(%i)\n",
                idx, crtc->state->active, intel_crtc->active);
 
+       /* plane mask is fixed up after all initial planes are calculated */
+       pipe_config->quirks &= ~PIPE_CONFIG_QUIRK_INITIAL_PLANES;
+       if (mode_changed)
+               intel_crtc->atomic.force_disabled_planes = 
crtc->state->plane_mask;
+
        if (mode_changed && crtc_state->enable &&
            dev_priv->display.crtc_compute_clock &&
            !WARN_ON(pipe_config->shared_dpll != DPLL_ID_PRIVATE)) {
@@ -12883,6 +12905,13 @@ intel_modeset_compute_config(struct drm_atomic_state 
*state)
                return ret;
 
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               if (to_intel_crtc_state(crtc_state)->quirks &
+                   PIPE_CONFIG_QUIRK_INITIAL_PLANES) {
+                       ret = drm_atomic_add_affected_planes(state, crtc);
+                       if (ret)
+                               return ret;
+               }
+
                if (!needs_modeset(crtc_state))
                        continue;
 
@@ -13529,13 +13558,17 @@ static void intel_begin_crtc_commit(struct drm_crtc 
*crtc)
        intel_runtime_pm_get(dev_priv);
 
        /* Perform vblank evasion around commit operation */
-       if (crtc->state->active && !needs_modeset(crtc->state))
+       if (crtc->state->active && !needs_modeset(crtc->state)) {
                intel_crtc->atomic.evade =
                        intel_pipe_update_start(intel_crtc,
                                                
&intel_crtc->atomic.start_vbl_count);
 
+               if (intel_crtc->atomic.force_disabled_planes)
+                       intel_disable_planes_on_crtc(crtc);
+       }
+
        if (!needs_modeset(crtc->state) && INTEL_INFO(dev)->gen >= 9)
-               skl_detach_scalers(intel_crtc);
+                skl_detach_scalers(intel_crtc);
 }
 
 static void intel_finish_crtc_commit(struct drm_crtc *crtc)
@@ -15040,14 +15073,63 @@ void i915_redisable_vga(struct drm_device *dev)
        i915_redisable_vga_power_on(dev);
 }
 
-static bool primary_get_hw_state(struct intel_crtc *crtc)
+static bool intel_read_hw_plane_state(struct intel_crtc *crtc,
+                                     struct intel_plane *intel_plane)
 {
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct drm_device *dev = crtc->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
-       if (!crtc->base.enabled)
-               return false;
+       switch (intel_plane->base.type) {
+       case DRM_PLANE_TYPE_PRIMARY:
+               return I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE;
+
+       case DRM_PLANE_TYPE_CURSOR:
+               if (IS_845G(dev) || IS_I865G(dev))
+                       return I915_READ(_CURACNTR) & CURSOR_ENABLE;
+               else
+                       return I915_READ(CURCNTR(crtc->plane)) & CURSOR_MODE;
+
+       default:
+               return true;
+       }
+}
+
+static int readout_plane_state(struct drm_atomic_state *state,
+                              struct intel_crtc *crtc,
+                              struct intel_crtc_state *crtc_state)
+{
+       struct intel_plane *p;
+       struct drm_plane_state *drm_plane_state;
+       bool active = crtc_state->base.active;
+
+       if (active) {
+               crtc_state->quirks |= PIPE_CONFIG_QUIRK_INITIAL_PLANES;
 
-       return I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE;
+               /* apply to previous sw state too */
+               to_intel_crtc_state(crtc->base.state)->quirks |=
+                       PIPE_CONFIG_QUIRK_INITIAL_PLANES;
+       }
+
+       for_each_intel_plane(state->dev, p) {
+               if (crtc->plane != p->plane)
+                       continue;
+
+               drm_plane_state = drm_atomic_get_plane_state(state, &p->base);
+               if (IS_ERR(drm_plane_state))
+                       return PTR_ERR(drm_plane_state);
+
+               if (active && intel_read_hw_plane_state(crtc, p)) {
+                       to_intel_plane_state(drm_plane_state)->visible = true;
+                       crtc_state->base.plane_mask |= 1 << 
drm_plane_index(&p->base);
+                       p->base.crtc = &crtc->base;
+               } else {
+                       to_intel_plane_state(drm_plane_state)->visible = false;
+                       crtc_state->base.plane_mask &= ~(1 << 
drm_plane_index(&p->base));
+                       p->base.crtc = drm_plane_state->crtc;
+               }
+       }
+
+       return 0;
 }
 
 static int readout_hw_crtc_state(struct drm_atomic_state *state,
@@ -15055,19 +15137,11 @@ static int readout_hw_crtc_state(struct 
drm_atomic_state *state,
 {
        struct drm_i915_private *dev_priv = to_i915(state->dev);
        struct intel_crtc_state *crtc_state;
-       struct drm_plane *primary = crtc->base.primary;
-       struct drm_plane_state *drm_plane_state;
-       struct intel_plane_state *plane_state;
-       int ret;
 
        crtc_state = intel_atomic_get_crtc_state(state, crtc);
        if (IS_ERR(crtc_state))
                return PTR_ERR(crtc_state);
 
-       ret = drm_atomic_add_affected_planes(state, &crtc->base);
-       if (ret)
-               return ret;
-
        memset(crtc_state, 0, sizeof(*crtc_state));
        crtc_state->base.crtc = &crtc->base;
        crtc_state->base.state = state;
@@ -15081,24 +15155,11 @@ static int readout_hw_crtc_state(struct 
drm_atomic_state *state,
        crtc->active = crtc_state->base.active;
        crtc->config = crtc_state;
 
-       drm_plane_state = drm_atomic_get_plane_state(state, primary);
-       if (IS_ERR(drm_plane_state))
-               return PTR_ERR(drm_plane_state);
-
-       plane_state = to_intel_plane_state(drm_plane_state);
-       plane_state->visible = primary_get_hw_state(crtc);
-
-       if (plane_state->visible) {
-               primary->crtc = &crtc->base;
-               crtc_state->base.plane_mask |= 1 << drm_plane_index(primary);
-       } else
-               crtc_state->base.plane_mask &= ~(1 << drm_plane_index(primary));
-
        DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
                      crtc->base.base.id,
                      crtc_state->base.active ? "enabled" : "disabled");
 
-       return 0;
+       return readout_plane_state(state, crtc, crtc_state);
 }
 
 static int readout_hw_pll_state(struct drm_atomic_state *state)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d96c9a24b94b..7b1a13f63872 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -327,6 +327,7 @@ struct intel_crtc_state {
         */
 #define PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS      (1<<0) /* unreliable sync 
mode.flags */
 #define PIPE_CONFIG_QUIRK_INHERITED_MODE       (1<<1) /* mode inherited from 
firmware */
+#define PIPE_CONFIG_QUIRK_INITIAL_PLANES       (1<<2) /* planes are in unknown 
state */
        unsigned long quirks;
 
        /* Pipe source size (ie. panel fitter input size)
@@ -485,8 +486,14 @@ struct intel_crtc_atomic_commit {
        bool disable_fbc;
        bool pre_disable_primary;
        bool update_wm;
+
+       /* planes that will be disabled in a normal way */
        unsigned disabled_planes;
 
+       /* planes that will be disabled during modeset,
+        * or initially enabled planes */
+       unsigned force_disabled_planes;
+
        /* Sleepable operations to perform after commit */
        unsigned fb_bits;
        bool wait_vblank;
-- 
2.1.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to