[Intel-gfx] [PATCH v8 5/9] drm/i915/dp: Enable Upfront link training for typeC DP support on BXT

2016-08-09 Thread Manasi Navare
From: Durgadoss R 

To support USB type C alternate DP mode, the display driver needs to
know the number of lanes required by the DP panel as well as number
of lanes that can be supported by the type-C cable. Sometimes, the
type-C cable may limit the bandwidth even if Panel can support
more lanes. To address these scenarios, the display driver will
start link training with max lanes, and if that fails, the driver
falls back to x2 lanes; and repeats this procedure for all
bandwidth/lane configurations.

* Since link training is done before modeset only the port
  (and not pipe/planes) and its associated PLLs are enabled.
* On DP hotplug: Directly start link training on the DP encoder.
* On Connected boot scenarios: When booted with an LFP and a DP,
  sometimes BIOS brings up DP. In these cases, we disable the
  crtc and then do upfront link training; and bring it back up.
* All local changes made for upfront link training are reset
  to their previous values once it is done; so that the
  subsequent modeset is not aware of these changes.

Changes since v7:
* Move the upfront link training to intel_dp_mode_valid()
  to avoid a race condition with DP MST sideband comms. (Ville)
Changes since v6:
* Fix some initialization bugs on link_rate (Jim Bride)
* Use link_rate (and not link_bw) for upfront (Ville)
* Make intel_dp_upfront*() as a vfunc (Ander)
* The train_set_valid variable in intel_dp was removed due to
  issues in fast link training. So, to indicate the link train
  status, move the channel_eq inside intel_dp.
Changes since v5:
* Moved retry logic in upfront to intel_dp.c so that it
  can be used for all platforms.
Changes since v4:
* Removed usage of crtc_state in upfront link training;
  Hence no need to find free crtc to do upfront now.
* Re-enable crtc if it was disabled for upfront.
* Use separate variables to track max lane count
  and link rate found by upfront, without modifying
  the original DPCD read from panel.
Changes since v3:
* Fixed a return value on BXT check
* Reworked on top of bxt_ddi_pll_select split from Ander
* Renamed from ddi_upfront to bxt_upfront since the
  upfront logic includes BXT specific functions for now.
Changes since v2:
* Rebased on top of latest dpll_mgr.c code and
  latest HPD related clean ups.
* Corrected return values from upfront (Ander)
* Corrected atomic locking for upfront in intel_dp.c (Ville)
Changes since v1:
*  all pll related functions inside ddi.c

Signed-off-by: Durgadoss R 
Signed-off-by: Jim Bride 
Signed-off-by: Manasi Navare 
---
 drivers/gpu/drm/i915/intel_ddi.c  |  47 
 drivers/gpu/drm/i915/intel_dp.c   | 370 +++---
 drivers/gpu/drm/i915/intel_dp_link_training.c |   7 +-
 drivers/gpu/drm/i915/intel_drv.h  |  16 ++
 4 files changed, 337 insertions(+), 103 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index dfb3fb6..3921230 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2378,6 +2378,53 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port 
*intel_dig_port)
return connector;
 }
 
+
+bool intel_bxt_upfront_link_train(struct intel_dp *intel_dp,
+ int clock, uint8_t lane_count,
+ bool link_mst)
+{
+   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;
+   struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+   enum intel_dpll_id dpll_id = (enum intel_dpll_id)dig_port->port;
+
+   /*
+* FIXME: Works only for BXT.
+* Select the required PLL. This works for platforms where
+* there is no shared DPLL.
+*/
+   pll = _priv->shared_dplls[dpll_id];
+   if (WARN_ON(pll->active_mask)) {
+   DRM_ERROR("Shared DPLL already in use. active_mask:%x\n", 
pll->active_mask);
+   return false;
+   }
+
+   tmp_pll_config = pll->config;
+
+   if (!bxt_ddi_dp_set_dpll_hw_state(clock, >config.hw_state)) {
+   DRM_ERROR("Could not setup DPLL\n");
+   pll->config = tmp_pll_config;
+   return false;
+   }
+
+   /* Enable PLL followed by port */
+   pll->funcs.enable(dev_priv, pll);
+   intel_ddi_pre_enable_dp(encoder, clock, lane_count, pll, link_mst);
+
+   DRM_DEBUG_KMS("Upfront link train %s: link_clock:%d lanes:%d\n",
+   intel_dp->channel_eq_status ? "Passed" : "Failed", clock, lane_count);
+
+   /* Disable port followed by PLL for next retry/clean up */
+   intel_ddi_post_disable(encoder);
+   pll->funcs.disable(dev_priv, pll);
+
+   

[Intel-gfx] [PATCH v8 5/9] drm/i915/dp: Enable Upfront link training for typeC DP support on BXT

2016-08-08 Thread Manasi Navare
From: Durgadoss R 

To support USB type C alternate DP mode, the display driver needs to
know the number of lanes required by the DP panel as well as number
of lanes that can be supported by the type-C cable. Sometimes, the
type-C cable may limit the bandwidth even if Panel can support
more lanes. To address these scenarios, the display driver will
start link training with max lanes, and if that fails, the driver
falls back to x2 lanes; and repeats this procedure for all
bandwidth/lane configurations.

* Since link training is done before modeset only the port
  (and not pipe/planes) and its associated PLLs are enabled.
* On DP hotplug: Directly start link training on the DP encoder.
* On Connected boot scenarios: When booted with an LFP and a DP,
  sometimes BIOS brings up DP. In these cases, we disable the
  crtc and then do upfront link training; and bring it back up.
* All local changes made for upfront link training are reset
  to their previous values once it is done; so that the
  subsequent modeset is not aware of these changes.

Changes since v7:
* Move the upfront link training to intel_dp_mode_valid()
  to avoid a race condition with DP MST sideband comms. (Ville)
Changes since v6:
* Fix some initialization bugs on link_rate (Jim Bride)
* Use link_rate (and not link_bw) for upfront (Ville)
* Make intel_dp_upfront*() as a vfunc (Ander)
* The train_set_valid variable in intel_dp was removed due to
  issues in fast link training. So, to indicate the link train
  status, move the channel_eq inside intel_dp.
Changes since v5:
* Moved retry logic in upfront to intel_dp.c so that it
  can be used for all platforms.
Changes since v4:
* Removed usage of crtc_state in upfront link training;
  Hence no need to find free crtc to do upfront now.
* Re-enable crtc if it was disabled for upfront.
* Use separate variables to track max lane count
  and link rate found by upfront, without modifying
  the original DPCD read from panel.
Changes since v3:
* Fixed a return value on BXT check
* Reworked on top of bxt_ddi_pll_select split from Ander
* Renamed from ddi_upfront to bxt_upfront since the
  upfront logic includes BXT specific functions for now.
Changes since v2:
* Rebased on top of latest dpll_mgr.c code and
  latest HPD related clean ups.
* Corrected return values from upfront (Ander)
* Corrected atomic locking for upfront in intel_dp.c (Ville)
Changes since v1:
*  all pll related functions inside ddi.c

Signed-off-by: Durgadoss R 
Signed-off-by: Jim Bride 
Signed-off-by: Manasi Navare 
---
 drivers/gpu/drm/i915/intel_ddi.c  |  47 
 drivers/gpu/drm/i915/intel_dp.c   | 370 +++---
 drivers/gpu/drm/i915/intel_dp_link_training.c |   7 +-
 drivers/gpu/drm/i915/intel_drv.h  |  16 ++
 4 files changed, 337 insertions(+), 103 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index dfb3fb6..3921230 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2378,6 +2378,53 @@ intel_ddi_init_hdmi_connector(struct intel_digital_port 
*intel_dig_port)
return connector;
 }
 
+
+bool intel_bxt_upfront_link_train(struct intel_dp *intel_dp,
+ int clock, uint8_t lane_count,
+ bool link_mst)
+{
+   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;
+   struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+   enum intel_dpll_id dpll_id = (enum intel_dpll_id)dig_port->port;
+
+   /*
+* FIXME: Works only for BXT.
+* Select the required PLL. This works for platforms where
+* there is no shared DPLL.
+*/
+   pll = _priv->shared_dplls[dpll_id];
+   if (WARN_ON(pll->active_mask)) {
+   DRM_ERROR("Shared DPLL already in use. active_mask:%x\n", 
pll->active_mask);
+   return false;
+   }
+
+   tmp_pll_config = pll->config;
+
+   if (!bxt_ddi_dp_set_dpll_hw_state(clock, >config.hw_state)) {
+   DRM_ERROR("Could not setup DPLL\n");
+   pll->config = tmp_pll_config;
+   return false;
+   }
+
+   /* Enable PLL followed by port */
+   pll->funcs.enable(dev_priv, pll);
+   intel_ddi_pre_enable_dp(encoder, clock, lane_count, pll, link_mst);
+
+   DRM_DEBUG_KMS("Upfront link train %s: link_clock:%d lanes:%d\n",
+   intel_dp->channel_eq_status ? "Passed" : "Failed", clock, lane_count);
+
+   /* Disable port followed by PLL for next retry/clean up */
+   intel_ddi_post_disable(encoder);
+   pll->funcs.disable(dev_priv, pll);
+
+