summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/display/intel_dp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dp.c')
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c426
1 files changed, 203 insertions, 223 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index aa77ddcee42c..392c3653d0d7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -172,10 +172,28 @@ int intel_dp_link_symbol_clock(int rate)
static int max_dprx_rate(struct intel_dp *intel_dp)
{
+ struct intel_display *display = to_intel_display(intel_dp);
+ struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+ int max_rate;
+
if (intel_dp_tunnel_bw_alloc_is_enabled(intel_dp))
- return drm_dp_tunnel_max_dprx_rate(intel_dp->tunnel);
+ max_rate = drm_dp_tunnel_max_dprx_rate(intel_dp->tunnel);
+ else
+ max_rate = drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+
+ /*
+ * Some broken eDP sinks illegally declare support for
+ * HBR3 without TPS4, and are unable to produce a stable
+ * output. Reject HBR3 when TPS4 is not available.
+ */
+ if (max_rate >= 810000 && !drm_dp_tps4_supported(intel_dp->dpcd)) {
+ drm_dbg_kms(display->drm,
+ "[ENCODER:%d:%s] Rejecting HBR3 due to missing TPS4 support\n",
+ encoder->base.base.id, encoder->base.name);
+ max_rate = 540000;
+ }
- return drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+ return max_rate;
}
static int max_dprx_lane_count(struct intel_dp *intel_dp)
@@ -1032,10 +1050,11 @@ u8 intel_dp_dsc_get_slice_count(const struct intel_connector *connector,
u8 test_slice_count = valid_dsc_slicecount[i] * num_joined_pipes;
/*
- * 3 DSC Slices per pipe need 3 DSC engines,
- * which is supported only with Ultrajoiner.
+ * 3 DSC Slices per pipe need 3 DSC engines, which is supported only
+ * with Ultrajoiner only for some platforms.
*/
- if (valid_dsc_slicecount[i] == 3 && num_joined_pipes != 4)
+ if (valid_dsc_slicecount[i] == 3 &&
+ (!HAS_DSC_3ENGINES(display) || num_joined_pipes != 4))
continue;
if (test_slice_count >
@@ -1075,7 +1094,7 @@ static bool source_can_output(struct intel_dp *intel_dp,
/*
* No YCbCr output support on gmch platforms.
* Also, ILK doesn't seem capable of DP YCbCr output.
- * The displayed image is severly corrupted. SNB+ is fine.
+ * The displayed image is severely corrupted. SNB+ is fine.
*/
return !HAS_GMCH(display) && !display->platform.ironlake;
@@ -1376,7 +1395,7 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
if (!HAS_DSC(display))
return false;
- if (connector->mst_port && !HAS_DSC_MST(display))
+ if (connector->mst.dp && !HAS_DSC_MST(display))
return false;
if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP &&
@@ -1391,12 +1410,11 @@ bool intel_dp_has_dsc(const struct intel_connector *connector)
static enum drm_mode_status
intel_dp_mode_valid(struct drm_connector *_connector,
- struct drm_display_mode *mode)
+ const struct drm_display_mode *mode)
{
struct intel_display *display = to_intel_display(_connector->dev);
struct intel_connector *connector = to_intel_connector(_connector);
struct intel_dp *intel_dp = intel_attached_dp(connector);
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
const struct drm_display_mode *fixed_mode;
int target_clock = mode->clock;
int max_rate, mode_rate, max_lanes, max_link_clock;
@@ -1407,7 +1425,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
bool dsc = false;
int num_joined_pipes;
- status = intel_cpu_transcoder_mode_valid(dev_priv, mode);
+ status = intel_cpu_transcoder_mode_valid(display, mode);
if (status != MODE_OK)
return status;
@@ -1496,7 +1514,7 @@ intel_dp_mode_valid(struct drm_connector *_connector,
if (status != MODE_OK)
return status;
- return intel_mode_valid_max_plane_size(dev_priv, mode, num_joined_pipes);
+ return intel_mode_valid_max_plane_size(display, mode, num_joined_pipes);
}
bool intel_dp_source_supports_tps3(struct intel_display *display)
@@ -1926,7 +1944,7 @@ static bool intel_dp_dsc_supports_format(const struct intel_connector *connector
return drm_dp_dsc_sink_supports_format(connector->dp.dsc_dpcd, sink_dsc_format);
}
-static bool is_bw_sufficient_for_dsc_config(u16 compressed_bppx16, u32 link_clock,
+static bool is_bw_sufficient_for_dsc_config(int dsc_bpp_x16, u32 link_clock,
u32 lane_count, u32 mode_clock,
enum intel_output_format output_format,
int timeslots)
@@ -1934,15 +1952,16 @@ static bool is_bw_sufficient_for_dsc_config(u16 compressed_bppx16, u32 link_cloc
u32 available_bw, required_bw;
available_bw = (link_clock * lane_count * timeslots * 16) / 8;
- required_bw = compressed_bppx16 * (intel_dp_mode_to_fec_clock(mode_clock));
+ required_bw = dsc_bpp_x16 * (intel_dp_mode_to_fec_clock(mode_clock));
return available_bw > required_bw;
}
static int dsc_compute_link_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
- struct link_config_limits *limits,
- u16 compressed_bppx16,
+ struct drm_connector_state *conn_state,
+ const struct link_config_limits *limits,
+ int dsc_bpp_x16,
int timeslots)
{
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
@@ -1957,15 +1976,37 @@ static int dsc_compute_link_config(struct intel_dp *intel_dp,
for (lane_count = limits->min_lane_count;
lane_count <= limits->max_lane_count;
lane_count <<= 1) {
- if (!is_bw_sufficient_for_dsc_config(compressed_bppx16, link_rate,
- lane_count, adjusted_mode->clock,
- pipe_config->output_format,
- timeslots))
- continue;
+ /*
+ * FIXME: intel_dp_mtp_tu_compute_config() requires
+ * ->lane_count and ->port_clock set before we know
+ * they'll work. If we end up failing altogether,
+ * they'll remain in crtc state. This shouldn't matter,
+ * as we'd then bail out from compute config, but it's
+ * just ugly.
+ */
pipe_config->lane_count = lane_count;
pipe_config->port_clock = link_rate;
+ if (drm_dp_is_uhbr_rate(link_rate)) {
+ int ret;
+
+ ret = intel_dp_mtp_tu_compute_config(intel_dp,
+ pipe_config,
+ conn_state,
+ dsc_bpp_x16,
+ dsc_bpp_x16,
+ 0, true);
+ if (ret)
+ continue;
+ } else {
+ if (!is_bw_sufficient_for_dsc_config(dsc_bpp_x16, link_rate,
+ lane_count, adjusted_mode->clock,
+ pipe_config->output_format,
+ timeslots))
+ continue;
+ }
+
return 0;
}
}
@@ -2055,111 +2096,66 @@ static int dsc_src_max_compressed_bpp(struct intel_dp *intel_dp)
}
/*
- * From a list of valid compressed bpps try different compressed bpp and find a
- * suitable link configuration that can support it.
+ * Note: for pre-13 display you still need to check the validity of each step.
*/
-static int
-icl_dsc_compute_link_config(struct intel_dp *intel_dp,
- struct intel_crtc_state *pipe_config,
- struct link_config_limits *limits,
- int dsc_max_bpp,
- int dsc_min_bpp,
- int pipe_bpp,
- int timeslots)
+static int intel_dp_dsc_bpp_step_x16(const struct intel_connector *connector)
{
- int i, ret;
-
- /* Compressed BPP should be less than the Input DSC bpp */
- dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
-
- for (i = ARRAY_SIZE(valid_dsc_bpp) - 1; i >= 0; i--) {
- if (valid_dsc_bpp[i] < dsc_min_bpp ||
- valid_dsc_bpp[i] > dsc_max_bpp)
- continue;
+ struct intel_display *display = to_intel_display(connector);
+ u8 incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd);
- ret = dsc_compute_link_config(intel_dp,
- pipe_config,
- limits,
- valid_dsc_bpp[i] << 4,
- timeslots);
- if (ret == 0) {
- pipe_config->dsc.compressed_bpp_x16 =
- fxp_q4_from_int(valid_dsc_bpp[i]);
- return 0;
- }
- }
+ if (DISPLAY_VER(display) < 14 || !incr)
+ return fxp_q4_from_int(1);
- return -EINVAL;
+ /* fxp q4 */
+ return fxp_q4_from_int(1) / incr;
}
-/*
- * From XE_LPD onwards we supports compression bpps in steps of 1 up to
- * uncompressed bpp-1. So we start from max compressed bpp and see if any
- * link configuration is able to support that compressed bpp, if not we
- * step down and check for lower compressed bpp.
- */
-static int
-xelpd_dsc_compute_link_config(struct intel_dp *intel_dp,
- const struct intel_connector *connector,
- struct intel_crtc_state *pipe_config,
- struct link_config_limits *limits,
- int dsc_max_bpp,
- int dsc_min_bpp,
- int pipe_bpp,
- int timeslots)
+/* Note: This is not universally usable! */
+static bool intel_dp_dsc_valid_bpp(struct intel_dp *intel_dp, int bpp_x16)
{
struct intel_display *display = to_intel_display(intel_dp);
- u8 bppx16_incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd);
- u16 compressed_bppx16;
- u8 bppx16_step;
- int ret;
+ int i;
- if (DISPLAY_VER(display) < 14 || bppx16_incr <= 1)
- bppx16_step = 16;
- else
- bppx16_step = 16 / bppx16_incr;
+ if (DISPLAY_VER(display) >= 13) {
+ if (intel_dp->force_dsc_fractional_bpp_en && !fxp_q4_to_frac(bpp_x16))
+ return false;
- /* Compressed BPP should be less than the Input DSC bpp */
- dsc_max_bpp = min(dsc_max_bpp << 4, (pipe_bpp << 4) - bppx16_step);
- dsc_min_bpp = dsc_min_bpp << 4;
-
- for (compressed_bppx16 = dsc_max_bpp;
- compressed_bppx16 >= dsc_min_bpp;
- compressed_bppx16 -= bppx16_step) {
- if (intel_dp->force_dsc_fractional_bpp_en &&
- !fxp_q4_to_frac(compressed_bppx16))
- continue;
- ret = dsc_compute_link_config(intel_dp,
- pipe_config,
- limits,
- compressed_bppx16,
- timeslots);
- if (ret == 0) {
- pipe_config->dsc.compressed_bpp_x16 = compressed_bppx16;
- if (intel_dp->force_dsc_fractional_bpp_en &&
- fxp_q4_to_frac(compressed_bppx16))
- drm_dbg_kms(display->drm,
- "Forcing DSC fractional bpp\n");
+ return true;
+ }
- return 0;
- }
+ if (fxp_q4_to_frac(bpp_x16))
+ return false;
+
+ for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) {
+ if (fxp_q4_to_int(bpp_x16) == valid_dsc_bpp[i])
+ return true;
}
- return -EINVAL;
+
+ return false;
}
+/*
+ * Find the max compressed BPP we can find a link configuration for. The BPPs to
+ * try depend on the source (platform) and sink.
+ */
static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
- const struct intel_connector *connector,
struct intel_crtc_state *pipe_config,
- struct link_config_limits *limits,
+ struct drm_connector_state *conn_state,
+ const struct link_config_limits *limits,
int pipe_bpp,
int timeslots)
{
struct intel_display *display = to_intel_display(intel_dp);
+ const struct intel_connector *connector = to_intel_connector(conn_state->connector);
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
+ int output_bpp;
int dsc_min_bpp;
int dsc_max_bpp;
+ int min_bpp_x16, max_bpp_x16, bpp_step_x16;
int dsc_joiner_max_bpp;
int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config);
+ int bpp_x16;
+ int ret;
dsc_min_bpp = fxp_q4_to_int_roundup(limits->link.min_bpp_x16);
@@ -2168,11 +2164,38 @@ static int dsc_compute_compressed_bpp(struct intel_dp *intel_dp,
num_joined_pipes);
dsc_max_bpp = min(dsc_joiner_max_bpp, fxp_q4_to_int(limits->link.max_bpp_x16));
- if (DISPLAY_VER(display) >= 13)
- return xelpd_dsc_compute_link_config(intel_dp, connector, pipe_config, limits,
- dsc_max_bpp, dsc_min_bpp, pipe_bpp, timeslots);
- return icl_dsc_compute_link_config(intel_dp, pipe_config, limits,
- dsc_max_bpp, dsc_min_bpp, pipe_bpp, timeslots);
+ /* FIXME: remove the round trip via integers */
+ min_bpp_x16 = fxp_q4_from_int(dsc_min_bpp);
+ max_bpp_x16 = fxp_q4_from_int(dsc_max_bpp);
+
+ bpp_step_x16 = intel_dp_dsc_bpp_step_x16(connector);
+
+ /* Compressed BPP should be less than the Input DSC bpp */
+ output_bpp = intel_dp_output_bpp(pipe_config->output_format, pipe_bpp);
+ max_bpp_x16 = min(max_bpp_x16, fxp_q4_from_int(output_bpp) - bpp_step_x16);
+
+ for (bpp_x16 = max_bpp_x16; bpp_x16 >= min_bpp_x16; bpp_x16 -= bpp_step_x16) {
+ if (!intel_dp_dsc_valid_bpp(intel_dp, bpp_x16))
+ continue;
+
+ ret = dsc_compute_link_config(intel_dp,
+ pipe_config,
+ conn_state,
+ limits,
+ bpp_x16,
+ timeslots);
+ if (ret == 0) {
+ pipe_config->dsc.compressed_bpp_x16 = bpp_x16;
+ if (intel_dp->force_dsc_fractional_bpp_en &&
+ fxp_q4_to_frac(bpp_x16))
+ drm_dbg_kms(display->drm,
+ "Forcing DSC fractional bpp\n");
+
+ return 0;
+ }
+ }
+
+ return -EINVAL;
}
int intel_dp_dsc_min_src_input_bpc(void)
@@ -2182,7 +2205,7 @@ int intel_dp_dsc_min_src_input_bpc(void)
}
static
-bool is_dsc_pipe_bpp_sufficient(struct link_config_limits *limits,
+bool is_dsc_pipe_bpp_sufficient(const struct link_config_limits *limits,
int pipe_bpp)
{
return pipe_bpp >= limits->pipe.min_bpp &&
@@ -2191,7 +2214,7 @@ bool is_dsc_pipe_bpp_sufficient(struct link_config_limits *limits,
static
int intel_dp_force_dsc_pipe_bpp(struct intel_dp *intel_dp,
- struct link_config_limits *limits)
+ const struct link_config_limits *limits)
{
struct intel_display *display = to_intel_display(intel_dp);
int forced_bpp;
@@ -2217,13 +2240,11 @@ int intel_dp_force_dsc_pipe_bpp(struct intel_dp *intel_dp,
static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
- struct link_config_limits *limits,
+ const struct link_config_limits *limits,
int timeslots)
{
const struct intel_connector *connector =
to_intel_connector(conn_state->connector);
- int dsc_max_bpp;
- int dsc_min_bpp;
u8 dsc_bpc[3] = {};
int forced_bpp, pipe_bpp;
int num_bpc, i, ret;
@@ -2231,7 +2252,7 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
forced_bpp = intel_dp_force_dsc_pipe_bpp(intel_dp, limits);
if (forced_bpp) {
- ret = dsc_compute_compressed_bpp(intel_dp, connector, pipe_config,
+ ret = dsc_compute_compressed_bpp(intel_dp, pipe_config, conn_state,
limits, forced_bpp, timeslots);
if (ret == 0) {
pipe_config->pipe_bpp = forced_bpp;
@@ -2239,9 +2260,6 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
}
}
- dsc_max_bpp = limits->pipe.max_bpp;
- dsc_min_bpp = limits->pipe.min_bpp;
-
/*
* Get the maximum DSC bpc that will be supported by any valid
* link configuration and compressed bpp.
@@ -2249,11 +2267,10 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
num_bpc = drm_dp_dsc_sink_supported_input_bpcs(connector->dp.dsc_dpcd, dsc_bpc);
for (i = 0; i < num_bpc; i++) {
pipe_bpp = dsc_bpc[i] * 3;
- if (pipe_bpp < dsc_min_bpp)
- break;
- if (pipe_bpp > dsc_max_bpp)
+ if (pipe_bpp < limits->pipe.min_bpp || pipe_bpp > limits->pipe.max_bpp)
continue;
- ret = dsc_compute_compressed_bpp(intel_dp, connector, pipe_config,
+
+ ret = dsc_compute_compressed_bpp(intel_dp, pipe_config, conn_state,
limits, pipe_bpp, timeslots);
if (ret == 0) {
pipe_config->pipe_bpp = pipe_bpp;
@@ -2267,7 +2284,7 @@ static int intel_dp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
static int intel_edp_dsc_compute_pipe_bpp(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
- struct link_config_limits *limits)
+ const struct link_config_limits *limits)
{
struct intel_display *display = to_intel_display(intel_dp);
struct intel_connector *connector =
@@ -2332,9 +2349,8 @@ static void intel_dp_fec_compute_config(struct intel_dp *intel_dp,
int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state,
- struct link_config_limits *limits,
- int timeslots,
- bool compute_pipe_bpp)
+ const struct link_config_limits *limits,
+ int timeslots)
{
struct intel_display *display = to_intel_display(intel_dp);
const struct intel_connector *connector =
@@ -2342,6 +2358,7 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
const struct drm_display_mode *adjusted_mode =
&pipe_config->hw.adjusted_mode;
int num_joined_pipes = intel_crtc_num_joined_pipes(pipe_config);
+ bool is_mst = intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST);
int ret;
intel_dp_fec_compute_config(intel_dp, pipe_config);
@@ -2350,12 +2367,10 @@ int intel_dp_dsc_compute_config(struct intel_dp *intel_dp,
return -EINVAL;
/*
- * compute pipe bpp is set to false for DP MST DSC case
- * and compressed_bpp is calculated same time once
- * vpci timeslots are allocated, because overall bpp
- * calculation procedure is bit different for MST case.
+ * Link parameters, pipe bpp and compressed bpp have already been
+ * figured out for DP MST DSC.
*/
- if (compute_pipe_bpp) {
+ if (!is_mst) {
if (intel_dp_is_edp(intel_dp))
ret = intel_edp_dsc_compute_pipe_bpp(intel_dp, pipe_config,
conn_state, limits);
@@ -2518,9 +2533,6 @@ intel_dp_compute_config_limits(struct intel_dp *intel_dp,
limits->min_rate = intel_dp_min_link_rate(intel_dp);
limits->max_rate = intel_dp_max_link_rate(intel_dp);
- /* FIXME 128b/132b SST+DSC support missing */
- if (!is_mst && dsc)
- limits->max_rate = min(limits->max_rate, 810000);
limits->min_rate = min(limits->min_rate, limits->max_rate);
limits->min_lane_count = intel_dp_min_lane_count(intel_dp);
@@ -2640,9 +2652,9 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
if (!ret && intel_dp_is_uhbr(pipe_config))
ret = intel_dp_mtp_tu_compute_config(intel_dp,
pipe_config,
- pipe_config->pipe_bpp,
- pipe_config->pipe_bpp,
conn_state,
+ fxp_q4_from_int(pipe_config->pipe_bpp),
+ fxp_q4_from_int(pipe_config->pipe_bpp),
0, false);
if (ret)
dsc_needed = true;
@@ -2666,7 +2678,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
return -EINVAL;
ret = intel_dp_dsc_compute_config(intel_dp, pipe_config,
- conn_state, &limits, 64, true);
+ conn_state, &limits, 64);
if (ret < 0)
return ret;
}
@@ -2831,15 +2843,14 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp,
as_sdp->sdp_type = DP_SDP_ADAPTIVE_SYNC;
as_sdp->length = 0x9;
as_sdp->duration_incr_ms = 0;
+ as_sdp->vtotal = intel_vrr_vmin_vtotal(crtc_state);
if (crtc_state->cmrr.enable) {
as_sdp->mode = DP_AS_SDP_FAVT_TRR_REACHED;
- as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = drm_mode_vrefresh(adjusted_mode);
as_sdp->target_rr_divider = true;
} else {
as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL;
- as_sdp->vtotal = adjusted_mode->vtotal;
as_sdp->target_rr = 0;
}
}
@@ -2920,7 +2931,7 @@ static bool can_enable_drrs(struct intel_connector *connector,
const struct intel_crtc_state *pipe_config,
const struct drm_display_mode *downclock_mode)
{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
+ struct intel_display *display = to_intel_display(connector);
if (pipe_config->vrr.enable)
return false;
@@ -2938,7 +2949,7 @@ static bool can_enable_drrs(struct intel_connector *connector,
if (pipe_config->has_pch_encoder)
return false;
- if (!intel_cpu_transcoder_has_drrs(i915, pipe_config->cpu_transcoder))
+ if (!intel_cpu_transcoder_has_drrs(display, pipe_config->cpu_transcoder))
return false;
return downclock_mode &&
@@ -2951,7 +2962,6 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
int link_bpp_x16)
{
struct intel_display *display = to_intel_display(connector);
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
const struct drm_display_mode *downclock_mode =
intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode);
int pixel_clock;
@@ -2964,7 +2974,7 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
pipe_config->update_m_n = true;
if (!can_enable_drrs(connector, pipe_config, downclock_mode)) {
- if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder))
+ if (intel_cpu_transcoder_has_m2_n2(display, pipe_config->cpu_transcoder))
intel_zero_m_n(&pipe_config->dp_m2_n2);
return;
}
@@ -3064,15 +3074,6 @@ intel_dp_audio_compute_config(struct intel_encoder *encoder,
intel_dp_is_uhbr(pipe_config);
}
-static void intel_dp_queue_modeset_retry_work(struct intel_connector *connector)
-{
- struct drm_i915_private *i915 = to_i915(connector->base.dev);
-
- drm_connector_get(&connector->base);
- if (!queue_work(i915->unordered_wq, &connector->modeset_retry_work))
- drm_connector_put(&connector->base);
-}
-
void
intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
struct intel_encoder *encoder,
@@ -3089,7 +3090,7 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
intel_dp->needs_modeset_retry = true;
if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
- intel_dp_queue_modeset_retry_work(intel_dp->attached_connector);
+ intel_connector_queue_modeset_retry_work(intel_dp->attached_connector);
return;
}
@@ -3098,8 +3099,8 @@ intel_dp_queue_modeset_retry_for_link(struct intel_atomic_state *state,
if (!conn_state->base.crtc)
continue;
- if (connector->mst_port == intel_dp)
- intel_dp_queue_modeset_retry_work(connector);
+ if (connector->mst.dp == intel_dp)
+ intel_connector_queue_modeset_retry_work(connector);
}
}
@@ -3148,7 +3149,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
if ((intel_dp_is_edp(intel_dp) && fixed_mode) ||
pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
- ret = intel_panel_fitting(pipe_config, conn_state);
+ ret = intel_pfit_compute_config(pipe_config, conn_state);
if (ret)
return ret;
}
@@ -3320,8 +3321,8 @@ intel_dp_sink_set_dsc_passthrough(const struct intel_connector *connector,
bool enable)
{
struct intel_display *display = to_intel_display(connector);
- struct drm_dp_aux *aux = connector->port ?
- connector->port->passthrough_aux : NULL;
+ struct drm_dp_aux *aux = connector->mst.port ?
+ connector->mst.port->passthrough_aux : NULL;
if (!aux)
return;
@@ -3348,7 +3349,7 @@ static int intel_dp_dsc_aux_ref_count(struct intel_atomic_state *state,
* On SST the decompression AUX device won't be shared, each connector
* uses for this its own AUX targeting the sink device.
*/
- if (!connector->mst_port)
+ if (!connector->mst.dp)
return connector->dp.dsc_decompression_enabled ? 1 : 0;
for_each_oldnew_connector_in_state(&state->base, _connector_iter,
@@ -3356,7 +3357,7 @@ static int intel_dp_dsc_aux_ref_count(struct intel_atomic_state *state,
const struct intel_connector *
connector_iter = to_intel_connector(_connector_iter);
- if (connector_iter->mst_port != connector->mst_port)
+ if (connector_iter->mst.dp != connector->mst.dp)
continue;
if (!connector_iter->dp.dsc_decompression_enabled)
@@ -3526,9 +3527,9 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode)
ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, mode);
} else {
- struct intel_lspcon *lspcon = dp_to_lspcon(intel_dp);
+ struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- lspcon_resume(dp_to_dig_port(intel_dp));
+ intel_lspcon_resume(dig_port);
/* Write the source OUI as early as possible */
intel_dp_init_source_oui(intel_dp);
@@ -3544,8 +3545,8 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode)
msleep(1);
}
- if (ret == 1 && lspcon->active)
- lspcon_wait_pcon_mode(lspcon);
+ if (ret == 1 && intel_lspcon_active(dig_port))
+ intel_lspcon_wait_pcon_mode(dig_port);
}
if (ret != 1)
@@ -4188,6 +4189,9 @@ static void intel_edp_mso_init(struct intel_dp *intel_dp)
static void
intel_edp_set_sink_rates(struct intel_dp *intel_dp)
{
+ struct intel_display *display = to_intel_display(intel_dp);
+ struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+
intel_dp->num_sink_rates = 0;
if (intel_dp->edp_dpcd[0] >= DP_EDP_14) {
@@ -4198,10 +4202,7 @@ intel_edp_set_sink_rates(struct intel_dp *intel_dp)
sink_rates, sizeof(sink_rates));
for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
- int val = le16_to_cpu(sink_rates[i]);
-
- if (val == 0)
- break;
+ int rate;
/* Value read multiplied by 200kHz gives the per-lane
* link rate in kHz. The source rates are, however,
@@ -4209,7 +4210,24 @@ intel_edp_set_sink_rates(struct intel_dp *intel_dp)
* back to symbols is
* (val * 200kHz)*(8/10 ch. encoding)*(1/8 bit to Byte)
*/
- intel_dp->sink_rates[i] = (val * 200) / 10;
+ rate = le16_to_cpu(sink_rates[i]) * 200 / 10;
+
+ if (rate == 0)
+ break;
+
+ /*
+ * Some broken eDP sinks illegally declare support for
+ * HBR3 without TPS4, and are unable to produce a stable
+ * output. Reject HBR3 when TPS4 is not available.
+ */
+ if (rate >= 810000 && !drm_dp_tps4_supported(intel_dp->dpcd)) {
+ drm_dbg_kms(display->drm,
+ "[ENCODER:%d:%s] Rejecting HBR3 due to missing TPS4 support\n",
+ encoder->base.base.id, encoder->base.name);
+ break;
+ }
+
+ intel_dp->sink_rates[i] = rate;
}
intel_dp->num_sink_rates = i;
}
@@ -4414,7 +4432,7 @@ intel_dp_mst_configure(struct intel_dp *intel_dp)
if (intel_dp->is_mst)
intel_dp_mst_prepare_probe(intel_dp);
- drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
+ drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst.mgr, intel_dp->is_mst);
/* Avoid stale info on the next detect cycle. */
intel_dp->mst_detect = DRM_DP_SST;
@@ -4430,9 +4448,9 @@ intel_dp_mst_disconnect(struct intel_dp *intel_dp)
drm_dbg_kms(display->drm,
"MST device may have disappeared %d vs %d\n",
- intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
+ intel_dp->is_mst, intel_dp->mst.mgr.mst_state);
intel_dp->is_mst = false;
- drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
+ drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst.mgr, intel_dp->is_mst);
}
static bool
@@ -4938,7 +4956,7 @@ intel_dp_mst_hpd_irq(struct intel_dp *intel_dp, u8 *esi, u8 *ack)
{
bool handled = false;
- drm_dp_mst_hpd_irq_handle_event(&intel_dp->mst_mgr, esi, ack, &handled);
+ drm_dp_mst_hpd_irq_handle_event(&intel_dp->mst.mgr, esi, ack, &handled);
if (esi[1] & DP_CP_IRQ) {
intel_hdcp_handle_cp_irq(intel_dp->attached_connector);
@@ -4987,7 +5005,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
bool link_ok = true;
bool reprobe_needed = false;
- drm_WARN_ON_ONCE(display->drm, intel_dp->active_mst_links < 0);
+ drm_WARN_ON_ONCE(display->drm, intel_dp->mst.active_links < 0);
for (;;) {
u8 esi[4] = {};
@@ -5003,7 +5021,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
drm_dbg_kms(display->drm, "DPRX ESI: %4ph\n", esi);
- if (intel_dp->active_mst_links > 0 && link_ok &&
+ if (intel_dp->mst.active_links > 0 && link_ok &&
esi[3] & LINK_STATUS_CHANGED) {
if (!intel_dp_mst_link_status(intel_dp))
link_ok = false;
@@ -5026,7 +5044,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
drm_dbg_kms(display->drm, "Failed to ack ESI\n");
if (ack[1] & (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY))
- drm_dp_mst_hpd_irq_send_new_request(&intel_dp->mst_mgr);
+ drm_dp_mst_hpd_irq_send_new_request(&intel_dp->mst.mgr);
}
if (!link_ok || intel_dp->link.force_retrain)
@@ -5125,7 +5143,7 @@ bool intel_dp_has_connector(struct intel_dp *intel_dp,
/* MST */
for_each_pipe(display, pipe) {
- encoder = &intel_dp->mst_encoders[pipe]->base;
+ encoder = &intel_dp->mst.stream_encoders[pipe]->base;
if (conn_state->best_encoder == &encoder->base)
return true;
}
@@ -5211,7 +5229,6 @@ static int intel_dp_retrain_link(struct intel_encoder *encoder,
struct drm_modeset_acquire_ctx *ctx)
{
struct intel_display *display = to_intel_display(encoder);
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
u8 pipe_mask;
int ret;
@@ -5242,7 +5259,7 @@ static int intel_dp_retrain_link(struct intel_encoder *encoder,
encoder->base.base.id, encoder->base.name,
str_yes_no(intel_dp->link.force_retrain));
- ret = intel_modeset_commit_pipes(dev_priv, pipe_mask, ctx);
+ ret = intel_modeset_commit_pipes(display, pipe_mask, ctx);
if (ret == -EDEADLK)
return ret;
@@ -5395,7 +5412,7 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
if (drm_WARN_ON(display->drm, intel_dp_is_edp(intel_dp)))
return connector_status_connected;
- lspcon_resume(dig_port);
+ intel_lspcon_resume(dig_port);
if (!intel_dp_get_dpcd(intel_dp))
return connector_status_disconnected;
@@ -5477,13 +5494,13 @@ void intel_digital_port_unlock(struct intel_encoder *encoder)
*/
bool intel_digital_port_connected_locked(struct intel_encoder *encoder)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct intel_display *display = to_intel_display(encoder);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
bool is_glitch_free = intel_tc_port_handles_hpd_glitches(dig_port);
bool is_connected = false;
intel_wakeref_t wakeref;
- with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
+ with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
unsigned long wait_expires = jiffies + msecs_to_jiffies_timeout(4);
do {
@@ -5595,7 +5612,7 @@ intel_dp_update_420(struct intel_dp *intel_dp)
intel_dp->downstream_ports);
/* on-board LSPCON always assumed to support 4:4:4->4:2:0 conversion */
intel_dp->dfp.ycbcr_444_to_420 =
- dp_to_dig_port(intel_dp)->lspcon.active ||
+ intel_lspcon_active(dp_to_dig_port(intel_dp)) ||
drm_dp_downstream_444_to_420_conversion(intel_dp->dpcd,
intel_dp->downstream_ports);
intel_dp->dfp.rgb_to_ycbcr =
@@ -5869,7 +5886,6 @@ intel_dp_connector_register(struct drm_connector *connector)
struct intel_display *display = to_intel_display(connector->dev);
struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector));
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
- struct intel_lspcon *lspcon = &dig_port->lspcon;
int ret;
ret = intel_connector_register(connector);
@@ -5891,9 +5907,8 @@ intel_dp_connector_register(struct drm_connector *connector)
* ToDo: Clean this up to handle lspcon init and resume more
* efficiently and streamlined.
*/
- if (lspcon_init(dig_port)) {
- lspcon_detect_hdr_capability(lspcon);
- if (lspcon->hdr_supported)
+ if (intel_lspcon_init(dig_port)) {
+ if (intel_lspcon_detect_hdr_capability(dig_port))
drm_connector_attach_hdr_output_metadata_property(connector);
}
@@ -6086,7 +6101,7 @@ static int intel_dp_connector_atomic_check(struct drm_connector *conn,
return ret;
if (intel_dp_mst_source_support(intel_dp)) {
- ret = drm_dp_mst_root_conn_atomic_check(conn_state, &intel_dp->mst_mgr);
+ ret = drm_dp_mst_root_conn_atomic_check(conn_state, &intel_dp->mst.mgr);
if (ret)
return ret;
}
@@ -6495,35 +6510,6 @@ out_vdd_off:
return false;
}
-static void intel_dp_modeset_retry_work_fn(struct work_struct *work)
-{
- struct intel_connector *connector = container_of(work, typeof(*connector),
- modeset_retry_work);
- struct intel_display *display = to_intel_display(connector);
-
- drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s]\n", connector->base.base.id,
- connector->base.name);
-
- /* Grab the locks before changing connector property*/
- mutex_lock(&display->drm->mode_config.mutex);
- /* Set connector link status to BAD and send a Uevent to notify
- * userspace to do a modeset.
- */
- drm_connector_set_link_status_property(&connector->base,
- DRM_MODE_LINK_STATUS_BAD);
- mutex_unlock(&display->drm->mode_config.mutex);
- /* Send Hotplug uevent so userspace can reprobe */
- drm_kms_helper_connector_hotplug_event(&connector->base);
-
- drm_connector_put(&connector->base);
-}
-
-void intel_dp_init_modeset_retry_work(struct intel_connector *connector)
-{
- INIT_WORK(&connector->modeset_retry_work,
- intel_dp_modeset_retry_work_fn);
-}
-
bool
intel_dp_init_connector(struct intel_digital_port *dig_port,
struct intel_connector *connector)
@@ -6532,13 +6518,9 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
struct intel_dp *intel_dp = &dig_port->dp;
struct intel_encoder *encoder = &dig_port->base;
struct drm_device *dev = encoder->base.dev;
- struct drm_i915_private *dev_priv = to_i915(dev);
enum port port = encoder->port;
int type;
- /* Initialize the work for modeset in case of link train failure */
- intel_dp_init_modeset_retry_work(connector);
-
if (drm_WARN(dev, dig_port->max_lanes < 1,
"Not enough lanes (%d) for DP on [ENCODER:%d:%s]\n",
dig_port->max_lanes, encoder->base.base.id,
@@ -6632,7 +6614,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
return true;
fail:
- intel_display_power_flush_work(dev_priv);
+ intel_display_power_flush_work(display);
drm_connector_cleanup(&connector->base);
return false;
@@ -6657,7 +6639,7 @@ void intel_dp_mst_suspend(struct intel_display *display)
continue;
if (intel_dp->is_mst)
- drm_dp_mst_topology_mgr_suspend(&intel_dp->mst_mgr);
+ drm_dp_mst_topology_mgr_suspend(&intel_dp->mst.mgr);
}
}
@@ -6680,12 +6662,10 @@ void intel_dp_mst_resume(struct intel_display *display)
if (!intel_dp_mst_source_support(intel_dp))
continue;
- ret = drm_dp_mst_topology_mgr_resume(&intel_dp->mst_mgr,
- true);
+ ret = drm_dp_mst_topology_mgr_resume(&intel_dp->mst.mgr, true);
if (ret) {
intel_dp->is_mst = false;
- drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
- false);
+ drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst.mgr, false);
}
}
}