xf86-video-intel: 9 commits - man/intel.man src/i830_display.c src/i830_driver.c src/i830.h src/i830_sdvo.c src/i830_sdvo_regs.h

Zhenyu Wang zhen at kemper.freedesktop.org
Sun Feb 15 21:07:56 PST 2009


 man/intel.man        |    6 -
 src/i830.h           |    3 
 src/i830_display.c   |   25 +++++-
 src/i830_driver.c    |   26 ++----
 src/i830_sdvo.c      |  212 ++++++++++++++++++++++++++++++++++-----------------
 src/i830_sdvo_regs.h |    3 
 6 files changed, 177 insertions(+), 98 deletions(-)

New commits:
commit 9d464bd5b0d2724f5edb26e859888ceb6a248f9b
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Feb 13 11:15:48 2009 +0800

    Fix SDVO/HDMI detect
    
    SDVOC detect bit is only valid for HDMIC.
    And for SDVO devices, SDVOB detect bit should be used
    to probe all possible SDVO outputs.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index f8219b7..77c127e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -912,21 +912,21 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       i830_lvds_init(pScrn);
 
    if (IS_I9XX(pI830)) {
+      Bool found;
       if ((INREG(SDVOB) & SDVO_DETECTED)) {
-	 Bool found = i830_sdvo_init(pScrn, SDVOB);
+	 found = i830_sdvo_init(pScrn, SDVOB);
 
 	 if (!found && SUPPORTS_INTEGRATED_HDMI(pI830))
 	    i830_hdmi_init(pScrn, SDVOB);
       }
 
-      if ((INREG(SDVOC) & SDVO_DETECTED) ||
-	      /* SDVOC detect bit is reserved on 965G/965GM */
-	      (IS_I965G(pI830) && !IS_G4X(pI830))) {
-	 Bool found = i830_sdvo_init(pScrn, SDVOC);
+      if ((INREG(SDVOB) & SDVO_DETECTED))
+	 found = i830_sdvo_init(pScrn, SDVOC);
+
+      if ((INREG(SDVOC) & SDVO_DETECTED) &&
+	    !found && SUPPORTS_INTEGRATED_HDMI(pI830))
+	 i830_hdmi_init(pScrn, SDVOC);
 
-	 if (!found && SUPPORTS_INTEGRATED_HDMI(pI830))
-	    i830_hdmi_init(pScrn, SDVOC);
-      }
    } else {
       i830_dvo_init(pScrn);
    }
commit 48445d2e939328495b4abe0fb7e579dfcef727bb
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Feb 13 11:11:18 2009 +0800

    SDVO: remove ForceSDVODetect option
    
    Which is just a hack to hide our SDVO detect drawback,
    we will have SDVO/HDMI detect fix later.

diff --git a/man/intel.man b/man/intel.man
index 65d1114..c7a3c61 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -202,12 +202,6 @@ information.
 Enable XvMC driver. Current support MPEG2 MC on 915/945 and G33 series.
 User should provide absolute path to libIntelXvMC.so in XvMCConfig file.
 Default: Disabled.
-.TP
-.BI "Option \*qForceSDVODetect\*q \*q" boolean \*q
-Instead of depending on SDVO detect status bit to initialize SDVO outputs,
-this option trys to ignore that status bit and try to probe on all SDVO
-ports anyway. Try this if some output is not detected on your ADD2 card.
-Use of this option will slow down your startup time. Default: Disabled.
 
 .SH OUTPUT CONFIGURATION
 On 830M and better chipsets, the driver supports runtime configuration of
diff --git a/src/i830.h b/src/i830.h
index bfd78dc..7904b9f 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -729,9 +729,6 @@ typedef struct _I830Rec {
    Bool debug_modes;
    unsigned int quirk_flag;
 
-   /* User option to ignore SDVO detect bit status, in case some outputs
-      not detected on SDVO, so let driver try its best. */
-   Bool force_sdvo_detect;
     /** User option to print acceleration fallback info to the server log. */
    Bool fallback_debug;
 } I830Rec;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index b8d8d37..f8219b7 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -317,7 +317,6 @@ typedef enum {
 #ifdef INTEL_XVMC
    OPTION_XVMC,
 #endif
-   OPTION_FORCE_SDVO_DETECT,
    OPTION_PREFER_OVERLAY,
 } I830Opts;
 
@@ -343,7 +342,6 @@ static OptionInfoRec I830Options[] = {
 #ifdef INTEL_XVMC
    {OPTION_XVMC,	"XvMC",		OPTV_BOOLEAN,	{0},	TRUE},
 #endif
-   {OPTION_FORCE_SDVO_DETECT, "ForceSDVODetect", OPTV_BOOLEAN,  {0},	FALSE},
    {OPTION_PREFER_OVERLAY, "XvPreferOverlay", OPTV_BOOLEAN, {0}, FALSE},
    {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
 };
@@ -914,14 +912,14 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       i830_lvds_init(pScrn);
 
    if (IS_I9XX(pI830)) {
-      if ((INREG(SDVOB) & SDVO_DETECTED) || pI830->force_sdvo_detect) {
+      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(SDVOC) & SDVO_DETECTED) || pI830->force_sdvo_detect ||
+      if ((INREG(SDVOC) & SDVO_DETECTED) ||
 	      /* SDVOC detect bit is reserved on 965G/965GM */
 	      (IS_I965G(pI830) && !IS_G4X(pI830))) {
 	 Bool found = i830_sdvo_init(pScrn, SDVOC);
@@ -1556,12 +1554,6 @@ I830GetEarlyOptions(ScrnInfoPtr pScrn)
     if (xf86ReturnOptValBool(pI830->Options, OPTION_FORCEENABLEPIPEA, FALSE))
 	pI830->quirk_flag |= QUIRK_PIPEA_FORCE;
 
-    if (xf86ReturnOptValBool(pI830->Options, OPTION_FORCE_SDVO_DETECT, FALSE)) {
-	pI830->force_sdvo_detect = TRUE;
-    } else {
-	pI830->force_sdvo_detect = FALSE;
-    }
-
     return TRUE;
 }
 
commit ddedf19f889da2ce6d69a3afce4665e2245682fa
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Feb 13 10:09:42 2009 +0800

    SDVO: Switch control bus only before DDC access
    
    Instead of set control bus switch before every i2c start,
    just set once before doing DDC. This should eliminate some
    encoders returning error during that.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 8066251..4b98a9b 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1377,9 +1377,7 @@ i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout)
     xf86OutputPtr	    output = b->DriverPrivate.ptr;
     I830OutputPrivatePtr    intel_output = output->driver_private;
     I2CBusPtr		    i2cbus = intel_output->pI2CBus;
-    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
 
-    i830_sdvo_set_control_bus_switch(output, dev_priv->ddc_bus);
     return i2cbus->I2CStart(i2cbus, timeout);
 }
 
@@ -1566,9 +1564,11 @@ i830_sdvo_get_ddc_modes(xf86OutputPtr output)
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     DisplayModePtr modes = NULL;
     xf86OutputPtr crt;
-    I830OutputPrivatePtr intel_output;
+    I830OutputPrivatePtr intel_output = output->driver_private;
     xf86MonPtr edid_mon = NULL;
-    struct i830_sdvo_priv *dev_priv;
+    struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+    i830_sdvo_set_control_bus_switch(output, dev_priv->ddc_bus);
 
     modes = i830_ddc_get_modes(output);
     if (modes != NULL)
commit f1ca56e17d0ecd4f1299061a6b3272bfd289e123
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Feb 13 10:02:02 2009 +0800

    SDVO: Fix TV support
    
    As SDVO TV uses SDVO_TVClkIn from SDVO encoder for clock reference,
    it needs to generate proper PLL for current input clock. This uses
    fixed PLL table from vbios for this. And possible sdvo mulitiplier
    has to be setup correctly. This makes TV output stable on my 945GCLF2
    board with NTSC-M format.

diff --git a/src/i830_display.c b/src/i830_display.c
index 8ecb5e5..8a5cf24 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1304,6 +1304,26 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 		   (float)adjusted_mode->Clock / 1000);
     }
 
+    /* SDVO TV has fixed PLL values depends on its clock range,
+       this mirrors vbios setting. */
+    if (is_sdvo && is_tv) {
+	if (adjusted_mode->Clock >= 100000 &&
+		adjusted_mode->Clock < 140500) {
+	    clock.p1 = 2;
+	    clock.p2 = 10;
+	    clock.n = 3;
+	    clock.m1 = 16;
+	    clock.m2 = 8;
+	} else if (adjusted_mode->Clock >= 140500 &&
+		adjusted_mode->Clock <= 200000) {
+	    clock.p1 = 1;
+	    clock.p2 = 10;
+	    clock.n = 6;
+	    clock.m1 = 12;
+	    clock.m2 = 8;
+	}
+    }
+
     fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
 
     dpll = DPLL_VGA_MODE_DIS;
@@ -1315,10 +1335,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	if (is_sdvo)
 	{
 	    dpll |= DPLL_DVO_HIGH_SPEED;
-	    if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) &&
-		!is_tv)
+	    if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)))
 	    {
-		int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
+		int sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier (adjusted_mode);
 		dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
 	    }
 	}
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 233141c..8066251 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -957,6 +957,31 @@ static void i830_sdvo_set_avi_infoframe(xf86OutputPtr output,
 			SDVO_HBUF_TX_VSYNC);
 }
 
+static void
+i830_sdvo_set_tv_format(xf86OutputPtr output)
+{
+    ScrnInfoPtr pScrn = output->scrn;
+    I830OutputPrivatePtr intel_output = output->driver_private;
+    struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+    struct i830_sdvo_tv_format *format, unset;
+    uint8_t status;
+
+    format = &dev_priv->tv_format;
+    memset(&unset, 0, sizeof(unset));
+    if (memcmp(format, &unset, sizeof(*format))) {
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "%s: Choosing default TV format of NTSC-M\n",
+		   SDVO_NAME(dev_priv));
+	format->ntsc_m = 1;
+	i830_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format,
+		sizeof(*format));
+	status = i830_sdvo_read_response(output, NULL, 0);
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "%s: Fail to set TV format\n", SDVO_NAME(dev_priv));
+    }
+}
+
 static Bool
 i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode)
@@ -1002,8 +1027,12 @@ i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 
 	    i830_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
 
+	    xf86SetModeCrtc(adjusted_mode, 0);
+
 	    ErrorF("input modeline:\n");
 	    xf86PrintModeline(0, adjusted_mode);
+	    /* Clock range is required to be in 100-200Mhz */
+	    adjusted_mode->Clock *= i830_sdvo_get_pixel_multiplier(adjusted_mode);
 	} else {
 	    return FALSE;
 	}
@@ -1049,20 +1078,28 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 	sdvox |= SDVO_AUDIO_ENABLE;
     }
 
-    i830_sdvo_get_dtd_from_mode(&input_dtd, mode);
+    /* We have tried to get input timing in mode_fixup, and filled into
+       adjusted_mode */
+    if (dev_priv->is_tv)
+	i830_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
+    else
+	i830_sdvo_get_dtd_from_mode(&input_dtd, mode);
 
     /* If it's a TV, we already set the output timing in mode_fixup.
      * Otherwise, the output timing is equal to the input timing.
      */
+    i830_sdvo_set_target_output(output, dev_priv->controlled_output);
+    /* Set the input timing to the screen. Assume always input 0. */
+    i830_sdvo_set_target_input(output, TRUE, FALSE);
+
+    if (dev_priv->is_tv)
+	i830_sdvo_set_tv_format(output);
+
     if (!dev_priv->is_tv) {
 	/* Set the output timing to the screen */
-	i830_sdvo_set_target_output(output, dev_priv->controlled_output);
 	i830_sdvo_set_output_timing(output, &input_dtd);
     }
 
-    /* Set the input timing to the screen. Assume always input 0. */
-    i830_sdvo_set_target_input(output, TRUE, FALSE);
-
     /* We would like to use i830_sdvo_create_preferred_input_timing() to
      * provide the device with a timing it can support, if it supports that
      * feature.  However, presumably we would need to adjust the CRTC to output
@@ -1620,10 +1657,9 @@ i830_sdvo_get_tv_mode(DisplayModePtr *head, int width, int height,
 static void
 i830_sdvo_check_tv_format(xf86OutputPtr output)
 {
-    ScrnInfoPtr pScrn = output->scrn;
     I830OutputPrivatePtr intel_output = output->driver_private;
     struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
-    struct i830_sdvo_tv_format format, unset;
+    struct i830_sdvo_tv_format format;
     uint8_t status;
 
     i830_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0);
@@ -1631,19 +1667,6 @@ i830_sdvo_check_tv_format(xf86OutputPtr output)
     if (status != SDVO_CMD_STATUS_SUCCESS)
 	return;
 
-    memset(&unset, 0, sizeof(unset));
-    if (memcmp(&format, &unset, sizeof(format))) {
-	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-		   "%s: Choosing default TV format of NTSC-M\n",
-		   SDVO_NAME(dev_priv));
-
-	format.ntsc_m = TRUE;
-	i830_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, &format,
-		sizeof(format));
-	status = i830_sdvo_read_response(output, NULL, 0);
-	if (status != SDVO_CMD_STATUS_SUCCESS)
-	    return;
-    }
     memcpy(&dev_priv->tv_format, &format, sizeof(format));
 }
 
commit acde0ef683d6ec33d0b478923ffb11bd6785798f
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Feb 13 09:53:57 2009 +0800

    SDVO: fix CREATE_PREFERRED_INPUT_TIMING command

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 5c2a4b1..233141c 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -594,9 +594,12 @@ i830_sdvo_create_preferred_input_timing(xf86OutputPtr output, uint16_t clock,
     struct i830_sdvo_preferred_input_timing_args args;
     uint8_t status;
 
+    memset(&args, 0, sizeof(args));
     args.clock = clock;
     args.width = width;
     args.height = height;
+    args.interlace = 0;
+    args.scaled = 0;
     i830_sdvo_write_cmd(output, SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING,
 			&args, sizeof(args));
     status = i830_sdvo_read_response(output, NULL, 0);
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index 6988d49..ab38355 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -101,6 +101,9 @@ struct i830_sdvo_preferred_input_timing_args {
     uint16_t clock;
     uint16_t width;
     uint16_t height;
+    uint8_t interlace:1;
+    uint8_t scaled:1;
+    uint8_t pad:6;
 } __attribute__((packed));
 
 /* I2C registers for SDVO */
commit 824b2f0c5530c3196901c961757e6677b042caf3
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Feb 13 09:50:45 2009 +0800

    SDVO: fix usage for SET_TV_FORMAT and GET_SDTV_RESOLUTION_SUPPORT command
    
    They both needs parameters.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 9cce316..5c2a4b1 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1635,9 +1635,13 @@ i830_sdvo_check_tv_format(xf86OutputPtr output)
 		   SDVO_NAME(dev_priv));
 
 	format.ntsc_m = TRUE;
-	i830_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, NULL, 0);
+	i830_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, &format,
+		sizeof(format));
 	status = i830_sdvo_read_response(output, NULL, 0);
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+	    return;
     }
+    memcpy(&dev_priv->tv_format, &format, sizeof(format));
 }
 
 static DisplayModePtr
@@ -1647,6 +1651,7 @@ i830_sdvo_get_tv_modes(xf86OutputPtr output)
     struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
     DisplayModePtr modes = NULL;
     struct i830_sdvo_sdtv_resolution_reply *res = &dev_priv->sdtv_resolutions;
+    struct i830_sdvo_sdtv_resolution_request tv_res;
     uint8_t status;
     float refresh = 60; /* XXX */
 
@@ -1654,7 +1659,10 @@ i830_sdvo_get_tv_modes(xf86OutputPtr output)
 
     /* Read the list of supported input resolutions for the selected TV format.
      */
-    i830_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT, NULL, 0);
+    memset(&tv_res, 0, sizeof(tv_res));
+    memcpy(&tv_res, &dev_priv->tv_format, sizeof(tv_res));
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
+	    &tv_res, sizeof(tv_res));
     status = i830_sdvo_read_response(output, res, sizeof(*res));
     if (status != SDVO_CMD_STATUS_SUCCESS)
 	return NULL;
commit 62c0c2f5549a51c5df209f7353a19ca301f221be
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Fri Feb 13 09:48:34 2009 +0800

    SDVO: fix error in modeline and DTD convert

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 508a467..9cce316 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -702,7 +702,7 @@ i830_sdvo_get_dtd_from_mode(struct i830_sdvo_dtd *dtd, DisplayModePtr mode)
     dtd->part1.v_high = (((height >> 8) & 0xf) << 4) |
 	((v_blank_len >> 8) & 0xf);
 
-    dtd->part2.h_sync_off = h_sync_offset;
+    dtd->part2.h_sync_off = h_sync_offset & 0xff;
     dtd->part2.h_sync_width = h_sync_len & 0xff;
     dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
 	(v_sync_len & 0xf);
@@ -724,27 +724,10 @@ i830_sdvo_get_dtd_from_mode(struct i830_sdvo_dtd *dtd, DisplayModePtr mode)
 static void
 i830_sdvo_get_mode_from_dtd(DisplayModePtr mode, struct i830_sdvo_dtd *dtd)
 {
-    uint16_t width, height;
-    uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
-    uint16_t h_sync_offset, v_sync_offset;
-
-    width = mode->CrtcHDisplay;
-    height = mode->CrtcVDisplay;
-
-    /* do some mode translations */
-    h_blank_len = mode->CrtcHBlankEnd - mode->CrtcHBlankStart;
-    h_sync_len = mode->CrtcHSyncEnd - mode->CrtcHSyncStart;
-
-    v_blank_len = mode->CrtcVBlankEnd - mode->CrtcVBlankStart;
-    v_sync_len = mode->CrtcVSyncEnd - mode->CrtcVSyncStart;
-
-    h_sync_offset = mode->CrtcHSyncStart - mode->CrtcHBlankStart;
-    v_sync_offset = mode->CrtcVSyncStart - mode->CrtcVBlankStart;
-
     mode->HDisplay = dtd->part1.h_active;
     mode->HDisplay += ((dtd->part1.h_high >> 4) & 0x0f) << 8;
     mode->HSyncStart = mode->HDisplay + dtd->part2.h_sync_off;
-    mode->HSyncStart += (dtd->part2.sync_off_width_high & 0xa0) << 2;
+    mode->HSyncStart += (dtd->part2.sync_off_width_high & 0xc0) << 2;
     mode->HSyncEnd = mode->HSyncStart + dtd->part2.h_sync_width;
     mode->HSyncEnd += (dtd->part2.sync_off_width_high & 0x30) << 4;
     mode->HTotal = mode->HDisplay + dtd->part1.h_blank;
@@ -754,7 +737,7 @@ i830_sdvo_get_mode_from_dtd(DisplayModePtr mode, struct i830_sdvo_dtd *dtd)
     mode->VDisplay += ((dtd->part1.v_high >> 4) & 0x0f) << 8;
     mode->VSyncStart = mode->VDisplay;
     mode->VSyncStart += (dtd->part2.v_sync_off_width >> 4) & 0xf;
-    mode->VSyncStart += (dtd->part2.sync_off_width_high & 0x0a) << 2;
+    mode->VSyncStart += (dtd->part2.sync_off_width_high & 0x0c) << 2;
     mode->VSyncStart += dtd->part2.v_sync_off_high & 0xc0;
     mode->VSyncEnd = mode->VSyncStart + (dtd->part2.v_sync_off_width & 0xf);
     mode->VSyncEnd += (dtd->part2.sync_off_width_high & 0x3) << 4;
@@ -763,7 +746,7 @@ i830_sdvo_get_mode_from_dtd(DisplayModePtr mode, struct i830_sdvo_dtd *dtd)
 
     mode->Clock = dtd->part1.clock * 10;
 
-    mode->Flags &= (V_PHSYNC | V_PVSYNC);
+    mode->Flags &= ~(V_PHSYNC | V_PVSYNC);
     if (dtd->part2.dtd_flags & 0x2)
 	mode->Flags |= V_PHSYNC;
     if (dtd->part2.dtd_flags & 0x4)
commit 37c67088a887e6380571e6eec8a8f058e3e24717
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Wed Feb 11 15:15:27 2009 +0800

    SDVO: check EDID info for DVI-I
    
    For SDVO DVI-I, check EDID info for digital output,
    otherwise mark it to be disconnected as analog output
    is driven by VGA then.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 1fbf8dc..508a467 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1507,7 +1507,9 @@ i830_sdvo_check_hdmi_encode (xf86OutputPtr output)
 static xf86OutputStatus
 i830_sdvo_detect(xf86OutputPtr output)
 {
-    uint8_t response[2];
+    I830OutputPrivatePtr intel_output = output->driver_private;
+    struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+    uint16_t response;
     uint8_t status;
 
     i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
@@ -1516,10 +1518,22 @@ i830_sdvo_detect(xf86OutputPtr output)
     if (status != SDVO_CMD_STATUS_SUCCESS)
 	return XF86OutputStatusUnknown;
 
-    if (response[0] != 0 || response[1] != 0)
-	return XF86OutputStatusConnected;
-    else
+    if (response == 0)
 	return XF86OutputStatusDisconnected;
+
+    if (response & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+    {
+	xf86MonPtr edid_mon;
+	/* Check EDID in DVI-I case */
+	i830_sdvo_set_control_bus_switch(output, dev_priv->ddc_bus);
+	edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+	if (!edid_mon || !DIGITAL(edid_mon->features.input_type)) {
+	    xfree(edid_mon);
+	    return XF86OutputStatusDisconnected;
+	}
+	xfree(edid_mon);
+    }
+    return XF86OutputStatusConnected;
 }
 
 static DisplayModePtr
commit 38079bc0f1038da77048bbf6e5c10758f9fb8a55
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Wed Feb 11 14:41:58 2009 +0800

    SDVO: Fix for HDMI encode and audio setup (try 5)
    
    SDVO HDMI encode and audio is not setup in detect,
    which fails in hotplug case for HDMI audio. Fix to
    check current encode type and set flag for HDMI audio
    enabling.
    
    Check and set HDMI encode state in get_modes.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 0750166..1fbf8dc 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -786,6 +786,24 @@ i830_sdvo_get_supp_encode(xf86OutputPtr output, struct i830_sdvo_encode *encode)
 }
 
 static Bool
+i830_sdvo_get_digital_encoding_mode(xf86OutputPtr output)
+{
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
+    uint8_t status;
+
+    i830_sdvo_set_target_output(output, dev_priv->controlled_output);
+
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_ENCODE, NULL, 0);
+    status = i830_sdvo_read_response(output, &dev_priv->is_hdmi, 1);
+    if (status != SDVO_CMD_STATUS_SUCCESS) {
+	dev_priv->is_hdmi = FALSE;
+	return FALSE;
+    }
+    return TRUE;
+}
+
+static Bool
 i830_sdvo_set_encode(xf86OutputPtr output, uint8_t mode)
 {
     uint8_t status;
@@ -1449,6 +1467,34 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
     }
 }
 
+static void
+i830_sdvo_set_hdmi_encode (xf86OutputPtr output)
+{
+    /* enable hdmi encoding mode if supported */
+    i830_sdvo_set_encode(output, SDVO_ENCODE_HDMI);
+    i830_sdvo_set_colorimetry(output, SDVO_COLORIMETRY_RGB256);
+}
+
+/**
+ * Determine if current TMDS encoding is HDMI.
+ * Return TRUE if found HDMI encoding is used, otherwise return FALSE.
+ */
+static Bool
+i830_sdvo_check_hdmi_encode (xf86OutputPtr output)
+{
+    I830OutputPrivatePtr intel_output = output->driver_private;
+    struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+    if (i830_sdvo_get_supp_encode(output, &dev_priv->encode) &&
+	    i830_sdvo_get_digital_encoding_mode(output) &&
+	    dev_priv->is_hdmi)
+    {
+	i830_sdvo_set_hdmi_encode(output);
+	return TRUE;
+    } else
+	return FALSE;
+}
+
 /**
  * Asks the SDVO device if any displays are currently connected.
  *
@@ -1485,10 +1531,11 @@ i830_sdvo_get_ddc_modes(xf86OutputPtr output)
     xf86OutputPtr crt;
     I830OutputPrivatePtr intel_output;
     xf86MonPtr edid_mon = NULL;
+    struct i830_sdvo_priv *dev_priv;
 
     modes = i830_ddc_get_modes(output);
     if (modes != NULL)
-	return modes;
+	goto check_hdmi;
 
     /* Mac mini hack.  On this device, I get DDC through the analog, which
      * load-detects as disconnected.  I fail to DDC through the SDVO DDC,
@@ -1508,6 +1555,23 @@ i830_sdvo_get_ddc_modes(xf86OutputPtr output)
 	modes = xf86OutputGetEDIDModes(output);
     }
 
+check_hdmi:
+    /* Check if HDMI encode, setup it and set the flag for HDMI audio */
+    intel_output = output->driver_private;
+    dev_priv = intel_output->dev_priv;
+
+    if (dev_priv->caps.output_flags & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+    {
+	if (!i830_sdvo_check_hdmi_encode(output)) {
+	    /* check EDID HDMI info for monitor */
+	    if (output->MonInfo && xf86LoaderCheckSymbol("xf86MonitorIsHDMI")
+		    && xf86MonitorIsHDMI(output->MonInfo)) {
+		dev_priv->is_hdmi = TRUE;
+		i830_sdvo_set_hdmi_encode (output);
+	    } else
+		dev_priv->is_hdmi = FALSE;
+	}
+    }
     return modes;
 }
 
@@ -1733,21 +1797,6 @@ i830_sdvo_select_ddc_bus(struct i830_sdvo_priv *dev_priv)
     dev_priv->ddc_bus = 1 << num_bits;
 }
 
-static Bool
-i830_sdvo_get_digital_encoding_mode(xf86OutputPtr output)
-{
-    I830OutputPrivatePtr    intel_output = output->driver_private;
-    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
-    uint8_t status;
-
-    i830_sdvo_set_target_output(output, dev_priv->controlled_output);
-
-    i830_sdvo_write_cmd(output, SDVO_CMD_GET_ENCODE, NULL, 0);
-    status = i830_sdvo_read_response(output, &dev_priv->is_hdmi, 1);
-    if (status != SDVO_CMD_STATUS_SUCCESS)
-	return FALSE;
-    return TRUE;
-}
 
 Bool
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
@@ -1876,14 +1925,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
         output->subpixel_order = SubPixelHorizontalRGB;
 	name_prefix="TMDS";
 
-	if (i830_sdvo_get_supp_encode(output, &dev_priv->encode) &&
-		i830_sdvo_get_digital_encoding_mode(output) &&
-		dev_priv->is_hdmi) {
-	    /* enable hdmi encoding mode if supported */
-	    i830_sdvo_set_encode(output, SDVO_ENCODE_HDMI);
-	    i830_sdvo_set_colorimetry(output, SDVO_COLORIMETRY_RGB256);
+	if (i830_sdvo_check_hdmi_encode (output))
 	    name_prefix = "HDMI";
-	}
     }
     else if (dev_priv->caps.output_flags & SDVO_OUTPUT_SVID0)
     {


More information about the xorg-commit mailing list