diff mbox

drm/i915: fix pixel color depth setting on eDP

Message ID 1263170015-1566-1-git-send-email-zhenyuw@linux.intel.com (mailing list archive)
State Rejected
Headers show

Commit Message

Zhenyu Wang Jan. 11, 2010, 12:33 a.m. UTC
None
diff mbox

Patch

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);