drm/amd/display: DAL3: HDR10 Infoframe encoding
authorAndrew Wong <andrew.wong1@amd.com>
Thu, 22 Dec 2016 20:41:30 +0000 (15:41 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 26 Sep 2017 21:07:29 +0000 (17:07 -0400)
- 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>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
drivers/gpu/drm/amd/display/dc/core/dc_surface.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
drivers/gpu/drm/amd/display/include/hw_sequencer_types.h
drivers/gpu/drm/amd/display/modules/color/color.c
drivers/gpu/drm/amd/display/modules/inc/mod_color.h

index 5e60640df61b533a56beb7b5106c4293469bcbcc..e368d660362f8cd9fb9556fb6b8491b97f489298 100644 (file)
@@ -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(
index 386b3cc14fbe482f4652f81289163452c1530aae..2b08f5ae5e33304ece0949a2e97550d5dfecbdef 100644 (file)
@@ -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,
index 39a6124aa85fe9a3f6c88ee0433e8a50ca934b3f..cda67a78dbfde784b07ae5aaeaf74183570b8d4b 100644 (file)
@@ -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;
 }
 
index 6b4c75a78fe887d4ecf239dfec61d8630369ea84..d962baa477f55e9519a69d2070132820b035dc72 100644 (file)
@@ -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;
 }
 
index 0ee6f41b604722cbfeabc3942655eedd717127d9..ef9a69759bd51e9ece51f5dff596c49a5deca9a5 100644 (file)
@@ -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;
 
index b74a29b40a666f17b08497cc27337a9f0d4f9d9b..82133ab3224d36c508ca96fd32fab209790b8fb1 100644 (file)
@@ -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,
index 9caf2b365420f2691a5ec77fc21873b7fd3b7488..8b4a30459eeb4334bfea6834c705bdfd1015917f 100644 (file)
@@ -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 {
index 9a78097e70f3a248a04d7d36d9e6f579b84abfa2..6bbca1b4d73649a3a6fa5d025992c120b77366db 100644 (file)
@@ -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
index 5c578aecf21c236e23386b88bb3f717718d5bda3..599d9f9aa7caa8c46c910f5e673f543a65d9674f 100644 (file)
@@ -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);
 
index 670b87fb8bd2e435915d4457ded29614752fe924..70349a88916c84545da8386ec9464d16a3d907ca 100644 (file)
@@ -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,