Always read out plane state, and do an initial modeset in modeset_gem_init.

---
 drivers/gpu/drm/i915/i915_dma.c      |  12 +-
 drivers/gpu/drm/i915/i915_drv.c      |   2 +-
 drivers/gpu/drm/i915/i915_drv.h      |   7 +-
 drivers/gpu/drm/i915/intel_atomic.c  |   7 -
 drivers/gpu/drm/i915/intel_display.c | 501 ++++++++++++++++++-----------------
 drivers/gpu/drm/i915/intel_drv.h     |   3 +-
 drivers/gpu/drm/i915/intel_fbdev.c   |  12 +-
 drivers/gpu/drm/i915/intel_lvds.c    |   2 +-
 8 files changed, 280 insertions(+), 266 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 88795d2f1819..ede07f6fe7f7 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -393,6 +393,7 @@ static const struct vga_switcheroo_client_ops 
i915_switcheroo_ops = {
 static int i915_load_modeset_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_atomic_state *state;
        int ret;
 
        ret = intel_parse_bios(dev);
@@ -431,13 +432,18 @@ static int i915_load_modeset_init(struct drm_device *dev)
 
        /* Important: The output setup functions called by modeset_init need
         * working irqs for e.g. gmbus and dp aux transfers. */
-       intel_modeset_init(dev);
+       state = intel_modeset_init(dev);
 
        ret = i915_gem_init(dev);
-       if (ret)
+       if (ret) {
+               if (state) {
+                       drm_atomic_state_free(state);
+                       drm_modeset_unlock_all(dev);
+               }
                goto cleanup_irq;
+       }
 
-       intel_modeset_gem_init(dev);
+       intel_modeset_gem_init(dev, state);
 
        /* Always safe in the mode setting case. */
        /* FIXME: do pre/post-mode set stuff in core KMS code */
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 78ef0bb53c36..a29b24bca25e 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -758,7 +758,7 @@ static int i915_drm_resume(struct drm_device *dev)
        spin_unlock_irq(&dev_priv->irq_lock);
 
        drm_modeset_lock_all(dev);
-       intel_modeset_setup_hw_state(dev, true);
+       intel_display_resume(dev);
        drm_modeset_unlock_all(dev);
 
        intel_dp_mst_resume(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d9410bd4ab59..e67d2f1e3ab8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3233,13 +3233,12 @@ static inline void intel_unregister_dsm_handler(void) { 
return; }
 
 /* modesetting */
 extern void intel_modeset_init_hw(struct drm_device *dev);
-extern void intel_modeset_init(struct drm_device *dev);
-extern void intel_modeset_gem_init(struct drm_device *dev);
+extern struct drm_atomic_state *intel_modeset_init(struct drm_device *dev);
+extern void intel_modeset_gem_init(struct drm_device *dev, struct 
drm_atomic_state *);
 extern void intel_modeset_cleanup(struct drm_device *dev);
 extern void intel_connector_unregister(struct intel_connector *);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
-extern void intel_modeset_setup_hw_state(struct drm_device *dev,
-                                        bool force_restore);
+extern void intel_display_resume(struct drm_device *dev);
 extern void i915_redisable_vga(struct drm_device *dev);
 extern void i915_redisable_vga_power_on(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
diff --git a/drivers/gpu/drm/i915/intel_atomic.c 
b/drivers/gpu/drm/i915/intel_atomic.c
index 4d87574a2032..f36fcc7ceecb 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -98,13 +98,6 @@ int intel_atomic_check(struct drm_device *dev,
                return -EINVAL;
        }
 
-       if (crtc_state &&
-           crtc_state->quirks & PIPE_CONFIG_QUIRK_INITIAL_PLANES) {
-               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 41193dab58c5..9b2acc7b4e29 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -109,6 +109,9 @@ static void skl_init_scalers(struct drm_device *dev, struct 
intel_crtc *intel_cr
        struct intel_crtc_state *crtc_state);
 static int i9xx_get_refclk(const struct intel_crtc_state *crtc_state,
                           int num_connectors);
+static void intel_pre_disable_primary(struct drm_crtc *crtc);
+static struct drm_atomic_state *
+intel_modeset_setup_hw_state(struct drm_device *dev, bool force_restore);
 
 static struct intel_encoder *intel_find_encoder(struct intel_connector 
*connector, int pipe)
 {
@@ -2567,40 +2570,41 @@ update_state_fb(struct drm_plane *plane)
 
 static void
 intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
-                            struct intel_initial_plane_config *plane_config)
+                            struct intel_initial_plane_config *plane_config,
+                            struct intel_plane_state *plane_state)
 {
+       struct drm_atomic_state *state = plane_state->base.state;
        struct drm_device *dev = intel_crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_crtc *c;
-       struct intel_crtc *i;
        struct drm_i915_gem_object *obj;
-       struct drm_plane *primary = intel_crtc->base.primary;
        struct drm_framebuffer *fb;
+       struct drm_plane *plane = plane_state->base.plane, *drm_plane;
+       struct drm_plane_state *drm_plane_state;
+       int i, ret;
 
        if (!plane_config->fb)
                return;
 
        if (intel_alloc_initial_plane_obj(intel_crtc, plane_config)) {
-               fb = &plane_config->fb->base;
-               goto valid_fb;
-       }
+               int ret;
 
-       kfree(plane_config->fb);
+               fb = &plane_config->fb->base;
+               ret = intel_pin_and_fence_fb_obj(plane, fb, &plane_state->base, 
NULL);
+               if (!ret)
+                       goto valid_fb;
+               drm_framebuffer_unreference(fb);
+       } else
+               kfree(plane_config->fb);
 
        /*
         * Failed to alloc the obj, check to see if we should share
         * an fb with another CRTC instead
         */
-       for_each_crtc(dev, c) {
-               i = to_intel_crtc(c);
-
-               if (c == &intel_crtc->base)
+       for_each_plane_in_state(state, drm_plane, drm_plane_state, i) {
+               if (drm_plane->type != DRM_PLANE_TYPE_PRIMARY)
                        continue;
 
-               if (!i->active)
-                       continue;
-
-               fb = c->primary->fb;
+               fb = drm_plane_state->fb;
                if (!fb)
                        continue;
 
@@ -2611,17 +2615,22 @@ intel_find_initial_plane_obj(struct intel_crtc 
*intel_crtc,
                }
        }
 
+       intel_pre_disable_primary(&intel_crtc->base);
+       to_intel_plane(plane)->disable_plane(plane, &intel_crtc->base);
+
        return;
 
 valid_fb:
+       drm_atomic_set_fb_for_plane(&plane_state->base, fb);
+       ret = drm_atomic_set_crtc_for_plane(&plane_state->base, 
&intel_crtc->base);
+       WARN_ON(ret);
+       plane->fb = fb;
+
+       plane_state->visible = true;
        obj = intel_fb_obj(fb);
        if (obj->tiling_mode != I915_TILING_NONE)
                dev_priv->preserve_bios_swizzle = true;
 
-       primary->fb = fb;
-       primary->crtc = primary->state->crtc = &intel_crtc->base;
-       update_state_fb(primary);
-       intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
        obj->frontbuffer_bits |= INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
 }
 
@@ -3229,7 +3238,7 @@ void intel_finish_reset(struct drm_device *dev)
                dev_priv->display.hpd_irq_setup(dev);
        spin_unlock_irq(&dev_priv->irq_lock);
 
-       intel_modeset_setup_hw_state(dev, true);
+       intel_display_resume(dev);
 
        intel_hpd_init(dev_priv);
 
@@ -6190,6 +6199,11 @@ void intel_display_suspend(struct drm_device *dev)
                intel_crtc_disable_noatomic(crtc);
 }
 
+void intel_display_resume(struct drm_device *dev)
+{
+       intel_modeset_setup_hw_state(dev, true);
+}
+
 /* Master function to enable/disable CRTC and corresponding power wells */
 int intel_crtc_control(struct drm_crtc *crtc, bool enable)
 {
@@ -7700,9 +7714,14 @@ void intel_mode_from_pipe_config(struct drm_display_mode 
*mode,
        mode->vsync_end = pipe_config->base.adjusted_mode.crtc_vsync_end;
 
        mode->flags = pipe_config->base.adjusted_mode.flags;
+       mode->type = DRM_MODE_TYPE_DRIVER;
 
        mode->clock = pipe_config->base.adjusted_mode.crtc_clock;
        mode->flags |= pipe_config->base.adjusted_mode.flags;
+
+       mode->hsync = drm_mode_hsync(mode);
+       mode->vrefresh = drm_mode_vrefresh(mode);
+       drm_mode_set_name(mode);
 }
 
 static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
@@ -11772,34 +11791,6 @@ static bool check_encoder_cloning(struct 
drm_atomic_state *state,
        return true;
 }
 
-static void intel_crtc_check_initial_planes(struct drm_crtc *crtc,
-                                           struct drm_crtc_state *crtc_state)
-{
-       struct intel_crtc_state *pipe_config =
-               to_intel_crtc_state(crtc_state);
-       struct drm_plane *p;
-       unsigned visible_mask = 0;
-
-       drm_for_each_plane_mask(p, crtc->dev, crtc_state->plane_mask) {
-               struct drm_plane_state *plane_state =
-                       drm_atomic_get_existing_plane_state(crtc_state->state, 
p);
-
-               if (WARN_ON(!plane_state))
-                       continue;
-
-               if (!plane_state->fb)
-                       crtc_state->plane_mask &=
-                               ~(1 << drm_plane_index(p));
-               else if (to_intel_plane_state(plane_state)->visible)
-                       visible_mask |= 1 << drm_plane_index(p);
-       }
-
-       if (!visible_mask)
-               return;
-
-       pipe_config->quirks &= ~PIPE_CONFIG_QUIRK_INITIAL_PLANES;
-}
-
 static int intel_crtc_atomic_check(struct drm_crtc *crtc,
                                   struct drm_crtc_state *crtc_state)
 {
@@ -11821,10 +11812,6 @@ 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 */
-       if (pipe_config->quirks & PIPE_CONFIG_QUIRK_INITIAL_PLANES)
-               intel_crtc_check_initial_planes(crtc, crtc_state);
-
        if (mode_changed)
                intel_crtc->atomic.update_wm = !crtc_state->active;
 
@@ -12374,24 +12361,35 @@ static bool intel_fuzzy_clock_check(int clock1, int 
clock2)
 static bool
 intel_pipe_config_compare(struct drm_device *dev,
                          struct intel_crtc_state *current_config,
-                         struct intel_crtc_state *pipe_config)
+                         struct intel_crtc_state *pipe_config,
+                         bool check_only)
 {
+       bool ret = true;
+
+#define INTEL_ERR_OR_DBG_KMS(fmt, ...) \
+       do { \
+               if (!check_only) \
+                       DRM_ERROR(fmt, ##__VA_ARGS__); \
+               else \
+                       DRM_DEBUG_KMS(fmt, ##__VA_ARGS__); \
+       } while (0)
+
 #define PIPE_CONF_CHECK_X(name)        \
        if (current_config->name != pipe_config->name) { \
-               DRM_ERROR("mismatch in " #name " " \
+               INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
                          "(expected 0x%08x, found 0x%08x)\n", \
                          current_config->name, \
                          pipe_config->name); \
-               return false; \
+               ret = false; \
        }
 
 #define PIPE_CONF_CHECK_I(name)        \
        if (current_config->name != pipe_config->name) { \
-               DRM_ERROR("mismatch in " #name " " \
+               INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
                          "(expected %i, found %i)\n", \
                          current_config->name, \
                          pipe_config->name); \
-               return false; \
+               ret = false; \
        }
 
 /* This is required for BDW+ where there is only one set of registers for
@@ -12402,30 +12400,30 @@ intel_pipe_config_compare(struct drm_device *dev,
 #define PIPE_CONF_CHECK_I_ALT(name, alt_name) \
        if ((current_config->name != pipe_config->name) && \
                (current_config->alt_name != pipe_config->name)) { \
-                       DRM_ERROR("mismatch in " #name " " \
+                       INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
                                  "(expected %i or %i, found %i)\n", \
                                  current_config->name, \
                                  current_config->alt_name, \
                                  pipe_config->name); \
-                       return false; \
+                       ret = false; \
        }
 
 #define PIPE_CONF_CHECK_FLAGS(name, mask)      \
        if ((current_config->name ^ pipe_config->name) & (mask)) { \
-               DRM_ERROR("mismatch in " #name "(" #mask ") "      \
+               INTEL_ERR_OR_DBG_KMS("mismatch in " #name "(" #mask ") "        
   \
                          "(expected %i, found %i)\n", \
                          current_config->name & (mask), \
                          pipe_config->name & (mask)); \
-               return false; \
+               ret = false; \
        }
 
 #define PIPE_CONF_CHECK_CLOCK_FUZZY(name) \
        if (!intel_fuzzy_clock_check(current_config->name, pipe_config->name)) 
{ \
-               DRM_ERROR("mismatch in " #name " " \
+               INTEL_ERR_OR_DBG_KMS("mismatch in " #name " " \
                          "(expected %i, found %i)\n", \
                          current_config->name, \
                          pipe_config->name); \
-               return false; \
+               ret = false; \
        }
 
 #define PIPE_CONF_QUIRK(quirk) \
@@ -12559,8 +12557,9 @@ intel_pipe_config_compare(struct drm_device *dev,
 #undef PIPE_CONF_CHECK_FLAGS
 #undef PIPE_CONF_CHECK_CLOCK_FUZZY
 #undef PIPE_CONF_QUIRK
+#undef INTEL_ERR_OR_DBG_KMS
 
-       return true;
+       return ret;
 }
 
 static void check_wm_state(struct drm_device *dev)
@@ -12757,7 +12756,7 @@ check_crtc_state(struct drm_device *dev)
                     "(expected %i, found %i)\n", crtc->base.state->active, 
crtc->active);
 
                if (active &&
-                   !intel_pipe_config_compare(dev, crtc->config, 
&pipe_config)) {
+                   !intel_pipe_config_compare(dev, crtc->config, &pipe_config, 
false)) {
                        I915_STATE_WARN(1, "pipe state doesn't match!\n");
                        intel_dump_pipe_config(crtc, &pipe_config,
                                               "[hw state]");
@@ -13064,20 +13063,6 @@ intel_modeset_compute_config(struct drm_atomic_state 
*state)
                        continue;
                }
 
-               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;
-
-                       /*
-                        * We ought to handle i915.fastboot here.
-                        * If no modeset is required and the primary plane has
-                        * a fb, update the members of crtc_state as needed,
-                        * and run the necessary updates during vblank evasion.
-                        */
-               }
-
                if (!needs_modeset(crtc_state)) {
                        ret = drm_atomic_add_affected_connectors(state, crtc);
                        if (ret)
@@ -13140,6 +13125,12 @@ static int __intel_set_mode(struct drm_atomic_state 
*state)
                        intel_crtc->active = false;
                        intel_disable_shared_dpll(intel_crtc);
                }
+
+               /* FIXME: Move this to i9xx_crtc_disable when it gets a pointer
+                * to the old crtc_state. */
+               if (to_intel_crtc_state(crtc_state)->quirks &
+                   PIPE_CONFIG_QUIRK_WRONG_PLANE)
+                       intel_crtc->plane = !intel_crtc->plane;
        }
 
        /* Only after disabling all output pipelines that will be changed can we
@@ -14975,12 +14966,12 @@ void intel_modeset_init_hw(struct drm_device *dev)
        intel_enable_gt_powersave(dev);
 }
 
-void intel_modeset_init(struct drm_device *dev)
+struct drm_atomic_state *intel_modeset_init(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
+       struct drm_atomic_state *state;
        int sprite, ret;
        enum pipe pipe;
-       struct intel_crtc *crtc;
 
        drm_mode_config_init(dev);
 
@@ -14999,7 +14990,7 @@ void intel_modeset_init(struct drm_device *dev)
        intel_init_pm(dev);
 
        if (INTEL_INFO(dev)->num_pipes == 0)
-               return;
+               return NULL;
 
        intel_init_display(dev);
        intel_init_audio(dev);
@@ -15054,30 +15045,11 @@ void intel_modeset_init(struct drm_device *dev)
        intel_fbc_disable(dev);
 
        drm_modeset_lock_all(dev);
-       intel_modeset_setup_hw_state(dev, false);
-       drm_modeset_unlock_all(dev);
-
-       for_each_intel_crtc(dev, crtc) {
-               if (!crtc->active)
-                       continue;
+       state = intel_modeset_setup_hw_state(dev, false);
+       if (!state)
+               drm_modeset_unlock_all(dev);
 
-               /*
-                * Note that reserving the BIOS fb up front prevents us
-                * from stuffing other stolen allocations like the ring
-                * on top.  This prevents some ugliness at boot time, and
-                * can even allow for smooth boot transitions if the BIOS
-                * fb is large enough for the active pipe configuration.
-                */
-               if (dev_priv->display.get_initial_plane_config) {
-                       dev_priv->display.get_initial_plane_config(crtc,
-                                                          &crtc->plane_config);
-                       /*
-                        * If the fb is shared between multiple heads, we'll
-                        * just get the first one.
-                        */
-                       intel_find_initial_plane_obj(crtc, &crtc->plane_config);
-               }
-       }
+       return state;
 }
 
 static void intel_enable_pipe_a(struct drm_device *dev)
@@ -15124,13 +15096,17 @@ intel_check_plane_mapping(struct intel_crtc *crtc)
        return true;
 }
 
-static void intel_sanitize_crtc(struct intel_crtc *crtc)
+static void intel_sanitize_crtc(struct intel_crtc *crtc,
+                               struct intel_crtc_state *pipe_config,
+                               bool force_restore)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *encoder;
+       struct drm_atomic_state *state = pipe_config->base.state;
+       struct intel_crtc_state *hw_state =
+               to_intel_crtc_state(crtc->base.state);
        u32 reg;
-       bool enable;
 
        /* Clear any frame start delays used for debugging left by the BIOS */
        reg = PIPECONF(crtc->config->cpu_transcoder);
@@ -15144,27 +15120,55 @@ static void intel_sanitize_crtc(struct intel_crtc 
*crtc)
                drm_crtc_vblank_on(&crtc->base);
        }
 
-       /* We need to sanitize the plane -> pipe mapping first because this will
-        * disable the crtc (and hence change the state) if it is wrong. Note
-        * that gen4+ has a fixed plane -> pipe mapping.  */
-       if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {
-               bool plane;
+       /* set up current state */
+       if (!force_restore && hw_state->base.active) {
+               bool enable;
 
-               DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
-                             crtc->base.base.id);
+               memcpy(pipe_config, hw_state, sizeof(*pipe_config));
+               __drm_atomic_helper_crtc_duplicate_state(&crtc->base, 
&pipe_config->base);
+               pipe_config->base.state = state;
 
-               /* Pipe has the wrong plane attached and the plane is active.
-                * Temporarily change the plane mapping and disable everything
-                * ...  */
-               plane = crtc->plane;
-               to_intel_plane_state(crtc->base.primary->state)->visible = true;
-               crtc->plane = !plane;
-               intel_crtc_disable_noatomic(&crtc->base);
-               crtc->plane = plane;
+               enable = false;
+               for_each_encoder_on_crtc(dev, &crtc->base, encoder)
+                       enable |= encoder->connectors_active;
+
+               pipe_config->base.active = !!enable;
+       }
+
+       if (hw_state->quirks & PIPE_CONFIG_QUIRK_WRONG_PLANE) {
+               if (force_restore || i915.fastboot)
+                       pipe_config->base.mode_changed = true;
+               else
+                       pipe_config->base.active = false;
        }
 
-       if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
-           crtc->pipe == PIPE_A && !crtc->active) {
+       /* XXX: This is needs to be modified for making fastboot possible
+        * by default without requiring a modeset.
+        */
+       if (hw_state->base.active && pipe_config->base.active) {
+               struct intel_crtc_state sw_state;
+
+               memset(&sw_state, 0, sizeof(sw_state));
+               sw_state.base = pipe_config->base;
+               sw_state.scaler_state = pipe_config->scaler_state;
+               sw_state.shared_dpll = pipe_config->shared_dpll;
+               sw_state.dpll_hw_state = pipe_config->dpll_hw_state;
+               sw_state.ddi_pll_sel = pipe_config->ddi_pll_sel;
+
+               intel_modeset_pipe_config(&crtc->base, &sw_state);
+
+               /* Check if we need to force a modeset */
+               if (!intel_pipe_config_compare(dev, &sw_state, hw_state, 
!i915.fastboot)) {
+                       DRM_DEBUG_KMS("sw and hw state differ, forcing 
modeset\n");
+                       pipe_config->base.mode_changed = true;
+               } else {
+                       *pipe_config = sw_state;
+               }
+       }
+
+
+       if (dev_priv->quirks & QUIRK_PIPEA_FORCE && !hw_state->base.active &&
+           crtc->pipe == PIPE_A && !pipe_config->base.active) {
                /* BIOS forgot to enable pipe A, this mostly happens after
                 * resume. Force-enable the pipe to fix this, the update_dpms
                 * call below we restore the pipe to the right state, but leave
@@ -15172,44 +15176,7 @@ static void intel_sanitize_crtc(struct intel_crtc 
*crtc)
                intel_enable_pipe_a(dev);
        }
 
-       /* Adjust the state of the output pipe according to whether we
-        * have active connectors/encoders. */
-       enable = false;
-       for_each_encoder_on_crtc(dev, &crtc->base, encoder)
-               enable |= encoder->connectors_active;
-
-       if (!enable)
-               intel_crtc_disable_noatomic(&crtc->base);
-
-       if (crtc->active != crtc->base.state->active) {
-
-               /* This can happen either due to bugs in the get_hw_state
-                * functions or because of calls to intel_crtc_disable_noatomic,
-                * or because the pipe is force-enabled due to the
-                * pipe A quirk. */
-               DRM_DEBUG_KMS("[CRTC:%d] hw state adjusted, was %s, now %s\n",
-                             crtc->base.base.id,
-                             crtc->base.state->enable ? "enabled" : "disabled",
-                             crtc->active ? "enabled" : "disabled");
-
-               crtc->base.state->enable = crtc->active;
-               crtc->base.state->active = crtc->active;
-               crtc->base.enabled = crtc->active;
-
-               /* Because we only establish the connector -> encoder ->
-                * crtc links if something is active, this means the
-                * crtc is now deactivated. Break the links. connector
-                * -> encoder links are only establish when things are
-                *  actually up, hence no need to break them. */
-               WARN_ON(crtc->active);
-
-               for_each_encoder_on_crtc(dev, &crtc->base, encoder) {
-                       WARN_ON(encoder->connectors_active);
-                       encoder->base.crtc = NULL;
-               }
-       }
-
-       if (crtc->active || HAS_GMCH_DISPLAY(dev)) {
+       if (hw_state->base.active || HAS_GMCH_DISPLAY(dev)) {
                /*
                 * We start out with underrun reporting disabled to avoid races.
                 * For correct bookkeeping mark this on active crtcs.
@@ -15265,6 +15232,7 @@ static void intel_sanitize_encoder(struct intel_encoder 
*encoder)
                for_each_intel_connector(dev, connector) {
                        if (connector->encoder != encoder)
                                continue;
+
                        connector->base.dpms = DRM_MODE_DPMS_OFF;
                        connector->base.encoder = NULL;
                }
@@ -15301,74 +15269,54 @@ void i915_redisable_vga(struct drm_device *dev)
        i915_redisable_vga_power_on(dev);
 }
 
-static bool primary_get_hw_state(struct intel_crtc *crtc)
-{
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
-
-       return !!(I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE);
-}
-
 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 intel_initial_plane_config plane_config = {};
        struct drm_plane_state *drm_plane_state;
+       struct intel_plane *p;
        bool active = crtc_state->base.active;
-       int ret = 0;
-
-       if (active) {
-               crtc_state->quirks |= PIPE_CONFIG_QUIRK_INITIAL_PLANES;
-
-               /* apply to previous sw state too */
-               to_intel_crtc_state(crtc->base.state)->quirks |=
-                       PIPE_CONFIG_QUIRK_INITIAL_PLANES;
-       }
 
        for_each_intel_plane(crtc->base.dev, p) {
-               bool visible = active;
+               struct intel_plane_state *plane_state;
 
                if (crtc->pipe != p->pipe)
                        continue;
 
                drm_plane_state = drm_atomic_get_plane_state(state, &p->base);
-               if (IS_ERR(drm_plane_state)) {
-                       ret = PTR_ERR(drm_plane_state);
-                       break;
-               }
+               if (IS_ERR(drm_plane_state))
+                       return PTR_ERR(drm_plane_state);
+               plane_state = to_intel_plane_state(drm_plane_state);
 
                /* Plane scaler state is not touched here. The first atomic
                 * commit will restore all plane scalers to its old state.
                 */
 
+               plane_state->visible = false;
                if (active && p->base.type == DRM_PLANE_TYPE_PRIMARY) {
-                       visible = primary_get_hw_state(crtc);
-                       to_intel_plane_state(drm_plane_state)->visible = 
visible;
-               } else {
-                       /*
-                        * unknown state, assume it's off to force a transition
-                        * to on when calculating state changes.
-                        */
-                       to_intel_plane_state(drm_plane_state)->visible = false;
-               }
+                       
to_i915(state->dev)->display.get_initial_plane_config(crtc, &plane_config);
+                       intel_find_initial_plane_obj(crtc, &plane_config, 
plane_state);
+               } else if (active)
+                       p->disable_plane(&p->base, &crtc->base);
 
-               p->base.crtc = drm_plane_state->crtc;
-               if (visible) {
-                       crtc_state->base.plane_mask |=
-                               1 << drm_plane_index(&p->base);
-               } else {
-                       crtc_state->base.plane_mask &=
-                               ~(1 << drm_plane_index(&p->base));
+               if (!plane_state->visible) {
+                       int ret;
+                       ret = drm_atomic_set_crtc_for_plane(drm_plane_state, 
NULL);
+                       WARN_ON(ret);
+                       drm_atomic_set_fb_for_plane(drm_plane_state, NULL);
                }
+               p->base.crtc = drm_plane_state->crtc;
        }
 
-       return ret;
+       return 0;
 }
 
 static int readout_hw_crtc_state(struct drm_atomic_state *state,
                                 struct intel_crtc *crtc)
 {
-       struct drm_i915_private *dev_priv = to_i915(state->dev);
+       struct drm_device *dev = state->dev;
+       struct drm_i915_private *dev_priv = to_i915(dev);
        struct intel_crtc_state *crtc_state;
        int ret;
 
@@ -15380,6 +15328,7 @@ static int readout_hw_crtc_state(struct 
drm_atomic_state *state,
        if (ret)
                return ret;
 
+       __drm_atomic_helper_crtc_destroy_state(&crtc->base, &crtc_state->base);
        memset(crtc_state, 0, sizeof(*crtc_state));
        crtc_state->base.crtc = &crtc->base;
        crtc_state->base.state = state;
@@ -15397,6 +15346,22 @@ static int readout_hw_crtc_state(struct 
drm_atomic_state *state,
                      crtc->base.base.id,
                      crtc_state->base.active ? "enabled" : "disabled");
 
+       /* We need to sanitize the plane -> pipe mapping first because this will
+        * disable the crtc (and hence change the state) if it is wrong. Note
+        * that gen4+ has a fixed plane -> pipe mapping.  */
+       if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {
+               DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
+                             crtc->base.base.id);
+
+               /* Pipe has the wrong plane attached and the plane is active.
+                * Temporarily change the plane mapping and disable everything
+                * ...  */
+               crtc_state->quirks |=
+                       PIPE_CONFIG_QUIRK_WRONG_PLANE;
+
+               crtc->plane = !crtc->plane;
+       }
+
        return readout_plane_state(state, crtc, crtc_state);
 }
 
@@ -15512,7 +15477,7 @@ static int readout_hw_connector_encoder_state(struct 
drm_atomic_state *state)
 
                        encoder->get_config(encoder, crtc_state);
 
-                       if (connector_state)
+                       if (!WARN_ON(!connector_state))
                                connector_state->crtc = &crtc->base;
                } else {
                        encoder->base.crtc = NULL;
@@ -15565,8 +15530,8 @@ err_free:
 
 /* Scan out the current hw modeset state, sanitizes it and maps it into the drm
  * and i915 state tracking structures. */
-void intel_modeset_setup_hw_state(struct drm_device *dev,
-                                 bool force_restore)
+static struct drm_atomic_state *
+intel_modeset_setup_hw_state(struct drm_device *dev, bool force_restore)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_crtc *crtc;
@@ -15574,27 +15539,42 @@ void intel_modeset_setup_hw_state(struct drm_device 
*dev,
        struct intel_encoder *encoder;
        struct drm_atomic_state *state;
        struct intel_shared_dpll_config shared_dplls[I915_NUM_PLLS];
-       int i;
+       int i, ret;
 
        state = intel_modeset_readout_hw_state(dev);
        if (IS_ERR(state)) {
                DRM_ERROR("Failed to read out hw state\n");
-               return;
+               return NULL;
        }
 
        drm_atomic_helper_swap_state(dev, state);
 
-       /* swap sw/hw dpll state */
-       intel_atomic_duplicate_dpll_state(dev_priv, shared_dplls);
-       intel_shared_dpll_commit(state);
-       memcpy(to_intel_atomic_state(state)->shared_dpll,
-              shared_dplls, sizeof(*shared_dplls) * dev_priv->num_shared_dpll);
+       if (force_restore) {
+               /* swap sw/hw dpll state */
+               intel_atomic_duplicate_dpll_state(dev_priv, shared_dplls);
+               intel_shared_dpll_commit(state);
+               memcpy(to_intel_atomic_state(state)->shared_dpll,
+                      shared_dplls, sizeof(*shared_dplls) * 
dev_priv->num_shared_dpll);
+       } else {
+               intel_shared_dpll_commit(state);
+               to_intel_atomic_state(state)->dpll_set = false;
+       }
 
        /* HW state is read out, now we need to sanitize this mess. */
        for_each_intel_encoder(dev, encoder) {
                intel_sanitize_encoder(encoder);
        }
 
+       if (!force_restore) {
+               struct drm_connector_state *conn_state;
+               struct drm_connector *connector;
+
+               for_each_connector_in_state(state, connector, conn_state, i) {
+                       conn_state->best_encoder = 
connector->state->best_encoder;
+                       conn_state->crtc = connector->state->crtc;
+               }
+       }
+
        for_each_crtc_in_state(state, crtc, crtc_state, i) {
                struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
@@ -15616,7 +15596,7 @@ void intel_modeset_setup_hw_state(struct drm_device 
*dev,
                                      &crtc->state->adjusted_mode);
                }
 
-               intel_sanitize_crtc(intel_crtc);
+               intel_sanitize_crtc(intel_crtc, 
to_intel_crtc_state(crtc_state), force_restore);
 
                /*
                 * sanitize_crtc may have forced an update of crtc->state,
@@ -15646,29 +15626,28 @@ void intel_modeset_setup_hw_state(struct drm_device 
*dev,
        else if (HAS_PCH_SPLIT(dev))
                ilk_wm_get_hw_state(dev);
 
-       if (force_restore) {
-               int ret;
+       if (!force_restore)
+               return state;
 
-               i915_redisable_vga(dev);
+       i915_redisable_vga(dev);
 
-               ret = intel_set_mode(state);
-               if (ret) {
-                       DRM_ERROR("Failed to restore previous mode\n");
-                       drm_atomic_state_free(state);
-               }
-       } else {
+       ret = intel_set_mode(state);
+       if (ret) {
+               DRM_ERROR("Failed to restore previous mode\n");
                drm_atomic_state_free(state);
        }
 
        intel_modeset_check_state(dev);
+       return NULL;
 }
 
-void intel_modeset_gem_init(struct drm_device *dev)
+void intel_modeset_gem_init(struct drm_device *dev, struct drm_atomic_state 
*state)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct drm_crtc *c;
        struct drm_i915_gem_object *obj;
-       int ret;
+       struct drm_crtc_state *crtc_state;
+       struct drm_crtc *c;
+       int ret, i;
 
        mutex_lock(&dev->struct_mutex);
        intel_init_gt_powersave(dev);
@@ -15693,27 +15672,67 @@ void intel_modeset_gem_init(struct drm_device *dev)
         * pinned & fenced.  When we do the allocation it's too early
         * for this.
         */
-       for_each_crtc(dev, c) {
-               obj = intel_fb_obj(c->primary->fb);
+       for_each_crtc_in_state(state, c, crtc_state, i) {
+               struct drm_connector_state *conn_state;
+               struct drm_connector *connector;
+               int j;
+               struct drm_plane *primary = c->primary;
+
+               obj = intel_fb_obj(primary->state->fb);
                if (obj == NULL)
-                       continue;
+                       goto disable;
 
                mutex_lock(&dev->struct_mutex);
-               ret = intel_pin_and_fence_fb_obj(c->primary,
-                                                c->primary->fb,
-                                                c->primary->state,
-                                                NULL);
+               ret = intel_pin_and_fence_fb_obj(primary, primary->state->fb,
+                                                primary->state, NULL);
                mutex_unlock(&dev->struct_mutex);
-               if (ret) {
-                       DRM_ERROR("failed to pin boot fb on pipe %d\n",
-                                 to_intel_crtc(c)->pipe);
-                       drm_framebuffer_unreference(c->primary->fb);
-                       c->primary->fb = NULL;
-                       c->primary->crtc = c->primary->state->crtc = NULL;
-                       update_state_fb(c->primary);
-                       c->state->plane_mask &= ~(1 << 
drm_plane_index(c->primary));
+               if (!ret && !crtc_state->active)
+                       goto disable;
+
+               if (!ret) {
+                       struct drm_plane_state *plane_state =
+                               drm_atomic_get_existing_plane_state(state, 
primary);
+
+                       ret = drm_atomic_set_crtc_for_plane(plane_state, c);
+                       WARN_ON(ret);
+                       drm_atomic_set_fb_for_plane(plane_state, 
primary->state->fb);
+                       continue;
+               }
+
+
+               obj->frontbuffer_bits &=
+                       ~INTEL_FRONTBUFFER_PRIMARY(to_intel_crtc(c)->pipe);
+
+               DRM_ERROR("failed to pin boot fb on pipe %d: %i\n",
+                         to_intel_crtc(c)->pipe, ret);
+
+               drm_framebuffer_unreference(primary->state->fb);
+               drm_framebuffer_unreference(primary->fb);
+               primary->fb = primary->state->fb = NULL;
+               primary->crtc = primary->state->crtc = NULL;
+               /* Do not update crtc_state->plane_mask, this forces
+                * the disabling of the primary plane during modeset.
+                */
+
+disable:
+               crtc_state->active = crtc_state->enable = false;
+
+               ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
+               WARN_ON(ret);
+
+               for_each_connector_in_state(state, connector, conn_state, j) {
+                       if (conn_state->crtc != c)
+                               continue;
+
+                       ret = drm_atomic_set_crtc_for_connector(conn_state, 
NULL);
+                       WARN_ON(ret);
                }
+
        }
+       ret = intel_set_mode(state);
+       if (ret)
+               DRM_ERROR("Initial modeset failed with %i\n", ret);
+       drm_modeset_unlock_all(dev);
 
        intel_backlight_register(dev);
 }
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bc7d0a003c8e..ea380b83eb5d 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -330,7 +330,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 */
+#define PIPE_CONFIG_QUIRK_WRONG_PLANE          (1<<2) /* intel_crtc->plane is 
wrong */
        unsigned long quirks;
 
        /* Pipe source size (ie. panel fitter input size)
@@ -528,7 +528,6 @@ struct intel_crtc {
        uint32_t cursor_size;
        uint32_t cursor_base;
 
-       struct intel_initial_plane_config plane_config;
        struct intel_crtc_state *config;
 
        /* reset counter value when the last flip was submitted */
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c 
b/drivers/gpu/drm/i915/intel_fbdev.c
index 6372cfc7d053..6ac4990a0c11 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -582,7 +582,6 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
        struct intel_framebuffer *fb = NULL;
        struct drm_crtc *crtc;
        struct intel_crtc *intel_crtc;
-       struct intel_initial_plane_config *plane_config = NULL;
        unsigned int max_size = 0;
 
        if (!i915.fastboot)
@@ -590,20 +589,21 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
 
        /* Find the largest fb */
        for_each_crtc(dev, crtc) {
+               struct intel_framebuffer *plane_fb =
+                       to_intel_framebuffer(crtc->primary->state->fb);
                intel_crtc = to_intel_crtc(crtc);
 
-               if (!intel_crtc->active || !crtc->primary->fb) {
+               if (!intel_crtc->active || !plane_fb) {
                        DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
                                      pipe_name(intel_crtc->pipe));
                        continue;
                }
 
-               if (intel_crtc->plane_config.size > max_size) {
+               if (plane_fb->obj->base.size > max_size) {
                        DRM_DEBUG_KMS("found possible fb from plane %c\n",
                                      pipe_name(intel_crtc->pipe));
-                       plane_config = &intel_crtc->plane_config;
                        fb = to_intel_framebuffer(crtc->primary->fb);
-                       max_size = plane_config->size;
+                       max_size = fb->obj->base.size;
                }
        }
 
@@ -638,7 +638,6 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
                        DRM_DEBUG_KMS("fb not wide enough for plane %c (%d vs 
%d)\n",
                                      pipe_name(intel_crtc->pipe),
                                      cur_size, fb->base.pitches[0]);
-                       plane_config = NULL;
                        fb = NULL;
                        break;
                }
@@ -659,7 +658,6 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
                        DRM_DEBUG_KMS("fb not big enough for plane %c (%d vs 
%d)\n",
                                      pipe_name(intel_crtc->pipe),
                                      cur_size, max_size);
-                       plane_config = NULL;
                        fb = NULL;
                        break;
                }
diff --git a/drivers/gpu/drm/i915/intel_lvds.c 
b/drivers/gpu/drm/i915/intel_lvds.c
index 161ab26f81fb..78d86ae01621 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -452,7 +452,7 @@ static int intel_lid_notify(struct notifier_block *nb, 
unsigned long val,
         */
        if (!HAS_PCH_SPLIT(dev)) {
                drm_modeset_lock_all(dev);
-               intel_modeset_setup_hw_state(dev, true);
+               intel_display_resume(dev);
                drm_modeset_unlock_all(dev);
        }
 
-- 
2.1.0

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

Reply via email to