diff mbox

[RFCv2,DP-typeC,6/6] drm/i915/dp: Enable Upfront link training for typeC DP support on CHV

Message ID 1444824013-23147-7-git-send-email-durgadoss.r@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

durgadoss.r@intel.com Oct. 14, 2015, noon UTC
To support USB type C alternate DP mode, the display driver needs to know the
number of lanes required by 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 the link
training fails, the driver then falls back to x2 lanes.

* Since link training is done before modeset, planes are not enabled. Only
  encoder and the its associated PLLs are enabled.
* Once link training is done, the encoder and its PLLs are disabled; so that
  the subsequent modeset is not aware of these changes.
* As of now, this is tested only on CHV.

Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 135 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_dp.c      |   2 +
 drivers/gpu/drm/i915/intel_drv.h     |   2 +
 3 files changed, 139 insertions(+)

Comments

kernel test robot Oct. 14, 2015, 1:41 p.m. UTC | #1
Hi Durgadoss,

[auto build test WARNING on drm-intel/for-linux-next -- if it's inappropriate base, please suggest rules for selecting the more suitable base]

url:    https://github.com/0day-ci/linux/commits/Durgadoss-R/Add-support-for-USB-typeC-based-DP/20151014-193613
config: x86_64-randconfig-s5-10142016 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   drivers/gpu/drm/i915/intel_display.c: In function 'chv_upfront_link_train':
   drivers/gpu/drm/i915/intel_display.c:15741:27: error: 'struct intel_connector' has no member named 'new_encoder'
       tmp_encoder = connector->new_encoder;
                              ^
   drivers/gpu/drm/i915/intel_display.c:15742:22: error: 'struct intel_encoder' has no member named 'new_crtc'
       tmp_crtc = encoder->new_crtc;
                         ^
   drivers/gpu/drm/i915/intel_display.c:15745:13: error: 'struct intel_connector' has no member named 'new_encoder'
       connector->new_encoder = encoder;
                ^
   drivers/gpu/drm/i915/intel_display.c:15746:11: error: 'struct intel_encoder' has no member named 'new_crtc'
       encoder->new_crtc = crtc;
              ^
   drivers/gpu/drm/i915/intel_display.c:15767:24: error: 'struct intel_dp' has no member named 'link_bw'
     tmp_link_bw = intel_dp->link_bw;
                           ^
   drivers/gpu/drm/i915/intel_display.c:15770:10: error: 'struct intel_dp' has no member named 'link_bw'
     intel_dp->link_bw =  intel_dp->dpcd[DP_MAX_LINK_RATE];
             ^
   In file included from include/uapi/linux/stddef.h:1:0,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from include/linux/list.h:4,
                    from include/linux/dmi.h:4,
                    from drivers/gpu/drm/i915/intel_display.c:27:
   drivers/gpu/drm/i915/intel_display.c:15775:14: error: 'struct intel_dp' has no member named 'link_bw'
     if (intel_dp->link_bw == DP_LINK_BW_5_4)
                 ^
   include/linux/compiler.h:147:28: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                               ^
>> drivers/gpu/drm/i915/intel_display.c:15775:2: note: in expansion of macro 'if'
     if (intel_dp->link_bw == DP_LINK_BW_5_4)
     ^
   drivers/gpu/drm/i915/intel_display.c:15775:14: error: 'struct intel_dp' has no member named 'link_bw'
     if (intel_dp->link_bw == DP_LINK_BW_5_4)
                 ^
   include/linux/compiler.h:147:40: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                                           ^
>> drivers/gpu/drm/i915/intel_display.c:15775:2: note: in expansion of macro 'if'
     if (intel_dp->link_bw == DP_LINK_BW_5_4)
     ^
   drivers/gpu/drm/i915/intel_display.c:15775:14: error: 'struct intel_dp' has no member named 'link_bw'
     if (intel_dp->link_bw == DP_LINK_BW_5_4)
                 ^
   include/linux/compiler.h:158:16: note: in definition of macro '__trace_if'
      ______r = !!(cond);     \
                   ^
>> drivers/gpu/drm/i915/intel_display.c:15775:2: note: in expansion of macro 'if'
     if (intel_dp->link_bw == DP_LINK_BW_5_4)
     ^
   drivers/gpu/drm/i915/intel_display.c:15776:11: error: 'struct intel_dp' has no member named 'link_bw'
      intel_dp->link_bw = DP_LINK_BW_2_7;
              ^
   drivers/gpu/drm/i915/intel_display.c:15780:15: error: request for member 'port_clock' in something not a structure or union
      crtc->config.port_clock =
                  ^
   drivers/gpu/drm/i915/intel_display.c:15781:41: error: 'struct intel_dp' has no member named 'link_bw'
        drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
                                            ^
   drivers/gpu/drm/i915/intel_display.c:15784:3: error: implicit declaration of function 'intel_dp_set_clock' [-Werror=implicit-function-declaration]
      intel_dp_set_clock(encoder, &crtc->config, intel_dp->link_bw);
      ^
   drivers/gpu/drm/i915/intel_display.c:15784:54: error: 'struct intel_dp' has no member named 'link_bw'
      intel_dp_set_clock(encoder, &crtc->config, intel_dp->link_bw);
                                                         ^
   drivers/gpu/drm/i915/intel_display.c:15785:3: error: implicit declaration of function 'chv_update_pll' [-Werror=implicit-function-declaration]
      chv_update_pll(crtc);
      ^
   drivers/gpu/drm/i915/intel_display.c:15787:3: error: too few arguments to function 'chv_enable_pll'
      chv_enable_pll(crtc);
      ^
   drivers/gpu/drm/i915/intel_display.c:1636:13: note: declared here
    static void chv_enable_pll(struct intel_crtc *crtc,
                ^
   In file included from include/uapi/linux/stddef.h:1:0,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from include/linux/list.h:4,
                    from include/linux/dmi.h:4,
                    from drivers/gpu/drm/i915/intel_display.c:27:
   drivers/gpu/drm/i915/intel_display.c:15792:15: error: 'struct intel_dp' has no member named 'has_fast_link_train'
      if (intel_dp->has_fast_link_train) {
                  ^
   include/linux/compiler.h:147:28: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                               ^
   drivers/gpu/drm/i915/intel_display.c:15792:3: note: in expansion of macro 'if'
      if (intel_dp->has_fast_link_train) {
      ^
   drivers/gpu/drm/i915/intel_display.c:15792:15: error: 'struct intel_dp' has no member named 'has_fast_link_train'
      if (intel_dp->has_fast_link_train) {
                  ^
   include/linux/compiler.h:147:40: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                                           ^
   drivers/gpu/drm/i915/intel_display.c:15792:3: note: in expansion of macro 'if'
      if (intel_dp->has_fast_link_train) {
      ^
   drivers/gpu/drm/i915/intel_display.c:15792:15: error: 'struct intel_dp' has no member named 'has_fast_link_train'
      if (intel_dp->has_fast_link_train) {
                  ^
   include/linux/compiler.h:158:16: note: in definition of macro '__trace_if'
      ______r = !!(cond);     \
                   ^
   drivers/gpu/drm/i915/intel_display.c:15792:3: note: in expansion of macro 'if'
      if (intel_dp->has_fast_link_train) {
      ^
   In file included from drivers/gpu/drm/i915/intel_display.c:35:0:
   drivers/gpu/drm/i915/intel_display.c:15810:35: error: 'struct intel_dp' has no member named 'link_bw'
        intel_dp->lane_count, intel_dp->link_bw);
                                      ^
   include/drm/drmP.h:208:41: note: in definition of macro 'DRM_DEBUG_KMS'
       drm_ut_debug_printk(__func__, fmt, ##args); \
                                            ^
   In file included from include/uapi/linux/stddef.h:1:0,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from include/linux/list.h:4,
                    from include/linux/dmi.h:4,
                    from drivers/gpu/drm/i915/intel_display.c:27:
   drivers/gpu/drm/i915/intel_display.c:15817:22: error: 'struct intel_dp' has no member named 'link_bw'
      } else if (intel_dp->link_bw == DP_LINK_BW_2_7) {
                         ^
   include/linux/compiler.h:147:28: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                               ^
   drivers/gpu/drm/i915/intel_display.c:15817:10: note: in expansion of macro 'if'
      } else if (intel_dp->link_bw == DP_LINK_BW_2_7) {
             ^
   drivers/gpu/drm/i915/intel_display.c:15817:22: error: 'struct intel_dp' has no member named 'link_bw'
      } else if (intel_dp->link_bw == DP_LINK_BW_2_7) {
                         ^
   include/linux/compiler.h:147:40: note: in definition of macro '__trace_if'
     if (__builtin_constant_p((cond)) ? !!(cond) :   \
                                           ^
   drivers/gpu/drm/i915/intel_display.c:15817:10: note: in expansion of macro 'if'
      } else if (intel_dp->link_bw == DP_LINK_BW_2_7) {
             ^
   drivers/gpu/drm/i915/intel_display.c:15817:22: error: 'struct intel_dp' has no member named 'link_bw'
      } else if (intel_dp->link_bw == DP_LINK_BW_2_7) {
                         ^
   include/linux/compiler.h:158:16: note: in definition of macro '__trace_if'
      ______r = !!(cond);     \
                   ^

vim +/if +15775 drivers/gpu/drm/i915/intel_display.c

 15759	start_link_train:
 15760	
 15761		DRM_DEBUG_KMS("upfront link training on pipe:%c\n",
 15762						pipe_name(crtc->pipe));
 15763		found = false;
 15764	
 15765		/* Save the existing lane_count and link_bw values */
 15766		tmp_lane_count = intel_dp->lane_count;
 15767		tmp_link_bw = intel_dp->link_bw;
 15768	
 15769		/* Initialize with Max Link rate & lane count supported by panel */
 15770		intel_dp->link_bw =  intel_dp->dpcd[DP_MAX_LINK_RATE];
 15771		intel_dp->lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] &
 15772						DP_MAX_LANE_COUNT_MASK;
 15773	
 15774		/* CHV does not support HBR2 */
 15775		if (intel_dp->link_bw == DP_LINK_BW_5_4)
 15776			intel_dp->link_bw = DP_LINK_BW_2_7;
 15777	
 15778		do {
 15779			/* Find port clock from link_bw */
 15780			crtc->config.port_clock =
 15781					drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
 15782	
 15783			/* Enable PLL followed by port */

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a2ec8cb..17b3c7a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -15751,3 +15751,138 @@  void intel_modeset_preclose(struct drm_device *dev, struct drm_file *file)
 		spin_unlock_irq(&dev->event_lock);
 	}
 }
+
+bool chv_upfront_link_train(struct drm_device *dev,
+		struct intel_dp *intel_dp, struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_connector *connector = intel_dp->attached_connector;
+	struct intel_encoder *tmp_encoder, *encoder = connector->encoder;
+	struct intel_crtc *tmp_crtc;
+	struct drm_crtc *tmp_drm_crtc;
+	bool found = false, valid_crtc = false;
+	uint8_t tmp_lane_count, tmp_link_bw;
+
+	if (!connector || !encoder) {
+		DRM_DEBUG_KMS("dp connector/encoder is NULL\n");
+		return false;
+	}
+
+	/* If we already have a crtc, start link training directly */
+	if (crtc) {
+		valid_crtc = true;
+		goto start_link_train;
+	}
+
+	/* Find an unused crtc and use it for link training */
+	for_each_intel_crtc(dev, crtc) {
+		if (intel_crtc_active(&crtc->base))
+			continue;
+
+		/* Make sure the new crtc will work with the encoder */
+		if (drm_encoder_crtc_ok(&encoder->base, &crtc->base)) {
+			/* Save the existing values */
+			tmp_encoder = connector->new_encoder;
+			tmp_crtc = encoder->new_crtc;
+			tmp_drm_crtc = encoder->base.crtc;
+
+			connector->new_encoder = encoder;
+			encoder->new_crtc = crtc;
+			encoder->base.crtc = &crtc->base;
+
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		DRM_ERROR("Could not find crtc for upfront link training\n");
+		return false;
+	}
+
+start_link_train:
+
+	DRM_DEBUG_KMS("upfront link training on pipe:%c\n",
+					pipe_name(crtc->pipe));
+	found = false;
+
+	/* Save the existing lane_count and link_bw values */
+	tmp_lane_count = intel_dp->lane_count;
+	tmp_link_bw = intel_dp->link_bw;
+
+	/* Initialize with Max Link rate & lane count supported by panel */
+	intel_dp->link_bw =  intel_dp->dpcd[DP_MAX_LINK_RATE];
+	intel_dp->lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] &
+					DP_MAX_LANE_COUNT_MASK;
+
+	/* CHV does not support HBR2 */
+	if (intel_dp->link_bw == DP_LINK_BW_5_4)
+		intel_dp->link_bw = DP_LINK_BW_2_7;
+
+	do {
+		/* Find port clock from link_bw */
+		crtc->config.port_clock =
+				drm_dp_bw_code_to_link_rate(intel_dp->link_bw);
+
+		/* Enable PLL followed by port */
+		intel_dp_set_clock(encoder, &crtc->config, intel_dp->link_bw);
+		chv_update_pll(crtc);
+		encoder->pre_pll_enable(encoder);
+		chv_enable_pll(crtc);
+		encoder->pre_enable(encoder);
+
+		/* Check if link training passed; if so update lane count */
+		/* TODO: Newer code has this variable as 'train_set_valid */
+		if (intel_dp->has_fast_link_train) {
+			intel_dp->dpcd[DP_MAX_LANE_COUNT] &=
+						~DP_MAX_LANE_COUNT_MASK;
+			intel_dp->dpcd[DP_MAX_LANE_COUNT] |=
+				intel_dp->lane_count & DP_MAX_LANE_COUNT_MASK;
+
+			found = true;
+		}
+
+		/* Reset encoder for next retry or for clean up */
+		encoder->disable(encoder);
+		encoder->post_disable(encoder);
+		chv_disable_pll(dev_priv, crtc->pipe);
+
+		if (found)
+			goto exit;
+
+		DRM_DEBUG_KMS("upfront link training failed. lanes:%d bw:%d\n",
+				intel_dp->lane_count, intel_dp->link_bw);
+
+		/* Go down to the next level and retry link training */
+		if (intel_dp->lane_count == 4) {
+			intel_dp->lane_count = 2;
+		} else if (intel_dp->lane_count == 2) {
+			intel_dp->lane_count = 1;
+		} else if (intel_dp->link_bw == DP_LINK_BW_2_7) {
+			intel_dp->link_bw = DP_LINK_BW_1_62;
+			intel_dp->lane_count = 4;
+		} else {
+			/* Tried all combinations, so exit */
+			break;
+		}
+
+	} while (1);
+
+exit:
+	/* Clear local associations made */
+	if (!valid_crtc) {
+		connector->new_encoder = tmp_encoder;
+		encoder->new_crtc = tmp_crtc;
+		encoder->base.crtc = tmp_drm_crtc;
+	}
+
+	if (found)
+		DRM_DEBUG_KMS("upfront link training passed. lanes:%d bw:%d\n",
+				intel_dp->lane_count, intel_dp->link_bw);
+
+	/* Restore lane_count and link_bw values */
+	intel_dp->lane_count = tmp_lane_count;
+	intel_dp->link_bw = tmp_link_bw;
+
+	return found;
+}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 8376b47..0254395 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4808,6 +4808,8 @@  static bool intel_dp_upfront_link_train(struct intel_dp *intel_dp)
 
 	if (HAS_DDI(dev))
 		return intel_ddi_upfront_link_train(dev, intel_dp, intel_crtc);
+	else if (IS_CHERRYVIEW(dev))
+		return intel_chv_upfront_link_train(dev, intel_dp, intel_crtc);
 
 	/* Not a supported platform. Assume we don't need upfront_train */
 	return true;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 82af4e6..c214797 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1166,6 +1166,8 @@  void skl_uninit_cdclk(struct drm_i915_private *dev_priv);
 void intel_dp_get_m_n(struct intel_crtc *crtc,
 		      struct intel_crtc_state *pipe_config);
 void intel_dp_set_m_n(struct intel_crtc *crtc, enum link_m_n_set m_n);
+bool intel_chv_upfront_link_train(struct drm_device *dev,
+		struct intel_dp *intel_dp, struct intel_crtc *crtc);
 int intel_dotclock_calculate(int link_freq, const struct intel_link_m_n *m_n);
 void
 ironlake_check_encoder_dotclock(const struct intel_crtc_state *pipe_config,