From patchwork Thu Sep 1 22:08:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Navare, Manasi" X-Patchwork-Id: 9309855 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 3E1F9607D6 for ; Thu, 1 Sep 2016 22:08:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 852432955D for ; Thu, 1 Sep 2016 22:08:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7A4232955F; Thu, 1 Sep 2016 22:08:51 +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=ham 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 F34DB2955D for ; Thu, 1 Sep 2016 22:08:50 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9DE006E9C7; Thu, 1 Sep 2016 22:08:43 +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 A5F5A6E31C for ; Thu, 1 Sep 2016 22:08:41 +0000 (UTC) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga105.jf.intel.com with ESMTP; 01 Sep 2016 15:08:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos; i="5.30,268,1470726000"; d="scan'208"; a="1023909213" Received: from manasi-otcmedia.jf.intel.com ([10.7.199.175]) by orsmga001.jf.intel.com with ESMTP; 01 Sep 2016 15:08:40 -0700 From: Manasi Navare To: intel-gfx@lists.freedesktop.org Date: Thu, 1 Sep 2016 15:08:19 -0700 Message-Id: <1472767699-31211-15-git-send-email-manasi.d.navare@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1472767699-31211-1-git-send-email-manasi.d.navare@intel.com> References: <1472767699-31211-1-git-send-email-manasi.d.navare@intel.com> Subject: [Intel-gfx] [PATCH 14/14] drm/i915/dp/mst: Add support for upfront link training for DP MST 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 From: Jim Bride Add upfront link training to intel_dp_mst_mode_valid() so that we know topology constraints before we validate the legality of modes to be checked. Call the function that loops through the link rates and lane counts starting from highest supported link rate and lane count for training the link in compliance with DP spec Signed-off-by: Manasi Navare Signed-off-by: Jim Bride --- drivers/gpu/drm/i915/intel_dp.c | 9 ++--- drivers/gpu/drm/i915/intel_dp_mst.c | 74 +++++++++++++++++++++++++++---------- drivers/gpu/drm/i915/intel_drv.h | 3 ++ 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 5a8ef69..83e882b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -131,7 +131,7 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, enum pipe pipe); static void intel_dp_unset_edid(struct intel_dp *intel_dp); -static int +int intel_dp_max_link_bw(struct intel_dp *intel_dp) { int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE]; @@ -150,7 +150,7 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp) return max_link_bw; } -static u8 intel_dp_max_lane_count(struct intel_dp *intel_dp) +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 temp, source_max, sink_max; @@ -312,8 +312,7 @@ static int intersect_rates(const int *source_rates, int source_len, return k; } -static int intel_dp_common_rates(struct intel_dp *intel_dp, - int *common_rates) +int intel_dp_common_rates(struct intel_dp *intel_dp, int *common_rates) { const int *source_rates, *sink_rates; int source_len, sink_len; @@ -336,7 +335,7 @@ static int intel_dp_common_rates(struct intel_dp *intel_dp, common_rates); } -static bool intel_dp_upfront_link_train(struct intel_dp *intel_dp) +bool intel_dp_upfront_link_train(struct intel_dp *intel_dp) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct intel_encoder *intel_encoder = &intel_dig_port->base; diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 54a9d76..98d45a4 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -41,21 +41,30 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, int bpp; int lane_count, slots; const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; - int mst_pbn; + int mst_pbn, common_len; + int common_rates[DP_MAX_SUPPORTED_RATES] = {}; pipe_config->dp_encoder_is_mst = true; pipe_config->has_pch_encoder = false; - bpp = 24; + /* - * for MST we always configure max link bw - the spec doesn't - * seem to suggest we should do otherwise. + * For MST we always configure for the maximum trainable link bw - + * the spec doesn't seem to suggest we should do otherwise. The + * calls to intel_dp_max_lane_count() and intel_dp_common_rates() + * both take successful upfront link training into account, and + * return the DisplayPort max supported values in the event that + * upfront link training was not done. */ - lane_count = drm_dp_max_lane_count(intel_dp->dpcd); + lane_count = intel_dp_max_lane_count(intel_dp); pipe_config->lane_count = lane_count; - pipe_config->pipe_bpp = 24; - pipe_config->port_clock = intel_dp_max_link_rate(intel_dp); + pipe_config->pipe_bpp = bpp = 24; + common_len = intel_dp_common_rates(intel_dp, common_rates); + pipe_config->port_clock = common_rates[common_len - 1]; + + DRM_DEBUG_KMS("DP MST link configured for %d lanes @ %d.\n", + pipe_config->lane_count, pipe_config->port_clock); state = pipe_config->base.state; @@ -137,6 +146,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, enum port port = intel_dig_port->port; struct intel_connector *connector = to_intel_connector(conn_state->connector); + struct intel_shared_dpll *pll = pipe_config->shared_dpll; + struct intel_shared_dpll_config tmp_pll_config; int ret; uint32_t temp; int slots; @@ -150,21 +161,23 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); if (intel_dp->active_mst_links == 0) { - intel_ddi_clk_select(&intel_dig_port->base, - pipe_config->shared_dpll); - - intel_prepare_dp_ddi_buffers(&intel_dig_port->base); - intel_dp_set_link_params(intel_dp, - pipe_config->port_clock, - pipe_config->lane_count, - true); - - intel_ddi_init_dp_buf_reg(&intel_dig_port->base); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + /* Disable the PLL since we need to acquire the PLL + * based on the link rate in the link training sequence + */ + tmp_pll_config = pll->config; + pll->funcs.disable(dev_priv, pll); + pll->config.crtc_mask = 0; + + /* If Link Training fails, send a uevent to generate a + *hotplug + */ + if (!(intel_ddi_link_train(intel_dp, pipe_config->port_clock, + pipe_config->lane_count, true, + false))) + drm_kms_helper_hotplug_event(encoder->base.dev); + pll->config = tmp_pll_config; - intel_dp_start_link_train(intel_dp); - intel_dp_stop_link_train(intel_dp); } ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr, @@ -336,6 +349,27 @@ intel_dp_mst_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; + struct intel_connector *intel_connector = to_intel_connector(connector); + struct intel_dp *intel_dp = intel_connector->mst_port; + + if (intel_dp->upfront_link_train && !intel_dp->upfront_done) { + bool do_upfront_link_train; + + do_upfront_link_train = intel_dp->compliance_test_type != + DP_TEST_LINK_TRAINING; + if (do_upfront_link_train) { + intel_dp->upfront_done = + intel_dp_upfront_link_train(intel_dp); + if (intel_dp->upfront_done) { + DRM_DEBUG_KMS("MST upfront trained at " + "%d lanes @ %d.", + intel_dp->max_lanes_upfront, + intel_dp->max_link_rate_upfront); + } else + DRM_DEBUG_KMS("MST upfront link training " + "failed."); + } + } /* TODO - validate mode against available PBN for link */ if (mode->clock < 10000) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 776beec..90fba17 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1416,6 +1416,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp); void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector); void intel_dp_mst_suspend(struct drm_device *dev); void intel_dp_mst_resume(struct drm_device *dev); +u8 intel_dp_max_lane_count(struct intel_dp *intel_dp); int intel_dp_max_link_rate(struct intel_dp *intel_dp); int intel_dp_rate_select(struct intel_dp *intel_dp, int rate); void intel_dp_hot_plug(struct intel_encoder *intel_encoder); @@ -1446,6 +1447,8 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing); void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock, uint8_t *link_bw, uint8_t *rate_select); bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp); +int intel_dp_common_rates(struct intel_dp *intel_dp, int *common_rates); +bool intel_dp_upfront_link_train(struct intel_dp *intel_dp); bool intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE]);