Commit e95afc1c authored by Sung Joon Kim's avatar Sung Joon Kim Committed by Alex Deucher

drm/amd/display: Enable AdaptiveSync in DC interface

[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: default avatarHarry Wentland <Harry.Wentland@amd.com>
Reviewed-by: default avatarAnthony Koo <Anthony.Koo@amd.com>
Acked-by: default avatarAlan Liu <HaoPing.Liu@amd.com>
Signed-off-by: default avatarSung Joon Kim <sungjoon.kim@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 235fef6c
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
......
......@@ -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;
......
......@@ -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)
......
......@@ -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,
......
......@@ -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 =
......
......@@ -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 =
......
......@@ -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);
......
......@@ -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)
......
......@@ -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,
......
......@@ -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);
......
......@@ -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 =
......
......@@ -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);
......
......@@ -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 =
......
......@@ -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*/
......
......@@ -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 */
......
......@@ -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);
......
......@@ -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 {
......
......@@ -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
......@@ -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;
}
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