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