Commit 63e7ee67 authored by Peterson Guo's avatar Peterson Guo Committed by Alex Deucher
Browse files

drm/amd/display: Add a left edge pixel if in YCbCr422 or YCbCr420 and odm



[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 <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Reviewed-by: default avatarGeorge Shen <george.shen@amd.com>
Signed-off-by: default avatarPeterson Guo <peterson.guo@amd.com>
Signed-off-by: default avatarAlex Hung <alex.hung@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 55ed120d
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -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] =