Commit 1646a6fe authored by Andrew Wong's avatar Andrew Wong Committed by Alex Deucher
Browse files

drm/amd/display: DAL3: HDR10 Infoframe encoding



- 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: default avatarAndrew Wong <andrew.wong1@amd.com>
Reviewed-by: default avatarAric Cyr <Aric.Cyr@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c89a58cd
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1489,6 +1489,9 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda
				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(struct dc *dc, struct dc_surface_update *upda
				}
			}

			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(
+114 −1
Original line number Diff line number Diff line
@@ -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 struct hw_info_frame *hw_info_frame,
						&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 core_stream *stream,
	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 pipe_ctx *pipe_ctx)
	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 pipe_ctx *pipe_ctx)
		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,
+0 −1
Original line number Diff line number Diff line
@@ -82,7 +82,6 @@ static bool construct(struct core_stream *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;
}

+2 −0
Original line number Diff line number Diff line
@@ -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;
}

+22 −1
Original line number Diff line number Diff line
@@ -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;

Loading