[Intel-gfx] [PATCH] drm/i915: fix pixel color depth setting on eDP

Zhenyu Wang zhenyuw at linux.intel.com
Mon Jan 11 01:33:35 CET 2010


Original DP mode_valid check didn't take pixel color depth into account,
which made one 1600x900 eDP panel's mode check invalid because of overclock,
but actually this 6bpc panel does can work with x1 lane at 2.7G. This one
trys to take bpc value properly both in mode validation and mode setting.
Currently using pipe detected bpc value, may be changed to probe eDP parameter
from VBT in future.

Also removes pipe B only for eDP which can work on any pipe.

Signed-off-by: Zhenyu Wang <zhenyuw at linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c |   18 ++++++++++-
 drivers/gpu/drm/i915/intel_dp.c      |   54 ++++++++++++++++++++++++++++-----
 drivers/gpu/drm/i915/intel_drv.h     |    2 +-
 3 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 002612f..f944f7f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2959,7 +2959,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			target_clock = mode->clock;
 			edp = intel_pipe_get_output(crtc);
 			intel_edp_link_config(to_intel_output(edp),
-					&lane, &link_bw);
+					&lane, &link_bw, &bpp);
 		} else {
 			/* DP over FDI requires target mode clock
 			   instead of link clock */
@@ -2981,6 +2981,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 				temp |= PIPE_8BPC;
 			else
 				temp |= PIPE_6BPC;
+		} else if (is_edp) {
+			bpp /= 3;
+			switch (bpp) {
+			case 8:
+				temp |= PIPE_8BPC;
+				break;
+			case 10:
+				temp |= PIPE_10BPC;
+				break;
+			case 6:
+				temp |= PIPE_6BPC;
+				break;
+			case 12:
+				temp |= PIPE_12BPC;
+				break;
+			}
 		} else
 			temp |= PIPE_8BPC;
 		I915_WRITE(pipeconf_reg, temp);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0ec07e4..c0a42e3 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -57,6 +57,7 @@ struct intel_dp_priv {
 	struct intel_output *intel_output;
 	struct i2c_adapter adapter;
 	struct i2c_algo_dp_aux_data algo;
+	int bpp;  /* eDP */
 };
 
 static void
@@ -68,7 +69,7 @@ intel_dp_link_down(struct intel_output *intel_output, uint32_t DP);
 
 void
 intel_edp_link_config (struct intel_output *intel_output,
-		int *lane_num, int *link_bw)
+		int *lane_num, int *link_bw, int *bpp)
 {
 	struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
 
@@ -77,6 +78,35 @@ intel_edp_link_config (struct intel_output *intel_output,
 		*link_bw = 162000;
 	else if (dp_priv->link_bw == DP_LINK_BW_2_7)
 		*link_bw = 270000;
+
+	*bpp = dp_priv->bpp;
+}
+
+static void
+intel_edp_detect_bpp(struct drm_i915_private *dev_priv, struct intel_dp_priv *dp_priv)
+{
+	u32 temp = I915_READ(DP_A);
+	int pipe_reg = (temp & DP_PIPEB_SELECT) ? PIPEBCONF : PIPEACONF;
+
+	temp = I915_READ(pipe_reg) & PIPE_BPC_MASK;
+
+	switch (temp & PIPE_BPC_MASK) {
+	case PIPE_8BPC:
+		dp_priv->bpp = 24;
+		break;
+	case PIPE_10BPC:
+		dp_priv->bpp = 30;
+		break;
+	case PIPE_6BPC:
+		dp_priv->bpp = 18;
+		break;
+	case PIPE_12BPC:
+		dp_priv->bpp = 36;
+		break;
+	default:
+		DRM_ERROR("unknown pipe bpc value\n");
+		dp_priv->bpp = 24;
+	}
 }
 
 static int
@@ -125,9 +155,14 @@ intel_dp_link_clock(uint8_t link_bw)
 
 /* I think this is a fiction */
 static int
-intel_dp_link_required(int pixel_clock)
+intel_dp_link_required(struct intel_output *intel_output, int pixel_clock)
 {
-	return pixel_clock * 3;
+	struct intel_dp_priv   *dp_priv = intel_output->dev_priv;
+
+	if (IS_eDP(intel_output))
+		return (pixel_clock * dp_priv->bpp) / 8;
+	else
+		return pixel_clock * 3;
 }
 
 static int
@@ -138,7 +173,7 @@ intel_dp_mode_valid(struct drm_connector *connector,
 	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output));
 	int max_lanes = intel_dp_max_lane_count(intel_output);
 
-	if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes)
+	if (intel_dp_link_required(intel_output, mode->clock) > max_link_clock * max_lanes)
 		return MODE_CLOCK_HIGH;
 
 	if (mode->clock < 10000)
@@ -492,7 +527,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		for (clock = 0; clock <= max_clock; clock++) {
 			int link_avail = intel_dp_link_clock(bws[clock]) * lane_count;
 
-			if (intel_dp_link_required(mode->clock) <= link_avail) {
+			if (intel_dp_link_required(intel_output, mode->clock) <= link_avail) {
 				dp_priv->link_bw = bws[clock];
 				dp_priv->lane_count = lane_count;
 				adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw);
@@ -1323,11 +1358,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	else if (output_reg == DP_D || output_reg == PCH_DP_D)
 		intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT);
 
-	if (IS_eDP(intel_output)) {
-		intel_output->crtc_mask = (1 << 1);
+	if (IS_eDP(intel_output))
 		intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT);
-	} else
-		intel_output->crtc_mask = (1 << 0) | (1 << 1);
+
+	intel_output->crtc_mask = (1 << 0) | (1 << 1);
 	connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
@@ -1385,6 +1419,8 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 					DRM_MODE_TYPE_PREFERRED;
 			}
 		}
+
+		intel_edp_detect_bpp(dev_priv, dp_priv);
 	}
 
 	/* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a51573d..110d033 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -175,7 +175,7 @@ extern void intel_dp_init(struct drm_device *dev, int dp_reg);
 void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode);
-extern void intel_edp_link_config (struct intel_output *, int *, int *);
+extern void intel_edp_link_config (struct intel_output *, int *, int *, int *);
 
 
 extern int intel_panel_fitter_pipe (struct drm_device *dev);
-- 
1.6.3.3




More information about the Intel-gfx mailing list