mirror of
https://github.com/torvalds/linux.git
synced 2026-05-23 14:42:08 +02:00
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: 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>
This commit is contained in:
parent
235fef6c7f
commit
e95afc1cf7
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user