From patchwork Wed Nov 30 07:30:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Navare, Manasi" X-Patchwork-Id: 9453857 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7049B6071C for ; Wed, 30 Nov 2016 07:28:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 61921283AC for ; Wed, 30 Nov 2016 07:28:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5529A283D3; Wed, 30 Nov 2016 07:28:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E5301283AC for ; Wed, 30 Nov 2016 07:28:22 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 05A196E1B0; Wed, 30 Nov 2016 07:28:22 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by gabe.freedesktop.org (Postfix) with ESMTPS id 0F6136E1CF; Wed, 30 Nov 2016 07:28:04 +0000 (UTC) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga105.jf.intel.com with ESMTP; 29 Nov 2016 23:28:03 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,720,1473145200"; d="scan'208";a="35754350" Received: from manasi-otcmedia.jf.intel.com ([10.7.199.175]) by orsmga004.jf.intel.com with ESMTP; 29 Nov 2016 23:28:03 -0800 From: Manasi Navare To: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Date: Tue, 29 Nov 2016 23:30:32 -0800 Message-Id: <1480491033-1923-2-git-send-email-manasi.d.navare@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1480491033-1923-1-git-send-email-manasi.d.navare@intel.com> References: <1480491033-1923-1-git-send-email-manasi.d.navare@intel.com> Cc: Daniel Vetter Subject: [Intel-gfx] [PATCH 2/3] drm/i915: Find fallback link rate/lane count X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP If link training fails, then we need to fallback to lower link rate first and if link training fails at RBR, then fallback to lower lane count. This function finds the next lower link rate/lane count value after link training failure and limits the max link_rate and lane_count values to these fallback values. v6: * Cap the max link rate and lane count to the max values obtained during fallback link training (Daniel Vetter) v5: * Start the fallback at the lane count value passed not the max lane count (Jani Nikula) v4: * Remove the redundant variable link_train_failed v3: * Remove fallback_link_rate_index variable, just obtain that using the helper intel_dp_link_rate_index (Jani Nikula) v2: Squash the patch that returns the link rate index (Jani Nikula) Acked-by: Tony Cheng Acked-by: Harry Wentland Cc: Ville Syrjala Cc: Jani Nikula Cc: Daniel Vetter Signed-off-by: Manasi Navare --- drivers/gpu/drm/i915/intel_dp.c | 59 ++++++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_drv.h | 4 +++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 8026a83..bc1268c 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -153,12 +153,18 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, static u8 intel_dp_max_lane_count(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); - u8 source_max, sink_max; + u8 temp, source_max, sink_max; source_max = intel_dig_port->max_lanes; sink_max = drm_dp_max_lane_count(intel_dp->dpcd); + temp = min(source_max, sink_max); + /* Limit the max value to max fallback value during link train + * failure handling. + */ + if (intel_dp->fallback_lane_count) + return min(temp, intel_dp->fallback_lane_count); - return min(source_max, sink_max); + return temp; } /* @@ -281,6 +287,15 @@ static int intel_dp_common_rates(struct intel_dp *intel_dp, int source_len, sink_len; sink_len = intel_dp_sink_rates(intel_dp, &sink_rates); + /* Limit the max sink rate to the max fallback link rate + * found during link training failure handling. + */ + if (intel_dp->fallback_link_rate) { + int len = sink_len - 1; + while (len > 0 && sink_rates[len] > intel_dp->fallback_link_rate) + len--; + sink_len = len + 1; + } source_len = intel_dp_source_rates(intel_dp, &source_rates); return intersect_rates(source_rates, source_len, @@ -288,6 +303,46 @@ static int intel_dp_common_rates(struct intel_dp *intel_dp, common_rates); } +static int intel_dp_link_rate_index(struct intel_dp *intel_dp, + int *common_rates, int link_rate) +{ + int common_len; + int index; + + common_len = intel_dp_common_rates(intel_dp, common_rates); + for (index = 0; index < common_len; index++) { + if (link_rate == common_rates[common_len - index - 1]) + return common_len - index - 1; + } + + return -1; +} + +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] = {}; + int common_len; + int link_rate_index = -1; + + common_len = intel_dp_common_rates(intel_dp, common_rates); + link_rate_index = intel_dp_link_rate_index(intel_dp, + common_rates, + link_rate); + if (link_rate_index > 0) { + intel_dp->fallback_link_rate = common_rates[link_rate_index - 1]; + intel_dp->fallback_lane_count = lane_count; + } else if (lane_count > 1) { + intel_dp->fallback_link_rate = 0; + intel_dp->fallback_lane_count = lane_count >> 1; + } else { + DRM_ERROR("Link Training Unsuccessful\n"); + return -1; + } + + return 0; +} + static enum drm_mode_status intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9bbe5c5..2da3b40 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -891,6 +891,8 @@ struct intel_dp { uint32_t DP; int link_rate; uint8_t lane_count; + int fallback_link_rate; + uint8_t fallback_lane_count; uint8_t sink_count; bool link_mst; bool has_audio; @@ -1393,6 +1395,8 @@ bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, void intel_dp_set_link_params(struct intel_dp *intel_dp, int link_rate, uint8_t lane_count, bool link_mst); +int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, + int link_rate, uint8_t lane_count); void intel_dp_start_link_train(struct intel_dp *intel_dp); void intel_dp_stop_link_train(struct intel_dp *intel_dp); void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode);