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