diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index dacb4b7588a0..3cdb06e81130 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2737,6 +2737,8 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state, /* 6.o Configure and enable FEC if needed */ intel_ddi_enable_fec(encoder, crtc_state); + intel_dip_cmn_sdp_transmission_line_enable(crtc_state); + /* 7.a 128b/132b SST. */ if (!is_mst && intel_dp_is_uhbr(crtc_state)) { /* VCPID 1, start slot 0 for 128b/132b, tu slots */ @@ -3124,6 +3126,7 @@ static void intel_ddi_buf_disable(struct intel_encoder *encoder, DP_TP_CTL_ENABLE, 0); } + intel_dip_cmn_sdp_transmission_line_disable(crtc_state); intel_ddi_disable_fec(encoder, crtc_state); if (DISPLAY_VER(display) < 14) diff --git a/drivers/gpu/drm/i915/display/intel_dip.c b/drivers/gpu/drm/i915/display/intel_dip.c index f8e8577b2755..f447150ff7bc 100644 --- a/drivers/gpu/drm/i915/display/intel_dip.c +++ b/drivers/gpu/drm/i915/display/intel_dip.c @@ -10,6 +10,7 @@ #include "intel_dip.h" #include "intel_dip_regs.h" #include "intel_display_types.h" +#include "intel_hdmi.h" static int intel_dip_get_as_sdp_transmission_line(const struct intel_crtc_state *crtc_state) { @@ -54,14 +55,109 @@ void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state) EMP_AS_SDP_DB_TL(crtc_state->dip.emp_as_sdp_tl)); } +static int intel_dip_sdp_stagger_to_tl(struct intel_crtc_state *crtc_state, + int stagger) +{ + return crtc_state->dip.cmn_sdp_tl + stagger; +} + +static +void intel_dip_cmn_sdp_tl_compute_config_late(struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + bool as_sdp; + + if (!HAS_COMMON_SDP_TL(display)) + return; + + as_sdp = crtc_state->infoframes.enable & + intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); + /* + * When AS SDP is enabled : + * - The common SDP Transmission Line matches the EMP SDP Transmission Line. + * + * When AS SDP is disabled: + * - Bspec mentions the positions as lines of delayed vblank. + * - Guardband = 1st line of delayed vblank + * - Common SDP Transmission line is set to 2nd line of delayed vblank. + */ + + if (as_sdp) + crtc_state->dip.cmn_sdp_tl = crtc_state->dip.emp_as_sdp_tl; + else + crtc_state->dip.cmn_sdp_tl = crtc_state->vrr.guardband - 1; + + if (drm_WARN_ON(display->drm, + crtc_state->dip.cmn_sdp_tl >= + crtc_state->vrr.guardband + crtc_state->set_context_latency)) + return; + + /* + * Currently we are programming the default stagger values, but these + * can be optimized if required, based on number of SDPs enabled. + * + * Default values of the Transmission lines for SDPs other than AS SDP: + * VSC : CMN SDP Transmission line + * GMP : CMN SDP Transmission line + * PPS : CMN SDP Transmission line + 1 + * VSC_EXT: CMN SDP Transmission line + 2 + */ + crtc_state->dip.vsc_sdp_tl = crtc_state->dip.cmn_sdp_tl; + crtc_state->dip.gmp_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, GMP_STAGGER_DEFAULT); + crtc_state->dip.pps_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, PPS_STAGGER_DEFAULT); + crtc_state->dip.vsc_ext_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, VSC_EXT_STAGGER_DEFAULT); +} + void intel_dip_sdp_tl_compute_config_late(struct intel_crtc_state *crtc_state) { crtc_state->dip.emp_as_sdp_tl = intel_dip_get_as_sdp_transmission_line(crtc_state); + + intel_dip_cmn_sdp_tl_compute_config_late(crtc_state); +} + +static +void intel_dip_cmn_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + u16 vsc_ext_stagger, pps_stagger, gmp_stagger; + u32 val; + + if (!HAS_COMMON_SDP_TL(display)) + return; + + val = intel_de_read(display, CMN_SDP_TL(display, cpu_transcoder)); + + if (!(val & TRANSMISSION_LINE_ENABLE)) + return; + + crtc_state->dip.cmn_sdp_tl = REG_FIELD_GET(BASE_TRANSMISSION_LINE_MASK, val); + + /* SDP VSC uses same transmission line as CMN base transmission line */ + crtc_state->dip.vsc_sdp_tl = crtc_state->dip.cmn_sdp_tl; + + val = intel_de_read(display, CMN_SDP_TL_STGR_CTL(display, cpu_transcoder)); + + vsc_ext_stagger = REG_FIELD_GET(VSC_EXT_STAGGER_MASK, val); + pps_stagger = REG_FIELD_GET(PPS_STAGGER_MASK, val); + gmp_stagger = REG_FIELD_GET(GMP_STAGGER_MASK, val); + + crtc_state->dip.vsc_ext_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, vsc_ext_stagger); + crtc_state->dip.pps_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, pps_stagger); + crtc_state->dip.gmp_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, gmp_stagger); } void intel_dip_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_state) { crtc_state->dip.emp_as_sdp_tl = intel_dip_read_emp_as_sdp_tl(crtc_state); + + intel_dip_cmn_sdp_transmission_line_get_config(crtc_state); } static int intel_dip_sdp_tl_to_stagger(const struct intel_crtc_state *crtc_state,