Commit abdd2768 authored by Fangzhi Zuo's avatar Fangzhi Zuo Committed by Alex Deucher
Browse files

drm/amd/display: Prune Invalid Modes For HDMI Output



[Why]
1. HDMI does not have 6 bpc support. Having 6 bpc pass validation
does not comply with spec.
2. Validate 420 only for native HDMI, but not apply to pcon use
case.
3. Current mode validation log is not readable.

[how]
1. Cap 8 bpc for dp-hdmi converter.
2. Validate yuv420 for pcon use case as well,
   if rgb/yuv444 8bpc cannot fit into pcon bw limitation of
   the link from the converter to HDMI sink.
3. Add readable pixel_format and color_depth into debug log.

Reviewed-by: default avatarWayne Lin <wayne.lin@amd.com>
Signed-off-by: default avatarFangzhi Zuo <Jerry.Zuo@amd.com>
Signed-off-by: default avatarZaeem Mohamed <zaeem.mohamed@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 38077562
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -7323,10 +7323,15 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
	const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL;
	int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8;
	enum dc_status dc_result = DC_OK;
	uint8_t bpc_limit = 6;

	if (!dm_state)
		return NULL;

	if (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
	    aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
		bpc_limit = 8;

	do {
		stream = create_stream_for_sink(connector, drm_mode,
						dm_state, old_stream,
@@ -7347,11 +7352,12 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
			dc_result = dm_validate_stream_and_context(adev->dm.dc, stream);

		if (dc_result != DC_OK) {
			DRM_DEBUG_KMS("Mode %dx%d (clk %d) failed DC validation with error %d (%s)\n",
			DRM_DEBUG_KMS("Mode %dx%d (clk %d) pixel_encoding:%s color_depth:%s failed validation -- %s\n",
				      drm_mode->hdisplay,
				      drm_mode->vdisplay,
				      drm_mode->clock,
				      dc_result,
				      dc_pixel_encoding_to_str(stream->timing.pixel_encoding),
				      dc_color_depth_to_str(stream->timing.display_color_depth),
				      dc_status_to_str(dc_result));

			dc_stream_release(stream);
@@ -7359,10 +7365,13 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
			requested_bpc -= 2; /* lower bpc to retry validation */
		}

	} while (stream == NULL && requested_bpc >= 6);
	} while (stream == NULL && requested_bpc >= bpc_limit);

	if (dc_result == DC_FAIL_ENC_VALIDATE && !aconnector->force_yuv420_output) {
		DRM_DEBUG_KMS("Retry forcing YCbCr420 encoding\n");
	if ((dc_result == DC_FAIL_ENC_VALIDATE ||
	     dc_result == DC_EXCEED_DONGLE_CAP) &&
	     !aconnector->force_yuv420_output) {
		DRM_DEBUG_KMS("%s:%d Retry forcing yuv420 encoding\n",
				     __func__, __LINE__);

		aconnector->force_yuv420_output = true;
		stream = create_validate_stream_for_sink(aconnector, drm_mode,
+40 −0
Original line number Diff line number Diff line
@@ -392,3 +392,43 @@ char *dc_status_to_str(enum dc_status status)

	return "Unexpected status error";
}

char *dc_pixel_encoding_to_str(enum dc_pixel_encoding pixel_encoding)
{
	switch (pixel_encoding) {
	case PIXEL_ENCODING_RGB:
		return "RGB";
	case PIXEL_ENCODING_YCBCR422:
		return "YUV422";
	case PIXEL_ENCODING_YCBCR444:
		return "YUV444";
	case PIXEL_ENCODING_YCBCR420:
		return "YUV420";
	default:
		return "Unknown";
	}
}

char *dc_color_depth_to_str(enum dc_color_depth color_depth)
{
	switch (color_depth) {
	case COLOR_DEPTH_666:
		return "6-bpc";
	case COLOR_DEPTH_888:
		return "8-bpc";
	case COLOR_DEPTH_101010:
		return "10-bpc";
	case COLOR_DEPTH_121212:
		return "12-bpc";
	case COLOR_DEPTH_141414:
		return "14-bpc";
	case COLOR_DEPTH_161616:
		return "16-bpc";
	case COLOR_DEPTH_999:
		return "9-bpc";
	case COLOR_DEPTH_111111:
		return "11-bpc";
	default:
		return "Unknown";
	}
}
+3 −3
Original line number Diff line number Diff line
@@ -812,12 +812,12 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream)
			stream->dst.height,
			stream->output_color_space);
	DC_LOG_DC(
			"\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixelencoder:%d, displaycolorDepth:%d\n",
			"\tpix_clk_khz: %d, h_total: %d, v_total: %d, pixel_encoding:%s, color_depth:%s\n",
			stream->timing.pix_clk_100hz / 10,
			stream->timing.h_total,
			stream->timing.v_total,
			stream->timing.pixel_encoding,
			stream->timing.display_color_depth);
			dc_pixel_encoding_to_str(stream->timing.pixel_encoding),
			dc_color_depth_to_str(stream->timing.display_color_depth));
	DC_LOG_DC(
			"\tlink: %d\n",
			stream->link->link_index);
+2 −0
Original line number Diff line number Diff line
@@ -60,5 +60,7 @@ enum dc_status {
};

char *dc_status_to_str(enum dc_status status);
char *dc_pixel_encoding_to_str(enum dc_pixel_encoding pixel_encoding);
char *dc_color_depth_to_str(enum dc_color_depth color_depth);

#endif /* _CORE_STATUS_H_ */