[PATCH 16/21] drm/i915: Modesetting for eDP on HSw

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Shobhit Kumar <shobhit.kumar at intel.com>

The MSA register and PIPE EDP register are differnet than that of DP.
Also link training flow though similar for DP had been corrected to
follow DP path

Signed-off-by: Shobhit Kumar <shobhit.kumar at intel.com>
Signed-off-by: Sateesh Kavuri <sateesh.kavuri at intel.com>
Signed-off-by: Eugeni Dodonov <eugeni.dodonov at intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_ddi.c | 70 ++++++++++++++++++++++++++++------------
 drivers/gpu/drm/i915/intel_dp.c  |  8 ++---
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 4 files changed, 55 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 1e70fae..1165d2e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4316,6 +4316,7 @@
 #define  PIPE_DDI_MODE_SELECT_DP_SST	(2<<24)
 #define  PIPE_DDI_MODE_SELECT_DP_MST	(3<<24)
 #define  PIPE_DDI_MODE_SELECT_FDI		(4<<24)
+#define  PIPE_DDI_BPC_MASK		(0x7<<20)
 #define  PIPE_DDI_BPC_8					(0<<20)
 #define  PIPE_DDI_BPC_10				(1<<20)
 #define  PIPE_DDI_BPC_6					(2<<20)
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 1c76d20..9d09f38 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -756,22 +756,16 @@ intel_ddi_mode_set_dp(struct drm_encoder *encoder,
 	int port = intel_dp->ddi_port;
 	int pipe = intel_crtc->pipe;
 	int port_width = PIPE_DDI_PORT_WIDTH_X1;
-	int temp;
+	int temp, reg;
 
 	DRM_DEBUG_KMS("Preparing DP DDI mode for Haswell on port %c, pipe %c\n",
 					port_name(port), pipe_name(pipe));
 
-	/* Turn on the eDP PLL if needed */
-	/* TBD: */
-
 	/*
 	 * There are two kinds of DP registers in HSW:
 	 * DDI CPU
 	 * LPT PCH
 	 */
-	/* Preserve the BIOS-computed detected bit. This is
-	 * supposed to be read-only.
-	 */
 	intel_dp->DP = I915_READ(DDI_BUF_CTL(intel_dp->ddi_port));
 	intel_dp->DP |= DDI_BUF_EMP_400MV_0DB_HSW;
 	intel_dp->TP = I915_READ(DP_TP_CTL(intel_dp->ddi_port));
@@ -794,6 +788,10 @@ intel_ddi_mode_set_dp(struct drm_encoder *encoder,
 		BUG();
 	}
 
+	/* Assuming all 4 lanes available to DDI A for eDP */
+	if (is_edp(intel_dp))
+		intel_dp->DP |= DDI_PORT_LANE_CAP_DDIA_4;
+
 	if (intel_dp->has_audio)
 		DRM_DEBUG_DRIVER("HSW DP Audio not yet supported\n");
 
@@ -830,14 +828,24 @@ intel_ddi_mode_set_dp(struct drm_encoder *encoder,
 
 		/* Set the MSA bits, since from HSW onwards,
 		 * this has to be explictly set */
-		temp = I915_READ(HSW_MSA_CTL);
+		if (is_edp(intel_dp))
+			temp = I915_READ(HSW_MSA_EDP_CTL);
+		else
+			temp = I915_READ(HSW_MSA_CTL);
+
 		temp |= HSW_MSA_SYNC_CLK;
 		temp &= ~HSW_MSA_DYNAMIC_RANGE;
 		temp &= ~HSW_MSA_COLORIMETRY;
 		temp &= ~HSW_MSA_BPC_MASK;
-		temp |= HSW_MSA_BPC_8_BITS; /* Color depth */
 
-		I915_WRITE(HSW_MSA_CTL, temp);
+		if (is_edp(intel_dp)) {
+			temp |= HSW_MSA_BPC_6_BITS; /* Color depth */
+			I915_WRITE(HSW_MSA_EDP_CTL, temp);
+		}
+		else {
+			temp |= HSW_MSA_BPC_8_BITS; /* Color depth */
+			I915_WRITE(HSW_MSA_CTL, temp);
+		}
 
 		if ((intel_dp->dpcd[DP_MAX_DOWNSPREAD] & 0x1) == 0x1) {
 			/* SSC Enabled Panel */
@@ -854,8 +862,9 @@ intel_ddi_mode_set_dp(struct drm_encoder *encoder,
 			 */
 			I915_WRITE(PORT_CLK_SEL(port),
 					PORT_CLK_SEL_SPLL);
-			I915_WRITE(PIPE_CLK_SEL(pipe),
-					PIPE_CLK_SEL_PORT(port));
+			if (!is_edp(intel_dp))
+				I915_WRITE(PIPE_CLK_SEL(pipe),
+						PIPE_CLK_SEL_PORT(port));
 		} else {
 			/* Non SSC Panel */
 			/* configure LCPLL for NON-SSC */
@@ -864,30 +873,49 @@ intel_ddi_mode_set_dp(struct drm_encoder *encoder,
 				LCPLL_PLL_REFERENCE_NON_SSC;
 			I915_WRITE(LCPLL_CTL, temp);
 			udelay(20);
-
 			/* Use LCPLL clock to drive the output to the dp port,
 			 * and tell the pipe to use this port for connection.
 			 */
 			I915_WRITE(PORT_CLK_SEL(port),
 					PORT_CLK_SEL_LCPLL_1350);
-			I915_WRITE(PIPE_CLK_SEL(pipe),
-					PIPE_CLK_SEL_PORT(port));
+			if (!is_edp(intel_dp))
+				I915_WRITE(PIPE_CLK_SEL(pipe),
+						PIPE_CLK_SEL_PORT(port));
 		}
 
 		/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in DP mode */
-		temp = I915_READ(DDI_FUNC_CTL(pipe));
+		if(is_edp(intel_dp)) {
+			reg = PIPE_DDI_FUNC_CTL_EDP;
+			temp = I915_READ(reg);
+			temp &= ~PIPE_DDI_EDP_INPUT_SRC_MASK ;
+
+			/* Use On/Off for now to address all cases; later we
+			 * need to also add support for always on without panel
+			 * fitter in case of native mode to save power
+			 */
+			temp &= ~PIPE_DDI_BPC_MASK;
+			temp |= PIPE_DDI_EDI_INPUT_SRC_A_ON_OFF;
+			temp |= ((intel_crtc->bpp > 24) ?
+				PIPE_DDI_BPC_12 :
+				PIPE_DDI_BPC_6);
+		}
+		else {
+			reg = DDI_FUNC_CTL(pipe);
+			temp = I915_READ(reg);
+			temp &= ~PIPE_DDI_BPC_MASK;
+			temp |= ((intel_crtc->bpp > 24) ?
+				PIPE_DDI_BPC_12 :
+				PIPE_DDI_BPC_8);
+		}
+
 		temp &= ~PIPE_DDI_PORT_MASK;
-		temp &= ~PIPE_DDI_BPC_12;
 		temp &= ~PIPE_DDI_PORT_WIDTH_MASK;
 		temp |= PIPE_DDI_SELECT_PORT(port) |
 			PIPE_DDI_MODE_SELECT_DP_SST |
 			port_width |
-			((intel_crtc->bpp > 24) ?
-			 PIPE_DDI_BPC_12 :
-			 PIPE_DDI_BPC_8) |
 			PIPE_DDI_FUNC_ENABLE;
 
-		I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+		I915_WRITE(reg, temp);
 	}
 }
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 38a1d3b..f086944 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -45,7 +45,7 @@
  * If a CPU or PCH DP output is attached to an eDP panel, this function
  * will return true, and false otherwise.
  */
-static bool is_edp(struct intel_dp *intel_dp)
+bool is_edp(struct intel_dp *intel_dp)
 {
 	return intel_dp->base.type == INTEL_OUTPUT_EDP;
 }
@@ -363,7 +363,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	 * clock divider.
 	 */
 	if (is_cpu_edp(intel_dp)) {
-		if (IS_GEN6(dev) || IS_GEN7(dev))
+		if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_HASWELL(dev))
 			aux_clock_divider = 200; /* SNB & IVB eDP input clock at 400Mhz */
 		else
 			aux_clock_divider = 225; /* eDP input clock at 450Mhz */
@@ -1753,7 +1753,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
 		uint32_t    signal_levels;
 
 
-		if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+		if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_HASWELL(dev)) {
 			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
 		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
@@ -1855,7 +1855,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
 			break;
 		}
 
-		if (IS_GEN7(dev) && is_cpu_edp(intel_dp)) {
+		if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_HASWELL(dev)) {
 			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]);
 			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels;
 		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5ca133d..a741a02 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -392,6 +392,7 @@ extern void intel_mark_busy(struct drm_device *dev,
 extern bool intel_lvds_init(struct drm_device *dev);
 extern void intel_dp_init(struct drm_device *dev, int dp_reg);
 extern struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder);
+extern bool is_edp(struct intel_dp *intel_dp);
 
 void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
-- 
1.7.11.1



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux