diff mbox

[RFC,07/30] drm/i915: make intel_ddi_enable_pipe work on DP

Message ID 1346191621-12996-8-git-send-email-przanoni@gmail.com (mailing list archive)
State RFC
Headers show

Commit Message

Paulo Zanoni Aug. 28, 2012, 10:06 p.m. UTC
From: Paulo Zanoni <paulo.r.zanoni@intel.com>

Not just HDMI/DVI.

Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h  | 10 +++++
 drivers/gpu/drm/i915/intel_ddi.c | 95 +++++++++++++++++++++++++++-------------
 drivers/gpu/drm/i915/intel_dp.c  |  5 ---
 drivers/gpu/drm/i915/intel_drv.h |  4 ++
 4 files changed, 79 insertions(+), 35 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index ee70588..9d34a2e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4514,6 +4514,16 @@ 
 #define  PIPE_CLK_SEL_DISABLED		(0x0<<29)
 #define  PIPE_CLK_SEL_PORT(x)		((x+1)<<29)
 
+#define _PIPEA_MSA_MISC			0x60410
+#define _PIPEB_MSA_MISC			0x61410
+#define PIPE_MSA_MISC(pipe) _PIPE(pipe, _PIPEA_MSA_MISC, _PIPEB_MSA_MISC)
+#define  PIPE_MSA_SYNC_CLK		(1<<0)
+#define  PIPE_MSA_6_BPC			(0<<5)
+#define  PIPE_MSA_8_BPC			(1<<5)
+#define  PIPE_MSA_10_BPC		(2<<5)
+#define  PIPE_MSA_12_BPC		(3<<5)
+#define  PIPE_MSA_16_BPC		(3<<5)
+
 /* LCPLL Control */
 #define LCPLL_CTL			0x130040
 #define  LCPLL_PLL_DISABLE		(1<<31)
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 0c83ffa..208f13f 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -762,65 +762,100 @@  static void intel_ddi_enable_pipe(struct intel_encoder *intel_encoder,
 				  struct drm_display_mode *adjusted_mode)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
-	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int port = intel_hdmi->ddi_port;
+	int port;
 	int pipe = intel_crtc->pipe;
-	u32 temp;
+	u32 func_val, msa_val;
+	struct intel_hdmi *intel_hdmi = NULL;
+	struct intel_dp *intel_dp = NULL;
+
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+		intel_hdmi = enc_to_intel_hdmi(encoder);
+		port = intel_hdmi->ddi_port;
+	} else {
+		intel_dp = enc_to_intel_dp(encoder);
+		port = intel_dp->port;
+	}
 
 	I915_WRITE(PIPE_CLK_SEL(pipe), PIPE_CLK_SEL_PORT(port));
 
 	udelay(20);
 
-	if (intel_hdmi->has_audio) {
-		/* Proper support for digital audio needs a new logic and a new set
-		 * of registers, so we leave it for future patch bombing.
-		 */
-		DRM_DEBUG_DRIVER("HDMI audio on pipe %c on DDI\n",
-				 pipe_name(intel_crtc->pipe));
-
-		/* write eld */
-		DRM_DEBUG_DRIVER("HDMI audio: write eld information\n");
-		intel_write_eld(encoder, adjusted_mode);
-	}
-
-	/* Enable PIPE_DDI_FUNC_CTL for the pipe to work in HDMI mode */
-	temp = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
+	func_val = PIPE_DDI_FUNC_ENABLE | PIPE_DDI_SELECT_PORT(port);
+	msa_val = PIPE_MSA_SYNC_CLK;
 
 	switch (intel_crtc->bpp) {
 	case 18:
-		temp |= PIPE_DDI_BPC_6;
+		func_val |= PIPE_DDI_BPC_6;
+		msa_val |= PIPE_MSA_6_BPC;
 		break;
 	case 24:
-		temp |= PIPE_DDI_BPC_8;
+		func_val |= PIPE_DDI_BPC_8;
+		msa_val |= PIPE_MSA_8_BPC;
 		break;
 	case 30:
-		temp |= PIPE_DDI_BPC_10;
+		func_val |= PIPE_DDI_BPC_10;
+		msa_val |= PIPE_MSA_10_BPC;
 		break;
 	case 36:
-		temp |= PIPE_DDI_BPC_12;
+		func_val |= PIPE_DDI_BPC_12;
+		msa_val |= PIPE_MSA_12_BPC;
 		break;
 	default:
 		WARN(1, "%d bpp unsupported by pipe DDI function\n",
 		     intel_crtc->bpp);
 	}
 
-	if (intel_hdmi->has_hdmi_sink)
-		temp |= PIPE_DDI_MODE_SELECT_HDMI;
-	else
-		temp |= PIPE_DDI_MODE_SELECT_DVI;
-
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-		temp |= PIPE_DDI_PVSYNC;
+		func_val |= PIPE_DDI_PVSYNC;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-		temp |= PIPE_DDI_PHSYNC;
+		func_val |= PIPE_DDI_PHSYNC;
 
-	I915_WRITE(DDI_FUNC_CTL(pipe), temp);
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+		if (intel_hdmi->has_hdmi_sink)
+			func_val |= PIPE_DDI_MODE_SELECT_HDMI;
+		else
+			func_val |= PIPE_DDI_MODE_SELECT_DVI;
+	} else {
+		func_val |= PIPE_DDI_MODE_SELECT_DP_SST;
 
-	intel_hdmi->set_infoframes(encoder, adjusted_mode);
+		switch (intel_dp->lane_count) {
+		case 1:
+			func_val |= PIPE_DDI_PORT_WIDTH_X1;
+			break;
+		case 2:
+			func_val |= PIPE_DDI_PORT_WIDTH_X2;
+			break;
+		case 4:
+			func_val |= PIPE_DDI_PORT_WIDTH_X4;
+			break;
+		default:
+			WARN(1, "Unsupported lane count %d\n",
+			     intel_dp->lane_count);
+		}
+
+		I915_WRITE(PIPE_MSA_MISC(pipe), msa_val);
+	}
+
+	I915_WRITE(DDI_FUNC_CTL(pipe), func_val);
+
+	if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
+		if (intel_hdmi->has_audio) {
+			DRM_DEBUG_KMS("HDMI audio on pipe %c on DDI\n",
+				      pipe_name(intel_crtc->pipe));
+
+			DRM_DEBUG_KMS("HDMI audio: write eld information\n");
+			intel_write_eld(encoder, adjusted_mode);
+		}
+
+		intel_hdmi->set_infoframes(encoder, adjusted_mode);
+	} else {
+		if (intel_dp->has_audio)
+			DRM_DEBUG_KMS("DP audio not supported yet\n");
+	}
 }
 
 void intel_ddi_mode_set(struct drm_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 977d9d2..31d6e78 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -76,11 +76,6 @@  static bool is_cpu_edp(struct intel_dp *intel_dp)
 	return is_edp(intel_dp) && !is_pch_edp(intel_dp);
 }
 
-static struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
-{
-	return container_of(encoder, struct intel_dp, base.base);
-}
-
 static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
 {
 	return container_of(intel_attached_encoder(connector),
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index aa62439..52c7547 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -420,6 +420,10 @@  static inline struct intel_encoder *intel_attached_encoder(struct drm_connector
 {
 	return to_intel_connector(connector)->encoder;
 }
+static inline struct intel_dp *enc_to_intel_dp(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct intel_dp, base.base);
+}
 
 extern void intel_connector_attach_encoder(struct intel_connector *connector,
 					   struct intel_encoder *encoder);