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

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
...@@ -1489,6 +1489,9 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda ...@@ -1489,6 +1489,9 @@ void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *upda
stream->public.out_transfer_func = stream->public.out_transfer_func =
updates[i].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 ...@@ -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] || if (is_new_pipe_surface[j] ||
updates[i].in_transfer_func) updates[i].in_transfer_func)
core_dc->hwss.set_input_transfer_func( core_dc->hwss.set_input_transfer_func(
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include "timing_generator.h" #include "timing_generator.h"
#include "transform.h" #include "transform.h"
#include "set_mode_types.h" #include "set_mode_types.h"
#include "virtual/virtual_stream_encoder.h" #include "virtual/virtual_stream_encoder.h"
#include "dce80/dce80_resource.h" #include "dce80/dce80_resource.h"
...@@ -1303,6 +1302,13 @@ static void translate_info_frame(const struct hw_info_frame *hw_info_frame, ...@@ -1303,6 +1302,13 @@ static void translate_info_frame(const struct hw_info_frame *hw_info_frame,
&hw_info_frame->vsc_packet, &hw_info_frame->vsc_packet,
sizeof(struct hw_info_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( static void set_avi_info_frame(
...@@ -1720,6 +1726,108 @@ static void set_spd_info_packet(struct core_stream *stream, ...@@ -1720,6 +1726,108 @@ static void set_spd_info_packet(struct core_stream *stream,
info_packet->valid = true; 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, static void set_vsc_info_packet(struct core_stream *stream,
struct hw_info_packet *info_packet) struct hw_info_packet *info_packet)
{ {
...@@ -1830,6 +1938,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) ...@@ -1830,6 +1938,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
info_frame.vendor_info_packet.valid = false; info_frame.vendor_info_packet.valid = false;
info_frame.spd_packet.valid = false; info_frame.spd_packet.valid = false;
info_frame.vsc_packet.valid = false; info_frame.vsc_packet.valid = false;
info_frame.hdrsmd_packet.valid = false;
signal = pipe_ctx->stream->signal; signal = pipe_ctx->stream->signal;
...@@ -1840,9 +1949,13 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx) ...@@ -1840,9 +1949,13 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
set_vendor_info_packet( set_vendor_info_packet(
pipe_ctx->stream, &info_frame.vendor_info_packet); pipe_ctx->stream, &info_frame.vendor_info_packet);
set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_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)) { } else if (dc_is_dp_signal(signal)) {
set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet); set_vsc_info_packet(pipe_ctx->stream, &info_frame.vsc_packet);
set_spd_info_packet(pipe_ctx->stream, &info_frame.spd_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, translate_info_frame(&info_frame,
......
...@@ -82,7 +82,6 @@ static bool construct(struct core_stream *stream, ...@@ -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->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
stream->status.link = &stream->sink->link->public; stream->status.link = &stream->sink->link->public;
return true; return true;
} }
......
...@@ -66,6 +66,8 @@ struct transfer_func { ...@@ -66,6 +66,8 @@ struct transfer_func {
static bool construct(struct dc_context *ctx, struct surface *surface) static bool construct(struct dc_context *ctx, struct surface *surface)
{ {
surface->protected.ctx = ctx; surface->protected.ctx = ctx;
memset(&surface->protected.public.hdr_static_ctx,
0, sizeof(struct dc_hdr_static_metadata));
return true; return true;
} }
......
...@@ -186,6 +186,25 @@ enum { ...@@ -186,6 +186,25 @@ enum {
TRANSFER_FUNC_POINTS = 1025 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 { enum dc_transfer_func_type {
TF_TYPE_PREDEFINED, TF_TYPE_PREDEFINED,
TF_TYPE_DISTRIBUTED_POINTS, TF_TYPE_DISTRIBUTED_POINTS,
...@@ -232,6 +251,8 @@ struct dc_surface { ...@@ -232,6 +251,8 @@ struct dc_surface {
bool horizontal_mirror; bool horizontal_mirror;
enum plane_stereo_format stereo_format; enum plane_stereo_format stereo_format;
struct dc_hdr_static_metadata hdr_static_ctx;
const struct dc_gamma *gamma_correction; const struct dc_gamma *gamma_correction;
const struct dc_transfer_func *in_transfer_func; const struct dc_transfer_func *in_transfer_func;
}; };
...@@ -267,7 +288,7 @@ struct dc_surface_update { ...@@ -267,7 +288,7 @@ struct dc_surface_update {
*/ */
/* gamma TO BE REMOVED */ /* gamma TO BE REMOVED */
struct dc_gamma *gamma; struct dc_gamma *gamma;
struct dc_hdr_static_metadata *hdr_static_metadata;
struct dc_transfer_func *in_transfer_func; struct dc_transfer_func *in_transfer_func;
struct dc_transfer_func *out_transfer_func; struct dc_transfer_func *out_transfer_func;
......
...@@ -518,6 +518,7 @@ static void dce110_stream_encoder_update_hdmi_info_packets( ...@@ -518,6 +518,7 @@ static void dce110_stream_encoder_update_hdmi_info_packets(
dce110_update_hdmi_info_packet(enc110, 0, &info_frame->vendor); 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, 1, &info_frame->gamut);
dce110_update_hdmi_info_packet(enc110, 2, &info_frame->spd); 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_dp_info_packets( ...@@ -554,16 +555,25 @@ static void dce110_stream_encoder_update_dp_info_packets(
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
uint32_t value = REG_READ(DP_SEC_CNTL); 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,
2, /* packetIndex */
&info_frame->spd);
dce110_update_generic_info_packet(
enc110, enc110,
0, /* packetIndex */ 3, /* packetIndex */
&info_frame->vsc); &info_frame->hdrsmd);
/* enable/disable transmission of packet(s). /* enable/disable transmission of packet(s).
* If enabled, packet transmission begins on the next frame * 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. /* This bit is the master enable bit.
* When enabling secondary stream engine, * When enabling secondary stream engine,
......
...@@ -31,6 +31,8 @@ struct encoder_info_frame { ...@@ -31,6 +31,8 @@ struct encoder_info_frame {
struct encoder_info_packet spd; struct encoder_info_packet spd;
/* video stream configuration */ /* video stream configuration */
struct encoder_info_packet vsc; struct encoder_info_packet vsc;
/* HDR Static MetaData */
struct encoder_info_packet hdrsmd;
}; };
struct encoder_unblank_param { struct encoder_unblank_param {
......
...@@ -88,7 +88,7 @@ struct hw_info_packet { ...@@ -88,7 +88,7 @@ struct hw_info_packet {
uint8_t hb1; uint8_t hb1;
uint8_t hb2; uint8_t hb2;
uint8_t hb3; uint8_t hb3;
uint8_t sb[28]; uint8_t sb[32];
}; };
struct hw_info_frame { struct hw_info_frame {
...@@ -100,6 +100,7 @@ struct hw_info_frame { ...@@ -100,6 +100,7 @@ struct hw_info_frame {
struct hw_info_packet spd_packet; struct hw_info_packet spd_packet;
/* Video Stream Configuration */ /* Video Stream Configuration */
struct hw_info_packet vsc_packet; struct hw_info_packet vsc_packet;
struct hw_info_packet hdrsmd_packet;
}; };
#endif #endif
...@@ -74,7 +74,7 @@ struct color_state { ...@@ -74,7 +74,7 @@ struct color_state {
struct color_gamut_data destination_gamut; struct color_gamut_data destination_gamut;
enum color_transfer_func input_transfer_function; enum color_transfer_func input_transfer_function;
enum color_transfer_func output_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 { struct core_color {
...@@ -1970,7 +1970,7 @@ bool mod_color_set_white_point(struct mod_color *mod_color, ...@@ -1970,7 +1970,7 @@ bool mod_color_set_white_point(struct mod_color *mod_color,
bool mod_color_set_mastering_info(struct mod_color *mod_color, bool mod_color_set_mastering_info(struct mod_color *mod_color,
const struct dc_stream **streams, int num_streams, 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); struct core_color *core_color = MOD_COLOR_TO_CORE(mod_color);
unsigned int stream_index, sink_index; unsigned int stream_index, sink_index;
...@@ -1980,14 +1980,14 @@ bool mod_color_set_mastering_info(struct mod_color *mod_color, ...@@ -1980,14 +1980,14 @@ bool mod_color_set_mastering_info(struct mod_color *mod_color,
streams[stream_index]->sink); streams[stream_index]->sink);
memcpy(&core_color->state[sink_index].mastering_info, memcpy(&core_color->state[sink_index].mastering_info,
mastering_info, mastering_info,
sizeof(struct color_mastering_info)); sizeof(struct dc_hdr_static_metadata));
} }
return true; return true;
} }
bool mod_color_get_mastering_info(struct mod_color *mod_color, bool mod_color_get_mastering_info(struct mod_color *mod_color,
const struct dc_sink *sink, const struct dc_sink *sink,
struct color_mastering_info *mastering_info) struct dc_hdr_static_metadata *mastering_info)
{ {
struct core_color *core_color = struct core_color *core_color =
MOD_COLOR_TO_CORE(mod_color); MOD_COLOR_TO_CORE(mod_color);
...@@ -1995,7 +1995,7 @@ bool mod_color_get_mastering_info(struct mod_color *mod_color, ...@@ -1995,7 +1995,7 @@ bool mod_color_get_mastering_info(struct mod_color *mod_color,
unsigned int sink_index = sink_index_from_sink(core_color, sink); unsigned int sink_index = sink_index_from_sink(core_color, sink);
memcpy(mastering_info, &core_color->state[sink_index].mastering_info, memcpy(mastering_info, &core_color->state[sink_index].mastering_info,
sizeof(struct color_mastering_info)); sizeof(struct dc_hdr_static_metadata));
return true; return true;
} }
...@@ -2756,8 +2756,10 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, ...@@ -2756,8 +2756,10 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color,
else else
output_tf->tf = TRANSFER_FUNCTION_SRGB; 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( if (!mod_color_update_gamut_to_stream(
mod_color, streams, num_streams)) mod_color, streams, num_streams))
...@@ -2769,6 +2771,8 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color, ...@@ -2769,6 +2771,8 @@ bool mod_color_update_gamut_info(struct mod_color *mod_color,
updates[0].gamma = core_color->state[sink_index].gamma; updates[0].gamma = core_color->state[sink_index].gamma;
updates[0].in_transfer_func = input_tf; updates[0].in_transfer_func = input_tf;
updates[0].out_transfer_func = output_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); dc_update_surfaces_for_target(core_color->dc, updates, 1, NULL);
......
...@@ -87,22 +87,6 @@ enum hdr_tf_support_flag { ...@@ -87,22 +87,6 @@ enum hdr_tf_support_flag {
smpte_st2084 = 0x04 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 { struct mod_color {
int dummy; int dummy;
}; };
...@@ -206,11 +190,11 @@ bool mod_color_get_user_enable(struct mod_color *mod_color, ...@@ -206,11 +190,11 @@ bool mod_color_get_user_enable(struct mod_color *mod_color,
bool mod_color_set_mastering_info(struct mod_color *mod_color, bool mod_color_set_mastering_info(struct mod_color *mod_color,
const struct dc_stream **streams, int num_streams, 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, bool mod_color_get_mastering_info(struct mod_color *mod_color,
const struct dc_sink *sink, 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, bool mod_color_set_user_enable(struct mod_color *mod_color,
const struct dc_stream **streams, int num_streams, const struct dc_stream **streams, int num_streams,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment