[PATCH 23/26] drm/i915/display: Limit m/n ratio to 10 for BMG + Display > 14
Ankit Nautiyal
ankit.k.nautiyal at intel.com
Wed Aug 7 09:27:50 UTC 2024
As per Bspec:68922 for platforms BMG and Display > 14 which support higher
link rates have a HW limitation:
If the CEILING( Link M / Link N ) ratio is greater than 10.0, then
hardware cannot support the given resolution / refresh rate at the given
configuration.
Modify the helper to compute m_n, to check for the max link_m/n ratio
for the given platforms, and return error code in case the
resolution/refresh rate is not supported.
Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal at intel.com>
---
drivers/gpu/drm/i915/display/intel_display.c | 27 ++++++++++++--
drivers/gpu/drm/i915/display/intel_display.h | 9 ++---
drivers/gpu/drm/i915/display/intel_dp.c | 37 +++++++++++++-------
drivers/gpu/drm/i915/display/intel_dp_mst.c | 26 ++++++++------
drivers/gpu/drm/i915/display/intel_fdi.c | 15 ++++----
5 files changed, 78 insertions(+), 36 deletions(-)
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index ba638b8a3d72..bf9c38a4288d 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -2683,8 +2683,15 @@ static void compute_m_n(u32 *ret_m, u32 *ret_n,
intel_reduce_m_n_ratio(ret_m, ret_n);
}
-void
-intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes,
+static int
+get_max_link_m_n_ratio(struct drm_i915_private *i915)
+{
+ return 10;
+}
+
+int
+intel_link_compute_m_n(struct drm_i915_private *i915,
+ u16 bits_per_pixel_x16, int nlanes,
int pixel_clock, int link_clock,
int bw_overhead,
struct intel_link_m_n *m_n)
@@ -2693,6 +2700,7 @@ intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes,
u32 data_m = intel_dp_effective_data_rate(pixel_clock, bits_per_pixel_x16,
bw_overhead);
u32 data_n = drm_dp_max_dprx_data_rate(link_clock, nlanes);
+ int link_m_n_ratio, max_link_m_n_ratio;
/*
* Windows/BIOS uses fixed M/N values always. Follow suit.
@@ -2711,6 +2719,21 @@ intel_link_compute_m_n(u16 bits_per_pixel_x16, int nlanes,
0x80000);
m_n->link_n_ext = 0;
+
+ if (DISPLAY_VER(i915) < 14 || (DISPLAY_VER(i915) == 14 && !IS_DGFX(i915)))
+ return 0;
+
+ max_link_m_n_ratio = get_max_link_m_n_ratio(i915);
+
+ link_m_n_ratio = DIV_ROUND_UP(m_n->link_m, m_n->link_m);
+
+ if (link_m_n_ratio > max_link_m_n_ratio) {
+ drm_dbg_kms(&i915->drm, "Cannot support Link_m/Link_n ratio : %d > max_link_m_n_ratio\n",
+ link_m_n_ratio);
+ return -EINVAL;
+ }
+
+ return 0;
}
void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 4cfd1da0bbc0..6a4451e6d500 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -412,10 +412,11 @@ int intel_atomic_add_affected_planes(struct intel_atomic_state *state,
struct intel_crtc *crtc);
u8 intel_calc_active_pipes(struct intel_atomic_state *state,
u8 active_pipes);
-void intel_link_compute_m_n(u16 bpp, int nlanes,
- int pixel_clock, int link_clock,
- int bw_overhead,
- struct intel_link_m_n *m_n);
+int intel_link_compute_m_n(struct drm_i915_private *i915,
+ u16 bpp, int nlanes,
+ int pixel_clock, int link_clock,
+ int bw_overhead,
+ struct intel_link_m_n *m_n);
u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
u32 pixel_format, u64 modifier);
enum drm_mode_status
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 9dde41c17b2f..9ec91617bf94 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2968,7 +2968,7 @@ static bool can_enable_drrs(struct intel_connector *connector,
intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS;
}
-static void
+static int
intel_dp_drrs_compute_config(struct intel_connector *connector,
struct intel_crtc_state *pipe_config,
int link_bpp_x16)
@@ -2977,6 +2977,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
const struct drm_display_mode *downclock_mode =
intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode);
int pixel_clock;
+ int ret;
/*
* FIXME all joined pipes share the same transcoder.
@@ -2988,7 +2989,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
if (!can_enable_drrs(connector, pipe_config, downclock_mode)) {
if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder))
intel_zero_m_n(&pipe_config->dp_m2_n2);
- return;
+ return 0;
}
if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915))
@@ -3000,14 +3001,18 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
if (pipe_config->splitter.enable)
pixel_clock /= pipe_config->splitter.link_count;
- intel_link_compute_m_n(link_bpp_x16, pipe_config->lane_count, pixel_clock,
- pipe_config->port_clock,
- intel_dp_bw_fec_overhead(pipe_config->fec_enable),
- &pipe_config->dp_m2_n2);
+ ret = intel_link_compute_m_n(i915, link_bpp_x16, pipe_config->lane_count, pixel_clock,
+ pipe_config->port_clock,
+ intel_dp_bw_fec_overhead(pipe_config->fec_enable),
+ &pipe_config->dp_m2_n2);
+ if (ret)
+ return ret;
/* FIXME: abstract this better */
if (pipe_config->splitter.enable)
pipe_config->dp_m2_n2.data_m *= pipe_config->splitter.link_count;
+
+ return 0;
}
static bool intel_dp_has_audio(struct intel_encoder *encoder,
@@ -3211,12 +3216,14 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_dp_audio_compute_config(encoder, pipe_config, conn_state);
- intel_link_compute_m_n(link_bpp_x16,
- pipe_config->lane_count,
- adjusted_mode->crtc_clock,
- pipe_config->port_clock,
- intel_dp_bw_fec_overhead(pipe_config->fec_enable),
- &pipe_config->dp_m_n);
+ ret = intel_link_compute_m_n(dev_priv, link_bpp_x16,
+ pipe_config->lane_count,
+ adjusted_mode->crtc_clock,
+ pipe_config->port_clock,
+ intel_dp_bw_fec_overhead(pipe_config->fec_enable),
+ &pipe_config->dp_m_n);
+ if (ret)
+ return ret;
/* FIXME: abstract this better */
if (pipe_config->splitter.enable)
@@ -3229,7 +3236,11 @@ intel_dp_compute_config(struct intel_encoder *encoder,
intel_dp_compute_as_sdp(intel_dp, pipe_config);
intel_psr_compute_config(intel_dp, pipe_config, conn_state);
intel_alpm_lobf_compute_config(intel_dp, pipe_config, conn_state);
- intel_dp_drrs_compute_config(connector, pipe_config, link_bpp_x16);
+
+ ret = intel_dp_drrs_compute_config(connector, pipe_config, link_bpp_x16);
+ if (ret)
+ return ret;
+
intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state);
intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state);
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index f5a5f9117192..5289ba133fc5 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -125,7 +125,7 @@ static int intel_dp_mst_bw_overhead(const struct intel_crtc_state *crtc_state,
return max(overhead, intel_dp_bw_fec_overhead(crtc_state->fec_enable));
}
-static void intel_dp_mst_compute_m_n(const struct intel_crtc_state *crtc_state,
+static int intel_dp_mst_compute_m_n(const struct intel_crtc_state *crtc_state,
const struct intel_connector *connector,
int overhead,
int bpp_x16,
@@ -133,15 +133,20 @@ static void intel_dp_mst_compute_m_n(const struct intel_crtc_state *crtc_state,
{
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
+ struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ int ret;
/* TODO: Check WA 14013163432 to set data M/N for full BW utilization. */
- intel_link_compute_m_n(bpp_x16, crtc_state->lane_count,
- adjusted_mode->crtc_clock,
- crtc_state->port_clock,
- overhead,
- m_n);
+ ret = intel_link_compute_m_n(i915, bpp_x16, crtc_state->lane_count,
+ adjusted_mode->crtc_clock,
+ crtc_state->port_clock,
+ overhead, m_n);
+ if (ret)
+ return ret;
m_n->tu = DIV_ROUND_UP_ULL(mul_u32_u32(m_n->data_m, 64), m_n->data_n);
+
+ return ret;
}
static int intel_dp_mst_calc_pbn(int pixel_clock, int bpp_x16, int bw_overhead)
@@ -223,10 +228,11 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
remote_bw_overhead = intel_dp_mst_bw_overhead(crtc_state, connector,
true, dsc, link_bpp_x16);
- intel_dp_mst_compute_m_n(crtc_state, connector,
- local_bw_overhead,
- link_bpp_x16,
- &crtc_state->dp_m_n);
+ if (!intel_dp_mst_compute_m_n(crtc_state, connector,
+ local_bw_overhead,
+ link_bpp_x16,
+ &crtc_state->dp_m_n))
+ continue;
/*
* The TU size programmed to the HW determines which slots in
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index 222cd0e1a2bc..b71414fa1f0f 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -324,7 +324,7 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
struct drm_device *dev = crtc->base.dev;
struct drm_i915_private *i915 = to_i915(dev);
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
- int lane, link_bw, fdi_dotclock;
+ int lane, link_bw, fdi_dotclock, ret;
/* FDI is a binary signal running at ~2.7GHz, encoding
* each output octet as 10 bits. The actual frequency
@@ -342,13 +342,14 @@ int ilk_fdi_compute_config(struct intel_crtc *crtc,
pipe_config->fdi_lanes = lane;
- intel_link_compute_m_n(fxp_q4_from_int(pipe_config->pipe_bpp),
- lane, fdi_dotclock,
- link_bw,
- intel_dp_bw_fec_overhead(false),
- &pipe_config->fdi_m_n);
+ ret = intel_link_compute_m_n(i915,
+ fxp_q4_from_int(pipe_config->pipe_bpp),
+ lane, fdi_dotclock,
+ link_bw,
+ intel_dp_bw_fec_overhead(false),
+ &pipe_config->fdi_m_n);
- return 0;
+ return ret;
}
static int intel_fdi_atomic_check_bw(struct intel_atomic_state *state,
--
2.45.2
More information about the Intel-gfx-trybot
mailing list