Blob Blame History Raw
From: Andrew Wong <andrew.wong1@amd.com>
Date: Thu, 22 Dec 2016 15:41:30 -0500
Subject: drm/amd/display: DAL3: HDR10 Infoframe encoding
Git-commit: 1646a6fe746d7e923774994d2020e1707dcda884
Patch-mainline: v4.15-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

- Add HDR metadata struct
- Add register programming calculations
- Added HDR metadata to surface and update_surface
- Add HDR info packet programming for DP port

Signed-off-by: Andrew Wong <andrew.wong1@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Harry Wentland <Harry.Wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c                 |    7 
 drivers/gpu/drm/amd/display/dc/core/dc_resource.c        |  115 ++++++++++++++-
 drivers/gpu/drm/amd/display/dc/core/dc_stream.c          |    1 
 drivers/gpu/drm/amd/display/dc/core/dc_surface.c         |    2 
 drivers/gpu/drm/amd/display/dc/dc.h                      |   23 ++-
 drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c  |   20 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h   |    2 
 drivers/gpu/drm/amd/display/include/hw_sequencer_types.h |    3 
 drivers/gpu/drm/amd/display/modules/color/color.c        |   16 +-
 drivers/gpu/drm/amd/display/modules/inc/mod_color.h      |   20 --
 10 files changed, 176 insertions(+), 33 deletions(-)

--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -1489,6 +1489,9 @@ void dc_update_surfaces_for_target(struc
 				stream->public.out_transfer_func =
 						updates[i].out_transfer_func;
 			}
+			if (updates[i].hdr_static_metadata)
+				surface->public.hdr_static_ctx =
+					*(updates[i].hdr_static_metadata);
 		}
 	}
 
@@ -1522,6 +1525,10 @@ void dc_update_surfaces_for_target(struc
 				}
 			}
 
+			if (updates[i].hdr_static_metadata) {
+				resource_build_info_frame(pipe_ctx);
+				core_dc->hwss.update_info_frame(pipe_ctx);
+			}
 			if (is_new_pipe_surface[j] ||
 					updates[i].in_transfer_func)
 				core_dc->hwss.set_input_transfer_func(
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -32,7 +32,6 @@
 #include "timing_generator.h"
 #include "transform.h"
 #include "set_mode_types.h"
-
 #include "virtual/virtual_stream_encoder.h"
 
 #include "dce80/dce80_resource.h"
@@ -1303,6 +1302,13 @@ static void translate_info_frame(const s
 						&hw_info_frame->vsc_packet,
 						sizeof(struct hw_info_packet));
 	}
+
+	if (hw_info_frame->hdrsmd_packet.valid) {
+		memmove(
+						&encoder_info_frame->hdrsmd,
+						&hw_info_frame->hdrsmd_packet,
+						sizeof(struct hw_info_packet));
+	}
 }
 
 static void set_avi_info_frame(
@@ -1720,6 +1726,108 @@ static void set_spd_info_packet(struct c
 	info_packet->valid = true;
 }
 
+static void set_hdr_static_info_packet(
+		struct core_surface *surface,
+		struct core_stream *stream,
+		struct hw_info_packet *info_packet)
+{
+	uint16_t i;
+	enum signal_type signal = stream->signal;
+
+	if (!surface)
+		return;
+
+	struct dc_hdr_static_metadata hdr_metadata =
+			surface->public.hdr_static_ctx;
+
+	if (dc_is_hdmi_signal(signal)) {
+		info_packet->valid = true;
+
+		info_packet->hb0 = 0x87;
+		info_packet->hb1 = 0x01;
+		info_packet->hb2 = 0x1A;
+		i = 1;
+	} else if (dc_is_dp_signal(signal)) {
+		info_packet->valid = true;
+
+		info_packet->hb0 = 0x00;
+		info_packet->hb1 = 0x87;
+		info_packet->hb2 = 0x1D;
+		info_packet->hb3 = (0x13 << 2);
+		i = 2;
+	}
+
+	uint32_t data;
+
+	data = hdr_metadata.is_hdr;
+	info_packet->sb[i++] = data ? 0x02 : 0x00;
+	info_packet->sb[i++] = 0x00;
+
+	data = hdr_metadata.chromaticity_green_x / 2;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.chromaticity_green_y / 2;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.chromaticity_blue_x / 2;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.chromaticity_blue_y / 2;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.chromaticity_red_x / 2;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.chromaticity_red_y / 2;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.chromaticity_white_point_x / 2;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.chromaticity_white_point_y / 2;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.max_luminance;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.min_luminance;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.maximum_content_light_level;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	data = hdr_metadata.maximum_frame_average_light_level;
+	info_packet->sb[i++] = data & 0xFF;
+	info_packet->sb[i++] = (data & 0xFF00) >> 8;
+
+	if (dc_is_hdmi_signal(signal)) {
+		uint32_t checksum = 0;
+
+		checksum += info_packet->hb0;
+		checksum += info_packet->hb1;
+		checksum += info_packet->hb2;
+
+		for (i = 1; i <= info_packet->hb2; i++)
+			checksum += info_packet->sb[i];
+
+		info_packet->sb[0] = 0x100 - checksum;
+	} else if (dc_is_dp_signal(signal)) {
+		info_packet->sb[0] = 0x01;
+		info_packet->sb[1] = 0x1A;
+	}
+}
+
 static void set_vsc_info_packet(struct core_stream *stream,
 		struct hw_info_packet *info_packet)
 {
@@ -1830,6 +1938,7 @@ void resource_build_info_frame(struct pi
 	info_frame.vendor_info_packet.valid = false;
 	info_frame.spd_packet.valid = false;
 	info_frame.vsc_packet.valid = false;
+	info_frame.hdrsmd_packet.valid = false;
 
 	signal = pipe_ctx->stream->signal;
 
@@ -1840,9 +1949,13 @@ void resource_build_info_frame(struct pi
 		set_vendor_info_packet(
 			pipe_ctx->stream, &info_frame.vendor_info_packet);
 		set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet);
+		set_hdr_static_info_packet(pipe_ctx->surface,
+				pipe_ctx->stream, &info_frame.hdrsmd_packet);
 	} else if (dc_is_dp_signal(signal)) {
 		set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet);
 		set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_packet);
+		set_hdr_static_info_packet(pipe_ctx->surface,
+				pipe_ctx->stream, &info_frame.hdrsmd_packet);
 	}
 
 	translate_info_frame(&info_frame,
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -82,7 +82,6 @@ static bool construct(struct core_stream
 	stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
 
 	stream->status.link = &stream->sink->link->public;
-
 	return true;
 }
 
--- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
@@ -66,6 +66,8 @@ struct transfer_func {
 static bool construct(struct dc_context *ctx, struct surface *surface)
 {
 	surface->protected.ctx = ctx;
+	memset(&surface->protected.public.hdr_static_ctx,
+			0, sizeof(struct dc_hdr_static_metadata));
 	return true;
 }
 
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -186,6 +186,25 @@ enum {
 	TRANSFER_FUNC_POINTS = 1025
 };
 
+struct dc_hdr_static_metadata {
+	bool is_hdr;
+
+	/* display chromaticities and white point in units of 0.00001 */
+	unsigned int chromaticity_green_x;
+	unsigned int chromaticity_green_y;
+	unsigned int chromaticity_blue_x;
+	unsigned int chromaticity_blue_y;
+	unsigned int chromaticity_red_x;
+	unsigned int chromaticity_red_y;
+	unsigned int chromaticity_white_point_x;
+	unsigned int chromaticity_white_point_y;
+
+	uint32_t min_luminance;
+	uint32_t max_luminance;
+	uint32_t maximum_content_light_level;
+	uint32_t maximum_frame_average_light_level;
+};
+
 enum dc_transfer_func_type {
 	TF_TYPE_PREDEFINED,
 	TF_TYPE_DISTRIBUTED_POINTS,
@@ -232,6 +251,8 @@ struct dc_surface {
 	bool horizontal_mirror;
 	enum plane_stereo_format stereo_format;
 
+	struct dc_hdr_static_metadata hdr_static_ctx;
+
 	const struct dc_gamma *gamma_correction;
 	const struct dc_transfer_func *in_transfer_func;
 };
@@ -267,7 +288,7 @@ struct dc_surface_update {
 	 */
 	/* gamma TO BE REMOVED */
 	struct dc_gamma *gamma;
-
+	struct dc_hdr_static_metadata *hdr_static_metadata;
 	struct dc_transfer_func *in_transfer_func;
 	struct dc_transfer_func *out_transfer_func;
 
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
@@ -518,6 +518,7 @@ static void dce110_stream_encoder_update
 		dce110_update_hdmi_info_packet(enc110, 0, &info_frame->vendor);
 		dce110_update_hdmi_info_packet(enc110, 1, &info_frame->gamut);
 		dce110_update_hdmi_info_packet(enc110, 2, &info_frame->spd);
+		dce110_update_hdmi_info_packet(enc110, 3, &info_frame->hdrsmd);
 	}
 
 }
@@ -554,16 +555,25 @@ static void dce110_stream_encoder_update
 	struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
 	uint32_t value = REG_READ(DP_SEC_CNTL);
 
-	if (info_frame->vsc.valid)
-		dce110_update_generic_info_packet(
+	dce110_update_generic_info_packet(
+				enc110,
+				0,  /* packetIndex */
+				&info_frame->vsc);
+	dce110_update_generic_info_packet(
 			enc110,
-			0,  /* packetIndex */
-			&info_frame->vsc);
+			2,  /* packetIndex */
+			&info_frame->spd);
+	dce110_update_generic_info_packet(
+			enc110,
+			3,  /* packetIndex */
+			&info_frame->hdrsmd);
 
 	/* enable/disable transmission of packet(s).
 	*  If enabled, packet transmission begins on the next frame
 	*/
-		REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid);
+	REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid);
+	REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid);
+	REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid);
 
 	/* This bit is the master enable bit.
 	* When enabling secondary stream engine,
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
@@ -31,6 +31,8 @@ struct encoder_info_frame {
 	struct encoder_info_packet spd;
 	/* video stream configuration */
 	struct encoder_info_packet vsc;
+	/* HDR Static MetaData */
+	struct encoder_info_packet hdrsmd;
 };
 
 struct encoder_unblank_param {
--- a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h
+++ b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h
@@ -88,7 +88,7 @@ struct hw_info_packet {
 	uint8_t hb1;
 	uint8_t hb2;
 	uint8_t hb3;
-	uint8_t sb[28];
+	uint8_t sb[32];
 };
 
 struct hw_info_frame {
@@ -100,6 +100,7 @@ struct hw_info_frame {
 	struct hw_info_packet spd_packet;
 	/* Video Stream Configuration */
 	struct hw_info_packet vsc_packet;
+	struct hw_info_packet hdrsmd_packet;
 };
 
 #endif
--- a/drivers/gpu/drm/amd/display/modules/color/color.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color.c
@@ -74,7 +74,7 @@ struct color_state {
 	struct color_gamut_data destination_gamut;
 	enum color_transfer_func input_transfer_function;
 	enum color_transfer_func output_transfer_function;
-	struct color_mastering_info mastering_info;
+	struct dc_hdr_static_metadata mastering_info;
 };
 
 struct core_color {
@@ -1970,7 +1970,7 @@ bool mod_color_set_white_point(struct mo
 
 bool mod_color_set_mastering_info(struct mod_color *mod_color,
 		const struct dc_stream **streams, int num_streams,
-		struct color_mastering_info *mastering_info)
+		const struct dc_hdr_static_metadata *mastering_info)
 {
 	struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
 	unsigned int stream_index, sink_index;
@@ -1980,14 +1980,14 @@ bool mod_color_set_mastering_info(struct
 				streams[stream_index]->sink);
 		memcpy(&core_color->state[sink_index].mastering_info,
 				mastering_info,
-				sizeof(struct color_mastering_info));
+				sizeof(struct dc_hdr_static_metadata));
 	}
 	return true;
 }
 
 bool mod_color_get_mastering_info(struct mod_color *mod_color,
 		const struct dc_sink *sink,
-		struct color_mastering_info *mastering_info)
+		struct dc_hdr_static_metadata *mastering_info)
 {
 	struct core_color *core_color =
 			MOD_COLOR_TO_CORE(mod_color);
@@ -1995,7 +1995,7 @@ bool mod_color_get_mastering_info(struct
 	unsigned int sink_index = sink_index_from_sink(core_color, sink);
 
 	memcpy(mastering_info, &core_color->state[sink_index].mastering_info,
-			sizeof(struct color_mastering_info));
+			sizeof(struct dc_hdr_static_metadata));
 
 	return true;
 }
@@ -2756,8 +2756,10 @@ bool mod_color_update_gamut_info(struct
 			else
 				output_tf->tf = TRANSFER_FUNCTION_SRGB;
 		}
+		/* 5. ---- POPULATE HDR METADATA ---- */
+		core_color->state[sink_index].mastering_info.is_hdr = is_hdr;
 
-		/* 5. ---- TODO: UPDATE INFOPACKETS ---- */
+		/* 6. ---- TODO: UPDATE INFOPACKETS ---- */
 
 		if (!mod_color_update_gamut_to_stream(
 				mod_color, streams, num_streams))
@@ -2769,6 +2771,8 @@ bool mod_color_update_gamut_info(struct
 		updates[0].gamma = core_color->state[sink_index].gamma;
 		updates[0].in_transfer_func = input_tf;
 		updates[0].out_transfer_func = output_tf;
+		updates[0].hdr_static_metadata =
+				&core_color->state[sink_index].mastering_info;
 
 		dc_update_surfaces_for_target(core_color->dc, updates, 1, NULL);
 
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h
@@ -87,22 +87,6 @@ enum hdr_tf_support_flag {
 	smpte_st2084 = 0x04
 };
 
-struct color_mastering_info {
-	unsigned int chromaticity_green_x;
-	unsigned int chromaticity_green_y;
-	unsigned int chromaticity_blue_x;
-	unsigned int chromaticity_blue_y;
-	unsigned int chromaticity_red_x;
-	unsigned int chromaticity_red_y;
-	unsigned int chromaticity_white_point_x;
-	unsigned int chromaticity_white_point_y;
-
-	unsigned int min_luminance;
-	unsigned int max_luminance;
-	unsigned int maximum_content_light_level;
-	unsigned int maximum_frame_average_light_level;
-};
-
 struct mod_color {
 	int dummy;
 };
@@ -206,11 +190,11 @@ bool mod_color_get_user_enable(struct mo
 
 bool mod_color_set_mastering_info(struct mod_color *mod_color,
 		const struct dc_stream **streams, int num_streams,
-		struct color_mastering_info *mastering_info);
+		const struct dc_hdr_static_metadata *mastering_info);
 
 bool mod_color_get_mastering_info(struct mod_color *mod_color,
 		const struct dc_sink *sink,
-		struct color_mastering_info *mastering_info);
+		struct dc_hdr_static_metadata *mastering_info);
 
 bool mod_color_set_user_enable(struct mod_color *mod_color,
 		const struct dc_stream **streams, int num_streams,