}
 }
 
+static int disable_conflicting_connectors(struct drm_atomic_state *state)
+{
+       struct drm_connector_state *conn_state;
+       struct drm_connector *connector;
+       struct drm_encoder *encoder;
+       unsigned encoder_mask = 0;
+       int i, ret;
+
+       for_each_connector_in_state(state, connector, conn_state, i) {
+               const struct drm_connector_helper_funcs *funcs = connector->helper_private;
+               struct drm_encoder *new_encoder;
+
+               if (!conn_state->crtc)
+                       continue;
+
+               if (funcs->atomic_best_encoder)
+                       new_encoder = funcs->atomic_best_encoder(connector, conn_state);
+               else
+                       new_encoder = funcs->best_encoder(connector);
+
+               if (new_encoder)
+                       encoder_mask |= 1 << drm_encoder_index(new_encoder);
+       }
+
+       drm_for_each_connector(connector, state->dev) {
+               struct drm_crtc_state *crtc_state;
+
+               if (drm_atomic_get_existing_connector_state(state, connector))
+                       continue;
+
+               encoder = connector->state->best_encoder;
+               if (!encoder || !(encoder_mask & (1 << drm_encoder_index(encoder))))
+                       continue;
+
+               conn_state = drm_atomic_get_connector_state(state, connector);
+               if (IS_ERR(conn_state))
+                       return PTR_ERR(conn_state);
+
+               DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], disabling [CONNECTOR:%d:%s]\n",
+                                encoder->base.id, encoder->name,
+                                conn_state->crtc->base.id, conn_state->crtc->name,
+                                connector->base.id, connector->name);
+
+               crtc_state = drm_atomic_get_existing_crtc_state(state, conn_state->crtc);
+
+               ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
+               if (ret)
+                       return ret;
+
+               if (!crtc_state->connector_mask) {
+                       ret = drm_atomic_set_mode_prop_for_crtc(crtc_state,
+                                                               NULL);
+                       if (ret < 0)
+                               return ret;
+
+                       crtc_state->active = false;
+               }
+       }
+
+       return 0;
+}
+
 static bool
 check_pending_encoder_assignment(struct drm_atomic_state *state,
                                 struct drm_encoder *new_encoder)
                }
        }
 
+       if (state->legacy_set_config) {
+               ret = disable_conflicting_connectors(state);
+               if (ret)
+                       return ret;
+       }
+
        for_each_connector_in_state(state, connector, connector_state, i) {
                /*
                 * This only sets crtc->mode_changed for routing changes,
        if (!state)
                return -ENOMEM;
 
+       state->legacy_set_config = true;
        state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
 retry:
        ret = __drm_atomic_helper_set_config(set, state);
 
  * @dev: parent DRM device
  * @allow_modeset: allow full modeset
  * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
+ * @legacy_set_config: Disable conflicting encoders instead of failing with -EINVAL.
  * @planes: pointer to array of plane pointers
  * @plane_states: pointer to array of plane states pointers
  * @crtcs: pointer to array of CRTC pointers
        struct drm_device *dev;
        bool allow_modeset : 1;
        bool legacy_cursor_update : 1;
+       bool legacy_set_config : 1;
        struct drm_plane **planes;
        struct drm_plane_state **plane_states;
        struct drm_crtc **crtcs;