const struct intel_crtc_state *old_crtc_state,
                                               const struct drm_connector_state *old_conn_state)
 {
+       struct intel_display *display = to_intel_display(encoder);
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_crtc *pipe_crtc;
+       int i;
 
-       for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
-                                        intel_crtc_joined_pipe_mask(old_crtc_state)) {
+       for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
                const struct intel_crtc_state *old_pipe_crtc_state =
                        intel_atomic_get_old_crtc_state(state, pipe_crtc);
 
 
        intel_ddi_disable_transcoder_func(old_crtc_state);
 
-       for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
-                                        intel_crtc_joined_pipe_mask(old_crtc_state)) {
+       for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
                const struct intel_crtc_state *old_pipe_crtc_state =
                        intel_atomic_get_old_crtc_state(state, pipe_crtc);
 
                             const struct intel_crtc_state *crtc_state,
                             const struct drm_connector_state *conn_state)
 {
-       struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+       struct intel_display *display = to_intel_display(encoder);
        struct intel_crtc *pipe_crtc;
+       int i;
 
        intel_ddi_enable_transcoder_func(encoder, crtc_state);
 
 
        intel_ddi_wait_for_fec_status(encoder, crtc_state, true);
 
-       for_each_intel_crtc_in_pipe_mask_reverse(&i915->drm, pipe_crtc,
-                                                intel_crtc_joined_pipe_mask(crtc_state)) {
+       for_each_pipe_crtc_modeset_enable(display, pipe_crtc, crtc_state, i) {
                const struct intel_crtc_state *pipe_crtc_state =
                        intel_atomic_get_new_crtc_state(state, pipe_crtc);
 
 
        return BIT(crtc->pipe) & bigjoiner_secondary_pipes(crtc_state);
 }
 
+u8 _intel_modeset_primary_pipes(const struct intel_crtc_state *crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+       if (!is_bigjoiner(crtc_state))
+               return BIT(crtc->pipe);
+
+       return bigjoiner_primary_pipes(crtc_state);
+}
+
+u8 _intel_modeset_secondary_pipes(const struct intel_crtc_state *crtc_state)
+{
+       return bigjoiner_secondary_pipes(crtc_state);
+}
+
 u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state)
 {
        if (crtc_state->joiner_pipes)
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        enum transcoder cpu_transcoder = new_crtc_state->cpu_transcoder;
        struct intel_crtc *pipe_crtc;
+       int i;
 
        if (drm_WARN_ON(&dev_priv->drm, crtc->active))
                return;
-
-       for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
-                                                intel_crtc_joined_pipe_mask(new_crtc_state))
+       for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i)
                intel_dmc_enable_pipe(display, pipe_crtc->pipe);
 
        intel_encoders_pre_pll_enable(state, crtc);
 
-       for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
-                                                intel_crtc_joined_pipe_mask(new_crtc_state)) {
+       for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) {
                const struct intel_crtc_state *pipe_crtc_state =
                        intel_atomic_get_new_crtc_state(state, pipe_crtc);
 
 
        intel_encoders_pre_enable(state, crtc);
 
-       for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
-                                                intel_crtc_joined_pipe_mask(new_crtc_state)) {
+       for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) {
                const struct intel_crtc_state *pipe_crtc_state =
                        intel_atomic_get_new_crtc_state(state, pipe_crtc);
 
        if (!transcoder_is_dsi(cpu_transcoder))
                hsw_configure_cpu_transcoder(new_crtc_state);
 
-       for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
-                                                intel_crtc_joined_pipe_mask(new_crtc_state)) {
+       for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) {
                const struct intel_crtc_state *pipe_crtc_state =
                        intel_atomic_get_new_crtc_state(state, pipe_crtc);
 
 
        intel_encoders_enable(state, crtc);
 
-       for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
-                                                intel_crtc_joined_pipe_mask(new_crtc_state)) {
+       for_each_pipe_crtc_modeset_enable(display, pipe_crtc, new_crtc_state, i) {
                const struct intel_crtc_state *pipe_crtc_state =
                        intel_atomic_get_new_crtc_state(state, pipe_crtc);
                enum pipe hsw_workaround_pipe;
                             struct intel_crtc *crtc)
 {
        struct intel_display *display = to_intel_display(state);
-       struct drm_i915_private *i915 = to_i915(display->drm);
        const struct intel_crtc_state *old_crtc_state =
                intel_atomic_get_old_crtc_state(state, crtc);
        struct intel_crtc *pipe_crtc;
+       int i;
 
        /*
         * FIXME collapse everything to one hook.
        intel_encoders_disable(state, crtc);
        intel_encoders_post_disable(state, crtc);
 
-       for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc,
-                                        intel_crtc_joined_pipe_mask(old_crtc_state)) {
+       for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
                const struct intel_crtc_state *old_pipe_crtc_state =
                        intel_atomic_get_old_crtc_state(state, pipe_crtc);
 
 
        intel_encoders_post_pll_disable(state, crtc);
 
-       for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc,
-                                        intel_crtc_joined_pipe_mask(old_crtc_state))
+       for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i)
                intel_dmc_disable_pipe(display, pipe_crtc->pipe);
 }
 
 
                             ((connector) = to_intel_connector((__state)->base.connectors[__i].ptr), \
                             (new_connector_state) = to_intel_digital_connector_state((__state)->base.connectors[__i].new_state), 1))
 
+#define for_each_crtc_in_masks(display, crtc, first_pipes, second_pipes, i) \
+       for ((i) = 0; \
+            (i) < (I915_MAX_PIPES * 2) && ((crtc) = intel_crtc_for_pipe(display, (i) % I915_MAX_PIPES), 1); \
+            (i)++) \
+               for_each_if((crtc) && ((first_pipes) | ((second_pipes) << I915_MAX_PIPES)) & BIT(i))
+
+#define for_each_crtc_in_masks_reverse(display, crtc, first_pipes, second_pipes, i) \
+       for ((i) = (I915_MAX_PIPES * 2 - 1); \
+            (i) >= 0 && ((crtc) = intel_crtc_for_pipe(display, (i) % I915_MAX_PIPES), 1); \
+            (i)--) \
+               for_each_if((crtc) && ((first_pipes) | ((second_pipes) << I915_MAX_PIPES)) & BIT(i))
+
+#define for_each_pipe_crtc_modeset_disable(display, crtc, crtc_state, i) \
+       for_each_crtc_in_masks(display, crtc, \
+                              _intel_modeset_primary_pipes(crtc_state), \
+                              _intel_modeset_secondary_pipes(crtc_state), \
+                              i)
+
+#define for_each_pipe_crtc_modeset_enable(display, crtc, crtc_state, i) \
+       for_each_crtc_in_masks_reverse(display, crtc, \
+                                      _intel_modeset_primary_pipes(crtc_state), \
+                                      _intel_modeset_secondary_pipes(crtc_state), \
+                                      i)
+
 int intel_atomic_check(struct drm_device *dev, struct drm_atomic_state *state);
 int intel_atomic_add_affected_planes(struct intel_atomic_state *state,
                                     struct intel_crtc *crtc);
 bool intel_crtc_is_bigjoiner_primary(const struct intel_crtc_state *crtc_state);
 bool intel_crtc_is_bigjoiner_secondary(const struct intel_crtc_state *crtc_state);
 u8 intel_crtc_joiner_secondary_pipes(const struct intel_crtc_state *crtc_state);
+u8 _intel_modeset_primary_pipes(const struct intel_crtc_state *crtc_state);
+u8 _intel_modeset_secondary_pipes(const struct intel_crtc_state *crtc_state);
 struct intel_crtc *intel_primary_crtc(const struct intel_crtc_state *crtc_state);
 bool intel_crtc_get_pipe_config(struct intel_crtc_state *crtc_state);
 bool intel_pipe_config_compare(const struct intel_crtc_state *current_config,
 
                                      const struct intel_crtc_state *old_crtc_state,
                                      const struct drm_connector_state *old_conn_state)
 {
+       struct intel_display *display = to_intel_display(encoder);
        struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_digital_port *dig_port = intel_mst->primary;
        struct intel_dp *intel_dp = &dig_port->dp;
        struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        struct intel_crtc *pipe_crtc;
        bool last_mst_stream;
+       int i;
 
        intel_dp->active_mst_links--;
        last_mst_stream = intel_dp->active_mst_links == 0;
                    DISPLAY_VER(dev_priv) >= 12 && last_mst_stream &&
                    !intel_dp_mst_is_master_trans(old_crtc_state));
 
-       for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
-                                        intel_crtc_joined_pipe_mask(old_crtc_state)) {
+       for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
                const struct intel_crtc_state *old_pipe_crtc_state =
                        intel_atomic_get_old_crtc_state(state, pipe_crtc);
 
 
        intel_ddi_disable_transcoder_func(old_crtc_state);
 
-       for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
-                                        intel_crtc_joined_pipe_mask(old_crtc_state)) {
+       for_each_pipe_crtc_modeset_disable(display, pipe_crtc, old_crtc_state, i) {
                const struct intel_crtc_state *old_pipe_crtc_state =
                        intel_atomic_get_old_crtc_state(state, pipe_crtc);
 
                                const struct intel_crtc_state *pipe_config,
                                const struct drm_connector_state *conn_state)
 {
+       struct intel_display *display = to_intel_display(encoder);
        struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
        struct intel_digital_port *dig_port = intel_mst->primary;
        struct intel_dp *intel_dp = &dig_port->dp;
        enum transcoder trans = pipe_config->cpu_transcoder;
        bool first_mst_stream = intel_dp->active_mst_links == 1;
        struct intel_crtc *pipe_crtc;
-       int ret;
+       int ret, i;
 
        drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder);
 
 
        intel_enable_transcoder(pipe_config);
 
-       for_each_intel_crtc_in_pipe_mask_reverse(&dev_priv->drm, pipe_crtc,
-                                                intel_crtc_joined_pipe_mask(pipe_config)) {
+       for_each_pipe_crtc_modeset_enable(display, pipe_crtc, pipe_config, i) {
                const struct intel_crtc_state *pipe_crtc_state =
                        intel_atomic_get_new_crtc_state(state, pipe_crtc);