drm/amd/display: When enabling CRC, disable dither & enable truncation
authorLeo (Sunpeng) Li <sunpeng.li@amd.com>
Tue, 23 Jan 2018 22:43:37 +0000 (17:43 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 19 Feb 2018 19:20:09 +0000 (14:20 -0500)
When user-mode is using 8bpc, the hardware represents it internally
using a higher bit depth. This causes problems when comparing CRCs for
color managment tests.

We need to disable dithering as well, since it makes CRC values
non-deterministic.

It's easy to see why dithering needs to be disabled, The reason why
truncation also needs to be enabled is better described with an example.
Consider the folowing which tests the color transform matrix (CTM):

Expected CRC = FB_A -> Degamma (Bypassed) -> CTM (Bypassed)
                                                  |
                                                  v
                            Obtain CRC  <- Regamma(Bypassed)

Actual CRC = FB_B -> Degamma (Bypassed) -> CTM (0.5*Identity)
                                                  |
                                                  v
                            Obtain CRC  <- Regamma(Bypassed)

FB_A contains a solid red color at half intensity (127 @ 8bpc)
FB_B contains a solid red color at full intensity (255 @ 8bpc)

We expect that Expected CRC = Actual CRC, but that's not the case. When
the CTM is applied, the output is at half intensity, but also at a
higher bit depth within hardware. i.e. 255/2 = 127.5: not representable
in 8bpc, but can be at 10bpc. This causes the two CRC's to be different.

The solution is to truncate the output bit depth to the same as input
when enabling CRC capture. Since Linux only supports 8bpc, hard code
that for now.

Signed-off-by: Leo (Sunpeng) Li <sunpeng.li@amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
drivers/gpu/drm/amd/display/dc/core/dc.c

index e5fb53a56b734b5bce0b71f819e4ba93efd4305b..55aa379cfcbef386c3800a7b4288b5765f02b57b 100644 (file)
@@ -60,18 +60,25 @@ int amdgpu_dm_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name,
                return -EINVAL;
        }
 
+       /* When enabling CRC, we should also disable dithering. */
        if (source == AMDGPU_DM_PIPE_CRC_SOURCE_AUTO) {
                if (dc_stream_configure_crc(stream_state->ctx->dc,
                                            stream_state,
-                                           true, true))
+                                           true, true)) {
                        crtc_state->crc_enabled = true;
+                       dc_stream_set_dither_option(stream_state,
+                                                   DITHER_OPTION_TRUN8);
+               }
                else
                        return -EINVAL;
        } else {
                if (dc_stream_configure_crc(stream_state->ctx->dc,
                                            stream_state,
-                                           false, false))
+                                           false, false)) {
                        crtc_state->crc_enabled = false;
+                       dc_stream_set_dither_option(stream_state,
+                                                   DITHER_OPTION_DEFAULT);
+               }
                else
                        return -EINVAL;
        }
index ea5c35166ffac46a60b382fb45d2d83202d13a79..f4ffbf2e2cafab4d3c72174ff7614230e0496152 100644 (file)
@@ -316,7 +316,6 @@ void dc_stream_set_dither_option(struct dc_stream_state *stream,
                }
        }
 
-       memset(&params, 0, sizeof(params));
        if (!pipes)
                return;
        if (option > DITHER_OPTION_MAX)
@@ -324,9 +323,18 @@ void dc_stream_set_dither_option(struct dc_stream_state *stream,
 
        stream->dither_option = option;
 
-       resource_build_bit_depth_reduction_params(stream,
-                               &params);
+       memset(&params, 0, sizeof(params));
+       resource_build_bit_depth_reduction_params(stream, &params);
        stream->bit_depth_params = params;
+
+       if (pipes->plane_res.xfm &&
+           pipes->plane_res.xfm->funcs->transform_set_pixel_storage_depth) {
+               pipes->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
+                       pipes->plane_res.xfm,
+                       pipes->plane_res.scl_data.lb_params.depth,
+                       &stream->bit_depth_params);
+       }
+
        pipes->stream_res.opp->funcs->
                opp_program_bit_depth_reduction(pipes->stream_res.opp, &params);
 }