Hi list,

with the attached patch and xorg.conf you can use Intel i9xx chipsets to
directly drive RGB/PAL SCART devices like a TV set.

As with my former Radeon vga-sync-fields patch even/odd fields are routed
straightly from softdecoder to the VGA port. No software deinterlacing
takes place anymore thus saving CPU power and resulting in an artifact free
picture.

Full synchronicity between video stream and VGA video output timing is
provided by tiny real-time tweaks to the VGA video timing registers.

This is what FRC stands for: (f)rame (r)ate (c)ontrol

Please see attached explanation file how synchronization locks in after 
starting video replay.

All you additionally need is a special VGA2SCART adapter cable like this:

http://www.vdr-portal.de/board/thread.php?postid=742945#post742945

At least Intel i910 i915 i945 chipsets are known to be compatible with 
the patch. These chips are found in recent hardware like Intel D945GCLF
or Asus Pundit P5945GC including many netbooks. 

You can build a cheap but high quality video replay device with that.

For further reference about frame rate control please see also:

http://linuxtv.org/pipermail/vdr/2008-July/017347.html
http://lists.freedesktop.org/archives/xorg/2008-September/038296.html

Cheers,
  Thomas

diff -ur ../xserver-xorg-video-intel-2.3.2.org/src/i810_driver.c ./src/i810_driver.c
--- ../xserver-xorg-video-intel-2.3.2.org/src/i810_driver.c	2009-02-09 21:28:24.000000000 +0100
+++ ./src/i810_driver.c	2009-02-09 21:31:00.000000000 +0100
@@ -262,7 +262,11 @@
    OPTION_NO_DDC,
    OPTION_SHOW_CACHE,
    OPTION_XVMC_SURFACES,
-   OPTION_PAGEFLIP
+   OPTION_PAGEFLIP,
+   OPTION_SYNC_FIELDS,
+   OPTION_YSCALE_FTUNE,
+   OPTION_YRGB_VPHASE,
+   OPTION_UV_VPHASE,
 } I810Opts;
  
 static const OptionInfoRec I810Options[] = {
@@ -275,7 +279,11 @@
    {OPTION_NO_DDC,		"NoDDC",	OPTV_BOOLEAN,	{0}, FALSE},
    {OPTION_SHOW_CACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE},
    {OPTION_XVMC_SURFACES,	"XvMCSurfaces",	OPTV_INTEGER,	{0}, FALSE},
-   {OPTION_PAGEFLIP,            "PageFlip",     OPTV_BOOLEAN, {0},   FALSE},
+   {OPTION_PAGEFLIP,            "PageFlip",     OPTV_BOOLEAN,	{0}, FALSE},
+   {OPTION_SYNC_FIELDS,		"SyncFields",	OPTV_BOOLEAN,	{0}, FALSE},
+   {OPTION_YSCALE_FTUNE,	"YScaleFineTune",OPTV_INTEGER,	{0}, FALSE},
+   {OPTION_YRGB_VPHASE,		"YRGB_VPhase",	OPTV_INTEGER,	{0}, FALSE},
+   {OPTION_UV_VPHASE,		"UV_VPhase",	OPTV_INTEGER,	{0}, FALSE},
    {-1,				NULL,		OPTV_NONE,	{0}, FALSE}
 };
 /* *INDENT-ON* */
@@ -2861,7 +2869,9 @@
 	 xf86DrvMsg(scrnIndex, X_PROBED,
 		    "Removing interlaced mode \"%s\"\n", mode->name);
       }
+#if 0 /* allow interlaced mode */
       return MODE_BAD;
+#endif
    }
    return MODE_OK;
 }
diff -ur ../xserver-xorg-video-intel-2.3.2.org/src/i830.h ./src/i830.h
--- ../xserver-xorg-video-intel-2.3.2.org/src/i830.h	2009-02-09 21:29:41.000000000 +0100
+++ ./src/i830.h	2009-02-09 21:31:00.000000000 +0100
@@ -524,6 +524,11 @@
    Bool *overlayOn;
 #endif
 
+   Bool sync_fields;
+   int YScale_ftune;
+   int YRGB_vphase;
+   int UV_vphase;
+
    /* EXA render state */
    float scale_units[2][2];
   /** Transform pointers for src/mask, or NULL if identity */
diff -ur ../xserver-xorg-video-intel-2.3.2.org/src/i830_crt.c ./src/i830_crt.c
--- ../xserver-xorg-video-intel-2.3.2.org/src/i830_crt.c	2009-02-09 21:28:24.000000000 +0100
+++ ./src/i830_crt.c	2009-02-09 21:31:00.000000000 +0100
@@ -87,7 +87,7 @@
     if (pMode->Flags & V_DBLSCAN)
 	return MODE_NO_DBLESCAN;
 
-    if (pMode->Clock > 400000 || pMode->Clock < 25000)
+    if (pMode->Clock > 400000 || pMode->Clock < 12000) /* lower minimum dotclk */
 	return MODE_CLOCK_RANGE;
 
     return MODE_OK;
@@ -392,6 +392,12 @@
 out:
     i830ReleaseLoadDetectPipe (output, dpms_mode);
 
+#if 0 /* not yet */
+    /*
+     * we also want to boot the Xserver without a CRT connected
+     */
+    status = XF86OutputStatusConnected;
+#endif
     return status;
 }
 
diff -ur ../xserver-xorg-video-intel-2.3.2.org/src/i830_display.c ./src/i830_display.c
--- ../xserver-xorg-video-intel-2.3.2.org/src/i830_display.c	2009-02-09 21:28:24.000000000 +0100
+++ ./src/i830_display.c	2009-02-09 21:31:00.000000000 +0100
@@ -95,9 +95,9 @@
 #define I8XX_P2_LVDS_FAST	      7
 #define I8XX_P2_SLOW_LIMIT	 165000
 
-#define I9XX_DOT_MIN		  20000
+#define I9XX_DOT_MIN		  12000 /* allow for PAL modes */
 #define I9XX_DOT_MAX		 400000
-#define I9XX_VCO_MIN		1400000
+#define I9XX_VCO_MIN		1000000 /* allow for PAL modes */
 #define I9XX_VCO_MAX		2800000
 
 /* Haven't found any reason to go this fast, but newer chips support it */
@@ -964,6 +964,14 @@
 i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode)
 {
+    if (mode->Flags & V_INTERLACE) {
+       mode->CrtcVDisplay = adjusted_mode->CrtcVDisplay = mode->VDisplay;
+       mode->CrtcVSyncStart = adjusted_mode->CrtcVSyncStart = mode->VSyncStart;
+       mode->CrtcVSyncEnd = adjusted_mode->CrtcVSyncEnd = mode->VSyncEnd;
+       mode->CrtcVBlankStart = adjusted_mode->CrtcVBlankStart = mode->CrtcVDisplay;
+       mode->CrtcVBlankEnd = adjusted_mode->CrtcVBlankEnd = mode->VTotal;
+       mode->CrtcVTotal = adjusted_mode->CrtcVTotal = mode->VTotal;
+    }
     return TRUE;
 }
 
@@ -1355,6 +1363,11 @@
     /* Wait for the clocks to stabilize. */
     usleep(150);
 
+    if (adjusted_mode->Flags & V_INTERLACE) {
+       pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
+    } else {
+       pipeconf &= ~PIPECONF_INTERLACE_W_FIELD_INDICATION;
+    }
     OUTREG(htot_reg, (adjusted_mode->CrtcHDisplay - 1) |
 	((adjusted_mode->CrtcHTotal - 1) << 16));
     OUTREG(hblank_reg, (adjusted_mode->CrtcHBlankStart - 1) |
diff -ur ../xserver-xorg-video-intel-2.3.2.org/src/i830_driver.c ./src/i830_driver.c
--- ../xserver-xorg-video-intel-2.3.2.org/src/i830_driver.c	2009-02-09 21:29:41.000000000 +0100
+++ ./src/i830_driver.c	2009-02-09 21:31:00.000000000 +0100
@@ -319,6 +319,10 @@
 #ifdef INTEL_XVMC
    OPTION_XVMC,
 #endif
+   OPTION_SYNC_FIELDS,
+   OPTION_YSCALE_FTUNE,
+   OPTION_YRGB_VPHASE,
+   OPTION_UV_VPHASE,
    OPTION_RENDERACCEL,
 } I830Opts;
 
@@ -348,6 +352,10 @@
 #ifdef INTEL_XVMC
    {OPTION_XVMC,	"XvMC",		OPTV_BOOLEAN,	{0},	TRUE},
 #endif
+   {OPTION_SYNC_FIELDS,	"SyncFields",	OPTV_BOOLEAN,	{0},	FALSE},
+   {OPTION_YSCALE_FTUNE,"YScaleFineTune",OPTV_INTEGER,	{0},	FALSE},
+   {OPTION_YRGB_VPHASE,	"YRGB_VPhase",	OPTV_INTEGER,	{0},	FALSE},
+   {OPTION_UV_VPHASE,	"UV_VPhase",	OPTV_INTEGER,	{0},	FALSE},
    {OPTION_RENDERACCEL, "RenderAccel",	OPTV_BOOLEAN,	{0},	TRUE},
    {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
 };
@@ -1711,6 +1719,43 @@
 	      pI830->colorKey);
 #endif
 
+   if (xf86GetOptValInteger(pI830->Options, OPTION_SYNC_FIELDS,
+			    &(pI830->sync_fields))) {
+      from = X_CONFIG;
+   } else {
+      pI830->sync_fields = TRUE;
+      from = X_DEFAULT;
+   }
+   xf86DrvMsg(pScrn->scrnIndex, from, "sync fields %sactivated\n",
+	      pI830->sync_fields ? "" : "de");
+   if (xf86GetOptValInteger(pI830->Options, OPTION_YSCALE_FTUNE,
+			    &(pI830->YScale_ftune))) {
+      from = X_CONFIG;
+   } else {
+      pI830->YScale_ftune = 0;
+      from = X_DEFAULT;
+   }
+   xf86DrvMsg(pScrn->scrnIndex, from, "vertical scale fine tuning set to %d\n",
+	      pI830->YScale_ftune);
+   if (xf86GetOptValInteger(pI830->Options, OPTION_YRGB_VPHASE,
+			    &(pI830->YRGB_vphase))) {
+      from = X_CONFIG;
+   } else {
+      pI830->YRGB_vphase = 0;
+      from = X_DEFAULT;
+   }
+   xf86DrvMsg(pScrn->scrnIndex, from, "Y/RGB vertical phase set to 0x%x\n",
+	      pI830->YRGB_vphase);
+   if (xf86GetOptValInteger(pI830->Options, OPTION_UV_VPHASE,
+			    &(pI830->UV_vphase))) {
+      from = X_CONFIG;
+   } else {
+      pI830->UV_vphase = 0;
+      from = X_DEFAULT;
+   }
+   xf86DrvMsg(pScrn->scrnIndex, from, "UV vertical phase set to 0x%x\n",
+	      pI830->UV_vphase);
+
 #ifdef XF86DRI
    pI830->allowPageFlip = FALSE;
    from = (!pI830->directRenderingDisabled &&
@@ -1795,6 +1840,24 @@
    /* Set display resolution */
    xf86SetDpi(pScrn, 0, 0);
 
+   if (!(pScrn->currentMode->Flags & V_INTERLACE)
+    && pI830->sync_fields) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support sync fields on non interlaced displays, disabled\n");
+      pI830->sync_fields = 0;
+   }
+
+   /*
+    * sync_fields only works with
+    * ModeLine  "1440x576_50i"     27.75   1440 1488 1609 1769   576  580  585  625  -hsync -vsync interlace
+    */
+   if ((pScrn->currentMode->Clock != 27750
+    ||  pScrn->currentMode->HDisplay != 1440
+    ||  pScrn->currentMode->VDisplay != 576)
+    && pI830->sync_fields) {
+      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot support sync fields with current timing, disabled\n");
+      pI830->sync_fields = 0;
+   }
+
    /* Load the required sub modules */
    if (!xf86LoadSubModule(pScrn, "fb")) {
       PreInitCleanup(pScrn);
diff -ur ../xserver-xorg-video-intel-2.3.2.org/src/i830_video.c ./src/i830_video.c
--- ../xserver-xorg-video-intel-2.3.2.org/src/i830_video.c	2009-02-09 21:28:24.000000000 +0100
+++ ./src/i830_video.c	2009-02-09 21:31:00.000000000 +0100
@@ -94,6 +94,7 @@
 
 #define TIMER_MASK      (OFF_TIMER | FREE_TIMER)
 
+static void vga_sync_fields(I830Ptr);
 static void I830InitOffscreenImages(ScreenPtr);
 
 static XF86VideoAdaptorPtr I830SetupImageVideoOverlay(ScreenPtr);
@@ -603,19 +604,35 @@
     xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
     xvContrast = MAKE_ATOM("XV_CONTRAST");
 
-    /* Set up textured video if we can do it at this depth and we are on
-     * supported hardware.
-     */
-    if (pScrn->bitsPerPixel >= 16 && (IS_I9XX(pI830) || IS_I965G(pI830)) &&
-	!(!IS_I965G(pI830) && pScrn->displayWidth > 2048))
-    {
-	texturedAdaptor = I830SetupImageVideoTextured(pScreen);
-	if (texturedAdaptor != NULL) {
-	    adaptors[num_adaptors++] = texturedAdaptor;
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
-	} else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to set up textured video\n");
+#if 0 /* always use overlay */
+    if (pI830->sync_fields) {
+#else
+    if (1) {
+#endif
+	/*
+	 * we deactivate textured XV method for compatibility with older xine-lib
+	 * versions not providing a configuration parameter for this.
+	 * for further information see:
+	 * 'video.device.xv_preferred_method' in file 'config_xineliboutput'
+	 */
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGA_SYNC_FIELDS disabled textured video mode\n");
+    } else {
+
+	/*
+	 * Set up textured video if we can do it at this depth and we are on
+	 * supported hardware.
+	 */
+	if (pScrn->bitsPerPixel >= 16 && (IS_I9XX(pI830) || IS_I965G(pI830)) &&
+	    !(!IS_I965G(pI830) && pScrn->displayWidth > 2048))
+	{
+	    texturedAdaptor = I830SetupImageVideoTextured(pScreen);
+	    if (texturedAdaptor != NULL) {
+		adaptors[num_adaptors++] = texturedAdaptor;
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n");
+	    } else {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Failed to set up textured video\n");
+	    }
 	}
     }
 
@@ -2013,7 +2030,11 @@
 	 * Y down-scale factor as a multiple of 4096.
 	 */
 	xscaleFract = ((src_w - 1) << 12) / drw_w;
-	yscaleFract = ((src_h - 1) << 12) / drw_h;
+	if (pI830->sync_fields) {
+	    yscaleFract = (((src_h >> 1) - 1 + pI830->YScale_ftune) << 12) / drw_h;
+	} else {
+	    yscaleFract = ((src_h - 1) << 12) / drw_h;
+	}
 
 	/* Calculate the UV scaling factor. */
 	xscaleFractUV = xscaleFract / uvratio;
@@ -2113,9 +2134,15 @@
 	    }
 	}
     }
-
-    OCMD = OVERLAY_ENABLE;
-    
+    if (pI830->sync_fields) {
+	OCMD = OVERLAY_ENABLE | BUF_TYPE_FIELD | TVSYNC_FLIP_ENABLE;
+	overlay->YRGB_VPH = pI830->YRGB_vphase;
+	overlay->UV_VPH   = pI830->UV_vphase;
+	overlay->HORZ_PH  = 0;
+	overlay->INIT_PHS = 0;
+    } else {
+	OCMD = OVERLAY_ENABLE;
+    }
     switch (id) {
     case FOURCC_YV12:
     case FOURCC_I420:
@@ -2145,7 +2172,6 @@
 	    OCMD |= Y_SWAP;
 	break;
     }
-
     OCMD &= ~(BUFFER_SELECT | FIELD_SELECT);
     if (pPriv->currentBuf == 0)
 	OCMD |= BUFFER0;
@@ -2525,6 +2551,9 @@
     }
 
     if (!pPriv->textured) {
+	if (pI830->sync_fields) {
+	    vga_sync_fields(RecPtr);
+	}
 	i830_display_video(pScrn, crtc, destId, width, height, dstPitch,
 			   x1, y1, x2, y2, &dstBox, src_w, src_h,
 			   drw_w, drw_h);
@@ -2964,3 +2993,315 @@
 	pPriv->oneLineMode = FALSE;
     }
 }
+
+/* --- 8< --- */
+/*
+ * field cycle duration in usecs for PAL
+ */
+#define SYF_PAL_FIELD_CYCLE 20000
+
+/*
+ * frame cycle duration in usecs for PAL
+ */
+#define SYF_PAL_FRAME_CYCLE (SYF_PAL_FIELD_CYCLE << 1)
+
+/*
+ * dependent on interlaced (progressive) input frame rate 25 (50) fps
+ * we set this to 0 (1). other params should adjust accordingly.
+ */
+#define SYF_INPUT_DOUBLE_RATE 0
+
+/*
+ * prefilter to prevent stray updates.
+ * our software PLL will not try to lock for these.
+ */
+#define SYF_CATCH_RANGE (18000 >> SYF_INPUT_DOUBLE_RATE)
+
+/*
+ * updates outside time window defined by this
+ * value spawn warnings when in debug mode
+ */
+#define SYF_WARN_RANGE (15000 >> SYF_INPUT_DOUBLE_RATE)
+
+/*
+ * we average 25 (50) frames to yield a cycle time of
+ * about one second for analysis of frame rate data.
+ * this serves as frequency divider for our software PLL.
+ */
+#define SYF_PLL_DIVIDER (25 << SYF_INPUT_DOUBLE_RATE)
+
+/*
+ * input frame cycle duration in usecs for 25 (50) fps
+ */
+#define SYF_FRAME_CYCLE (SYF_PAL_FRAME_CYCLE >> SYF_INPUT_DOUBLE_RATE)
+
+/*
+ * offset in usecs from double buffer switch where we try to place double
+ * buffer updates. 
+ * this minimizes sensivity to jitter of our software PLL phase comparator.
+ */
+#define SYF_SYNC_POINT (SYF_FRAME_CYCLE >> 1)
+
+/*
+ * one trim increment compensates drift speed for about 29usec/sec.
+ * this represents resolution of our VCO input. 
+ */
+#define SYF_MIN_STEP_USEC 700
+
+/* NOT CURRENTLY USED
+ * factor weighting drift against sync point displacement
+ * when calculating overall compensation 
+ */
+#define SYF_DISP_DRIFT_FACTOR 1
+
+/* NOT CURRENTLY USED
+ * to allow for smooth adaption also on slower devices we delimit maximum
+ * trim change per step size.
+ * this implements some kind of low pass filter for our VCO input.
+ */
+#define SYF_MAX_TRIM_REL 1000
+
+/*
+ * maximum absolute trim values allowed due to current
+ * hardware/driver contraints.
+ * this delimits 'maximum voltage' controlling our VCO.
+ * currently allowed range is defined symmetrically around the center voltage.
+ */
+#define SYF_MAX_TRIM_ABS 2
+
+#define DEBUG
+#ifdef DEBUG
+#define ERRORF ErrorF
+#else
+#define ERRORF(...)
+#endif
+
+#define USE_METER
+#ifdef USE_METER
+#define OUT_GRAPHIC meter_out
+extern void meter_out(int, int);
+#else
+#define OUT_GRAPHIC(...)
+#endif
+
+#ifdef STANDALONE
+
+#define DOVSTA          0x30008
+#define HTOTAL_A        0x60000
+#define HBLANK_A        0x60004
+#define HSYNC_A         0x60008
+#define PIPEA_DSL       0x70000
+#define PIPEACONF       0x70008
+
+#define ErrorF printf
+#define B(a) (*(argv + (a)) ? *(argv + (a)) : 0)
+#define INREG(reg) *(volatile unsigned *)(vptr + (reg))
+#define OUTREG(reg, val) INREG(reg) = (val)
+#define min(a, b) ((a) <= (b) ? (a) : (b))
+#define max(a, b) ((a) >= (b) ? (a) : (b))
+#define abs(a) ((a) >= 0 ? (a) : -(a))
+#else
+#define B(a) (a)
+#endif
+#define OC_FIELD (1 << 19)
+
+#include <sys/time.h>
+#include <unistd.h>
+
+typedef struct _syf {
+    int cnt; 
+    int tsum; 
+    int trim; 
+    int drift; 
+    int spoint;
+} syf_t;
+
+typedef struct _drm_i945_syncf {
+    struct timeval tv_now;
+    struct timeval tv_vbl;
+    unsigned trim;
+} drm_i945_syncf_t;
+
+#define VSF_SUB(a, b, c) \
+    if ((a).tv_usec < (b).tv_usec) { \
+	(c).tv_sec = (a).tv_sec - (b).tv_sec - 1; \
+	(c).tv_usec = (a).tv_usec - (b).tv_usec + 1000000; \
+    } else { \
+	(c).tv_sec = (a).tv_sec - (b).tv_sec; \
+	(c).tv_usec = (a).tv_usec - (b).tv_usec; \
+    }
+
+#define VSF_TV2USEC(a, b) \
+    (b) = (a).tv_sec * 1000000 + (a).tv_usec;
+
+/*
+ * following values are hardcoded at the moment. they only work with 
+ * the modeline given below. though they appear to comply with 
+ * various i945 based motherboard designs.
+ *
+ * ModeLine "1440x576_50i"  27.75  1440 1488 1609 1769  576 580 585 625  -hsync -vsync interlace
+ */
+#define HTOTAL_A_OPT  0x06e8059f
+#define HSYNC_A_OPT   0x064805cf
+
+void
+meter_out(val, symb)
+{
+    static char meter[81];
+    static char headr[81] = "|<- -20ms                               0                              +20ms ->|";
+
+    if (!symb || symb == 1) {
+	if (!symb) ErrorF("%s", headr);
+        if (symb == 1) ErrorF("%s", meter);
+        memset(meter, '-', 80);
+        return;
+    }
+    val /= 500;
+    val = min(val,  39);
+    val = max(val, -40);
+    meter[40 + val] = symb;
+}
+/* --- 8< --- */
+
+void
+vga_sync_fields(RecPtr)
+    I830Ptr RecPtr;
+{
+    static syf_t syf, syf_clear;
+    static drm_i945_syncf_t syncf_prev;
+    static struct timeval skew2vbl_prev;
+
+    drm_i945_syncf_t syncf;
+    struct timeval skew2vbl;
+    struct timeval tv_usecs;
+    int usecs;
+    int dovsta, pipea_dsl;
+
+/* --- 8< --- */
+        syncf.trim = (INREG(HTOTAL_A) >> 16) - (HTOTAL_A_OPT >> 16);
+        gettimeofday(&syncf.tv_now, 0);
+
+        /*
+         *  DOVSTA 0x00104000 => PIPEA_DSL 0x0000011e
+         *  DOVSTA 0x80085000 => PIPEA_DSL 0x0000011f
+         *  [...]
+         *  DOVSTA 0x80104000 => PIPEA_DSL 0x00000138
+         *  DOVSTA 0x80104000 => PIPEA_DSL 0x00000000
+         *
+         *  the chip does not provide current field status directly.
+         *  but we can derive that from xor'ed dovsta and pipea_dsl contents.
+         *      _______________                 ________
+         * ____|               |_______________|         dovsta
+         *      ___             ___             ___
+         * ____|   |___________|   |___________|   |____ pipea_dsl
+         *          _______________                 ____
+         * ________|               |_______________|     field status
+         *
+         *         0          286 312
+         */
+
+#define FIELD_SWITCH_THRESHOLD 287
+
+        /* field * 20000 + line * 64 == 39968 max. for field==1, line==312 */
+	dovsta = INREG(DOVSTA);
+	pipea_dsl = INREG(PIPEA_DSL);
+        skew2vbl.tv_usec =
+		  (pipea_dsl < FIELD_SWITCH_THRESHOLD ^ !(dovsta & OC_FIELD))
+		  * SYF_PAL_FIELD_CYCLE + (pipea_dsl << 6);
+	skew2vbl.tv_sec = 0;
+	VSF_SUB(syncf.tv_now, skew2vbl, syncf.tv_vbl);
+	VSF_SUB(syncf.tv_now, syncf_prev.tv_now, tv_usecs);
+	VSF_TV2USEC(tv_usecs, usecs);
+#ifdef STANDALONE
+	if (syncf_prev.tv_now.tv_sec) {
+	    usleepv += SYF_FRAME_CYCLE - usecs;
+	}
+#endif
+	syncf_prev = syncf;
+	if (abs(usecs - SYF_FRAME_CYCLE) > SYF_CATCH_RANGE) {
+
+	    /*
+	     * toss stray intervals and reset
+	     */
+	    syf = syf_clear;
+	    skew2vbl_prev.tv_sec = ~0;
+            OUT_GRAPHIC(0, 0);
+	    ErrorF("      R               %11d\n", usecs);
+#ifdef STANDALONE
+	    goto main_loop_end;
+#else
+	    return;
+#endif
+	}
+	if (abs(usecs - SYF_FRAME_CYCLE) > SYF_WARN_RANGE) {
+            OUT_GRAPHIC(0, 0);
+	    ErrorF("      W               %11d\n", usecs);
+	}
+
+#ifndef STANDALONE
+
+        /*
+         * we must delay the next double buffer update
+         * until even field has been processed. this occurs
+         * after scan line FIELD_SWITCH_THRESHOLD has been passed.
+         * on a sufficiently synchronized system running at a
+         * sync point of about 20000 usecs this imposes
+         * no additional sleep time.
+         *
+         *  0      even       20000      odd      40000
+         *  |-------------------|-------------------|
+         *    ...---sleep--->|
+         *                 18368
+         */
+        if (skew2vbl.tv_usec < FIELD_SWITCH_THRESHOLD << 6) {
+            usleep((FIELD_SWITCH_THRESHOLD << 6) - skew2vbl.tv_usec);
+        }
+#endif
+	VSF_SUB(syncf.tv_now, syncf.tv_vbl, skew2vbl)
+	if (skew2vbl_prev.tv_sec != ~0) {
+	    syf.tsum += usecs;
+	    syf.spoint += skew2vbl.tv_usec - SYF_SYNC_POINT;
+	    VSF_SUB(skew2vbl, skew2vbl_prev, tv_usecs);
+	    VSF_TV2USEC(tv_usecs, usecs);
+	    syf.drift += usecs;
+	    ++syf.cnt;
+	}
+	if (skew2vbl_prev.tv_sec != ~0 && !(syf.cnt % SYF_PLL_DIVIDER)) {
+	    syf.spoint /= SYF_PLL_DIVIDER;
+            OUT_GRAPHIC(0, '+');
+            OUT_GRAPHIC(syf.spoint, '|');
+            OUT_GRAPHIC(syf.drift, '*');
+            OUT_GRAPHIC(0, 1);
+
+	    syf.trim = (syf.drift + syf.spoint / SYF_DISP_DRIFT_FACTOR) / SYF_MIN_STEP_USEC;
+	    syf.trim = max(syf.trim, -SYF_MAX_TRIM_REL);
+	    syf.trim = min(syf.trim,  SYF_MAX_TRIM_REL);
+	    ERRORF("%7d %7d [%3d%+4d] %7d\n", syf.drift, syf.spoint, 
+	    			(char)(syncf.trim & 0xff), syf.trim, syf.tsum);
+	    syf.spoint = 0;
+	    syf.drift = 0;
+	    syf.tsum = 0;
+	}
+        if (B(1) && syf.trim) {
+            int t = (char)(syncf.trim & 0xff);
+
+            if (syf.trim > 0) {
+                t = min(t + 1,  SYF_MAX_TRIM_ABS);
+                --syf.trim;
+            } else {
+                t = max(t - 1, -SYF_MAX_TRIM_ABS);
+                ++syf.trim;
+            }
+	    if (syncf.trim != t) {
+		t <<= 16;
+                OUTREG(HTOTAL_A,  HTOTAL_A_OPT + t);
+                OUTREG(HBLANK_A,  HTOTAL_A_OPT + t);
+                OUTREG(HSYNC_A,   HSYNC_A_OPT  + (t << 1));
+                OUTREG(PIPEACONF, INREG(PIPEACONF));
+	    }
+	}
+        skew2vbl_prev = skew2vbl;
+/* --- 8< --- */
+
+}
+
Section "ServerLayout"
        Identifier     "X.org Configured"
        Screen      0  "Screen0" 0 0
        InputDevice    "Mouse0" "CorePointer"
        InputDevice    "Keyboard0" "CoreKeyboard"

        Option "BlankTime"   "0"
        Option "StandbyTime" "0"
        Option "SuspendTime" "0"
        Option "OffTime"     "0"
EndSection

Section "Files"
        RgbPath      "/etc/X11/rgb"
        ModulePath   "/usr/lib/xorg/modules"
        FontPath     "/usr/share/fonts/X11/misc"
EndSection

Section "Module"
        Load  "extmod"
        Load  "xtrap"
        Load  "GLcore"
        Load  "dbe"
        Load  "record"
        Load  "dri"
        Load  "glx"
EndSection

Section "InputDevice"
        Identifier  "Keyboard0"
        Driver      "kbd"
EndSection

Section "InputDevice"
        Identifier  "Mouse0"
        Driver      "mouse"
        Option      "Protocol" "auto"
        Option      "Device" "/dev/input/mice"
        Option      "ZAxisMapping" "4 5 6 7"
EndSection

Section "Monitor"
        Identifier   "Monitor0"
        VendorName   "Monitor Vendor"
        ModelName    "Monitor Model"

        HorizSync    15-16
        VertRefresh  50-51
        Modeline  "720x576_50i"      13.875   720  744  808  888   576  580  
585  625  -hsync -vsync interlace
        Modeline  "800x520_50i"      17.00    800  856  936 1088   520  548  
553  625  -hsync -vsync interlace
        ModeLine  "1440x576_50i"     27.75   1440 1488 1609 1769   576  580  
585  625  -hsync -vsync interlace
EndSection

Section "Device"
        ### Available Driver options are:-
        ### Values: <i>: integer, <f>: float, <bool>: "True"/"False",
        ### <string>: "String", <freq>: "<f> Hz/kHz/MHz"
        ### [arg]: arg optional
        #Option     "NoAccel"                   # [<bool>]
        #Option     "SWcursor"                  # [<bool>]
        #Option     "ColorKey"                  # <i>
        #Option     "CacheLines"                # <i>
        #Option     "Dac6Bit"                   # [<bool>]
        #Option     "DRI"                       # [<bool>]
        #Option     "NoDDC"                     # [<bool>]
        #Option     "ShowCache"                 # [<bool>]
        #Option     "XvMCSurfaces"              # <i>
        #Option     "PageFlip"                  # [<bool>]

        Option      "SyncFields"                "True"
        Option      "YScaleFineTune"            "1"
        Option      "YRGB_VPhase"               "0x77777777"
        Option      "UV_VPhase"                 "0"
        Option      "monitor-VGA"               "Monitor0"

        Identifier  "Card0"
        Driver      "intel"
        VendorName  "Intel Corporation"
        BoardName   "82945G/GZ Integrated Graphics Controller"

#       Option      "ModeDebug"       "True"
EndSection

Section "Screen"
        Identifier "Screen0"
        Device     "Card0"
        Monitor    "Monitor0"
        DefaultDepth    24
        SubSection "Display"
            Viewport   0 0
            Depth      24

#           Modes      "720x576_50i"
#           Modes      "800x520_50i"
            Modes      "1440x576_50i"

        EndSubSection
EndSection

Interpretation of Xserver Xorg.0.log output when frame rate control is active
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The following log output typically is seen after starting video replay.


|<- -20ms                               0                              +20ms 
->|      R                    958351
-------|--------------------------------*---------------------------------------
   -265  -16590 [ -3-168]  999986
-------|--------------------------------+-*-------------------------------------
   1009  -16687 [-28-156] 1000916
--------|-------------------------------*---------------------------------------
   -243  -16284 [-37-165]  999081
---------|------------------------------+*--------------------------------------
    564  -15511 [-37-149]  999834
----------|-----------------------------+*--------------------------------------
    736  -15076 [-37-143] 1000008
------------|---------------------------+*--------------------------------------
    718  -14349 [-37-136]  999990
-------------|--------------------------+*--------------------------------------
    732  -13619 [-37-128] 1000003
---------------|------------------------+*--------------------------------------
    744  -12891 [-37-121] 1000016
----------------|-----------------------+*--------------------------------------
    671  -12163 [-37-114]  999943
------------------|---------------------+--*------------------------------------
   1678  -11397 [-37 -97] 1000949
-------------------|--------------------*---------------------------------------
   -175  -10703 [-37-108]  999097
---------------------|------------------+*--------------------------------------
    719   -9973 [-37 -92]  999992
----------------------|-----------------+*--------------------------------------
    737   -9246 [-37 -85] 1000009
-----------------------|----------------+*--------------------------------------
    727   -8517 [-37 -77]  999995
-------------------------|--------------+*--------------------------------------
    742   -7787 [-37 -70] 1000014
--------------------------|-------------+*--------------------------------------
    744   -7058 [-37 -63] 1000015
----------------------------|-----------+*--------------------------------------
    696   -6330 [-37 -56]  999968
-----------------------------|----------+*--------------------------------------
    769   -5599 [-37 -48] 1000041
-------------------------------|--------+*--------------------------------------
    709   -4860 [-37 -41]  999958
--------------------------------|-------+*--------------------------------------
    725   -4122 [-37 -33]  999998
----------------------------------|-----+*--------------------------------------
    719   -3129 [-37 -24]  999992
-----------------------------------|----+*--------------------------------------
    747   -2665 [-37 -19] 1000016
-------------------------------------|--+*--------------------------------------
    742   -1938 [-37 -11] 1000016
--------------------------------------|-+*--------------------------------------
    722   -1207 [-37  -4]  999996
----------------------------------------|*--------------------------------------
    943    -471 [-37  +4] 1000215
----------------------------------------*---------------------------------------
    433     341 [-33  +7]  999806
----------------------------------------*|--------------------------------------
    403     729 [-26 +11]  999962
----------------------------------------*-|-------------------------------------
    168    1048 [-15 +12]  999997
----------------------------------------*-|-------------------------------------
   -164    1044 [ -3  +8]  999994
----------------------------------------*|--------------------------------------
   -392     727 [  5  +3] 1000050
----------------------------------------*---------------------------------------
   -339     392 [  8  +0] 1000224
---------------------------------------*|---------------------------------------
   -816    -352 [  8 -11]  999753
---------------------------------------|*---------------------------------------
   -334    -825 [ -3 -11]  999997
---------------------------------------|*---------------------------------------
      0    -989 [-14  -9] 1000010
---------------------------------------|*---------------------------------------
    257    -845 [-23  -5]  999983
----------------------------------------*---------------------------------------
    446    -467 [-28  +0]  999994
----------------------------------------|*--------------------------------------
    731     110 [-28  +8] 1000261
----------------------------------------*|--------------------------------------
     19     509 [-20  +5]  999741
----------------------------------------*|--------------------------------------
    118     564 [-15  +6] 1000007
----------------------------------------*|--------------------------------------
    -55     592 [ -9  +5]  999998
                                                                                
     ^       ^     ^   ^       ^
                                                                                
     /       |     |   |       |
              25 frame average of drift speed VGA-video timing against xine-lib 
calls        |     |   |       |
              to XvPutimage(). it's represented by asterisks '*' in debug 
output             |     |   |       |
                                                                                
             |     |   |       |
                                                                                
             /     |   |       |
                        sync point displacement indicated by bars '|' in debug 
output. it's a      |   |       |
                        25 frame average of where frame updates hit the 40ms 
update interval       |   |       |
                                                                                
                   |   |       |
                                                                                
                   /   |       |
                                               frame rate adjustement active 
for the last 25 frames    |       |
                                                                                
                       |       |
                                                                                
                       /       |
                                                          yet unclipped 
relative frame rate adjustement        |
                                                          calculated for 
upcoming 25 frames                    |
                                                                                
                               |
                                                                                
                               /
                                                             time elapsed since 
last 25 frames sent by xine-lib

legend:
 |   syncpoint: frame update position within 40ms interval averaged over 25 
frames
 *   driftspeed: skew between video stream frame (input rate) and VGA video 
timing (output rate) averaged over 25 frames

algorithm:
 by altering the drift speed accordingly we let the sync point drift towards 
the center region of 40ms update interval

_______________________________________________
xorg mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/xorg

Reply via email to