summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_dp_mst.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dp_mst.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c100
1 files changed, 82 insertions, 18 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 27ce5c3f5951..45d2230d1801 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -43,6 +43,7 @@
#include "intel_dp_hdcp.h"
#include "intel_dp_mst.h"
#include "intel_dp_tunnel.h"
+#include "intel_dp_link_training.h"
#include "intel_dpio_phy.h"
#include "intel_hdcp.h"
#include "intel_hotplug.h"
@@ -211,8 +212,8 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
drm_dbg_kms(&i915->drm, "Trying bpp %d\n", bpp);
- link_bpp_x16 = to_bpp_x16(dsc ? bpp :
- intel_dp_output_bpp(crtc_state->output_format, bpp));
+ link_bpp_x16 = fxp_q4_from_int(dsc ? bpp :
+ intel_dp_output_bpp(crtc_state->output_format, bpp));
local_bw_overhead = intel_dp_mst_bw_overhead(crtc_state, connector,
false, dsc, link_bpp_x16);
@@ -289,7 +290,7 @@ static int intel_dp_mst_find_vcpi_slots_for_bpp(struct intel_encoder *encoder,
if (!dsc)
crtc_state->pipe_bpp = bpp;
else
- crtc_state->dsc.compressed_bpp_x16 = to_bpp_x16(bpp);
+ crtc_state->dsc.compressed_bpp_x16 = fxp_q4_from_int(bpp);
drm_dbg_kms(&i915->drm, "Got %d slots for pipe bpp %d dsc %d\n", slots, bpp, dsc);
}
@@ -308,8 +309,8 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
* YUV420 is only half of the pipe bpp value.
*/
slots = intel_dp_mst_find_vcpi_slots_for_bpp(encoder, crtc_state,
- to_bpp_int(limits->link.max_bpp_x16),
- to_bpp_int(limits->link.min_bpp_x16),
+ fxp_q4_to_int(limits->link.max_bpp_x16),
+ fxp_q4_to_int(limits->link.min_bpp_x16),
limits,
conn_state, 2 * 3, false);
@@ -374,11 +375,11 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
crtc_state,
max_bpp / 3);
max_compressed_bpp = min(max_compressed_bpp,
- to_bpp_int(limits->link.max_bpp_x16));
+ fxp_q4_to_int(limits->link.max_bpp_x16));
min_compressed_bpp = intel_dp_dsc_sink_min_compressed_bpp(crtc_state);
min_compressed_bpp = max(min_compressed_bpp,
- to_bpp_int_roundup(limits->link.min_bpp_x16));
+ fxp_q4_to_int_roundup(limits->link.min_bpp_x16));
drm_dbg_kms(&i915->drm, "DSC Sink supported compressed min bpp %d compressed max bpp %d\n",
min_compressed_bpp, max_compressed_bpp);
@@ -478,10 +479,10 @@ adjust_limits_for_dsc_hblank_expansion_quirk(const struct intel_connector *conne
crtc->base.base.id, crtc->base.name,
connector->base.base.id, connector->base.name);
- if (limits->link.max_bpp_x16 < to_bpp_x16(24))
+ if (limits->link.max_bpp_x16 < fxp_q4_from_int(24))
return false;
- limits->link.min_bpp_x16 = to_bpp_x16(24);
+ limits->link.min_bpp_x16 = fxp_q4_from_int(24);
return true;
}
@@ -489,18 +490,18 @@ adjust_limits_for_dsc_hblank_expansion_quirk(const struct intel_connector *conne
drm_WARN_ON(&i915->drm, limits->min_rate != limits->max_rate);
if (limits->max_rate < 540000)
- min_bpp_x16 = to_bpp_x16(13);
+ min_bpp_x16 = fxp_q4_from_int(13);
else if (limits->max_rate < 810000)
- min_bpp_x16 = to_bpp_x16(10);
+ min_bpp_x16 = fxp_q4_from_int(10);
if (limits->link.min_bpp_x16 >= min_bpp_x16)
return true;
drm_dbg_kms(&i915->drm,
- "[CRTC:%d:%s][CONNECTOR:%d:%s] Increasing link min bpp to " BPP_X16_FMT " in DSC mode due to hblank expansion quirk\n",
+ "[CRTC:%d:%s][CONNECTOR:%d:%s] Increasing link min bpp to " FXP_Q4_FMT " in DSC mode due to hblank expansion quirk\n",
crtc->base.base.id, crtc->base.name,
connector->base.base.id, connector->base.name,
- BPP_X16_ARGS(min_bpp_x16));
+ FXP_Q4_ARGS(min_bpp_x16));
if (limits->link.max_bpp_x16 < min_bpp_x16)
return false;
@@ -1113,6 +1114,33 @@ static void intel_mst_pre_pll_enable_dp(struct intel_atomic_state *state,
to_intel_crtc(pipe_config->uapi.crtc));
}
+static bool intel_mst_probed_link_params_valid(struct intel_dp *intel_dp,
+ int link_rate, int lane_count)
+{
+ return intel_dp->link.mst_probed_rate == link_rate &&
+ intel_dp->link.mst_probed_lane_count == lane_count;
+}
+
+static void intel_mst_set_probed_link_params(struct intel_dp *intel_dp,
+ int link_rate, int lane_count)
+{
+ intel_dp->link.mst_probed_rate = link_rate;
+ intel_dp->link.mst_probed_lane_count = lane_count;
+}
+
+static void intel_mst_reprobe_topology(struct intel_dp *intel_dp,
+ const struct intel_crtc_state *crtc_state)
+{
+ if (intel_mst_probed_link_params_valid(intel_dp,
+ crtc_state->port_clock, crtc_state->lane_count))
+ return;
+
+ drm_dp_mst_topology_queue_probe(&intel_dp->mst_mgr);
+
+ intel_mst_set_probed_link_params(intel_dp,
+ crtc_state->port_clock, crtc_state->lane_count);
+}
+
static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
struct intel_encoder *encoder,
const struct intel_crtc_state *pipe_config,
@@ -1149,17 +1177,19 @@ static void intel_mst_pre_enable_dp(struct intel_atomic_state *state,
intel_dp_sink_enable_decompression(state, connector, pipe_config);
- if (first_mst_stream)
+ if (first_mst_stream) {
dig_port->base.pre_enable(state, &dig_port->base,
pipe_config, NULL);
+ intel_mst_reprobe_topology(intel_dp, pipe_config);
+ }
+
intel_dp->active_mst_links++;
ret = drm_dp_add_payload_part1(&intel_dp->mst_mgr, mst_state,
drm_atomic_get_mst_payload_state(mst_state, connector->port));
if (ret < 0)
- drm_dbg_kms(&dev_priv->drm, "Failed to create MST payload for %s: %d\n",
- connector->base.name, ret);
+ intel_dp_queue_modeset_retry_for_link(state, &dig_port->base, pipe_config);
/*
* Before Gen 12 this is not done as part of
@@ -1223,6 +1253,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
enum transcoder trans = pipe_config->cpu_transcoder;
bool first_mst_stream = intel_dp->active_mst_links == 1;
struct intel_crtc *pipe_crtc;
+ int ret;
drm_WARN_ON(&dev_priv->drm, pipe_config->has_pch_encoder);
@@ -1254,8 +1285,11 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state,
if (first_mst_stream)
intel_ddi_wait_for_fec_status(encoder, pipe_config, true);
- drm_dp_add_payload_part2(&intel_dp->mst_mgr,
- drm_atomic_get_mst_payload_state(mst_state, connector->port));
+ ret = drm_dp_add_payload_part2(&intel_dp->mst_mgr,
+ drm_atomic_get_mst_payload_state(mst_state,
+ connector->port));
+ if (ret < 0)
+ intel_dp_queue_modeset_retry_for_link(state, &dig_port->base, pipe_config);
if (DISPLAY_VER(dev_priv) >= 12)
intel_de_rmw(dev_priv, hsw_chicken_trans_reg(dev_priv, trans),
@@ -1998,3 +2032,33 @@ bool intel_dp_mst_crtc_needs_modeset(struct intel_atomic_state *state,
return false;
}
+
+/**
+ * intel_dp_mst_prepare_probe - Prepare an MST link for topology probing
+ * @intel_dp: DP port object
+ *
+ * Prepare an MST link for topology probing, programming the target
+ * link parameters to DPCD. This step is a requirement of the enumaration
+ * of path resources during probing.
+ */
+void intel_dp_mst_prepare_probe(struct intel_dp *intel_dp)
+{
+ int link_rate = intel_dp_max_link_rate(intel_dp);
+ int lane_count = intel_dp_max_lane_count(intel_dp);
+ u8 rate_select;
+ u8 link_bw;
+
+ if (intel_dp->link_trained)
+ return;
+
+ if (intel_mst_probed_link_params_valid(intel_dp, link_rate, lane_count))
+ return;
+
+ intel_dp_compute_rate(intel_dp, link_rate, &link_bw, &rate_select);
+
+ intel_dp_link_training_set_mode(intel_dp, link_rate, false);
+ intel_dp_link_training_set_bw(intel_dp, link_bw, rate_select, lane_count,
+ drm_dp_enhanced_frame_cap(intel_dp->dpcd));
+
+ intel_mst_set_probed_link_params(intel_dp, link_rate, lane_count);
+}