xf86-video-intel: 11 commits - src/common.h src/i810_reg.h src/i830_debug.c src/i830_display.c src/i830_driver.c src/i830.h src/i830_hdmi.c src/i830_sdvo.c src/i830_sdvo.h src/Makefile.am src/reg_dumper/.gitignore src/reg_dumper/hotplug.c src/reg_dumper/Makefile.am

Eric Anholt anholt at kemper.freedesktop.org
Fri Jun 20 00:03:16 PDT 2008


 src/Makefile.am            |    1 
 src/common.h               |    1 
 src/i810_reg.h             |   37 ++++++-
 src/i830.h                 |    4 
 src/i830_debug.c           |   31 +++++
 src/i830_display.c         |    3 
 src/i830_driver.c          |   15 ++
 src/i830_hdmi.c            |  233 +++++++++++++++++++++++++++++++++++++++++++++
 src/i830_sdvo.c            |   24 ++--
 src/i830_sdvo.h            |    2 
 src/reg_dumper/.gitignore  |    1 
 src/reg_dumper/Makefile.am |    9 +
 src/reg_dumper/hotplug.c   |  151 +++++++++++++++++++++++++++++
 13 files changed, 495 insertions(+), 17 deletions(-)

New commits:
commit 6b6be2b2a7179c1c9fa12989e16076aae105f4e2
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jun 19 15:01:00 2008 -0700

    Fix a crash in i830_sdvo_init error paths by setting up dev_priv earlier.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 8914e1b..cdfc9c6 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1527,10 +1527,12 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 	return FALSE;
     }
     output->driver_private = intel_output;
+    dev_priv = (struct i830_sdvo_priv *) (intel_output + 1);
+    intel_output->dev_priv = dev_priv;
+
     output->interlaceAllowed = FALSE;
     output->doubleScanAllowed = FALSE;
     
-    dev_priv = (struct i830_sdvo_priv *) (intel_output + 1);
     intel_output->type = I830_OUTPUT_SDVO;
     intel_output->pipe_mask = ((1 << 0) | (1 << 1));
     intel_output->clone_mask = (1 << I830_OUTPUT_SDVO);
@@ -1572,7 +1574,6 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
     }
 
     intel_output->pI2CBus = i2cbus;
-    intel_output->dev_priv = dev_priv;
 
     /* Read the regs to test if we can talk to the device */
     for (i = 0; i < 0x40; i++) {
commit 65ad29d78793c7804f133a58de80ffaa0404ca28
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jun 19 14:27:30 2008 -0700

    Automatically detect the presence of HDMI.
    
    Now, SDVO is only probed if the SDVO detected bit is set.  If the SDVO probe
    fails, but the detect bit is set, assume that it's an HDMI output.

diff --git a/src/common.h b/src/common.h
index 5efdc0c..1765bb5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -372,6 +372,7 @@ extern int I810_DEBUG;
 #define HWS_NEED_GFX(pI810) (IS_G33CLASS(pI810) || IS_IGD_GM(pI810) || IS_G4X(pI810))
 /* chipsets require status page in non stolen memory */
 #define HWS_NEED_NONSTOLEN(pI810) (IS_IGD_GM(pI810) || IS_G4X(pI810))
+#define SUPPORTS_INTEGRATED_HDMI(pI810) (IS_IGD_GM(pI810) || IS_G4X(pI810))
 
 #define GTT_PAGE_SIZE			KB(4)
 #define ROUND_TO(x, y)			(((x) + (y) - 1) / (y) * (y))
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 5782d48..28505c8 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -924,13 +924,19 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       i830_lvds_init(pScrn);
 
    if (IS_I9XX(pI830)) {
-#if 1
-      i830_sdvo_init(pScrn, SDVOB);
-      i830_sdvo_init(pScrn, SDVOC);
-#else
-      i830_hdmi_init(pScrn, SDVOB);
-      i830_hdmi_init(pScrn, SDVOC);
-#endif
+      if (INREG(SDVOB) & SDVO_DETECTED) {
+	 Bool found = i830_sdvo_init(pScrn, SDVOB);
+
+	 if (!found && SUPPORTS_INTEGRATED_HDMI(pI830))
+	    i830_hdmi_init(pScrn, SDVOB);
+      }
+
+      if (INREG(SDVOB) & SDVO_DETECTED) {
+	 Bool found = i830_sdvo_init(pScrn, SDVOC);
+
+	 if (!found && SUPPORTS_INTEGRATED_HDMI(pI830))
+	    i830_hdmi_init(pScrn, SDVOC);
+      }
    } else {
       i830_dvo_init(pScrn);
    }
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 331059b..8914e1b 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1503,7 +1503,7 @@ i830_sdvo_select_ddc_bus(struct i830_sdvo_priv *dev_priv)
     dev_priv->ddc_bus = 1 << num_bits;
 }
 
-void
+Bool
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 {
     xf86OutputPtr	    output;
@@ -1518,13 +1518,13 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 
     output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,NULL);
     if (!output)
-	return;
+	return FALSE;
     intel_output = xnfcalloc (sizeof (I830OutputPrivateRec) +
 			      sizeof (struct i830_sdvo_priv), 1);
     if (!intel_output)
     {
 	xf86OutputDestroy (output);
-	return;
+	return FALSE;
     }
     output->driver_private = intel_output;
     output->interlaceAllowed = FALSE;
@@ -1546,7 +1546,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
     if (i2cbus == NULL)
     {
 	xf86OutputDestroy (output);
-	return;
+	return FALSE;
     }
 
     if (output_device == SDVOB) {
@@ -1568,7 +1568,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 		   "Failed to initialize %s I2C device\n",
 		   SDVO_NAME(dev_priv));
 	xf86OutputDestroy (output);
-	return;
+	return FALSE;
     }
 
     intel_output->pI2CBus = i2cbus;
@@ -1581,7 +1581,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 		       "No SDVO device found on SDVO%c\n",
 		       output_device == SDVOB ? 'B' : 'C');
 	    xf86OutputDestroy (output);
-	    return;
+	    return FALSE;
 	}
     }
 
@@ -1594,7 +1594,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
     if (ddcbus == NULL) 
     {
 	xf86OutputDestroy (output);
-	return;
+	return FALSE;
     }
     if (output_device == SDVOB)
         ddcbus->BusName = "SDVOB DDC Bus";
@@ -1611,7 +1611,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
     if (!xf86I2CBusInit(ddcbus)) 
     {
 	xf86OutputDestroy (output);
-	return;
+	return FALSE;
     }
 
     intel_output->pI2CBus = i2cbus;
@@ -1670,7 +1670,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
     if (!xf86OutputRename (output, name))
     {
 	xf86OutputDestroy (output);
-	return;
+	return FALSE;
     }
 
     i830_sdvo_select_ddc_bus(dev_priv);
@@ -1718,4 +1718,5 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
     REPORT_OUTPUT_FLAG(SDVO_OUTPUT_SCART1, "SCART1");
     REPORT_OUTPUT_FLAG(SDVO_OUTPUT_LVDS1, "LVDS1");
 
+    return TRUE;
 }
diff --git a/src/i830_sdvo.h b/src/i830_sdvo.h
index 1368e43..798a88d 100644
--- a/src/i830_sdvo.h
+++ b/src/i830_sdvo.h
@@ -25,7 +25,7 @@
  *
  */
 
-void
+Bool
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device);
 
 int
commit ea0d21006ec71bc56acde7291e5f8d28e54b83fe
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jun 19 14:10:29 2008 -0700

    Fix hdmi POSTING_READ to use the register number instead of the register value.
    
    We won't dwell too long on how this ever worked.

diff --git a/src/i830_hdmi.c b/src/i830_hdmi.c
index c256296..72d4c63 100644
--- a/src/i830_hdmi.c
+++ b/src/i830_hdmi.c
@@ -82,7 +82,7 @@ i830_hdmi_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 	sdvox |= SDVO_PIPE_B_SELECT;
 
     OUTREG(dev_priv->output_reg, sdvox);
-    POSTING_READ(sdvox);
+    POSTING_READ(dev_priv->output_reg);
 }
 
 static void
commit 2fa9240a3b685a0c3d0e2644fc144c927b67b6b3
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 20 15:14:46 2008 -0700

    Get HDMI output working.
    
    HDMI, despite claiming to have pixel multiply support, actually doesn't
    want it, at least in the way that SDVO did.  Disable it.
    
    Also disable the NULL_PACKETS_DURING_VSYNC bit.  Despite the docs telling us
    to set it, the output doesn't like it when you do that, and the BIOS doesn't
    set it.
    
    Also add a posting read to SDVOx setting.  Without it, half the X starts
    wouldn't get anything on the screen.  (interestingly, it was every other
    startup, not just a chance).

diff --git a/src/i830_hdmi.c b/src/i830_hdmi.c
index 931a55c..c256296 100644
--- a/src/i830_hdmi.c
+++ b/src/i830_hdmi.c
@@ -52,25 +52,13 @@ i830_hdmi_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
     return MODE_OK;
 }
 
-static int
-i830_hdmi_get_pixel_multiplier(DisplayModePtr mode)
-{
-    if (mode->Clock >= 100000)
-	return 1;
-    else if (mode->Clock >= 50000)
-	return 2;
-    else
-	return 4;
-}
-
 static Bool
 i830_hdmi_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode)
 {
-    /* Make the CRTC code factor in the SDVO pixel multiplier.
+    /* The HDMI output doesn't need the pixel multiplication that SDVO does,
+     * so no fixup.
      */
-    adjusted_mode->Clock *= i830_hdmi_get_pixel_multiplier(mode);
-
     return TRUE;
 }
 
@@ -88,13 +76,13 @@ i830_hdmi_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 
     sdvox = SDVO_ENCODING_HDMI |
 	SDVO_BORDER_ENABLE |
-	SDVO_NULL_PACKETS_DURING_VSYNC |
 	SDVO_VSYNC_ACTIVE_HIGH |
 	SDVO_HSYNC_ACTIVE_HIGH;
     if (intel_crtc->pipe == 1)
 	sdvox |= SDVO_PIPE_B_SELECT;
 
     OUTREG(dev_priv->output_reg, sdvox);
+    POSTING_READ(sdvox);
 }
 
 static void
commit dc8ab9d35b261b6105a62949cfb47a3554531d0b
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 20 13:49:47 2008 -0700

    Set the sync active bits like we're supposed to, matching the BIOS.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index ecc2686..515e73d 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1262,8 +1262,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /** Requird for HDMI operation */
 #define SDVO_NULL_PACKETS_DURING_VSYNC		(1 << 9)
 #define SDVO_BORDER_ENABLE			(1 << 7)
-/** new with 965, default is to be set */
+/** New with 965, default is to be set */
 #define SDVO_VSYNC_ACTIVE_HIGH			(1 << 4)
+/** New with 965, default is to be set */
 #define SDVO_HSYNC_ACTIVE_HIGH			(1 << 3)
 /** 915/945 only, read-only bit */
 #define SDVOB_PCIE_CONCURRENCY			(1 << 3)
diff --git a/src/i830_hdmi.c b/src/i830_hdmi.c
index 77a51c6..931a55c 100644
--- a/src/i830_hdmi.c
+++ b/src/i830_hdmi.c
@@ -88,7 +88,9 @@ i830_hdmi_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 
     sdvox = SDVO_ENCODING_HDMI |
 	SDVO_BORDER_ENABLE |
-	SDVO_NULL_PACKETS_DURING_VSYNC;
+	SDVO_NULL_PACKETS_DURING_VSYNC |
+	SDVO_VSYNC_ACTIVE_HIGH |
+	SDVO_HSYNC_ACTIVE_HIGH;
     if (intel_crtc->pipe == 1)
 	sdvox |= SDVO_PIPE_B_SELECT;
 
commit af13826ed063b60a1e4179101e8889b4ab7a9d0b
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 10 11:51:05 2008 -0700

    Add pixel multiplier support for HDMI

diff --git a/src/i830_hdmi.c b/src/i830_hdmi.c
index a5d2265..77a51c6 100644
--- a/src/i830_hdmi.c
+++ b/src/i830_hdmi.c
@@ -52,10 +52,25 @@ i830_hdmi_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
     return MODE_OK;
 }
 
+static int
+i830_hdmi_get_pixel_multiplier(DisplayModePtr mode)
+{
+    if (mode->Clock >= 100000)
+	return 1;
+    else if (mode->Clock >= 50000)
+	return 2;
+    else
+	return 4;
+}
+
 static Bool
 i830_hdmi_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode)
 {
+    /* Make the CRTC code factor in the SDVO pixel multiplier.
+     */
+    adjusted_mode->Clock *= i830_hdmi_get_pixel_multiplier(mode);
+
     return TRUE;
 }
 
commit 9a05662918223477eb1cf6f80ffac08712721c70
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Mar 10 11:47:15 2008 -0700

    The phase shift its are now reserved, and add HDMI clock limits.

diff --git a/src/i830_display.c b/src/i830_display.c
index 7697d4f..7857ee3 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1175,7 +1175,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	    dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
 	    break;
 	}
-	if (IS_I965G(pI830))
+	if (IS_I965G(pI830) && !IS_IGD_GM(pI830))
 	    dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
     } else {
 	if (is_lvds) {
diff --git a/src/i830_hdmi.c b/src/i830_hdmi.c
index 103443f..a5d2265 100644
--- a/src/i830_hdmi.c
+++ b/src/i830_hdmi.c
@@ -43,6 +43,12 @@ struct i830_hdmi_priv {
 static int
 i830_hdmi_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
 {
+    if (mode->Clock > 165000)
+	return MODE_CLOCK_HIGH;
+
+    if (mode->Clock < 20000)
+	return MODE_CLOCK_LOW;
+
     return MODE_OK;
 }
 
commit beba1dd3561e38573ed9f507328caf7f8fb9f84a
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 6 16:05:17 2008 -0800

    Initial HDMI work.  Not currently hooked up at startup.

diff --git a/src/Makefile.am b/src/Makefile.am
index 0784c06..9dd9b37 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -100,6 +100,7 @@ intel_drv_la_SOURCES = \
          i830_driver.c \
 	 i830_dvo.c \
          i830.h \
+	 i830_hdmi.c \
          i830_i2c.c \
          i830_io.c \
 	 i830_lvds.c \
diff --git a/src/i810_reg.h b/src/i810_reg.h
index dcf14bf..ecc2686 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1216,6 +1216,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 # define FP_M2_DIV_SHIFT			0
 
 #define PORT_HOTPLUG_EN		0x61110
+# define HDMIB_HOTPLUG_INT_EN			(1 << 29)
+# define HDMIC_HOTPLUG_INT_EN			(1 << 28)
+# define HDMID_HOTPLUG_INT_EN			(1 << 27)
 # define SDVOB_HOTPLUG_INT_EN			(1 << 26)
 # define SDVOC_HOTPLUG_INT_EN			(1 << 25)
 # define TV_HOTPLUG_INT_EN			(1 << 18)
@@ -1223,6 +1226,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 # define CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
 
 #define PORT_HOTPLUG_STAT	0x61114
+# define HDMIB_HOTPLUG_INT_STATUS		(1 << 29)
+# define HDMIC_HOTPLUG_INT_STATUS		(1 << 28)
+# define HDMID_HOTPLUG_INT_STATUS		(1 << 27)
 # define CRT_HOTPLUG_INT_STATUS			(1 << 11)
 # define TV_HOTPLUG_INT_STATUS			(1 << 10)
 # define CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
@@ -1251,6 +1257,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define SDVO_PHASE_SELECT_DEFAULT		(6 << 19)
 #define SDVO_CLOCK_OUTPUT_INVERT		(1 << 18)
 #define SDVOC_GANG_MODE				(1 << 16)
+#define SDVO_ENCODING_SDVO			(0x0 << 10)
+#define SDVO_ENCODING_HDMI			(0x2 << 10)
+/** Requird for HDMI operation */
+#define SDVO_NULL_PACKETS_DURING_VSYNC		(1 << 9)
 #define SDVO_BORDER_ENABLE			(1 << 7)
 /** new with 965, default is to be set */
 #define SDVO_VSYNC_ACTIVE_HIGH			(1 << 4)
diff --git a/src/i830.h b/src/i830.h
index 2a804ab..00a5059 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -238,6 +238,7 @@ typedef struct {
 #define I830_OUTPUT_SDVO 5
 #define I830_OUTPUT_LVDS 6
 #define I830_OUTPUT_TVOUT 7
+#define I830_OUTPUT_HDMI 8
 
 struct _I830DVODriver {
    int type;
@@ -802,6 +803,9 @@ void i830_crt_init(ScrnInfoPtr pScrn);
 /* i830_dvo.c */
 void i830_dvo_init(ScrnInfoPtr pScrn);
 
+/* i830_hdmi.c */
+void i830_hdmi_init(ScrnInfoPtr pScrn, int output_reg);
+
 /* i830_lvds.c */
 void i830_lvds_init(ScrnInfoPtr pScrn);
 
diff --git a/src/i830_display.c b/src/i830_display.c
index 56a718d..7697d4f 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1103,6 +1103,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	    lvds_bits = intel_output->lvds_bits;
 	    break;
 	case I830_OUTPUT_SDVO:
+	case I830_OUTPUT_HDMI:
 	    is_sdvo = TRUE;
 	    if (intel_output->needs_tv_clock)
 		is_tv = TRUE;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 604665e..5782d48 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -924,8 +924,13 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       i830_lvds_init(pScrn);
 
    if (IS_I9XX(pI830)) {
+#if 1
       i830_sdvo_init(pScrn, SDVOB);
       i830_sdvo_init(pScrn, SDVOC);
+#else
+      i830_hdmi_init(pScrn, SDVOB);
+      i830_hdmi_init(pScrn, SDVOC);
+#endif
    } else {
       i830_dvo_init(pScrn);
    }
diff --git a/src/i830_hdmi.c b/src/i830_hdmi.c
new file mode 100644
index 0000000..103443f
--- /dev/null
+++ b/src/i830_hdmi.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "i830.h"
+#include "xf86Modes.h"
+#include "i830_display.h"
+
+struct i830_hdmi_priv {
+    uint32_t output_reg;
+
+    uint32_t save_SDVO;
+};
+
+static int
+i830_hdmi_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
+{
+    return MODE_OK;
+}
+
+static Bool
+i830_hdmi_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
+		     DisplayModePtr adjusted_mode)
+{
+    return TRUE;
+}
+
+static void
+i830_hdmi_mode_set(xf86OutputPtr output, DisplayModePtr mode,
+		   DisplayModePtr adjusted_mode)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    I830OutputPrivatePtr intel_output = output->driver_private;
+    struct i830_hdmi_priv *dev_priv = intel_output->dev_priv;
+    I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcPtr crtc = output->crtc;
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+    uint32_t sdvox;
+
+    sdvox = SDVO_ENCODING_HDMI |
+	SDVO_BORDER_ENABLE |
+	SDVO_NULL_PACKETS_DURING_VSYNC;
+    if (intel_crtc->pipe == 1)
+	sdvox |= SDVO_PIPE_B_SELECT;
+
+    OUTREG(dev_priv->output_reg, sdvox);
+}
+
+static void
+i830_hdmi_dpms(xf86OutputPtr output, int mode)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    I830OutputPrivatePtr intel_output = output->driver_private;
+    struct i830_hdmi_priv *dev_priv = intel_output->dev_priv;
+    I830Ptr pI830 = I830PTR(pScrn);
+    uint32_t  temp;
+
+    if (mode == DPMSModeOff) {
+	temp = INREG(dev_priv->output_reg);
+	OUTREG(dev_priv->output_reg, temp & ~SDVO_ENABLE);
+    } else {
+	temp = INREG(dev_priv->output_reg);
+	OUTREG(dev_priv->output_reg, temp | SDVO_ENABLE);
+    }
+}
+
+static void
+i830_hdmi_save(xf86OutputPtr output)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    I830OutputPrivatePtr intel_output = output->driver_private;
+    struct i830_hdmi_priv *dev_priv = intel_output->dev_priv;
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    dev_priv->save_SDVO = INREG(dev_priv->output_reg);
+}
+
+static void
+i830_hdmi_restore(xf86OutputPtr output)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    I830OutputPrivatePtr intel_output = output->driver_private;
+    struct i830_hdmi_priv *dev_priv = intel_output->dev_priv;
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    OUTREG(dev_priv->output_reg, dev_priv->save_SDVO);
+}
+
+/**
+ * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect HDMI connection.
+ *
+ * \return TRUE if HDMI port is connected.
+ * \return FALSE if HDMI port is disconnected.
+ */
+static xf86OutputStatus
+i830_hdmi_detect(xf86OutputPtr output)
+{
+    ScrnInfoPtr	pScrn = output->scrn;
+    I830OutputPrivatePtr intel_output = output->driver_private;
+    struct i830_hdmi_priv *dev_priv = intel_output->dev_priv;
+    I830Ptr pI830 = I830PTR(pScrn);
+    uint32_t temp, bit;
+
+    temp = INREG(PORT_HOTPLUG_EN);
+
+    OUTREG(PORT_HOTPLUG_EN,
+	   temp |
+	   HDMIB_HOTPLUG_INT_EN |
+	   HDMIC_HOTPLUG_INT_EN |
+	   HDMID_HOTPLUG_INT_EN);
+
+    POSTING_READ(PORT_HOTPLUG_EN);
+
+    switch (dev_priv->output_reg) {
+    case SDVOB:
+	bit = HDMIB_HOTPLUG_INT_STATUS;
+	break;
+    case SDVOC:
+	bit = HDMIC_HOTPLUG_INT_STATUS;
+	break;
+    default:
+	return XF86OutputStatusUnknown;
+    }
+
+    if ((INREG(PORT_HOTPLUG_STAT) & bit) != 0)
+	return XF86OutputStatusConnected;
+    else
+	return XF86OutputStatusDisconnected;
+}
+
+static void
+i830_hdmi_destroy (xf86OutputPtr output)
+{
+    I830OutputPrivatePtr intel_output = output->driver_private;
+
+    if (intel_output != NULL) {
+	xf86DestroyI2CBusRec(intel_output->pDDCBus, FALSE, FALSE);
+	xfree(intel_output);
+    }
+}
+
+static const xf86OutputFuncsRec i830_hdmi_output_funcs = {
+    .dpms = i830_hdmi_dpms,
+    .save = i830_hdmi_save,
+    .restore = i830_hdmi_restore,
+    .mode_valid = i830_hdmi_mode_valid,
+    .mode_fixup = i830_hdmi_mode_fixup,
+    .prepare = i830_output_prepare,
+    .mode_set = i830_hdmi_mode_set,
+    .commit = i830_output_commit,
+    .detect = i830_hdmi_detect,
+    .get_modes = i830_ddc_get_modes,
+    .destroy = i830_hdmi_destroy
+};
+
+void
+i830_hdmi_init(ScrnInfoPtr pScrn, int output_reg)
+{
+    xf86OutputPtr output;
+    I830OutputPrivatePtr intel_output;
+    struct i830_hdmi_priv *dev_priv;
+
+    output = xf86OutputCreate(pScrn, &i830_hdmi_output_funcs,
+			      (output_reg == SDVOB) ? "HDMI-1" : "HDMI-2");
+    if (!output)
+	return;
+    intel_output = xnfcalloc(sizeof (I830OutputPrivateRec) +
+			     sizeof (struct i830_hdmi_priv), 1);
+    if (intel_output == NULL) {
+	xf86OutputDestroy(output);
+	return;
+    }
+    output->driver_private = intel_output;
+    output->interlaceAllowed = FALSE;
+    output->doubleScanAllowed = FALSE;
+
+    dev_priv = (struct i830_hdmi_priv *)(intel_output + 1);
+    dev_priv->output_reg = output_reg;
+
+    intel_output->dev_priv = dev_priv;
+    intel_output->type = I830_OUTPUT_HDMI;
+    intel_output->pipe_mask = ((1 << 0) | (1 << 1));
+    intel_output->clone_mask = (1 << I830_OUTPUT_HDMI);
+
+    /* Set up the DDC bus. */
+    if (output_reg == SDVOB)
+	I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOE, "HDMIDDC_B");
+    else
+	I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOE, "HDMIDDC_C");
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "HDMI output %d detected\n",
+	       1 + (output_reg - SDVOB));
+}
commit da58dc3b02999f3244d0eaf77180b828d85bd609
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 6 14:57:57 2008 -0800

    Add DisplayPort registers.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index dc4f5e8..dcf14bf 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1451,6 +1451,30 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 /** @} */
 
+#define DP_B			0x64100
+#define DPB_AUX_CH_CTL		0x64110
+#define DPB_AUX_CH_DATA1	0x64114
+#define DPB_AUX_CH_DATA2	0x64118
+#define DPB_AUX_CH_DATA3	0x6411c
+#define DPB_AUX_CH_DATA4	0x64120
+#define DPB_AUX_CH_DATA5	0x64124
+
+#define DP_C			0x64200
+#define DPC_AUX_CH_CTL		0x64210
+#define DPC_AUX_CH_DATA1	0x64214
+#define DPC_AUX_CH_DATA2	0x64218
+#define DPC_AUX_CH_DATA3	0x6421c
+#define DPC_AUX_CH_DATA4	0x64220
+#define DPC_AUX_CH_DATA5	0x64224
+
+#define DP_D			0x64300
+#define DPD_AUX_CH_CTL		0x64310
+#define DPD_AUX_CH_DATA1	0x64314
+#define DPD_AUX_CH_DATA2	0x64318
+#define DPD_AUX_CH_DATA3	0x6431c
+#define DPD_AUX_CH_DATA4	0x64320
+#define DPD_AUX_CH_DATA5	0x64324
+
 /*
  * Two channel clock control. Turn this on if you need clkb for two channel mode
  * Overridden by global LVDS power sequencing
diff --git a/src/i830_debug.c b/src/i830_debug.c
index 19cc661..2b5708e 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -628,6 +628,31 @@ static struct i830SnapshotRec {
     DEFINEREG(MI_ARB_STATE),
     DEFINEREG(MI_RDRET_STATE),
     DEFINEREG(ECOSKPD),
+
+    DEFINEREG(DP_B),
+    DEFINEREG(DPB_AUX_CH_CTL),
+    DEFINEREG(DPB_AUX_CH_DATA1),
+    DEFINEREG(DPB_AUX_CH_DATA2),
+    DEFINEREG(DPB_AUX_CH_DATA3),
+    DEFINEREG(DPB_AUX_CH_DATA4),
+    DEFINEREG(DPB_AUX_CH_DATA5),
+
+    DEFINEREG(DP_C),
+    DEFINEREG(DPC_AUX_CH_CTL),
+    DEFINEREG(DPC_AUX_CH_DATA1),
+    DEFINEREG(DPC_AUX_CH_DATA2),
+    DEFINEREG(DPC_AUX_CH_DATA3),
+    DEFINEREG(DPC_AUX_CH_DATA4),
+    DEFINEREG(DPC_AUX_CH_DATA5),
+
+    DEFINEREG(DP_D),
+    DEFINEREG(DPD_AUX_CH_CTL),
+    DEFINEREG(DPD_AUX_CH_DATA1),
+    DEFINEREG(DPD_AUX_CH_DATA2),
+    DEFINEREG(DPD_AUX_CH_DATA3),
+    DEFINEREG(DPD_AUX_CH_DATA4),
+    DEFINEREG(DPD_AUX_CH_DATA5),
+
 #if 0
     DEFINEREG2(FENCE_NEW + 0, i810_debug_fence_new),
     DEFINEREG2(FENCE_NEW + 8, i810_debug_fence_new),
commit 52a414d1158aa7512fb79560dc220e2a78456a2d
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 6 14:00:18 2008 -0800

    Remove VGA regs from debug output.

diff --git a/src/i830_debug.c b/src/i830_debug.c
index 074e8b9..19cc661 100644
--- a/src/i830_debug.c
+++ b/src/i830_debug.c
@@ -697,6 +697,7 @@ void i830CompareRegsToSnapshot(ScrnInfoPtr pScrn, char *where)
 }
 #endif /* !REG_DUMPER */
 
+#if 0
 static void i830DumpIndexed (ScrnInfoPtr pScrn, char *name, int id, int val, int min, int max)
 {
     I830Ptr pI830 = I830PTR(pScrn);
@@ -737,6 +738,7 @@ static void i830DumpAR(ScrnInfoPtr pScrn)
     OUTREG8(0x3c0, orig_arx);
     INREG8(st01); /* switch back to index mode */
 }
+#endif
 
 void i830DumpRegs (ScrnInfoPtr pScrn)
 {
@@ -748,8 +750,10 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
     int ref;
     int	dot;
     int phase;
+#if 0
     int msr;
     int crt;
+#endif
 
     xf86DrvMsg (pScrn->scrnIndex, X_INFO, "DumpRegsBegin\n");
     for (i = 0; i < NUM_I830_SNAPSHOTREGS; i++) {
@@ -767,6 +771,7 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
 			i830_snapshot[i].name, (unsigned int)val);
 	}
     }
+#if 0
     i830DumpIndexed (pScrn, "SR", 0x3c4, 0x3c5, 0, 7);
     msr = INREG8(0x3cc);
     xf86DrvMsg (pScrn->scrnIndex, X_INFO, "%20.20s: 0x%02x\n",
@@ -778,6 +783,7 @@ void i830DumpRegs (ScrnInfoPtr pScrn)
     else
 	crt = 0x3b0;
     i830DumpIndexed (pScrn, "CR", crt + 4, crt + 5, 0, 0x24);
+#endif
     for (pipe = 0; pipe <= 1; pipe++)
     {
 	fp = INREG(pipe == 0 ? FPA0 : FPB0);
diff --git a/src/reg_dumper/.gitignore b/src/reg_dumper/.gitignore
index f72a165..b0f9b6f 100644
--- a/src/reg_dumper/.gitignore
+++ b/src/reg_dumper/.gitignore
@@ -1,3 +1,4 @@
+intel_hotplug
 intel_idle
 intel_reg_dumper
 intel_stepping
diff --git a/src/reg_dumper/Makefile.am b/src/reg_dumper/Makefile.am
index b840b24..d49a59b 100644
--- a/src/reg_dumper/Makefile.am
+++ b/src/reg_dumper/Makefile.am
@@ -1,4 +1,4 @@
-noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping
+noinst_PROGRAMS = intel_reg_dumper intel_idle intel_stepping intel_hotplug
 
 intel_reg_dumper_SOURCES = \
 	main.c \
@@ -12,9 +12,16 @@ intel_idle_SOURCES = \
 	xprintf.c \
 	../i830_debug.c
 
+intel_hotplug_SOURCES = \
+	hotplug.c \
+	reg_dumper.h \
+	xprintf.c \
+	../i830_debug.c
+
 intel_stepping_SOURCES = \
 	stepping.c
 
+intel_hotplug_LDADD = $(PCIACCESS_LIBS)
 intel_reg_dumper_LDADD = $(PCIACCESS_LIBS)
 intel_idle_LDADD = $(PCIACCESS_LIBS)
 intel_stepping_LDADD = $(PCIACCESS_LIBS)
commit b60bbbfd7b7dcf31726ad615a493f34f17cc6309
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Mar 6 13:59:06 2008 -0800

    Add little hotplug detector app.

diff --git a/src/reg_dumper/hotplug.c b/src/reg_dumper/hotplug.c
new file mode 100644
index 0000000..68fe584
--- /dev/null
+++ b/src/reg_dumper/hotplug.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright © 2007 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <pciaccess.h>
+#include <err.h>
+#include <unistd.h>
+
+#include "reg_dumper.h"
+#include "../i810_reg.h"
+
+struct idle_flags {
+    uint32_t instdone_flag;
+    char *name;
+    unsigned int count;
+};
+
+int main(int argc, char **argv)
+{
+    struct pci_device *dev;
+    I830Rec i830;
+    I830Ptr pI830 = &i830;
+    ScrnInfoRec scrn;
+    int err, mmio_bar;
+    void *mmio;
+    int i;
+
+    err = pci_system_init();
+    if (err != 0) {
+	fprintf(stderr, "Couldn't initialize PCI system: %s\n", strerror(err));
+	exit(1);
+    }
+
+    /* Grab the graphics card */
+    dev = pci_device_find_by_slot(0, 0, 2, 0);
+    if (dev == NULL)
+	errx(1, "Couldn't find graphics card");
+
+    err = pci_device_probe(dev);
+    if (err != 0) {
+	fprintf(stderr, "Couldn't probe graphics card: %s\n", strerror(err));
+	exit(1);
+    }
+
+    if (dev->vendor_id != 0x8086)
+	errx(1, "Graphics card is non-intel");
+
+    i830.PciInfo = &i830.pci_info_rec;
+    i830.PciInfo->chipType = dev->device_id;
+
+    i830.pci_dev = dev;
+
+    mmio_bar = IS_I9XX((&i830)) ? 0 : 1;
+
+    err = pci_device_map_range (dev,
+				dev->regions[mmio_bar].base_addr,
+				dev->regions[mmio_bar].size, 
+				PCI_DEV_MAP_FLAG_WRITABLE,
+				&mmio);
+
+    if (err != 0) {
+	fprintf(stderr, "Couldn't map MMIO region: %s\n", strerror(err));
+	exit(1);
+    }
+    i830.mmio = mmio;
+
+    scrn.scrnIndex = 0;
+    scrn.pI830 = &i830;
+
+    OUTREG(SDVOB, (0x0 << 10));
+    OUTREG(SDVOC, (0x0 << 10));
+
+    OUTREG(PORT_HOTPLUG_EN,
+	   (1 << 29) |
+	   (1 << 28) |
+	   (1 << 27) |
+	   SDVOB_HOTPLUG_INT_EN |
+	   SDVOC_HOTPLUG_INT_EN |
+	   (1 << 24) |
+	   CRT_HOTPLUG_INT_EN |
+	   TV_HOTPLUG_INT_EN |
+	   CRT_HOTPLUG_INT_EN);
+
+    for (i = 0;; i++) {
+	OUTREG(PORT_HOTPLUG_STAT,
+	       (1 << 20) |
+	       (1 << 19) |
+	       (1 << 18) |
+	       (1 << 17) |
+	       CRT_HOTPLUG_INT_STATUS |
+	       TV_HOTPLUG_INT_STATUS |
+	       SDVOC_HOTPLUG_INT_STATUS |
+	       SDVOB_HOTPLUG_INT_STATUS);
+	INREG(PORT_HOTPLUG_STAT);
+
+	usleep(500 * 1000);
+
+	printf("%5d: 0x%08x\n", i, INREG(PORT_HOTPLUG_STAT));
+	sleep(1);
+    }
+
+    return 0;
+}
+
+void xf86DrvMsg(int scrnIndex, int severity, const char *format, ...)
+{
+    va_list va;
+
+    switch (severity) {
+    case X_INFO:
+	printf("(II): ");
+	break;
+    case X_WARNING:
+	printf("(WW): ");
+	break;
+    case X_ERROR:
+	printf("(EE): ");
+	break;
+    }
+
+    va_start(va, format);
+    vprintf(format, va);
+    va_end(va);
+}


More information about the xorg-commit mailing list