From 0254325ac3a0bfd6013577871b7224e5f4e4abec Mon Sep 17 00:00:00 2001 From: Andrew Wong Date: Thu, 22 Dec 2016 15:41:30 -0500 Subject: [PATCH 0103/4131] 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: Andrew Wong Reviewed-by: Aric Cyr Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- 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 ++++- .../drm/amd/display/dc/dce/dce_stream_encoder.c | 20 +++- .../gpu/drm/amd/display/dc/inc/hw/stream_encoder.h | 2 + .../drm/amd/display/include/hw_sequencer_types.h | 3 +- drivers/gpu/drm/amd/display/modules/color/color.c | 16 +-- .../gpu/drm/amd/display/modules/inc/mod_color.h | 20 +--- 10 files changed, 176 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5e60640..e368d66 100644 --- 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(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( 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 386b3cc..2b08f5a 100644 --- 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 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, diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 39a6124..cda67a7 100644 --- 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, stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble; stream->status.link = &stream->sink->link->public; - return true; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c index 6b4c75a..d962baa 100644 --- 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; } diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 0ee6f41..ef9a697 100644 --- 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; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c index b74a29b..82133ab 100644 --- 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_hdmi_info_packets( 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_dp_info_packets( 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, + 2, /* packetIndex */ + &info_frame->spd); + dce110_update_generic_info_packet( enc110, - 0, /* packetIndex */ - &info_frame->vsc); + 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, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h index 9caf2b3..8b4a304 100644 --- 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 { diff --git a/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h b/drivers/gpu/drm/amd/display/include/hw_sequencer_types.h index 9a78097..6bbca1b 100644 --- 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 diff --git a/drivers/gpu/drm/amd/display/modules/color/color.c b/drivers/gpu/drm/amd/display/modules/color/color.c index 5c578aec..599d9f9 100644 --- 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 mod_color *mod_color, 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 mod_color *mod_color, 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 mod_color *mod_color, 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 mod_color *mod_color, 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 mod_color *mod_color, 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); diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_color.h b/drivers/gpu/drm/amd/display/modules/inc/mod_color.h index 670b87fb..70349a8 100644 --- 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 mod_color *mod_color, 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, -- 2.7.4