drm/amd/display: Add left edge pixel for YCbCr422/420 + ODM pipe split
authorGeorge Shen <george.shen@amd.com>
Wed, 7 Feb 2024 19:40:34 +0000 (14:40 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 20 Mar 2024 17:37:03 +0000 (13:37 -0400)
[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.

Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Acked-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: George Shen <george.shen@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@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 e7dc128f6284b45846f4eff707d3f052dab7b108..7f3e7c49a486bae9236cf59e27537150cd3006fc 100644 (file)
@@ -3167,6 +3167,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 ec4bf9432bdb1894396334e5558a3e126635aaec..798e6f7fa4e3f9834de2513dd6cf41d28c550e5a 100644 (file)
@@ -828,6 +828,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;
 }
 
@@ -1444,6 +1454,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;
@@ -1475,10 +1486,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 8b3536c380b8de70f500edef2c91f0169690cd3f..4dfc2dff5e01b19fc927567f301b31bfd93e0baf 100644 (file)
@@ -1579,6 +1579,11 @@ static void dcn20_detect_pipe_changes(struct dc_state *old_state,
        if (old_pipe->stream_res.tg != new_pipe->stream_res.tg)
                new_pipe->update_flags.bits.tg_changed = 1;
 
+       if (resource_is_pipe_type(new_pipe, OPP_HEAD)) {
+               if (old_pipe->stream_res.left_edge_extra_pixel != new_pipe->stream_res.left_edge_extra_pixel)
+                       new_pipe->update_flags.bits.opp_changed = 1;
+       }
+
        /*
         * Detect mpcc blending changes, only dpp inst and opp matter here,
         * mpccs getting removed/inserted update connected ones during their own
@@ -1962,6 +1967,11 @@ static void dcn20_program_pipe(
                        pipe_ctx->stream_res.opp,
                        &pipe_ctx->stream->bit_depth_params,
                        &pipe_ctx->stream->clamping);
+
+               if (resource_is_pipe_type(pipe_ctx, OPP_HEAD))
+                       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 b1b72e688f741ad5bd1d7109e854464e1a1ea639..e034cbb40620ce6bf2abb77b323c306238a9b0b8 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 77a60aa9f27bbfdfa8a652306e2366dc0eca4345..b14d52e52fa2f43c2f7fa46891513de0675c8180 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(