aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.c47
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.h1
3 files changed, 52 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index fcdc188c2c35..b3ae81a6ab16 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6298,6 +6298,10 @@ static int intel_atomic_check_config(struct intel_atomic_state *state,
if (ret)
return ret;
+ ret = intel_fdi_add_affected_crtcs(state);
+ if (ret)
+ return ret;
+
for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) {
if (!intel_crtc_needs_modeset(new_crtc_state)) {
if (intel_crtc_is_bigjoiner_slave(new_crtc_state))
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index 7448219b401c..e6429dfebe15 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -120,6 +120,53 @@ void intel_fdi_link_train(struct intel_crtc *crtc,
dev_priv->display.funcs.fdi->fdi_link_train(crtc, crtc_state);
}
+/**
+ * intel_fdi_add_affected_crtcs - add CRTCs on FDI affected by other modeset CRTCs
+ * @state: intel atomic state
+ *
+ * Add a CRTC using FDI to @state if changing another CRTC's FDI BW usage is
+ * known to affect the available FDI BW for the former CRTC. In practice this
+ * means adding CRTC B on IVYBRIDGE if its use of FDI lanes is limited (by
+ * CRTC C) and CRTC C is getting disabled.
+ *
+ * Returns 0 in case of success, or a negative error code otherwise.
+ */
+int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state)
+{
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ const struct intel_crtc_state *old_crtc_state;
+ const struct intel_crtc_state *new_crtc_state;
+ struct intel_crtc *crtc;
+
+ if (!IS_IVYBRIDGE(i915) || INTEL_NUM_PIPES(i915) != 3)
+ return 0;
+
+ crtc = intel_crtc_for_pipe(i915, PIPE_C);
+ new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc);
+ if (!new_crtc_state)
+ return 0;
+
+ if (!intel_crtc_needs_modeset(new_crtc_state))
+ return 0;
+
+ old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
+ if (!old_crtc_state->fdi_lanes)
+ return 0;
+
+ crtc = intel_crtc_for_pipe(i915, PIPE_B);
+ new_crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
+ if (IS_ERR(new_crtc_state))
+ return PTR_ERR(new_crtc_state);
+
+ old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc);
+ if (!old_crtc_state->fdi_lanes)
+ return 0;
+
+ return intel_modeset_pipes_in_mask_early(state,
+ "FDI link BW decrease on pipe C",
+ BIT(PIPE_B));
+}
+
/* units of 100MHz */
static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state)
{
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.h b/drivers/gpu/drm/i915/display/intel_fdi.h
index 66b01c55c0eb..477ff0136934 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.h
+++ b/drivers/gpu/drm/i915/display/intel_fdi.h
@@ -16,6 +16,7 @@ struct intel_crtc_state;
struct intel_encoder;
struct intel_link_bw_limits;
+int intel_fdi_add_affected_crtcs(struct intel_atomic_state *state);
int intel_fdi_link_freq(struct drm_i915_private *i915,
const struct intel_crtc_state *pipe_config);
bool intel_fdi_compute_pipe_bpp(struct intel_crtc_state *crtc_state);