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