/* display clock increase/decrease */
        /* pll clock increase/decrease */
 
-       void (*load_csc_matrix)(const struct intel_crtc_state *crtc_state);
+       /*
+        * Program double buffered color management registers during
+        * vblank evasion. The registers should then latch during the
+        * next vblank start, alongside any other double buffered registers
+        * involved with the same commit.
+        */
+       void (*color_commit)(const struct intel_crtc_state *crtc_state);
+       /*
+        * Load LUTs (and other single buffered color management
+        * registers). Will (hopefully) be called during the vblank
+        * following the latching of any double buffered registers
+        * involved with the same commit.
+        */
        void (*load_luts)(const struct intel_crtc_state *crtc_state);
 };
 
 
        I915_WRITE(CGM_PIPE_MODE(pipe), mode);
 }
 
-void intel_color_set_csc(const struct intel_crtc_state *crtc_state)
-{
-       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
-
-       if (dev_priv->display.load_csc_matrix)
-               dev_priv->display.load_csc_matrix(crtc_state);
-}
-
 /* Loads the legacy palette/gamma unit for the CRTC. */
 static void i9xx_load_luts_internal(const struct intel_crtc_state *crtc_state,
                                    const struct drm_property_blob *blob)
        i9xx_load_luts_internal(crtc_state, crtc_state->base.gamma_lut);
 }
 
+static void hsw_color_commit(const struct intel_crtc_state *crtc_state)
+{
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+       I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
+
+       ilk_load_csc_matrix(crtc_state);
+}
+
 /* Loads the legacy palette/gamma unit for the CRTC on Haswell. */
 static void haswell_load_luts(const struct intel_crtc_state *crtc_state)
 {
                reenable_ips = true;
        }
 
-       I915_WRITE(GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode);
-
        i9xx_load_luts(crtc_state);
 
        if (reenable_ips)
                 */
                I915_WRITE(PREC_PAL_INDEX(pipe), 0);
        }
-
-       I915_WRITE(GAMMA_MODE(pipe), crtc_state->gamma_mode);
 }
 
 static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state)
                 */
                I915_WRITE(PREC_PAL_INDEX(pipe), 0);
        }
-
-       I915_WRITE(GAMMA_MODE(pipe), crtc_state->gamma_mode);
 }
 
 static void cherryview_load_luts(const struct intel_crtc_state *crtc_state)
        const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
        enum pipe pipe = crtc->pipe;
 
+       cherryview_load_csc_matrix(crtc_state);
+
        if (crtc_state_is_legacy_gamma(crtc_state)) {
-               /* Turn off degamma/gamma on CGM block. */
-               I915_WRITE(CGM_PIPE_MODE(pipe),
-                          (crtc_state->base.ctm ? CGM_PIPE_MODE_CSC : 0));
                i9xx_load_luts_internal(crtc_state, gamma_lut);
                return;
        }
                }
        }
 
-       I915_WRITE(CGM_PIPE_MODE(pipe),
-                  (crtc_state->base.ctm ? CGM_PIPE_MODE_CSC : 0) |
-                  (degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) |
-                  (gamma_lut ? CGM_PIPE_MODE_GAMMA : 0));
-
        /*
         * Also program a linear LUT in the legacy block (behind the
         * CGM block).
        dev_priv->display.load_luts(crtc_state);
 }
 
+void intel_color_commit(const struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+
+       if (dev_priv->display.color_commit)
+               dev_priv->display.color_commit(crtc_state);
+}
+
 static int check_lut_size(const struct drm_property_blob *lut, int expected)
 {
        int len;
        drm_mode_crtc_set_gamma_size(&crtc->base, 256);
 
        if (IS_CHERRYVIEW(dev_priv)) {
-               dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix;
                dev_priv->display.load_luts = cherryview_load_luts;
        } else if (IS_HASWELL(dev_priv)) {
-               dev_priv->display.load_csc_matrix = ilk_load_csc_matrix;
                dev_priv->display.load_luts = haswell_load_luts;
+               dev_priv->display.color_commit = hsw_color_commit;
        } else if (IS_BROADWELL(dev_priv) || IS_GEN9_BC(dev_priv) ||
                   IS_BROXTON(dev_priv)) {
-               dev_priv->display.load_csc_matrix = ilk_load_csc_matrix;
                dev_priv->display.load_luts = broadwell_load_luts;
+               dev_priv->display.color_commit = hsw_color_commit;
        } else if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) {
-               dev_priv->display.load_csc_matrix = ilk_load_csc_matrix;
                dev_priv->display.load_luts = glk_load_luts;
+               dev_priv->display.color_commit = hsw_color_commit;
        } else {
                dev_priv->display.load_luts = i9xx_load_luts;
        }
 
         * clocks enabled
         */
        intel_color_load_luts(pipe_config);
+       intel_color_commit(pipe_config);
 
        if (dev_priv->display.initial_watermarks != NULL)
                dev_priv->display.initial_watermarks(old_intel_state, pipe_config);
 
        haswell_set_pipemisc(pipe_config);
 
-       intel_color_set_csc(pipe_config);
-
        intel_crtc->active = true;
 
        /* Display WA #1180: WaDisableScalarClockGating: glk, cnl */
         * clocks enabled
         */
        intel_color_load_luts(pipe_config);
+       intel_color_commit(pipe_config);
 
        if (INTEL_GEN(dev_priv) >= 11)
                icl_set_pipe_chicken(intel_crtc);
 
        i9xx_set_pipeconf(pipe_config);
 
-       intel_color_set_csc(pipe_config);
-
        intel_crtc->active = true;
 
        intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
        i9xx_pfit_enable(pipe_config);
 
        intel_color_load_luts(pipe_config);
+       intel_color_commit(pipe_config);
 
        dev_priv->display.initial_watermarks(old_intel_state,
                                             pipe_config);
        i9xx_pfit_enable(pipe_config);
 
        intel_color_load_luts(pipe_config);
+       intel_color_commit(pipe_config);
 
        if (dev_priv->display.initial_watermarks != NULL)
                dev_priv->display.initial_watermarks(old_intel_state,
 
        if (!modeset &&
            (intel_cstate->base.color_mgmt_changed ||
-            intel_cstate->update_pipe)) {
-               intel_color_set_csc(intel_cstate);
+            intel_cstate->update_pipe))
                intel_color_load_luts(intel_cstate);
-       }
 
        /* Perform vblank evasion around commit operation */
        intel_pipe_update_start(intel_cstate);
        if (modeset)
                goto out;
 
+       if (intel_cstate->base.color_mgmt_changed ||
+           intel_cstate->update_pipe)
+               intel_color_commit(intel_cstate);
+
        if (intel_cstate->update_pipe)
                intel_update_pipe_config(old_intel_cstate, intel_cstate);
        else if (INTEL_GEN(dev_priv) >= 9)