drm/amd/display: Add left edge pixel for YCbCr422/420 + ODM pipe split
authorGeorge Shen <george.shen@amd.com>
Sat, 6 Jan 2024 03:01:03 +0000 (22:01 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 7 Feb 2024 17:26:22 +0000 (12:26 -0500)
[Why]
Currently 3-tap chroma subsampling is used for YCbCr422/420. When ODM
pipesplit is used, pixels on the left edge of ODM slices need one extra
pixel from the right edge of the previous slice to calculate the correct
chroma value.

Without this change, the chroma value is slightly different than
expected. This is usually imperceptible visually, but it impacts test
pattern CRCs for compliance test automation.

[How]
Update logic to use the register for adding extra left edge pixel for
YCbCr422/420 ODM cases.

Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com>
Signed-off-by: George Shen <george.shen@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/inc/resource.h

index eb803d4d34786fb99078cffb748dbbb6b16a25b3..e58bd0861dc0a182eaf6c32c41158f3849f2c9af 100644 (file)
@@ -3090,6 +3090,10 @@ static bool update_planes_and_stream_state(struct dc *dc,
 
                        if (otg_master && otg_master->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE)
                                resource_build_test_pattern_params(&context->res_ctx, otg_master);
+
+                       if (otg_master && (otg_master->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422 ||
+                                       otg_master->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420))
+                               resource_build_subsampling_params(&context->res_ctx, otg_master);
                }
        }
 
index 259ccbe858b492b610c80ad2ae4c0a4f35c9ec76..528d3eb245ea06aa323a46d144a4731aa05cde3a 100644 (file)
@@ -822,6 +822,16 @@ static struct rect calculate_odm_slice_in_timing_active(struct pipe_ctx *pipe_ct
                        stream->timing.v_border_bottom +
                        stream->timing.v_border_top;
 
+       /* Recout for ODM slices after the first slice need one extra left edge pixel
+        * for 3-tap chroma subsampling.
+        */
+       if (odm_slice_idx > 0 &&
+                       (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422 ||
+                               pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)) {
+               odm_rec.x -= 1;
+               odm_rec.width += 1;
+       }
+
        return odm_rec;
 }
 
@@ -1438,6 +1448,7 @@ void resource_build_test_pattern_params(struct resource_context *res_ctx,
        enum controller_dp_test_pattern controller_test_pattern;
        enum controller_dp_color_space controller_color_space;
        enum dc_color_depth color_depth = otg_master->stream->timing.display_color_depth;
+       enum dc_pixel_encoding pixel_encoding = otg_master->stream->timing.pixel_encoding;
        int h_active = otg_master->stream->timing.h_addressable +
                otg_master->stream->timing.h_border_left +
                otg_master->stream->timing.h_border_right;
@@ -1469,10 +1480,36 @@ void resource_build_test_pattern_params(struct resource_context *res_ctx,
                else
                        params->width = last_odm_slice_width;
 
+               /* Extra left edge pixel is required for 3-tap chroma subsampling. */
+               if (i != 0 && (pixel_encoding == PIXEL_ENCODING_YCBCR422 ||
+                               pixel_encoding == PIXEL_ENCODING_YCBCR420)) {
+                       params->offset -= 1;
+                       params->width += 1;
+               }
+
                offset += odm_slice_width;
        }
 }
 
+void resource_build_subsampling_params(struct resource_context *res_ctx,
+       struct pipe_ctx *otg_master)
+{
+       struct pipe_ctx *opp_heads[MAX_PIPES];
+       int odm_cnt = 1;
+       int i;
+
+       odm_cnt = resource_get_opp_heads_for_otg_master(otg_master, res_ctx, opp_heads);
+
+       /* For ODM slices after the first slice, extra left edge pixel is required
+        * for 3-tap chroma subsampling.
+        */
+       if (otg_master->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422 ||
+                       otg_master->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
+               for (i = 0; i < odm_cnt; i++)
+                       opp_heads[i]->stream_res.left_edge_extra_pixel = (i == 0) ? false : true;
+       }
+}
+
 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
 {
        const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
index d26353dafc1cca85fb844d57ff67c5cedcd9fecd..68268803e754226029e9aaa52e794c30d24904c1 100644 (file)
@@ -1573,7 +1573,8 @@ static void dcn20_detect_pipe_changes(struct dc_state *old_state,
         * makes this assumption at the moment with how hubp reset is matched to
         * same index mpcc reset.
         */
-       if (old_pipe->stream_res.opp != new_pipe->stream_res.opp)
+       if (old_pipe->stream_res.opp != new_pipe->stream_res.opp ||
+                       old_pipe->stream_res.left_edge_extra_pixel != new_pipe->stream_res.left_edge_extra_pixel)
                new_pipe->update_flags.bits.opp_changed = 1;
        if (old_pipe->stream_res.tg != new_pipe->stream_res.tg)
                new_pipe->update_flags.bits.tg_changed = 1;
@@ -1959,6 +1960,10 @@ static void dcn20_program_pipe(
                        pipe_ctx->stream_res.opp,
                        &pipe_ctx->stream->bit_depth_params,
                        &pipe_ctx->stream->clamping);
+
+               pipe_ctx->stream_res.opp->funcs->opp_program_left_edge_extra_pixel(
+                       pipe_ctx->stream_res.opp,
+                       pipe_ctx->stream_res.left_edge_extra_pixel);
        }
 
        /* Set ABM pipe after other pipe configurations done */
index 3a6bf77a68732166d320dbea642929c3201d3e01..ebb659c327e06f7a3baf6e975b7f745536441920 100644 (file)
@@ -333,6 +333,8 @@ struct stream_resource {
        uint8_t gsl_group;
 
        struct test_pattern_params test_pattern_params;
+
+       bool left_edge_extra_pixel;
 };
 
 struct plane_resource {
index 2eae2f3e846d8ab431a7f57744f5349c7deb5cab..77e87c8de7778ee7305f02f21982a574462d38d2 100644 (file)
@@ -107,6 +107,10 @@ void resource_build_test_pattern_params(
                struct resource_context *res_ctx,
                struct pipe_ctx *pipe_ctx);
 
+void resource_build_subsampling_params(
+               struct resource_context *res_ctx,
+               struct pipe_ctx *pipe_ctx);
+
 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx);
 
 enum dc_status resource_build_scaling_params_for_context(