From: Peterson Guo <[email protected]>

[WHY]
On some cards when odm is used, the monitor will have 2 separate pipes
split vertically. When compression is used on the YCbCr colour space on
the second pipe to have correct colours, we need to read a pixel from the
end of first pipe to accurately display colours. Hardware was programmed
properly to account for this extra pixel but it was not calculated
properly in software causing a split screen on some monitors.

[HOW]
The fix adjusts the second pipe's viewport and timings if the pixel
encoding is YCbCr422 or YCbCr420.

Cc: Mario Limonciello <[email protected]>
Cc: Alex Deucher <[email protected]>
Cc: [email protected]
Reviewed-by: George Shen <[email protected]>
Signed-off-by: Peterson Guo <[email protected]>
Signed-off-by: Alex Hung <[email protected]>
---
 .../dc/resource/dcn20/dcn20_resource.c        | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c 
b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
index 189d0c85872e..7a5b9aa5292c 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
@@ -1510,6 +1510,7 @@ bool dcn20_split_stream_for_odm(
 
        if (prev_odm_pipe->plane_state) {
                struct scaler_data *sd = &prev_odm_pipe->plane_res.scl_data;
+               struct output_pixel_processor *opp = 
next_odm_pipe->stream_res.opp;
                int new_width;
 
                /* HACTIVE halved for odm combine */
@@ -1543,7 +1544,28 @@ bool dcn20_split_stream_for_odm(
                sd->viewport_c.x += dc_fixpt_floor(dc_fixpt_mul_int(
                                sd->ratios.horz_c, sd->h_active - 
sd->recout.x));
                sd->recout.x = 0;
+
+               /*
+                * When odm is used in YcbCr422 or 420 colour space, a split 
screen
+                * will be seen with the previous calculations since the extra 
left
+                *  edge pixel is accounted for in fmt but not in viewport.
+                *
+                * Below are calculations which fix the split by fixing the 
calculations
+                * if there is an extra left edge pixel.
+                */
+               if (opp && opp->funcs->opp_get_left_edge_extra_pixel_count
+                               && 
opp->funcs->opp_get_left_edge_extra_pixel_count(
+                                       opp, 
next_odm_pipe->stream->timing.pixel_encoding,
+                                       resource_is_pipe_type(next_odm_pipe, 
OTG_MASTER)) == 1) {
+                       sd->h_active += 1;
+                       sd->recout.width += 1;
+                       sd->viewport.x -= 
dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
+                       sd->viewport_c.x -= 
dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
+                       sd->viewport_c.width += 
dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
+                       sd->viewport.width += 
dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
+               }
        }
+
        if (!next_odm_pipe->top_pipe)
                next_odm_pipe->stream_res.opp = 
pool->opps[next_odm_pipe->pipe_idx];
        else
@@ -2132,6 +2154,7 @@ bool dcn20_fast_validate_bw(
                        ASSERT(0);
                }
        }
+
        /* Actual dsc count per stream dsc validation*/
        if (!dcn20_validate_dsc(dc, context)) {
                
context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states]
 =
-- 
2.43.0

Reply via email to