drm/amd/display: Enable AdaptiveSync in DC interface
authorSung Joon Kim <sungjoon.kim@amd.com>
Wed, 11 Jan 2023 18:12:21 +0000 (13:12 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 24 Jan 2023 18:26:25 +0000 (13:26 -0500)
[why]
Start enabling AdaptiveSync feature on Linux environment.

[how]
Adding AdaptiveSync support in DC layer
- building AdaptiveSync info_packets
- adjusting the v_startup parameter

Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
Reviewed-by: Anthony Koo <Anthony.Koo@amd.com>
Acked-by: Alan Liu <HaoPing.Liu@amd.com>
Signed-off-by: Sung Joon Kim <sungjoon.kim@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
23 files changed:
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/dc.h
drivers/gpu/drm/amd/display/dc/dc_dp_types.h
drivers/gpu/drm/amd/display/dc/dc_link.h
drivers/gpu/drm/amd/display/dc/dc_stream.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_stream_encoder.h
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dio_stream_encoder.h
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c

index 7f84a8d..103c934 100644 (file)
@@ -2960,6 +2960,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
        if (update->vsp_infopacket)
                stream->vsp_infopacket = *update->vsp_infopacket;
 
+       if (update->adaptive_sync_infopacket)
+               stream->adaptive_sync_infopacket = *update->adaptive_sync_infopacket;
+
        if (update->dither_option)
                stream->dither_option = *update->dither_option;
 
@@ -3165,6 +3168,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
                                        stream_update->vsc_infopacket ||
                                        stream_update->vsp_infopacket ||
                                        stream_update->hfvsif_infopacket ||
+                                       stream_update->adaptive_sync_infopacket ||
                                        stream_update->vtem_infopacket) {
                                resource_build_info_frame(pipe_ctx);
                                dc->hwss.update_info_frame(pipe_ctx);
index 2a46f28..bf0ff6f 100644 (file)
@@ -3270,6 +3270,50 @@ static void set_hfvs_info_packet(
        *info_packet = stream->hfvsif_infopacket;
 }
 
+static void adaptive_sync_override_dp_info_packets_sdp_line_num(
+               const struct dc_crtc_timing *timing,
+               struct enc_sdp_line_num *sdp_line_num,
+               struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param)
+{
+       uint32_t asic_blank_start = 0;
+       uint32_t asic_blank_end   = 0;
+       uint32_t v_update = 0;
+
+       const struct dc_crtc_timing *tg = timing;
+
+       /* blank_start = frame end - front porch */
+       asic_blank_start = tg->v_total - tg->v_front_porch;
+
+       /* blank_end = blank_start - active */
+       asic_blank_end = (asic_blank_start - tg->v_border_bottom -
+                                               tg->v_addressable - tg->v_border_top);
+
+       if (pipe_dlg_param->vstartup_start > asic_blank_end) {
+               v_update = (tg->v_total - (pipe_dlg_param->vstartup_start - asic_blank_end));
+               sdp_line_num->adaptive_sync_line_num_valid = true;
+               sdp_line_num->adaptive_sync_line_num = (tg->v_total - v_update - 1);
+       } else {
+               sdp_line_num->adaptive_sync_line_num_valid = false;
+               sdp_line_num->adaptive_sync_line_num = 0;
+       }
+}
+
+static void set_adaptive_sync_info_packet(
+               struct dc_info_packet *info_packet,
+               const struct dc_stream_state *stream,
+               struct encoder_info_frame *info_frame,
+               struct _vcs_dpi_display_pipe_dest_params_st *pipe_dlg_param)
+{
+       if (!stream->adaptive_sync_infopacket.valid)
+               return;
+
+       adaptive_sync_override_dp_info_packets_sdp_line_num(
+                       &stream->timing,
+                       &info_frame->sdp_line_num,
+                       pipe_dlg_param);
+
+       *info_packet = stream->adaptive_sync_infopacket;
+}
 
 static void set_vtem_info_packet(
                struct dc_info_packet *info_packet,
@@ -3362,6 +3406,7 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
        info->vsc.valid = false;
        info->hfvsif.valid = false;
        info->vtem.valid = false;
+       info->adaptive_sync.valid = false;
        signal = pipe_ctx->stream->signal;
 
        /* HDMi and DP have different info packets*/
@@ -3382,6 +3427,10 @@ void resource_build_info_frame(struct pipe_ctx *pipe_ctx)
                set_spd_info_packet(&info->spd, pipe_ctx->stream);
 
                set_hdr_static_info_packet(&info->hdrsmd, pipe_ctx->stream);
+               set_adaptive_sync_info_packet(&info->adaptive_sync,
+                                                                               pipe_ctx->stream,
+                                                                               info,
+                                                                               &pipe_ctx->pipe_dlg_param);
        }
 
        patch_gamut_packet_checksum(&info->gamut);
index 7105bc5..e967455 100644 (file)
@@ -1414,6 +1414,7 @@ struct dpcd_caps {
        union dpcd_fec_capability fec_cap;
        struct dpcd_dsc_capabilities dsc_caps;
        struct dc_lttpr_caps lttpr_caps;
+       struct adaptive_sync_caps adaptive_sync_caps;
        struct dpcd_usb4_dp_tunneling_info usb4_dp_tun_info;
 
        union dp_128b_132b_supported_link_rates dp_128b_132b_supported_link_rates;
index 84da543..1845838 100644 (file)
@@ -502,7 +502,11 @@ union down_spread_ctrl {
        1 = Main link signal is downspread <= 0.5%
        with frequency in the range of 30kHz ~ 33kHz*/
                uint8_t SPREAD_AMP:1;
-               uint8_t RESERVED2:2;/*Bit 6:5 = RESERVED. Read all 0s*/
+               uint8_t RESERVED2:1;/*Bit 5 = RESERVED. Read all 0s*/
+       /* Bit 6 = FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE.
+       0 = FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE is not enabled by the Source device (default)
+       1 = FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE is enabled by Source device */
+               uint8_t FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE:1;
        /*Bit 7 = MSA_TIMING_PAR_IGNORE_EN
        0 = Source device will send valid data for the MSA Timing Params
        1 = Source device may send invalid data for these MSA Timing Params*/
@@ -858,6 +862,21 @@ struct psr_caps {
        unsigned int psr_power_opt_flag;
 };
 
+union dpcd_dprx_feature_enumeration_list_cont_1 {
+       struct {
+               uint8_t ADAPTIVE_SYNC_SDP_SUPPORT:1;
+               uint8_t AS_SDP_FIRST_HALF_LINE_OR_3840_PIXEL_CYCLE_WINDOW_NOT_SUPPORTED: 1;
+               uint8_t RESERVED0: 2;
+               uint8_t VSC_EXT_SDP_VER1_SUPPORT: 1;
+               uint8_t RESERVED1: 3;
+       } bits;
+       uint8_t raw;
+};
+
+struct adaptive_sync_caps {
+       union dpcd_dprx_feature_enumeration_list_cont_1 dp_adap_sync_caps;
+};
+
 /* Length of router topology ID read from DPCD in bytes. */
 #define DPCD_USB4_TOPOLOGY_ID_LEN 5
 
index eb85189..19d15b7 100644 (file)
@@ -280,6 +280,7 @@ struct dc_link {
                bool dp_keep_receiver_powered;
                bool dp_skip_DID2;
                bool dp_skip_reset_segment;
+               bool dp_skip_fs_144hz;
                bool dp_mot_reset_segment;
                /* Some USB4 docks do not handle turning off MST DSC once it has been enabled. */
                bool dpia_mst_dsc_always_on;
index ef33d7d..5674525 100644 (file)
@@ -190,6 +190,7 @@ struct dc_stream_state {
        struct dc_info_packet vsp_infopacket;
        struct dc_info_packet hfvsif_infopacket;
        struct dc_info_packet vtem_infopacket;
+       struct dc_info_packet adaptive_sync_infopacket;
        uint8_t dsc_packed_pps[128];
        struct rect src; /* composition area */
        struct rect dst; /* stream addressable area */
@@ -313,6 +314,7 @@ struct dc_stream_update {
        struct dc_info_packet *vsp_infopacket;
        struct dc_info_packet *hfvsif_infopacket;
        struct dc_info_packet *vtem_infopacket;
+       struct dc_info_packet *adaptive_sync_infopacket;
        bool *dpms_off;
        bool integer_scaling_update;
        bool *allow_freesync;
index 594679d..01a0233 100644 (file)
@@ -652,10 +652,16 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
                pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
                        pipe_ctx->stream_res.stream_enc,
                        &pipe_ctx->stream_res.encoder_info_frame);
-       else
+       else {
+               if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num)
+                       pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num(
+                               pipe_ctx->stream_res.stream_enc,
+                               &pipe_ctx->stream_res.encoder_info_frame);
+
                pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
                        pipe_ctx->stream_res.stream_enc,
                        &pipe_ctx->stream_res.encoder_info_frame);
+       }
 }
 
 void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
index 1527c3b..8ea5fc8 100644 (file)
@@ -753,12 +753,19 @@ void enc1_stream_encoder_update_dp_info_packets(
         * use other packetIndex (such as 5,6) for other info packet
         */
 
+       if (info_frame->adaptive_sync.valid)
+               enc1_update_generic_info_packet(
+                               enc1,
+                               5,  /* packetIndex */
+                               &info_frame->adaptive_sync);
+
        /* 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_GSP2_ENABLE, info_frame->spd.valid);
        REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid);
+       REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid);
 
        /* This bit is the master enable bit.
         * When enabling secondary stream engine,
index cacf3f5..d1a953c 100644 (file)
@@ -423,6 +423,22 @@ void enc2_set_dynamic_metadata(struct stream_encoder *enc,
        }
 }
 
+static void enc2_stream_encoder_update_dp_info_packets_sdp_line_num(
+               struct stream_encoder *enc,
+               struct encoder_info_frame *info_frame)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       if (info_frame->adaptive_sync.valid == true &&
+               info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) {
+               //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF
+               REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1);
+
+               REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM,
+                                       info_frame->sdp_line_num.adaptive_sync_line_num);
+       }
+}
+
 static void enc2_stream_encoder_update_dp_info_packets(
        struct stream_encoder *enc,
        const struct encoder_info_frame *info_frame)
@@ -587,6 +603,8 @@ static const struct stream_encoder_funcs dcn20_str_enc_funcs = {
                enc2_stream_encoder_update_hdmi_info_packets,
        .stop_hdmi_info_packets =
                enc2_stream_encoder_stop_hdmi_info_packets,
+       .update_dp_info_packets_sdp_line_num =
+               enc2_stream_encoder_update_dp_info_packets_sdp_line_num,
        .update_dp_info_packets =
                enc2_stream_encoder_update_dp_info_packets,
        .send_immediate_sdp_message =
index 17df537..5f9079d 100644 (file)
@@ -404,6 +404,22 @@ static void enc3_read_state(struct stream_encoder *enc, struct enc_state *s)
        }
 }
 
+void enc3_stream_encoder_update_dp_info_packets_sdp_line_num(
+               struct stream_encoder *enc,
+               struct encoder_info_frame *info_frame)
+{
+       struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+       if (info_frame->adaptive_sync.valid == true &&
+               info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) {
+               //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF
+               REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1);
+
+               REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM,
+                                       info_frame->sdp_line_num.adaptive_sync_line_num);
+       }
+}
+
 void enc3_stream_encoder_update_dp_info_packets(
        struct stream_encoder *enc,
        const struct encoder_info_frame *info_frame)
@@ -452,12 +468,20 @@ void enc3_stream_encoder_update_dp_info_packets(
         * use other packetIndex (such as 5,6) for other info packet
         */
 
+       if (info_frame->adaptive_sync.valid)
+               enc->vpg->funcs->update_generic_info_packet(
+                               enc->vpg,
+                               5,  /* packetIndex */
+                               &info_frame->adaptive_sync,
+                               true);
+
        /* 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_GSP2_ENABLE, info_frame->spd.valid);
        REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid);
+       REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid);
 
        /* This bit is the master enable bit.
         * When enabling secondary stream engine,
@@ -803,6 +827,8 @@ static const struct stream_encoder_funcs dcn30_str_enc_funcs = {
                enc3_stream_encoder_update_hdmi_info_packets,
        .stop_hdmi_info_packets =
                enc3_stream_encoder_stop_hdmi_info_packets,
+       .update_dp_info_packets_sdp_line_num =
+               enc3_stream_encoder_update_dp_info_packets_sdp_line_num,
        .update_dp_info_packets =
                enc3_stream_encoder_update_dp_info_packets,
        .stop_dp_info_packets =
index 54ee230..0631097 100644 (file)
@@ -292,6 +292,10 @@ void enc3_stream_encoder_update_hdmi_info_packets(
 void enc3_stream_encoder_stop_hdmi_info_packets(
        struct stream_encoder *enc);
 
+void enc3_stream_encoder_update_dp_info_packets_sdp_line_num(
+               struct stream_encoder *enc,
+               struct encoder_info_frame *info_frame);
+
 void enc3_stream_encoder_update_dp_info_packets(
        struct stream_encoder *enc,
        const struct encoder_info_frame *info_frame);
index 7360b3c..2b5041a 100644 (file)
@@ -674,10 +674,16 @@ void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx)
                pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
                        pipe_ctx->stream_res.stream_enc,
                        &pipe_ctx->stream_res.encoder_info_frame);
-       else
+       else {
+               if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num)
+                       pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num(
+                               pipe_ctx->stream_res.stream_enc,
+                               &pipe_ctx->stream_res.encoder_info_frame);
+
                pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
                        pipe_ctx->stream_res.stream_enc,
                        &pipe_ctx->stream_res.encoder_info_frame);
+       }
 }
 
 void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
index 16639bd..d76f55a 100644 (file)
@@ -430,6 +430,22 @@ static void dcn31_hpo_dp_stream_enc_set_stream_attribute(
                        MSA_DATA_LANE_3, 0);
 }
 
+static void dcn31_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num(
+               struct hpo_dp_stream_encoder *enc,
+               struct encoder_info_frame *info_frame)
+{
+       struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc);
+
+       if (info_frame->adaptive_sync.valid == true &&
+               info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) {
+               //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF
+               REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_SOF_REFERENCE, 1);
+
+               REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_TRANSMISSION_LINE_NUMBER,
+                                       info_frame->sdp_line_num.adaptive_sync_line_num);
+       }
+}
+
 static void dcn31_hpo_dp_stream_enc_update_dp_info_packets(
                struct hpo_dp_stream_encoder *enc,
                const struct encoder_info_frame *info_frame)
@@ -458,12 +474,20 @@ static void dcn31_hpo_dp_stream_enc_update_dp_info_packets(
                                &info_frame->hdrsmd,
                                true);
 
+       if (info_frame->adaptive_sync.valid)
+               enc->vpg->funcs->update_generic_info_packet(
+                               enc->vpg,
+                               5,  /* packetIndex */
+                               &info_frame->adaptive_sync,
+                               true);
+
        /* enable/disable transmission of packet(s).
         * If enabled, packet transmission begins on the next frame
         */
        REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->vsc.valid);
        REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->spd.valid);
        REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->hdrsmd.valid);
+       REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->adaptive_sync.valid);
 
        /* check if dynamic metadata packet transmission is enabled */
        REG_GET(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL,
@@ -714,6 +738,7 @@ static const struct hpo_dp_stream_encoder_funcs dcn30_str_enc_funcs = {
        .dp_blank = dcn31_hpo_dp_stream_enc_dp_blank,
        .disable = dcn31_hpo_dp_stream_enc_disable,
        .set_stream_attribute = dcn31_hpo_dp_stream_enc_set_stream_attribute,
+       .update_dp_info_packets_sdp_line_num = dcn31_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num,
        .update_dp_info_packets = dcn31_hpo_dp_stream_enc_update_dp_info_packets,
        .stop_dp_info_packets = dcn31_hpo_dp_stream_enc_stop_dp_info_packets,
        .dp_set_dsc_pps_info_packet = dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet,
index 0e1949d..208208f 100644 (file)
@@ -421,6 +421,11 @@ void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx)
                                &pipe_ctx->stream_res.encoder_info_frame);
                return;
        } else {
+               if (pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num)
+                       pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets_sdp_line_num(
+                               pipe_ctx->stream_res.stream_enc,
+                               &pipe_ctx->stream_res.encoder_info_frame);
+
                pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
                        pipe_ctx->stream_res.stream_enc,
                        &pipe_ctx->stream_res.encoder_info_frame);
index 67f4589..aff23c6 100644 (file)
@@ -429,6 +429,8 @@ static const struct stream_encoder_funcs dcn314_str_enc_funcs = {
                enc3_stream_encoder_update_hdmi_info_packets,
        .stop_hdmi_info_packets =
                enc3_stream_encoder_stop_hdmi_info_packets,
+       .update_dp_info_packets_sdp_line_num =
+               enc3_stream_encoder_update_dp_info_packets_sdp_line_num,
        .update_dp_info_packets =
                enc3_stream_encoder_update_dp_info_packets,
        .stop_dp_info_packets =
index 33dfdf8..ed07723 100644 (file)
@@ -280,6 +280,10 @@ void enc3_stream_encoder_update_hdmi_info_packets(
 void enc3_stream_encoder_stop_hdmi_info_packets(
        struct stream_encoder *enc);
 
+void enc3_stream_encoder_update_dp_info_packets_sdp_line_num(
+               struct stream_encoder *enc,
+               struct encoder_info_frame *info_frame);
+
 void enc3_stream_encoder_update_dp_info_packets(
        struct stream_encoder *enc,
        const struct encoder_info_frame *info_frame);
index f01968f..45578b8 100644 (file)
@@ -463,6 +463,8 @@ static const struct stream_encoder_funcs dcn32_str_enc_funcs = {
                enc3_stream_encoder_update_hdmi_info_packets,
        .stop_hdmi_info_packets =
                enc3_stream_encoder_stop_hdmi_info_packets,
+       .update_dp_info_packets_sdp_line_num =
+               enc3_stream_encoder_update_dp_info_packets_sdp_line_num,
        .update_dp_info_packets =
                enc3_stream_encoder_update_dp_info_packets,
        .stop_dp_info_packets =
index d2b89c5..fb2ec8e 100644 (file)
@@ -1004,6 +1004,39 @@ static enum dcn_zstate_support_state  decide_zstate_support(struct dc *dc, struc
        }
 }
 
+static void dcn20_adjust_freesync_v_startup(
+               const struct dc_crtc_timing *dc_crtc_timing, int *vstartup_start)
+{
+       struct dc_crtc_timing patched_crtc_timing;
+       uint32_t asic_blank_end   = 0;
+       uint32_t asic_blank_start = 0;
+       uint32_t newVstartup      = 0;
+
+       patched_crtc_timing = *dc_crtc_timing;
+
+       if (patched_crtc_timing.flags.INTERLACE == 1) {
+               if (patched_crtc_timing.v_front_porch < 2)
+                       patched_crtc_timing.v_front_porch = 2;
+       } else {
+               if (patched_crtc_timing.v_front_porch < 1)
+                       patched_crtc_timing.v_front_porch = 1;
+       }
+
+       /* blank_start = frame end - front porch */
+       asic_blank_start = patched_crtc_timing.v_total -
+                                       patched_crtc_timing.v_front_porch;
+
+       /* blank_end = blank_start - active */
+       asic_blank_end = asic_blank_start -
+                                       patched_crtc_timing.v_border_bottom -
+                                       patched_crtc_timing.v_addressable -
+                                       patched_crtc_timing.v_border_top;
+
+       newVstartup = asic_blank_end + (patched_crtc_timing.v_total - asic_blank_start);
+
+       *vstartup_start = ((newVstartup > *vstartup_start) ? newVstartup : *vstartup_start);
+}
+
 void dcn20_calculate_dlg_params(
                struct dc *dc, struct dc_state *context,
                display_e2e_pipe_params_st *pipes,
@@ -1063,6 +1096,11 @@ void dcn20_calculate_dlg_params(
                context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz =
                                                pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
                context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest;
+               if (context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid)
+                       dcn20_adjust_freesync_v_startup(
+                               &context->res_ctx.pipe_ctx[i].stream->timing,
+                               &context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start);
+
                pipe_idx++;
        }
        /*save a original dppclock copy*/
index 193ee41..e66a570 100644 (file)
@@ -1272,6 +1272,38 @@ static bool is_dtbclk_required(struct dc *dc, struct dc_state *context)
        return false;
 }
 
+static void dcn20_adjust_freesync_v_startup(const struct dc_crtc_timing *dc_crtc_timing, int *vstartup_start)
+{
+       struct dc_crtc_timing patched_crtc_timing;
+       uint32_t asic_blank_end   = 0;
+       uint32_t asic_blank_start = 0;
+       uint32_t newVstartup      = 0;
+
+       patched_crtc_timing = *dc_crtc_timing;
+
+       if (patched_crtc_timing.flags.INTERLACE == 1) {
+               if (patched_crtc_timing.v_front_porch < 2)
+                       patched_crtc_timing.v_front_porch = 2;
+       } else {
+               if (patched_crtc_timing.v_front_porch < 1)
+                       patched_crtc_timing.v_front_porch = 1;
+       }
+
+       /* blank_start = frame end - front porch */
+       asic_blank_start = patched_crtc_timing.v_total -
+                                       patched_crtc_timing.v_front_porch;
+
+       /* blank_end = blank_start - active */
+       asic_blank_end = asic_blank_start -
+                                       patched_crtc_timing.v_border_bottom -
+                                       patched_crtc_timing.v_addressable -
+                                       patched_crtc_timing.v_border_top;
+
+       newVstartup = asic_blank_end + (patched_crtc_timing.v_total - asic_blank_start);
+
+       *vstartup_start = ((newVstartup > *vstartup_start) ? newVstartup : *vstartup_start);
+}
+
 static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
                                       display_e2e_pipe_params_st *pipes,
                                       int pipe_cnt, int vlevel)
@@ -1375,6 +1407,11 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
                        }
                }
 
+               if (context->res_ctx.pipe_ctx[i].stream->adaptive_sync_infopacket.valid)
+                       dcn20_adjust_freesync_v_startup(
+                               &context->res_ctx.pipe_ctx[i].stream->timing,
+                               &context->res_ctx.pipe_ctx[i].pipe_dlg_param.vstartup_start);
+
                pipe_idx++;
        }
        /* If DCN isn't making memory requests we can allow pstate change and lower clocks */
index 42db4b7..bb5ad70 100644 (file)
@@ -72,6 +72,12 @@ enum dynamic_metadata_mode {
        dmdata_dolby_vision
 };
 
+struct enc_sdp_line_num {
+       /* Adaptive Sync SDP */
+       bool adaptive_sync_line_num_valid;
+       uint32_t adaptive_sync_line_num;
+};
+
 struct encoder_info_frame {
        /* auxiliary video information */
        struct dc_info_packet avi;
@@ -85,6 +91,9 @@ struct encoder_info_frame {
        struct dc_info_packet vsc;
        /* HDR Static MetaData */
        struct dc_info_packet hdrsmd;
+       /* Adaptive Sync SDP*/
+       struct dc_info_packet adaptive_sync;
+       struct enc_sdp_line_num sdp_line_num;
 };
 
 struct encoder_unblank_param {
@@ -154,6 +163,10 @@ struct stream_encoder_funcs {
        void (*stop_hdmi_info_packets)(
                struct stream_encoder *enc);
 
+       void (*update_dp_info_packets_sdp_line_num)(
+               struct stream_encoder *enc,
+               struct encoder_info_frame *info_frame);
+
        void (*update_dp_info_packets)(
                struct stream_encoder *enc,
                const struct encoder_info_frame *info_frame);
@@ -302,6 +315,10 @@ struct hpo_dp_stream_encoder_funcs {
                bool compressed_format,
                bool double_buffer_en);
 
+       void (*update_dp_info_packets_sdp_line_num)(
+               struct hpo_dp_stream_encoder *enc,
+               struct encoder_info_frame *info_frame);
+
        void (*update_dp_info_packets)(
                struct hpo_dp_stream_encoder *enc,
                const struct encoder_info_frame *info_frame);
index 8f86d13..ba53437 100644 (file)
@@ -1646,6 +1646,22 @@ static bool retrieve_link_cap(struct dc_link *link)
 
                if (status != DC_OK)
                        dm_error("%s: Read DPRX caps data failed.\n", __func__);
+
+               /* AdaptiveSyncCapability  */
+               dpcd_dprx_data = 0;
+               for (i = 0; i < read_dpcd_retry_cnt; i++) {
+                       status = core_link_read_dpcd(
+                                       link, DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1,
+                                       &dpcd_dprx_data, sizeof(dpcd_dprx_data));
+                       if (status == DC_OK)
+                               break;
+               }
+
+               link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.raw = dpcd_dprx_data;
+
+               if (status != DC_OK)
+                       dm_error("%s: Read DPRX caps data failed. Addr:%#x\n",
+                                       __func__, DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1);
        }
 
        else {
index edf5845..91fe039 100644 (file)
@@ -41,4 +41,40 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
 void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
                struct dc_info_packet *info_packet);
 
+enum adaptive_sync_type {
+       ADAPTIVE_SYNC_TYPE_NONE                  = 0,
+       ADAPTIVE_SYNC_TYPE_DP                    = 1,
+       ADAPTIVE_SYNC_TYPE_PCON_IN_WHITELIST     = 2,
+       ADAPTIVE_SYNC_TYPE_PCON_NOT_IN_WHITELIST = 3,
+       ADAPTIVE_SYNC_TYPE_EDP                   = 4,
+};
+
+enum adaptive_sync_sdp_version {
+       AS_SDP_VER_0 = 0x0,
+       AS_SDP_VER_1 = 0x1,
+       AS_SDP_VER_2 = 0x2,
+};
+
+#define AS_DP_SDP_LENGTH (9)
+
+struct frame_duration_op {
+       bool          support;
+       unsigned char frame_duration_hex;
+};
+
+struct AS_Df_params {
+       bool   supportMode;
+       struct frame_duration_op increase;
+       struct frame_duration_op decrease;
+};
+
+void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
+               enum adaptive_sync_type asType, const struct AS_Df_params *param,
+               struct dc_info_packet *info_packet);
+
+void mod_build_adaptive_sync_infopacket_v2(const struct dc_stream_state *stream,
+               const struct AS_Df_params *param, struct dc_info_packet *info_packet);
+
+void mod_build_adaptive_sync_infopacket_v1(struct dc_info_packet *info_packet);
+
 #endif
index 6969105..a8a31d0 100644 (file)
@@ -519,3 +519,58 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
                info_packet->valid = true;
 }
 
+void mod_build_adaptive_sync_infopacket(const struct dc_stream_state *stream,
+               enum adaptive_sync_type asType,
+               const struct AS_Df_params *param,
+               struct dc_info_packet *info_packet)
+{
+       info_packet->valid = false;
+
+       memset(info_packet, 0, sizeof(struct dc_info_packet));
+
+       switch (asType) {
+       case ADAPTIVE_SYNC_TYPE_DP:
+               if (stream != NULL)
+                       mod_build_adaptive_sync_infopacket_v2(stream, param, info_packet);
+               break;
+       case ADAPTIVE_SYNC_TYPE_PCON_IN_WHITELIST:
+               mod_build_adaptive_sync_infopacket_v1(info_packet);
+               break;
+       case ADAPTIVE_SYNC_TYPE_NONE:
+       case ADAPTIVE_SYNC_TYPE_PCON_NOT_IN_WHITELIST:
+       default:
+               break;
+       }
+}
+
+void mod_build_adaptive_sync_infopacket_v1(struct dc_info_packet *info_packet)
+{
+       info_packet->valid = true;
+       // HEADER {HB0, HB1, HB2, HB3} = {00, Type, Version, Length}
+       info_packet->hb0 = 0x00;
+       info_packet->hb1 = 0x22;
+       info_packet->hb2 = AS_SDP_VER_1;
+       info_packet->hb3 = 0x00;
+}
+
+void mod_build_adaptive_sync_infopacket_v2(const struct dc_stream_state *stream,
+               const struct AS_Df_params *param,
+               struct dc_info_packet *info_packet)
+{
+       info_packet->valid = true;
+       // HEADER {HB0, HB1, HB2, HB3} = {00, Type, Version, Length}
+       info_packet->hb0 = 0x00;
+       info_packet->hb1 = 0x22;
+       info_packet->hb2 = AS_SDP_VER_2;
+       info_packet->hb3 = AS_DP_SDP_LENGTH;
+
+       //Payload
+       info_packet->sb[0] = param->supportMode; //1: AVT; 0: FAVT
+       info_packet->sb[1] = (stream->timing.v_total & 0x00FF);
+       info_packet->sb[2] = (stream->timing.v_total & 0xFF00) >> 8;
+       //info_packet->sb[3] = 0x00; Target RR, not use fot AVT
+       info_packet->sb[4] = (param->increase.support << 6 | param->decrease.support << 7);
+       info_packet->sb[5] = param->increase.frame_duration_hex;
+       info_packet->sb[6] = param->decrease.frame_duration_hex;
+}
+