From: Manasi Navare <manasi.d.navare@intel.com>
To: Mika Kahola <mika.kahola@intel.com>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH v2 11/14] drm/i915: Fallback to lower link rate and lane count during link training
Date: Wed, 7 Sep 2016 09:48:25 -0700 [thread overview]
Message-ID: <20160907164825.GA29651@intel.com> (raw)
In-Reply-To: <1473241669.28727.22.camel@intel.com>
On Wed, Sep 07, 2016 at 12:47:49PM +0300, Mika Kahola wrote:
> On Tue, 2016-09-06 at 17:13 -0700, Manasi Navare wrote:
> > According to the DisplayPort Spec, in case of Clock Recovery failure
> > the link training sequence should fall back to the lower link rate
> > followed by lower lane count until CR succeeds.
> > On CR success, the sequence proceeds with Channel EQ.
> > In case of Channel EQ failures, it should fallback to
> > lower link rate and lane count and start the CR phase again.
> >
> > v2:
> > * Add a helper function to return index of requested link rate
> > into common_rates array
> > * Changed the link rate fallback loop to make use
> > of common_rates array (Mika Kahola)
> > * Changed INTEL_INFO to INTEL_GEN (David Weinehall)
> >
> > Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
> > ---
> > drivers/gpu/drm/i915/intel_ddi.c | 125
> > +++++++++++++++++++++++---
> > drivers/gpu/drm/i915/intel_dp.c | 15 ++++
> > drivers/gpu/drm/i915/intel_dp_link_training.c | 12 ++-
> > drivers/gpu/drm/i915/intel_drv.h | 7 +-
> > 4 files changed, 145 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> > b/drivers/gpu/drm/i915/intel_ddi.c
> > index 67a6a0b..e38bf4b 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -1634,19 +1634,18 @@ void intel_ddi_clk_select(struct
> > intel_encoder *encoder,
> > }
> > }
> >
> > -static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
> > +static void intel_ddi_pre_enable_edp(struct intel_encoder *encoder,
> > int link_rate, uint32_t
> > lane_count,
> > - struct intel_shared_dpll *pll,
> > - bool link_mst)
> > + struct intel_shared_dpll *pll)
> > {
> > struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> > struct drm_i915_private *dev_priv = to_i915(encoder-
> > >base.dev);
> > enum port port = intel_ddi_get_encoder_port(encoder);
> >
> > intel_dp_set_link_params(intel_dp, link_rate, lane_count,
> > - link_mst);
> > - if (encoder->type == INTEL_OUTPUT_EDP)
> > - intel_edp_panel_on(intel_dp);
> > + false);
> > +
> > + intel_edp_panel_on(intel_dp);
> >
> > intel_ddi_clk_select(encoder, pll);
> > intel_prepare_dp_ddi_buffers(encoder);
> > @@ -1657,6 +1656,29 @@ static void intel_ddi_pre_enable_dp(struct
> > intel_encoder *encoder,
> > intel_dp_stop_link_train(intel_dp);
> > }
> >
> > +static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
> > + int link_rate, uint32_t
> > lane_count,
> > + struct intel_shared_dpll *pll,
> > + bool link_mst)
> > +{
> > + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> > + struct drm_i915_private *dev_priv = to_i915(encoder-
> > >base.dev);
> > + struct intel_shared_dpll_config tmp_pll_config;
> > +
> > + /* Disable the PLL and obtain the PLL for Link Training
> > + * that starts with highest link rate and lane count.
> > + */
> > + 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, link_rate, lane_count,
> > link_mst,
> > + false)))
> > + drm_kms_helper_hotplug_event(encoder->base.dev);
> > + pll->config = tmp_pll_config;
> > +}
> > +
> > static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder,
> > bool has_hdmi_sink,
> > struct drm_display_mode
> > *adjusted_mode,
> > @@ -1690,20 +1712,26 @@ static void intel_ddi_pre_enable(struct
> > intel_encoder *intel_encoder,
> > struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
> > int type = intel_encoder->type;
> >
> > - if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
> > + if (type == INTEL_OUTPUT_EDP)
> > + intel_ddi_pre_enable_edp(intel_encoder,
> > + crtc->config->port_clock,
> > + crtc->config->lane_count,
> > + crtc->config->shared_dpll);
> > +
> > + if (type == INTEL_OUTPUT_DP)
> > intel_ddi_pre_enable_dp(intel_encoder,
> > crtc->config->port_clock,
> > crtc->config->lane_count,
> > crtc->config->shared_dpll,
> > intel_crtc_has_type(crtc-
> > >config,
> > INTEL_OU
> > TPUT_DP_MST));
> > - }
> > - if (type == INTEL_OUTPUT_HDMI) {
> > +
> > + if (type == INTEL_OUTPUT_HDMI)
> > intel_ddi_pre_enable_hdmi(intel_encoder,
> > crtc->config-
> > >has_hdmi_sink,
> > &crtc->config-
> > >base.adjusted_mode,
> > crtc->config-
> > >shared_dpll);
> > - }
> > +
> > }
> >
> > static void intel_ddi_post_disable(struct intel_encoder
> > *intel_encoder,
> > @@ -2431,6 +2459,83 @@ intel_ddi_get_link_dpll(struct intel_dp
> > *intel_dp, int clock)
> > return pll;
> > }
> >
> > +bool
> > +intel_ddi_link_train(struct intel_dp *intel_dp, int max_link_rate,
> > + uint8_t max_lane_count, bool link_mst, bool
> > is_upfront)
> > +{
> > + struct intel_connector *connector = intel_dp-
> > >attached_connector;
> > + struct intel_encoder *encoder = connector->encoder;
> > + struct drm_i915_private *dev_priv = to_i915(encoder-
> > >base.dev);
> > + struct intel_shared_dpll *pll;
> > + struct intel_shared_dpll_config tmp_pll_config;
> > + int link_rate, link_rate_index;
> > + uint8_t lane_count;
> > + int common_rates[DP_MAX_SUPPORTED_RATES] = {};
> > + bool ret = false;
> > +
> > + link_rate_index = intel_dp_link_rate_index(intel_dp,
> > common_rates,
> > + max_link_rate);
> > + if (link_rate_index < 0) {
> > + DRM_ERROR("Invalid Link Rate\n");
> > + return false;
> > + }
> > + for (lane_count = max_lane_count; lane_count > 0; lane_count
> > >>= 1) {
> > + for (link_rate = common_rates[link_rate_index];
> > + link_rate_index >= 0; link_rate_index --) {
> > + pll = intel_ddi_get_link_dpll(intel_dp,
> > link_rate);
> > + if (pll == NULL) {
> > + DRM_ERROR("Could not find DPLL for
> > link "
> > + "training.\n");
> > + return false;
> > + }
> > + tmp_pll_config = pll->config;
> > + pll->funcs.enable(dev_priv, pll);
> > +
> > + intel_dp_set_link_params(intel_dp,
> > link_rate,
> > + lane_count,
> > link_mst);
> > +
> > + intel_ddi_clk_select(encoder, pll);
> > + intel_prepare_dp_ddi_buffers(encoder);
> > + intel_ddi_init_dp_buf_reg(encoder);
> > + intel_dp_sink_dpms(intel_dp,
> > DRM_MODE_DPMS_ON);
> > + ret = intel_dp_start_link_train(intel_dp);
> > + if (ret)
> > + break;
> > +
> > + /* Disable port followed by PLL for next
> > retry/clean up */
> > + intel_ddi_post_disable(encoder, NULL, NULL);
> > + pll->funcs.disable(dev_priv, pll);
> > + pll->config = tmp_pll_config;
> > + }
> > + if (ret) {
> > + DRM_DEBUG_KMS("Link Training successful at
> > link rate: "
> > + "%d lane:%d\n", link_rate,
> > lane_count);
> > + break;
> > + }
> > + }
> > + intel_dp_stop_link_train(intel_dp);
> > +
> > + if (is_upfront) {
> > + DRM_DEBUG_KMS("Upfront link train %s: link_clock:%d
> > lanes:%d\n",
> > + ret ? "Passed" : "Failed",
> > + link_rate, lane_count);
> > + /* Disable port followed by PLL for next retry/clean
> > up */
> > + intel_ddi_post_disable(encoder, NULL, NULL);
> > + pll->funcs.disable(dev_priv, pll);
> > + pll->config = tmp_pll_config;
> In a case where link training was successful, I guess we could leave
> the port on. Is there a reason why we should do otherwise?
>
The port needs to be turned off and plls need to be disabled in case of upfront
since we dont want to change any HW state yet. Upfront training only happens
to cache the max lanes and lax link rate values and does not change any HW state.
>
> > + if (ret) {
> > + /* Save the upfront values */
> > + intel_dp->max_lanes_upfront = lane_count;
> > + intel_dp->max_link_rate_upfront = link_rate;
> My compiler wasn't really a big fan of these new members in a intel_dp
> struct so I these needs to be defined in intel_drv.h
>
> drivers/gpu/drm/i915/intel_ddi.c: In function ‘intel_ddi_link_train’:
> drivers/gpu/drm/i915/intel_ddi.c:2528:12: error: ‘struct intel_dp’ has
> no member named ‘max_lanes_upfront’
> intel_dp->max_lanes_upfront = lane_count;
> ^
> drivers/gpu/drm/i915/intel_ddi.c:2529:12: error: ‘struct intel_dp’ has
> no member named ‘max_link_rate_upfront’
>
This probably happened due to rebasing issue. Actually this entire if upfront part
should be added in the next patch that enables upfront link training. That is where
these fields get defined inside the intel_dp structure.
I will correct this and submit a new revision.
Manasi
> intel_dp->max_link_rate_upfront = link_rate;
> > + }
> > + }
> > +
> > + if (!lane_count)
> > + DRM_ERROR("Link Training Failed\n");
> > +
> > + return ret;
> > +}
> > +
> > void intel_ddi_init(struct drm_device *dev, enum port port)
> > {
> > struct drm_i915_private *dev_priv = to_i915(dev);
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c
> > b/drivers/gpu/drm/i915/intel_dp.c
> > index dfdbe65..391e384 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1443,6 +1443,21 @@ intel_dp_max_link_rate(struct intel_dp
> > *intel_dp)
> > return rates[len - 1];
> > }
> >
> > +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 = common_len - 1; index >= 0; index--) {
> > + if (link_rate == common_rates[index])
> > + return index;
> > + }
> > +
> > + return -1;
> > +}
> > +
> > int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
> > {
> > return rate_to_index(rate, intel_dp->sink_rates);
> > diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c
> > b/drivers/gpu/drm/i915/intel_dp_link_training.c
> > index 0fb845d..705dbd1 100644
> > --- a/drivers/gpu/drm/i915/intel_dp_link_training.c
> > +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c
> > @@ -309,9 +309,15 @@ void intel_dp_stop_link_train(struct intel_dp
> > *intel_dp)
> > DP_TRAINING_PATTERN_DISABLE);
> > }
> >
> > -void
> > +bool
> > intel_dp_start_link_train(struct intel_dp *intel_dp)
> > {
> > - intel_dp_link_training_clock_recovery(intel_dp);
> > - intel_dp_link_training_channel_equalization(intel_dp);
> > + bool ret;
> > +
> > + if (intel_dp_link_training_clock_recovery(intel_dp)) {
> > + ret =
> > intel_dp_link_training_channel_equalization(intel_dp);
> > + if (ret)
> > + return true;
> > + }
> > + return false;
> > }
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h
> > b/drivers/gpu/drm/i915/intel_drv.h
> > index e5bc976..90e7b15 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -1160,6 +1160,9 @@ void intel_ddi_clock_get(struct intel_encoder
> > *encoder,
> > struct intel_crtc_state *pipe_config);
> > void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool
> > state);
> > uint32_t ddi_signal_levels(struct intel_dp *intel_dp);
> > +bool intel_ddi_link_train(struct intel_dp *intel_dp, int
> > max_link_rate,
> > + uint8_t max_lane_count, bool link_mst,
> > + bool is_upfront);
> > struct intel_shared_dpll *intel_ddi_get_link_dpll(struct intel_dp
> > *intel_dp,
> > int clock);
> > unsigned int intel_fb_align_height(struct drm_device *dev,
> > @@ -1381,7 +1384,7 @@ 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);
> > -void intel_dp_start_link_train(struct intel_dp *intel_dp);
> > +bool 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);
> > void intel_dp_encoder_reset(struct drm_encoder *encoder);
> > @@ -1403,6 +1406,8 @@ void intel_dp_add_properties(struct intel_dp
> > *intel_dp, struct drm_connector *co
> > void intel_dp_mst_suspend(struct drm_device *dev);
> > void intel_dp_mst_resume(struct drm_device *dev);
> > int intel_dp_max_link_rate(struct intel_dp *intel_dp);
> > +int intel_dp_link_rate_index(struct intel_dp *intel_dp, int
> > *common_rates,
> > + int link_rate);
> > int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
> > void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
> > void intel_power_sequencer_reset(struct drm_i915_private *dev_priv);
> --
> Mika Kahola - Intel OTC
>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2016-09-07 16:48 UTC|newest]
Thread overview: 81+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-01 22:08 [PATCH 00/14] Enable Upfront Link Training on DDI platforms Manasi Navare
2016-09-01 22:08 ` [PATCH v2 01/14] drm/i915: Don't pass crtc_state to intel_dp_set_link_params() Manasi Navare
2016-09-01 22:08 ` [PATCH v2 02/14] drm/i915: Remove ddi_pll_sel from intel_crtc_state Manasi Navare
2016-09-01 22:08 ` [PATCH v3 03/14] drm/i915: Split intel_ddi_pre_enable() into DP and HDMI versions Manasi Navare
2016-09-01 22:08 ` [PATCH v2 04/14] drm/i915: Split bxt_ddi_pll_select() Manasi Navare
2016-09-01 22:08 ` [PATCH 05/14] drm/i915: Split skl_get_dpll() Manasi Navare
2016-09-01 22:08 ` [PATCH 06/14] drm/i915: Split hsw_get_dpll() Manasi Navare
2016-09-01 22:08 ` [PATCH v3 07/14] drm/i915/dp: Add a standalone function to obtain shared dpll for HSW/BDW/SKL/BXT Manasi Navare
2016-09-02 20:06 ` Pandiyan, Dhinakaran
2016-09-07 22:08 ` Manasi Navare
2016-09-07 22:47 ` [PATCH v4 7/14] " Manasi Navare
2016-09-01 22:08 ` [PATCH 08/14] drm/i915/dp: Move max. vswing check to it's own function Manasi Navare
2016-09-02 8:05 ` Mika Kahola
2016-09-06 9:58 ` Mika Kahola
2016-09-06 21:25 ` Manasi Navare
2016-09-07 0:13 ` [PATCH v2 8/14] " Manasi Navare
2016-09-07 7:00 ` Mika Kahola
2016-09-07 18:28 ` [PATCH v3 " Manasi Navare
2016-09-08 7:38 ` Mika Kahola
2016-09-13 11:44 ` Jani Nikula
2016-09-01 22:08 ` [PATCH 09/14] drm/dp/i915: Make clock recovery in the link training compliant with DP Spec 1.2 Manasi Navare
2016-09-02 9:16 ` Mika Kahola
2016-09-02 17:55 ` Pandiyan, Dhinakaran
2016-09-07 0:13 ` [PATCH v2 9/14] " Manasi Navare
2016-09-07 7:33 ` Mika Kahola
2016-09-07 18:28 ` [PATCH v3 " Manasi Navare
2016-09-08 8:20 ` Mika Kahola
2016-09-01 22:08 ` [PATCH 10/14] drm/i915: Make DP link training channel equalization DP 1.2 Spec compliant Manasi Navare
2016-09-02 11:20 ` Mika Kahola
2016-09-02 19:05 ` Pandiyan, Dhinakaran
2016-09-07 7:50 ` Mika Kahola
2016-09-13 16:09 ` Rodrigo Vivi
2016-09-01 22:08 ` [PATCH 11/14] drm/i915: Fallback to lower link rate and lane count during link training Manasi Navare
2016-09-02 12:03 ` David Weinehall
2016-09-06 17:34 ` Manasi Navare
2016-09-02 12:49 ` David Weinehall
2016-09-06 17:54 ` Manasi Navare
2016-09-02 13:00 ` Mika Kahola
2016-09-06 18:01 ` Manasi Navare
2016-09-02 19:52 ` Pandiyan, Dhinakaran
2016-09-02 20:01 ` Jim Bride
2016-09-07 0:13 ` [PATCH v2 " Manasi Navare
2016-09-07 9:47 ` Mika Kahola
2016-09-07 16:47 ` Jim Bride
2016-09-07 16:48 ` Manasi Navare [this message]
2016-09-07 18:28 ` [PATCH v3 " Manasi Navare
2016-09-08 0:30 ` [PATCH v4 " Manasi Navare
2016-09-08 9:32 ` Mika Kahola
2016-09-09 1:05 ` Rodrigo Vivi
2016-09-09 7:11 ` Jani Nikula
2016-09-09 7:11 ` Jani Nikula
2016-09-09 17:13 ` Manasi Navare
2016-09-09 23:29 ` [PATCH v5 " Manasi Navare
2016-09-01 22:08 ` [PATCH 12/14] drm/i915: Reverse the loop in intel_dp_compute_config Manasi Navare
2016-09-02 13:08 ` Mika Kahola
2016-09-08 14:47 ` Manasi Navare
2016-09-02 20:24 ` Pandiyan, Dhinakaran
2016-09-08 20:02 ` [PATCH v2 12/14] drm/i915: Remove the link rate and lane count loop in compute config Manasi Navare
2016-09-13 1:14 ` Pandiyan, Dhinakaran
2016-09-14 1:05 ` Manasi Navare
2016-09-01 22:08 ` [PATCH v11 13/14] drm/i915/dp: Enable Upfront link training for typeC DP support on HSW/BDW/SKL/BXT (DDI platforms) Manasi Navare
2016-09-07 0:13 ` [PATCH v12 " Manasi Navare
2016-09-07 18:28 ` [PATCH v13 " Manasi Navare
2016-09-08 12:10 ` Mika Kahola
2016-09-08 15:06 ` Manasi Navare
2016-09-08 17:22 ` [PATCH v14 " Manasi Navare
2016-09-08 20:02 ` [PATCH v15 " Manasi Navare
2016-09-09 7:34 ` Jani Nikula
2016-09-09 23:29 ` [PATCH 13-1/14] drm/i915: Change the placement of some static functions in intel_dp.c Manasi Navare
2016-09-12 23:21 ` Rodrigo Vivi
2016-09-09 23:29 ` [PATCH v16 13-2/14] drm/i915/dp: Enable Upfront link training on HSW/BDW/SKL/BXT Manasi Navare
2016-09-13 0:22 ` Rodrigo Vivi
2016-09-09 7:31 ` [PATCH v14 13/14] drm/i915/dp: Enable Upfront link training for typeC DP support on HSW/BDW/SKL/BXT (DDI platforms) Jani Nikula
2016-09-01 22:08 ` [PATCH 14/14] drm/i915/dp/mst: Add support for upfront link training for DP MST Manasi Navare
2016-09-07 0:13 ` [PATCH v2 " Manasi Navare
2016-09-07 10:53 ` Mika Kahola
2016-09-07 16:40 ` Jim Bride
2016-09-08 10:21 ` Mika Kahola
2016-09-08 11:50 ` Mika Kahola
2016-09-01 22:48 ` ✗ Fi.CI.BAT: failure for Enable upfront link training on DDI platforms (rev3) Patchwork
2016-09-07 0:54 ` ✗ Fi.CI.BAT: warning for Enable upfront link training on DDI platforms (rev8) Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160907164825.GA29651@intel.com \
--to=manasi.d.navare@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=mika.kahola@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).