drm/i915: Move CSC load back into .color_commit_arm() when PSR is enabled on skl/glk
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Mon, 20 Mar 2023 09:54:34 +0000 (11:54 +0200)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 21 Mar 2023 16:02:50 +0000 (18:02 +0200)
SKL/GLK CSC unit suffers from a nasty issue where a CSC
coeff/offset register read or write between DC5 exit and
PSR exit will undo the CSC arming performed by DMC, and
then during PSR exit the hardware will latch zeroes into
the active CSC registers. This causes any plane going
through the CSC to output all black.

We can sidestep the issue by making sure the PSR exit has
already actually happened before we touch the CSC coeff/offset
registers. Easiest way to guarantee that is to just move the
CSC programming back into the .color_commir_arm() as we force
a PSR exit (and crucially wait for it to actually happen)
prior to touching the arming registers.

When PSR (and thus also DC states) are disabled we don't
have anything to worry about, so we can keep using the
more optional _noarm() hook for writing the CSC registers.

Cc: <stable@vger.kernel.org> #v5.19+
Cc: Manasi Navare <navaremanasi@google.com>
Cc: Drew Davenport <ddavenport@chromium.org>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Jouni Högander <jouni.hogander@intel.com>
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/8283
Fixes: d13dde449580 ("drm/i915: Split pipe+output CSC programming to noarm+arm pair")
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230320095438.17328-3-ville.syrjala@linux.intel.com
Reviewed-by: Imre Deak <imre.deak@intel.com>
drivers/gpu/drm/i915/display/intel_color.c

index 6096a80..a503d82 100644 (file)
@@ -617,6 +617,22 @@ static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
        icl_load_csc_matrix(crtc_state);
 }
 
+static void skl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
+{
+       /*
+        * Possibly related to display WA #1184, SKL CSC loses the latched
+        * CSC coeff/offset register values if the CSC registers are disarmed
+        * between DC5 exit and PSR exit. This will cause the plane(s) to
+        * output all black (until CSC_MODE is rearmed and properly latched).
+        * Once PSR exit (and proper register latching) has occurred the
+        * danger is over. Thus when PSR is enabled the CSC coeff/offset
+        * register programming will be peformed from skl_color_commit_arm()
+        * which is called after PSR exit.
+        */
+       if (!crtc_state->has_psr)
+               ilk_load_csc_matrix(crtc_state);
+}
+
 static void ilk_color_commit_noarm(const struct intel_crtc_state *crtc_state)
 {
        ilk_load_csc_matrix(crtc_state);
@@ -659,6 +675,9 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
        enum pipe pipe = crtc->pipe;
        u32 val = 0;
 
+       if (crtc_state->has_psr)
+               ilk_load_csc_matrix(crtc_state);
+
        /*
         * We don't (yet) allow userspace to control the pipe background color,
         * so force it to black, but apply pipe gamma and CSC appropriately
@@ -3102,7 +3121,7 @@ static const struct intel_color_funcs icl_color_funcs = {
 
 static const struct intel_color_funcs glk_color_funcs = {
        .color_check = glk_color_check,
-       .color_commit_noarm = ilk_color_commit_noarm,
+       .color_commit_noarm = skl_color_commit_noarm,
        .color_commit_arm = skl_color_commit_arm,
        .load_luts = glk_load_luts,
        .read_luts = glk_read_luts,
@@ -3111,7 +3130,7 @@ static const struct intel_color_funcs glk_color_funcs = {
 
 static const struct intel_color_funcs skl_color_funcs = {
        .color_check = ivb_color_check,
-       .color_commit_noarm = ilk_color_commit_noarm,
+       .color_commit_noarm = skl_color_commit_noarm,
        .color_commit_arm = skl_color_commit_arm,
        .load_luts = bdw_load_luts,
        .read_luts = bdw_read_luts,