xf86-video-intel: 4 commits - src/i830_display.c src/i830.h src/i830_sdvo.c

Eric Anholt anholt at kemper.freedesktop.org
Wed Apr 9 15:23:46 PDT 2008


 src/i830.h         |    1 
 src/i830_display.c |    9 +-
 src/i830_sdvo.c    |  226 ++++++++++++++++++++++++++++++++++++++---------------
 3 files changed, 172 insertions(+), 64 deletions(-)

New commits:
commit 96ae9a9f0abc582e45ff4e17dd213c8739c24cb3
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Apr 9 14:17:29 2008 -0700

    SDVO: Rename output_dtd variable to input_dtd, which is its new job.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 3141cc9..2379127 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -808,7 +808,7 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
     uint32_t sdvox;
     int sdvo_pixel_multiply;
     struct i830_sdvo_in_out_map in_out;
-    struct i830_sdvo_dtd output_dtd;
+    struct i830_sdvo_dtd input_dtd;
     uint8_t status;
 
     if (!mode)
@@ -827,13 +827,15 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 			&in_out, sizeof(in_out));
     status = i830_sdvo_read_response(output, NULL, 0);
 
-    /* If it's a TV, we already set the output timing in mode_fixup. */
-    if (!dev_priv->is_tv) {
-	i830_sdvo_get_dtd_from_mode(&output_dtd, mode);
+    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.
+     */
+    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, &output_dtd);
+	i830_sdvo_set_output_timing(output, &input_dtd);
     }
 
     /* Set the input timing to the screen. Assume always input 0. */
@@ -854,7 +856,7 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 	i830_sdvo_set_input_timing(output, &input_dtd);
     }
 #else
-    i830_sdvo_set_input_timing(output, &output_dtd);
+    i830_sdvo_set_input_timing(output, &input_dtd);
 #endif
 
     switch (i830_sdvo_get_pixel_multiplier(mode)) {
commit 72c3995d5158286d20e97296f4552697f32f935f
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 8 15:00:18 2008 -0700

    SDVO: Set adjusted_mode in mode_fixup from the preferred input timings for TV.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index ecddbaf..3141cc9 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -557,13 +557,12 @@ i830_sdvo_set_output_timing(xf86OutputPtr output, struct i830_sdvo_dtd *dtd)
     return i830_sdvo_set_timing(output, SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
 }
 
-#if 0
 static Bool
 i830_sdvo_create_preferred_input_timing(xf86OutputPtr output, uint16_t clock,
 					uint16_t width, uint16_t height)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
     struct i830_sdvo_preferred_input_timing_args args;
+    uint8_t status;
 
     args.clock = clock;
     args.width = width;
@@ -578,10 +577,10 @@ i830_sdvo_create_preferred_input_timing(xf86OutputPtr output, uint16_t clock,
 }
 
 static Bool
-i830_sdvo_get_preferred_input_timing(I830OutputPtr output,
+i830_sdvo_get_preferred_input_timing(xf86OutputPtr output,
 				     struct i830_sdvo_dtd *dtd)
 {
-    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    Bool status;
 
     i830_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
 			NULL, 0);
@@ -599,7 +598,6 @@ i830_sdvo_get_preferred_input_timing(I830OutputPtr output,
 
     return TRUE;
 }
-#endif
 
 /** Returns the SDVO_CLOCK_RATE_MULT_* for the current clock multiplier */
 static int
@@ -644,14 +642,155 @@ i830_sdvo_set_clock_rate_mult(xf86OutputPtr output, uint8_t val)
     return TRUE;
 }
 
+static void
+i830_sdvo_get_dtd_from_mode(struct i830_sdvo_dtd *dtd, DisplayModePtr mode)
+{
+    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;
+
+    dtd->part1.clock = mode->Clock / 10;
+    dtd->part1.h_active = width & 0xff;
+    dtd->part1.h_blank = h_blank_len & 0xff;
+    dtd->part1.h_high = (((width >> 8) & 0xf) << 4) |
+	((h_blank_len >> 8) & 0xf);
+    dtd->part1.v_active = height & 0xff;
+    dtd->part1.v_blank = v_blank_len & 0xff;
+    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_width = h_sync_len & 0xff;
+    dtd->part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
+	(v_sync_len & 0xf);
+    dtd->part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) |
+	((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) |
+	((v_sync_len & 0x30) >> 4);
+
+    dtd->part2.dtd_flags = 0x18;
+    if (mode->Flags & V_PHSYNC)
+	dtd->part2.dtd_flags |= 0x2;
+    if (mode->Flags & V_PVSYNC)
+	dtd->part2.dtd_flags |= 0x4;
+
+    dtd->part2.sdvo_flags = 0;
+    dtd->part2.v_sync_off_high = v_sync_offset & 0xc0;
+    dtd->part2.reserved = 0;
+}
+
+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->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;
+    mode->HTotal += (dtd->part1.h_high & 0xf) << 8;
+
+    mode->VDisplay = dtd->part1.v_active;
+    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.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;
+    mode->VTotal = mode->VDisplay + dtd->part1.v_blank;
+    mode->VTotal += (dtd->part1.v_high & 0xf) << 8;
+
+    mode->Clock = dtd->part1.clock * 10;
+
+    mode->Flags &= (V_PHSYNC | V_PVSYNC);
+    if (dtd->part2.dtd_flags & 0x2)
+	mode->Flags |= V_PHSYNC;
+    if (dtd->part2.dtd_flags & 0x4)
+	mode->Flags |= V_PVSYNC;
+}
+
 static Bool
 i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode)
 {
-    /* Make the CRTC code factor in the SDVO pixel multiplier.  The SDVO
-     * device will be told of the multiplier during mode_set.
-     */
-    adjusted_mode->Clock *= i830_sdvo_get_pixel_multiplier(mode);
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
+
+    if (!dev_priv->is_tv) {
+	/* Make the CRTC code factor in the SDVO pixel multiplier.  The SDVO
+	 * device will be told of the multiplier during mode_set.
+	 */
+	adjusted_mode->Clock *= i830_sdvo_get_pixel_multiplier(mode);
+    } else {
+	struct i830_sdvo_dtd output_dtd;
+	Bool success;
+
+	/* We need to construct preferred input timings based on our output
+	 * timings.  To do that, we have to set the output timings, even
+	 * though this isn't really the right place in the sequence to do it.
+	 * Oh well.
+	 */
+
+	ErrorF("output modeline:\n");
+	xf86PrintModeline(0, mode);
+
+	/* Set output timings */
+	i830_sdvo_get_dtd_from_mode(&output_dtd, mode);
+	i830_sdvo_set_target_output(output, dev_priv->controlled_output);
+	i830_sdvo_set_output_timing(output, &output_dtd);
+
+	/* Set the input timing to the screen. Assume always input 0. */
+	i830_sdvo_set_target_input(output, TRUE, FALSE);
+
+
+	success = i830_sdvo_create_preferred_input_timing(output,
+							  mode->Clock / 10,
+							  mode->HDisplay,
+							  mode->VDisplay);
+	if (success) {
+	    struct i830_sdvo_dtd input_dtd;
+
+	    i830_sdvo_get_preferred_input_timing(output, &input_dtd);
+
+	    i830_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
+
+	    ErrorF("input modeline:\n");
+	    xf86PrintModeline(0, adjusted_mode);
+	} else {
+	    return FALSE;
+	}
+    }
 
     return TRUE;
 }
@@ -668,9 +807,6 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
     I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
     uint32_t sdvox;
     int sdvo_pixel_multiply;
-    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;
     struct i830_sdvo_in_out_map in_out;
     struct i830_sdvo_dtd output_dtd;
     uint8_t status;
@@ -691,50 +827,14 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 			&in_out, sizeof(in_out));
     status = i830_sdvo_read_response(output, NULL, 0);
 
-    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;
+    /* If it's a TV, we already set the output timing in mode_fixup. */
+    if (!dev_priv->is_tv) {
+	i830_sdvo_get_dtd_from_mode(&output_dtd, mode);
 
-    output_dtd.part1.clock = mode->Clock / 10;
-    output_dtd.part1.h_active = width & 0xff;
-    output_dtd.part1.h_blank = h_blank_len & 0xff;
-    output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) |
-	((h_blank_len >> 8) & 0xf);
-    output_dtd.part1.v_active = height & 0xff;
-    output_dtd.part1.v_blank = v_blank_len & 0xff;
-    output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) |
-	((v_blank_len >> 8) & 0xf);
-
-    output_dtd.part2.h_sync_off = h_sync_offset;
-    output_dtd.part2.h_sync_width = h_sync_len & 0xff;
-    output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
-	(v_sync_len & 0xf);
-    output_dtd.part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) |
-	((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) |
-	((v_sync_len & 0x30) >> 4);
-
-    output_dtd.part2.dtd_flags = 0x18;
-    if (mode->Flags & V_PHSYNC)
-	output_dtd.part2.dtd_flags |= 0x2;
-    if (mode->Flags & V_PVSYNC)
-	output_dtd.part2.dtd_flags |= 0x4;
-
-    output_dtd.part2.sdvo_flags = 0;
-    output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0;
-    output_dtd.part2.reserved = 0;
-
-    /* Set the output timing to the screen */
-    i830_sdvo_set_target_output(output, dev_priv->controlled_output);
-    i830_sdvo_set_output_timing(output, &output_dtd);
+	/* Set the output timing to the screen */
+	i830_sdvo_set_target_output(output, dev_priv->controlled_output);
+	i830_sdvo_set_output_timing(output, &output_dtd);
+    }
 
     /* Set the input timing to the screen. Assume always input 0. */
     i830_sdvo_set_target_input(output, TRUE, FALSE);
commit b61178524bece756dc0fd4f798c6c7743b5725db
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 8 14:11:42 2008 -0700

    SDVO: Fix lols TV mode list handling.

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index e25de3a..ecddbaf 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1208,12 +1208,11 @@ i830_sdvo_get_tv_mode(DisplayModePtr *head, int width, int height,
     mode->next = NULL;
     mode->prev = NULL;
 
-    mode->next = NULL;
-    mode->prev = *head;
+    mode->next = *head;
+    mode->prev = NULL;
     if (*head != NULL)
-	(*head)->next = mode;
-    else
-	*head = mode;
+	(*head)->prev = mode;
+    *head = mode;
 }
 
 /**
commit 5db73f18d2badec37523850024b9aa824e4e6bd8
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 8 13:53:51 2008 -0700

    SDVO: Use the TV reference clock for SDVO TV outputs.
    
    Based on a patch by Will Wiseman.

diff --git a/src/i830.h b/src/i830.h
index 834e4dc..318b188 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -288,6 +288,7 @@ typedef struct _I830OutputPrivateRec {
    I2CBusPtr		    pDDCBus;
    struct _I830DVODriver    *i2c_drv;
    Bool			    load_detect_temp;
+   Bool			    needs_tv_clock;
    uint32_t		    lvds_bits;
    int                      pipe_mask;
    int			    clone_mask;
diff --git a/src/i830_display.c b/src/i830_display.c
index 4091e79..ca5e5dc 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -1100,6 +1100,8 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	    break;
 	case I830_OUTPUT_SDVO:
 	    is_sdvo = TRUE;
+	    if (intel_output->needs_tv_clock)
+		is_tv = TRUE;
 	    break;
 	case I830_OUTPUT_DVO_TMDS:
 	case I830_OUTPUT_DVO_LVDS:
@@ -1144,7 +1146,8 @@ 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))
+	    if ((IS_I945G(pI830) || IS_I945GM(pI830) || IS_G33CLASS(pI830)) &&
+		!is_tv)
 	    {
 		int sdvo_pixel_multiply = adjusted_mode->Clock / mode->Clock;
 		dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
@@ -1182,7 +1185,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
 	}
     }
 
-    if (is_tv)
+    if (is_sdvo && is_tv)
+	dpll |= PLL_REF_INPUT_TVCLKINBC;
+    else if (is_tv)
     {
 	/* XXX: just matching BIOS for now */
 /*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 642ba88..e25de3a 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1535,6 +1535,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
         output->subpixel_order = SubPixelHorizontalRGB; /* XXX */
 	name_prefix="TV";
 	dev_priv->is_tv = TRUE;
+	intel_output->needs_tv_clock = TRUE;
     }
     else if (dev_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
     {


More information about the xorg-commit mailing list