diff options
| author | Arun R Murthy <arun.r.murthy@intel.com> | 2025-04-24 20:45:15 +0530 |
|---|---|---|
| committer | Imre Deak <imre.deak@intel.com> | 2025-04-30 22:08:16 +0300 |
| commit | c53372dfb630e8b047a3c6677e62ffb6fda2752c (patch) | |
| tree | 0cfeb398d7a51193727d5b0e1adb7c9d3bbdb9ae /drivers/gpu/drm/i915/display/intel_dp.c | |
| parent | 7d585426a6538a717f55a1bb0b614d465bd03805 (diff) | |
drm/i915/display: move min_hblank from dp_mst.c to dp.c
Minimum HBlank is programmed to address jitter for high resolutions with
high refresh rates that have small Hblank, specifically where Hblank is
smaller than one MTP.
TODO: Add the min_hblank calculation for hdmi as well.
v2: move from intel_audio.c to intel_dp.c
some correction in link_bpp_x16 (Imre)
v3: min_hblank for 8b/10b MST and 128b/132b SST/MST
handle error for intel_dp_mst_dsc_get_slice_count
reset min_hblank before disabling transcoder (Imre)
v4: compute link_bpp_x16 within compute_min_hblank,
return error in case of compute failure
call compute_min_hblank() before vrr_compute_config (Imre)
v5: readout MIN_HBLAN reg for Xe3+
Signed-off-by: Arun R Murthy <arun.r.murthy@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Link: https://lore.kernel.org/r/20250424-hblank-v7-2-8b002f1506cc@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dp.c')
| -rw-r--r-- | drivers/gpu/drm/i915/display/intel_dp.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 213bb92f3fff..b299b5d8b68e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3104,6 +3104,76 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state, } } +int intel_dp_compute_min_hblank(struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + const struct drm_display_mode *adjusted_mode = + &crtc_state->hw.adjusted_mode; + struct intel_connector *connector = to_intel_connector(conn_state->connector); + int symbol_size = intel_dp_is_uhbr(crtc_state) ? 32 : 8; + /* + * min symbol cycles is 3(BS,VBID, BE) for 128b/132b and + * 5(BS, VBID, MVID, MAUD, BE) for 8b/10b + */ + int min_sym_cycles = intel_dp_is_uhbr(crtc_state) ? 3 : 5; + bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); + int num_joined_pipes = intel_crtc_num_joined_pipes(crtc_state); + int min_hblank; + int max_lane_count = 4; + int hactive_sym_cycles, htotal_sym_cycles; + int dsc_slices = 0; + int link_bpp_x16; + + if (DISPLAY_VER(display) < 30) + return 0; + + /* MIN_HBLANK should be set only for 8b/10b MST or for 128b/132b SST/MST */ + if (!is_mst && !intel_dp_is_uhbr(crtc_state)) + return 0; + + if (crtc_state->dsc.compression_enable) { + dsc_slices = intel_dp_dsc_get_slice_count(connector, + adjusted_mode->crtc_clock, + adjusted_mode->crtc_hdisplay, + num_joined_pipes); + if (!dsc_slices) { + drm_dbg(display->drm, "failed to calculate dsc slice count\n"); + return -EINVAL; + } + } + + if (crtc_state->dsc.compression_enable) + link_bpp_x16 = crtc_state->dsc.compressed_bpp_x16; + else + link_bpp_x16 = fxp_q4_from_int(intel_dp_output_bpp(crtc_state->output_format, + crtc_state->pipe_bpp)); + + /* Calculate min Hblank Link Layer Symbol Cycle Count for 8b/10b MST & 128b/132b */ + hactive_sym_cycles = drm_dp_link_symbol_cycles(max_lane_count, + adjusted_mode->hdisplay, + dsc_slices, + link_bpp_x16, + symbol_size, is_mst); + htotal_sym_cycles = adjusted_mode->htotal * hactive_sym_cycles / + adjusted_mode->hdisplay; + + min_hblank = htotal_sym_cycles - hactive_sym_cycles; + /* minimum Hblank calculation: https://groups.vesa.org/wg/DP/document/20494 */ + min_hblank = max(min_hblank, min_sym_cycles); + + /* + * adjust the BlankingStart/BlankingEnd framing control from + * the calculated value + */ + min_hblank = min_hblank - 2; + + min_hblank = min(10, min_hblank); + crtc_state->min_hblank = min_hblank; + + return 0; +} + int intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, @@ -3203,6 +3273,10 @@ intel_dp_compute_config(struct intel_encoder *encoder, &pipe_config->dp_m_n); } + ret = intel_dp_compute_min_hblank(pipe_config, conn_state); + if (ret) + return ret; + /* FIXME: abstract this better */ if (pipe_config->splitter.enable) pipe_config->dp_m_n.data_m *= pipe_config->splitter.link_count; |
