diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dp.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_dp.c | 425 |
1 files changed, 201 insertions, 224 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f1f3b1bb1e89..9476aaa91900 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]); - return 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 max_rate; } static int max_dprx_lane_count(struct intel_dp *intel_dp) @@ -1075,7 +1093,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 +1394,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 +1409,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 +1424,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 +1513,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) @@ -1791,7 +1808,7 @@ int intel_dp_dsc_max_src_input_bpc(struct intel_display *display) if (DISPLAY_VER(display) == 11) return 10; - return 0; + return intel_dp_dsc_min_src_input_bpc(); } int intel_dp_dsc_compute_max_bpp(const struct intel_connector *connector, @@ -1926,7 +1943,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 +1951,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 +1975,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,112 +2095,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); + struct intel_display *display = to_intel_display(connector); + u8 incr = drm_dp_dsc_sink_bpp_incr(connector->dp.dsc_dpcd); - for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) { - if (valid_dsc_bpp[i] < dsc_min_bpp) - continue; - if (valid_dsc_bpp[i] > dsc_max_bpp) - break; + if (DISPLAY_VER(display) < 14 || !incr) + return fxp_q4_from_int(1); - 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; - } - } - - 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); @@ -2169,11 +2163,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) @@ -2183,7 +2204,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 && @@ -2192,7 +2213,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; @@ -2218,13 +2239,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; @@ -2232,7 +2251,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; @@ -2240,9 +2259,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. @@ -2250,11 +2266,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; @@ -2268,7 +2283,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 = @@ -2333,9 +2348,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 = @@ -2343,6 +2357,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); @@ -2351,12 +2366,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); @@ -2519,9 +2532,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); @@ -2641,9 +2651,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; @@ -2667,7 +2677,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; } @@ -2829,19 +2839,17 @@ static void intel_dp_compute_as_sdp(struct intel_dp *intel_dp, crtc_state->infoframes.enable |= intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); - /* Currently only DP_AS_SDP_AVT_FIXED_VTOTAL mode supported */ 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_FIXED_VTOTAL; - as_sdp->vtotal = adjusted_mode->vtotal; + as_sdp->mode = DP_AS_SDP_AVT_DYNAMIC_VTOTAL; as_sdp->target_rr = 0; } } @@ -2922,7 +2930,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; @@ -2940,7 +2948,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 && @@ -2953,7 +2961,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; @@ -2966,7 +2973,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; } @@ -3066,15 +3073,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, @@ -3091,7 +3089,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; } @@ -3100,8 +3098,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); } } @@ -3150,7 +3148,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; } @@ -3322,8 +3320,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; @@ -3350,7 +3348,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, @@ -3358,7 +3356,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) @@ -3528,9 +3526,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); @@ -3546,8 +3544,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) @@ -4190,6 +4188,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) { @@ -4200,10 +4201,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, @@ -4211,7 +4209,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; } @@ -4416,7 +4431,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; @@ -4432,9 +4447,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 @@ -4940,7 +4955,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); @@ -4989,7 +5004,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] = {}; @@ -5005,7 +5020,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; @@ -5028,7 +5043,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) @@ -5127,7 +5142,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; } @@ -5213,7 +5228,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; @@ -5244,7 +5258,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; @@ -5397,7 +5411,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; @@ -5479,13 +5493,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 { @@ -5597,7 +5611,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 = @@ -5871,7 +5885,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); @@ -5893,9 +5906,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); } @@ -6088,7 +6100,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; } @@ -6497,35 +6509,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) @@ -6534,13 +6517,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, @@ -6634,7 +6613,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; @@ -6659,7 +6638,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); } } @@ -6682,12 +6661,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); } } } |