[PATCH 16/25] drm/amd/display: HDR Enablement For Applications

Harry Wentland harry.wentland at amd.com
Mon Jan 23 14:36:04 UTC 2017


From: Amy Zhang <Amy.Zhang at amd.com>

- Made sure dest color space is updated in stream and info frame
- Optimized segment distribution algorithm for regamma mapping

Change-Id: Ia9bb4e56719e23a9827080194d89f715ee5fde29
Signed-off-by: Amy Zhang <Amy.Zhang at amd.com>
Acked-by: Harry Wentland <Harry.Wentland at amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr at amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc_resource.c  | 14 ++++
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h       |  6 +-
 .../amd/display/dc/dce110/dce110_hw_sequencer.c    | 94 ++++++++++++++++++----
 drivers/gpu/drm/amd/display/dc/inc/hw/transform.h  | 11 +++
 4 files changed, 107 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index fe79a2890247..8b41c7708562 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1310,6 +1310,20 @@ static void set_avi_info_frame(
 		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
 				COLORIMETRY_NO_DATA;
 
+	if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
+		color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
+		color_space == COLOR_SPACE_2020_YCBCR) {
+		info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 =
+				COLORIMETRYEX_BT2020RGBYCBCR;
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_EXTENDED;
+	} else if (color_space == COLOR_SPACE_ADOBERGB) {
+		info_frame.avi_info_packet.info_packet_hdmi.bits.EC0_EC2 =
+				COLORIMETRYEX_ADOBERGB;
+		info_frame.avi_info_packet.info_packet_hdmi.bits.C0_C1 =
+				COLORIMETRY_EXTENDED;
+	}
+
 	/* TODO: un-hardcode aspect ratio */
 	aspect = stream->public.timing.aspect_ratio;
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index 00958bdbb417..a17e7bc96f9e 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -444,7 +444,11 @@ enum dc_color_space {
 	COLOR_SPACE_YCBCR601,
 	COLOR_SPACE_YCBCR709,
 	COLOR_SPACE_YCBCR601_LIMITED,
-	COLOR_SPACE_YCBCR709_LIMITED
+	COLOR_SPACE_YCBCR709_LIMITED,
+	COLOR_SPACE_2020_RGB_FULLRANGE,
+	COLOR_SPACE_2020_RGB_LIMITEDRANGE,
+	COLOR_SPACE_2020_YCBCR,
+	COLOR_SPACE_ADOBERGB,
 };
 
 enum dc_quantization_range {
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index ee393a168c84..e9fd83e9af79 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -594,39 +594,88 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func
 	struct fixed31_32 y3_max;
 
 	int32_t segment_start, segment_end;
-	uint32_t hw_points, start_index;
-	uint32_t i, j;
+	uint32_t i, j, k, seg_distr[16], increment, start_index;
+	uint32_t hw_points = 0;
 
 	memset(regamma_params, 0, sizeof(struct pwl_params));
 
 	if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
-		/* 16 segments x 16 points
+		/* 16 segments
 		 * segments are from 2^-11 to 2^5
 		 */
 		segment_start = -11;
 		segment_end = 5;
 
+		seg_distr[0] = 2;
+		seg_distr[1] = 2;
+		seg_distr[2] = 2;
+		seg_distr[3] = 2;
+		seg_distr[4] = 2;
+		seg_distr[5] = 2;
+		seg_distr[6] = 3;
+		seg_distr[7] = 4;
+		seg_distr[8] = 4;
+		seg_distr[9] = 4;
+		seg_distr[10] = 4;
+		seg_distr[11] = 5;
+		seg_distr[12] = 5;
+		seg_distr[13] = 5;
+		seg_distr[14] = 5;
+		seg_distr[15] = 5;
+
 	} else {
-		/* 10 segments x 16 points
+		/* 10 segments
 		 * segment is from 2^-10 to 2^0
 		 */
 		segment_start = -10;
 		segment_end = 0;
+
+		seg_distr[0] = 3;
+		seg_distr[1] = 4;
+		seg_distr[2] = 4;
+		seg_distr[3] = 4;
+		seg_distr[4] = 4;
+		seg_distr[5] = 4;
+		seg_distr[6] = 4;
+		seg_distr[7] = 4;
+		seg_distr[8] = 5;
+		seg_distr[9] = 5;
+		seg_distr[10] = -1;
+		seg_distr[11] = -1;
+		seg_distr[12] = -1;
+		seg_distr[13] = -1;
+		seg_distr[14] = -1;
+		seg_distr[15] = -1;
+	}
+
+	for (k = 0; k < 16; k++) {
+		if (seg_distr[k] != -1)
+			hw_points += (1 << seg_distr[k]);
 	}
 
-	hw_points = (segment_end - segment_start) * 16;
 	j = 0;
-	/* (segment + 25) * 32, every 2nd point */
-	start_index = (segment_start + 25) * 32;
-	for (i = start_index; i <= 1025; i += 2) {
-		if (j > hw_points)
-			break;
-		rgb_resulted[j].red = output_tf->tf_pts.red[i];
-		rgb_resulted[j].green = output_tf->tf_pts.green[i];
-		rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
-		j++;
+	for (k = 0; k < (segment_end - segment_start); k++) {
+		increment = 32 / (1 << seg_distr[k]);
+		start_index = (segment_start + k + 25) * 32;
+		for (i = start_index; i < start_index + 32; i += increment) {
+			if (j == hw_points - 1)
+				break;
+			rgb_resulted[j].red = output_tf->tf_pts.red[i];
+			rgb_resulted[j].green = output_tf->tf_pts.green[i];
+			rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
+			j++;
+		}
 	}
 
+	/* last point */
+	start_index = (segment_end + 25) * 32;
+	rgb_resulted[hw_points - 1].red =
+			output_tf->tf_pts.red[start_index];
+	rgb_resulted[hw_points - 1].green =
+			output_tf->tf_pts.green[start_index];
+	rgb_resulted[hw_points - 1].blue =
+			output_tf->tf_pts.blue[start_index];
+
 	arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
 			dal_fixed31_32_from_int(segment_start));
 	arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
@@ -677,11 +726,22 @@ static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func
 
 	regamma_params->hw_points_num = hw_points;
 
-	for (i = 0; i < segment_end - segment_start; i++) {
-		regamma_params->arr_curve_points[i].offset = i * 16;
-		regamma_params->arr_curve_points[i].segments_num = 4;
+	i = 1;
+	for (k = 0; k < 16 && i < 16; k++) {
+		if (seg_distr[k] != -1) {
+			regamma_params->arr_curve_points[k].segments_num =
+					seg_distr[k];
+			regamma_params->arr_curve_points[i].offset =
+					regamma_params->arr_curve_points[k].
+					offset + (1 << seg_distr[k]);
+		}
+		i++;
 	}
 
+	if (seg_distr[k] != -1)
+		regamma_params->arr_curve_points[k].segments_num =
+				seg_distr[k];
+
 	struct pwl_result_data *rgb = rgb_resulted;
 	struct pwl_result_data *rgb_plus_1 = rgb_resulted + 1;
 
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
index ef743b70b3e9..a510d3fe48ec 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
@@ -47,6 +47,17 @@ enum colorimetry {
 	COLORIMETRY_EXTENDED = 3
 };
 
+enum colorimetry_ext {
+	COLORIMETRYEX_XVYCC601 = 0,
+	COLORIMETRYEX_XVYCC709 = 1,
+	COLORIMETRYEX_SYCC601 = 2,
+	COLORIMETRYEX_ADOBEYCC601 = 3,
+	COLORIMETRYEX_ADOBERGB = 4,
+	COLORIMETRYEX_BT2020YCC = 5,
+	COLORIMETRYEX_BT2020RGBYCBCR = 6,
+	COLORIMETRYEX_RESERVED = 7
+};
+
 enum active_format_info {
 	ACTIVE_FORMAT_NO_DATA = 0,
 	ACTIVE_FORMAT_VALID = 1
-- 
2.9.3



More information about the amd-gfx mailing list