From: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> Extract this function to make the input and output parameters more clear to the code reader. I also have plans to allow ways to change the current parameters, so the code will get even more complicated without the refactor. I also have plans to add alternative implementations to intel_dp_compute_link_config() and, again, the refactor makes it easier. Another change worth noticing is that now we will print all our "attempts" in dmesg (see the debug code at link_config_is_possible()). This will allow us to quickly identify if the user is trying fast and narrow, or wide and slow, and also identify the minimum and maximum BW and lane count values used by the code. Signed-off-by: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx> --- drivers/gpu/drm/i915/intel_dp.c | 94 +++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 19537a6..884166b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -768,6 +768,52 @@ intel_dp_set_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n) I915_WRITE(PIPE_LINK_N2(transcoder), m_n->link_n); } +static bool link_config_is_possible(int mode_rate, int lanes, int bw) +{ + int link_clock, link_avail; + + link_clock = drm_dp_bw_code_to_link_rate(bw); + link_avail = intel_dp_max_data_rate(link_clock, lanes); + + DRM_DEBUG_KMS("DP link avail with 0x%x bw and %d lanes: %d. Required: %d (%d%%)\n", + bw, lanes, link_avail, mode_rate, + mode_rate * 100 / link_avail); + + return (mode_rate <= link_avail); +} + +/* + * This function tries to find the minimal number of lanes and BW required based + * on the parameters given. If not possible, it returns false. + */ +static bool intel_dp_compute_link_config(int mode_clock, int bpp, + int min_lanes, int max_lanes, + int min_bw, int max_bw, + int *lanes_used, int *bw_used) +{ + /* Conveniently, the link BW constants become indices with a shift...*/ + static int bws[] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7, DP_LINK_BW_5_4 }; + int min_bw_index = min_bw >> 3; + int max_bw_index = max_bw >> 3; + int mode_rate; + int lanes, bw_it; + + mode_rate = intel_dp_link_required(mode_clock, bpp); + + for (lanes = min_lanes; lanes <= max_lanes; lanes <<= 1) + for (bw_it = min_bw_index; bw_it <= max_bw_index; bw_it++) + if (link_config_is_possible(mode_rate, lanes, + bws[bw_it])) + goto found; + + return false; + +found: + *lanes_used = lanes; + *bw_used = bws[bw_it]; + return true; +} + bool intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) @@ -779,13 +825,10 @@ intel_dp_compute_config(struct intel_encoder *encoder, enum port port = dp_to_dig_port(intel_dp)->port; struct intel_crtc *intel_crtc = encoder->new_crtc; struct intel_connector *intel_connector = intel_dp->attached_connector; - int lane_count, clock; + int lanes_used, bw_used; int max_lane_count = intel_dp_max_lane_count(intel_dp); - /* Conveniently, the link BW constants become indices with a shift...*/ - int max_clock = intel_dp_max_link_bw(intel_dp) >> 3; - int bpp, mode_rate; - static int bws[] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7, DP_LINK_BW_5_4 }; - int link_avail, link_clock; + int max_bw = intel_dp_max_link_bw(intel_dp); + int bpp; if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A) pipe_config->has_pch_encoder = true; @@ -808,7 +851,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, DRM_DEBUG_KMS("DP link computation with max lane count %i " "max bw %02x pixel clock %iKHz\n", - max_lane_count, bws[max_clock], + max_lane_count, max_bw, adjusted_mode->crtc_clock); /* Walk through all bpp values. Luckily they're all nicely spaced with 2 @@ -821,26 +864,17 @@ intel_dp_compute_config(struct intel_encoder *encoder, bpp = dev_priv->vbt.edp_bpp; } - for (; bpp >= 6*3; bpp -= 2*3) { - mode_rate = intel_dp_link_required(adjusted_mode->crtc_clock, - bpp); - - for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { - for (clock = 0; clock <= max_clock; clock++) { - link_clock = drm_dp_bw_code_to_link_rate(bws[clock]); - link_avail = intel_dp_max_data_rate(link_clock, - lane_count); - - if (mode_rate <= link_avail) { - goto found; - } - } - } - } + for (; bpp >= 6*3; bpp -= 2*3) + if (intel_dp_compute_link_config(adjusted_mode->crtc_clock, bpp, + 1, max_lane_count, + DP_LINK_BW_1_62, + max_bw, + &lanes_used, &bw_used)) + break; - return false; + if (bpp < 6*3) + return false; -found: if (intel_dp->color_range_auto) { /* * See: @@ -856,25 +890,23 @@ found: if (intel_dp->color_range) pipe_config->limited_color_range = true; - intel_dp->link_bw = bws[clock]; - intel_dp->lane_count = lane_count; + intel_dp->link_bw = bw_used; + intel_dp->lane_count = lanes_used; pipe_config->pipe_bpp = bpp; pipe_config->port_clock = drm_dp_bw_code_to_link_rate(intel_dp->link_bw); DRM_DEBUG_KMS("DP link bw %02x lane count %d clock %d bpp %d\n", intel_dp->link_bw, intel_dp->lane_count, pipe_config->port_clock, bpp); - DRM_DEBUG_KMS("DP link bw required %i available %i\n", - mode_rate, link_avail); - intel_link_compute_m_n(bpp, lane_count, + intel_link_compute_m_n(bpp, lanes_used, adjusted_mode->crtc_clock, pipe_config->port_clock, &pipe_config->dp_m_n); if (intel_connector->panel.downclock_mode != NULL && intel_dp->drrs_state.type == SEAMLESS_DRRS_SUPPORT) { - intel_link_compute_m_n(bpp, lane_count, + intel_link_compute_m_n(bpp, lanes_used, intel_connector->panel.downclock_mode->clock, pipe_config->port_clock, &pipe_config->dp_m2_n2); -- 1.9.0 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx