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

Eugeni Dodonov
2012-06-28T18:54:47Z

From: Shobhit Kumar <shobhit.kumar@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@intel.com>
Signed-off-by: Sateesh Kavuri <sateesh.kavuri@intel.com>
Signed-off-by: Eugeni Dodonov <eugeni.dodonov@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