drm/i915: detect digital outputs on Haswell
authorEugeni Dodonov <eugeni.dodonov@intel.com>
Wed, 9 May 2012 18:37:27 +0000 (15:37 -0300)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Sat, 19 May 2012 20:39:50 +0000 (22:39 +0200)
Digital port detection on Haswell is indicated by the presence of a bit in
DDI_BUF_CTL for port A, and by a different register for ports B, C and D.
So we check for those bits during the initialization time and let the hdmi
function know about those.

Note that this bit does not indicates whether the output is DP or HDMI.
However, the DDI buffers can be programmed in a way that is shared between
DP/HDMI and FDI/HDMI except for PORT E.

So for now, we detect those digital outputs as being HDMI, but proper DP
support is still pending.

Note that DDI A can only drive eDP, so we do not handle it here for hdmi
initialization.

v2: simplify Haswell handling logic

v3: use generic function for handling digital outputs.

Signed-off-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h

index f44aae1247715e013ec6ee7d7df073cfc8d66f17..22bb0dd9a911e71810856e17d0546103874b5cd1 100644 (file)
@@ -220,3 +220,32 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
 
        DRM_DEBUG_KMS("FDI train done.\n");
 }
+
+/* For DDI connections, it is possible to support different outputs over the
+ * same DDI port, such as HDMI or DP or even VGA via FDI. So we don't know by
+ * the time the output is detected what exactly is on the other end of it. This
+ * function aims at providing support for this detection and proper output
+ * configuration.
+ */
+void intel_ddi_init(struct drm_device *dev, enum port port)
+{
+       /* For now, we don't do any proper output detection and assume that we
+        * handle HDMI only */
+
+       switch(port){
+       case PORT_A:
+               /* We don't handle eDP and DP yet */
+               DRM_DEBUG_DRIVER("Found digital output on DDI port A\n");
+               break;
+       /* Assume that the  ports B, C and D are working in HDMI mode for now */
+       case PORT_B:
+       case PORT_C:
+       case PORT_D:
+               intel_hdmi_init(dev, DDI_BUF_CTL(port));
+               break;
+       default:
+               DRM_DEBUG_DRIVER("No handlers defined for port %d, skipping DDI initialization\n",
+                               port);
+               break;
+       }
+}
index f1bb2e2ec1731a4773d4894d574cdc91e2c75e61..1a06f97e73f808a01fc99eb3ffcee81f2c0f9f5b 100644 (file)
@@ -6474,7 +6474,26 @@ static void intel_setup_outputs(struct drm_device *dev)
 
        intel_crt_init(dev);
 
-       if (HAS_PCH_SPLIT(dev)) {
+       if (IS_HASWELL(dev)) {
+               int found;
+
+               /* Haswell uses DDI functions to detect digital outputs */
+               found = I915_READ(DDI_BUF_CTL_A) & DDI_INIT_DISPLAY_DETECTED;
+               /* DDI A only supports eDP */
+               if (found)
+                       intel_ddi_init(dev, PORT_A);
+
+               /* DDI B, C and D detection is indicated by the SFUSE_STRAP
+                * register */
+               found = I915_READ(SFUSE_STRAP);
+
+               if (found & SFUSE_STRAP_DDIB_DETECTED)
+                       intel_ddi_init(dev, PORT_B);
+               if (found & SFUSE_STRAP_DDIC_DETECTED)
+                       intel_ddi_init(dev, PORT_C);
+               if (found & SFUSE_STRAP_DDID_DETECTED)
+                       intel_ddi_init(dev, PORT_D);
+       } else if (HAS_PCH_SPLIT(dev)) {
                int found;
 
                if (I915_READ(HDMIB) & PORT_DETECTED) {
index 0ad1bb3839769b4570812337189aabbd0e1500cc..fd96ffbf501bd508614f307ffaa6dddeb410a9af 100644 (file)
@@ -448,6 +448,7 @@ extern void intel_write_eld(struct drm_encoder *encoder,
 extern void intel_cpt_verify_modeset(struct drm_device *dev, int pipe);
 extern void intel_prepare_ddi(struct drm_device *dev);
 extern void hsw_fdi_link_train(struct drm_crtc *crtc);
+extern void intel_ddi_init(struct drm_device *dev, enum port port);
 
 /* For use by IVB LP watermark workaround in intel_sprite.c */
 extern void intel_update_watermarks(struct drm_device *dev);