diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 20c0b94b8fcbc17c50f9dd1db97d63f25be0b085..80555800f5f41349f9015dc527eba624e418ee24 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -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;