diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index e4650f1625cc..1808af6d635d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -284,17 +284,29 @@ static int intel_dp_rate_index(const int *rates, int len, int rate) return -1; } -static int intel_dp_common_rates(struct intel_dp *intel_dp, - int *common_rates) +static void intel_dp_set_common_rates(struct intel_dp *intel_dp) { - int max_rate = intel_dp->max_sink_link_rate; - int i, common_len; + WARN_ON(!intel_dp->num_source_rates || !intel_dp->num_sink_rates); - common_len = intersect_rates(intel_dp->source_rates, - intel_dp->num_source_rates, - intel_dp->sink_rates, - intel_dp->num_sink_rates, - common_rates); + intel_dp->num_common_rates = intersect_rates(intel_dp->source_rates, + intel_dp->num_source_rates, + intel_dp->sink_rates, + intel_dp->num_sink_rates, + intel_dp->common_rates); + + /* Paranoia, there should always be something in common. */ + if (WARN_ON(intel_dp->num_common_rates == 0)) { + intel_dp->common_rates[0] = default_rates[0]; + intel_dp->num_common_rates = 1; + } +} + +/* get length of common rates potentially limited by max_rate */ +static int intel_dp_common_len_rate_limit(struct intel_dp *intel_dp, + int max_rate) +{ + const int *common_rates = intel_dp->common_rates; + int i, common_len = intel_dp->num_common_rates; /* Limit results by potentially reduced max rate */ for (i = 0; i < common_len; i++) { @@ -305,25 +317,23 @@ static int intel_dp_common_rates(struct intel_dp *intel_dp, return 0; } -static int intel_dp_link_rate_index(struct intel_dp *intel_dp, - int *common_rates, int link_rate) +static int intel_dp_link_rate_index(struct intel_dp *intel_dp, int link_rate) { int common_len; - common_len = intel_dp_common_rates(intel_dp, common_rates); + common_len = intel_dp_common_len_rate_limit(intel_dp, + intel_dp->max_sink_link_rate); - return intel_dp_rate_index(common_rates, common_len, link_rate); + return intel_dp_rate_index(intel_dp->common_rates, common_len, link_rate); } int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, int link_rate, uint8_t lane_count) { - int common_rates[DP_MAX_SUPPORTED_RATES]; + const int *common_rates = intel_dp->common_rates; int link_rate_index; - link_rate_index = intel_dp_link_rate_index(intel_dp, - common_rates, - link_rate); + link_rate_index = intel_dp_link_rate_index(intel_dp, link_rate); if (link_rate_index > 0) { intel_dp->max_sink_link_rate = common_rates[link_rate_index - 1]; intel_dp->max_sink_lane_count = lane_count; @@ -1506,8 +1516,6 @@ static void snprintf_int_array(char *str, size_t len, static void intel_dp_print_rates(struct intel_dp *intel_dp) { - int common_len; - int common_rates[DP_MAX_SUPPORTED_RATES]; char str[128]; /* FIXME: too big for stack? */ if ((drm_debug & DRM_UT_KMS) == 0) @@ -1521,8 +1529,8 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp) intel_dp->sink_rates, intel_dp->num_sink_rates); DRM_DEBUG_KMS("sink rates: %s\n", str); - common_len = intel_dp_common_rates(intel_dp, common_rates); - snprintf_int_array(str, sizeof(str), common_rates, common_len); + snprintf_int_array(str, sizeof(str), + intel_dp->common_rates, intel_dp->num_common_rates); DRM_DEBUG_KMS("common rates: %s\n", str); } @@ -1560,14 +1568,14 @@ bool intel_dp_read_desc(struct intel_dp *intel_dp) int intel_dp_max_link_rate(struct intel_dp *intel_dp) { - int rates[DP_MAX_SUPPORTED_RATES] = {}; int len; - len = intel_dp_common_rates(intel_dp, rates); + len = intel_dp_common_len_rate_limit(intel_dp, + intel_dp->max_sink_link_rate); if (WARN_ON(len <= 0)) return 162000; - return rates[len - 1]; + return intel_dp->common_rates[len - 1]; } int intel_dp_rate_select(struct intel_dp *intel_dp, int rate) @@ -1636,11 +1644,11 @@ intel_dp_compute_config(struct intel_encoder *encoder, int link_rate_index; int bpp, mode_rate; int link_avail, link_clock; - int common_rates[DP_MAX_SUPPORTED_RATES] = {}; int common_len; uint8_t link_bw, rate_select; - common_len = intel_dp_common_rates(intel_dp, common_rates); + common_len = intel_dp_common_len_rate_limit(intel_dp, + intel_dp->max_sink_link_rate); /* No common link rates between source and sink */ WARN_ON(common_len <= 0); @@ -1678,7 +1686,6 @@ intel_dp_compute_config(struct intel_encoder *encoder, /* Use values requested by Compliance Test Request */ if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) { link_rate_index = intel_dp_link_rate_index(intel_dp, - common_rates, intel_dp->compliance.test_link_rate); if (link_rate_index >= 0) min_clock = max_clock = link_rate_index; @@ -1686,7 +1693,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, } DRM_DEBUG_KMS("DP link computation with max lane count %i " "max bw %d pixel clock %iKHz\n", - max_lane_count, common_rates[max_clock], + max_lane_count, intel_dp->common_rates[max_clock], adjusted_mode->crtc_clock); /* Walk through all bpp values. Luckily they're all nicely spaced with 2 @@ -1722,7 +1729,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, lane_count <= max_lane_count; lane_count <<= 1) { - link_clock = common_rates[clock]; + link_clock = intel_dp->common_rates[clock]; link_avail = intel_dp_max_data_rate(link_clock, lane_count); @@ -1754,7 +1761,7 @@ found: pipe_config->lane_count = lane_count; pipe_config->pipe_bpp = bpp; - pipe_config->port_clock = common_rates[clock]; + pipe_config->port_clock = intel_dp->common_rates[clock]; intel_dp_compute_rate(intel_dp, pipe_config->port_clock, &link_bw, &rate_select); @@ -3715,6 +3722,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) else intel_dp_set_sink_rates(intel_dp); + intel_dp_set_common_rates(intel_dp); + return true; } @@ -3726,8 +3735,10 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) return false; /* Don't clobber cached eDP rates. */ - if (!is_edp(intel_dp)) + if (!is_edp(intel_dp)) { intel_dp_set_sink_rates(intel_dp); + intel_dp_set_common_rates(intel_dp); + } if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT, &intel_dp->sink_count, 1) < 0) @@ -3950,7 +3961,6 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp) { int status = 0; int min_lane_count = 1; - int common_rates[DP_MAX_SUPPORTED_RATES] = {}; int link_rate_index, test_link_rate; uint8_t test_lane_count, test_link_bw; /* (DP CTS 1.2) @@ -3979,7 +3989,6 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp) /* Validate the requested link rate */ test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw); link_rate_index = intel_dp_link_rate_index(intel_dp, - common_rates, test_link_rate); if (link_rate_index < 0) return DP_TEST_NAK; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 92e353dc61bf..4a4bf9cb0d90 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -956,6 +956,9 @@ struct intel_dp { int num_sink_rates; int sink_rates[DP_MAX_SUPPORTED_RATES]; bool use_rate_select; + /* intersection of source and sink rates */ + int num_common_rates; + int common_rates[DP_MAX_SUPPORTED_RATES]; /* Max lane count for the sink as per DPCD registers */ uint8_t max_sink_lane_count; /* Max link BW for the sink as per DPCD registers */