drm/i915: Stage new modeset state straight into atomic state
authorAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Tue, 21 Apr 2015 14:13:15 +0000 (17:13 +0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Fri, 8 May 2015 11:04:06 +0000 (13:04 +0200)
The logic that stages the state before the modeset was still updating
first the old staged config and then populating the atomic state based
on that. Change this to use only the atomic state.

Note that now the staged config is updated in the function
intel_modeset_commit_output_state(). This is done so that the modeset
check and the force restore path in the hw state read out code continue
to work.

Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_display.c

index 20c0b94b8fcbc17c50f9dd1db97d63f25be0b085..80555800f5f41349f9015dc527eba624e418ee24 100644 (file)
@@ -11152,27 +11152,47 @@ static void intel_modeset_update_connector_atomic_state(struct drm_device *dev)
  * intel_modeset_commit_output_state
  *
  * This function copies the stage display pipe configuration to the real one.
+ *
+ * FIXME: we want to replace this with a proper state swap in the future
  */
-static void intel_modeset_commit_output_state(struct drm_device *dev)
+static void intel_modeset_commit_output_state(struct drm_atomic_state *state)
 {
-       struct intel_crtc *crtc;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+       struct drm_connector *connector;
+       struct drm_connector_state *connector_state;
        struct intel_encoder *encoder;
-       struct intel_connector *connector;
+       struct intel_connector *intel_connector;
+       int i;
 
-       for_each_intel_connector(dev, connector) {
-               connector->base.encoder = &connector->new_encoder->base;
+       for_each_connector_in_state(state, connector, connector_state, i) {
+               *connector->state = *connector_state;
+
+               connector->encoder = connector_state->best_encoder;
+               if (connector->encoder)
+                       connector->encoder->crtc = connector_state->crtc;
        }
 
-       for_each_intel_encoder(dev, encoder) {
-               encoder->base.crtc = &encoder->new_crtc->base;
+       /* Update crtc of disabled encoders */
+       for_each_intel_encoder(state->dev, encoder) {
+               int num_connectors = 0;
+
+               for_each_intel_connector(state->dev, intel_connector)
+                       if (intel_connector->base.encoder == &encoder->base)
+                               num_connectors++;
+
+               if (num_connectors == 0)
+                       encoder->base.crtc = NULL;
        }
 
-       for_each_intel_crtc(dev, crtc) {
-               crtc->base.state->enable = crtc->new_enabled;
-               crtc->base.enabled = crtc->new_enabled;
+       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               crtc->state->enable = crtc_state->enable;
+               crtc->enabled = crtc_state->enable;
        }
 
-       intel_modeset_update_connector_atomic_state(dev);
+       /* Copy the new configuration to the staged state, to keep the few
+        * pieces of code that haven't been converted yet happy */
+       intel_modeset_update_staged_output_state(state->dev);
 }
 
 static void
@@ -11622,7 +11642,7 @@ intel_modeset_update_state(struct drm_atomic_state *state)
                        intel_encoder->connectors_active = false;
        }
 
-       intel_modeset_commit_output_state(dev);
+       intel_modeset_commit_output_state(state);
 
        /* Double check state. */
        for_each_crtc(dev, crtc) {
@@ -12739,10 +12759,11 @@ intel_modeset_stage_output_state(struct drm_device *dev,
                                 struct drm_atomic_state *state)
 {
        struct intel_connector *connector;
+       struct drm_connector *drm_connector;
        struct drm_connector_state *connector_state;
-       struct intel_encoder *encoder;
-       struct intel_crtc *crtc;
-       struct intel_crtc_state *crtc_state;
+       struct drm_crtc *crtc;
+       struct drm_crtc_state *crtc_state;
+       int i, ret;
 
        /* The upper layers ensure that we either disable a crtc or have a list
         * of connectors. For paranoia, double-check this. */
@@ -12752,21 +12773,28 @@ intel_modeset_stage_output_state(struct drm_device *dev,
        for_each_intel_connector(dev, connector) {
                bool in_mode_set = intel_connector_in_mode_set(connector, set);
 
+               if (!in_mode_set && connector->base.state->crtc != set->crtc)
+                       continue;
+
+               connector_state =
+                       drm_atomic_get_connector_state(state, &connector->base);
+               if (IS_ERR(connector_state))
+                       return PTR_ERR(connector_state);
+
                if (in_mode_set) {
                        int pipe = to_intel_crtc(set->crtc)->pipe;
-                       connector->new_encoder =
-                               intel_find_encoder(connector, pipe);
+                       connector_state->best_encoder =
+                               &intel_find_encoder(connector, pipe)->base;
                }
 
-               if (!connector->base.encoder ||
-                   connector->base.encoder->crtc != set->crtc)
+               if (connector->base.state->crtc != set->crtc)
                        continue;
 
                /* If we disable the crtc, disable all its connectors. Also, if
                 * the connector is on the changing crtc but not on the new
                 * connector list, disable it. */
                if (!set->fb || !in_mode_set) {
-                       connector->new_encoder = NULL;
+                       connector_state->best_encoder = NULL;
 
                        DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
                                connector->base.base.id,
@@ -12775,86 +12803,58 @@ intel_modeset_stage_output_state(struct drm_device *dev,
        }
        /* connector->new_encoder is now updated for all connectors. */
 
-       /* Update crtc of enabled connectors. */
-       for_each_intel_connector(dev, connector) {
-               struct drm_crtc *new_crtc;
+       for_each_connector_in_state(state, drm_connector, connector_state, i) {
+               connector = to_intel_connector(drm_connector);
+
+               if (!connector_state->best_encoder) {
+                       ret = drm_atomic_set_crtc_for_connector(connector_state,
+                                                               NULL);
+                       if (ret)
+                               return ret;
 
-               if (!connector->new_encoder)
                        continue;
+               }
 
-               if (intel_connector_in_mode_set(connector, set))
-                       new_crtc = set->crtc;
-               else
-                       new_crtc = connector->new_encoder->base.crtc;
+               if (intel_connector_in_mode_set(connector, set)) {
+                       struct drm_crtc *crtc = connector->base.state->crtc;
+
+                       /* If this connector was in a previous crtc, add it
+                        * to the state. We might need to disable it. */
+                       if (crtc) {
+                               crtc_state =
+                                       drm_atomic_get_crtc_state(state, crtc);
+                               if (IS_ERR(crtc_state))
+                                       return PTR_ERR(crtc_state);
+                       }
+
+                       ret = drm_atomic_set_crtc_for_connector(connector_state,
+                                                               set->crtc);
+                       if (ret)
+                               return ret;
+               }
 
                /* Make sure the new CRTC will work with the encoder */
-               if (!drm_encoder_crtc_ok(&connector->new_encoder->base,
-                                        new_crtc)) {
+               if (!drm_encoder_crtc_ok(connector_state->best_encoder,
+                                        connector_state->crtc)) {
                        return -EINVAL;
                }
-               connector->new_encoder->new_crtc = to_intel_crtc(new_crtc);
-
-               connector_state =
-                       drm_atomic_get_connector_state(state, &connector->base);
-               if (IS_ERR(connector_state))
-                       return PTR_ERR(connector_state);
-
-               connector_state->crtc = new_crtc;
-               connector_state->best_encoder = &connector->new_encoder->base;
 
                DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
                        connector->base.base.id,
                        connector->base.name,
-                       new_crtc->base.id);
-       }
-
-       /* Check for any encoders that needs to be disabled. */
-       for_each_intel_encoder(dev, encoder) {
-               int num_connectors = 0;
-               for_each_intel_connector(dev, connector) {
-                       if (connector->new_encoder == encoder) {
-                               WARN_ON(!connector->new_encoder->new_crtc);
-                               num_connectors++;
-                       }
-               }
-
-               if (num_connectors == 0)
-                       encoder->new_crtc = NULL;
-               else if (num_connectors > 1)
-                       return -EINVAL;
-       }
-       /* Now we've also updated encoder->new_crtc for all encoders. */
-       for_each_intel_connector(dev, connector) {
-               connector_state =
-                       drm_atomic_get_connector_state(state, &connector->base);
-               if (IS_ERR(connector_state))
-                       return PTR_ERR(connector_state);
+                       connector_state->crtc->base.id);
 
-               if (connector->new_encoder) {
-                       if (connector->new_encoder != connector->encoder)
-                               connector->encoder = connector->new_encoder;
-               } else {
-                       connector_state->crtc = NULL;
-                       connector_state->best_encoder = NULL;
-               }
+               if (connector_state->best_encoder != &connector->encoder->base)
+                       connector->encoder =
+                               to_intel_encoder(connector_state->best_encoder);
        }
-       for_each_intel_crtc(dev, crtc) {
-               crtc->new_enabled = false;
-
-               for_each_intel_encoder(dev, encoder) {
-                       if (encoder->new_crtc == crtc) {
-                               crtc->new_enabled = true;
-                               break;
-                       }
-               }
 
-               if (crtc->new_enabled != crtc->base.state->enable) {
-                       crtc_state = intel_atomic_get_crtc_state(state, crtc);
-                       if (IS_ERR(crtc_state))
-                               return PTR_ERR(crtc_state);
+       for_each_crtc_in_state(state, crtc, crtc_state, i) {
+               ret = drm_atomic_add_affected_connectors(state, crtc);
+               if (ret)
+                       return ret;
 
-                       crtc_state->base.enable = crtc->new_enabled;
-               }
+               crtc_state->enable = drm_atomic_connectors_for_crtc(state, crtc);
        }
 
        return 0;