[Intel-gfx] [PATCH] SDVO: Fix TV support

Zhenyu Wang zhenyu.z.wang at intel.com
Fri Feb 13 07:05:39 CET 2009


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.
---
 src/i830_display.c |   25 ++++++++++++++++++--
 src/i830_sdvo.c    |   63 +++++++++++++++++++++++++++++++++++----------------
 2 files changed, 65 insertions(+), 23 deletions(-)

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));
 }
 
-- 
1.5.6.5




More information about the Intel-gfx mailing list